KISS在移动开发中——什么是它,简单性原则以及如何应用它

作者: IT Sectr 发布日期: 2026-05-12 阅读时间: 8 分钟

KISS (Keep It Simple, Stupid) — 要求系统最大简单性的开发原则。复杂性只应在绝对必要时添加,而不是提前添加。根据 IEEE Transactions on Software Engineering (2020) 的研究,代码复杂性与缺陷密度相关:高圈复杂度的模块每千行代码包含的bug数量是低复杂度模块的3.6倍。KISS — 不是原始性,而是有意识地选择最简单的可行方案。

要点

  • KISS — 简单性原则:满足需求的最简单解决方案优于复杂方案。
  • 过度工程化(过度复杂) — KISS的主要敌人:为未来准备的抽象使代码复杂化而没有益处。
  • 简单代码更容易阅读、测试和维护 — 降低了项目的拥有成本。
  • 圈复杂度 — 显示代码中独立路径数量的度量;其增长与缺陷数量直接相关。
  • 重构向简单性 — 逆向过程:不是复杂化,而是在理解需求的过程中简化架构。

什么是KISS?

KISS (Keep It Simple, Stupid) — 要求最小化系统复杂性的设计原则。由工程师Kelly Johnson(洛克希德SR-71黑鸟)在20世纪60年代的美国海军中提出。约翰逊要求飞机能够在野外条件下由机械师无需特殊工具进行维修 — 这就是KISS的本质。

在软件开发中,KISS意味着:解决方案应尽可能简单,但不能更简单(这句话的后半部分归功于阿尔伯特·爱因斯坦)。简单性 — 不是原始性的同义词;简单的解决方案以最小的冗余执行任务。

Google Research (2022) 的研究表明:新开发人员进入项目的平均时间在遵循KISS的项目中为3周,而在架构过度的项目中为10周。简单代码 — 是对新团队成员适应速度的投资。

将KISS作为过滤器应用:在添加新的抽象之前,问自己“it是否解决了今天出现的问题还是一年后可能出现的问题?”如果是后者 — 不要做。

KISS与奥卡姆剃刀原则

奥卡姆剃刀(14世纪) — 哲学原则:“如无必要,勿增实体”。在编程中这意味着:从两个同样满足需求的解决方案中,选择实体(类、模块、依赖项)较少的一个。KISS — 奥卡姆剃刀在代码中的实际实现。

区别在于奥卡姆剃刀是一般的认知原则,而KISS是具有可衡量结果的具体工程实践:降低圈复杂度、减少代码行数、缩短代码审查时间。度量指标可以客观评估KISS的遵守情况。

遵循度量标准:如果新开发人员在一分钟内无需注释就能理解代码片段,则认为代码“足够简单”。如果需要更多时间 — 请简化。

为什么简单性在移动开发中至关重要?

移动开发具有三个使KISS特别重要的特点:有限的设备资源(内存、处理器)、频繁的平台更新(iOS每年、Android每季度)以及通过CI/CD快速交付功能的需求。复杂的代码无法承受这种节奏。

Apple WWDC 2023: “Embrace Swift Generics” 的分析显示:平均每个iOS项目包含40–60%“死代码” — 为未来编写但从未使用的抽象。这些代码不仅增加了二进制文件的大小,还减慢了编译速度并增加了导航难度。KISS防止了这种情况:只编写现在需要的内容。

根据 Android Developer Relations Report (2024),代码与测试比率低(低于1:0.8)的项目生产性bug增加了67%。复杂的代码更难测试 — 这是对质量的直接威胁。简单性 — 高测试覆盖率的必要条件。

通过度量指标衡量代码的复杂性:圈复杂度(Cyclomatic Complexity) — 保持每个方法在10以下,理想情况下为5以下。使用Detekt(Android)或SwiftLint(iOS)进行自动检查。

KISS vs 过度工程化:实践示例

过度架构:过多的层次

典型的过度工程化 — 在只有一个数据源的项目中创建 抽象仓库工厂。开发人员不是使用简单的Repository类,而是构建一个链条:RepositoryFactory → IRepository → BaseRepository → RepositoryImpl — 为了假设的API更换为GraphQL。

根据 JetBrains Developer Survey (2023) 的调查,43%的Android开发人员承认在重构时至少丢弃过一次架构层,因为它没有被使用。KISS说:当第二种实现出现时再创建抽象,而不是提前预防。

从没有接口的具体实现开始。当第二个数据源出现时 — 通过重构提取接口(IDE会自动完成)。这比提前编写接口更快。

过于复杂的依赖注入图

DI框架(Dagger, Hilt, Swinject) — 强大的工具,但常常引发复杂化。开发人员为每个实体创建单独的模块,即使它只在单个地方使用。KISS替代方案:对于简单情况,通过构造函数进行手动注入。

kotlin
// 过度工程化:为单一仓库创建的模块
@Module
object UserModule {
    @Provides
    fun provideUserRepo(): UserRepository = UserRepositoryImpl()
}

// KISS:手动注入,如果只有一个仓库
class UserViewModel(
    private val repo: UserRepository = UserRepositoryImpl()
) { /* ... */ }

构造函数中的手动注入 — 最简单的DI模式。不需要代码生成、注解或模块。切换到DI框架只有当项目达到5个以上屏幕且手动注入变得难以维护时。

如何在Android和iOS中应用KISS?

Android中的KISS:简单的ViewModel和LiveData

Android ViewModel — 过度复杂性的常见来源。开发人员在简单的MutableLiveData配合postValue就足够的地方添加StateFlow、combine、flatMapLatest和转换链。KISS建议:从最简单的解决方案开始(LiveData),仅为特定任务复杂化(状态重置、防抖)。

