架构设计原则:SOLID 与 KISS

核心要点

  • SOLID 原则:单一职责、开闭原则、里氏替换、接口隔离、依赖倒置
  • KISS 原则:保持简单
  • DRY 原则:不要重复自己
  • YAGNI 原则:不要过度设计
  • 架构模式:分层架构、微服务、事件驱动
  • 实际案例:应用设计原则重构代码

上周帮朋友看了他写的一个项目代码,差点没把我气笑。

一个简单的用户管理系统,写成了一团乱麻。用户信息验证、数据库操作、邮件发送、日志记录,所有逻辑都堆在一个类里,几百行代码下来,连他自己都找不到某个功能在哪里。

这就是典型的架构设计原则缺失的结果。今天就聊聊两个最基础但最重要的架构设计原则:SOLID 和 KISS。

什么是 SOLID 原则?

SOLID 是五个设计原则的首字母缩写:

单一职责原则 (SRP)

一个类应该只有一个引起变化的原因。

比如用户管理系统中,用户信息验证、数据库操作、邮件发送、日志记录应该分开成不同的类。这样如果需要修改验证逻辑,只会影响验证类,不会影响其他功能。

开闭原则 (OCP)

软件实体应该对扩展开放,对修改关闭。

意思是当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改现有代码。比如需要添加新的用户验证方式,可以继承现有的验证类,而不是修改原有的验证方法。

里氏替换原则 (LSP)

子类应该能够替换父类而不改变程序的正确性。

比如一个鸟类抽象类有一个“飞”的方法,那么子类麻雀、老鹰都应该实现这个方法。但如果子类是企鹅,那么就不应该实现“飞”的方法,因为企鹅不会飞。这时候需要重新设计抽象类。

接口隔离原则 (ISP)

客户端不应该被迫依赖它不需要的接口。

意思是接口应该尽可能小,只包含客户端需要的方法。比如一个打印机接口,不应该包含扫描、复印等方法,因为有些打印机只支持打印功能。

依赖倒置原则 (DIP)

高层模块不应该依赖低层模块,二者都应该依赖抽象。

抽象不应该依赖细节,细节应该依赖抽象。比如高层模块的业务逻辑不应该直接依赖低层模块的数据库操作,而是应该依赖一个抽象的数据访问接口。

什么是 KISS 原则?

KISS 原则是“Keep It Simple, Stupid”的缩写,意思是保持简单。

软件开发中,简单的方案往往比复杂的方案更有效。复杂的方案可能会带来更多的问题,比如维护困难、性能下降、调试复杂等。

比如,有些开发者喜欢使用复杂的设计模式,即使简单的方案就能解决问题。这样不仅会增加开发时间,还会让代码难以理解和维护。

其他重要原则

除了 SOLID 和 KISS 原则,还有一些其他重要的设计原则:

DRY 原则

DRY 原则是“Don’t Repeat Yourself”的缩写,意思是不要重复自己。

软件开发中,相同的代码不应该重复出现。如果发现有重复的代码,应该将其提取到一个公共的方法或类中。这样不仅可以减少代码量,还可以提高代码的可维护性。

YAGNI 原则

YAGNI 原则是“You Aren’t Gonna Need It”的缩写,意思是不要过度设计。

软件开发中,不要添加不需要的功能。有些开发者喜欢提前预测未来的需求,添加一些可能永远不会用到的功能。这样不仅会增加开发时间,还会让代码变得复杂。

实际案例:应用设计原则重构代码

让我用朋友的用户管理系统作为例子,展示如何应用设计原则重构代码。

重构前的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class UserManager:
def __init__(self):
self.db = Database()
self.mailer = Mailer()
self.logger = Logger()

def register_user(self, username, password, email):
# 验证用户信息
if len(username) < 3:
raise Exception("用户名长度不能少于3个字符")
if len(password) < 6:
raise Exception("密码长度不能少于6个字符")
if "@" not in email:
raise Exception("邮箱格式不正确")

# 保存到数据库
user = {"username": username, "password": password, "email": email}
self.db.save(user)

# 发送欢迎邮件
self.mailer.send_welcome_email(email)

# 记录日志
self.logger.log(f"用户注册成功:{username}")

def login_user(self, username, password):
# 查询用户
user = self.db.find({"username": username})
if not user:
raise Exception("用户不存在")

# 验证密码
if user["password"] != password:
raise Exception("密码错误")

# 记录日志
self.logger.log(f"用户登录成功:{username}")

def reset_password(self, username, email):
# 查询用户
user = self.db.find({"username": username, "email": email})
if not user:
raise Exception("用户不存在")

# 生成新密码
new_password = self.generate_random_password()

# 更新数据库
user["password"] = new_password
self.db.update(user)

