Technique 5: Promote Well-Developed Disciplines
Ultimately, you want an organization where everyone is focused on good principles at all levels of design, including architecture. People should be asking the right questions, deferring commitment, and keeping things divided as they ought to be. Much of that change will grow organically within your organization. People will have to change their thinking, and mostly they'll have to do it on their own.
However, some things are so valuable, so important, and so portable that the software industry has codified them as disciplines. Two such things are design patterns and test-driven development (TDD). In reality, they're just two facets of the same creature. Design patterns are barely useful when not paired with TDD. Test-driven development without design patterns isn't really TDD—it's just writing tests first (see Figure 12).
Figure 12 The state of the art.
Together, and in the hands of an expert, true test-driven development can generate software that is flexible, safe to change, and inexpensive to maintain. In the context of this article, though, the most important thing about the application of these skills is that they drive people to make good choices. Test-driven development compels people to do two things that will drive them toward better encapsulation.
First, it makes a programmer want to attack a large problem as a bunch of small problems. It's the old Agile argument: tackling a series of small, easily accomplished tasks is a lot easier than wrestling with one giant, insurmountable-seeming goal (see Figure 13).
Figure 13 Bite-sized pieces.
Second, test-driven development makes programmers want to develop a feature starting from the outside and working their way inward. This ensures that everything is created in the context of need, which has two beneficial consequences: You don't make things you don't need, and everything you do make fulfills the need it was intended to address (see Figure 14).
Figure 14 When you focus on the innermost component of a design first, you often lose sight of what matters.
These forces make doing the wrong thing harder and doing the right thing easier. They do it by working together. Someone who starts writing code willy-nilly in a client application can just as easily bake some behavior into that application which ought to live on the server. Someone who is breaking a problem into a thousand pieces and starting with one in the bowels of the system can end up creating a tangled, coupled mess of garbage.
However, someone who starts developing code in a client application as close to the "surface" of that application as possible, and taking measures to ensure that each thing built is completely testable, will do things much differently. The need to test something before any of its dependencies exists imposes a certain amount of encapsulation, and the need to separate things into small, testable pieces forces people to think about where each piece will live.
So take an active role in driving adoption of test-driven development and design patterns among your developers. Learn about it (if necessary) and promote it. It will help them write better code and allow better architectures to emerge.