Design

From Domain Analysis to Domain Models to Object-oriented Designs to Code

How do we take fuzzy requirements information (features, use-cases, sketches, domain analysis) and get to code?
  • You can just start coding..
  • But, most times the underlying logic needed in the app is so fuzzy that the initial code will be garbage
  • Solution: make an initial object-oriented design to dig a little deeper.
A progression
  • Domain analysis: understand your domain better (you should have done this in requirements).
  • Domain modeling: use UML class diagrams to outline the key objects and relationships of the app
  • Object-Oriented Design: the classes in your code and the relationships between then: refine the domain model UML more with coding in mind
  • Code: use the object-oriented design to help in initial coding.
For the design iteration of the projects, we will make an initial object-oriented design.

Initiating and refining designs

Domain modeling to get started

  • A Domain model is a conceptual model of the underlying domain, not necessarily of the actual program.
  • Our form of domain modeling is to make a UML class diagram of the underlying domain
    -- This means applying code process diagramming tools (UML) to real-world processes: seems strange but it works!
  • For more background and details on domain modeling with UML, see these slides from CS389 at Pace University.
  • Entity-relationship diagrams of databases are a similar diagram, but lack the ability to put actions (methods) in them
  • Depending on the framework(s) used this diagram can be refined to an object-oriented design and serve as the initial classes/objects of the application.

Textual analysis to get started

This is a simple but effective way to come up with an initial list of classes / methods

  • Look at your vision statement, feature list, and use-cases.
  • Classes are the nouns (the things)
  • Methods are the verbs.

Tangent: UML class diagrams

Lets look at some domain models expressed in UML. UML class diagrams have many fancy features. You really only need to use a few of them, but we are going to be sticklers on these few.
  • Classes: make sure to include relevant fields and methods in a class. Don't include a field if its already shown elsewhere in the diagram. Don't forget methods!
  • Associations: all an association is is a line conecting two classes. Its that simple. If classes are interacting directly, put a line between them.
  • Multiplicities: on an association, denote how many of each thing is interacting: 1, 2, 5, * (same as 0..*), 1..*, 2..*, etc
  • Whole-part relationships on associations: use the diamond on associations to show the whole and parts. The filled-in diamond means "ownership".
  • Inheritance: use the special inheritance arrow between classes, only for inheritance.
  • Other: feel free to use other UML syntax. In particular naming associations can be helpful. But, its not required. Regular arrowheads on associations mean "accessibilty" - from one class you can get to another. They are often used but are not required.

Class design

  • Think about an individual class' responsibilities; make any responsibility or action a class needs a method of the class (with an evocative name so you will remember what its supposed to do)
  • Play out different storyboards / use-cases over the class diagram and make sure there is a class & method responsible for implementing each action in the use-case
  • If two or more classes are similar but not quite the same, make an abstract superclass of them containing the shared functionality
  • Refine your UML class diagram with appropriate notation to better understand relationships
    • classes interacting with each other are placed nearby and are marked with a UML association edge
    • think carefully about the multiplicity on the UML associations, they help add understanding.
    • Think about "is-a" and "part-of" for inheritance and association edges respectively (the former adds open arrows, the latter adds the diamonds)
    • Draw a class diagram showing only the classes involved in the part of the app you are focusing on. This helps reduce clutter.
    • Focus on the core logic for your projects -- there isn't much interesting in all the UI classes for example, so there is probably no need to diagram them.

Evolving the requirements to a design

Use-case refinement

  • Use-cases are a bridge from the more complex features to code: they are very simple pseudocode
  • Some requirements-level use-cases need refinement as the app comes more into focus: turn customer-focused steps into a sketch of the algorithm implementing it
Techniques for fleshing out the use-cases
  • Add new use cases based on a missed complex action needed in e.g. a UI
  • Given improved UI sketches and classes, replay a use-case looking for missing steps
  • Expand on individual use-case steps which clearly have more sub-steps in them
  • Break out too-big steps into their own use cases

UI refinement

  • Visualise in detail how the app is going to work; don't use fake placeholder names, draw potentially real data in the views.
  • Make sure there is a UI associated with each feature or use-case activity

Component and Package Design

Terminology: packages, components, and deployment nodes.

  • Packages aka Modules: Dividing software into packages is critical for larger software: complex software has larger logical groupings of code than classes.
  • Components: a component has a run-time identity with an explicit run-time interface. For example if you are using a database, that is a separate component.
  • Deployment node: the physical network setup for distributed applications. Components are often remotely deployed.

Start with the bigger picture: pull out logical modules to factor design from the top.

  • You should have a vague idea of what libraries/frameworks you want to use already
  • Refine that to a component/deployment structure of your application
  • Within components, look for modular functionality groupings to make packages from

Design Examples

  • We will spend a good amount of time doing an example initial design in lecture. Here are the rough notes we made for the record:

  • Also see some recent OOSE Project design documents.

Prototyping

For complex libraries/frameworks, prototype before integrating into your app
  • Exercise the library with a small bit of code to make sure its doing what you need it to; then use it in your app
  • Prototyping is also helpful for UIs, stand them up with mock servers before actually them hooking up.

Project Iteration 2

The details of what you need to do for Iteration 2 will be discussed.