架构原则概述:高内聚低耦合、关注点分离、DRY原则、KISS原则、YAGNI原则

聊到架构原则,我脑子里第一个蹦出来的词就是「内聚与耦合」。这两个词,说白了就是衡量代码质量的一把尺。你想想看,一个模块内部的东西是不是都围绕同一件事?模块之间是不是尽量少说话?这就是高内聚、低耦合的核心。

高内聚与低耦合

高内聚,指的是一个模块内部的元素之间关联紧密,共同完成一个明确的功能。低耦合,指的是模块之间的依赖关系尽量弱,一个模块的变化对其它模块的影响尽可能小。

我在项目中遇到过这样一个场景:一个订单模块里混了用户登录校验、商品库存查询、支付回调处理。结果每次改支付逻辑,都要重新测试整个订单模块。这就是典型的内聚不够。后来我把支付逻辑抽出去,订单模块只负责订单状态流转,问题就解决了。

核心要点:

  • 高内聚:模块内部职责单一,改动集中在一个小范围内
  • 低耦合:模块之间通过接口通信,不直接依赖内部实现

举个例子,一个用户服务模块,它只负责用户的注册、登录、信息查询。它不应该知道订单模块怎么处理支付。这就是高内聚。如果用户服务直接调用了订单服务的数据库表,那就是耦合过紧。

// 高内聚示例
class UserService {
    public function getUserById($id) {
        // 只做用户查询
        return $this->userRepository->find($id);
    }
}

// 低耦合示例
class OrderService {
    private $userService;
    
    public function __construct(UserService $userService) {
        $this->userService = $userService; // 依赖接口,不依赖具体实现
    }
    
    public function createOrder($userId, $productId) {
        $user = $this->userService->getUserById($userId);
        // 创建订单逻辑
    }
}

我的经验:判断内聚够不够,有个简单方法:如果你改一个功能需要改三个以上的文件,那大概率内聚出了问题。

关注点分离

关注点分离,英文叫 Separation of Concerns。说白了,就是把不同的事情交给不同的模块去处理。你写代码的时候,不要在一个函数里既处理业务逻辑,又处理数据库操作,还处理界面渲染。

我记得有一次接手一个老项目,一个控制器方法有 300 多行,里面混杂着 SQL 查询、HTML 拼接、权限校验。改一个需求,要翻半天才能找到对应的代码。这就是典型的关注点没有分离。

关注点分离的好处很明显:

  • 每个模块只关心自己的事,逻辑清晰
  • 修改一个关注点,不影响其它关注点
  • 便于单元测试,每个模块可以独立测试

常见的实现方式就是分层架构:表现层、业务层、数据访问层。每一层只处理自己该处理的事。

注意:关注点分离不是越细越好。我曾经见过一个项目分了 8 层,结果每层之间传递数据要写一堆转换代码,反而增加了复杂度。适度分离,够用就好。

DRY 原则

DRY 是 Don't Repeat Yourself 的缩写。意思就是不要重复你自己。这个原则听起来简单,但实际做起来并不容易。

我见过很多代码里,同样的校验逻辑在三个地方各写了一遍。后来需求变了,改了一个地方,另外两个没改,线上就出了 bug。这就是重复代码的代价。

DRY 原则的核心是:每一段知识在系统中只应该有一个权威的表示。也就是说,同样的逻辑,只写一次,然后复用。

// 违反 DRY 原则
function validateEmail1($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

function validateEmail2($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

// 符合 DRY 原则
function validateEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL);
}

避坑指南:我曾经为了追求 DRY,把两个看似相同但实际语义不同的逻辑强行合并成一个函数。结果后来需求分化,那个函数变得臃肿不堪。DRY 的前提是「同一件事」,而不是「看起来像」。

KISS 原则

KISS 是 Keep It Simple, Stupid 的缩写。翻译过来就是「保持简单,傻瓜」。这个原则强调:简单是软件设计的最高追求。

你想想看,一个复杂的系统,维护成本高、出 bug 的概率大、新人上手慢。而简单的系统,一眼就能看懂,改起来也放心。

我见过太多过度设计的案例了。一个简单的 CRUD 系统,非要引入事件驱动、CQRS、领域事件。结果项目延期,代码没人能看懂。其实很多时候,一个简单的 MVC 就够了。

KISS 原则的实践建议:

  • 能用数组解决的问题,不要引入对象
  • 能用 if-else 解决的问题,不要引入设计模式
  • 能用单表解决的问题,不要引入分库分表

我的观点:简单不是简陋,而是恰到好处。一个简单的系统,应该能清晰地表达它的意图,而不是让读者去猜。

YAGNI 原则

YAGNI 是 You Aren't Gonna Need It 的缩写。意思是「你其实不需要它」。这个原则告诉我们:只实现当前需要的功能,不要为未来可能需要的功能提前设计。

为什么?因为未来的需求很可能和你想的不一样。你花了两周时间设计了一个通用的扩展框架,结果需求来了,你的框架根本用不上,还得重写。

我曾经在一个项目中,提前设计了一个「万能配置中心」,支持多种数据源、多种格式、多种缓存策略。结果项目上线一年,只用到了最简单的 JSON 文件配置。那套复杂的框架,成了没人敢动的遗留代码。

警告:YAGNI 不是让你不做设计。合理的架构设计是必要的,但不要为「可能」的需求过度设计。记住:你不需要为永远不会来的需求买单。

知识体系总览

下面这张图,我把这五个原则的关系梳理了一下。你可以看到,它们其实是从不同角度在追求同一个目标:让代码更容易理解、更容易修改、更容易维护。

架构原则核心体系 高内聚低耦合 模块内部紧密,模块间松散 关注点分离 各司其职,互不干扰 DRY 原则 不重复自己 KISS 原则 保持简单 YAGNI 原则 不需要就别做 共同目标:可维护、可扩展、可理解的代码

这五个原则,其实是一个整体。高内聚低耦合是结构上的要求,关注点分离是职责上的划分,DRY 是避免重复,KISS 是控制复杂度,YAGNI 是防止过度设计。它们互相补充,缺一不可。

在实际项目中,我建议你从 KISS 和 YAGNI 入手。先把当前需求做简单,不要想太多。然后逐步引入关注点分离和高内聚低耦合。DRY 原则则贯穿始终,时刻提醒自己不要写重复代码。

总结一下:

  • 高内聚低耦合:模块内部紧,模块间松
  • 关注点分离:不同的事交给不同的模块
  • DRY:同样的逻辑只写一次
  • KISS:简单是最高级的复杂
  • YAGNI:不为未来不确定的需求买单

嗯,这些原则说起来简单,但真正用好需要大量的实践。我建议你在写每一行代码之前,都问自己一句:这个设计够简单吗?这个逻辑有没有重复?这个模块的职责是不是太杂了?慢慢养成习惯,你的代码质量会有质的提升。

公众号:蓝海资料掘金营,微信deep3321