17 Oct 2009
- Bring enthusiasm to work, and be friendly
- Understand the user’s business/domain
- Never do a requirements document in isolation
- Model after the real world
- If it won’t run, it is garbage
- Learn to Love Application Maintenance
- Read and talk about software
- Read widely
- Listen for feedback
- Craft over Career
Recently, I was a lucky recipient of a great book on software development titled “Domain Driven Design: Tackling Complexity in the Heart of Software” by Eric Evans. Many people in the field consider this book a classic, and I quickly found out why. Reading the book sparked my motivation to finally do something that I have been meaning to for some time; this was to capture (at least for my own benefit) a list of good practices for delivering great software.
One decade of reading, working and observing a lot of smart people in the software development field has provided me many insights into why some software development teams “click” and deliver great software, and why other teams seem to simply whither away after only a few days or months of working together. Some of the key insights that I have are, very oddly enough, nothing to do with how programmers code but rather the social interactions that occur right from when the design for the software is conceived to when the software is delivered to the end users of the system. My key insights are (in no particular order):
We have all worked in teams where there were at least one or two individuals who considered their work simply a chore, and never had interest in it otherwise. These individuals simply rob all fun and enthusiasm from the rest of the team by their constant grumpiness and moping. I have even had to put up with a few individuals during my career, who although considered very “productive” by some, were single-handedly responsible for ruining any shared chemistry and synergies within the team due to their unwillingness to work with others and their total dislike for collective success. However, I have also been incredibly lucky to work with people who always shared an infectious enthusiasm and positive attitude when tackling any challenge that came their way (not just in the software realm), and always managed to be cheerful and friendly even when having a seemingly bad day at work. Teams comprising of such individuals are so rare to come by that most programmers (including me) would gladly consider working even for less pay to share in the fun and learning that almost always happens in such environments.
This insight has very special meaning to me these days because this was one area that I really didn’t pay attention at all until much later in my career. I was so focused on developing “frameworks” and other cool gadgetry to support the “structural” foundations of the software that I almost never paid attention to learning a little bit about the problem domain that I was writing the software for. The lack of knowledge hindered me from truly delivering the kind of software that not only addressed any current needs of the end user, but also one that permitted easy enhancements in the future. The people that I have come to admire these days are those who through the course of any software project become so savvy in the end user’s domain, and as a result are able to forge great relationships as a result between the software team and the end users.
“Almost everybody feels at peace with nature: listening to the ocean waves against the shore, by a still lake, in a field of grass, on a windblown heath. One day, when we have learned the timeless way again, we shall feel the same about our towns, and we shall feel as much at peace in them, as we do today walking by the ocean, or stretched out in the long grass of a meadow.” — Christopher Alexander, The Timeless Way of Building
Many successful projects that I have participated in included design sessions where the end user (or a business analyst) starts by providing a high-level overview of their business area/domain as well as summary of the problem they are attempting to solve. Even when this took a few days (or weeks depending on how large and complex the problem was), this was only a small price or “sacrifice” to pay for the rich interactions that usually almost always followed later since the programmers now had a good understanding of the end user’s domain. This, in turn, permitted them to develop software that addressed their needs. Another advantage that this approach provided was that these interactions often permitted end users to gain insights into the abstraction and modeling processes used by programmers to formulate the design for the system.</p>
I have a big chuckle these days when I hear a programmer asking for a “detailed software requirements” document before they can begin work. Now, don’t get me wrong here. I am not saying that we shouldn’t bother creating documents containing detailed specifications of the software that we plan to build. But, to ask the end user or a business analyst to write this document in total isolation and simply hand it to you is really asking for trouble. How often have many of us seen “requirements documents” from end users or business analysts that really do not have any requirements at all, but rather contain a hazy/distorted vision of the final solution itself. This only creates frustration for the programmer who now has two tasks in front of him/her: 1) infer the real requirements from this preconceived “solution”, and 2) develop the right design for this software (based on what will now be only considered “his/her” vision). This method often (and unintentionally) leaves end users frustrated (and sometimes offended as well) since it makes them feel as though their ideas were totally ignored, leading to a lack of buy-in later. So, my point is that we all need to work with the end users as the requirements are being captured/formulated.
The book I refer to above is bang-on on this topic. I have witnessed many failed software projects where the development team insisted on using a completely unique set of terminology to aid in their understanding of the user’s domain. Although some abstractions are always necessary when modeling software, abstracting too aggressively although may help meet short-term goals will create numerous problems for the long run. One frequent problem that results is the confusion that occurs often during any inter-team communications due to the need to translate the “lingo” back and forth between the teams as there is no shared vocabulary of the domain involved to help in the collective understanding of the system being developed. To communicate easily, the design model must be easily understood by both parties. This results in collective ownership of the software due to the investment in this shared model of understanding on which the software is based.
On one project in the past, a team was looking at deploying software that had been written by seemingly bright individuals. The software was throwing cryptic error messages during the install process, and the administrators were making no progress at all. When the support team reviewed the code, they noticed right away that the code was extremely hard to read, understand and modify. When approached for clarification, the original programmers of the software spewed some mumbo-jumbo about all the “advanced techniques” and design patterns they had apparently utilized in developing this software and directed the blame at administration team that was attempting to deploy this software. My take away from watching this fiasco unfold was that it didn’t matter what is “inside” the software, but if you cannot make the software easy to run and administer, it is really garbage.
It is a pity when I hear people say that they will only work on new technologies and that they cannot be bothered with either troubleshooting or enhancing old applications and technologies either because they are harder to work on or don’t look cool on their resume. As I have gotten older, my personal realization is that working with legacy applications and extending them (up to a reasonable extent) is far more challenging and enjoyable than working on newer technologies and doing green-field development. Don’t get me wrong here. I do enjoy every opportunity to try or implement something new, but there is always great learning that occurs when you get exposed to both software development practices and technologies that have evolved over the years when working with older systems that are nearing the end of their lives. The understanding that comes from working on old applications can also significantly help us when making a costly decision when deciding between a complete rewrite of the application versus or extending the life of the existing application by addressing any key issues within their current implementation. I have seen time and time again, technologists suggesting new (and often unproven) technologies very quickly with very little understanding of the real problems. In several cases a simple enhancement (when done the right away) extends the lifetime of software by years buying the customer more breathing room to spend this money on something more significant. With a good service-oriented architectural approach (with service-enabled interfaces combined with message queueing) many seemingly archaic systems are/can be brought back to life for long life times which can keep a customer/client happy especially in this economy.
Most of us who work in great teams will agree that the best software teams chat frequently about software development. Despite constant chatter and passionate discussions within these groups, one can notice that this environment always generates enthusiasm and excitement which forges the teams together. This insight has provided an added benefit for me in that it has kept me very humble due to the realization that happens very quickly that there are many aspects of software development that I have simply no clue at all, and it inspires me to read and understand those topics further.
At a software conference that I attended some years ago, I became convinced of the many benefits of reading outside of one’s area of specialty, or “focus”. A speaker had invested significant amount of time and effort researching a problem that had risen recently in the software industry, and during his research had even read studies conducted in areas that seemed unrelated to software. While doing this, he had found several elegant ways of tackling a similar problem that had risen and been successfully addressed in another industry. During his very captivating presentation, he first proceeded to illustrate the many “parallels” that existed between these two seemingly unrelated industries, and later explained why the same approaches would work in tackling the problem in the software domain. The breadth of knowledge in this man was extraordinary, and this allowed the speaker to come up with an elegant solution without having to “re-invent the wheel”.
Very few teams seem to do this, but teams that do gain immensely. By talking to the end users after the software has been deployed for use, we can easily learn what went wrong (or right). With this understanding, teams can either repeat (or not repeat) practices that were followed during a particular software project. In the past, I have been very guilty of not following this practice myself, choosing not to call the end users after the software has been delivered out of fear that I would only hear complaints from them. However, when I did force myself to do this in a disciplined way, I was often pleasantly surprised to hear more good news than bad. Even during the few occasions where there was mostly bad news, the end users were somewhat relieved to see that you shared in their problems, and it helped diffuse any potential tension that would have otherwise been detrimental to the relationship in the long run.
One of my personal revelations lately is that we need to focus on getting good at what we are doing at any given time during our career rather than being too focused on the future. Simply chasing a promotion so that we can make more money and/or “lead” other people only gives us a false satisfaction that we are getting ahead when all we do is leave a trail of mess behind in the work undertaken and with the relationships we form with our colleagues. True fulfillment for most people seem to come only when they take delight at doing whatever they do, when they hone their craft and become good at it, and when they achieve a goal by working together in a fun atmosphere with other members in a team.