# 发送密码重置邮件
self.mailer.send_reset_password_email(email, new_password)

# 记录日志
self.logger.log(f"密码重置成功:{username}")

def generate_random_password(self):
import random
import string
return ''.join(random.choices(string.ascii_letters + string.digits, k=8))

重构后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# 用户信息验证
class UserValidator:
@staticmethod
def validate_username(username):
if len(username) < 3:
raise Exception("用户名长度不能少于3个字符")

@staticmethod
def validate_password(password):
if len(password) < 6:
raise Exception("密码长度不能少于6个字符")

@staticmethod
def validate_email(email):
if "@" not in email:
raise Exception("邮箱格式不正确")

@staticmethod
def validate_register_info(username, password, email):
UserValidator.validate_username(username)
UserValidator.validate_password(password)
UserValidator.validate_email(email)

# 数据库操作
class UserRepository:
def __init__(self, db):
self.db = db

def save_user(self, user):
self.db.save(user)

def find_user_by_username(self, username):
return self.db.find({"username": username})

def find_user_by_username_and_email(self, username, email):
return self.db.find({"username": username, "email": email})

def update_user(self, user):
self.db.update(user)

# 邮件发送
class UserMailer:
def __init__(self, mailer):
self.mailer = mailer

def send_welcome_email(self, email):
self.mailer.send_welcome_email(email)

def send_reset_password_email(self, email, new_password):
self.mailer.send_reset_password_email(email, new_password)

# 日志记录
class UserLogger:
def __init__(self, logger):
self.logger = logger

def log_register_success(self, username):
self.logger.log(f"用户注册成功:{username}")

def log_login_success(self, username):
self.logger.log(f"用户登录成功:{username}")

def log_reset_password_success(self, username):
self.logger.log(f"密码重置成功:{username}")

# 密码生成
class PasswordGenerator:
@staticmethod
def generate_random_password():
import random
import string
return ''.join(random.choices(string.ascii_letters + string.digits, k=8))

# 业务逻辑
class UserManager:
def __init__(self, validator, repository, mailer, logger, password_generator):
self.validator = validator
self.repository = repository
self.mailer = mailer
self.logger = logger
self.password_generator = password_generator

def register_user(self, username, password, email):
# 验证用户信息
self.validator.validate_register_info(username, password, email)

# 保存到数据库
user = {"username": username, "password": password, "email": email}
self.repository.save_user(user)

# 发送欢迎邮件
self.mailer.send_welcome_email(email)

# 记录日志
self.logger.log_register_success(username)

def login_user(self, username, password):
# 查询用户
user = self.repository.find_user_by_username(username)
if not user:
raise Exception("用户不存在")

# 验证密码
if user["password"] != password:
raise Exception("密码错误")

# 记录日志
self.logger.log_login_success(username)

def reset_password(self, username, email):
# 查询用户
user = self.repository.find_user_by_username_and_email(username, email)
if not user:
raise Exception("用户不存在")

# 生成新密码
new_password = self.password_generator.generate_random_password()

# 更新数据库
user["password"] = new_password
self.repository.update_user(user)

# 发送密码重置邮件
self.mailer.send_reset_password_email(email, new_password)

# 记录日志
self.logger.log_reset_password_success(username)

重构结果分析

重构后的代码更加清晰、易于维护。每个类都有明确的职责,逻辑分离,符合 SOLID 原则。同时,代码也变得更加简单,符合 KISS 原则。

架构模式

除了设计原则,架构模式也是软件开发中的重要概念。常见的架构模式包括:

分层架构

分层架构将系统分为多个层次,每个层次负责不同的功能。常见的层次包括:

  • 表现层:负责与用户交互
  • 业务逻辑层:负责处理业务逻辑
  • 数据访问层:负责与数据库交互
  • 数据存储层:负责数据存储

微服务架构

微服务架构将系统拆分为多个小型服务,每个服务负责一个特定的功能。服务之间通过 API 进行通信。

事件驱动架构

事件驱动架构通过事件来驱动系统的行为。当某个事件发生时,系统会根据事件类型执行相应的操作。

总结

架构设计原则是软件开发中的重要概念,它们可以帮助开发者设计出可维护、可扩展的系统。SOLID 和 KISS 原则是最基础但最重要的设计原则,其他原则如 DRY 和 YAGNI 原则也同样重要。

在实际开发中,我们应该根据系统的需求和特点选择合适的架构模式,并应用相应的设计原则。这样可以提高代码的质量,降低维护成本,提高开发效率。

朋友的项目经过重构后,代码变得更加清晰、易于维护。他说现在修改功能时,再也不用像之前那样在几百行代码中找来找去了。

这就是架构设计原则的力量。