Practical Software Design - A few thoughts!
This post draws its inspiration from the many religious attempts I have made in the past to follow those golden "Oh you must follow these steps to do design. Else you are doomed". I have tried to use them 'literally' and have come to a conclusion that practical or real life software design is far away from what most of these so called experts claim. Here's my take on what actually happens when you sit down to design a software.
Note: By software design, I mean anything ranging from a small algorithm design to something as big as a framework design. I have come to realize a few things.
- Visualize what your end software program would look like - Abstraction really comes in handy!
- Realizing that tools like UML are only aids to convey your ideas
Sometime back I worked on a project as a software developer. I worked on a module whose design wasn't depicted in any sort of UML. It didn't have those class diagrams or sequence diagrams. But we still managed to pull off the module in a great manner. We in fact ended up reusing it for several other applications. At that time, I wasn't convinced of the above fact and blamed my lead for not producing the above design artifacts. He just smiled at me. I was quite annoyed since I firmly believed that 'Good design means having good UML diagrams and those flashy sequence diagrams'. What I failed to realize was that they were just a means of achieving the goal and not the end in themselves. A few months back I got a chance to be in the shoes of that designer myself. I was really watching myself as to how I would go about this new responsibility. I was seeing if I would religiously follow all those UML diagrams and present them to the stakeholders or would I follow some simple techniques like flowcharts and block diagrams to help them convey my design along with supporting code for APIs and reference implementations. I was in a fix. But subconsciously I chose to do the latter. I never felt that I produced any inferior design by not having UML in my design artifacts (although I did include them later for consistency). I was very much able to convey my design to all the stakeholders. The module was developed and delivered without the so called traditional approaches of design. The bottom line was that tools like UML help in communication since they offer a common language to communicate your intent. But they should never become a bottle neck. Not knowing UML doesn't necessarily disqualify your design although it might be difficult to explain what you want to convey since you might heavily rely on your API docs or reference implementations.
- Code - The ultimate realization of what's in your brain as 'Design'
- Refactoring - Do it diligently and mercilessly
I have come to terms with this fact very recently. Some time ago I used to feel that refactoring is actually a sign that you did not design something well. When I think of it now, I can't help but laugh at myself. I now feel that if I can re-factor something easily without breaking too much around my original design (viz having to remove some methods in an API or move a method from one API to another), I have done a decent design. Sometime back I was reading this book called Practical API design by Jarsalov Tulcach. The author talks about something called as the 'Known Universe.' It refers to how much you know about a problem domain. All our solutions are pretty much going to be based on how much we know about a problem. In software development, if there is anything that is constant, then it must be change. Hence given the fact that your design is going to change anyway, the challenge now lies in making sure how much ready are you in incorporating these changes as your software evolves. The need for refactoring arises from the above truth. Trust me when I say this, no matter how good a design looks today, you will always feel the need to change it, as and when your understanding of the problem domain changes. The smartness lies in adopting the techniques or best practices to shield yourself from having to do too many changes to fit in those new requirements. Hence re-factoring is here to stay. Better get used to it. If there is a need to re-factor your code, don't hesitate to do it. It doesn't indicate that your design is inferior. It just means that the design now needs to accommodate fresh requirements that were not known when the initial design was proposed.
P.S. Feel free to comment on the above points. All the above mentioned points are pretty much the resultant of little exposure that I have to software design. I am yet to learn a lot of things and I am fascinated by the sheer amount of learning that lies ahead of me.