System Design -- Software Engineering


Index

  1. Context Diagrams
  2. Data-Flow Diagrams
  3. Logical Data Flow Diagram
  4. Physical Data Flow Diagram
  5. Levels of Data Flow Diagrams
  6. Problem Partitioning
  7. Software design principles
  8. Modularity
  9. Cohesion
  10. Coupling
  11. Top-Down vs Bottom-Up Design
  12. 1. Top-Down Design
  13. 2. Bottom-Up Design
  14. Top-Down vs Bottom-Up Design Tabular Comparison
  15. Decision Trees
  16. Decision Table

Context Diagrams

https://www.geeksforgeeks.org/context-diagrams/

Pasted image 20241109130951.png


Components :

  1. System Boundary: The context diagram encapsulates the entire system as a single, high-level process (often represented as a single circle or square) to show the system in its entirety without internal details.

  2. External Entity :

    • These are entities outside the system boundary that interact with the system.
    • They could be users, other systems, or processes that provide input to or receive output from the system.

Pasted image 20241109131747.png

  1. System/Product/Process:
    • This is the primary focus of the diagram, representing the system being analyzed or designed.

Pasted image 20241109131941.png

  1. Data Flows: Arrows indicate the flow of data between the system and external entities. Each arrow is labeled to show what kind of information or data is exchanged, such as "user request," "report," or "payment confirmation."

    • Unidirectional Data Flow :

    • Unidirectional data flow indicates that data moves in only one direction between two components.

    • For example, data flows from an external entity to a process, or from a process to a data store, but not in the opposite direction. This type of data flow is represented by a single arrow indicating the direction of data movement.

Pasted image 20241109132154.png


Example : Library Management System

A context diagram for this information would include the following elements:

Pasted image 20241109132710.png

Advantages:


Disadvantages:


Data-Flow Diagrams

https://www.geeksforgeeks.org/what-is-dfddata-flow-diagram/

https://www.youtube.com/watch?v=KN-inGJG540&list=PLxCzCOWd7aiEed7SKZBnC6ypFDWYLRvB2&index=20

Data Flow Diagrams (DFDs) expand on context diagrams by illustrating the internal processes, data stores, and data flow within a system. DFDs show how data is transformed as it moves through the system, capturing the system's functionality in a structured, easy-to-understand way. DFDs are especially useful in the early stages of system design to define the system's data processes without delving into specific technical details.

Pasted image 20241110130915.png

Components :


https://www.youtube.com/watch?v=IQFfMb2T2PY&list=PLxCzCOWd7aiEed7SKZBnC6ypFDWYLRvB2&index=20 (Logical vs Physical DFD)

Logical Data Flow Diagram

Logical data flow diagram mainly focuses on the system process.

Pasted image 20241110132231.png


Physical Data Flow Diagram

Pasted image 20241110132346.png

Now, there are 4 levels of DFD depending on its complexity ,


Levels of Data Flow Diagrams

https://www.youtube.com/watch?v=qtTWBs49BCA&list=PLxCzCOWd7aiEed7SKZBnC6ypFDWYLRvB2&index=19

  1. Level 0 (or Context DFD):

    • This is a high-level diagram that represents the entire system as a single process.

    • It’s essentially the same as the context diagram, showing the system’s interaction with external entities.

      Pasted image 20241110125651.png

  2. Level 1 DFD:

    • Level 1 DFD breaks down the single process from Level 0 into more detailed subprocesses.

    • It shows the main functions or modules of the system and how data flows between them.

    • For instance, in a Library Management System, Level 1 might include processes like "Check Out Book," "Return Book," and "Manage Inventory."

      Pasted image 20241110125900.png

  3. Level 2 and Beyond:

    • Level 2 DFDs decompose Level 1 processes into even more specific subprocesses.

    • This hierarchical decomposition continues until the system is sufficiently detailed for design or development purposes.

      Pasted image 20241110125910.png

  4. Level 3 (and beyond) DFD

In simple terms , higher levels = more defined system.


Problem Partitioning

Problem Partitioning is a design approach in system analysis and software engineering that breaks down a complex system into smaller, manageable parts or modules. This decomposition allows developers to focus on individual components, making it easier to understand, design, and implement the system. By dividing a problem into parts, each module can be developed independently and later integrated to form the complete system.


