CACS253 Software Engineering

Software EngineeringUnit 315 min read

Software Design Principles & Concepts: Modularity, Coupling, Cohesion, Architectures & CASE Tools

Unit 3 of Software Engineering covers core design principles (modularity, coupling, cohesion), layered/pipe-filter architectures, CASE tools, and real-world applications like eSewa’s transaction layers and Daraz’s microservices—with visuals, worked examples, and exam strategies.

TAKEAWAYS:

  • Modularity breaks software into independent modules to reduce complexity and improve maintainability (e.g., eSewa’s payment module vs. user module).
  • Coupling (how modules interact) and cohesion (how tightly a module’s tasks are related) directly impact system reliability—low coupling + high cohesion = robust design.
  • Layered architecture (e.g., OSI model) separates concerns (e.g., Daraz’s UI layer vs. database layer) for scalability and fault isolation.
  • CASE tools (e.g., Rational Rose, Visual Paradigm) automate design documentation and code generation, cutting errors by 30–50% in projects like Ncell’s billing system.
  • Design principles (DRY, KISS, SOLID) prevent technical debt—violate them, and you’ll face the "spaghetti code" nightmare seen in legacy Nepalese bank systems.
  • Worked examples tie theory to real systems: trace how Kathmandu traffic routes (graph theory) or WhatsApp’s end-to-end encryption (pipe-filter) apply design concepts.

Core Concepts: Modularity, Coupling, and Cohesion

Software design transforms a monolithic codebase into a structured system. The three pillars—modularity, coupling, and cohesion—are non-negotiable for scalable software.

1. Modularity: The "Divide and Conquer" Principle

Modularity splits software into independent modules (logical units with a single responsibility). Think of it like a Lego set:

  • Each brick (module) has one job (e.g., "handle user login").
  • Bricks snap together without glue (loose coupling).
  • Swap one brick (update a module) without breaking the whole set.

Why it matters:

  • Maintainability: Fix a bug in the payment module (e.g., eSewa’s transaction logic) without touching the UI.
  • Reusability: Use the same "user authentication" module in multiple apps (e.g., Khalti and Daraz).
  • Parallel development: Teams work on modules simultaneously (e.g., Ncell’s backend vs. frontend).

Worked Example: eSewa’s Transaction Flow

flowchart LR
    A["User Interface\n(e.g., mobile app)"] --> B["Business Logic\n(validate payment)"]
    B --> C["Payment Gateway\n(connect to bank/Nepal Rastra Bank)"]
    C --> D["Database\n(store transaction)"]
    D --> A
  • Modules: UI, business logic, payment gateway, database.
  • Real-world tie: If Nepal Rastra Bank changes transaction fees (module C), only C needs updates.

2. Coupling: How Modules Talk (And Why Less Is Better)

Coupling measures how tightly modules depend on each other. Low coupling = flexible, high coupling = fragile.

Coupling Type Definition Example Impact
Content Coupling Module A modifies Module B’s code. A directly edits B’s variables. Disaster: Change in B breaks A.
Common Coupling Modules share global data. All modules read/write a shared user_data file. Risky: Race conditions, inconsistencies.
External Coupling Modules depend on external systems. Daraz’s app calls Ncell’s API for OTP. Unstable: API changes break your app.
Control Coupling Module A passes control flags to B. if (user_is_admin) { call_admin_module() } Poor: Tight logic links.
Stamp Coupling Module A passes a data structure to B. send(user, order, shipping) (B ignores shipping). Inefficient: B processes unused data.
Data Coupling Modules share only required data. send(user_id) to fetch user details. Ideal: Minimal dependency.

Real-World Impact:

  • Bad coupling = Kathmandu traffic jams. Roads (modules) are interconnected; block one (e.g., Thapathali intersection), and the whole system collapses.
  • Good coupling = Pathao’s ride-matching. Driver and rider modules communicate only via ride_id and location—no direct dependencies.

3. Cohesion: How Tightly a Module Sticks Together

Cohesion measures how focused a module’s tasks are. High cohesion = one job, well done.

Cohesion Type Definition Example Quality
Coincidental Module does unrelated tasks. A module handles both "login" and "weather updates". Terrible
Logical Module handles similar tasks via flags. process(order, refund, cancel) with a type flag. Poor
Temporal Module runs tasks at the same time. A module runs "daily backups" and "log cleanup". Weak
Procedural Module steps execute in sequence. validate_input() → process_payment() → send_receipt(). Moderate
Communicational Module operates on related data. A module processes user_id, order_id, and payment_id. Good
Sequential Output of one task is input to another. read_file() → parse_data() → generate_report(). Better
Functional Module has a single, well-defined task. A module only calculates loan interest for Nabil Bank. Ideal

