Jun 11, 1999

Growing Frameworks: Miscellany

Philosophy
                Interfaces
                Generic
                Hotspots
 
Graph
Workflow
Reporting
Drawing
 

Graph

                G = <N,E>
                N & E = 0
                E = <N,N>
 
Graph - Node - Edge
 
================================
                                Graph                    
 
1.             Graph
                Enumeration getEdges()
                Enumeration getNodes()
                boolean isMember(Node)
                boolean isMember(Edge)
                int getEdgeCount()
                int getNodeCount()
 
                Node
                Object getUserObject()
                void setUserObject()
 
                Edge
                Object getUserObject()
                void setUserObject()
                Node getFromNode()
                Node getToNode()
 
2.             Node
                Enumeration getIncomingEdges()
                Enumeration getOutgoingEdges()
 
3.             Graph
                boolean isValid()
 
4.             Graph
                Mutable
                addNode(Node)
                removeNode(Node)
                addEdge(Edge)
                removeEdge(Edge)
 
                Edge
                Mutable ??
                                setFromNode()
                                setToNode()
 
5.             Node
                                inNodes
                                outNodes
 
6.             Graph
                                throws??
 
 
Decisions -
* Add edges to the nodes or the graph?
* Should createNode() and createEdge ()  be factory methods on Graph?
* Implementations - Node could have list of outnodes (with implicit edges), or perhaps independent nodes & edges in a bitarray.
 
Graph Applications:
                Workflow
                                Bug-tracking
                                Trouble tickets
                                Student registration
 
 

DRAWING TOOL

 
Figure
                bounds
                position
                draw
                dependents
                contains
 
Handle
 
Canvas
 
Tool

 

BACKGROUND THINKING

 
Frameworks in the small:
* Interface - trace specs   Hoffman??
* Specsmanship - model
* Parnas
* Booch
* Meyer
 
 

FINAL GRAPH

 
Node
                Object getUserObject()
                void setUserObject(Object o)
                Enum getInEdges(), getOutEdges()
                Enum getInNodes(), getOutNodes()
 
Edge
                Node getFromNode()
                Node getToNode()
                Object getUserObject()                       *
                void setUserObject(Object o)            *
                                * implications for independent representation
 
Graph
                Enum getEdges()
                Enum getNodes()
                int getEdgeCount()
                int getNodeCount()
                bool isMember(node)
                bool isMember(edge)
                bool isValid()
 
MutableGraph -  subtype
                createNode([uo])
                createEdge([uo])
                removeNode(n)
                removeEdge(e)
                                throw graph change exception??
 

OUTLINE

 
I. What is a framework?
                Philosophy - generic, interface, hotspots
                definitions
 
II. Graph - mini-framework
                Domain - sample uses
                Dimensions of flexibility
                First few cuts - multiple implementations
                Frameworks in the small
                Final framework - code
                Sample uses
                                web checker
                                traffic simulator
                                UML Diagrammer
                Use of packages
 
INTERLUDE: Frameworks in the small
 
III. Patterns and Swing
 
IV. Workflow
                Layered framework
                model
                framework
                design patterns - policy vs implementation, strategy
                uses
                                bug tracker
                                student registration
                                trouble tickets
 
V. Reporting
                Predicate / Result
                Groups
 
VI. Drawing
                Separate framework
                Connect to graph
 
VII. Assembly
 
VIII. Growth, Delivery, Engineering
 

HOFFMAN - FRAMEWORKS in the SMALL

 
* Consistent: "with partial knowledge, the remainder of the system can be predicted"
* Essential - omit needless features
* General: Open-ended (future expansion) and complete (all functions of class)
* Minimal - independent features are separate
* Opaque - information hiding. Each module hides a secret. The module needn't change its interface even if the secret changes.
 
Application:
                Pop combines pop and top - bad
                ungetc combines get  and advance - bad
                graph - node & edge deletion
                combining get/set generally bad
 
Graph interface
Function                       Input    Output       Exceptions
s_init      int           -               maxnodes
g_numnodes         -               int
----------------------------------------------------------
s_addnode            int           -               nodenum, exnode
s_delnode             int           -               notexnode
g_exnode               int           bool       
----------------------------------------------------------
s_addedge            int           -               exedge, len
                int          
                real
