KISS 原则--设计模式

越简单越好

之前的课程中,我们学习了经典的 SOLID 原则。现在,我们开始学习KISS 原则和
YAGNI 原则。其中,KISS 原则比较经典,耳熟能详,我们就从kiss原则入手。

1、理解“KISS 原则”
KISS 原则(Keep It Simple, Stupid):KISS 原则强调保持代码简单,易于理解和维
护。在编写代码时,应避免使用复杂的逻辑、算法和技术,尽量保持代码简洁明了。
这样可以提高代码的可读性、可维护性和可测试性。当然,这并不意味着要牺牲代码
的性能和功能,而是要在保证性能和功能的前提下,尽量简化代码实现。
KISS 原则算是一个万金油类型的设计原则,可以应用在很多场景中。它不仅经常用
来指导软件开发,还经常用来指导更加广泛的系统设计、产品设计等,比如,冰箱、
建筑、iPhone 手机的设计等等。
我们知道,代码的可读性和可维护性是衡量代码质量非常重要的两个标准。而 KISS
原则就是保持代码可读和可维护的重要手段。代码足够简单,也就意味着很容易读
懂,bug 比较难隐藏。即便出现 bug,修复起来也比较简单。

2、代码简单和代码行数少

冒泡排序:

public class BubbleSort {
public static void main(String[] args) {
int[] arr = {4, 2, 7, 1, 8, 5};
bubbleSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
}
// 冒泡排序算法实现
public static void bubbleSort(int[] arr) {
int n = arr.length;
// 外层循环控制遍历次数
for (int i = 0; i < n - 1; i++) {
// 内层循环用于比较相邻的元素
for (int j = 0; j < n - 1 - i; j++) {
// 如果前一个元素大于后一个元素,则交换位置
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}

快速排序:

public class QuickSort {
public static void main(String[] args) {
int[] arr = {4, 2, 7, 1, 8, 5};
quickSort(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.print(i + " ");
}
}
我们可以看到,快速排序明显比冒泡排序复杂,写多出了很多行,那么我们能说下边
的代码不符合kiss原则吗?
// 快速排序算法实现
public static void quickSort(int[] arr, int left, int right) {
if (left < right) {
// 划分数组
int pivotIndex = partition(arr, left, right);
// 分别对左右子数组进行快速排序
quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);
}
}
// 将数组划分为两部分,并返回基准元素的索引
public static int partition(int[] arr, int left, int right) {
int pivot = arr[left]; // 选择基准元素
int i = left, j = right;
while (i < j) {
// 从右向左找到一个小于基准的元素
while (i < j && arr[j] >= pivot) {
j--;
}
// 从左向右找到一个大于基准的元素
while (i < j && arr[i] <= pivot) {
i++;
}
// 交换两个元素的位置
if (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
// 将基准元素和指针相遇位置的元素交换
arr[left] = arr[i];
arr[i] = pivot;
return i;
}
}

在这里面我们不得不去说一下这个造轮子的相关的观点

对于我们去实现比如说类似于冒泡排序快速排序的相关的方法

我们不应该自己去进行相关的动手去实现的

而且我们应该去调用原本在Java之中的相关的库,这样也会去减少我们在编写程序的时候,减少程序出现相关的bug的可能

我们将以一个简单的电影票系统为例子,进行两次迭代,以满足KISS原则。在该场景
中,我们需要为不同类型的用户(如普通用户、学生、会员等)提供不同的票价折
扣。
版本1(不满足KISS原则):

1(不满足KISS原则):
版本2(经过第一次迭代):
public class MovieTicketSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户类型(1.普通用户 2.学生 3.会员):");
int userType = scanner.nextInt();
System.out.println("请输入原票价:");
double originalPrice = scanner.nextDouble();
double discountedPrice;
if (userType == 1) {
discountedPrice = originalPrice;
} else if (userType == 2) {
discountedPrice = originalPrice * 0.8;
} else if (userType == 3) {
discountedPrice = originalPrice * 0.5;
} else {
System.out.println("输入错误!");
return;
}
System.out.println("折扣后的票价为:" + discountedPrice);
}
}
public class MovieTicketSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户类型(1.普通用户 2.学生 3.会员):");
int userType = scanner.nextInt();
System.out.println("请输入原票价:");
double originalPrice = scanner.nextDouble();
double discountedPrice = getDiscountedPrice(userType, originalPrice);
if (discountedPrice < 0) {
在第一次迭代中,我们将计算折扣价格的逻辑提取到一个新的方法
getDiscountedPrice 中,使 main 方法更加简洁。同时,我们使用 switch 语句
代替 if-else 语句来处理不同用户类型的折扣计算,使得代码更加清晰易读。
版本3(经过第二次迭代,满足KISS原则):
System.out.println("输入错误!");
} else {
System.out.println("折扣后的票价为:" + discountedPrice);
}
}
public static double getDiscountedPrice(int userType, double originalPrice) {
switch (userType) {
case 1:
return originalPrice;
case 2:
return originalPrice * 0.8;
case 3:
return originalPrice * 0.5;
default:
return -1;
}
}
}
public class MovieTicketSystem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int userType = getUserType(scanner);
double originalPrice = getOriginalPrice(scanner);
double discountedPrice = getDiscountedPrice(userType, originalPrice);
if (discountedPrice < 0) {
System.out.println("输入错误!");
} else {
System.out.println("折扣后的票价为:" + discountedPrice);
}
}
public static int getUserType(Scanner scanner) {
System.out.println("请输入用户类型(1.普通用户 2.学生 3.会员):");
经过两次迭代,我们将原始代码的不同功能部分进行了拆分和重构,使得整个程序的
结构更加清晰和简洁,易于理解和维护。这就是遵循KISS原则的一个典型例子。
3、代码逻辑复杂就违背 KISS 原则吗?
并非所有的复杂代码逻辑都违背了KISS原则。KISS原则强调的是保持代码简洁、易于
理解和维护。有时候,为了实现某个功能,确实需要一定程度的复杂逻辑。关键在于
如何尽可能地让代码简单和清晰。
遵循KISS原则的复杂代码应当具备以下特点:
1. 模块化:将复杂的代码逻辑拆分成多个简单、独立的模块,每个模块负责一个特
定的功能。这有助于降低代码的复杂度,提高代码的可读性和可维护性。
2. 清晰的命名:为变量、方法、类等使用清晰、有意义的命名,以便于其他人(或
未来的你)阅读和理解代码。
3. 注释和文档:为复杂的代码逻辑编写清晰、详细的注释和文档,解释代码的作用
和实现原理。这有助于其他人(或未来的你)更容易地理解和维护代码。
4. 避免不必要的复杂度:尽量避免引入不必要的复杂性,如使用过于复杂的算法或
数据结构。在实现功能的同时,要考虑代码的简洁性和可读性。
return scanner.nextInt();
}
public static double getOriginalPrice(Scanner scanner) {
System.out.println("请输入原票价:");
return scanner.nextDouble();
}
public static double getDiscountedPrice(int userType, double originalPrice) {
switch (userType) {
case 1:
return originalPrice;
case 2:
return originalPrice * 0.8;
case 3:
return originalPrice * 0.5;
default:
return -1;
}
}
}

