I had the chance to attend an object oriented programming boot camp with Fred George last week thanks to Obie Fernandez and the fine folks I work with at 2U. One of the most interesting tidbits of information Fred passed on to us is his definition of when code is "done". Here is the criteria Fred uses, ordered by importance.
Code is done when:
- It works
- It communicates
- There is no duplicate code
- The fewest classes/methods are used
The first criteria is an obvious one - It works. Obviously code is not done until after it meets the business criteria and is bug free. I don't think there will be any arguments here.
Secondly, code must communicate in order to be considered done. That seems like a strange choice of terminology, but when you think about it the word communicate does make the most sense. Code cannot be considered done until after it is readable and maintainable.
Code as if someone smarter than you will read it, and someone stupider than you will maintain it
This was quote was put in Slack by one of my coworkers, Elsie Powell, the other day. I don't have a proper source for it, other than to point to Elsie, but the point it makes holds true for anyone writing code. If you cannot look at a method and immediately understand its purpose and the purpose of each line of code in context of the method, you should refactor it to be understandable.
No code duplication
Code duplication hurts maintainability and readability. When you do the same task in multiple places it is hard to change or update, as you need to find each place you perform the task and update that block of code. The same can be said for doing the same task in different ways. You risk introducing bugs, and its simply harder to maintain.
The fewest classes/methods are used
One of the first things Fred had us do during the bootcamp was write a
Rectangle class. Most of us came up with something like this:
# Understands a polygon with four sides connected with right angles class Rectangle def initialize(height, width) @height, @width = height, width end def area @height * @width end end
This passed the muster of Fred, so we moved on. Our next task was to create a square. The six pairs all created a class that looked like this:
# Understands a polygon with four equal sides connected with right angles class Square < Rectangle def initialize(dimension) Rectangle.new(dimension, dimension) end end
Now this looks fine, but Fred made the good point that we aren't actually doing anything in the
Square class. It just creates a
Rectangle. To quote Fred, "it has no kick."
The proper implementation was instead:
# Understands a polygon with four sides connected with right angles class Rectangle def initialize(height, width) @height, @width = height, width end def area @height * @width end self.square(dimension) Rectangle.new(dimension, dimension) end def is_square? @height == @width end end
This way, we could say
Rectangle.square(5) and get back the proper object, but still have the square functionality.
This was a long explanation to basically just say make sure that the code you are writing actually has a purpose, and that the purpose is defined. Don't create unnecessary classes or methods when you can simply add functionality to the classes or methods that you already have.
I definitely agree with the criteria laid out by Fred re: code being done. If your code doesn't meet the criteria laid out above then it isn't done and you likely have some refactoring to do before declaring it done.