The Art of Agile Development: Ubiquitous Language
May 13, 2010
The second edition is now available! The Art of Agile Development has been completely revised and updated with all new material. Visit the Second Edition page for more information, or buy it on Amazon.
- Next: Stand-Up Meetings
- Previous: Sit Together
- Up: Chapter 6: Collaborating
in 99 words
Programmers should speak the language of domain experts to avoid miscommunication, delays, and errors. To avoid mental translation between domain language and code, design your software to use the language of the domain. Reflect in code how users of the software think and speak about their work. One powerful approach is to create a domain model.
The ubiquitous language is a living language. Domain experts influence design and code and the issues discovered while coding influence domain experts. When you discover discrepancies, it's an opportunity for conversation and joint discovery. Then update your design to reflect the results.
Fireflies light the night--
Signaling for a mate, or
perhaps, a dinner
The following text is excerpted from The Art of Agile Development by James Shore and Shane Warden, published by O'Reilly. Copyright © 2008 the authors. All rights reserved.
We understand each other.
Try describing the business logic in your current system to a nonprogrammer domain expert. Are you able to explain how the system works in terms the domain expert understands? Can you avoid programmer jargon, such as the names of design patterns or coding styles? Is your domain expert able to identify potential problems in your business logic?
If not, you need a ubiquituous language.
The Domain Expertise Conundrum
One of the challenges of professional software development is that programmers aren't necessarily experts in the areas for which they write software. For example, I've helped write software that controls factory robots, directs complex financial transactions, and analyzes data from scientific instruments. When I started on these projects, I knew nothing about those things.
It's a conundrum. The people who are experts in the problem domain—the domain experts—are rarely qualified to write software. The people who are qualified to write software—the programmers—don't always understand the problem domain.
Hiring programmers with expertise in a particular domain will reduce this problem, but it won't eliminate it. In addition, given the choice between a great programmer with no domain experience and a poor programmer with lots of domain experience, I would choose the better programmer.
Overcoming this problem is, fundamentally, an issue of communication. Domain experts communicate their expertise to programmers, who in turn encode that knowledge in software. The challenge is communicating that information clearly and accurately.
Imagine for a moment that you're driving to a job interview. You forgot your map, so you're getting directions from a friend on your cell phone (hands free, of course!):
"I just passed a gas station on the right," you say. "That was a major intersection."
"Wait..." says your friend, as he puzzles over a map. "What street are you on? Which direction are you going?"
"I can't tell!" you yelp, slamming on the brakes as a bright yellow sports car cuts you off. "Uh... sorry. It's a pretty twisty road—does that help? Wait... I just passed Hanover."
"Hanover Street or Hanover Loop?" asks your friend.
The problem in this scenario is that you and your friend are speaking two different languages. You're talking about what you see on the road and your friend is talking about what he sees on his map. You need to translate between the two, and that adds delay and error. You'll get to your job interview eventually, but you'll probably miss a few turns along the way and you might not get there on time.
A similar problem occurs between programmers and domain experts. Programmers program in the language of technology: classes, methods, algorithms, and databases. Domain experts talk in the language of their domain: financial models, chip fabrication plants, and the like.
You could try to translate between the two languages, but it will add delays and errors. You'd produce some software eventually, but you'd probably introduce some bugs along the way. Instead, pick just one language for the whole team to use... a ubiquitous language.
How to Speak the Same Language
Programmers should speak the language of their domain experts, not the other way around.
Imagine that you're creating a piece of software for typesetting musical scores. The publishing house you're working for provides an XML description of the music and you need to render it properly. This is a difficult task, filled with seemingly minor stylistic choices that are vitally important to your customers.
In this situation, you could focus on XML elements, parents, children, and attributes. You could talk about device contexts, bitmaps, and glyphs. If you did, your conversation might sound something like this:
Programmer: "We were wondering how we should render this clef element. For example, if the element's first child is
Gand the second child is
2, but the octave-change element is
-1, which glyph should we use? Is it a treble clef?"
Domain expert: (Thinking, "I have no idea what these guys are talking about. But if I admit it, they'll respond with something even more confusing. I'd better fake it.") "Um... sure, G, that's treble. Good work."
Instead, focus on domain terms rather than technical terms.
Programmer: "We were wondering how we should print this G clef. It's on the second line of the staff but one octave lower. Is that a treble clef?"
Domain expert: (Thinking, "An easy one. Good.") "That's often used for tenor parts in choral music. It's a treble clef, yes, but because it's an octave lower we use two symbols rather than one. Here, I'll show you an example."
The domain expert's answer is different the second time because he unsderstands the question. The conversation in the first example would have led to a bug.
Ubiquitous Language in Code
As a programmer, you might have trouble speaking the language of your domain experts. When you're working on a tough problem, it's difficult to make the mental translation from the language of code to the language of the domain.
A better approach is to design your code to use the language of the domain. You can name your classes, methods, and variables anything. Why not use the terms that your domain experts use?
Reflect how the users think and speak about their work.
This is more than learning the domain to write the software; this is reflecting in code how the users of the software think and speak about their work. By encoding your understanding of the domain, you refine your knowledge and—due to code's uncompromising need for precision—expose gaps in your knowledge that would otherwise result in bugs.
To continue the example, a program to typeset a musical score based on XML input could be designed around XML concepts. A better approach, though, would be to design it around domain concepts, as shown in Figure.
One powerful way to design your application to speak the language of the domain is to create a domain model. This process deserves its own book; [Evans] and [Wirfs-Brock & McKean] are two worthy examples.
The process of creating a domain-centric design is domain-driven design or domain modelling. Some people consider it synonymous with object-oriented design. In this case, domain-centric design is sometimes called "true" object-oriented design in order to contrast it with object-oriented designs that don't emphasize domain concepts.
Refining the Ubiquitous Language
The ubiquitous language informs programmers, but the programmers' need for rigorous formalization also informs the rest of the team. I often see situations in which programmers ask a question—inspired by a coding problem—that in turn causes domain experts to question some of their assumptions.
Your ubiquitous language, therefore, is a living language. It's only as good as its ability to reflect reality. As you learn new things, improve the language as well. There are three caveats about doing this, however.
First, ensure that the whole team—especially the domain experts—understands and agrees with the changes you're proposing. This will probably require a conversation to resolve any conflicts. Embrace that!
Second, check that the changes clarify your understanding of the business requirements. It may seem clearer to make a change, but the language must still reflect what the users need to accomplish with the software. Keep out programmer jargon—you can help domain experts refine their understanding of complicated corner cases, but don't replace their language with your own.
Third, update the design of the software with the change. The model and the ubiquitous language must always stay in sync. A change to the language implies a change to the model. Yes, this does mean that you should refactor the code when your understanding of the domain changes. Delaying these changes introduces an insidious type of technical debt: a mismatch between your design and reality, which will lead to ugly kludges and bugs.
Should we avoid the use of technical terms altogether? Our business domain doesn't mention anything about GUI widgets or a database.
It's okay to use technical language in areas that are unrelated to the domain. For example, it's probably best to call a database connection a "connection" and a button a "button." However, you should typically encapsulate these technical details behind a domain-centric face.
When you share a common language between customers and programmers, you reduce the risk of miscommunication. When you use this common language within the design and implementation of the software, you produce code that's easier to understand and modify.
When the whole team uses the ubiquitous language while sitting together, everyone can overhear domain discussions, especially during pairing sessions. Team members overhear domain and implementation discussions and join in the conversation to resolve questions and expose hidden assumptions.
If you don't have any domain experts sitting with your team, you may have trouble understanding the domain experts' thought process deeply enough to have a ubiquitous language. Attempting a ubiquitous language is even more important in this situation, though, as it will allow you to communicate more effectively with domain experts when you do have the opportunity to speak with them.
On the other hand, some problems are so technical they don't involve non-programmer domain knowledge at all. Compilers and web servers are examples of this category. If you're building this sort of software, the language of technology is the language of the domain. You'll still have a ubiquitous language, but that language will be technical.
Some teams have no experience creating domain-centric designs. If this is true of your team, proceed with caution. Domain-centric designs require a shift in thinking that can be difficult. See "Further Reading" at the end of this section to get started and consider hiring a programmer with experience in this area to help you learn.
It's always a good idea to speak the language of your domain experts. However, avoiding a domain-centric design can lead to simpler designs in small, technology-centric projects involving trivial business rules. Be careful, though: this design approach leads to defects and complex, unmaintainable designs in larger projects. See [Fowler 2002a] for further discussion of this trade-off.
Even small XP projects typically involve four programmers working for several months, so most XP projects are big enough to need a domain-centric design. Talk to your mentor (see "Find a Mentor" in Chapter 2) before deciding to use another approach.
Domain-Driven Design [Evans] is an excellent and thorough discussion of how to create a domain-centric design.
Object Design [Wirfs-Brock & McKean] discusses roles, responsibilities, and behaviors in the context of modelling applications.
Patterns of Enterprise Application Architecture [Fowler 2002a] has a good discussion of the trade-offs between domain models and other architectural approaches.
- Next: Stand-Up Meetings
- Previous: Sit Together
- Up: Chapter 6: Collaborating