Design is one of my favourite parts of programming, but I constantly run into the problem of how to tell whether my design is any good.
Before we go any further, I think we should define what makes a good design is. My definition is that if you can change it in the future without cursing your past self, it must have been good design. You may have noticed that using that definition makes it difficult to figure out whether a design is any good until potentially months after the fact when you need to change it. It would be nice to know ahead of time whether your design is going to lead to a lot of swearing in the future, and that’s where I have trouble.
To be fair, if I could definitively answer the question of whether a design was good without having to try to change it, I’d be a millionaire and I’d be writing this post from my own private island :) Whether a design that seems good now is going to continue to be helpful in the future is just a hard problem and there’s no getting around that.
That said, I think code smells can help a lot there. A code smell is, in the words of Martin Fowler, a surface indication that usually corresponds to a deeper problem in the system. The term was coined by Kent Beck while he helped Martin Fowler with his book Refactoring.
This whole concept would probably make more sense with an example. An especially designy code smell is a class that does too much. Ideally a class should have one responsibility – if it’s concerned with more than one thing that’s a strong sign it should be broken up into separate classes. The specific problem with a class that does too much is that it’s likely to lead to long, messy methods that do too many things and don’t make sense because of it, and it generally makes it hard to reason about your system. The more one class does, the more state it’s likely to need to keep track of, and the more state one class keeps track of, the more chances you have to completely mess it up. You may have gotten a hint here that software design is about accepting that humans are bad at it and trying to work around that basic fact :p
The thing with a code smell is that it’s not a hard and fast rule, it’s just a hint that something could be wrong. Sometimes it can be reasonable for a class to do “too much,” it depends on the exact thing you’re trying to accomplish and the context (i.e. the rest of your application) that your class is part of. Having a good design is more about the thing you’re trying to accomplish than it is about following all the rules whether or not they make sense in your particular situation.
The great thing about code smells and design patterns and all that is that they let you take advantage of other people’s experience. Can you imagine how long it would take to get good at software design if you had to make all the mistakes yourself? I love hearing what other people have messed up so I can maybe avoid that particular problem. And from the other side, I’d love it if anything I’ve told another dev helped them avoid a problem. It’s all well and good if I solve a problem for myself, but if I can help a couple of people avoid the problem in the first place and if those people help a couple other people avoid that problem, then I’ve done much more good than if I quietly fixed my own code and moved on.
Stay tuned for more posts about code smells, there are plenty of them to get through :)