《Head First Object-Oriented Analysis and Design》读书笔记

 

Head First Object-Oriented Analysis and Design

 

Great software in 3 easy steps:

 

1. Make sure your software does what the customerwants it to do.

2. Apply basic OO principles to add flexibility.

3. Strive for a maintainable, reusable design.

 

 

Don’t create problems to solve problems.

 

Use a textual description of the problem you’re trying to solve to make sure that your design lines up with theintended functionality of your application.

 

1. Objects should do what their names indicate.

2. Each object should represent a single concept.

3. Unused properties are a dead giveaway.

 

Encapsulation allows you to hide the inner workings ofyour application’s parts, but yet make it clear what each part does.

Encapsulation is breaking your application intological parts that have a clear boundary that allows an object to hide its dataand methods from other objects.

 

从一个对象的一部分中抽象出另一对象,代表一类属性,从而减少类的字段数量。

 

Anytime you see duplicate code, look for a place toencapsulate!

 

Delegation is when an object needs to perform acertain task, and instead of doing that task directly, it asks another objectto handle the task (or sometimes just a part of the task).

Delegation makes your code more reusable. It also letseach object worry about its own functionality, rather than spreading the codethat handles a single object’s behavior all throughout yourapplication.

This means your objects are more independent of eachother, or more loosely coupled.

 

 

A requirement is a singular need detailing what a particularproduct or service should be or do. It is most commonly used in a formal sensein systems engineering or software engineering.

 

Creating a requirements list. The best way to get goodrequirements is to understand what a system is supposed  to do.

 

A use case is a technique for capturing the potentialrequirements of a new system or software change. Each use case provides one ormore scenarios that convey how the system should interact with the end user oranother system to achieve a specific goal. A use case describes what yoursystem does to accomplish a particular customer goal. A use case has a singlegoal, but can have multiple paths to reach that goal.

 

A use case is simply a story about how your systemworks.

 

There are three basic parts to a good use case:

Every use case must have a clear value to the system.

Every use case must have a definited starting andstopping point. Something must begin the process, and then there must be acondition that indicates that the process is complete.

Every use case is started off by an externalinitiator, outside of the system.

 

Use cases are meant to help you understand what asystem should do—and often to explain the system to others (like thecustomer or your boss). If your use case focuses on specific code-leveldetails, it’s not going to be useful to anyone but aprogrammer. As a general rule, your use cases should use simple, everydaylanguage. If you’re using lots of programming terms, ortechnical jargon, your use case is probably getting too detailed to be thatuseful.

 

Is a use case the same as a use case diagram?

A:  No, usecases are usually a list of steps. Use case diagrams are a way to show usecases visually, but we’ve already been working on our owndiagram of how the system works.

 

Your system must work in the real world, not just wheneverything goes as you expect it to.

 

Requirements always change. If you’ve got good use cases, though, you can usually change your softwarequickly to adjust to those new requirements.

 

A complete path through a use case, from the firststep to the last, is called a scenario. Most use cases have several differentscenarios, but they always share the same user goal.

 

If a step is optional in how a system works, or a stepprovides an alternate path through a system, use numbered sub-steps, like 3.1,4.1, and 5.1, or 2.1.1, 2.2.1, and 2.3.1.

 

Your software has a context. Analysis helps you ensureyour system works in a real-world context.

 

Figuring out potential problems, and then solvingthose problems—before you release your app out into the real world.

 

Delegation shields your objects from implementationchanges to other objects in your software.

 

Looking at the nouns (and verbs) in your use case tofigure out classes and methods is called textual analysis. The nouns of a usecase are candidates for classes in your system, and the verbs are candidatesfor methods on your system’s classes.

 

A good use case clearly and accurately explains what asystem does, in language that’s easily understood.

 

With a good use case complete, textual analysis is aquick and easy way to figure out the classes in your system.

 

A solid line from one class to another is called anassociation. It means that one class is associated with another class, byreference, extension, inheritance, etc.

 

The line with a diamond means aggregation. Aggregationis a special form of association, and means that one thing is made up (in part)of another thing.

 

