Object Calisthenics In JavaScript - An Introduction
Several years ago, Brian Kotek introduced me to the concept of Object Calisthenics. Object Calisthenics is an exercise defined by Jeff Bay to help programmers think very critically about their application design choices in an object-oriented context. I attempted this exercise a long time ago; but, I was quickly flustered by my lack of understanding. Now, a few more years of experience under my belt, I thought it would be an exciting exercise to try again. While I see myself as being very technically-capable in programming, I clearly lack a strong understanding of Object Oriented Programming (OOP). I'm hoping that this exercise will help me gain clarity and kick the bad habits that I have accumulated from years of procedural programming.
Some quick background information - what's the point of Object Calisthenics? Here is an excerpt from Jeff Bay's paper on the subject:
We've all seen poorly written code that's hard to understand, test, and maintain. Object-oriented programming promised to save us from our old procedural code, allowing us to write software incrementally, reusing as we go along. But sometimes it seems like we're just chasing down the same old complex, coupled designs in Java that we had in C.
Good object-oriented design is hard to learn. Transitioning from procedural development to object-oriented design requires a major shift in thinking that is more difficult than it seems. Many developers assume they're doing a good job with OO design, when in reality they're unconsciously stuck in old habits that are hard to break. It doesn't help that many examples and best practices (even Sun's code in the JDK) encourage poor OO design in the name of performance or simple weight of history.
The core concepts behind good design are well understood. Alan Shalloway has suggested that seven code qualities matter: cohesion, loose coupling, no redundancy, encapsulation, testability, readability, and focus. Yet it's hard to put those concepts into practice. It's one thing to understand that encapsulation means hiding data, implementation, type, design, or construction. It's another thing altogether to design code that implements encapsulation well. So here's an exercise that can help you to internalize principles of good object-oriented design and actually use them in real life.
In the above PDF, Jeff Bay goes on to describe the 9 rules of Object Calisthenics:
- One level of indentation per method.
- Don't use the ELSE keyword.
- Wrap all primitives and Strings in classes.
- First class collections (no simple Arrays).
- One dot per line (don't violate the Law of Demeter).
- Don't abbreviate names.
- Keep all classes less than 50 lines.
- No classes with more than two instance variables.
- No getters or setters.
This sounds tough! But, that's what makes it exciting. For this exercise, I want to do something that is non-trivial; but, also something that is not so complex that it takes forever to finish it. After a few days of mulling over ideas, I decided to go with the concept of a "Match Maker" (as in, Relationships). This gives me the opportunity to look at polymorphism, collections, and behaviors.
To get started, I've created a GitHub repository for this exercise as I am sure it will require many iterations to get right. Very exciting! Wish me luck :D
Reader Comments
Eh?
So it's expecting people to write:
?
That sounds like an arbitrary limit. :/
@Peter Boughton. The Else restriction isn't so that you use another if with !, it is trying to get you to use polymorphism. The source link has a bit more of an explanation Don't use the ELSE keyword. This one is tough. We're very used to using if/else or switch/case. But good OO designs rely on polymorphism in place of conditional logic.
50 lines is definitely arbitrary, but the point is trying to ensure that each class is doing one thing and one thing alone. In js I think 50 lines is reasonable, but if you're in something like java you should probably avoid counting some of the boiler plate code like imports.
Great post Ben. I love seeing the different forms of practice that people use to improve their development skills.
@Peter,
I believe the main goal of the exercise is to help you think outside of your comfort zone. It's kind of like the idea of never saying "No" to things. Clearly, that's crazy! There's lost of things you *should* say No to. But, the point is to be more open than you used to be.
This, to me, is the same way. By going extreme, you will necessarily have to change the way you think about things. Some of things may be good; some may be bad. I can't know until I try.
I'm 1-hour into this... and already I have a lot of anxiety!!! This stuff is hard!
There is a point where using more Polymorphism/ creating more classes actually hurts more than hinders a program. It might allow for more scalability, but there are a lot of areas where building as much scalability in as possible is futile because it'll never be changed. Besides, more often than not it hurts performance, though usually negligibly. This whole thing seems more like a farce designed to hurt people's brains rather than a practical exercise.
I think I'll give this exercise a try. Though I'm not realy sure I completely understood it...
@Joe,
I think it is definitely designed to "hurt people's brains." I think that's the point. It's like shocking the heart to get it back to a good rhythm - the benefit is not in the shock itself, but rather in the resultant adjustment. As long as this helps me expand my understanding, it will be a worthwhile endeavor.
@All,
I tried to work on this over the weekend. Here is the code and reflections that I came up with:
www.bennadel.com/blog/2375-Object-Calisthenics-In-JavaScript-My-First-Attempt.htm
I am looking forward to trying it again. There were parts that didn't necessarily agree with me; but, I really enjoyed the way it challenged me to think hard about where behavior should reside.
@Peter,
Glad you like the idea. I definitely recommend it!
Good stuff as always!
Here is a helpful link for the if else refactor - using polymorphism:
http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
@Steve,
I've been reading through the SourceMaking.com websites. It's pretty awesome! I have never seen this before, but their articles on refactoring (and the like) are super insightful. Thanks so much for passing this along - I'm loving it!
@Peter,
The idea of avoiding ELSE is that you decouple these actions from their relative context, making them usable anywhere. So as opposed to your example you could write:
Or, better yet, you could design a set of subclasses whose
does something completely different.
If you're focusing on Inversion of Control and value loose coupling, this makes the most sense.