CS 441: Principles of Software Design

advertisement
CS 4240: The OO Paradigm
Revisited
Readings: Chap. 1 of Design
Patterns Explained
OO (some review)
Coupling, cohesion

Old problems

Before OO, functional decomposition




Break problem down
Function deals with subproblem
Hierarchical. Levels of abstraction
Problems:




Control and coordination centered in main method
Required changes have big impacts
Logic may be distributed
Data changes affect may modules
Functions:



What we call them:
functions, methods, modules
Functions are a core construct in OO
and non-OO programs
Principals of good functions apply in
either language

But less of a problem in OO – can you
think why?
What makes a function good?

Your answers:
Good qualities in functions:


Lots written about this!
Clean Code: A Handbook of Agile SW
Craftsmanship
Robert C. Martin

Read Chapter 3 in UVa digital library
version
Good Qualities in Functions

Small


How small?
Do One Thing: Strong Cohesion


Why?
One level of abstraction per function


Thus, functions fall into levels of abstraction
Name reflects the one task it does
Interface Qualities of Functions

What about its interface?


Inputs, return value/arguments
Other sources of data or “output”


Side effects
Some rules?
Good Qualities in Functions (2)

Number of arguments: small


Flag arguments



“Bundling” arguments
What are they? What bad thing do they
suggest is happening?
Avoid side effects
Avoid output arguments
Good Qualities in Functions (3)


Don’t Repeat Yourself (DRY)
Command/Query Separation


Do something. Or answer something.
Don’t do both.
Returning Errors

Return value? Output argument?


Burden on caller?
Exceptions: what advantages?
Design Representation

If you’re just programming with
functions (not OO), how could you
represent your system?
Example: Structure Chart
Comments on Struct. Chart





How are data and functions tied together?
Can procedural abstraction be done?
Data abstraction?
How sensitive to change are parts of this
design? Where?
Page 8 of DPE text: can a function cope with
variability in data? (Will this be an issue?)
Back to Shalloway and Trott…
Requirements


See textbook’s discussion on
requirements and why they change.
Bottom line:
Change is inevitable. Deal with it.
Design Principles (again)


Decomposition leads to modularity
Properties of modules:




Internal “goodness”
Inter-module relationships
Cohesion
Coupling

Note: old terms first defined for functionoriented modules
Cohesion of a module


“How closely operations [what’s
encapsulated] in a module are related.”
Think of:



Strength of purpose
A cohesive group of people works well
together towards a goal
Extreme of non-cohesive OO module:
a god class
Coupling between modules


“strength [or goodness] of the connection
between two modules.”
We want quality connections. Why?




Flexibility, independence of modules
“Looser” connections, less brittle system
Reusability
Goal:

Loosely-coupled modules, each highly cohesive
Coupling: What’s “Good”?

How do modules “connect”?

Invoke operations in each other [dynamic]




Small operations, or start/invoke something larger
Pass data to each other [dynamic]
Defined in terms of each other [static]
General:



Simple, as little as possible (data)
Direct connections, very visible
Flexible

E.g. report an event, but not tell the other module how to
handle it
Back to Functional Decomposition

Side effects
Finding bugs is the problem, not fixing
them

Change to data impact many functions


Snowball effect, cascade of changes
OO Improves This Because

Modules become responsible for:

Encapsulating data


Encapsulating operations on data



Controlling access, maintaining intergrity
Functionality is bound to data
Why is this an example of DRY principle?
For a modules in OO, we define:

Responsibilities, data, operations
Classes in Java, C++


“My responsibilities?” What my role is!
Clear how data and operations are defined
when we write a Java class, but what about
responsibilities?


Implied by operations?
Answer:


Note in the code. Maybe in the comments.
Certainly in the design (even if implicit)
Responsibilities matter a lot in understanding the
design.
Step back: Perspectives of
modules


Martin Fowler (UML Distilled) talks about
three levels of perspectives to talk about
modules (or SW development)
Note we’re practicing abstraction in doing
this!


Explain why to me later on!
Note: it’s easier to understand this if you think
about limiting it to objects for now
Levels of perspective in OO

Conceptual



Specification



Domain-level, problem-level -- not yet considering
solutions
What is an object’s responsibilities?
Solution-level, but an abstract view
Interfaces, not internal implementation
Implementation

Code level: full details of how it’s coded
So… What’s an Object?

Depends on what level you’re using, where
you’re at in development





