OOAD Exercise Step 5: In which we build of tower from things we should be worried about

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 4: In which we transform big software problems into smaller, more manageable ones) we used System Analysis (one of our Analysis Superpowers) to turn our use case diagram and feature list into a set of well encapsulated packages (or systems). Now all we need to do is decide which system we should start on first!

This seems like it should be an easy decision, but don’t be mislead! Where you start your low level design makes a big difference. A lot of engineers (myself included) like to start by working on parts of a solution they already understand; solving problems you already “get” is fast, feels good, and has the fringe benefit of making you look like a total-rock-star. The problem here is starting with what you know well will cause your design to change as you learn about those things you don’t know so well. This can land you in an endless cycle of re-design/re-implementation that could not only tarnish your rock-star image, but might leave your team (even if it’s a team of one) doing twice the work. I know, right? Yikes, indeed. To make sure we avoid anything like that let’s cover our 3rd Analysis Superpower:

Analysis Superpower 003: Building a tower of things you should be worried about!

At least it doesn't seem like a good idea...

So, when you see buildings go up in real life – you generally don’t see the construction crew start at the top of the tower and work their way down, I mean, it’s just not done (at least I don’t think it is). In fact, if your building doesn’t have a foundation, or you realize you need to add one later you’re more/less screwed. Which makes foundations one thing you definitely want to think about when you’re building something. Software works the same way – except figuring out just what that foundation should be is occasionally harder than you would think.

One great way to figure out what a foundation should be is to evaluate each system and determine how much risk it poses to the rest of the application. We do this using a little Risk Analysis – which is the process of determining what your foundation is, and which systems build upon it. Good risk analysis can help define interfaces between systems that are much less likely to break over time, and interfaces that don’t break means well encapsulated code that doesn’t need to be re-factored every time a behavior changes.

Have you ever worked on a project with some jerk that breaks all your code because they realized their interface wasn’t going to do the job they wanted it to do? Did they do it multiple times during the process? There are few things I find to be a bigger waste of time than refactoring a ton of code because someone didn’t even try to think it through the first time around.

Poor risk analysis can leave your interfaces a bit like this...

How not to do risk analysis:

For a project this small figuring this out is kind of a freebie; but it’s still an important part of OOAD. When I’m making a game my knee jerk reaction is to avoid the game engine component. Game engines are huge and require a lot of research and thought, which can seem a little overwhelming. I’ve written some before, and moreover we’re using Unity3d – so let’s see what happens if I just leave that until last and follow my “gut feelings” for what I should work on first:

It won't crush you, you'll just have to do twice as much work this way...

The problem here is that if my impulsive decisions didn’t work out (and they wouldn’t, because I’m writing it this way on purpose) I’ll have to constantly change my design and rework code as parts about our software that weren’t well understood are exposed – which is a huge waste of everyones time (even if you’re just working by yourself). If you build off of a foundation of the riskiest, least understood systems this kind of refactoring should be kept to a minimum. Now, let’s take a look at a better way to select a foundation…

A better way to do risk analysis:

Before you ask yourself if anyone's dumb enough to organize their systems as I did in the "how not to" section, let me answer your question by saying, "Yes, yes I am".

As you can see I’ve got my systems listed on the left side of the diagram, and my “Tower of things I should be worried about” on the right. Building a tower is a great way to double check your thinking, and it gets you thinking about the lower level relationships of the solution. In order to determine what goes where; each system is given points based on three separate categories, the more points a system has the closer to the foundation it should be. Here’s how the points break down:

  • Understanding: Each system is given 1 to 3 poitns based on how well you understand the problem it’s going to solve. 1 point for a well understood system, 3 points for a complete unknown, and 2 points for somewhere in-between.
  • Affected by: Each system gets one point for each arrow you can draw pointing away from it (this defines interaction with other systems, events, method calls, etc.).
  • Affects others: Each system gets one point for each arrow pointing toward it (this indicates that changes in the interface to this system have the potential to negatively impact other systems).

