0% found this document useful (0 votes)
106 views

Object Oriented Design HEAD FIRST NOTES

Use cases help software developers understand the requirements of a system by describing scenarios of how users will interact with the system to achieve specific goals. A use case captures the steps required in both successful and unsuccessful interactions. While use cases do not directly help write code, they provide important context for developers to design systems that meet users' needs and handle unexpected situations. Defining use cases upfront helps ensure projects satisfy requirements and prevent costly rework later.

Uploaded by

Manpreet Kaur
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
106 views

Object Oriented Design HEAD FIRST NOTES

Use cases help software developers understand the requirements of a system by describing scenarios of how users will interact with the system to achieve specific goals. A use case captures the steps required in both successful and unsuccessful interactions. While use cases do not directly help write code, they provide important context for developers to design systems that meet users' needs and handle unexpected situations. Defining use cases upfront helps ensure projects satisfy requirements and prevent costly rework later.

Uploaded by

Manpreet Kaur
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Q Q: I still am confused about how this is a form of encapsulation.

Can you explain that


: again?

A: A: The idea behind encapsulation is to protect information in one part of your application
from the other parts of your application. In its simplest form, you can protect the data in
your class from the rest of your app by making that data private. But sometimes
the information might be an entire set of properties—like the details about a guitar
—or even behavior—like how a particular type of duck flies.
When you break that behavior out from a class, you can change the behavior without the
class having to change as well. So if you changed how properties were stored, you
wouldn’t have to change your  Guitar class at all, because the properties are encapsulated
away from  Guitar.
That’s the power of encapsulation: by breaking up the different parts of your app, you can
change one part without having to change all the other parts. In general, you should
encapsulate the parts of your app that might vary away from the parts that will stay the
same.

Q Q: But I don’t really see how this encapsulation makes my code more flexible. Can you
: explain that again?

A: A: Once you’ve gotten your software to work like it’s supposed to, flexibility becomes a
big deal. What if the customer wants to add new properties or features to the app? If
you’ve got tons of duplicate code or confusing inheritance structures in your app, making
changes is going to be a pain.
By introducing principles like encapsulation and good class design into your code, it’s
easier to make these changes, and your application becomes a lot more flexible.

Q Q: You said I should “delegate” comparisons to GuitarSpec. What’s delegation?


:

A: A: Delegation is when an object needs to perform a certain task, and instead of doing that
task directly, it asks another object to handle the task (or sometimes just a part of the task).
So in the design puzzle, you want the search() method in Inventory to ask GuitarSpec to
tell it if two specs are equal, instead of comparing the two GuitarSpec objects directly
within the search() method itself. search() delegates the comparison to GuitarSpec.

Q Q: What’s the point of that?


:

A: A: Delegation makes your code more reusable. It also lets each object worry about its own
functionality, rather than spreading the code that handles a single object’s behavior all
throughout your application
One of the most common examples of delegation in Java is the equals() method. Instead of
a method trying to figure out if two objects are equal, it calls equals() on one of the objects
and passes in the second object. Then it just gets back a true or false response from
the equals() method.
Q Q: And what does delegation have to do with code being more reusable?
:

A: A: Delegation lets each object worry about equality (or some other task) on its own. This
means your objects are more independent of each other, or more loosely coupled. Loosely
coupled objects can be taken from one app and easily reused in another, because they’re
not tightly tied to other objects’ code.

Q Q: And what does loosely coupled mean again?


:

A: A: Loosely coupled is when the objects in your application each have a specific job to do,
and they do only that job. So the functionality of your app is spread out over lots of well-
defined objects, which each do a single task really well.

Q Q: And why is that good?


:

A: A: Loosely coupled applications are usually more flexible, and easy to change. Since each
object is pretty independent of the other objects, you can make a change to one object’s
behavior without having to change all the rest of your objects. So adding new features or
functionality becomes a lot easier.
OOA&D is about writing great software, not doing a bunch of paperwork!

Customers are satisfied when their apps WORK. We can get requirements from the

customer to make sure that we build them what they ask for. Use cases and diagrams are helpful
ways to do that, but it’s all about figuring out what the customer wants the app to do.

We’ll talk all about requirements in Chapter 2.

Customers are satisfied when their apps KEEP WORKING. Nobody is happy when an


application that worked yesterday is crashing today. If we design our apps well, then they’re
going to be robust, and not break every time a customer uses them in unusual ways. Class and
sequence diagrams can help show us design problems, but the point is to write well-designed and
robust code.

