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!
  • 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: The UML class diagram widgets we will be using

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 step-by-step operations
  • Some requirements-level use-cases need refinement as the app comes more into focus
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 going over example initial designs, including 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 as dummies before hooking into app logic.

Project Iteration 2

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