You have to start somewhere, but you better pick the right somewhere! You know how to break your application up into lots of small problems, but all that means is that you have LOTS of small problems. In this chapter, we’re going to help you figure out where to start, and make sure that you don’t waste any time working on the wrong things. It’s time to take all those little pieces laying around your workspace, and figure out how to turn them into a well-ordered, well-designed application. Along the way, you’ll learn about the all-important 3 Qs of architecture, and how Risk is a lot more than just a cool war game from the ‘80s.
So you’ve got lots of small pieces of functionality that you know how to take care of... but you’ve also got use case diagrams, feature lists, and a whole lot of other things to think about.
The framework supports different types of terrain.
The framework supports different time periods, including fictional periods like sci-fi and fantasy.
The framework supports multiple types of troops or units that are game-specific.
The framework supports add-on modules for additional campaigns or battle scenarios.
The framework provides a board made up of square tiles, and each tile has a terrain type.
The framework keeps up with whose turn it is.
The framework coordinates basic movement.
We have feature lists...
...high-level views of what we need to build...
...the customer’s vision...
...and even some design patterns to apply.
It’s really not enough to just figure out the individual pieces of a big problem. You also need to know a little bit about how those pieces fit together, and which ones might be more important than others; that way, you’ll know what you should work on first.
You write great software the same way, whether you’re working on a small project, or a huge one. You can still apply the three steps we talked about way back in Chapter 1.
The first step is always to make sure an application does what it’s supposed to do. In small projects, we used a requirements list to write down functionality; in big projects, we’ve been using a feature list to figure those things out:
Even if we know to start by focusing on functionality, we still need to figure out which pieces are the most important. Those are the pieces we want to focus on first.
The things in your application that are really important are architecturally significant, and you should focus on them FIRST.
You gotta start somewhere!
It’s awfully hard to talk about the relationships between parts of a system if you don’t have any of the parts themselves. So say you wanted to talk about how the Board module interacted with the Units module:
To figure out how these modules interact, you’d need to have at least the basics of the two modules in place first.
So architecture isn’t just about the relationships between parts of your app; it’s also about figuring out which parts are the most important, so you can start building those parts first.
When you’re trying to figure out if something is architecturally significant, there are three questions you can ask:
Is the feature really core to what a system actually is? Think about it this way: can you imagine the system without that feature? If not, then you’ve probably found a feature that is part of the essence of a system.
If you’re not sure what the description of a particular feature really means, it’s probably pretty important that you pay attention to that feature. Anytime you’re unsure about what something is, it could take lots of time, or create problems with the rest of the system. Spend time on these features early, rather than late.
Another place to focus your attention early on is on features that seem really hard to implement, or are totally new programming tasks for you. If you have no idea how you’re going to tackle a particular problem, you better spend some time up front looking at that feature, so it doesn’t create lots of problems down the road.
Using the three Qs of architecture, we’ve started to add some order to all that confusion we started out with:
We’ve gotten Gary’s system down to three key features, but the big question remains: which one should you work on first?
Jim: What in the world are you guys thinking? What good is it starting with anything that isn’t the essence of the system?
Joe: That’s ridiculous. Even if that’s the essence of the system, you’ve got to figure out what game-specific units are. That could take weeks to write if it’s harder than we think!
Frank: Maybe... but we know that coordinating movement will be tough, because we don’t have a clue how to do it! How can you possibly work on anything else when you know the movement deal is going to be difficult?
Joe: But the game-specific units might be difficult, too! We just don’t know, and that’s my point. We’ve got to figure out the parts of the system we don’t know anything about, or they could be real trouble!
Jim: You guys go on and write movement engines and deal with units. Me, I’m gonna write a board, because... well... something tells me Gary will want to see a board for his board game system. And I’m not about to leave the board for later... I’m taking it on first.
Frank: You’re both nuts. While you’re putting off the hard tasks, I’m gonna make sure the things that I don’t have any real idea about are taken care of, right away.
The reason that these features are architecturally significant is that they all introduce RISK to your project. It doesn’t matter which one you start with—as long as you are working towards reducing the RISKS in succeeding.
Take another look at our key features:
The point here is to REDUCE RISK, not to argue over which key feature you should start with first. You can start with ANY of these, as long as you’re focused on building what you’re supposed to be building.
To actually make Board
compile and work, we need to create a Tile
and Unit
class. Here’s how we wrote those classes:
You don’t need to worry about everything that Tile
and Unit
will eventually need to do. Your focus is on making Board
and its key features work, not on completing Tile
or Unit
. That’s why we left Unit
so bare, and added only a few methods to Tile
.
Focus on one feature at a time to reduce risk in your project.
Don’t get distracted with features that won’t help reduce risk.
You can download these Board-related classes for Gary’s framework at http://www.headfirstlabs.com. Just look for Head First OOA&D, and find “Gary’s Game System - Board classes.”
Our architecture and key feature list has helped us get the basic Board
in place, and make sure we’re capturing the essence of the system for the customer. Let’s look back at our key feature list:
Build on what you’ve already got done whenever possible.
When you’ve got nothing but requirements and diagrams, you’ve just got to pick a place to start. But now that we do have some code and classes, it’s easiest to pick another key feature that relates to what we’ve already built. And remember our definition for architecture?
You really can’t talk about the relationships between parts if you don’t have two parts that have a relationship. We know Board
and Unit
are related, and that “game-specific units” are a key feature, so that’s the obvious thing to work on next.
The simplest way to understand a bit more about what “game-specific units” means is to talk to some of Gary’s customers, the game designers who will be using his framework. Let’s listen in on what they have to say:
We’re starting to learn more about what “game-specific units” means, but we still need to figure out how to actually add support for this feature to our game system framework. Let’s start by taking a look at the different types of units the customers mentioned, and figure out what’s common between them.
At first glance, you might have come up with a solution that looks something like this:
Commonality is about more than just the names of properties... you need to look a little bit deeper.
It might seem like there’s not anything common across all the units used in different games, but let’s take a step back from focusing on the actual names of the properties for each unit. What’s really the same for each unit?
At first glance, you might have come up with a solution that looks something like this:
Wondering why we spent all that time on commonality analysis? Look back at the first solution in Which feature should we work on next?, and then again at the second solution, on the left, and then fill out the table below to see what commonality has really bought us in terms of our design:
Number of unit types | Number of unit classes - Solution #1 | Number of unit classes - Solution #2 |
3 | ||
5 | ||
10 | ||
25 | ||
50 | ||
100 |
Which solution do you think is better? _______________________________________
Why? _______________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
We identified what was common, and put it in the Unit base class. The result was that game designers now only have to keep up with ONE unit class, instead of 25, 50, or 100!
We’ve figured out another key feature, reduced risk to our project even further, and only have one feature left to worry about.
We’re focusing on doing just the things that reduce risk.
Remember, the point of architecture is to reduce risk, and to create order. There are plenty of other things to work on in your application, but those are for after you’ve got a handle on how your application will be structured, and have the major risks reduced to the point where they are manageable.
We were trying to get a handle on the Unit class, and what “game-specific units” meant; at this point, we’ve done that:
Want to see the answers to the BE the Author exercise? Read the next four pages and see how close your pages are to what we did.
When you’re not sure what a feature really means, one of the best things you can do is ask the customer. We did this with the game-specific units, so let’s try the same thing for figuring out what coordinating movement means.
Listening to the customers should have given you a pretty good idea of what the third key feature of Gary’s game system framework is all about. Write what you think that feature really means in the blanks below:
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
Next you need to try and figure out what’s common about the different movement scenarios that the customers in Solution #2: It’s all the same! have been talking about. Are there some basic things that apply to all the different types of movement? If you think that there are, write those common things in the blanks below:
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
If you have an understanding of what “coordinating movement” means, and you know what things are common across all games, you should have an idea about what you need to do to the game framework to make this feature work. Write your ideas down in this final set of blanks:
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
_____________________________________________________________________
Here’s what we thought we needed to do based on what Gary’s customers were saying about movement:
Units should be able to move from one tile on the board to another. Movement is based on a calculation or algorithm specific to each game, and sometimes involves the game-specific properties of a unit.
So what exactly is common among all the different possible movement scenarios? Remember what the customers said?
Did you see what kept showing up in our chart? Every time we found some commonality, the variability column had the same words: “different for every game.”
When you find more things that are different about a feature than things that are the same, there may not be a good, generic solution.
Customers don’t pay you for great code, they pay you for great software.
Absolutely! Remember, great software is more than just great code.
Great code is well-designed, and generally functions like it’s supposed to. But great software not only is well-designed, it comes in on time and does what the customer really wants it to do.
That’s what architecture is about: reducing the risks of you delivering your software late, or having it not work like the customer wants it to. Our key feature list, class diagrams, and those partially done classes all help make sure we’re not just developing great code, but that we’re developing great software.