You’ve learned a bit about fragile apps already.

Customers are satisfied when their apps can be UPGRADED. There’s nothing worse than a
customer asking for a simple new feature, and being told it’s going to take two weeks and
$25,000 to make it happen. Using OO techniques like encapsulation, composition, and delegation
will make your applications maintainable and extensible.

Want more on delegation, composition, and aggregation? We’ll talk about all of these in detail
in Chapter 5, and then again in Chapter 8.

Programmers are satisfied when their apps can be REUSED. Ever built something for one
customer, and realized you could use something almost exactly the same for another customer? If
you do just a little bit of analysis on your apps, you can make sure they’re easily reused, by
avoiding all sorts of nasty dependencies and associations that you don’t really need. Concepts like
the Open-Closed Principle (OCP) and the Single Responsibility Principle (SRP) are big time in
helping here.

You’ll get to see these principles really strut their stuff in Chapter 8.

Programmers are satisfied when their apps are FLEXIBLE. Sometimes just a little
refactoring can take a good app and turn it into a nice framework that can be used for all sorts of
different things. This is where you can begin to move from being a head-down coder and start
thinking like a real architect (oh yeah, those guys make a lot more money, too). Big-picture
thinking is where it’s at.

Chapter 6 and Chapter 7 are all about looking at the big picture, and really developing a good
architecture for your applications.

This is ALL OOA&D! It’s not about doing silly diagrams... it’s about writing killer applications
that leave your customer happy, and you feeling like you’ve kicked major ass.

BULLET POINTS
 It takes very little for something to go wrong with an application that is fragile.
 You can use OO principles like encapsulation and delegation to build
applications that are flexible.
 Encapsulation is breaking your application into logical parts that have a clear
boundary that allows an object to hide its data and methods from other objects.
 Delegation is giving another object the responsibility of handling a particular
task.
 Always begin a project by figuring out what the customer wants.
 Once you’ve got the basic functionality of an app in place, work on refining the
design so it’s flexible.
 With a functional and flexible design, you can employ design patterns to improve
your design further, and make your app easier to reuse.
 Find the parts of your application that change often, and try and separate them
from the parts of your application that don’t change.
 Building an application that works well but is poorly designed satisfies the
customer but will leave you with pain, suffering, and lots of late nights fixing
problems.
 Object oriented analysis and design (OOA&D) provides a way to produce well-
designed applications that satisfy both the customer and the programmer.

CHAPTER 2: Requirements Gathering


So what exactly is a requirement, anyway?
requirement. A requirement is a singular need detailing what a particular product
or service should be or do. It is most commonly used in a formal sense in
systems engineering or software engineering.

Q Q: So a requirement is just one of the things that a customer wants the application
: you build for them to do?

A A: Actually, a requirement is a lot more than just what the customer wants—although
: that’s a good place to start. Begin by finding out what your customer wants and expects,
and what they think the system you’re building for them should do. But there’s still a lot
more to think about...
Remember, most people expect things to work even if problems occur. So you’ve got to
anticipate what might go wrong, and add requirements to take care of those problems as
well. A good set of requirements goes beyond just what your customers tell you, and
makes sure that the system works, even in unusual or unexpected circumstances.

 A use case is what people call the steps that a system takes to make
something happen. In Todd and Gina’s case, the “something” that
needs to happen is getting Fido outside to do his business, and then
back inside.
use case. A use case is a technique for capturing the potential requirements of
a new system or software change. Each use case provides one or
more scenarios that convey how the system should interact with the end user
or another system to achieve a specific goal.
Q Q: So a use case is just a list of the steps that a system has to do to work correctly?
:

A: A: In most cases, yes. But, remember, one of the key points about a use case is that it is
focused on accomplishing one particular goal. If your system does more than one thing—
like let Fido outside and track how many times he’s been out in an entire day—then you’ll
need more than one use case.
Q Q: If the use case doesn’t help me write my code, then what’s the point? Why
: spend all this time on use cases?

A: A: Use cases do help you write your code—they just aren’t specific about
programming details. For instance, if you didn’t write a use case for Todd and Gina,
you never would have figured out that Fido might get stuck outside, or realize that
the dog door needed to close automatically. Those all came from writing a use case.
Remember, you’ll never write great software if you can’t deliver an app that does
what the customer wants it to do. Use cases are a tool to help you figure that out—
and then you’re ready to write code to actually implement the system your use case
describes.
Q: Why did you make the timer variable final?
A: Because we need to call its  cancel() method in
the  TimerTask anonymous class. If you need to access
variables in your anonymous class from the enclosing class
(that’s  Remote in this case), those variables must be final. And,
really, just because it makes things work.
BULLET POINTS
 Requirements are things your system must do to work correctly.
 Your initial requirements usually come from your customer.
 To make sure you have a good set of requirements, you should develop use cases
