This article provides an overview of the elements of C++; specifically, the 'C' portion of C++.
Note how section 2.2 describes tokens as the "minimal chunks of a program". The root goal of programming is solving problems using the 'chunks' of a programming language. Of course, the chunks must be appropriate for the type of problems to be solved. Generally, smaller chunks are applicable to many types of tasks, but involve more effort; larger chunks involve less effort, but are designed for more specific tasks.
Analysis and design
Phase 1: What are we making?
In the previous generation of program design (called procedural design), this is called "creating the requirements analysis and system specification".
These, of course, were places to get lost; intimidatingly-named
documents that could become big projects in their own right. Their
intention was good, however. The requirements analysis says "Make a list
of the guidelines we will use to know when the job is done and the
customer is satisfied". The system specification says "Here's a
description of what the program will do (not how) to
satisfy the requirements". The requirements analysis is really a
contract between you and the customer (even if the customer works within
your company or is some other object or system). The system
specification is a top-level exploration into the problem and in some
sense a discovery of whether it can be done and how long it will take.
Since both of these will require consensus among people (and because
they will usually change over time), I think it's best to keep them as
bare as possible – ideally, to lists and basic diagrams – to save time.
You might have other constraints that require you to expand them into
bigger documents, but by keeping the initial document small and concise,
it can be created in a few sessions of group brainstorming with a
leader who dynamically creates the description. This not only solicits
input from everyone, it also fosters initial buy-in and agreement by
everyone on the team. Perhaps most importantly, it can kick off a
project with a lot of enthusiasm.
It's
necessary to stay focused on the heart of what you're trying to
accomplish in this phase: determine what the system is supposed to do.
The most valuable tool for this is a collection of what are called "use
cases". Use cases identify key features in the system that will reveal
some of the fundamental classes you'll be using. These are essentially
descriptive answers to questions like:
- "Who will use this system?"
- "What can those actors do with the system?"
- "How does this actor do that with this system?"
- "How else might this work if someone else were doing this, or if the same actor had a different objective?" (to reveal variations)
- "What problems might happen while doing this with the system?" (to reveal exceptions)
If
you are designing an auto-teller, for example, the use case for a
particular aspect of the functionality of the system is able to describe
what the auto-teller does in every possible situation. Each of these
"situations" is referred to as a scenario,
and a use case can be considered a collection of scenarios. You can
think of a scenario as a question that starts with: "What does the
system do if...?" For example, "What does the auto-teller do if a
customer has just deposited a check within 24 hours and there's not
enough in the account without the check to provide the desired
withdrawal?"
Use case diagrams are intentionally simple to prevent you from getting bogged down in system implementation details prematurely:
Each stick person represents an "actor,"
which is typically a human or some other kind of free agent. (These can
even be other computer systems, as is the case with "ATM"). The box
represents the boundary of your system. The ellipses represent the use
cases, which are descriptions of valuable work that can be performed
with the system. The lines between the actors and the use cases
represent the interactions.
It doesn't matter how the system is actually implemented, as long as it looks like this to the user.
A use case does not need to be terribly complex, even if the underlying system is complex. It is only intended to show the system as it appears to the user. For example:
The
use cases produce the requirements specifications by determining all
the interactions that the user may have with the system. You try to
discover a full set of use cases for your system, and once you've done
that you have the core of what the system is supposed to do. The nice
thing about focusing on use cases is that they always bring you back to
the essentials and keep you from drifting off into issues that aren't
critical for getting the job done. That is, if you have a full set of
use cases you can describe your system and move onto the next phase. You
probably won't get it all figured out perfectly on the first try, but
that's OK. Everything will reveal itself in time, and if you demand a
perfect system specification at this point you'll get stuck.
If
you get stuck, you can kick-start this phase by using a rough
approximation tool: describe the system in a few paragraphs and then
look for nouns and verbs. The nouns can suggest actors, context of the
use case (e.g. "lobby"), or artifacts manipulated in the use case. Verbs
can suggest interactions between actors and use cases, and specify
steps within the use case. You'll also discover that nouns and verbs
produce objects and messages during the design phase (and note that use
cases describe interactions between subsystems, so the "noun and verb"
technique can be used only as a brainstorming tool as it does not
generate use cases) .
The boundary between a use case and an actor can point out the existence of a user interface, but it does not define such a user interface. For a process of defining and creating user interfaces, see Software for Use by Larry Constantine and Lucy Lockwood, (Addison Wesley Longman, 1999) or go to www.ForUse.com.
Although it's a black art, at this point some kind of basic scheduling is important. You now have an overview of what you're building so you'll probably be able to get some idea of how long it will take. A lot of factors come into play here. If you estimate a long schedule then the company might decide not to build it (and thus use their resources on something more reasonable – that's a good thing). Or a manager might have already decided how long the project should take and will try to influence your estimate. But it's best to have an honest schedule from the beginning and deal with the tough decisions early. There have been a lot of attempts to come up with accurate scheduling techniques (like techniques to predict the stock market), but probably the best approach is to rely on your experience and intuition. Get a gut feeling for how long it will really take, then double that and add 10 percent. Your gut feeling is probably correct; you can get something working in that time. The "doubling" will turn that into something decent, and the 10 percent will deal with the final polishing and details. However you want to explain it, and regardless of the moans and manipulations that happen when you reveal such a schedule, it just seems to work out that way.