kotlin
// KISS:没有响应式链的简单ViewModel
class ProfileViewModel : ViewModel() {
    private val _name = MutableLiveData<String>()
    val name: LiveData<String> = _name

    fun loadUser(id: String) {
        viewModelScope.launch {
            _name.postValue(repo.getUser(id).name)
        }
    }
}

在这个示例中,ViewModel使用协程进行异步请求,LiveData用于发布结果。没有StateFlow,没有combine — 只有真正需要的内容。添加StateFlow当需要具有显式状态的单向数据流(UDF)时。

iOS中的KISS:使用结构体代替类

iOS中,KISS原则体现在数据模型优先选择结构体(struct)而非类(class)。结构体是值类型,不需要通过ARC进行内存管理,默认不可变。类仅在需要标识(两个引用指向同一对象)或继承时才合理。

swift
// KISS:为模型使用struct而不是class
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

// 过度工程化:带有手动init和deinit的class
class UserClass: NSObject {
    let id: Int
    init(id: Int) { self.id = id }
}

User结构体自动获得memberwise初始化、Equatable和Hashable支持(所有字段)、不可变性和多线程环境中的安全性。类需要手动初始化、NSObject实现,并且容易通过共享状态出现竞态条件。

网络层的简单性

网络层 — 另一个经常违反KISS的领域。开发人员添加包含5个以上元素的拦截器链、通过抽象工厂进行序列化以及每个端点的映射器。KISS解决方案:一个带配置的URLSession和一个通过Codable/JSON的解码。

根据 Apple: URLSession Programming Guide (2023) 的建议,基于URLSession和Codable的简单网络层覆盖了95%的移动应用程序场景。复杂的拦截器链仅用于特定情况:令牌刷新、日志记录、加密。

从基于URLSession + Codable的简单网络层开始。根据实际需求添加拦截器,而不是提前准备。这样可以将网络层的代码减少2–3倍。

遵循KISS时的常见错误

混淆简单性和原始性

简单性 — 与原始性不同。简单的解决方案是简洁、易懂且无多余地完成任务。原始的 — 忽略最佳实践和健康的架构。区别在于简单的解决方案易于扩展,而原始的不易。

示例:使用 Activity 作为所有屏幕的唯一实体 — 这是原始性,而不是简单性。简单性 — 使用Navigation Component配合不同Fragment处理不同屏幕,但没有不必要的抽象。KISS不证明糟糕的架构是合理的。

自我检查:您的代码在添加新功能时是否能改变?如果能 — 简单性是正确的。如果每个功能都必须重写所有内容 — 这是原始性,请立即重构。

以KISS的名义忽略模式

模式(MVVM, MVI, Coordinator) — 不是复杂化,而是结构化。KISS不禁止使用经过验证的架构模式。禁止过度使用它们:在一个模式就足够的地方使用三个模式。中庸之道 — 每个项目一个架构模式,不超过2–3个辅助模式(DI, Navigation)。

根据 State of Mobile Architecture Report (2024),使用恰好一个架构模式的项目在第一年开发中比组合3个以上模式的“弗兰肯斯坦”项目少34%的bug。选择MVVM或MVI用于移动项目 — 并在所有屏幕上坚持使用它。

不要在一个项目中混合MVVM和MVI。如果团队选择了MVVM — 整个项目应遵循MVVM。例外 — 具有自己架构解决方案的单独功能模块,但这应是有意识的选择。

常见问题

KISS原则用简单的话怎么说?

KISS(Keep It Simple, Stupid) — 要求代码尽可能简单的原则。如果任务可以在没有不必要的类、模式和抽象的情况下解决 — 就不用它们解决。简单的解决方案更容易理解、测试和修改。

KISS和DRY有什么区别?

DRY禁止重复代码,KISS — 过度复杂。有时它们会冲突:消除重复(DRY)的尝试可能导致复杂的抽象(违反KISS)。三次法则(Rule of Three)有助于平衡:仅在第三次重复后才进行抽象。

什么时候可以违反KISS?

KISS可以被违反当您确切知道未来需求时:例如,通过KMM支持第二个平台或在下个季度迁移到新架构。条件:未来需求必须有文档记录,而不是假设性猜测。

如何衡量代码的简单性?

使用客观度量指标:圈复杂度(每个方法不超过10),每个方法的行数(不超过20),嵌套层级(不超过3)。对于Android — Detekt插件,对于iOS — SwiftLint。主观度量:新开发人员应在一分钟内理解代码。

KISS和SOLID兼容吗?

是的,KISSSOLID兼容。SOLID关乎正确的架构,KISS — 关乎最小复杂性。违反KISS是由于过度应用SOLID而产生的:在三个就足够的地方创建数十个类。黄金法则:SOLID在合理范围内,KISS作为每一步的过滤器。

总结

  • KISS(Keep It Simple, Stupid) — 最小复杂性原则,在美国海军的工程实践中提出。
  • 过度工程化 — KISS的主要敌人:为未来准备的抽象使代码复杂化而无当前收益。
  • 简单代码更容易测试:根据Google的数据,遵循KISS的项目生产性bug减少67%。
  • 圈复杂度 — 简单性的客观度量;保持每个方法在10以下。
  • KISS不证明原始性是合理的:忽视基本架构模式不是简单性,而是疏忽。
  • KISS和DRY的平衡通过三次法则实现:仅在第三次重复后才进行抽象。
  • 衡量简单性:新开发人员的入职时间(KISS — 3周,过度工程化 — 10周)。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读