for your system.
 Use cases detail exactly what your system should do.
 A use case has a single goal, but can have multiple paths to reach that goal.
 A good use case has a starting and stopping condition, an external initiator,
and clear value to the user.
 A use case is simply a story about how your system works.
 You will have at least one use case for each goal that your system must
accomplish.
 After your use cases are complete, you can refine and add to your requirements.
 A requirements list that makes all your use cases possible is a good set of
requirements.
 Your system must work in the real world, not just when everything goes as you
expect it to.
 When things go wrong, your system must have alternate paths to reach the
system’s goals.
CHAPTER 3: Requirements Change
Q Q: I understand the main path of a use case, but can you explain what an alternate
: path is again?

A: A: An alternate path is one or more steps that a use case has that are optional, or
provide alternate ways to work through the use case. Alternate paths can
be additional steps added to the main path, or provide steps that allow you to get to the
goal in a totally different way than parts of the main path.

Q Q: So when Fido goes outside and gets stuck, that’s part of an alternate path, right?
:

A: A: Right. In the use case, Steps 6.1, 6.2, 6.3, 6.4, and 6.5 are an alternate path. Those
are additional steps that the system may go through, and are needed only when Fido gets
stuck outside. But it’s an alternate path because Fido doesn’t always get stuck outside—
the system could go from Step 6 directly on to Step 7.

Q Q: And we use sub-steps for that, like 6.1 and 6.2?


:

A: A: Exactly. Because an alternate path that has additional steps is just a set of steps that
can occur as part of another step on the use case’s main path. When Fido gets stuck
outside, the main path steps are 6 and 7, so the alternate path steps start at 6.1 and go
through 6.5; they’re an optional part of Step 6.

Q Q: So what do you call it when you have two different paths through part of a use
: case?

A: A: Well, that’s actually just another kind of alternate path. When Fido barks, there’s one
path that involves Todd and Gina hearing Fido and opening the door, and another path
that involves the bark recognizer hearing a bark and opening the door. But the system is
designed for one or the other—either the remote opens the door, or the bark recognizer
does—not both.

Q Q: Can you have more than one alternate path in the same use case?
:

A: A: Absolutely. You can have alternate paths that provide additional steps, and multiple
ways to get from the starting condition to the ending condition. You can even have an
alternate path that ends the use case early... but we don’t need anything that complicated
for Todd and Gina’s dog door.
 A complete path through a use case, from the first step to the last, is called
a scenario.
 Most use cases have several different scenarios, but they always share the
same user goal.
Any time you change your use case, you need to go back and check your
requirements. Remember, the whole point of a good use case is to get good
requirements. If your use case changes, that may mean that your requirements change,
too.
CHAPTER 4: TAKING YOUR SOFTWARE INTO THE REAL WORLD

The key to making sure things work and that the real world doesn’t screw up your application is analysis:
figuring out potential problems, and then solving those problems—before you release your app out into the real
world.

Analysis helps you ensure your system works in a real-world context.

THERE ARE NO DUMB QUESTIONS


Q Q: I came up with a different solution. Does that mean my solution is wrong?
:

A: A: No, as long as your solution kept all the dogs except for Bruce from going in and out
of the dog door. That’s what makes talking about software so tricky: there’s usually
more than one way to solve a problem, and there’s not always just one “right” solution.

Q Q: In my solution, I turned step 3 of the original use case into two steps, instead of


: just replacing the existing step. Where did I go wrong?

A: A: You didn’t go wrong. Just as there is usually more than one solution to a problem,
there is usually more than one way to write that solution in a use case. If you use more
than one step, but have the scenario with other dogs barking handled, then you’ve got a
working use case.

Q Q: So these use cases really aren’t that precise, are they?


:

A: A: Actually, use cases are very precise. If your use case doesn’t detail exactly what
your system is supposed to do, then you could miss an important requirement or two
and end up with unhappy customers.
But, use cases don’t have to be very formal; in other words, your use case may not look
like ours, and ours might not look like anyone else’s. The important thing is that your
use case makes sense to you, and that you can explain it to your co-workers, boss, and
customers.
We need a new use case to store the owner’s dog’s bark.

