软件设计原则 KISS、YAGNI、DRY
flyfish
设计模式、设计原则与编程惯用法综述
图片来源SpaceX
简约至极的猛禽3(Raptor 3)火箭发动机
一、KISS (Keep It Simple, Stupid!, 保持简单)
KISS原则,即“Keep it simple, stupid!”(保持简单,傻瓜!)是一个设计原则。
在软件开发中,KISS 原则是“Keep It Simple, Stupid ”的缩写,意思是“保持简单,笨蛋”。
设计和实现应追求简单,而不是为了增加功能而使系统复杂化。简单的系统通常更易于维护和调试。
避免引入不必要的复杂逻辑和功能,聚焦于当前需求。复杂度的增加会导致更高的错误风险和维护成本。
代码和系统设计应清晰易懂,以便其他开发人员或将来的自己能够轻松理解和修改。
简单的设计通常意味着更少的依赖关系和更清晰的结构,使得系统更容易维护和扩展。
可以实践的方法
在开发过程中,优先实现产品的核心功能,而不是一次性加入所有可能的功能。随着用户反馈的到来,逐步迭代和增加新功能。
使用模块化的方法来设计系统,使得每个模块只负责一个单一的功能,模块之间的依赖关系尽量简单明了。
在设计阶段,应关注实际需求,避免为解决潜在的或未来的假想问题而过度设计系统。
在编码时,采用清晰、直接的编码风格,避免使用不必要的复杂语言特性和技巧
一些极简主义概念
这一原则可能源于类似的一些极简主义概念,例如:
奥卡姆剃刀原理;
“简约即是极致的精致”;
“简洁是智慧的灵魂”;
“少即是多”;
“让简单的任务变得简单!”;
“一个作者若制造出比实际需要更多的文字,那么他就是在给读者制造麻烦。”
“足球很简单,但简单地踢球却是最难的事情。”
“完美不在于无物可增,而在于无物可减。”
“先简化,再减轻重量”。
“尽可能使一切变得简单,但不要过于简单。”
“简化、简化、简化”
“扩张意味着复杂化,而复杂化意味着衰败;或者更直白地说——越复杂,死得越快。”
二、YAGNI(You Aren’t Gonna Need It, 你不需要它)
Gonna是一个非标准的英语口语缩写词,它来源于 “going to”,意为 “将要” 或 “打算”
YAGNI(You Aren’t Gonna Need It,即“你不需要它”)是一种软件开发原则,鼓励开发人员避免在系统中添加未明确需要的功能。其核心思想是避免过早添加不必要的功能,以免增加系统的复杂性、延长开发时间以及可能引入更多的错误。YAGNI原则来源于极限编程(Extreme Programming)。
为什么开发者应该遵循 YAGNI 原则
通过只实现当前需要的功能,开发人员可以避免浪费时间和资源,进而提高开发效率、减少复杂性并提高代码的可维护性。
全是成本原因
构建不必要的功能会消耗时间、精力和资源,包括计划、编码和测试。如果这些功能最终被证明是不需要的,那开发成本就成了浪费。
开发不必要的功能会占用时间,从而延迟更重要功能的实现,导致错失商业机会或其他收益。
不必要的功能会增加软件的复杂性,给后续开发和维护带来额外的负担。
添加多余的功能可能会引入错误或糟糕的设计决策,后期的修复和调整会产生额外的时间和资源成本。
可以实践的方法
获取必要需求:明确项目需要的功能,将其分类为“必须有的”和“可以等待的”,专注于当前所需。
与团队讨论:与团队分享计划和目标,确保大家步调一致。
制定简单计划:将大目标分解为小任务,保持计划的简单性。
拒绝不合适的功能:面对新的功能请求,除非是很小的改进,否则要学会说“不”,以免偏离重点。
记录进度:保持对项目进度的记录,帮助追踪和验证项目方向的正确性。
三、DRY(Don’t Repeat Yourself, 不重复自己)
为什么要遵循 DRY 原则
DRY(Don’t Repeat Yourself)原则 是软件开发中重要的设计理念,旨在通过减少代码的重复,提高软件的效率和可维护性。
1 如果代码在不同地方多次出现,一旦需要修改,就必须在所有地方都进行修改,否则容易导致不一致和错误。将重复的代码提取成一个函数或模块,只需在一个地方进行修改即可,减少出错的可能性。
2 代码中的重复部分少了,维护起来就更容易,修改代码时不需要担心遗漏某个重复的地方。没有重复的代码,逻辑更加清晰,开发者能够更容易地理解和更新代码。
3 精简的代码更容易阅读和理解,其他开发者能够快速掌握代码的功能和目的。通过模块化设计消除重复代码,逻辑层次更加分明。
4 将通用的功能提取成模块,可以在多个项目中重复使用,节省开发时间。
不需要为类似的功能编写多段代码,可以复用已经写好的模块。
可以实践的方法
实践 DRY(Don’t Repeat Yourself)原则主要涉及在软件开发过程中识别和消除代码的重复。
1. 抽取公共代码
函数/方法提取 :将重复出现的代码块提取到单独的函数或方法中。这样,如果需要修改这段逻辑,只需在一个地方进行更改。
# Before DRY
result1 = a + b + c
result2 = d + e + f
# After DRY
def add_three_numbers(x, y, z):
return x + y + z
result1 = add_three_numbers(a, b, c)
result2 = add_three_numbers(d, e, f)
2. 使用模块和类
模块化设计 :将相关的功能封装到模块中,方便在不同项目中复用。
面向对象编程 :通过类和对象来封装数据和行为,将相似的逻辑集中到一个类中。
# Before DRY
def calculate_area_circle(radius):
return 3.14 * radius * radius
def calculate_circumference_circle(radius):
return 2 * 3.14 * radius
# After DRY
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius * self.radius
def circumference(self):
return 2 * 3.14 * self.radius
3. 参数化配置
使用参数化 :通过参数化来消除硬编码的重复代码,使得代码更加灵活和可配置。
# Before DRY
def greet_user_english():
print("Hello!")
def greet_user_spanish():
print("¡Hola!")
# After DRY
def greet_user(language):
greetings = {
'english': "Hello!",
'spanish': "¡Hola!"
}
print(greetings.get(language, "Hello!"))
等等例子
其他的包括使用库和工具,利用现有的库和工具来减少重复开发。通过定期的代码审查,识别和消除代码重复。
在开发过程中,持续关注代码的重复,及时进行重构,以保持代码的简洁和高效。
在生成重复性的文档、代码块或 UI 组件时使用模板,避免重复劳动等等