Why Use Problem Partitioning?

  1. Manageability: Smaller components are easier to develop, test, and maintain.
  2. Parallel Development: Different team members or groups can work on separate modules simultaneously.
  3. Simplified Debugging and Testing: By isolating different system functions, debugging and testing become more straightforward.
  4. Reusability: Modules developed through problem partitioning can often be reused in other projects.
  5. Enhanced Focus: Partitioning allows designers and developers to focus on specific functionalities without getting overwhelmed by the entire system.

Techniques for Problem Partitioning

Several techniques can be used to partition a problem:

  1. Functional Decomposition: Breaking down the system based on functionality. For instance, in a Library Management System, functionalities like “Manage Books,” “Manage Members,” and “Handle Payments” can be treated as separate modules.

  2. Modularization: The system is divided into modules, where each module performs a specific part of the system's overall functionality. Modularization makes sure each module has a single responsibility and minimal overlap with others.

  3. Object-Oriented Partitioning: In object-oriented design, the system is broken down into classes and objects that encapsulate both data and functions. This approach focuses on the real-world entities that the system will manage (e.g., "Book," "Member," "Transaction" in a Library System).

  4. Layered Approach: Dividing the system into layers based on the roles each layer performs. For instance, a typical three-layer system might include:

    • Presentation Layer: User interface.
    • Logic Layer: Business rules and logic processing.
    • Data Layer: Database and data access.
  5. Top-Down vs. Bottom-Up Approaches:

    • Top-Down: Starts with the most general functions and progressively breaks them down into detailed, lower-level functions. Useful for systems where the overall structure is well-understood.
    • Bottom-Up: Begins by designing and developing low-level functions or modules first, which are then integrated into higher-level functions. This approach can be beneficial when individual components are better understood than the overall structure.

As the number of partition increases = Cost of partition and complexity increases.


Software design principles

Software design principles are concerned with providing means to handle the complexity of
the design process effectively
.

Effectively managing the complexity will not only reduce the effort needed for design but can
also reduce the scope of introducing errors during design.


Some software design principles

Abstraction


Modularity

Modularity specifies to the division of software into separate modules which are differently
named and addressed and are integrated later on in to obtain the completely functional
software
.

It is the only property that allows a program to be intellectually manageable. Single large
programs are difficult to understand and read due to a large number of reference variables,
control paths, global variables, etc.

The desirable properties of a modular system are:


Advantages of Modularity:

Disadvantages of Modularity:

Cohesion

https://www.youtube.com/watch?v=NweTzHYBgYU&list=PLxCzCOWd7aiEed7SKZBnC6ypFDWYLRvB2&index=33 (Cohesion and coupling)

Cohesion refers to how closely related the responsibilities of a module or class are.

A module with high cohesion has well-defined responsibilities and focuses on a single task or
purpose, making it easier to maintain and understand
.

Cohesion is a desirable property in software design.

Types of Cohesion:

  1. Functional Cohesion:
    The highest level of cohesion where all parts of a module work together to achieve a single, well-defined task.
    Example: A function that calculates the area of a circle.

  2. Sequential Cohesion:
    Elements of a module are grouped because the output of one element serves as input to another.
    Example: A module that processes a sequence of data.

  3. Communicational Cohesion:
    Elements are grouped because they operate on the same data or contribute to a single data
    structure
    .

    Example: A module that performs various operations on a single data record.

  4. Procedural Cohesion:
    Elements are grouped because they always follow a specific sequence of execution.
    Example: A series of steps in a procedure, such as a task scheduler.

  5. Temporal Cohesion:
    Elements are related by timing and need to be executed at the same time.
    Example: Initialization routines that run when a system starts.

  6. Logical Cohesion:
    Elements perform similar functions but are selected based on a control flag.
    Example: A module that handles different types of user input.

  7. Coincidental Cohesion:
    The weakest form of cohesion, where elements are grouped arbitrarily with no meaningful relationship.
    Example: A utility class containing unrelated functions.


