I moved my blog again. This time to GitHub Pages.
I have written the reasons here. Check it out if you want to know why. :)
Happy coding!!
And enjoy doing the other good things that you love doing. (And let's already stop doing the bad things we are doing :) )
Saturday, April 1, 2017
Sunday, February 19, 2017
Substituting polymorphism for if/else or switch/case - Example #1 - Shapes
This is Example #1 of the series of examples I'm going to give on "Substituting polymorphism for if/else or switch/case statements".
It's your first day at work. You are very excited to be involved in a real-world project.
Your team lead tried to explain to you the purpose of the project you are involved in.
You have to implement this method:
(Because I used C# for many years, I'm going to display C# in these posts. But I will also write these examples in Python and maybe other OO languages in the future. You can view them here.)
The codebase of the project you are involved in already have these classes:
Then after a few hours of hard work, you pushed your code to the repository, waiting for your team lead's comments.
Your team lead's comment came in.
Now I understand what you want me to do with drawing shapes.
Let me be the one to refactor my code, please. I think I already know what to do.
(Please go to the GitHub repository to view the complete refactoring.)
MTGOTB, TCOTU, BGWML
You have a new task
It's your first day at work. You are very excited to be involved in a real-world project.
Your team lead tried to explain to you the purpose of the project you are involved in.
"Here at Hugis Inc., we strive to be the best drawer of shapes."After an hour, he gave you your first task.
You have to implement this method:
(Because I used C# for many years, I'm going to display C# in these posts. But I will also write these examples in Python and maybe other OO languages in the future. You can view them here.)
The codebase of the project you are involved in already have these classes:
- a base Shape class,
- classes for Circle, Square, and Triangle that derives from the Shape class.
The Evil code
This task is so easy!!! (you say to yourself)You then started typing on the keyboard. Click! Click! Click!
Then after a few hours of hard work, you pushed your code to the repository, waiting for your team lead's comments.
The Good Code
Your team lead's comment came in.
"Good job!"Wow!
"But there is a better way of doing this.You then went to his table and watched him refactor your code.
"We want to put the function drawCircle() inside the Circle class, and the function drawSquare() inside the Square class, because we want to have an easy access them anywhere in the system.
"Come over here. I'm going to show you how I will do the changes."
"Because we want to be able to draw each Shape that we have, we will create an abstract method named draw() in our base Shape class.No.
abstract public void Draw();
"Do you know what an abstract method is?"
"An abstract method is a method definition that has no implementation -- like the getArea() method in the Shape class.Ahh! The Shape class did not provide an implementation for getArea() because different shapes has different formulas for getting the area! Great!
"Notice that getArea() does not have an implementation inside the Shape class. But any class that inherits from the Shape class is required to provide an implementation for getArea()"
Now I understand what you want me to do with drawing shapes.
Let me be the one to refactor my code, please. I think I already know what to do.
"Ok! Go Ahead!"You went back to your machine and started refactoring your code.
(Please go to the GitHub repository to view the complete refactoring.)
MTGOTB, TCOTU, BGWML
Saturday, February 18, 2017
Substituting polymorphism for if/else or switch/case - Introduction
A few weeks ago I saw this post from a facebook friend:
He is saying jokingly something like "Programming is like love... don't switch() because it will end up with a break... LOL"
I then asked him if his alternative to switch/case is polymorphism. He said no; and that he does not yet know what polymorphism is.
So after a few days, I thought of creating a blog post where I will teach how to replace if/else or switch/case statements with polymorphism.
But did you know that, if you are using an object-oriented language such as Java, C# or Python, codes like those ones above are sometimes considered evil?
But I did not say that they are always evil. I said that they are sometimes evil. ("Sometimes evil" because I only have a few years of programming experience. "Often evil" when I have more :D . I'm just joking.)
They are evil because they might make modifications in the future much harder than they should be.
I found this great explanation by Steve Guidetti about polymorphism from code.tutsplus.com:
Then after that, go back here because I'm going to give you a number of examples on how to convert your if/else and switch/case statements into polymorphic code.
(Another reason why I delegate the explanation to others is because I'm not very good at explaining things using the English language :) )
It's only that I read an article a few months ago which claims that giving students lots of examples of a problem and their solutions can help them easily spot similar occurrences of that problem and can help them easily solve those kinds of problems. (But I already forgot where that article is located. Maybe I took a note of it somewhere but I'm not able to find it. I will just update this post when I will find it in the future)
Here are the examples:
1. Drawing Shapes
2. to be posted
3. to be posted
4. to be posted
Examples from other people:
https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
Have fun coding!!!
MTGOTB TCOTU BGWML
He is saying jokingly something like "Programming is like love... don't switch() because it will end up with a break... LOL"
I then asked him if his alternative to switch/case is polymorphism. He said no; and that he does not yet know what polymorphism is.
So after a few days, I thought of creating a blog post where I will teach how to replace if/else or switch/case statements with polymorphism.
I'm going to try to teach you how to replace your if/else with polymorphism
Have you seen code like this one below?If (typeOfShape is Circle) drawCircle() Elseif (typeOfShape is Square) drawSquare() Elseif (typeOfShape is Triangle) drawTriangle()Or this one?
Switch (typeOfShape) Case Circle: drawCircle() Case Square: drawSquare() Case Triangle: drawTriangle()If you have been programming for a few years already, I believe you have seen lots of code that looks like those.
But did you know that, if you are using an object-oriented language such as Java, C# or Python, codes like those ones above are sometimes considered evil?
Evil? (you might say).Yes! EVIL!
But I did not say that they are always evil. I said that they are sometimes evil. ("Sometimes evil" because I only have a few years of programming experience. "Often evil" when I have more :D . I'm just joking.)
They are evil because they might make modifications in the future much harder than they should be.
(you might be asking…) How else am I going to do conditional constructs like that? If/else and switch/case are the only ones available!There is actually another method available to us on how to do conditions in OO languages. It is called polymorphism.
I found this great explanation by Steve Guidetti about polymorphism from code.tutsplus.com:
Polymorphism is a long word for a very simple concept.There are already lots of available resources on the web about polymorphism. [The] Google [search engine] is your friend. Ask your friend to teach you polymorphism. But I recommend you to start with that explanation from code.tutsplus.com I linked to above, or from stackoverflow.
Polymorphism describes a pattern in object oriented programming in which classes have different functionality while sharing a common interface.
The beauty of polymorphism is that the code working with the different classes does not need to know which class it is using since they're all used the same way.
A real world analogy for polymorphism is a button. Everyone knows how to use a button: you simply apply pressure to it. What a button "does," however, depends on what it is connected to and the context in which it is used -- but the result does not affect how it is used. If your boss tells you to press a button, you already have all the information needed to perform the task.
Then after that, go back here because I'm going to give you a number of examples on how to convert your if/else and switch/case statements into polymorphic code.
(Another reason why I delegate the explanation to others is because I'm not very good at explaining things using the English language :) )
Why are you going to give me lots of examples? I think one example will do. 'You think I'm dumb?No. I do not think you are dumb.
It's only that I read an article a few months ago which claims that giving students lots of examples of a problem and their solutions can help them easily spot similar occurrences of that problem and can help them easily solve those kinds of problems. (But I already forgot where that article is located. Maybe I took a note of it somewhere but I'm not able to find it. I will just update this post when I will find it in the future)
Here are the examples:
1. Drawing Shapes
2. to be posted
3. to be posted
4. to be posted
Examples from other people:
https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
Have fun coding!!!
MTGOTB TCOTU BGWML
Saturday, February 4, 2017
Hints for Nand2Tetris Chapter 1 Exercises
I have already done Chapters 1 to 8 of Nand2Tetris last 2013. But I want to finish it. I have decided to do everything all over again.
I am not allowed to put online my solutions to the Nand2Tetris exercises. So what I'm going to do instead is to give some hints on how to solve them.
Here are the hints for the Chapter 1 Exercises:
1. Not gate - look at the Nand truth table; notice the output when both a and b are the same
2. And gate - use your newly created Not gate (and the Nand gate of course)
3. Or gate - we can use the idea from the Canonical Representation presented on page 9. But instead of focusing on the 1 outputs of the Or function, let's focus instead on the 0 output.
The Or function has only one 0 output.
This means that we can be able to create an Or gate without using an Or gate. haha
We can solve this using the And and Not gates
"We will Not the And."
4. Xor gate - we can now use the Canonical Representation from page 9.
5. Multiplexor (Mux) - same as #4; use the Canonical Representation from page 9
6. Demultiplexor (DMux) - use truth table to determine when a and b will be 1; then use the Canonical Representation
7 to 10. Multi-Bit gates (Not16, And16, Or16, Mux16) - read "A.5.3 Busses" of the Appendix to know more about how to solve these.
Do something like this, for example, for the Multibit Not gate:
Not(in=in[0], out=out[0]);
Not(in=in[1], out=out[1]);
...
Not(in=in[9], out=out[9]);
12 Multi-Way/Multi-Bit Multiplexor
12.a (Mux4Way16) - use Mux16 and temporary internal pins
12.b Mux8Way16 - similar to 12.a but also use Mux4Way16
13. Multi-Way/Multi-Bit Demultiplexor - quite similar to 12.a and 12.b
13.a DMux4Way - Use DMux and internal pins
13.b DMux8Way - same to 13.b but also use DMux4Way
If you have any comments or corrections or ideas on how to make the hints better, please tell me. Thanks!
I am not allowed to put online my solutions to the Nand2Tetris exercises. So what I'm going to do instead is to give some hints on how to solve them.
Here are the hints for the Chapter 1 Exercises:
1. Not gate - look at the Nand truth table; notice the output when both a and b are the same
2. And gate - use your newly created Not gate (and the Nand gate of course)
3. Or gate - we can use the idea from the Canonical Representation presented on page 9. But instead of focusing on the 1 outputs of the Or function, let's focus instead on the 0 output.
The Or function has only one 0 output.
This means that we can be able to create an Or gate without using an Or gate. haha
We can solve this using the And and Not gates
"We will Not the And."
4. Xor gate - we can now use the Canonical Representation from page 9.
5. Multiplexor (Mux) - same as #4; use the Canonical Representation from page 9
6. Demultiplexor (DMux) - use truth table to determine when a and b will be 1; then use the Canonical Representation
7 to 10. Multi-Bit gates (Not16, And16, Or16, Mux16) - read "A.5.3 Busses" of the Appendix to know more about how to solve these.
Do something like this, for example, for the Multibit Not gate:
Not(in=in[0], out=out[0]);
Not(in=in[1], out=out[1]);
...
Not(in=in[9], out=out[9]);
...
11. Multi-Way Or (Or8Way) - use Or gates and internal pins (see A.5.2 of Appendix A for an explanation for internal pins)
12 Multi-Way/Multi-Bit Multiplexor
12.a (Mux4Way16) - use Mux16 and temporary internal pins
12.b Mux8Way16 - similar to 12.a but also use Mux4Way16
13. Multi-Way/Multi-Bit Demultiplexor - quite similar to 12.a and 12.b
13.a DMux4Way - Use DMux and internal pins
13.b DMux8Way - same to 13.b but also use DMux4Way
If you have any comments or corrections or ideas on how to make the hints better, please tell me. Thanks!
Subscribe to:
Posts (Atom)