How do we balance these opposing forces so that engineers stay engaged and productive building the right product for the customer using as lightweight a process as possible? Here are two books that offer complimentary ideas for how to do it.
User Stories Applied: For Agile Software Development lays out a process for defining a product with plenty of customer involvement and enough documentation to ensure that the right thing is built, but no more. Learning UML 2.0 describes the Unified Modeling Language that can be used to design and document a complex software system (or any system, really) so that engineers and customers alike can visualize in more detail exactly what is being built. It may not seem like these two books are directly comparable since they are dealing with different aspects of the development process, but they have more in common than you would think. Let's look a little closer.
User Stories Applied: For Agile Software Development
More than a lot has been written about Agile software development over the years. I've read a lot of bits and pieces, mostly on various blogs, but I had yet to read a detailed description of any part of it until picking up this book by Mike Cohn. I was pleased to find it a very easy and enjoyable read that reminded me of The Pragmatic Programmer. The focus is centered on one aspect of Agile that defines the process for product definition and project management, and Mike does an excellent job of clearly explaining all of the ins and outs of user stories within the context of real projects.
What appeals to me most about user stories is that they make a concerted effort to address the realities of developers and customers and the project that sits between them. The fundamental reality is that no one knows what the right system that best achieves the user's goals will be until it is built. That means that in a working development process, the developers will need to change the design of the system as it is being built, and the customers will change their minds about what they want built. The fact that the final product is a moving target is not the fault of either the developers or the customers. It is the result of our inability to predict the future, and the better a development process accepts that reality, the better it will be able to manage the inevitable changes that will occur.
Requirements specifications try to address the product definition problem by documenting every minutiae of the system to be built so that both the developers and customers can sign off on the resulting contract with their expectations in full agreement. Then the developers only need to go off and build the system to the specifications and deliver it to the customer. But the results are hardly ever satisfactory because a requirements spec is not an adequate substitute for the working system that it is trying to represent.
Part of the problem is that specs can so easily be misinterpreted by anyone and everyone. Each stakeholder can interpret nearly any part of a spec to mean what they want it to mean because human language is ambiguous no matter how hard we try to make it otherwise. Disagreements can easily erupt over things that everyone thought were clear in their own minds when they were written down. I've experienced these arguments first-hand, and it always amazed me that there seemed to be no way to adequately phrase the offending requirement so that everyone understood it the same way.
Another problem with specs is that it's nearly impossible to get an overall understanding of a project from a 300+ page spec. Even a 100-page spec can be mind-numbingly boring to read and understand. Trying to process all of the details to form a complete mental image of the system is a nightmare. Beyond that, most people loathe writing specs in the first place, so if no one volunteers, some hapless developer will probably get stuck writing most of the spec while everyone else signs off on it without reading it. Then it will sit on a shelf and a file server until a disagreement needs to be resolved, at which point it is brought out and the above mentioned arguments ensue because no one really understood the spec in the first place.
User stories attempt to solve these problems by focusing on the user's goals and encouraging communication between the developers and the customers. Product features are written down on note cards instead of in requirements documents, and they are described only briefly so that it is obvious that they encompass a discrete feature without being the final, detailed answer to the problem. The stories are there to encourage discussion instead of record keeping, and those discussions should happen as they are necessary, not all upfront.
Then the development process consists of a series of 2-4 week iterations that each consist of implementing a subset of the stories. The team of developers and customers decides which stories will be done in each iteration, and during the planning of each iteration stories can be refined, split, added, and removed. As stories are further defined and implemented, details can be written on the back of the story card as tests that should be written, run, and passing before the story is considered complete.
The development process includes ways to estimate the scheduling of stories, planning software releases, and measuring and monitoring the project's progress. A concerted effort is made to defer implementation details and infrastructure building until it is absolutely necessary because features may change or get dropped, and then that work would be wasted. Everything is done in as lightweight and flexible a way as possible while giving the team the responsibility to build a product that, first and foremost, solves the user's problems.
This is only a very brief explanation, and there is much more covered in this completely accessible book. All in all, the development process resonated with me a great deal, and I would highly recommend User Stories Applied to anyone interested in getting the requirements monkey off their back.
Learning UML 2.0
Whereas User Stories Applied explained a development process, Learning UML 2.0 describes a modeling language. Something that user stories leaves out is documentation of the system that is being built, even though it was the suboptimal documentation of the requirements specification. One way to fill that gap at least partially is with UML diagrams that show how the system is connected together at various levels of abstraction.
Russ Miles gives a fine treatment of UML in this book, explaining clearly and concisely all of the intricacies of UML diagrams with a running blog content management system example. He did seem to lose the thread once when comparing communication and sequence diagrams with a goofy boxing match analogy, but otherwise he stuck to the task at hand and the book was a quick and easy read.
As for UML itself, it can model different aspects of a complex system using a wide array of diagrams: use cases, activity, class, object, sequence, communication, timing, composite structure, component, package, state machine, and deployment diagrams. These diagrams can describe a system in multiple levels of detail starting with throwaway sketches that only convey key points, moving into blueprints that form a more detailed specification of the system, and going all the way to a programming language that can completely model a system and generate code for multiple deployment environments.
I got the impression from the book that UML as a programming language (or executable model) has not really been achieved, yet. I would have to say that I can't see how an executable UML model would hold much of an advantage over a high-level dynamic language as a modeling language. Sure, it would be represented as a set of diagrams that would theoretically be easier to understand by less technical people, but in reality such a model would be so incredibly complex and unwieldy that it would be more trouble than it was worth. Not to mention the fact that drawing the model as a set of diagrams in that amount of detail would make the model terribly inflexible. Any changes to the system would be quite difficult to maintain in a massive drawing of interconnected symbols, even if there are ways to subdivide and group components. That's partly why digital hardware design moved from schematics to HDLs (hardware description languages) decades ago.
I've done a fair amount of modeling of ASICs (application-specific integrated circuits) using C++ and MATLAB as modeling languages because it was much faster to develop a working system that could be shown to the customer using these languages than using the normal ASIC design tools. And the resulting model was much more flexible than the final implementation that was done in schematics and Verilog, so when the customer requested changes, it was fairly straightforward to experiment with the model before committing to a particular design.
Even though the software models of these ASICs had a lot of value in rapid virtual prototyping and enabling better communication with the customer, we were always looking for more ways to use the models throughout the projects. One of the problems with models is that if there is no reason to keep them up-to-date with current design changes, they will quickly become out of sync with the real product. To prevent that from happening, and because it was easy to show that the output from the models was correct, we designed the models to generate test cases that could be used as input stimulus and output checks in simulations of the ASIC products.
This feature proved invaluable for verifying our designs because we could sit down with the customer and our software model and make sure that the system was generating the desired output with their provided input stimulus. The model became the golden standard for the design. Then we could close the loop by verifying the physical design simulations against the model so that everyone was confident that when the first silicon came back, the chips would behave correctly. We enjoyed a number of successes using this method.
When I try to see an equivalent method of using UML to model software systems, I end up drawing a blank. The reason C++ and MATLAB worked for modeling ASICs was that they were a sufficiently detailed abstraction that ran orders of magnitude faster than the simulations, but were easily modified to enable experimentation. UML doesn't have those same advantages over high-level languages. A sufficiently detailed UML abstraction would most likely run slower and be harder to develop in enough detail while being less flexible than a model written in Ruby or Python.
The bottom line is, why spend the time making UML diagrams a programming language when there are better alternatives? That is not to say that UML is not useful. I thought the class, object, sequence, and state machine diagrams were incredibly useful for designing the architecture of software systems. In fact, I've been using those types of diagrams, albeit more informally, throughout my career, and I'm sure most software engineers do as well. It's great to have a more formal treatment of these important design tools.
It's often difficult to wrap your head around a system, whether it's one you're looking at in code that you need to maintain, or one that you're actively developing. Drawing these types of diagrams and seeing a visual representation of the system can give you a much clearer understanding to work from. Those same diagrams can also be useful as documentation for the customer or for other developers that need to maintain the software in the future. But it would be good to stop at the right level of detail, before the UML diagrams get so complex that they cease to be clearly recognizable as a visual representation of the system.
UML Augmented Stories
User stories are a great improvement over the dreary busy-work of requirements specifications. They encourage better communication with the customer, engage engineers more fully in the development process, and help everyone be more productive in making a quality product that meets user's needs by getting out of the way. They do leave a hole in the area of documentation, but UML can at least partially fill that gap while also providing value to the development process through clear visual models of the software system. If I had to choose between them, I think User Stories Applied will have a bigger impact on a team's productivity and results, but both books are easy reads with plenty of useful stuff in them. I highly recommend them both.