OOAD Exercise Step 4: In which we transform big software problems into smaller, more manageable ones

So, in case you haven’t visited before I’m writing a small game using a simple and very effective methodology. I’m also taking you, dear reader, along for the ride!

In our last post (Step 3: in which we discover that our feature list sucks) we employed the first of our Analysis Superpowers by checking our feature list against our use case diagram to see if we had anything missing (which we definitely did). Now that we’ve got that problem solved, it’s time to learn a new Analysis Superpower!

Not really the best way to choose what use cases/features to start on first!

So, now we have this big list of features and use cases; and we have some idea how they all relate to each other. At this point you might be wondering what to work on first. It’s important when making this decision that you choose parts that are well encapsulated, so your team (even if it’s just you) can work as independently as possible. You also always want to focus on the riskiest, least understood items before focusing on the ones you know well. There are essentially two steps involved in making this happen, the first of which is called System Analysis (we’ll cover the second one in the next article).

The totally kick ass world of System Analysis:

System Analysis is where you take your use cases and features and group them into logical categories or systems. For instance, the use case/features listed below were paired together during our last step:

(UC008): Application handles player and game status information.

(Woebot-F002): The game shall provide a time based scoring system – the faster you finish the game, the higher your score.

(Woebot-F004): The player shall posses a health meter which can be reduced by taking damage or increased by collecting health units.

From comparing and contrasting the relationships above we could categorize all three of these items under one system. A system name should describe the responsibility of that system as briefly and succinctly as possible, so we’ll call this one “Status Update System”. So, by putting that use case and it’s features under one name we’ve created a small, well encapsulated section of the project that can be worked on fairly independently. It also has the benefit of describing a few different behaviors with only a few words. This is going to come in very handy later when we talk about our third Analysis Superpower, but in the meantime let’s go through the rest of our features and use cases and see if we can fit them into categories too.

How not to do System Analysis:

In the diagram below I’ve laid out our use cases/features, and grouped them into multiple arrow boxes pointing to a system they might belong to. Obviously, since this is the “How not to” section, I’ve done something wrong.

If one or more systems seem to have common behavior then they can usually be combined.

If you create a system for each set of use cases and features you’re likely to end up with a lot of systems. The problem with breaking things up this way is that it doesn’t make the solution any easier to manage. Not only are there too many chunks, but they share a lot of common behavior, which doesn’t really make sense. Let’s look at a different way to lay these out…

A better way to do System Analysis:

What we need to do is combine some of the common elements from our previous diagram to create as few systems as possible, each carrying out a single major responsibility.

This level of abstraction is going to make the rest of our work a lot easier, you'll see...

So, now everything is organized into logical chunks. More importantly we’ve identified parts of our software that can be encapsulated from other parts. In other words all any system needs to know about another system is what it does, and not how it gets done. For instance, the Game Engine system shouldn’t care whether character input comes from a mouse, joystick, keyboard, or some kind of monster AI – it should all work the same way. Likewise, the weapon system should be able to handle targeting, shooting, upgrades, and other weapon behavior regardless of what character fires a weapon (for instance, maybe there are bad guys who will use the same kind of weapon as the player). In addition, any classes in a system should be able to handle change without breaking code in the other systems (we’ll get to classes in another article).

Encapsulation is good for all kinds of things, not just software development...

You’ll also notice that I added two more use cases in this step that I hadn’t thought of before. Again, one of the most important parts of this process is that it helps you think through what your software is going to do. That way you don’t realize you have to make a bunch of changes once code is written. I’ve added what we did today to our Woebot Chapter 1: Design Document, please feel free to review it.

12 Responses to OOAD Exercise Step 4: In which we transform big software problems into smaller, more manageable ones

Thanks again for another great step :)
I see that you are covering commonaltiy and variability anlysis here to define as few systems as possible to manage the solution. How should we handle the features and uses cases which are not common to a single system and they do not fit in any of our exisiting systems? Should we create one subsystem for each of these features (which is of course overkill) or should we group all of them together in a single sub system named “Random System”? Or there might be reasons why we are having issues deciding where they belong, such as features and uses cases still being too vague to be placed in a sytem? Could you think of some more of those reasons?

As always Rizwan that’s a totally great question! Of course, it would be ideal if everything fit in nice little boxes but that’s often not the case. When you’re stuck like that I really think the choice is up to each developer. For instance, some functionality might be so small that it makes sense in a “Random” or “Common” system, but then maybe some might be large enough to warrant their own (especially if it’s something you think might be extended in the future). Maybe those small disparate items make more sense as requirements in another system instead of as feature level details. Technically it’s not important how you do it as long as you’ve identified as many commonalities as possible, and more importantly you took the time to think about the best way to do it. Every developer is going to approach this type of design a little differently, and that’s totally fine. In pretty much every outcome they’ll be making more informed decisions about their projects by taking the time to do it. (Like a blueprint, or even a painters sketch – no one really likes doing those parts, but they’re an important part of the process)