s_deledge              int           -               notexedge
                int
g_exedge               int           bool       
                int
g_edgelen             int           real          notexedge
                int
----------------------------------------------------------
g_expath                int           bool
                int
g_pathlen              int           real          notexpath
                int
g_firststep             int           int           notexpath
                int
--------------------------------------------------------
Note: ex=exist, g=get, s=set                              
 
 
 
 

Abstract Data Types

Completeness
                Each method defined for each representation
 
Consequence
                Does it accept null?
                Does it return null?
                Can args have illegal values eg out of range?
 
 

WHAT IS A GRAPH?

 
We aren't doing this to provide a pure mathematical graph: we're doing it so we can apply the idea of a graph to real problems. This leads us to other considerations:
 
* We have information to attach to nodes and edges
 
* Edge from node to itself?
 
* Do we want multiple occurrences of an edge? (Classical def doesn't allow it.)
 
* Are our graphs mutable or immutable? We might like to distinguish these cases.
 
* Do we want constraints on our graph? (eg connected or non-cyclic)
 
 
From our sample domains, we see the need to handle these cases:
* We need to attach information to both nodes and edges. Every application we examined could take advantage of this.
* We will allow multiple occurrences of edges. When an edge has extra information, it's not merely recording connectivitiy, it's attaching ther info to the edge, and many sets of information could connect two nodes.
* Mutable/immutable is a useful distinction. (Example jdk1.2 collections) Many situations may have an expensive construction stage, followed by read-only use.
* Validity of the graph is important. This may be useful in allowing for multiple implementations. Some can take advantage of limited graph structure.
 
 
 
APPROACH
Graph class
                Develop class - subclass to use - critique interface
 
From class to framework
                Move to interface - black-box via adding userObject
 
HOFFMAN _ BAD GRAPH
 
Function                       Input    Output       Exceptions
s_init      int           -               maxnodes
g_numnodes         -               int
g_inf       -               real                          *1
s_addedge            int           -               nodenum, len, src_q_dst
                int          
                real
g_visited               int           real                          *2
                int
g_pathlen              int           real
g_firststep             int           int           notexpath
                int
g_edgelen             int           real          notexedge              *3
                int
 
*1  Infinity > any path length
*2  True if edge for node
*3  Length s to d, or g_inf if no path.
 
Notes: Assumes edge of length 0 between any node and itself.
Method g_first_step returns the first node in the shortest path to d. Pass in the previous result to compose a path.
 
Problems:
1. Can't add node without edges present
2. "self-loop" on node is a pain
3. Pathlen - can't find edge without also finding the path
4. No deletion except s_init
 
 
 
 
 
 
 
 
 

GRAPH CLASS - NOTES

 
Now - this is not a terrible class.
But there are things that can be improved.
 
Three things stand out:
1.
2. The "name" field is in all subclasses - but some won't need it. Furthere - it's there as a public field - it should at least be wrapped. Probably best to remove it completely.
3.
 
Guidelines:
Don't make subclasses pay for extra baggage
 
List of nodes:
Let's make them enumerations.
String name - remove it. Let subclasses add it if they need it.
 
// v0.2
public class Node {
                private Vector nodes;
                public void addEdge (Node n)
                public void removeEdge(Node n)
                public Enumeration getNodes()
                public Enumeration pathTo(Node n)
}
 
 

PULLING OUT THE ABSTRACTION

 
The graph case is "easy", because we have the mathematical model to fall back on.
 
First, we see there is a class for Nodes, but none for the graph as a whole, so we'll add
                public class Graph {
                                public Enum getNodes()
                                public void addNode(Node n)
                                public Enum getNodeCount()
                                public void removeNode(Node n)
                }
 
Second, we may want edges to be explicit. This may make our overall representation a little more expensive, but we have information we need to associate with edges.
 
                public class Edge {
                                public Node getFromNode()
                                public Node getToNode()
                                Edge(Node n1, Node n2)
                }
 
We'd like to be able to look at all edges in the graph:
                getEdges()
                getEdgeCount()
 
Where do we add edges - the node or the graph? Probably want to add them to the graph.
                add(edge)
                remove(edge)
                add(node)
                remove(node)
 
Multiple implementations are a consideration.
 

GROWING INTO A FRAMEWORK

 
* Indepdent of implementation - strong barrier
 
* Inversion of control (vs library)
 
* Extensible - black-box
 
 
 
 
 

IDEAS

* Adapter classes
* Frameworks
* Pree - Hot spots
 

GUIDELINES

 
Rules - Interface
* Avoid getter/setter functions
* Look for missing abstractions
* Pre/post-conditions
* Defined behavior for all arguments (eg null)
* Consistency
* Independent features are separate (minimal)
* What's the secret?
* Don't expose attributes
* Essential: omit needless features
* General: open-ended and complete
 
Closed set - native types or frameworks'
 
Guidelines - framework
* Abstract classes
* Black-box, white-box
* Library
* Flow of control
* Hot spots
* Don't make subclasses pay for what they don't use (cost ala carte)
* Implementation -independent
* Class relationships to base class
* Seek models - steal ideas
 
Patterns in frameworks
* Template method
* Factory
* Composite
* Decorator
* Strategy
 
Lifetimes
* Expand/contract
* Release
* Testing
 

PATTERNS IN AWT

 
MVC/Event-Observer
                Event mechanism
                PLAF
 
Composite
                JComposite -> Container
               
Flyweight
                Border
 
Decorator
                Border (Compound Border)
 
Template Method
                JComponent paint, paintComponent, etc.
 
Strategy
                LayoutManager
 
Factory Method
                DateFormat
               
Interpreter
                SimpleDateFormat
 

 

REPORTS

Query
 
Format
 
Accumulators
                By type
                By date
                By page
 
 

References

 
Schmidt, Douglas. Using Design Patterns to Develop Reusable Object-Oriented Software. ACM Computing Surveys, 28(4), December, 1996.
 
J. Vlissides. Subject Oriented Design. C++ Report, Feb., 1998.
 
Harrison & Ossher. Subject-Oriented Programming. OOPSLA '93.
 
 
                                Testing OO
 
R.M. Poston. Automated Testing from Object Models. CACM Sept'94, v37 #9, pp 48-58.
 
G. Rothermel & M.J.Harrold. Selecting Regression[s] Tests for Object-Oriented Software. Proc Conf Software Maintenance, IEEE, 1994, pp 14-25.
 
D.E. Perry & G.E. Kaiser. Adequate Testing and Object-Oriented Programming. JOOP 1990 2(5) pp 13-19.
 
Sept '94 CACM. Special issue on object-oriented testing.
 
Jacobson. OOSE.
Marrick. The Craft of Software Testing.
McGregor. Object-oriented Software Development.
Siegel. Object-Oriented Software Testing.
 
Object Magazine. Pattern Language for Testing Object-Oriented Software. V5 #8 Jan'96. pp 32-38. "PLOOT" - Firesmith.
 
CACM Oct. '97 - Special issue on frameworks
 
Framework-Based Software Development in C++
                Gregory F. Rogers, Jan. '97
 
CACM Oct' 96
                Special issue on patterns

References
 
Online (URLs)
 
Books
 
Articles
 
 
 
Winograd/Flores
                Reflection in Action
 
The Reflective Practitioner
                Donald Schoen
 
 
 
 

Ideas

 
Frameworks vs class libraries
 
[What's the difference?]
 
 
 
Show dynamic models for designs
 
 
 
Beans as a framework
 
 

Workflow

 
(Idea for another framework)
 
Entities
Processes
Constraints
"Who's next?" - workflow engine
Measurement
Return to sender
State machine?
Aging
Off the clock
 
 
 
Reports:
Time in node
Time in cycle
Close time (clock, off-clock)
By node, etc.
Predicates
Recursion?
 

JotDraw

 
Fast interaction
 
Links count (move objects => links adjust)
 
Fast
 
                X  for shapes  [buttons]
 
                Auto-scroll for typing
 
Keystrokes for shapes
 
Auto resize
 
Zones (tab key)
 
Click to drag or delete
 
Drag bomb over node to kill?
 
 
 
Issues
 
Conflicting Class Hierarchies
 
 
Separation of concerns
 
 
Coupling & cohesion
 
 
Separate policy & implementation
 
Explain why it's better (rules)
 
 
 
 
Threads
 
 
Corba
 
 
Applet as an example of template method
 
 

Putting it all together - design of a searching framework.