Abstract classes are placeholders for actual implementationclasses. The abstract class defines behavior, and the subclasses implement thatbehavior. Whenever you find common behavior in two or more places, look toabstract that behavior into a class, and then reuse that behavior in the commonclasses.

 

A line with an arrow that isn’t colored in means generalization. You use a generalization to showthat a class extends and inherits behavior from a more generalized class.

 

Coding to an interface, rather than to an implementation,makes your software easier to extend. By coding to an interface, your code willwork with all of the interface’s subclasses—even ones that haven’t been created yet.

 

There’s more to encapsulation than justavoiding lots of copy-and-paste. Encapsulation also helps you protect yourclasses from unnecessary changes.

 

Encapsulate what varies.

 

Each class has only one reason to change.

Each individual class does only one thing

 

封装有两个方向,一是向上抽象的方向,而是向下只封装变化点。变化的类里不要牵扯到不变的内容。

 

When you have a set of properties that vary acrossyour objects, use a collection, like a Map, to store those propertiesdynamically.

 

Cohesion measures the degree of connectivity among theelements of a single module, class, or object. The higher the cohesion of yoursoftware is, the more well-defined and related the responsibilities of eachindividual class in your application. Each class has a very specific set ofclosely related actions it performs.

 

You can solve a big problem by breaking it into lotsof functional pieces, and then working on each of those pieces individually.

 

A feature is just a high-level description ofsomething a system needs to do.

 

Get features from the customer, and then figure outthe requirements you need to implement those features.

 

Features are “big things” thatlots of requirements combine to satisfy.

 

So even though you could start writing use cases, thatprobably won’t help you figure out exactly what you’re trying to build, from the big-picture point of view. When you’re working on a system, it’s a good idea todefer details as long as you can... you won’t get caughtup in the little things when you should be working on the big things.

 

Always defer details as long as you can.

 

Use a feature or requirement list to capture the BIGTHINGS that your system needs to do.

 

Draw a use case diagram to show what your system ISwithout getting into unnecessary detail.

 

Domain analysis lets you check your designs, and stillspeak the customer’s language, describing a problemusing terms the customer will understand.

 

The process of identifying, collecting, organizing,and representing the relevant information of a domain, based upon the study ofexisting systems and their development histories, knowledge captured from domainexperts, underlying theory, and emerging technology within a domain.

 

Domain analysis helps you avoid building parts of asystem that  aren’t your job to build.

 

1 We listened to the customer.

2 We made sure we understood the system.

3 We drew up blueprints for the system we’re building.

4 We broke the big problem up into smaller pieces offunctionality.

 

Architecture is the organizational structure of asystem, including its decomposition into parts, their connectivity, interactionmechanisms, and the guiding principles and decisions that you use in the designof a system. Architecture is your design structure, and highlights the mostimportant parts of your app, and the relationships between those parts.

 

The things in your application that are really importantare architecturally significant, and you should focus on them FIRST.

 

The reason that these features are architecturallysignificant is that they all introduce RISK to your project. It doesn’t matter which one you start with—as long asyou are working towards reducing the RISKS in succeeding.

 

Sometimes the best way to write great code is to holdoff on writing code as long as you can.

 

Principle #1:

The Open-Closed Principle (OCP)

Classes should be open for extension, and closed formodification.

The OCP is all about allowing change, but doing itwithout requiring you to modify existing code.

 

The OCP is about flexibility, and goes beyond justinheritance.

 

可通过继承和组合来实现OCP

 

Principle #2:

The Don’t Repeat Yourself Principle (DRY)

Avoid duplicate code by abstracting out things thatare common and placing those things in a single location.

 

DRY is really about ONE requirement in ONE place

 

DRY is about having each piece of information and behaviorin your system in a single, sensible place.

 

Principle #3:

The Single Responsibility Principle (SRP)

Every object in your system should have a singleresponsibility, and all the object’s services should be focused on carryingout that single responsibility.

 

Cohesion is actually just another name for the SRP.

 

Contestant #4:

The Liskov Substitution Principle (LSP)

Subtypes must be substitutable for their base types.

 

The LSP is all about well-designed inheritance. Whenyou inherit from a base class, you must be able to substitute your subclass forthat base class without things going

