LLD Introduction
Design Thinking
Approach to problem solving
Design Thinking is a systematic, human-centered approach to solving complex software engineering challenges. Before drawing class models or writing execution logic, you must understand the problem constraints, define entities, and build low-fidelity prototypes.
1. Learning Objectives
- Apply the five phases of Design Thinking (Empathize, Define, Ideate, Prototype, Test) to code architecture.
- Translate descriptive product specifications into class structures and system requirements.
- Validate designs using scenario-based walkthroughs before implementation.
2. Problem Statement
Most software project failures do not stem from bad coding skills, but rather from building the wrong solution.
- Without Design Thinking: Engineers jump straight to implementation. They build models without clarifying assumptions, resulting in missing functionalities and large-scale structural rework.
- With Design Thinking: Requirements are gathered, entities are mapped, and edge-cases are accounted for prior to coding.
3. Real-world Analogy
Imagine building a customized mountain bicycle. If you jump straight into welding metal tubes, you might build a bicycle that is too heavy, has the wrong gear ratio for steep climbs, or lacks suspension points.
Instead, you talk to riders (Empathize), list the constraints (Define), brainstorm shock absorber options (Ideate), draw layouts (Prototype), and test it on dirt trails (Test) before manufacturing the frame.
4. Theory
Applying Design Thinking to LLD translates into five concrete stages:
- Empathize: Gather requirements. What are the users doing? Clarify constraints (e.g. "Can a user have multiple wishlists?").
- Define: Outline the domain model. Identify entities (Nouns in specifications) and operations (Verbs in specifications).
- Ideate: Draft design alternatives. Should we use inheritance or composition? Which design patterns fit?
- Prototype: Draw UML class structures and sketch interfaces.
- Test: Write unit tests and run dry-run walkthroughs against specific scenarios.
5. Visual Diagram
This flowchart visualizes the design thinking loop applied to software design:
6. Syntax Explanation
When defining domain structures, we use Composition to represent "Has-A" relationships (e.g. a Wishlist has a collection of Product objects).
- In Java, collections are declared via
ListorSet. - In Python, we use type hinting like
List[Product]to declare relationships. - In C++, we use smart pointers
std::vector>.
7. Step-by-Step Implementation
Let's design a simple Product Catalog Wishlist based on the following requirement: *"A customer can add products to a custom wishlist and display them."*
- Step 1: Identify Nouns:
Product,Wishlist. Identify Verbs:addProduct,getProducts. - Step 2: Declare the
Productentity. - Step 3: Declare the
Wishlistclass, containing a collection ofProducts. - Step 4: Write the client code to simulate and verify this flow.
8. Complete Code
9. Code Walkthrough
In the Wishlist class, we shield the internal products list. Returning Collections.unmodifiableList(products) in Java or a copy of the list in Python/C++ blocks clients from editing the wishlist contents without going through the class's addProduct() method.
10. Execution Flow
- Create
Productinstance on the heap. - Create
Wishlistinstance on the heap. - Invoke
wishlist.addProduct(product), passing the reference pointer. - Verify addition by requesting the unmodifiable collection and asserting size.
11. Internal Working
Returning an unmodifiable wrapper in Java allocates a lightweight read-only view in the Heap that points to the original list. If a client attempts to execute .add() on this wrapper, a runtime UnsupportedOperationException is thrown, protecting internal state.
12. Complexity Analysis
- Time Complexity: $O(1)$ to append a product reference to the array list.
- Space Complexity: $O(1)$ extra space used per element.
13. Best Practices
- List constraints first: Always clarify constraints (e.g. maximum wishlist capacity) in the empathize phase.
- Return read-only collections: Protect internal lists from direct external writes.
- Write test specs: Mock client scenarios to test edge cases.
14. Common Mistakes
- Returning direct references to mutable internal lists, which bypasses class encapsulation.
- Failing to validate inputs (e.g. allowing
nullproducts to be added to the list).
15. Interview Questions
Q: How do you identify domain entities from a text-based problem statement?
Answer: Read the requirements and perform "noun-verb analysis." Nouns typically map to classes and variables, while verbs map to class methods and interactions.
16. Practice Exercises
- Easy: Add a method
removeProduct(Product product)to theWishlistclass. - Medium: Add a constraint to limit the wishlist to a maximum of 10 items. Throw an exception when exceeded.
- Hard: Build a dynamic sharing mechanism allowing users to share their wishlist with other users in read-only mode.
17. Challenge Problem
Design an encapsulated Shopping Cart class where discounts can be applied dynamically using different coupon structures.
18. Summary
- Design Thinking centers software development around user needs.
- Noun-verb analysis translates textual requirements into class blueprints.
- Encapsulated lists should be wrapped to block external writes.
19. Cheat Sheet
| Design Phase | Main Focus | Key Output |
|---|---|---|
| 1. Empathize & Define | Clarify requirements & nouns/verbs | Requirement checklist, constraints |
| 2. Ideate & Prototype | UML structures & class drafts | Class diagrams, interface skeletons |
| 3. Test | Validate code against dry-runs | Unit test execution success |
20. Quiz
1. What is the first stage in the Design Thinking loop?
A) Test
B) Empathize (Correct)
C) Prototype
2. How are class names and attributes identified from requirements?
A) Analyzing nouns in the specifications (Correct)
B) Analyzing verbs in the specifications
C) Generating random names
3. What is the benefit of returning 'Collections.unmodifiableList()' in Java?
A) It compiles the list faster at runtime
B) It prevents clients from modifying the list directly, keeping variables encapsulated (Correct)
C) It automatically encrypts the database record
4. In the mountain bike analogy, trail testing matches which software stage?
A) Empathize
B) Test (Correct)
C) Define
5. Which of the following is a sign of lack of design planning?
A) Decoupled interface wrappers
B) Tightly coupled code structures that miss user requirements (Correct)
C) Writing unit tests before implementation
6. What type of collection prevents duplicate entries?
A) List
B) Set (Correct)
C) Stack
7. What is the time complexity of adding a pointer reference to an ArrayList?
A) O(log N)
B) O(1) (Correct)
C) O(N)
8. Which exception is thrown in Java if a client tries to modify an unmodifiable list?
A) NullPointerException
B) UnsupportedOperationException (Correct)
C) ClassCastException
9. In noun-verb analysis, what do verbs typically map to?
A) Class names
B) Method names (Correct)
C) Variable types
10. Why is testing placed at the end of the design thinking loop?
A) To validate that the prototype correctly solves the defined problem (Correct)
B) It is the least important step
C) To write CSS styling files
21. Next Lesson Preview
Congratulations! You have completed the LLD Introduction module. In the next module, OOP Fundamentals, we begin with Classes and Objects to explore the core pillars of object-oriented design!