Chapter1:What Is Design and Architecture?_《clean architecture》notes

What Is Design and Architecture?

        • [Key Concepts & Challenges](#Key Concepts & Challenges)
      • [Code Demonstration: The Problem](#Code Demonstration: The Problem)
        • [Scenario: A Poorly Designed `Employee` Class](#Scenario: A Poorly Designed Employee Class)
      • [Refactored Code: Applying SRP](#Refactored Code: Applying SRP)
        • [Solution: Split Responsibilities into Separate Classes](#Solution: Split Responsibilities into Separate Classes)
      • [Why This Matters](#Why This Matters)
      • [Multiple-Choice Questions](#Multiple-Choice Questions)
      • [Answers and Explanations](#Answers and Explanations)
      • [Code Test Cases](#Code Test Cases)

Key Concepts & Challenges
  1. Core Thesis :

    Design and architecture are the same concept---both focus on structuring software to minimize human effort required for development and maintenance.

  2. Case Study Analysis :

    A system with exponentially growing costs (e.g., 40x cost increase per line of code over 8 releases) demonstrates how poor architecture leads to unmaintainable code.

  3. Architectural Goals:

    • Flexibility: Enable easy modifications.
    • Sustainability: Avoid exponential cost growth.
    • Separation of Concerns: Isolate components to reduce interdependency.

Code Demonstration: The Problem

Scenario: A Poorly Designed Employee Class

A monolithic Employee class violating the Single Responsibility Principle (SRP). It handles payroll calculations, hour reporting, and database operations---three distinct responsibilities.

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// BAD DESIGN: Monolithic class violating SRP
class Employee {
private:
    string name;
    double hoursWorked;
    double payRate;

public:
    Employee(string name, double payRate) : name(name), payRate(payRate), hoursWorked(0) {}

    void logHours(double hours) {
        hoursWorked += hours;
    }

    double calculatePay() {
        return hoursWorked * payRate;
    }

    void saveToDatabase() {
        // Simulate database save
        cout << "Saving " << name << "'s data to database." << endl;
    }
};

// Test Case
int main() {
    Employee emp("John Doe", 20.0);
    emp.logHours(40);
    cout << "Pay: $" << emp.calculatePay() << endl;  // Output: Pay: $800
    emp.saveToDatabase();  // Output: Saving John Doe's data to database.
    return 0;
}

Compile & Run:

bash 复制代码
g++ -o employee employee.cpp && ./employee

Problem:

  • Changes to payroll logic (e.g., tax calculations) require modifying the same class as database operations.
  • High risk of unintended side effects (e.g., breaking the database code while updating payroll).

Refactored Code: Applying SRP

Solution: Split Responsibilities into Separate Classes
  • PayCalculator: Handles payroll logic.
  • HourReporter: Manages hour tracking.
  • EmployeeSaver: Handles database operations.
  • Employee: Coordinates dependencies (facade pattern).
cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// GOOD DESIGN: Separate responsibilities
class PayCalculator {
public:
    static double calculatePay(double hours, double rate) {
        return hours * rate;
    }
};

class HourReporter {
private:
    double hoursWorked = 0;
public:
    void logHours(double hours) {
        hoursWorked += hours;
    }
    double getHours() const {
        return hoursWorked;
    }
};

class EmployeeSaver {
public:
    static void saveToDatabase(const string& name) {
        cout << "Saving " << name << "'s data to database." << endl;
    }
};

// Facade class to coordinate components
class Employee {
private:
    string name;
    double payRate;
    HourReporter hourReporter;

public:
    Employee(string name, double payRate) : name(name), payRate(payRate) {}

    void logHours(double hours) {
        hourReporter.logHours(hours);
    }

    double calculatePay() {
        return PayCalculator::calculatePay(hourReporter.getHours(), payRate);
    }

    void saveToDatabase() {
        EmployeeSaver::saveToDatabase(name);
    }
};

// Test Case
int main() {
    Employee emp("John Doe", 20.0);
    emp.logHours(40);
    cout << "Pay: $" << emp.calculatePay() << endl;  // Output: Pay: $800
    emp.saveToDatabase();  // Output: Saving John Doe's data to database.
    return 0;
}

Compile & Run:

bash 复制代码
g++ -o employee_refactored employee_refactored.cpp && ./employee_refactored

Benefits:

  • Changes to payroll logic do not affect database operations.
  • Each class has one reason to change (aligned with SRP).
  • Easier to test components in isolation.

Why This Matters

  1. Maintainability: Isolating components reduces the risk of cascading failures.
  2. Scalability: Adding features (e.g., tax calculations) becomes localized.
  3. Testability: Mocking dependencies (e.g., database) simplifies unit testing.

Multiple-Choice Questions


Question 1

What is the primary goal of software architecture according to Chapter 1?

A) To maximize the number of features delivered in the first release

B) To minimize the human effort required to build and maintain the system

C) To ensure the system works perfectly on the first deployment

D) To align with the latest programming paradigms


Question 2

In the case study presented, what caused the exponential growth in the cost per line of code?

A) Poorly trained developers

B) Accumulation of technical debt and architectural decay

C) Frequent changes in customer requirements

D) Hardware limitations


Question 3

Which statement best describes the relationship between "behavior" and "architecture" in software?

A) Behavior is more important than architecture.

B) Architecture ensures long-term maintainability, while behavior addresses immediate functionality.

C) Architecture is irrelevant if the system's behavior meets requirements.

D) Behavior and architecture are always in direct conflict.