terribly wrong. Otherwise, you’ve used inheritance incorrectly!

 

 

Delegate functionality to another class.

If you need to use functionality in another class, butyou don’t want to change that functionality, consider usingdelegation instead of inheritance.

 

Use composition to assemble behaviors from otherclasses

Composition allows you to use behavior from a familyof other classes, and to change that behavior at runtime.

 

In composition, the object composed of other behaviorsowns those behaviors. When the object is destroyed, so are all of itsbehaviors.

The behaviors in a composition do not exist outside ofthe composition itself.

 

Composition is really about ownership.

 

Aggregation is when one class is used as part ofanother class, but still exists outside of that other class.

 

If you favor delegation, composition, and aggregationover inheritance, your software will usually be more flexible, and easier tomaintain, extend, and reuse.

 

You write great software iteratively. Work on the big picture,and then iterate over pieces of the app until it’s complete.

 

You can choose to focus on specific features of theapplication. This approach is all about taking one piece of functionality thatthe customer wants, and working on that functionality until it’s complete.

 

Feature driven development...is when you pick aspecific feature in your app, and plan, analyze, and develop that feature tocompletion.

 

You can also choose to focus on specific flows throughthe application. This approach takes a complete path through the application,with a clear start and end, and implements that path in your code.

 

Use case driven development is when you pick ascenario through a use case, and write code to support that complete scenario throughthe use case.

 

Feature driven development is more granular. Workswell when you have a lot of different features that don’t interconnect a whole lot.

Allows you to show the customer working code faster.

Is very functionality-driven.

You’re not going to forget about anyfeatures using feature driven development.

Works particularly well on systems with lots ofdisconnected pieces of functionality.

 

 

 

Use case driven development is more “big picture”.

Works well when your app has lots of processes andscenarios rather than individual pieces of functionality.

Allows you to show the customer bigger pieces offunctionality at each stage of development.

Is very user-centric.

You’ll code for all the different ways auser can use your system with use case driven development.

Works particularly well on transactional systems,where the system is largely defined by lengthy, complicated processes.

 

1 Each test case should have an ID and a name.

2 Each test case should have one specific thing thatit tests.

3 Each test case should have an input you supply.

4 Each test case should have an output that youexpect.

5 Most test cases have a starting state.

 

基于契约编程

When you program by contract, you and your software’s users are agreeing that your software will behave in a certainway.

 

Methods usually return null or unchecked exceptionswhen errors occur in programming by contract environments.

 

防御式编程

But what happens if you don’t think your code will be used correctly? Or if you think thatcertain actions are such a bad idea that you don’t wantto let users deal with them in their own way? In these cases, you may want toconsider defensive programming.

 

Methods usually return “empty” objects or throw checked exceptions in defensive programming environments.

 

When you are programming by contract, you’re working with client code to agree on how you’ll handle problem situations.

When you’re programming defensively, you’re making sure the client gets a “safe” response, no matter what the client wants to have happen.

 

 

So what does that process look like?

 

Feature List

Figure out what your app is supposed to do at a highlevel

 

Use Case Diagrams

Nail down the big processes that your app performs,and any external forces that are involved.

 

Break Up the Problem

Break your application up into modules offunctionality, and then decide on an order in which to tackle each of yourmodules.

 

Requirements

Figure out the individual requirements for each module,and make sure those fit in with the big picture.

 

Domain Analysis

Figure out how your use cases map to objects in your app,and make sure your customer is on the same page as you are.

 

Preliminary Design

Fill in details about your objects, definerelationships between the objects, and apply principles and patterns.

 

Implementation

Write code, test it, and make sure it works. Do thisfor each behavior, each feature, each use case, each problem, until you’re done.

 

Delivery

You’re done! Release your software,submit your invoices, and get paid.

 

 

 

Features and use cases work together, but they are notthe same thing.

 

 

OOA&D is about having lots of options. There is neverone right way to solve a problem, so the more options you have, the betterchance you’ll find a good solution to every problem.

 

Refactoring changes the internal structure of yourcode WITHOUT affecting your code’s behavior.

 

 

你可能感兴趣的:(《Head First Object-Oriented Analysis and Design》读书笔记)