Advantages of High Cohesion:
  1. Ease of Maintenance: Highly cohesive modules are easier to maintain and understand, as they focus on a single task or responsibility.

  2. Improved Reusability: Modules that do one thing well can be reused in different parts of the system or in other projects.

  3. Simpler Testing: Testing a cohesive module is easier because it has a well-defined purpose and fewer dependencies.

  4. Enhanced Readability: Code is more organized and readable, making it easier for new developers to understand the system.


Disadvantages of Low Cohesion:
  1. Difficult Maintenance: Modules with low cohesion are harder to maintain and understand
    because they handle multiple unrelated tasks.

  2. Complex Testing: Testing becomes more challenging due to the increased complexity of a
    module with mixed responsibilities.

  3. Reduced Reusability: Modules are less reusable as they lack a single, well-defined purpose.


Coupling

Coupling refers to the degree of dependency between modules.

Low coupling is desirable because it indicates that modules are independent of each other,
making the system more flexible and easier to maintain
.

Types of Coupling:

  1. Content Coupling (Highest):
    One module directly modifies or relies on the internal details of another module.
    Example: A module accessing the private data of another module.

  2. Common Coupling:
    Two or more modules share the same global data.
    Example: Multiple modules accessing and modifying global variables.

  3. External Coupling:
    Modules are dependent on external factors like external file formats, hardware, or protocols.
    Example: Modules interacting with the same external interface.

  4. Control Coupling:
    One module controls the behavior of another module by passing control information.
    Example: A function passing a control flag to indicate which operation to perform.

  5. Stamp Coupling (Data-Structured Coupling):
    Modules share a data structure but only use a part of it.
    Example: A function receiving an entire record but using only one field.

  6. Data Coupling (Lowest):
    Modules share data through parameters. Only necessary data is shared.
    Example: A function that accepts input arguments to perform a calculation.


Advantages of Low Coupling:
  1. Ease of Maintenance: Changes in one module are less likely to impact other modules,
    making the system easier to maintain and update.

  2. Flexibility and Scalability: Systems with low coupling are easier to extend and scale because
    modules can be modified or replaced independently.

  3. Simpler Debugging: When an issue occurs, it is easier to isolate and debug a loosely coupled
    module.

  4. Reusability: Loosely coupled modules are more reusable in different contexts since they
    have fewer dependencies.


Disadvantages of High Coupling:
  1. Difficult Maintenance: When modules are highly dependent on each other, a change in one
    module may require changes in several others, making maintenance more challenging.

  2. Reduced Flexibility: The system becomes rigid and difficult to extend or modify, as altering
    one part can have a ripple effect throughout the system.

  3. Complex Testing: Testing a highly coupled system is complicated because modules cannot be
    tested independently.

  4. Limited Reusability: Modules are less reusable in other contexts since they are tightly
    connected to other parts of the system.


Top-Down vs Bottom-Up Design

Top-Down and Bottom-Up Design are two contrasting approaches in system design and development. Each offers a different strategy for structuring and developing systems, and both have specific benefits and challenges. They can also be combined in a hybrid approach, depending on the system's requirements.

1. Top-Down Design

In Top-Down Design, the system is approached from a high level and gradually broken down into more specific components and functions. This process starts with the most abstract view of the system, focusing on the big picture before moving into detailed design.

Imagine building a car. In a top-down approach, you’d start by designing the whole car,
then break it down into systems like the engine, wheels, and body, and then further break down the engine into parts like pistons and cylinders.

Pasted image 20241110135829.png


Steps in Top-Down Design

  1. Define the System’s Overall Purpose: Identify what the entire system should achieve.
  2. Break Down into Subsystems: Split the system into major components or subsystems, each responsible for a major function.
  3. Decompose Further: Each subsystem is then decomposed into more specific functions and modules.
  4. Detail Individual Modules: Continue this decomposition until reaching modules with specific, manageable functions.

Example of Top-Down Design: Library Management System


Advantages of Top-Down Design


Disadvantages of Top-Down Design


2. Bottom-Up Design

In Bottom-Up Design, the process starts with the creation of individual, detailed components, which are then gradually combined into higher-level structures. This approach focuses on first developing and testing low-level modules and building upwards.

In the same car analogy, a bottom-up approach would start by designing individual parts,
like the pistons or brakes, and then integrate these to form subsystems like the engine or brake
system, and finally assemble the car.

