Sponsored Link •
Doing the simplest thing that could possibly work is a frequent advice of the agile development movement. But how applicable is that advice in different kinds of development contexts?
One of the key tenets of agile development is to do the simplest thing that could possibly work. By its very definition, this dictum is hard to disagree with: after all, who would want to do deliver a solution more complex than it should be?
Test-driven development provides a practical path to following the simplest-thing-that-could-work principle: Write one unit test that exercises a simple function or method, and then implement that method in a most minimal manner that lets the test pass.
While few would argue for complex solutions in place of simple ones, most business systems tend to be anything but simple, both in terms of code and features. Abstraction is a proven way to deal with the unavoidable complexity of many enterprise business requirements: Abstraction allows common functionality to be implemented in one place and reused throughout the system.
But abstraction can also work against simplicity: It may take more work to apply abstract concepts to concrete, immediate problems. If more code needs to be routinely written to bridge the gap between highly abstract concepts and simple use-cases, that extra code will, over time, add complexity to the system, and make the system more difficult to understand.
In a recent blog post, Jay Fields explores the intersection of the simplest-thing-that-could-work with the real requirements of enterprise systems:
Often the emphasis of the phrase is like so: the simplest thing that could possibly work. However, recently ... [I] was discussing the idea that the emphasis should be: the simplest thing that could possibly work. The difference is only emphasis, but it's a change worth considering...
I believe there are occasions where the simplest thing that could possibly work is writing 10 lines of code today that do what you need, and deleting them tomorrow in light of new requirements...
Also, painting yourself into a corner when you can jump over the paint is fine, but if someone else keeps painting on the other side, you may not be able to get out. The small amount of code that we wrote can be rewritten in about an hour, but if someone else was going to add to that code then we would have probably gone down the more complicated path. No one was building on our code so we weren't as worried about the foundation we put in place...
While the point Fields raises applies to almost any sort of software project, it is even more relevant to projects that aim to develop a product. In many consulting engagements, by contrast, the definition of "possibly"—in possibly work—can be set rather low: For instance, if the goal is to demonstrate the next working milestone of an application, it is possible to write some code that, while perfectly meeting the immediate requirement, will most likely have to be thrown away. In a product development environment, that sort of effort would be considered waste.
As someone responsible for hiring consultants and, in a different context, as a consultant, I have seen that doing the simplest thing that could possibly work can be counterproductive. Starting out with the simplest thing, and then refactoring to more abstract patterns may seem like a sensible thing to do, but domain expertise can often, and luckily, shortcut several iterations of refactorings: Familiarity with a domain means that an architect can design a bit with the future in mind, since he has, in a sense, lived that future already. I've also found that organizations are not always tolerant of a developer's desire to refactor code to better abstractions: Once a feature is in place and demonstrably works, managers may tend to move a developer onto new projects and new features. "Post-release entropy reduction," to use Luke Hohmann's term, while extremely desirable, is not always possible.
In your projects how do you decide between doing the simplest thing that could possibly work and designing with the future needs of the project or code base in mind?
|Frank Sommers is a Senior Editor with Artima Developer. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld. Frank also serves as chief editor of the Web zine ClusterComputing.org, the IEEE Technical Committee on Scalable Computing's newsletter. Prior to that, he edited the Newsletter of the IEEE Task Force on Cluster Computing. Frank is also founder and president of Autospaces, a company dedicated to bringing service-oriented computing to the automotive software market.
Prior to Autospaces, Frank was vice president of technology and chief software architect at a Los Angeles system integration firm. In that capacity, he designed and developed that company's two main products: A financial underwriting system, and an insurance claims management expert system. Before assuming that position, he was a research fellow at the Center for Multiethnic and Transnational Studies at the University of Southern California, where he participated in a geographic information systems (GIS) project mapping the ethnic populations of the world and the diverse demography of southern California. Frank's interests include parallel and distributed computing, data management, programming languages, cluster and grid computing, and the theoretic foundations of computation. He is a member of the ACM and IEEE, and the American Musicological Society.