惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
G
Google Developers Blog
博客园 - 三生石上(FineUI控件)
B
Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Hugging Face - Blog
Hugging Face - Blog
C
Check Point Blog
V
V2EX
Vercel News
Vercel News
U
Unit 42
Recent Announcements
Recent Announcements
Last Week in AI
Last Week in AI
J
Java Code Geeks
WordPress大学
WordPress大学
罗磊的独立博客
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
小众软件
小众软件
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
云风的 BLOG
云风的 BLOG

Surmon.me

一人有限集团 你就是不敢 创造力是温柔的谎言 人类正在退出人类 AI 代替不了这样的你 脉冲点火背后的架构设计 基于 Cloudflare 生态的 AI Agent 实现 NodePress 支持用户登录了 从统计学习到通用智能 2025 投资报告:走慢的路 无依之地 会杀人的菩萨 无我不是共识 文化的积重与偏见 当下即安 科学的尽头是态度 无我不是 Egoless 信仰不因恐惧而存在 世间无解的矛与盾 先别急着做些什么 佛不需要你的皈依 真理的幻觉 两扇大门 造心里的浮屠 自胜者强 逻辑与智慧 真的相 快乐的秘密 只需愿意 是名体验
简洁编码指南
Surmon · 2017-04-11 · via Surmon.me

简洁编码指南

就三点:

  • 编码风格:忌简忌繁、统一风格
  • 编码结构:模块化、函数式、易读性、复用元素的抽象
  • 编码过程:扩展能力、测试

编码风格

保持良好的编码风格

  • 不要刻意简写难以理解的表达式,也不要嵌套过于冗余的函数
  • 缩进统一、命名统一、标符统一、文件结构统一... 一切能以标准量化的的都需要拿标准约束
  • Lint 等 QA 约束工具是必须的,用工具来实践程序正义

更详细的编码规范,可以来这: Developer code guide

编码结构

Spaghetti code (面条代码)的特征

  • 代码没有组织,且多处出现重复的代码块

    • 一般是封装粒度不够造成
  • 多个代码块之间高度耦合,跳来跳去,使其难以调试

    • 函数抽象程度不够
    • OOP 理解不深刻
    • 典型的命令式编程
  • 代码不会分解成条件块或标签,使其难以阅读。

    • 到这个程度就不知道代码写的有多糟了

避免面条代码的方法

  • 需要复用的代码一定要封装
  • “模块化” 不仅仅是文件意义的模块化,而是指逻辑单元的模块化,比如函数;当然现在大部分框架、库、平台... 都有自己成熟的模块化系统,在模块化的基础上尽量取得平衡
  • 函数的模块化和封装要尽量地 “函数式”,不依赖外部变量,不改变外部变量,有输入,有输出,不过度嵌套,中间量清晰易读
  • 避免全局变量和类成员传递数据,函数内部更应该优先使用局部变量和参数变量
  • 优秀的代码是不需要注释的,所以命名本身很重要很重要

优秀的代码组织应该是清晰的树状结构,自上而下分解任务, 自下而上完成任务。

编码过程

防止 over-engineering (过度设计)

过度设计是指,太过于考虑今后代码的扩展性、复用性,或太过于考虑测试的便利性,导致系统被过度设计为难以理解、难以重用的复杂结构。

世界上有两种 “没有 BUG” 的代码。一种是“没有明显 BUG 的代码”,另一种是 “明显没有 BUG 的代码”。

第一种情况,由于代码复杂不堪,加上很多测试,各种 coverage,看起来测试都通过了,所以就认为代码是正确的。

第二种情况,由于代码简单直接,就算没写很多测试,你一眼看去就知道它不可能有 BUG。

你钟爱哪一种?

防止过度设计的方法:

  • 先把眼前的问题解决掉,解决好,再考虑将来的扩展问题
  • 先写出可用的代码,反复推敲,再考虑是否需要重用的问题
  • 先写出可用,简单,明显没有 BUG 的代码,再考虑测试的问题

代码规范可以参考上面链接就可以了,可以根据自己的情况修改规范以建立自己的标准,下面分享一些平日较为不易理解的代码片段。

隐式转换

==!= 操作符会在需要的情况下自动转换数据类型; ===!== 不会,它们会同时比较值和数据类型,也称为严格比较。

        
        

12345678

[10] === 10 // false [10] == 10 // true '10' == 10 // true '10' === 10 // false [] == 0 // true [] === 0 // false '' == false // true (but true == "a" is false,因为true隐式转换为字符串为'1') '' === false // false

赋值判断

        
        

1234567891011

// 正常流程 var a if (b) { a = b } else { a = c } // 三目运算 var a = b ? b : c // 利用短路运算判断赋值 var a = b || c

数据类型判断 typeofinstanceof

        
        

123456789101112131415161718192021222324

/* typeof 会返回一个变量的基本类型,针对数组和对象均返回 'object' */ typeof 666 // 'number' typeof Date() // 'string' typeof [] // 'object' typeof {} // 'object' typeof false // 'boolean' typeof new Function() // 'function' typeof undefined // 'undefined' typeof null // 'object' /* instanceof 仅检测对象的原型链是否指向构造函数的 prototype 对象 由于 JavaScript 中万物皆对象,故一切用 new 关键字实例的对象最深原型永远指向 Object */ 666 instanceof Number // false new Number(666) instanceof Number // true new Number(666) instanceof Object // true '666' instanceof String // false new String('666') instanceof String // true new Object() instanceof Object // true [] instanceof Object // true [] instanceof Array // true new Date() instanceof Date // true new Date() instanceof Object // true

快速求和

        
        

123

// eval 能做的事真的太多了 var nums = [1, 2, 3, 4, 5, 6...] console.log('和:', eval(nums.join('+')))

简写判断

        
        

123456789101112131415

// 标准判断(推荐) if (a) { b() } // 简写 if (a) b() // 利用短路运算简写 a && b() // 或者(极力不推荐) var foo = 10 foo == 10 && doSomething() foo == 5 || doSomething()

with 作用域

        
        

1234

var obj = { name: 'xxx' } with (obj) { console.log(name) // 'xxx' }

复杂的流程控制

        
        

12345678910111213141516171819202122232425262728293031323334

// 一种不太好的情况 if (a) { doSomethingA() } else if (b) { doSomethingB() } else if (c) { doSomethingC() } else if (d || e) { doSomethingDE() } else if (f) { doSomethingF() } //... // 可以用switch/case来代替 switch (true) { case a: doSomethingA() break case b: doSomethingB() break case c: doSomethingC() break case d || e: doSomethingDE() break case f: doSomethingF() break default: doSomethingDefault() break }