Pasted image 20241110140123.png


Steps in Bottom-Up Design

  1. Develop Low-Level Modules First: Build small, self-contained modules that accomplish specific tasks.
  2. Combine Modules into Subsystems: Group related modules to form functional units or subsystems.
  3. Integrate into Higher Levels: Continue combining subsystems until the entire system is built.

Example of Bottom-Up Design: Library Management System


Advantages of Bottom-Up Design


Disadvantages of Bottom-Up Design


Top-Down vs Bottom-Up Design Tabular Comparison

Aspect Top-Down Design Bottom-Up Design
Focus Overall system first, then details Individual components first, then combine
Structure Hierarchical, organized around goals Modular, organized around functionality
Adaptability Less adaptable to change More adaptable to change
Design Process Starts from abstract to specific Starts from specific to abstract
Documentation More structured and hierarchical May lack high-level cohesion initially
Testing and Debugging Higher-level issues first Lower-level issues first

Pasted image 20241110140414.png

Pasted image 20241110140426.png


Decision Trees

Decision Trees are a visual tool used in software engineering and decision-making processes to outline possible decisions, their outcomes, and potential paths for reaching a goal. They are particularly useful for representing structured, step-by-step decision-making processes.

In system design, decision trees help analyze choices, break down complex decisions, and visualize the possible results of each choice. They are widely used in software engineering, data science, machine learning, and business processes.

Structure of a Decision Tree

A decision tree typically consists of the following elements:

  1. Root Node: Represents the initial decision point or primary question.
  2. Decision Nodes: Represent each decision or choice at different stages, typically marked with branches leading to further nodes.
  3. Branches: Paths that connect nodes and represent the outcome of a particular choice.
  4. Leaf Nodes: End points that represent the final outcomes or results of the decisions made through the tree.

Pasted image 20241110141137.png

Each node in a decision tree can lead to multiple possible branches, providing a structured way to visualize different choices and outcomes.


Advantages of Decision Trees


Disadvantages of Decision Trees


Decision Trees in Software Development

In software engineering, decision trees can help with various tasks:

  1. Requirements Analysis: By mapping out possible decisions and conditions, decision trees assist in clarifying requirements and understanding how different features interact.

  2. Error Handling: Decision trees can help determine error-handling paths based on specific conditions in the system.

  3. Testing Scenarios: Test cases can be developed based on each branch in the decision tree, ensuring each decision path is adequately tested.

  4. Algorithm Design: Algorithms with conditional branching logic, such as those in AI or rule-based systems, can use decision trees to outline paths and possible outcomes.


Example of a decision Tree

flowchart LR;
	Rain--Yes-->Take_Umbrella
	Rain--None-->Rain_possibility
	Rain_possibility--High-->Take_Umbrella
	Rain_possibility--Low-->Don't_take_Umbrella

Decision Table

Decision Tables are a structured way of representing decision logic by laying out conditions, possible actions, and the relationships between them. They are especially helpful for organizing complex decision-making processes with multiple conditions, where a simple decision tree might become overly complex.


Structure of a Decision Table

A decision table is organized in a grid format, with rows and columns representing the conditions, actions, and possible combinations of decisions. The main components include:

  1. Conditions: Factors or inputs that influence the decision (e.g., “Is the user an administrator?”).
  2. Actions: The outcomes or steps taken depending on the condition's state (e.g., “Grant full access”).
  3. Rules: Each column represents a unique combination of condition states and the resulting actions (e.g., “If user is an admin and logged in, then grant access”).

Layout of a Decision Table

Typically, decision tables are structured as follows:

Condition/Action Rule 1 Rule 2 Rule 3 Rule 4
Condition 1 Yes Yes No No
Condition 2 Yes No Yes No
Action 1 X
Action 2 X X
Action 3 X

In this format:


Example of a Decision Table: User Access Permissions

Let's say we’re designing access permissions for a system, based on the user’s role and login status:

Condition / Action Rule 1 Rule 2 Rule 3 Rule 4
Is user an admin? Yes Yes No No
Is user logged in? Yes No Yes No
Grant full access X
Grant partial access X
Deny access X X

Interpretation:


Advantages of Decision Tables


Disadvantages of Decision Tables