So, when we total the points I gave each system (they’ll be a little different for everyone) we end up with the Game Engine system at the bottom. The one system I wanted to skip until the end looks like it could’ve caused me more headaches than any of the others. So even though this kind of step seems trivial, it’s always worthwhile to double check your thinking! The very worst thing that could happen is that you find out you were right all along (for me, this is rarely the case). I’ve added what we did today to our Woebot Chapter 1: Design Document, please feel free to review it.

So, that’s it for this post. Next time in Step 6: In which we write use cases that are more fun than a root canal we’ll cover our fourth (and most powerful) Analysis Superpower. Thanks for reading, and please leave and questions or comments you might have down below.

This entry was posted in Software Design, Woebot Chapter 1. Bookmark the permalink.

6 Responses to OOAD Exercise Step 5: In which we build of tower from things we should be worried about

  1. Rizwan says:

    Thanks again Eagan for writing the next step :)

    Risk analysis does make sense while we are working on a new software system but It could also be very helpful if we are working on medium to large scale sized project on an existing system. Agreed/disagreed?

    • Great question as per usual :D. At first I was going to say, “it depends” but the more I think about it the more I feel that in any significant amount of code refactoring/development this is a useful thing to think about – even if you don’t go to the trouble to diagram it out :)

  2. Shane says:

    About your interfaces comment above and the refactoring jerk… I get a bit unpopular sometimes because though I think interfaces are useful, I think they are a bit dangerous as well and should be used with caution in modular and enterprise architectures for anything user related. What I often find is every feature ends up as “the thin end of the wedge” and an interface can’t possibly plan for the complex relationships that come out of customer requests and repository branching and tagging can make produce a maintenance nightmare keeping the interfaces in synch. While premature optimization is one of the roots on the tree of evil, creating necessary relationships that are both likely to change and brittle is just as bad imo.

    That said, what do you think of Aspect Oriented Development as it relates to UML? Can uml represent AOP concepts or is it intended mostly for OOP?

    • Shane,

      Poorly defined interfaces are incredibly risky, I quite agree with you. I’m not sure what one would use them for on a user facing end – these are usually based on UI components and meta data for me – and the one place I think inheritance actually works out ok. The whole thing about this or any other process is that it has to hold up well to change – if you’re finding that interfaces aren’t holding up well then it either shouldn’t be used as an interface (GUI components are a perfect example of something where the cost benefit isn’t always 1:1), or in other situations it might be that the problem just wasn’t as well understood as it could’ve been when they were defined. However, that said, the whole point of interfaces is so that your software does hold up well to change, and that behavior can change at runtime without affecting other bits of code. You rarely need a listbox display to change behavior at runtime, but what your application does with the data in a listbox certainly might need to :). So I think for me as well the interfaces usually end up behind any kind of user facing components. It all depends on what you need any what you’re doing – there are frameworks where something like that might make sense.

      As far as AOP goes, though I’m not a huge fan of the kind of code it creates; some of the principles are the same and would translate quite well into UML. I would be very surprised if specific modeling elements for this didn’t exist already :). Thanks again for commenting, it totally makes my day!

      P.S. Who’s the refactoring jerk, is that me?

      • Shane says:

        oh god no, I was challenging the word “jerk”. :)

        I keep looking for ways to distribute intelligence across an application in ecma based scripts (namely actionscript and javascript) in video driven applications where god knows what a customer is going to want next. The issue I’ve been struggling with is I keep running into legacy code where users have used things like IvideoPlayer.play, where modules will register themselves with some kind of central controller and other modules would call these methods via interface. This is a simplified example of course, but problems start when someone inserts a module that is meant to interrupt the standard flow of events, like say a click to play or advertsing component that is meant to block the play command or new methods are needed for something we never could have predicted like IVideoPlayer.adjustContrast that needs to be envoked in the same manner. Because of that I’m partial to loose coupling over interface binding for that kind of thing. Now when it comes to generic integration points like registration or ingestion, etc I have no problem with, and use interfaces regularly. It sounds like we are more or less in agreement, just elaborating a bit on where I’m coming from.

        As to your posts, I’m finding them useful, keep em coming!

  3. Justin says:

    Thanks for writing this guide, it’s been very helpful so far! As someone just starting out, I’ve seen plenty of tutorials on writing code. This is the first I’ve seen of arguably the most important step of all! Do you plan on finishing it?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>