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), onlyCneeds 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_idandlocation—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:
- Presentation Layer: UI (e.g., Daraz’s mobile app).
- Business Logic Layer: Rules (e.g., "Apply 10% discount if cart > Rs. 5000").
- Data Access Layer: Database queries (e.g., "Fetch user cart from MySQL").
- 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:
- Pipe: Data channel (e.g., a message queue).
- 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
- Diagram Automation: Generate UML diagrams (e.g., class diagrams for NEPSE’s trading system).
- Code Generation: Convert design models to code (e.g., Java classes from a UML diagram).
- Version Control Integration: Track changes in requirements (e.g., Pathao’s ride-pricing updates).
- 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:
- Draw a class diagram in Rational Rose.
- Generate Java/Python classes for
Customer,Loan,Payment. - 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:
Stockclass 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
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.
Daraz’s Microservices (Pipe-Filter)
- Concept: Pipe-filter architecture.
- How it works:
- Order Pipeline:
- Filter 1: Validate cart (check stock, prices).
- Filter 2: Process payment (via Khalti/Daraz Pay).
- Filter 3: Update inventory.
- Filter 4: Send confirmation email.
- Order Pipeline:
- Impact: If Daraz adds a new payment method (e.g., IME Pay), only Filter 2 changes.
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.
- Modules:
- Impact: Reduced bugs by 50% during the 2022 tariff revision.
Exam Tip
This unit is conceptual but heavily tested through:
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.
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,Paymentmodules with low coupling (modules communicate vialoan_idonly).
- Always tie theory to real systems. For example:
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.
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.
SOLID Principles:
- Most tested principle: Single Responsibility.
- Tip: Use real examples like NEPSE’s trading system to explain violations/fixes.
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…