Conceptual: set of responsibilities
Specification: set of methods (an interface) that
meets its responsibilities
Implementation: coding you’ve learned to do
Designers work at Specification level (mostly)
Analysts work at Conceptual level (mostly)
Classes, Objects and Instantiation

Review!


What’s an instance? What’s instantiation?
Do we need classes to do OO
programming?


No. But why are they helpful?
Define common properties. (DRY again.)
Abstract Types

Review: abstract class vs. interface
How are they used? What’s common
about them?

Explain:


Collections of these. References to these.
Review: polymorphism


What are the mechanics of
polymorphism in OO? (Implementation
level perspective)
At a higher level, what’s it for?
More (not from text)

More on coupling, cohesion
Cohesion

How diverse are the things inside an
“entity”


A what? Module, function,… In OO a class.
What’s this mean?


Class should represent a single
abstraction
Or, it should address a single general
responsibility
Problems Created by Bad
Cohesion


Hard to understand the class
If two abstractions grouped into one class,
that implies a one-to-one relationship


Often we specialize a class along a dimension



What if this changes?
This new thing is like the existing one except we
extend it in one area (dimension)
Problems arise when each of the several
abstractions need such specialization
Note meaning of “specialization” here
The “Multiplicity” Problem

Consider an Account class that holds:


What if one customer needs two
accounts?


Customer name, address, tax ID, Account
status, etc.
Two Account objects, but each stores
name and address
What if one account has two owners?

You can’t do this, unless you create a
collection in each Account to hold owner
info
Specializing along Dimensions

Let’s say we need variations on class Account



These are two dimensions, but are they mutually
exclusive?



First, based on account type: Cash Account, Credit
Account
Second, based on customer type: Individual Account,
Institutional Account
We often compose along two dimensions
E.g. Individual Cash Account, Individual Credit Account,
etc.
Specialization often implemented as inheritance:
Do we really want multiple inheritance?
Inheritance Diamonds

Structures like this cause messy problems!
Account
Cash Account
Credit Account
Individual Account
Instiutional Account
Two more classes here
Individual Cash Account
Individual Credit Account
Separating Abstractions


Composition across dimensions
achieved by aggregation (“PART-OF”)
You can see how this improves earlier
problem too
owner
Account
Customer
*
Cash Account
Credit Account
1..*
Individual Customer Instiutional Customer
An OO Design Principle…
Prefer aggregation over inheritance!

Keep in mind:


Often at the conceptual perspective, the
“IS-A” relationship is true
But at the design/implementation level, we
don’t use inheritance
How to Achieve Better
Cohesion


Some of this is just good OO experience
We can learn from database normalization



Eliminate redundancy
Attributes should have a single value and should not
have structure (repeating groups of things)
Attributes always describe an instance of its
containing class


That’s what attributes are all about! State values that
define a particular instance
Note: there are always tradeoffs! Sometimes
we combine abstractions into one class for
efficiency.
Coupling and Class Design

How dependent an object/class is on
the world around it




How many connections
Nature of the connections
Will changes cause a “ripple effect”?
Our goals:


Reduce coupling if possible
Improve nature of necessary coupling
Forms of Coupling (from
Richter)

Identity Coupling



An object contains a reference or pointer to
another object
Eliminate associations or make them oneway
Representational Coupling

An object refers to another through that
object’s interface

How it does this affects the degree of coupling
Forms of Coupling (cont’d)

Subclass Coupling

Object refers to another object using a
subclass reference for that object


A client should refer to the most general
type possible


Not the more general superclass or interface
Why? Subclasses may be added later, possibly
by someone else
Try to write code that minimizes
dependencies on subclass details

Instead rely on the common interface defined in
the superclass or interface
Reminder: Use Java Interfaces
to Avoid Subclass Coupling


Java’s interfaces; C++ classes with pure
virtual functions and no data members
Interfaces define a role not a classabstraction

Many classes can pay that role
THE POINT:
 We can define reference to a thing in terms of
the role (interface) instead of the class type
Forms of Coupling (cont’d)

Inheritance coupling

A subclass is coupled to its superclass at
compile-time



In general, prefer late to early
Seems like the only way to do things, but
ask:
While the program executes, does an
object need to change its subclass?
Aggregation is supported at run-time

We’ll see the State design pattern later
Shy Code and the Law of
Demeter


See handout on the Law of Demeter
Summary: An object’s method should only
call other methods that belong to:






Itself (the current object)
Any parameter object that was passed to it
An object it created
Any of its components objects
What does this rule out? (Ponder that.)
Delegation
END
Download