Our analysis has made us realize we need to make some changes to our use case—and those changes mean that
we need to make some additions to our system, too.
If we’re comparing a bark from our bark recognizer to the owner’s dog’s bark, then we actually need to store
the owner’s dog’s bark somewhere. And that means we need another use case.

THERE ARE NO DUMB QUESTIONS


Q Q: Do we really need a whole new use case for storing the owner’s dog’s bark?
:

A: A: Yes. Each use case should detail one particular user goal. The user goal for our
original use case was to get a dog outside and back in without using the bathroom in
the house, and the user goal of this new use case is to store a dog’s bark. Since those
aren’t the same user goal, you need two different use cases.

Q Q: Is this really the result of good analysis, or just something we should have
: thought about in the last two chapters?

A: A: Probably a bit of both. Sure, we probably should have figured out that we needed to
store the owner’s dog’s bark much earlier, but that’s what analysis is really about:
making sure that you didn’t forget anything that will help your software work in a real
world context.

Q Q: How are we representing the dog’s bark?


:
A: A: That’s a good question, and it’s one you’re going to have to answer next...

Delegation in Sam’s dog door: an in-depth look


Sam is doing something very similar in his Bark and DogDoor classes. Let’s see
exactly what’s going on:
1. The BarkRecognizer gets a Bark to evaluate.

Doug’s hardware hears a dog barking, wraps the sound of the dog’s bark
in a new Bark object, and delivers that Bark instance to
the recognize() method.

2. BarkRecognizer gets the owner’s dog’s bark from DogDoor


The recognize() method calls getAllowedBark() on the dog door it’s attached
to, and retrieves a Bark object representing the owner’s dog’s bark.
3. BarkRecognizer delegates bark comparison to Bark
The recognize() method asks the owner’s dog’s Bark object to see if it is
equal to the Bark instance supplied by Doug’s hardware,
using Bark.equals().

4. Bark decides if it’s equal to the bark from Doug’s hardware


The Bark object representing the owner’s dog’s bark figures out if it is
equal to the Bark object from Doug’s hardware... however that needs to
happen.
NOTE
The details of how this comparison happens are hidden from all the other objects
in the dog door application.

The power of loosely coupled applications

Now suppose that we started storing the sound of a dog barking as a WAV file
in Bark. We’d need to change the equals() method in the Bark class to do a more
advanced comparison of sounds and account for the WAV files. But, since
the recognize() method delegates bark comparison, no code
in BarkRecognizer would have to change.
So with delegation and a loosely coupled application, you can change the
implementation of one object, like Bark, and you won’t have to change all the
other objects in your application. Your objects are shielded from
implementation changes in other objects.

Delegation shields your objects from implementation changes


to other objects in your software.
Pay attention to the nouns in your use case
Maria’s figured out something really important: the nouns in a use case
are usually the classes you need to write and focus on in your system.

Remember, you need classes only for the parts of the system you have to
represent. We don’t need a class for “outside” or “inside” or “the owner”
because our software doesn’t have to represent those things.

THERE ARE NO DUMB QUESTIONS


Q Q: So you’re telling me as long as I write use cases, all my software will work like
: it should?

A: A: Well, use cases are certainly a good start towards writing good software. But
there’s a lot more to it than that. Remember, analysis helps you figure out the classes
from your use case, and in the next chapter, we’ll spend some time talking about good
design principles in writing those classes.

Q Q: I’ve never used use cases before, and I’ve never had any problems. Are you
: saying that I have to write use cases to create good software?

A: A: No, not at all. There are plenty of programmers who are good at their jobs, and
don’t even know what a use case is. But if you want your software to satisfy the
customer more often, and you want your code to work correctly with less rework, then
use cases can really help you nail your requirements down... before you make
embarrassing mistakes in front of your boss or a customer.

Q Q: It seems like this stuff about nouns and analysis is pretty tricky, and I’m not
: any good at English grammar. What can I do?

A: A: You really don’t need to focus too much on grammar. Just write your use cases in
conversational English (or whatever language you speak and write in). Then figure out
what the “things” are in your use case—those are generally the nouns. For each noun,
think about if you need a class to represent it, and you’ve got a good start on a real-
world analysis of your system.

Q Q: But what if I make a mistake like Randy did, and use a noun in my use case
: when I shouldn’t?

A: A: Randy’s mistake—using “bark” as a noun in step 3 of his use case—had nothing to