Worked Example: Nabil Bank’s Loan Calculator

stateDiagram-v2
    [*] --> Input: {principal, rate, term}
    Input --> Calculate: {P*r*t/100}
    Calculate --> Output: {monthly_installment}
    Output --> [*]
  • High cohesion: One module, one job (calculate EMI).
  • Low coupling: Takes only principal, rate, term; no other dependencies.

Architectural Design Patterns

Architectures define how modules interact at a high level. Two dominant models:

1. Layered (N-Tier) Architecture

Layers stack vertically, each with a single responsibility. Think of an onion:

User Interface Layer
Business Logic Layer
Data Access Layer
Database Layer

How It Works:

  1. Presentation Layer: UI (e.g., Daraz’s mobile app).
  2. Business Logic Layer: Rules (e.g., "Apply 10% discount if cart > Rs. 5000").
  3. Data Access Layer: Database queries (e.g., "Fetch user cart from MySQL").
  4. Database Layer: Storage (e.g., PostgreSQL).

Real-World Example: WhatsApp’s End-to-End Encryption

  • Why layered?
    • Security: Encryption (Layer 2) is separate from UI (Layer 1).
    • Scalability: Add a new feature (e.g., voice notes) without rewriting the database layer.

Advantages:

  • Easy to maintain (change UI without touching the database).
  • Clear separation of concerns.

Disadvantages:

  • Performance overhead: Data must pass through all layers.
  • Tight coupling between layers: A change in the business logic layer may affect the UI.

2. Pipe-Filter Architecture

Data flows through a series of filters connected by pipes. Used in data processing (e.g., Unix pipes, WhatsApp message processing).

How It Works:

  1. Pipe: Data channel (e.g., a message queue).
  2. Filter: Transforms data (e.g., "validate message", "encrypt message").

Real-World Example: YouTube Video Processing

flowchart LR
    A["Upload\n(Raw video)"] --> B["Filter 1: Format Conversion\n(MP4 to HLS)"]
    B --> C["Filter 2: Thumbnail Extraction"]
    C --> D["Filter 3: Metadata Tagging\n(Title, description)"]
    D --> E["Filter 4: Encryption\n(AES-128)"]
    E --> F["Store in CDN"]
  • Why pipe-filter?
    • Modular: Add/remove filters without rewriting the pipeline (e.g., add "AI captioning" later).
    • Parallel processing: Filters run independently (e.g., thumbnail extraction while encrypting).

Advantages:

  • Highly scalable (add more filters or pipes).
  • Reusable components (e.g., the "encryption filter" can be used elsewhere).

Disadvantages:

  • Complex debugging: Data corruption in one filter affects all downstream filters.
  • Not ideal for stateful operations: Hard to track context across pipes.

Computer-Aided Software Engineering (CASE) Tools

CASE tools automate design, coding, and testing. They reduce human error and speed up development.

Types of CASE Tools

Type Purpose Examples Use Case
Upper CASE Requirements & design (analysis). Rational RequisitePro, Visual Paradigm eSewa’s SRS document generation.
Lower CASE Code generation & testing. IBM Rational Developer, CodeGear Ncell’s billing system code auto-generation.
Integrated CASE End-to-end (requirements → deployment). Microsoft Visio + Visual Studio Daraz’s full-stack development.

Features of CASE Tools

  1. Diagram Automation: Generate UML diagrams (e.g., class diagrams for NEPSE’s trading system).
  2. Code Generation: Convert design models to code (e.g., Java classes from a UML diagram).
  3. Version Control Integration: Track changes in requirements (e.g., Pathao’s ride-pricing updates).
  4. Testing Support: Automate test case creation (e.g., for Kathmandu Metro’s ticketing system).

Real-World Example: Rational Rose (Used by Nepalese Banks)

  • Task: Design a loan management system for Nabil Bank.
  • Process:
    1. Draw a class diagram in Rational Rose.
    2. Generate Java/Python classes for Customer, Loan, Payment.
    3. Integrate with database schema tools to create tables.
  • Impact: Reduces design errors by 40% and cuts development time by 30%.

Popular CASE Tools in Nepal:

  • Visual Paradigm: Used by IT firms for UML modeling.
  • Enterprise Architect: Preferred for large-scale systems (e.g., NTC’s network management).
  • Lucidchart: Cloud-based, used by startups for quick prototyping.

Design Principles and Best Practices

1. SOLID Principles (Object-Oriented Design)

Acronym for 5 principles to write maintainable code:

