Design Processes

Building a great software requires some form of processes in order to through its lifetime. There are many software design development lifecycle (SDLC) to choose but all of them generally falls into the following process milestones.

Requirement Gathering

In this stage, all members including business unit gathers the requirements for building a software. Requirements say WHAT the system will do and NOT how it will do it.

It is pretty much the human-side of social communications.

Caveat

It is hard to decide precisely what to build upfront.

Things to Considers

  • What does the customer want?
  • What is (think legal, policy constraints, technological availability, etc):
    • desired
    • required
    • not necessary
  • Customers often do not know what they really want; vague, biased by what they see. Query the requirements again from time to time to get a more accurate idea.
  • Get the list of minimal vital requirements at a given time before proceeding to next stage.

Converting Requirements to Functional Architecture

The next step is to convert the requirements into functional architecture. This means you need to convert the aspects of problem space (domain model) into a the aspects of solution space (object model). Some examples are:

  • Real-world concepts ➔ System implementation
  • Requirements, concepts ➔ Classes, objects
  • Relationship among concepts ➔ References among objects, inheritance hierarchies, etc.
  • Solving a problem ➔ Computing a Result
  • Building Vocabulary ➔ Finding solution
  • Present intuitively ➔ Graphs, Tables, Charts, etc
  • Perform competitively ➔ benchmark, testing, etc


Analysis

The goal is to find the concepts of the problem domain and establish a common communications vocabulary and documentations, mainly for communications. Hence, it is often visual, like using UML. Hint:

  1. A domain model for communicating between developers, testers, clients, domain experts, …
  2. Agree on a single vocabulary and visualization
  3. Focus on concepts, not software classes, not data:
    • ideas, things, objects
    • give it a name, define it and give examples (symbol, intention, extension)
    • many choices are available, seek them out
    • model can never be perfect
      • That's okay. Start with partial model, extend with additional information later. This communicates clearly.
      • Otherwise, it is a sign of analysis paralysis.


When we analyze the requirements, we consider looking into:

  1. understanding the problem
    • Read the requirements descriptions, look for nouns
    • Reuse existing models
    • Use a category list
    • Analyze typical use scenarios
    • Brainstorming
    • The hit: collect first ➔ filter ➔ revise later
  2. identify the key concepts and their relationships
    • remove concepts irrelevant from the problem
    • remove vague concepts (e.g. "system")
    • remove redundant concepts, agrees on name
    • remove implementation constructs
    • distinguish attributes (string / numbers) and concepts
    • model relationship between concepts (is a, related to, has one, has many, belongs to, owns, etc.)
  3. build a visual vocabulary (flow chart, etc)
    • Distinguish between concepts and attributes (if you can't quantify the concept in string or number, it is a conceptual class)
    • Associate the relationship between concepts
  4. agree to design and common set of terms using low representation gap (congruency)
    • Seek out intuitive understanding, like clear vocabulary in both spaces.
    • Seek out real world abstractions changing factors.
    • Simplify vocabularies.
    • facilitate understanding of design and implementation
    • facilitate traceability from problem to solution
    • facilitate facilitate evolution (small changes in domain space leads to small changes in codes)
    • ease tracking and performing of changes
  5. create a domain model (a.k.a conceptual model)
    • Usually the use of UML Diagram with Sequence Diagram
    • Association, inheritances, ... as needed
    • DO NOT include implementation-specific details, e.g. types, method signatures, etc.
    • Include notes as needed
    • Complement with examples, glossary, etc. as needed
    • Formality depends on size of projects
    • Expect revisions
    • Stay distinctive from solution model:
      • domain model describes the implementation details in the solution model, not the other way round
      • domain model speaks concepts and relationships, not necessarily data to be stored
      • no UI, database, etc. in domain model.



Design

Once you have the domain model, in design steps, we consider looking into:

  1. identifying software classes and their relationships with class diagrams
    • Finding out the types of responsibilities (knowing & doing)
      • Doing - something to itself like creating objects or calculations, initiating action in other objects, controlling or coordinating activities in other projects.
      • Knowing - understand about private encapsulated data, related objects, things that it can derive and calculate.
  2. assign responsibility (attributes, methods)
  3. explore behavior with interactive diagrams
  4. explore design alternatives
  5. create an object model (a.k.a design model or design class diagram)
  6. create a map design for code, implementing classes and methods


Design User Experience / User Interface

The next step is always about designing the user experience / user interface, be it GUI or API calls. This is because modern software is no longer using pooling but are driven by events, known as event-driven programming or reactive programming.

Hence, it is important to design the front-end first (GUI or API), and then decouples it with its associated back-end events like the implementation the button triggers.

Observer patterns are often used in this step.


Event-Driven Programming vs. Non-Event Driven Programming

The biggest differences is the user experiences and resources consumption.

  • Event-driven does not block the resources (CPU) for other processing in a system; Non-event-driven is blocking the CPU since it needs to pool the event.
  • Event-driven is highly responsive since it executes upon user's events; non-event-driven is not responsive and sometimes unresponsive since the pooling has a tendency to miss an event trigger if the read timing and trigger timing are out of sync.
  • In main thread, event-driven is asynchronously driven (react upon triggers) while non-event-driven tends to be synchronously driven (looping).

That's all about design processes.