do with Randy’s grammar. He didn’t think through the use case, and how his system
would work in the real world. Instead of focusing on getting the owner’s dog outside,
he was worrying about one specific bark. He focused on the wrong thing!
When you write your use case, reread it, and make sure that it makes sense to you. You
might even want to let a couple of friends or co-workers read through it, too, and make
sure it will work in the real world, not just in a controlled environment.
A good use case clearly and accurately explains what a system does, in language
that’s easily understood.
With a good use case complete, textual analysis is a quick and easy way to figure
out the classes in your system.
SHARPEN YOUR PENCIL ANSWERS
Why didn’t Maria create a Dog class?
When you picked the nouns out of the use case, one that kept showing up was “the
owner’s dog.” But Maria decided not to create a Dog object. Why not? Here are three
reasons we think Maria made the right choice.

Remember: pay attention to those nouns!


Even if the nouns in your use case don’t get turned into classes in your system,
they’re always important to making your system work like it should.

The point is that the nouns are what you should focus on. If you focus on
the dog in this step, you’ll figure out that you need to make sure the dog
gets in and out of the dog door—whether he has one bark,
or multiple barks.
Pay attention to the nouns in your use case, even when they aren’t classes in
your system.
Think about how the classes you do have can support the behavior your use
case describes.

 The verbs in your use case are (usually) the methods of the objects in
your system.

THERE ARE NO DUMB QUESTIONS


Q Q: So the nouns in the use case turn into classes, and the verbs turn into methods?
:

A: A: That’s almost it. Actually, the nouns are candidates for classes... not every noun will
be a class. For instance, “the owner” is a noun in the use case (check out Steps 2.1 and
3.1, for example), but we don’t need a class for that noun. So even though “the owner” is
a candidate for a class, it doesn’t become a class in the actual system.
In the same way, the verbs are candidates for operations. For example, one verb phrase is
“does his business,” but we just couldn’t bear to write a  pee() or  poop() method. We
hope you’ll agree that we made the right choice! Still, textual analysis is a really good
start to figuring out the classes and methods you’ll need in your system.

Q Q: It looks like the nouns that are outside the system don’t get turned into classes. Is
: that always true?

A: A: Most of the time it is. The only common exception is when you have to interact with
something outside the system—like when there’s some state or behavior that the system
needs to work with on a recurring basis.
In the dog door system, for example, we didn’t need a class for the owner because
the  Remote class took care of all the owner-related activity. If we ever needed to track
owner state, though—like if the owner was asleep or awake—then we might have to create
an  Owner class.
 Exactly! I hate writing a bunch of classes and then finding out I did
something wrong. With use cases and class diagrams, if I make a mistake,
I can just scribble things out and redraw my diagram.

BULLET POINTS
 Analysis helps you ensure that your software works in the real world context, and
not just in a perfect environment.
 Use cases are meant to be understood by you, your managers, your customers,
and other programmers.
 You should write your use cases in whatever format makes them most usable to
you and the other people who are looking at them.
 A good use case precisely lays out what a system does, but does not indicate how
the system accomplishes that task.
 Each use case should focus on only one customer goal. If you have multiple
goals, you will need to write multiple use cases.
 Class diagrams give you an easy way to show your system and its code
constructs at a 10,000-foot view.
 The attributes in a class diagram usually map to the member variables of your
classes.
 The operations in a class diagram usually represent the methods of your classes.
 Class diagrams leave lots of detail out, such as class constructors, some type
information, and the purpose of operations on your classes.
 Textual analysis helps you translate a use case into code-level classes, attributes,
and operations.
 The nouns of a use case are candidates for classes in your system, and the verbs
are candidates for methods on your system’s classes.

WHAT’S MY DEFINITION
UML and use cases have a lot of terms that are similar to, but not quite the same as, the
programming terms you’re already familiar with. Below are several OOA&D-related
terms, and their definitions... but everything is all mixed up. Connect the term to the
definition, and unscramble the mess.

Noun Analysis Lists all the code-level constructs, along with their attributes and
operations.

Multiplicity This is the UML term that usually represents a method in one of your
classes.

Attribute Helps you figure out the candidates for methods on the objects in
your system.

Class Visually shows that one class has a relation to another class, often
Diagram through an attribute.

Operation Equivalent to a member variable in a class.

Association Describes how many of a specific type can be stored in an attribute


of a class.

Verb Analysis You do this to your use case to figure out what classes you need in
your system.

You might also like