cs 4240: the oo paradigm revisited readings: chap. 1 of design patterns explained oo (some review)...

44
CS 4240: The OO Paradigm Revisited Readings: Chap. 1 of Design Patterns Explained OO (some review) Coupling, cohesion

Upload: norma-lindsey

Post on 23-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

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

CraftsmanshipRobert 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 “Bundling” arguments

Flag 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 function-oriented 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 Controlling access, maintaining intergrity

Encapsulating operations on data 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

Domain-level, problem-level -- not yet considering solutions

What is an object’s responsibilities? Specification

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 What if this changes?

Often we specialize a class along a dimension 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:

Customer name, address, tax ID, Account status, etc.

What if one customer needs two accounts? 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

First, based on account type: Cash Account, Credit Account

Second, based on customer type: Individual Account, Institutional Account

These are two dimensions, but are they mutually exclusive?

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

Account

Cash Account Credit Account Individual Account Instiutional Account

Individual Cash Account Individual Credit Account

Two more classes here

Structures like this cause messy problems!

Separating Abstractions

Account

Cash Account Credit Account Individual Customer Instiutional Customer

Customer

*

owner

1..*

Composition across dimensions achieved by aggregation (“PART-OF”)

You can see how this improves earlier problem too

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 one-way

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

Not the more general superclass or interface A client should refer to the most general

type possible 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 class-

abstraction 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