This document summarizes a presentation given by Blair Schneider McKay on October 22, 2003. The presentation covered design patterns including Adapter, Bridge, Factory Method, and Observer. It also included a section on "How to Keep an Information-Technology Job". The agenda outlined the topics to be covered in the 50 minute presentation on design patterns and the 20 minute section on keeping an IT job.
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
UPE Presentation Design Patterns
1. UPE Presentation, 10/22/2003
Presented By:
Blair Schneider McKay
Consultant, Arrow Strategies, LLC.
Current Project:
AT&T College and University Services
Ann Arbor, MI
Email: blairschneidermckay@compuserve.com
“Design Patterns”
~50 minutes
“How to Keep an Information-Technology Job”
~20 minutes
2. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
3. Software Development Evolves
Some “Good” Practices:
Encapsulation
Separating Interface from Implementation
Abstraction
Some “Bad” Practices:
Global Data
Magic Numbers
Spaghetti Logic
Tight Coupling
6. Layered Architectures
OSI 7-Layer Networking Model:
Layer 1: PHYSICAL
Layer 2: DATA-LINK
Layer 3: NETWORK
Layer 4: TRANSPORT
Layer 5: SESSION
Layer 6: PRESENTATION
Layer 7: APPLICATION telnet, ftp, pop3, smtp
conversions, encrypt/decrypt, parts of odbc / html
cookies, “shopping basket” techniques, etc.
TCP, data reliability (re-transmission, etc.)
IP
ppp, slip, hdlc, token-ring, MAC addressing
NIC cards, RS-232, electrical characteristics
7. Rant
Alert!
Rant
Alert!
Rant
Alert!
Layered Architectures –N-Tier Systems
PRESENTATION
APPLICATION
BUSINESS LOGIC
DATA
In the 1990s, many client-server shops adopted “all-in-one” development
platforms: PowerBuilder, Visual Basic, ASP, Centura/Gupta, “4th
generation” db-tools and stored-procedure languages, and so forth.
Such tools tend to encourage code that spans many (or all!) layers. Systems
built this way are massively coupled and hard to maintain.
I believe this has damaged the overall reputation of software development.
Rant
Alert!
User interfaces. “Look and feel.”
Code re-used across applications and domains.
Code that addresses a one-time need.
Pass-through and acceleration/caching only.
(According to Blair…)
8. Design Patterns
Simple, elegant solutions to problems that occur in a
wide variety of applications and architectures.
Canonical Reference:
“Design Patterns: Elements of Reusable Object-Oriented Software”
by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
(commonly referred to as “The Gang of Four” or “GoF”)
Addison-Wesley, 1995. ISBN 0-201-63361-2
Language-independent (for the most part).
Based on abstraction and the interrelationship between
components. Generally not concerned with the actual
“job” of those components.
9. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
10. Adapter Pattern – Motivating Example
Imagine that you want to exploit the functionality of existing code
– such as a third-party or open-source library – but you can’t (or
would rather not) modify that code’s interface.
Library
Class
Caller
Caller Adapter
Library
Class
Caller Adapter
Library
Class
Some useful adapters:
ODBC, JDBC, Apache Portable Runtime (APR), The
ACE Toolkit, POSIX, …
11. Adaptee
Adapter
Client Target
Request()
Request() ProprietaryRequest()
Adapter Pattern
(Also called “Wrapper”)
Used to connect a caller to an existing class, often legacy or library
code, when the caller requires a different interface.
Object Adapter (Uses Composition):
(Diagram based on p. 141 in “Design Patterns”, by Gamma et al. Addison Wesley, 1995.)
13. client.cpp
#include “Adapter.h“
Adapter a;
// Calling-interface that I like:
Rectangle box( Point(0, 100), Point(15, 55) );
a.drawCircle( box );
Adapter Pattern
Simple “Pass-Through” Implementation
ShapeMaster.h
class ShapeMaster
{
// Proprietary Interface
public:
void RenderCircle( int h_pos, int v_pos, int radius );
void RenderTriangle( /* ... */ );
void RenderSquare( /* ... */ );
// ...
}
14. Adapter Pattern
Simple “Pass-Through” Implementation
Adapter.h
class Rectangle;
class Point;
class GGLib::ShapeMaster;
class Adapter
{
public:
// ctors and such
void drawCircle( const Rectangle& box );
private:
ShapeMaster* impl_;
}
// ...
Adapter.cpp
#include “Rectancle.h”
#include “GreatGraphicsLib/ShapeMaster.h”
void Adapter::drawCircle( const Rectangle& box )
{
int h_pos = ( box.point1.horizontal
+ box.point2.horizontal ) / 2 ;
int v_pos = ( box.point1.vertical
+ box.point2.vertical ) / 2 ;
int radius = min(abs(box.point2.vertical – box.point1.vertical),
abs(box.point2.horizontal – box.point1.horizontal)) / 2;
impl_->RenderCircle( h_pos, v_pos, radius );
}
15. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
16. Bridge Pattern – (aka “Handle/Body”)
This is similar to adapter, but you build it into the class structure
itself, rather than use it to wrap existing code.
Implementation
Client Abstraction
Request() RequestImpl()
The bridge is a natural extension of “Separate Interface from
Implementation.” But here, classes relationships themselves
provide the separation, rather than in-class language features.
18. CalculatorImpl.h
#include “FrequentlyChangingClass1.h”
#include “FrequentlyChangingClass2.h”
#include “FrequentlyChangingClass3.h”
#include “CostlyToCompile1.h”
#include “CostlyToCompile2.h”
#include “Number.h”
class CalculatorImpl
{
public:
CalculatorImpl();
virtual ~CalculatorImpl();
Number square_root( const Number& input );
Number natural_log( const Number& input );
// ...
private:
CostlyToCompile1 cc1_;
CostlyToCompile2 cc2_;
// etc.
};
Bridge Pattern – The C++ “pImpl” Idiom
Implemented
19. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
20. class Widget {
void f(int x) // “__f_int_(int x)”
{
std::cout << “The integer is “ << x << “n”;
}
void f(double d) // “__f_double_(double x)”
{
std::cout << “The double is “ << d << “n”;
}
};
Brief Review of Polymorphism - 1
First off, it is not function overloading:
These are two completely different functions. The
comment text (green) shows how a compiler might
“mangle” their names internally to distinguish them.
21. Brief Review of Polymorphism - 2
Polymorphism is about handling different objects as if they were
all the same. (Access through a common interface.)
Consider example of an “Aquarium” screen-saver:
Main program-loop iterates over a collection of “Sprites”, telling
each sprite when to move. Even though the collection holds
different types of objects, they can all be handled as if they were
the same type.
Sprite
Shark
Guppy Kelp Crab
22. Brief Review of Polymorphism - 3A
Here’s how not to design such a program . . .
Sprite.h
enum SpriteType
{
GUPPY, SHARK, CRAB, KELP
};
class Sprite
{
public:
virtual SpriteType type() const = 0;
// ...
};
Guppy.h
#include "Sprite.h"
class Guppy : public Sprite
{
public:
virtual SpriteType type() const { return GUPPY; }
void swim();
// ...
};
23. SpriteTester1.cpp
void test_sprites1(SpriteList& list)
{
Sprite* s = list.first();
do {
// THIS IS BAD CODE. DON'T DO THIS!
switch(s->type())
{
case GUPPY: {
dynamic_cast<Guppy*>(s)->swim();
continue;
}
case CRAB: {
dynamic_cast<Crab*>(s)->skuttle();
continue;
}
case KELP: {
dynamic_cast<Kelp*>(s)->wave();
continue;
}
// other cases, like Shark, etc. ...
default: {
throw std::exception("Unhandled Sprite!");
}
} // switch
} while ( (s = list.next()) != 0 );
}
Brief Review of Polymorphism - 3B
How not to design such a program, continued . . .
25. Brief Review of Polymorphism - 4B
SpriteTester2.cpp
void test_sprites2(SpriteList& list)
{
Sprite* s = list.first();
do {
// Much better implementation ....
s->move();
} while ( (s = list.next()) != 0 );
}
Using polymorphism to avoid runtime type-checking:
26. Module1.cpp
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h"
// ...
// Add randomly-selected sprite to SpriteList.
int pctile = rand() % 100; // Random: 0 to 99
if ((pctile -= 80) < 0) // 80% chance
sprites.push_back(new Guppy);
else if ((pctile -= 10) < 0) // 10% chance
sprites.push_back(new Shark);
else
sprites.push_back(new Crab); // remaining 10%
Fine, but what about creating objects?
Module2.cpp
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h"
// ...
// Accept user choice.
char key = get_key_press();
if (key == 'g')
sprites.push_back(new Guppy);
else if (key == 's')
sprites.push_back(new Shark);
// ...
main.cpp
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h"
// ...
// Initialize SpriteList.
srand(time(0));
for (size_t i = 0; i < 10; ++i) {
int pctile = rand() % 100; // random:0 to 99
if ((pctile -= 80) < 0) // 80% chance
sprites.push_back(new Guppy);
else if ((pctile -= 5) < 0) // 5% chance
sprites.push_back(new Shark);
else if ((pctile -= 10) < 0) // 10% chance
sprites.push_back(new Kelp);
else
sprites.push_back(new Crab); // remaining %
}
27. Wouldn’t It Be Nice
To Have a “Virtual Constructor”?
We do!
It’s called the “Factory Method”.
28. Factory Method – Simplest Form
SpriteFactory.cpp
#include “SpriteFactory.h"
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h“
Sprite* getNewSprite()
{
int pctile = rand() % 100; // random:0 to 99
if ((pctile -= 80) < 0) // 80% chance
return new Guppy;
else if ((pctile -= 10) < 0) // 10% chance
return new Shark;
else if ((pctile -= 5) < 0) // 5% chance
return new Kelp;
else
return new Crab; // remaining %
}
SpriteFactory.h
class Sprite; // forward declaration
Sprite* getNewSprite();
main.cpp
#include “SpriteFactory.h”
class Sprite; // optional forward declaration
SpriteList sprites;
// ...
// initialize SpriteList
for (size_t i=0; i<10; ++i) {
sprites.push_back( getNewSprite() );
}
// do something to SpriteList
test_sprites(sprites);
29. Parameterized Factory Method
SpriteFactory.cpp
#include "SpriteFactory.h"
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h“
#include "Quagga.h"
#include <cassert>
Sprite* getNewSprite(SpriteType type)
{
switch (type) {
case SHARK: return new Shark;
case KELP: return new Kelp;
case CRAB: return new Crab;
case GUPPY: return new Guppy;
case QUAGGA: return new Quagga;
default: {
assert(false && “Unhandled fish-type”);
return new Guppy;
}
}
Sprite* getNewSprite()
{
// ...
SpriteFactory.h
#include “Sprite.h”
Sprite* getNewSprite(SpriteType type);
Sprite* getNewSprite();
Module2.cpp
#include “SpriteFactory.h"
// ...
// Accept user choice.
char key = get_key_press();
SpriteType type = convertKeyPress(key);
sprites.push_back( getNewSprite(type) );
// ...
30. Using Full Objects as Factory Parameters
Pass the factory a pointer or reference to a
context object:
Product* create( Context* runState );
The factory then interrogates the context object for
information about what sort of product is needed.
The context object could be the caller itself:
Product* createFromContext( this );
31. Stateful Factories
The Factory Method can be a member of a class, and can
“remember” what it’s done before:
SpriteFactory.h
#include ”Sprite.h”
class SpriteFactory {
public:
SpriteFactory();
virtual ~SpriteFactory();
Sprite* getNewSprite();
Sprite* getNewSprite( SpriteType type );
private:
Sprite* getNewSpriteImpl();
SpriteType last_type_created_;
// ...
};
SpriteFactory.cpp
#include “SpriteFactory.h"
#include "Shark.h"
#include "Guppy.h"
#include "Kelp.h"
#include "Crab.h“
SpriteFactory::SpriteFactory()
: last_type_created_(GUPPY)
{
}
Sprite* getNewSprite()
{
Sprite* ret = getNewSpriteImpl();
while ( ret->type() == last_type_created_ ) {
ret = getNewSpriteImpl();
}
last_one_created_ = ret->type();
return ret;
}
// ...
32. Related Patterns – Prototype
class Guppy : public Sprite
{
public:
Sprite* clone() const; // return copy of myself
// ...
}
Even the factory doesn’t need to know exactly how to
build each product sub-class.
The sub-class itself can take on that responsibility.
SpriteFactory::SpriteList my_prototypes_;
Sprite* SpriteFactory::getSprite( SpriteType requested )
{
for (/* ... each prototype in my list . . .*/) {
if (prototype->type() == requested)
return prototype->clone();
}
// return default type or throw exception.
}
33. Related Patterns – Abstract Factory
• In the Abstract Factory, the factory itself is polymorphic.
• Clients who want new products call on concrete sub-class
factories through an abstract interface.
• This lets you organize your system around families of related
products.
FishFactory
SaltwaterFishFactory
FreshwaterFishFactory
Client
34. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
35. Observer Pattern
Here is a simplified Observer pattern:
Observer Subject
attach()
detach()
notify()
update()
ConcreteObserver
update()
(Diagram based on p. 294 in “Design Patterns”, by Gamma et al. Addison Wesley, 1995.)
The goal of this pattern is for each (concrete) observer object to
receive updates on state changes that occur within the subject
object – without the subject object knowing any details about each
observer. This is the ultimate in “need-to-know” programming.
36. Observer Pattern – Event Sequence
Observer Subject
attach()
detach()
notify()
update()
ConcreteObserver
update()
Setup:
1. Observer calls attach() on Subject, passing “this” pointer.
2. Client of Subject (or Subject itself) calls notify() at appropriate time.
3. In notify(), Subject iterates through list of observers and calls
update() on each one, possibly passing state-data.
Use:
Tear-down:
4. Observer calls detach().
38. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
39. IT Job-Market Woes
general economic worries
less corporate $ for research and development
tight state and federal budgets
exploitation of general economic worries
people at all levels are expected to “make
sacrifices”
employers are looking for bargains
competition from overseas outsourcing
insecurity over the pace of technological change
manager bias vs. employee training and education
40. How To Keep Your Job
#1 Recognize that you may not be able to.
Decisions affecting you are often made far up the
organizational hierarchy, by people who know little to
nothing about you.
Long-term job-security is becoming increasingly rare.
Even the best, hardest-working, and most conscientious
employees aren’t immune.
41. How To Keep Your Job
#2 Make yourself indispensable.
Not by being a jerk! E.g., not by “hiding code” or
otherwise hoarding vital information, by making other
people look bad, by stifling innovation, etc.
Become a Subject Matter Expert (SME), in one or more
subjects. Share what you know. Become a “guru”.
Know a little bit about many things.
Take initiative.
42. #3 “Do what the boss says first.”
#3 “Do what the boss says first.”
How To Keep Your Job
#3R (Blair’s Amendment)
Attend to the boss’s concerns first.
You should take your supervisor’s concerns seriously
and give them a high priority.
However, you were hired to use your brain.
Sometimes, raising objections (politely) is good for
both you and the company.
Sometimes, it’s bad for both you and the company, but
it’s still the right thing to do.
43. #4 Be accountable.
How To Keep Your Job
Be able to account for how you spend your time.
If they aren’t provided for you, ask for clearly defined
goals, and major milestones against which your
performance will be measured.
Don’t dread performance reviews; relish them. These
are your best opportunity for “selling yourself” all over
again – and for bringing up your own concerns.
If you do make a mistake, own up to it. Be honest about
what went wrong, how you’re going to fix it, and how you’ll
make sure it doesn’t happen again.
44. #5 Cultivate good communication skills.
How To Keep Your Job
Use the correct technical terms (even when other
people laugh at you.)
Spell-check.
Proof-read. (Including the “To:” and “Cc:” fields!)
If you have problems with grammar, pick up a good short
book on the subject, such as “The Elements of Style”,
by Strunk and White. (Macmillan, 1999. ISBN 020530902X.)
Be professional and polite, in your writing and in your
conversation.
45. #6 Be above reproach.
How To Keep Your Job
Be extremely cautious about humor. Stay far away
from anything that even hints of sexism, racism,
ageism, or any other sort of chauvinism.
Above all, treat others with courtesy and respect.
(Even when they least deserve it!)
Watch out for the big three:
- Sex
- Politics
- Religion
46. #7 Have a life outside of work.
How To Keep Your Job
Well-rounded people tend to be successful and resilient.
A few examples:
- Family
- Religion / Community Involvement
- Political Action
- Hobbies
- Sports / Exercise
- Professional Organizations
- Non-Professional Organizations
- Personal Studies / Personal Development
If you define yourself by your job, losing that job will
be devastating.
47. #8 Live within your means.
How To Keep Your Job
If losing a job will cause a financial catastrophe, you
are in a terrible negotiating position.
Money in the bank means you can be choosy about
your next job.
Debt leads to insecurity.
Insecurity undermines everything else you want to
portray and to accomplish.
48. #9 Get Certified.
How To Keep Your Job
Vendor certifications are sometimes a bad joke, but
there’s money to be had….
At least, it shows you are current. A computer science
education from 10 years ago would probably have
lacked C++, HTML, XML, etc.
If no official certification exists, you may want to go for
outside training – community college, professional
seminar, etc. – and note the specifics on your resume.
49. #10 Stay Upbeat.
How To Keep Your Job
Your relationship with management really will suffer if
you are constantly negative.
When you are targeted by office politics, etc:
Don’t get mad.
Don’t get even.
Just get on with it.
(“Foil your enemies” by simply going on to greater
heights of personal and/or professional success.
Nothing will annoy them more!)
50. How to Keep Your Job
Summary:
#1 Recognize that you may not be able to.
#2 Make yourself indispensable.
#3 Attend to the boss’s concerns first.
#4 Be accountable.
#5 Cultivate good communication skills.
#6 Be above reproach.
#7 Have a life outside of work.
#8 Live within your means.
#9 Get Certified
#10 Stay Upbeat
51. And if you do lose your job….
Go easy on yourself.
Go easy on the person who is firing you.
Leave the way you entered: a class act.
Ask for help.
Don’t panic.
52. Blair’s Prognostications:
Don’t get tied down to one particular technology, vendor,
problem-domain, development style, etc.
So, …
Keep learning!
Help each other.
“The buzz on the street”:
Smaller, cheaper, faster.
Heterogeneous systems.
Embedded systems.
Systems integration.
53. Agenda
1. “Design Patterns”
• Adapter
• Bridge
• Factory Method
• Observer
2. “How to Keep an Information-Technology Job”
3. Q & A
54. References
For more info, please feel free to contact me:
BlairSchneiderMckay@compuserve.com
“Effective C++ and More Effective C++” (CD-ROM), by Scott Meyers.
Addison Wesley, 1998. ISBN 0201310155
“Design Patterns: Elements of Reusable Object-Oriented Software” by
Erich Gamma, John Vlissides, Ralph Johnson, Richard Helm, John M.
Vlissides. Addison Wesley, 1994. ISBN 0201633612
“Exceptional C++”, by Herb Sutter. Addison Wesley, 1999.
ISBN 0201615622
“More Exceptional C++”, by Herb Sutter. Addison Wesley, 2001.
ISBN 020170434X
“C++ Gotchas: Avoiding Common Problems in Coding and Design”,
by Stephen Dewhurst. Addison Wesley, 2002. ISBN 0321125185