Question 4

What critical insight does the "Hare and Tortoise" analogy highlight?

A) Fast development cycles guarantee long-term success.

B) Clean code and disciplined design are prerequisites for sustainable development.

C) Overconfidence in short-term speed leads to long-term failure.

D) Testing is more important than design.


Question 5

Which principle does structured programming emphasize?

A) Use of unrestricted goto statements

B) Functional decomposition into provable units

C) Object-oriented inheritance hierarchies

D) Immutable data structures


Question 6

What is the consequence of ignoring architectural quality early in a project?

A) Increased short-term productivity

B) Higher long-term maintenance costs and reduced adaptability

C) Immediate customer satisfaction

D) Simplified debugging


Question 7

Which of the following are symptoms of poor architecture? (Select all that apply)

A) Frequent merge conflicts in version control

B) High test coverage

C) Difficulty adding new features without breaking existing ones

D) Low initial development speed


Question 8

How does the chapter define "design" in the context of software?

A) The visual layout of user interfaces

B) The arrangement of code to minimize effort for future changes

C) The process of writing efficient algorithms

D) The selection of third-party libraries


Question 9

What role does "testability" play in evaluating architecture?

A) It is irrelevant to architectural quality.

B) It enforces rigid design patterns.

C) It ensures components can be validated and modified safely.

D) It prioritizes speed over correctness.


Question 10

Why does the chapter argue that "architecture" is more valuable than "behavior"?

A) Behavior can always be fixed later.

B) Architecture enables adaptability, while behavior is temporary.

C) Users care more about system structure than functionality.

D) Behavior is impossible to test.



Answers and Explanations


Question 1
Correct Answer: B
Explanation: The chapter emphasizes that the primary goal of architecture is to minimize the human effort required to build and maintain the system over its lifetime. Short-term feature delivery (A) or perfect initial behavior © are secondary to sustainable design.


Question 2
Correct Answer: B
Explanation: The case study attributes rising costs to architectural decay (technical debt), where poor design choices made early in the project led to exponential maintenance difficulties.


Question 3
Correct Answers: B, C
Explanation:

  • B: Architecture ensures long-term maintainability, while behavior addresses immediate needs.
  • C: A system with perfect behavior but no architecture becomes unmaintainable.
  • A and D are false dichotomies.

Question 4
Correct Answers: B, C
Explanation:

  • B: Clean code and discipline are prerequisites for avoiding long-term failure.
  • C: Overconfidence in speed (the "Hare") leads to failure, as seen in the case study.

Question 5
Correct Answer: B
Explanation: Structured programming focuses on breaking down problems into smaller, provable units using constructs like loops and conditionals.


Question 6
Correct Answer: B
Explanation: Ignoring architecture leads to technical debt, which increases maintenance costs and reduces the system's ability to adapt to changes.


Question 7
Correct Answers: A, C
Explanation:

  • A: Frequent merges indicate fragmented ownership of poorly structured code.
  • C: Poor architecture makes changes riskier and more time-consuming.

Question 8
Correct Answer: B
Explanation: Design is defined as structuring code to reduce future effort, aligning with the goal of sustainable architecture.


Question 9
Correct Answer: C
Explanation: Testable architectures allow components to be validated and modified safely, ensuring long-term viability.


Question 10
Correct Answer: B
Explanation: The chapter argues that architecture's value lies in enabling adaptability (e.g., handling future requirements), while behavior is transient.


Code Test Cases

Example 1: Structured Programming in C

c 复制代码
#include <stdio.h>

// Calculate squares of the first N integers
int main() {
    int n = 25;
    for (int i = 0; i < n; i++) {
        printf("%d\n", i * i);
    }
    return 0;
}

Purpose: Demonstrates structured programming using loops and avoids goto.


Example 2: Testable Function in Python

python 复制代码
def calculate_squares(n: int) -> list[int]:
    return [i*i for i in range(n)]

# Test case
def test_calculate_squares():
    assert calculate_squares(5) == [0, 1, 4, 9, 16]

if __name__ == "__main__":
    test_calculate_squares()
    print("All tests passed!")

Purpose: Emphasizes testability and modular design.


相关推荐
辰海Coding2 小时前
MiniSpring框架学习笔记-解决循环依赖的简化IoC容器
笔记·学习
杜子不疼.2 小时前
【C++ AI 大模型接入 SDK】 - DeepSeek 模型接入(上)
开发语言·c++·chatgpt
晓梦林3 小时前
cp520靶场学习笔记
android·笔记·学习
石山代码4 小时前
C++ 内存分区 堆区
java·开发语言·c++
心中有国也有家4 小时前
cann-recipes-infer:昇腾 NPU 推理的“菜谱集合”
经验分享·笔记·学习·算法
玄米乌龙茶1234 小时前
LLM成长笔记(三):API 开发基础
笔记
Upsy-Daisy4 小时前
AI Agent 项目学习笔记(八):Tool Calling 工具调用机制总览
人工智能·笔记·学习
LuminousCPP5 小时前
数据结构 - 线性表第四篇:C 语言通讯录优化升级全记录(踩坑 + 思考)
c语言·开发语言·数据结构·经验分享·笔记·学习
张小姐的猫6 小时前
【Linux】多线程 —— 线程互斥
linux·运维·服务器·c++
一只机电自动化菜鸟6 小时前
一建机电备考笔记(40) 建筑机电施工—排水管道施工(含考频+题型)
经验分享·笔记·学习·职场和发展·课程设计