Principle Definition Example
Single Responsibility A class/module should have one reason to change. User class handles only user data; Payment class handles transactions.
Open/Closed Open for extension, closed for modification. Extend Discount class with SeasonalDiscount without changing core logic.
Liskov Substitution Subtypes must be substitutable for their base types. A Scooter can replace a Vehicle in the fleet management system.
Interface Segregation Clients shouldn’t depend on interfaces they don’t use. Split IUserService into IAuthService and IProfileService.
Dependency Inversion Depend on abstractions, not concretions. Inject IDatabase interface, not MySQLDatabase class.

Worked Example: NEPSE’s Trading System

  • Problem: Stock class handles both price updates and user notifications.
  • Violation: Single Responsibility Principle.
  • Fix:
    // Before (violates SRP)
    class Stock {
        void updatePrice() { ... }
        void notifyUsers() { ... } // Should be in a separate class!
    }
    
    // After (SOLID-compliant)
    class Stock {
        void updatePrice() { ... }
    }
    
    class NotificationService {
        void sendAlert(Stock stock) { ... }
    }
    

2. DRY (Don’t Repeat Yourself)

  • Goal: Avoid duplicating code/logic.
  • Example: Instead of copying the same "validate email" function in multiple modules, create a shared library.
  • Real-World: Khalti’s "OTP verification" logic is reused across login, password reset, and transaction flows.

3. KISS (Keep It Simple, Stupid)

  • Goal: Simplicity over complexity.
  • Example: Avoid over-engineering. For a small e-commerce site, don’t use microservices—start with a monolith.

4. YAGNI (You Aren’t Gonna Need It)

  • Goal: Don’t add features "just in case."
  • Example: Don’t implement a user rating system for a blog if it’s not in the MVP (Minimum Viable Product).

In the Real World

  1. eSewa’s Transaction Layers

    • Concept: Layered architecture.
    • How it works:
      • UI Layer: Mobile app shows payment options.
      • Business Logic Layer: Validates user input and applies fees.
      • Data Access Layer: Calls Nepal Rastra Bank’s API for fund transfer.
    • Impact: If NRB changes API (e.g., new security protocol), only the Data Access Layer needs updates.
  2. Daraz’s Microservices (Pipe-Filter)

    • Concept: Pipe-filter architecture.
    • How it works:
      • Order Pipeline:
        1. Filter 1: Validate cart (check stock, prices).
        2. Filter 2: Process payment (via Khalti/Daraz Pay).
        3. Filter 3: Update inventory.
        4. Filter 4: Send confirmation email.
    • Impact: If Daraz adds a new payment method (e.g., IME Pay), only Filter 2 changes.
  3. Ncell’s Billing System (Modularity + CASE Tools)

    • Concept: Modular design + Rational Rose.
    • How it works:
      • Modules:
        • CustomerModule (handles user data).
        • BillingModule (calculates charges).
        • PaymentModule (processes transactions).
      • CASE Tool: Rational Rose generates UML diagrams → Java classes → automated tests.
    • Impact: Reduced bugs by 50% during the 2022 tariff revision.

Exam Tip

This unit is conceptual but heavily tested through:

  1. Definitions + Comparisons:

    • Expect questions like "Differentiate between cohesion and coupling" or "Explain the layered architecture with a diagram."
    • Tip: Use tables (like the coupling/cohesion table above) to compare terms quickly.
  2. Worked Examples:

    • Always tie theory to real systems. For example:
      • "How would you design a loan management system for Nabil Bank using modularity?"
      • Answer: Split into Customer, Loan, Payment modules with low coupling (modules communicate via loan_id only).
  3. Diagrams:

    • Mandatory for layered architecture, pipe-filter, and state diagrams.
    • Tip: Draw 3 layers for layered architecture and 4 filters for pipe-filter in exams.
  4. CASE Tools:

    • Know types (Upper/Lower/Integrated) and examples (Visual Paradigm, Rational Rose).
    • Tip: Mention automation (e.g., "CASE tools reduce errors by 30–50%") to justify their use.
  5. SOLID Principles:

    • Most tested principle: Single Responsibility.
    • Tip: Use real examples like NEPSE’s trading system to explain violations/fixes.
  6. Common Pitfalls:

    • Avoid: Describing coupling/cohesion without examples.
    • Do: Use Nepali apps (eSewa, Daraz, Khalti) to illustrate concepts.

Final Checklist Before Exam:

  • Can you draw layered architecture and pipe-filter diagrams?
  • Can you explain SOLID principles with a real-world fix?
  • Do you know 3 CASE tools and their uses in Nepal?
  • Can you compare cohesion types in a table?

Based on the TU BCA syllabus for Software Engineering (CACS253), unit 3.

Discussion

Loading…