One of the anonymous reviewers of my OOPSLA paper made the point, paraphrasing, that the main problem in software development is not the difficulty of programming, but the difficulty of getting a development project to function effectively. This is usually seen as the subject of methodology, with “extreme†and “agile†methods being the latest trends. My initial reaction to this criticism was to point to the example of spreadsheets, which make a certain class of problems simple enough to be solved by an end-user or power-user themselves, without enduring the trials and tribulations of a professionally staffed development project. Even on such multi-person projects, reducing the programming effort ought to reduce the size of the team and the number of interactions subject to error. However the fundamental point of the criticism remains true: the biggest problem in software development is teamwork. It has occurred to me that the design philosophy of Subtext can contribute to solving this problem.
The real problem is that we still haven’t figured out an effective way to divide the labor of software development. Economists since Adam Smith have pointed to the division of labor as the key to efficiency and progress. To divide labor, there must be commodities to exchange between specialists. A prominent example of such a commodity in software development is the specification: an informal description of system behavior, produced by analysts interviewing users, approved by those users, and consumed by the programmers.
Programmers in the real world will tell you that specs aren’t worth the paper they are written on. They are half-baked informal descriptions that are too abstract to be understood by the users, and too imprecise to be useful to the programmers. They are full of internal inconsistencies and factual errors, because there is no way to test them. They are obsolete the day they are published, because it is too difficult to rewrite them as the system becomes better understood. Things are no better with the other standard commodities of development: project plans, schedules, cost estimates, and documentation.
Extreme Programming responds to this problem by eliminating the specs and docs and plans, along with the specialists who produce them. There are just users and programmers, collaborating intimately without formal plans. The sole commodity is code, which is the spec, and the doc, and the tests. There is much to recommend this approach, but it appears to work best with smaller projects. In Economic terms, it is still cottage industry. The fundamental scaling problem remains: we do not know how to divide up big software projects to allow teams to solve them effectively.
I propose a universal commodity of exchange in software projects; a common currency of development: examples. Specifically, examples as executable artifacts integrated into the programming language (as in Subtext), or at least into the IDE (as in EG). The key properties of examples are that:
- They can visually demonstrate system behaviors of concern to the users.
- They can be built without coding by analysts or power-users.
- They can test code, asserting that certain inputs lead to certain outputs.
Examples essentially formalize use cases, which have proven to be an effective communication medium between users, designers, and implementers. By turning use cases into concrete examples, users gain realistic demos, designers gain automated tools, and implementers gain both a clear specification as well as a test suite. Managers gain the ability to plan and observe work by the satisfaction of examples; implementers can more reliably estimate the work required to satisfy concrete examples. Documenters can base much of their content on the examples. Everyone benefits from keeping the examples in sync with the code, which is required because they are used as tests. Development becomes more efficient because examples help everyone collaborate.
I see two major hurdles to be overcome for examples to function as the common currency of software development. The first hurdle is that although they are formal artifacts, examples must retain the informality and flexibility of use case techniques. Overcoming this hurdle is partly a matter of good usability-engineering, but may also depend on a simple yet general framework for expressing examples that can be adapted to specific application domains. This is a goal of Subtext, but I see no fundamental reason why it can’t also be done in conventional IDE’s like Eclipse, given sufficient resources.
The second hurdle is more fundamental: can examples truly replace specifications? Examples concretely describe only a finite subset of behaviors, while specifications can abstractly describe infinite sets of behaviors. Formal specifications, written in some machine-analyzable logic, are clearly superior to examples. But formal specification has been one of the great disappointments of software engineering. The dirty little secret is that writing a complete formal spec of a system can be as difficult and error-prone as implementing it in code. In practice, we rely on informal specifications. My conjecture is that formal examples are better than informal specifications.
I claim that in most cases, a well-chosen set of concrete examples can more effectively communicate an intended abstract behavior than an explicit but informal abstract description. People are quite adept at inferring abstractions from examples, but notoriously poor at understanding and constructing abstractions explicitly. This is one reason that use cases are so successful. But unlike informal specs, examples can actually test whether code satisfies them: they are “specs with teethâ€. By serving as tests, examples are forced to evolve with the code, avoiding the rapid obsolescence of specs.
We are still free to mix informal specifications with formal examples. Informal commentary on examples could be quite helpful in conveying their intention. The key is to treat such commentary as just that: explanatory comments without proscriptive power. To actually require or disallow some behavior, a concrete example should be formulated that isolates that case. Once we no longer expect specifications to be complete, we are also freed to use lightweight formal techniques that are incomplete, such as Alloy. Alloy has the singular ability to both find and check models of a specification, within finite bounds. This capability could be used to concisely specify large (but still finite) sets of examples, generating their input states and asserting their outputs.
In summary, I am proposing that formal examples can serve as a common currency for software development. They support collaboration between users, designers, programmers, managers, testers, and documenters. Examples are a unit of exchange that allows the effective division of labor, making us more efficient and enabling us to do bigger things.
Michael Feathers wrote:
Thanks, Mike.
I knew that! 🙂 Forgot about those guys. They have the methodological case for examples locked down. What I would like to see, though, is examples that are much more closely integrated with the code, rather than just text strings in a document.
The need to write custom “fixture” code to map between the string world of FIT and the run-time world of code is an undesireable barrier. In Subtext, I want examples to be exactly the same thing as code executions. This particularly pays off for scripting examples with input states and side-effect outputs: states and changes should be as easy to incorporate into examples as numeric literals. Likewise example screen shots and user actions should be cinematically realistic, not a textual screenplay.
But that is all icing on the cake. I would agree that lightweight tools like FIT should be able to realize much of the advantage of centering development around examples.
The covert operatives at Intentional Software are talking about something related: a super use case editor. You would have to sign an NDA to find out any details.
The trouble with the spreadsheet example is that spreadsheets in the large are very buggy and extremely hard to debug (essentially nothing but multi-person inspection works). See http://panko.cba.hawaii.edu/ssr/Mypapers/whatknow.htm for the horrendous details.
[Whereas with programming it takes specially talented people whom have trained for years in order to build software that in the large is very buggy and extremely hard to debug 🙂 — Jonathan]
I disagree – the biggest problem in software development is no longer process, or getting a project to function, and consequently the discussion about which process is better is a moot one.
I believe, and I can back this up with countless examples from real-life companies, that the biggest problem today is the disappearance of the ‘engineering’ from software engineering, as a direct result of the commoditization of development, and the resulting lack of code quality.
It turns out that it is not sufficient for a software product to simply satisfy the requirements. For too long the results of software development were considered black boxes, and QA was something that comes AFTER development and is essentially a validation of the system responses based on feeding it predetermined data.
The underlying assumption here was that code=code, i.e. two people with different skill sets in two different projects using different methodologies will ultimately produce the same code. The variance was considered in the time that it takes, or in the risk that the undertaking would fail.
We need to refocus on being engineers, first and foremost, and emphasize the fact that engineering work is the creative process of finding the optimal solution, or close to optimal, and not just finding ANY kind of solution. Which is what I have seen people doing for the better part of my career.