3、代码逻辑复杂就违背 KISS 原则吗?
并非所有的复杂代码逻辑都违背了KISS原则。KISS原则强调的是保持代码简洁、易于
理解和维护。有时候,为了实现某个功能,确实需要一定程度的复杂逻辑。关键在于
如何尽可能地让代码简单和清晰。
遵循KISS原则的复杂代码应当具备以下特点:
1. 模块化:将复杂的代码逻辑拆分成多个简单、独立的模块,每个模块负责一个特
定的功能。这有助于降低代码的复杂度,提高代码的可读性和可维护性。
2. 清晰的命名:为变量、方法、类等使用清晰、有意义的命名,以便于其他人(或
未来的你)阅读和理解代码。
3. 注释和文档:为复杂的代码逻辑编写清晰、详细的注释和文档,解释代码的作用
和实现原理。这有助于其他人(或未来的你)更容易地理解和维护代码。
4. 避免不必要的复杂度:尽量避免引入不必要的复杂性,如使用过于复杂的算法或
数据结构。在实现功能的同时,要考虑代码的简洁性和可读性。

总之,遵循KISS原则并不意味着代码必须简单到极致。相反,它鼓励我们在实现功能
的同时,尽量保持代码的简洁、易于理解和维护。一个良好的开发者应当在实际项目
中找到适当的平衡点,既满足功能需求,又不过分增加代码的复杂度。


4、如何写出满足 KISS 原则的代码?
实际上,我们前面已经讲到了一些方法。这里我稍微总结一下。
不要使用同事可能不懂的技术来实现代码。比如前面例子中的正则表达式,还有
一些编程语言中过于高级的语法等。
不要重复造轮子,要善于使用已经有的工具类库。经验证明,自己去实现这些类
库,出 bug 的概率会更高,维护的成本也比较高。
不要过度优化。不要过度使用一些奇技淫巧(比如,位运算代替算术运算、复杂
的条件语句代替 if-else、使用一些过于底层的函数等)来优化代码,牺牲代码的
可读性。
实际上,代码是否足够简单是一个挺主观的评判。同样的代码,有的人觉得简单,有
的人觉得不够简单。而往往自己编写的代码,自己都会觉得够简单。所以,评判代码
是否简单,还有一个很有效的间接方法,那就是 code review。如果在 code review
的时候,同事对你的代码有很多疑问,那就说明你的代码有可能不够“简单”,需要优
化啦。
小问题:你怎么看待在开发中重复造轮子这件事情?什么时候要重复造轮子?什么时
候应该使用现成的工具类库、开源框架?

重复造轮子有时可以帮助深入理解问题,掌握核心概念,或满足特定需求,但也可能浪费资源和时间。通常,如果现有工具或库已经成熟、稳定、符合需求且维护良好,优先使用它们是更有效的选择。只有当现有解决方案不满足特定需求,或者在学习过程中需要从基础开始构建时,才应考虑重复造轮子。

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值