Thanks again for taking the time to read these. Your question totally made my day :D.

So I totally shut down when you talk your techie talk, but I do understand the words “manageable chunks” which works well in many other contexts. So congrats to you for all the mistakes and all the manageable chunk-making!

How would you represent more pervasive elements of your architecture, such as an eventing engine or some kind of module registration / management class? I see how you’ve wrapped discreet barriers against the facets of your application, so I’m wondering if that’s a task for a different phase of development or is that just not applicable in this case?

How would you represent more pervasive elements of your architecture, such as an eventing engine or some kind of module registration / management class? I see how you’ve wrapped discreet barriers against the facets of your application, so I’m wondering if that’s a task for a different phase of development or is that just not applicable in this case?

That kind of stuff usually happens at a lower level in this methodology (called Domain Analysis, and it’s the only fun part about writing use cases IMHO). Each system needs to expose one or more consistent interfaces to other systems in your application so that any time the code behind those interfaces changes it doesn’t break the code that uses them – but figuring out what those should be called / what methods they should have, and how it should be organized is a lot more effective if you write use cases about how they’re used first (which is a *huge* pain in the ass, but can totally transform your solution). That’s a great question Shane – thanks for asking! :D

Yeah, I can understand the importance of use cases and simultaneously get annoyed with them and don’t particularly enjoy how “product managers” (not project managers) don’t like or trust cycles being spent on use cases. I do wonder though if the way of the world is “show me something as instantly as possible”, what tools or design philosophies are out there for that and if those tools will ultimately win out. Is UML more in the “waterfall” vs agile camp or is it agnostic? Just from the descriptions I’m seeing here it seems to take the “design everything before coding” approach.

So, to write a entire design document to the point where I’m ready to code takes me between one and two weeks depending on the size of the project. If you’ve got “Product Managers” that have any authority over what you do with your time where you work then I advise looking for a company that has their priorities straight.

Of course, any methodology that has you spend time thinking about the problem before you start writing code right away is going to improve that code. Some companies subscribe to prototyping, but when you’ve got product managers they usually see a demo and think it’s ready to sell (even when you tell them that it’s absolutely not). So, the only functional solution I’ve ever found for that problem was to get a job at a company that understands best practices – and knows that product managers should in now way be capable of influencing outcome of a project other than to make feature requests / recommendations. I think that with product managers, you get people who don’t know a damn thing about the craft of software development driving it for everyone else – which really sucks if you want to feel good about what you make.

UML is pretty agnostic – you can totally use it to torture other people by putting in in a wretched stage gate review process, or having day long meetings about it. I use it as a tool to encourage developers to think about problems before they solve them – but I don’t actually believe everything should be designed before you code it – but there are some steps that make a huge difference if you do them first. People keep calling this process waterfall – but it’s an agile process and isn’t anything close to waterfall. Once things are broken into systems you can pick and choose how much you do from there (sometimes one use case is all I need). Basically, you want your design to be “just good enough” to start coding. That’s subjective for everyone, but I’ve had very good results using these as a general guidelines.

Thanks, that was clarifying! I like the find another job advice, but there’s always that oooooone thing the company does that makes you not want to leave. With the exception of what I call “Panic Driven Design”, I’m in a pretty sweet spot right now with my current job, working on a framework supporting feature parity between flash and html widgets for a company called KickApps. It keeps me learning, pushed, but most importantly, working from home. :) I plan on sticking it out for a while but eventually I’d like to move on to a company focused on technology and not just mergers and acquisitions. Because of the environment “I’m growing up in”, I’m not really close to best practices other than my own study so I tend to categorize in broad strokes. I’m all about the tools though and what I’d like to see are some IDE plugins that allow you to attach uml to files / classes, etc. I think the closer you bring tools like UML to the environments that reference them, the more people will use them in one of those inverse square type relationships. Sorry to clutter up the comments with personal droppings, feel free to sweep it up if you don’t want them on the floor!

Are you kidding me? I’m so happy whenever anyone on comments on my blog that I wouldn’t even delete one from my mother (I’ll take what I can get :D). I empathize about the work situation, I’ve been there before myself and totally understand. As far as UML integration VS2010 does a better job of it than previously, but it’s a hard problem to solve. Thanks again for commenting!