Software Design Principles and Guidelines: Douglas C. Schmidt
Software Design Principles and Guidelines: Douglas C. Schmidt
(SECURITY, EVENT NOTIFICATION, TRANSACTIONS, PERSISTENCE, LOAD BALANCING, FAULT TOLERANCE, A/V STREAMING, DYNAMIC RESOURCE MANAGEMENT, SCHEDULING, NAMING, TRADING, LOGGING, ETC...) HOME
MIDDLEWARE SERVICES
CLIENT
operation()
COMPONENT EXECUTOR
CALL BACKS
Development Methodologies
OBJECT ADAPTER
STUBS
CONTAINER
MIDDLEWARE INTERFACE
SKELETONS
MESSAGE-PASSING MIDDLEWARE
OS KERNEL
NETWORK PROTOCOLS NETWORK INTERFACE
OS KERNEL
NETWORK PROTOCOLS
NETWORK
NETWORK INTERFACE
Design Principles
Design Principles
Decompose system into components i.e., identify the software architecture Determine relationships between components e.g., identify component dependencies Determine intercomponent communication mechanisms e.g., globals, function calls, shared memory, IPC/RPC
STREAM Head
CCM Stream
Interfaces should be well-dened Facilitates component testing and team communication Describe component functionality e.g., informally or formally Identify opportunities for systematic reuse Both top-down and bottom-up
MIB ACE
RUN-TIME
TELECOM SWITCHES
EVENT SERVER
STREAM Tail
Design Principles
In the design process the orientation moves from Customer to developer What to how Macro steps include: 1. Preliminary Design External design describes the real-world model Architectural design decomposes the requirement specication into software subsystems 2. Detailed Design Specify each subsystem Further decomposed subsystems, if necessary
Design Principles
Given a requirements spec, design is an iterative decision process with the following general steps:
1. List the hard decisions and decisions likely to change 2. Design a component specication to hide each such decision Make decisions that apply to whole program family rst Modularize most likely changes rst Then modularize remaining difcult decisions and decisions likely to change Design the uses hierarchy as you do this (include reuse decisions) 3. Treat each higher-level component as a specication and apply above process to each 4. Continue rening until all design decisions are: hidden in a component contain easily comprehensible components provide individual, independent, low-level implementation assignments Main goal of these concepts and principles is to: Manage software system complexity Improve software quality factors Facilitate systematic reuse Resolve common design challenges
5
Design Principles
Design Principles
WWW
SERVER
Web server design decisions Portability issues I/O demuxing and concurrency HTTP protocol processing File access Web server components Event dispatcher Protocol handler Cached virtual lesystem
7
HTML
PARSER
PROTOCOL HANDLERS
GUI
REQUESTER
DISPATCHER
GRAPHICS ADAPTER
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
OS KERNEL
OS I/O SUBSYSTEM NETWORK ADAPTERS
NETWORK
www.cs.wustl.edu/jxh/ research/
6
Design Principles
Design Principles
Solution: Decomposition
Decomposition handles complexity by splitting large problems into smaller problems This divide and conquer concept is common to all life-cycle processes and design techniques Basic methodology: 1. Select a piece of the problem (initially, the whole problem) 2. Determine the components in this piece using a design paradigm, e.g., functional, structured, object-oriented, generic, etc. 3. Describe the components interactions 4. Repeat steps 1 through 3 until some termination criteria is met e.g., customer is satised, run out of time/money, etc. ;-)
Design Principles
Design Principles
Features High-performance Flexible concurrency, demuxing, and caching mechanisms Uses frameworks based on ACE
www.cs.wustl.edu/schmidt/PDF/JAWS.pdf
10
State
Component configurator
Tilde expander
11
Design Principles
Design Principles
Solution: Abstraction
ESSENTIAL CHARACTERISTICS
UNESSENTIAL DETAILS
Abstraction manages complexity by emphasizing essential characteristics and suppressing implementation details Allows postponement of certain design decisions that occur at various levels of analysis, e.g., Representational and algorithmic considerations Architectural and structural considerations External environment and platform considerations
Problems: If the web server is hard coded using low-level system calls it will be hard to port If web server developers write software thats tightly coupled with internal implementation details the software will be hard to evolve
IMPLEMENTATION
12
13
Design Principles
ACE Streams
BACKS
EVENT
EVENT
LOOP
Information Hiding
EVENT
LOOP
CALL
i.e., design decisions that are subject to change should be hidden behind abstract interfaces Application software should communicate only through well-dened interfaces Each interface should be specied by as little information as possible If internal details change, clients should be minimally affected May not even require recompilation and relinking...
CALLBACKS
FUNCTIONALITY
APPLICATION-
1. Procedural abstraction
3. Control abstraction
2. Data abstraction
Design Principles
CLASSES
INVOCATIONS
LOCAL
CLASSES
ADT
IPC
ACE Reactor
ACE Task
CALLBACKS
14
15
16
Design Principles
Design Principles
Algorithms
Data representations
+ + + + + + + + + + + + + + + + + + * 1
init (size : size_t) : int msg_type (type : ACE_Message_Type) msg_type () : ACE_Message_Type msg_priority (prio : u_long) msg_priority () : u_long clone () : ACE_Message_Block * duplicate () : ACE_Message_Block * release () : ACE_Message_Block * set_flags (flags : u_long) : u_long clr_flags (flags : u_long) : u_long copy (buf : const char *,n : size_t) : int rd_ptr (n : size_t) rd_ptr () : char * wr_ptr (n : size_t) wr_ptr () : char * length () : size_t total_length () : size_t size () : size_t
Lower-level interfaces
ACE_Data _Block
PAYLOAD (1) SIMPLE MESSAGE STRUCTURE
reference_count() = 2
ACE_Data_Block
Multiple policies can be implemented by same mechanisms e.g., OS scheduling and virtual memory paging Same policy can be implemented by multiple mechanisms e.g., reliable communication service can be provided by multiple protocols
18
17
Design Principles
head_ tail_
Message Queue
Design Principles
Message Block
ACE_Message_Queue
# # # # head_ : ACE_Message_Block * tail_ : ACE_Message_Block * high_water_mark_ : size_t low_water_mark_ : size_t
Data_Block
next() prev() cont()
SYNCH STRATEGY
Message Block
Data_Block
Message Block
Data_Block
Message Block
Data_Block
+ ACE_Message_Queue (high_water_mark : size_t = DEFAULT_HWM, low_water_mark : size_t = DEFAULT_LWM, notify : ACE_Notification_Strategy * = 0) + open (high_water_mark : size_t = DEFAULT_HWM, low_water_mark : size_t = DEFAULT_LWM, notify : ACE_Notification_Strategy * = 0) : int + flush () : int + notification_strategy (s : ACE_Notification_Strategy *) : void + is_empty () : int + is_full () : int + enqueue_tail (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + enqueue_head (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + enqueue_prio (item : ACE_Message_Block *, timeout : ACE_Time_Value * = 0) : int + dequeue_head (item : ACE_Message_Block *&, timeout : ACE_Time_Value * = 0) : int + dequeue_tail (item : ACE_Message_Block *&, timeout : ACE_Time_Value * = 0) : int + high_water_mark (new_hwm : size_t) : void + high_water_mark (void) : size_t + low_water_mark (new_lwm : size_t) : void + low_water_mark (void) : size_t + close () : int + deactivate () : int + activate () : int + pulse () : int + state () : int
Design encapsulates and parameterizes various aspects e.g., synchronization, memory allocators, and reference counting can be added transparently
Design Principles
Design Principles
Context: A production web server that uses abstraction and information hiding Problems: Need to determine the appropriate units of decomposition, which should Possess well-specied abstract interfaces and Have high cohesion and low coupling
A modular system is one thats structured into identiable abstractions called components A software entity that represents an abstraction A work assignment for developers A unit of code that has one or more names has identiable boundaries can be (re-)used by other components encapsulates data hides unnecessary details can be separately compiled
LOGGING
20
21
Design Principles
Design Principles
Stream
APPLICATION
Stream
COMPONENT EXECUTOR
CALL BACKS
STREAM Head
A Stream allows exible conguration of layered processing modules A Stream component contains a stack of Module components Each Module contains two Task components i.e., read and write Tasks Each Task contains a Message Queue component and a Thread Manager component
CONTAINER
EVENT SINK EVENT SOURCE
DOWNSTREAM
UPSTREAM
Dene components that provide multiple interfaces and implementations Anticipate change
MESSAGE
MODULE
WRITE TASK
READ TASK
22
23
Design Principles
Design Principles
Component continuity Do small changes to the specication affect a localized and limited number of components? Component protection Are the effects of run-time abnormalities conned to a small number of related components?
24
Design Principles
Design Principles
Every component should communicate with as few others as Information Hiding possible All information about a Small interfaces (weak coupling) component should be If any two components communicate private unless its specically declared at all, they should exchange as little public information as possible
26
27
Design Principles
Design Principles
Solution: Extensibility
Extensible software is important to support successions of quick updates and additions to address new requirements and take advantage of emerging opportunities/markets Extensible components must be both open and closed, i.e., the open/closed principle: Open component ! still available for extension This is necessary since the requirements and specications are rarely completely understood from the systems inception Closed component ! available for use by other components This is necessary since code sharing becomes unmanageable when reopening a component triggers many changes
Features
Task
SYNCH STRATEGY
Event Handler
handle_input() handle_output() handle_exception() handle_signal() handle_timeout () handle_close() get_handle()=0 A
Service Object
suspend()=0 resume()=0 A
Message Queue
Tasks can register with a Reactor They can be dynamically linked They can queue data They can run as active objects JAWS uses inheritance and dynamic binding to produce task components that are both open and closed
Shared Object
init()=0 fini ()=0 info()=0 A
28
29
PRESENTATION PRESENTATION
APPLICATION APPLICATION
TRANSPORT TRANSPORT
NETWORK NETWORK
GATEWAY B
Context: A production web server whose requirements will change over time Problems: To enhance reuse and exibility, it is often necessary to decompose a web server into smaller, more manageable units that are layered in order to Enhance reuse, e.g., multiple higher-layer services can share lower-layer services Transparently and incrementally enhancement functionality Improve performance by allowing the selective omission of unnecessary service functionality Improve implementations, testing, and maintenance
30
NETWORK NETWORK
VIRTUAL LINK
GATEWAY A
PRESENTATION PRESENTATION
APPLICATION APPLICATION
TRANSPORT TRANSPORT
Design Principles
NETWORK NETWORK
HOST A
SESSION SESSION
NETWORK NETWORK
PHYSICAL PHYSICAL
HOST B
SESSION SESSION
A virtual machine layer provides a set of operations that are useful in developing a family of similar systems
Extensions provide additional data types and associated software instructions Modeled after hardware instruction set primitives that work on a limited set of data types
Design Principles
31
Design Principles
NETWORKED SERVICE COMPONENTS LAYER
LOGGING SERVER JAWS ADAPTIVE WEB SERVER
FRAMEWORK LAYER
SERVICE HANDLER
ACCEPTOR
CONNECTOR
CORBA HANDLER
e.g., compiler ! assembler ! obj code ! microcode ! gates, transistors, signals, etc.
Software Virtual Machine set of system calls restartable system calls signals signal handlers masking signals signal stack
C++
WRAPPER FACADE LAYER
Computer architectures
STREAMS
OS ADAPTATION LAYER
PROCESS/THREAD SUBSYSTEM
COMMUNICATION SUBSYSTEM
www.cs.wustl.edu/ schmidt/ACE.html
32
Design Principles
e.g., Linux
C APIS
PROCESSES/ THREADS
SOCKETS/
TLI
UNIX FIFOS
SELECT/ IO COMP
DYNAMIC LINKING
SHARED MEMORY
Operating systems
MEM MAP
FILE SAP
Hardware Machine instruction set restartable instructions interrupts/traps interrupt/trap handlers blocking interrupts interrupt stack
REACTOR/ PROACTOR
SERVICE CONFIGURATOR
SHARED MALLOC
Design Principles
Design Principles
34
35
33
38
Design Principles
Design Principles
Class X
Class Y
A uses relation does not necessarily yield a hierarchy (avoid cycles...)
Design Principles
AcceptorConnector Service Configurator
svc_run
svc_run
svc_run
svc_run
Some invocations are not uses e.g., error logging Some uses dont involve invocations e.g., message passing, interrupts, shared memory access
Streams
QUEUEING LAYER
Options
HTTP Handler
I/O DEMUXING
LAYER
36
Design Principles
Dening Hierarchies
Relations that dene hierarchies include:
The rst two are general to all design methods, the latter two are more particular to OO design and programming
ACE_IPC_SAP ACE_Addr
ACE_SOCK_IO
ACE_SOCK
ACE_SOCK_Acceptor
ACE_INET_Addr
ACE_SOCK_Stream
ACE_SOCK_Connector
Task
39
37
The is-composed-of relationship shows how the system is broken down in components
Design Principles
Sock Stream
Rule of thumb:
Design Principles
Sock Stream
Start with an invocation hierarchy and eliminate those invocations (i.e., calls) that are not uses relationships
HTTP Handler
Sock Stream
Reactor
Sock Acceptor
40
However, the following are not equivalent: level (virtual machine) component (an entity that hides one or more secrets) a subprogram (a code unit) Components and levels need not be identical, as a component may appear in several levels of a uses hierarchy
Design Principles
HTTP_1_0 Handler
HTTP_1_1 Handler
Many programming languages support the is-composed-of relation via some higher-level component or record structuring technique
This ancestor/descendant relationship is associated with object-oriented design and programming languages that possess inheritance and dynamic binding
e.g., an HTTP_1_0_Handler Is-A ACE_Event_Handler that is specialized for processing HTTP 1.0 requests
Design Principles
class X possesses Is-A relationship with class Y if instances of class X are specialization of class Y.
42
43
41
Memento
IDL
SKELETON
IDL
STUBS
ORB RUN-TIME
SCHEDULER
Tilde Expander
~
/home/...
Protocol Handler Event Dispatcher
Acceptor
Protocol Filter
Service Configurator
OS KERNEL
REAL-TIME I/O SUBSYSTEM HIGH-SPEED NETWORK INTERFACE
ACE components
OS KERNEL
REAL-TIME I/O SUBSYSTEM HIGH-SPEED NETWORK INTERFACE
NETWORK
Active Object
Strategy
TAO is a high-performance, real-time implementation of the CORBA specication JAWS is a high-performance, adaptive Web server that implements the HTTP specication JAWS and TAO were developed using the wrapper facades and frameworks provided by the ACE toolkit
State
Service Configurator
IOP
State
46 Design Principles
Design Principles
Reactor
Minimize footprints for embedded systems Promotes system reusability Anticipates potential changes
HTTP Acceptor
CV_Filesystem
This principle should be applied to facilitate extension and contraction of large-scale software systems, particularly reusable middleware infrastructure
Design Principles
CLIENT
out args + return value
Analyze requirements to identify minimally useful subsets Also identify minimal increments to subsets
44 45
Design Principles
Problems:
OBJ REF
operation ()
OBJECT
(SERVANT)
Singleton
Context: A production web server whose requirements will change over time
It may be necessary to reduce the overall functionality of the server to run in resource-constrained environments To meet externally imposed schedules, it may be necessary to release the server without all the features enabled
Adapter
47
Design Principles
Design Principles
Backward compatibility
48
49
Design Principles
Design Principles
Agile Processes
Stresses customer satisfaction, and therefore, involvement Provide what the customer wants, as quickly as possible Provide only what the customer wants Encourages changes in requirements Relies on testing For example, eXtreme Programming practices Planning, designing, coding, testing
User Story
Requirements
Commitment Schedule
Iteration
Technology Spike
based on http://www.extremeprogramming.org/rules/planninggame.html
Start with user stories Written by customers, to specify system requirements Minimal detail, typically just a few sentences on a card Expected development time: 1 to 3 weeks each, roughly Planning game creates commitment schedule for entire project Each iteration should take 2-3 weeks
50
51
Design Principles
Design Principles
Design Principles
Design Principles
54
55
Design Principles
Design Principles
56
57
Design Principles
Design Principles
58
59
Design Principles
Design Principles
Keep it simple.
Fancy designs are buggier than simple ones; they are harder to implement, harder to verify, and often less efcient Problems that appear complex are often just simple problems huddled together Our job as designers is to identify the simpler problems, separate them, and then solve them individually
60 61
Design Principles
Design Principles
62
Design Principles
Design Principles
64
65
Design Principles
Design Principles
Concluding Remarks
Good designs can generally be distilled into a few key principles: Separate interface from implementation Determine what is common and what is variable with an interface and an implementation Allow substitution of variable implementations via a common interface i.e., the open/closed principle Dividing commonality from variability should be goal-oriented rather than exhaustive Design is not simply the act of drawing a picture using a CASE tool or using graphical UML notation!!! Design is a fundamentally creative activity
66
67