Practical Uses of Decision Tables in Software Engineering

Decision tables are useful in various stages of software development, including:

  1. Requirements Analysis: They help in clarifying business rules by outlining different outcomes based on various conditions.
  2. Test Case Design: Test cases can be created for each rule in the table, ensuring all scenarios are covered.
  3. Algorithm Design: For systems with conditional logic, decision tables provide a structured approach to defining each possible path.
  4. Error Handling: For systems requiring specific responses to different error conditions, decision tables provide a comprehensive view of error-handling paths.

Structured English

Structured English is a technique used in system design to describe complex processes and decision logic in a clear, precise, and structured form. It uses a simplified version of English with specific conventions to help developers and stakeholders understand and document business logic or system procedures without the complexity of full programming language syntax.


Key Features of Structured English

  1. Restricted Vocabulary: Uses a limited set of words (such as IF, THEN, ELSE, WHILE, DO) to describe logic.
  2. Clear and Concise Statements: Avoids ambiguity by breaking down processes into straightforward, readable steps.
  3. Indentation and Structure: Uses indentation to show hierarchy and sequence, which improves readability.
  4. Action and Condition Statements: Describes actions (like calculations or assignments) and conditions (logical checks) to represent procedural logic.

When to Use Structured English

Structured English is particularly useful when:


Components of Structured English

  1. Action Statements: Indicate specific actions that the system needs to perform (e.g., DISPLAY invoice total or CALCULATE total sales).
  2. Conditional Statements: Describe conditions and decision-making logic (e.g., IF customer type is regular THEN apply discount).
  3. Loops: Use WHILE or FOR to represent repetition in the logic (e.g., WHILE there are items in cart).
  4. Indentation: Each level of nesting is indented to visually represent the structure of decisions and actions, enhancing readability.

Example of Structured English

Let’s go through a scenario where we’re defining the logic for a simple Order Processing System:

  1. Process Order:
    • IF order quantity > stock available
      • THEN display “Insufficient stock”
    • ELSE:
      • CALCULATE total cost
      • IF customer is a premium member
        • THEN APPLY 10% discount
      • ELSE:
        • APPLY standard discount
      • UPDATE stock quantity

In this example, Structured English is used to lay out the order processing logic in a way that is easy to understand and implement.


Advantages of Structured English


Disadvantages of Structured English


Practical Use Cases for Structured English in Software Engineering

  1. Documentation: Structured English serves as an intermediate step between business requirements and actual code, making it easier for developers to translate requirements.
  2. Algorithm Design: It helps in laying out algorithms clearly before they are implemented, which is useful for team discussions and review.
  3. Business Rules Implementation: By translating business logic into structured steps, it ensures that the system design reflects business requirements accurately.

Functional vs Object Oriented approaches

https://www.youtube.com/watch?v=bTv3qCtSR5c&list=PLxCzCOWd7aiEed7SKZBnC6ypFDWYLRvB2&index=21

The Functional and Object-Oriented (OO) approaches are two major paradigms in software development. Each has a distinct way of structuring and managing code, along with unique advantages and use cases. Let’s explore the key differences, benefits, and when each approach is typically used.


1. Functional Approach

The Functional Approach emphasizes computation as the evaluation of mathematical functions, avoiding changing-state and mutable data. Functional programming treats functions as first-class citizens, meaning they can be assigned to variables, passed as parameters, and returned as results.


2. Object-Oriented (OO) Approach

The Object-Oriented Approach models real-world entities as “objects” that contain both data (attributes) and methods (functions). This paradigm organizes code around objects rather than actions or logic, making it useful for applications that model real-world entities and interactions.


Key Differences Between Functional and OO Approaches

Feature Functional Approach Object-Oriented Approach
State Emphasizes immutability, avoids shared state Allows mutable state within objects
Modularity Based on pure functions and higher-order functions Based on classes and objects
Code Structure Organized around functions and data transformations Organized around objects and their interactions
Concurrency Easily supports concurrency due to immutability More challenging due to mutable state
Real-World Modeling Less intuitive for real-world object modeling Models real-world objects naturally
Execution Flow Follows a declarative approach Follows an imperative approach

Choosing Between Functional and OO Approaches


Example: Bank Account System (Comparing Approaches)