Emergent design is not something you do because you are doing Agile and you don’t have any choice because you don’t understand what you need to build. Emergent design is a better way to design – even when you know what you want your system to do.
I’ll admit I didn’t understand this until about 12 years ago. I was in a situation where I understood what I wanted my system to do, but I couldn’t come up with a good design for it. I tried designing incrementally as a design approach because my normal methods weren’t working. In the process, I achieved some insights that helped me better understand design in an Agile world.
I have written this blog recounting my own experience in learning this, not just to describe what was, for me, the beginning of my understanding of emergent design, but to also illustrate a couple of methods of thinking that I have found useful and think you might find of use as well.
In the 80s I had developed state of the art spa/salon software that was still in use almost 20 years later. It was written in DOS and had never been converted to Windows. Around 2001, I had to enhance it but wanted to leave it under DOS for several reasons that aren’t pertinent to this article. I mention this because had it been running under Windows, some of these challenges may have been different – but I think not. Anyway, the software had several options for both business logic and the UI. There were three flavors of business logic:
The restrictions on the business logic were quite simple and were achieved by limiting access to the pages people were allowed to see. At the same time, screens could be normal (25 rows x 80 characters) or large (40 rows x 132 characters). They could also have touch screens or not. The current design worked for all of these combinations of business logic and screens with a fairly good decoupling of the business logic from the UI..
I was considering a new set of requirements. This would expand the number of business logic and UI options considerably. The details aren’t important, but essentially I now would have about six different business logics as well as need to handle UIs that were either DOS based or HTML based. While there were some client-server solutions available (e.g., Java) that might have solved the problem, there were good reasons not to go that route.
Now this wasn’t really that complicated – I would sometimes want to do the display via DOS and sometimes do it by rendering HTML. I figured a design for this would take me maybe a day to complete after which I could start adding the new functionality with the end in mind.
I had been thinking about how to solve this problem for the last week or so prior to going to a conference. Overall, I had spent about a day attempting to achieve a solution – without success. I have learned that when something takes me longer than I anticipate, it’s usually because I have taken a non-optimal route. This wasn’t that hard a problem – it shouldn’t have taken more than a day – but here I was, more than a day of work later and no solution in sight.
I have also learned that when I have a problem I can’t solve, I should talk to someone whom I respect that I think can give me some sage advice. Now Bob Martin is one of my heroes and I knew he was at the conference. In fact, I heard that he had done a talk the day before about not building frameworks. I’d been told that he was adamant about this – sounding like when Nikita Khrushchev banged his shoe on the podium of the UN saying “we will bury you” (referring to the United States). I could actually easy see Uncle Bob doing this – and I mean this as a compliment.
So, I thought, maybe I should talk to Uncle Bob about things to get a different perspective. Unfortunately, I knew he’d be too busy – so I did the next best thing – I pretended to have a conversation with them. OK, I’m not really walking the streets of New York – I knew he wasn’t there. But I know doing this unlocks some sub-conscious knowledge I have. BTW – I seriously recommend this practice but suggest that you go off someplace quiet, by yourself, like I did, so you don’t look too odd. Of course, nowadays, with cell-phones, no one will realize you’re talking to yourself anyway.
I actually figured Bob was wrong and I was just wasting my time but what did I have to lose? Anyway, if it did fail, it’d be nice to be right with Uncle Bob for once (and don’t mention that since he really wasn’t there I couldn’t really win!). So, I asked (my pretend) Bob, “you don’t really mean never end up with a framework, what you mean is to not go about building one. Is that right?” He answered “that’s right. Start with something small, then add to it, keep adding function one piece at a time until you’ve got it all. Eventually, you may end up with a framework, but you won’t have built one, you’ll have evolved one.” I responded – “well, I don’t see how that’ll do me any good, I mean I am absolutely clear what I need to end up with – and a framework is clearly the best solution.” Bob just grunted in response, but I decided to go ahead and try his approach anyway because my approach was clearly not working.
I decided to start with a simple case – handling two different business logics with one UI. Coming up with a starting design only took five minutes – no surprise. Then I decided I would add rendering HTML and smiled to myself thinking – “well, I may not know how to solve this problem but at least I’m going to demonstrate that Uncle Bob doesn’t know how to either.” To my great surprise, within 10 minutes I had a design that solved the problem of a DOS and HTML UI and was simple to implement. What happened!?
People talk about learning from failure, but the opportunity is to learn from any result that is different from what you expected. This was certainly not what I expected. So I stopped to explore it. Clearly it wasn’t that I was just 10 minutes from a solution when I had the conversation with Uncle Bob. Something else had happened.
So I replayed my thought process starting with the initial simple case. In reviewing what I had done, I realized that while I had not attended to the different UIs (DOS and HTML) that I would have to support, I did attend to that I would have to have multiple UIs. The solution was clear – put all of the code that involved how the business logic talked to the UI in one class. Then, when the UI needed to change, I would only need to change it in one place (for more on this approach, read Shalloway’s Law in Essential Skills for the Agile Developer).
The result was that I was solving a simple problem while considering how it would change, not solving a complex problem not having to worry about change. The simpler problem was easier to solve since it didn’t overload my brain. By attending to the fact that it needed to change, when I considered how to add rendering HTML, it was a simple problem to solve. In other words, at the beginning, I was not attending to all of the ways that the UI would change, merely attending to the fact that it would change. In this case, I put in an abstract layer that handled this UI. I made the interface work for the DOS UI. However, when the HTML UI was needed, all I needed to do was:
In truth, I wasn’t truly doing emergent design because I was designing something and then continuing with the design. I was designing in steps. True emergent design would have me design, then build what I designed, then design the next extension, … But the success was enough to give me the insight that designing for change while attending to a subset of the problem was a powerful design method that could achieve quality designs where considering all of the issues would merely achieve overwhelm of my brain.
Emergent design is not merely doing the simplest thing possible, however. It is focused on creating high quality code while only implementing what you need at the time – not exactly the same thing. By collecting all of the interactions between the business logic and the DOS UI, I may not have been the simplest thing possible but I was clearly avoiding complexity while setting the stage for future extensions.
For those undertaking Agile methods, emergent design shows the way to design as well as instilling confidence that by attending to quality, one can implement design changes as needed when one becomes aware of them. After years now of doing emergent design, I am fairly confident that anyone doing it won’t paint themselves into a corner. Sure, they will hit times where they have to refactor, but the work of doing that won’t be more than the work that would have been required had they understood the challenge earlier. Of course, this is only true if the design is of high quality – that is, there is no redundancy or poor coupling. How one can achieve that in complex situations may still take a few other insights – but doing so can be done incrementally. I’ll be writing a follow blog in the next few weeks about how separating concerns in different manners can help with this.
Postscript: About a year later Uncle Bob and I were at the next rendition of the conference where he had helped me out so much. I was walking by a room when I saw him in there getting ready for his talk. Not wanting to disturb him, but wanting to acknowledge his contribution to me I yelled to him from outside the room “hey, Bob, you were right.” Bob asked “right about what?” a bit perplexed. I responded “about the argument we had.” Of course, Bob was really perplexed now so I added – “you weren’t there.” Bob immediately responded “as long as I was right.” I did explain this and my earlier conversation “with” him a few years later.
Upcoming blogs: The methods I used here included two other very important design principles: Refactor to the open-closed and Shalloway’s principle. I’ve linked to them here but will blog more on them later.
Scott Bains, excellent Emergent Design: The Evolutionary Nature of Professional Software Development.