首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么代码会遭人耻笑,什么妹子会受人喜欢?从妹子角度戏说代码优劣。

什么代码会遭人耻笑,什么妹子会受人喜欢?从妹子角度戏说代码优劣。

作者头像
LIYI
发布2019-09-27 17:04:46
3670
发布2019-09-27 17:04:46
举报
文章被收录于专栏:艺述论专栏艺述论专栏

今天给大家分享一点关于变量和函数方面的内容。

在日常生活中,丑姑娘和好姑娘一眼就能识别;在代码中,好代码与坏代码却不容易觉察,这里面有标准,但每个程序员都觉得自己创造的代码好。了解这些标准,可以有效避免写出坏代码。

目录

好的标准是什么

- 可读性 = 清晰

- 复用性 = 没脾气

- 扩展性 = 有所为、有所不为

代码实例讲解

- 变量

- 函数

好的标准是什么

在人类中,好妹子一般都具有什么特征呢?

  1. 皮肤白皙,五官端正,有立体感
  2. 脾气好,好说话,易于相处
  3. 愿意尝试新鲜事物,并愿意把快乐分享给我们

这三点标准,在代码中,对应的标准是:

  1. 可读性
  2. 复用性
  3. 扩展性

1,可读性 = 清晰

现在依次看一下,先看“可读性”。

可读性,就是说特征明显,浅显易懂。就像美女,五官端正,棱角分明,身材苗条,举止有形,远远一看就是美女;如果趴近了瞅半天还发现不了美,就不是美女。

拿具体的代码来讲,就是清晰:

  • 逻辑清晰
  • 代码清晰
  • 注释清晰等

所有的地方都清晰。

如果拿到一个项目,钻进去看半天,函数调用是云里来雾里去,难觅其规律,也没有一行半行的注释,这就是丑代码,起码是不漂亮的代码。

好的代码,就像美女一样,只瞥一眼,就被吸引了。写代码,就要写让人一看就明白的代码。

2,复用性 = 没脾气

再看一下“复用性”。

就像好脾气的妹子,和什么样的人都能聊得来,大家都喜欢她;脾气不大好的妹子,只能和一部分人聊得来,只愿意和一部分人交朋友,为什么?因为她有个人好恶,不能平等地看待芸芸众生;脾气特差的妹子,是不能和任何人交朋友的,像李莫愁李师姐,她逢人就送一枚毒针,尤其是遇到性陆的人,脾气爆的很,为什么?因为她觉得人人都是恶的,“男人没一个是好东西”。心中有偏见,行为才傲慢。

再拿代码来类比一下吧,好的代码就是没脾气,没有偏好。因为无偏好,所以适用的场景就多,场景多,复用性就强。举个具体的例子,微服务能力以 SDK 提供,SDK 是Java 的,就只能由 Java 调用;SDK 是 Go 语言的,就只能由 Golang 调用,而如果以 RESTFul API 的形式提供,只要是能进行 HTTP/HTTPS 协议通讯,甭管是什么语言,都可以调用。这就是没脾气,或者理解为少脾气。

写代码,就要写没脾气的代码。

3,扩展性 = 有所为、有所不为

最后再看一下“扩展性”。

复用性好的代码,往往功能是单一的、确定的,其方法往往只干一件事,其模块往往只集中负责一个业务功能,并且是独占负责,不允许其它模块是搅和。

举个例子,一个用户 login 功能,假如已经在一个 user 模块中提供了,就不要在其它模块中提供。每个服务对外都是一个资源,资源是唯一的。如果系统中有两个模块,一个user,一个auth,都提供了一个login功能,那么修改 login 的逻辑时,是不是两个地方都要修改?这就是坏的设计。

好的设计,就是一个模块集中负责一个功能,一个方法只干一件事。在面向对象中,这叫做“单一职责法则”

回过头来,再接着看“扩展性”。因为代码都是单一职责了,如果想增加职责怎么办?

可以添加新的方法;如果是新的功能,可以添加新的模块。这在软件设计上,就是扩展性,也叫可扩展性。综合考虑一下,不让修改旧方法,而建议添加新方法,这叫做“开放-封闭法则”,也是面向对象中与“单一职责法则”齐名的顶重要的一个设计法则,对修改封闭,对扩展开放。

举个对比的例子,就像冬天里美女冷了,要加衣服,里面穿了毛衣了,此时不要在那个毛衣上打主意,往上绑毛线或打补丁都不可行,这样是美女也丑了;合理的、简单的路子就是在外面加件羽绒服。

写代码,做设计,就要这样,有所为,有所不为,有所开放,有所封闭。

代码实例讲解

理解了“可读性、复用性、扩展性”三个概念,接下来我们看看具体的代码例子,主要看变量和函数两部分。

变量

举 3 个例子

示例 1

// bad code
const yyyymmdstr = moment().format('YYYY/MM/DD');

破坏了可读性

// better code
const currentDate = moment().format('YYYY/MM/DD');

示例 2

// bad code
const ADDRESS = 'One Infinite Loop, Cupertino 95014';
const CITY_ZIP_CODE_REGEX = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(ADDRESS.match(CITY_ZIP_CODE_REGEX)[1], ADDRESS.match(CITY_ZIP_CODE_REGEX)[2]);

可读性差

// better code
const ADDRESS = 'One Infinite Loop, Cupertino 95014';
const CITY_ZIP_CODE_REGEX = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = ADDRESS.match(CITY_ZIP_CODE_REGEX) || [];
saveCityZipCode(city, zipCode);

在该示例中,好坏代码的差别在于“ADDRESS.match(CITY_ZIP_CODE_REGEX)”这行代码的执行结果,没有析构声明为临时常量。

差代码涉及重复运算,且未做容错判断;好代码这些都做了,并且将中间的计算结果通过析构声明的语法,声明为临时常量,使代码具有了可描述性。

能够准确、清晰描述的代码,就是好代码。该示例涉及的逻辑简单,如果一个算法涉及多个算法步骤,前后跨度的上下文执行环境长,在这种情况下,隐含变量多了将非常不利于代码的理解。

示例 3

// bad code
const car = {
carMake: 'Honda',
carModel: 'Accord',
carColor: 'Blue'
};
function paintCar(car) {
car.carColor = 'Red';
}

破坏了可读性、简洁性

// better code
const car = {
make: 'Honda',
model: 'Accord',
color: 'Blue'
};
function paintCar(car) {
car.color = 'Red';
}

可读性强并不代表信息冗余,冗余信息会增加无谓的心智负担。在该示例中,差代码car对象中每个字段都有一个car前缀,本身对象的名称就是car,再加一个car前缀就是画蛇添足。

先秦宋玉在《登徒子好色赋》中形容邻家妹子的美,说“增之一分则太长,减之一分则太短”。对比于此处,代码中描述的对象,信息即不要缺失,也不要冗余,刚刚好,就是好。

函数

也举三个例子

示例 1

// bad code
function createMenu(...args) {
// ...
}
createMenu( 'Foo','Bar','Baz',true)

坏代码可读性差,扩展性也不强

// better code
function createMenu({ title, body, buttonText, cancellable }) {
// ...
}
createMenu({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
});

在该示例中,坏代码定义的是不定参数,传递几个都可以,参数名字和意义也不知道;在好代码中,参数是一个对象,在形参列表中通过 ES6 的析构语法,变成一个个名称和意义明确的参数,可读性强;扩展性也强,在参数对象中增加新字段,不影响旧析构代码。

例如:

createMenu({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true,
count:100 // 此处添加了新的字段
});

原代码不添加对count字段的析构,也没事:

function createMenu({ title, body, buttonText, cancellable }) {
// ...
}

如果用得着,再添加也不迟,这就是具有良好的可扩展性。

示例 2

// bad code
const menuConfig = {
title: null,
body: 'Bar',
buttonText: null,
cancellable: true
};
function createMenu(config) {
config.title = config.title || 'Foo';
config.body = config.body || 'Bar';
config.buttonText = config.buttonText || 'Baz';
config.cancellable = config.cancellable !== undefined ? config.cancellable : true;
}
createMenu(menuConfig);

有损代码简洁性

// better code
const menuConfig = {
title: 'Order',
// 'body' 没有,这个 key 是缺失的,但没关系,因为有默认值
buttonText: 'Send',
cancellable: true
};
function createMenu(config) {
config = Object.assign({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
}, config);
// config 就变成了: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}
// ...
}
createMenu(menuConfig);

在该示例中,坏代码有点啰嗦;而好代码通过Object.assign确立了参数对象的默认值,所以可以省去许多短路评价判断的代码。

注意,Object.assign是将一个右对象所有可枚举的属性,拷贝到左对象中,并返回左对象。语法为: Object.assign(target, ...sources);

好的代码都是简洁的。为什么好代码都能简洁呢?为什么有时候我们写代码做不到简洁呢?

每个方法都有它的输入和输出。如果输出只有一个或一种类型,那么它干的就是一件事;如果输出是两样东西,它干就不是一件事。对于输入也是一样的,如果输入是确定的,那么代码就会很清晰,逻辑就会很简单;如果输入是未知的,或是变化的,那么代码就需要应对多种复杂的情况。很显然,给方法的参数设定默认值,可以有效地将输入简化,从而增加代码的可读性和清晰度。

示例 3

// bad code
// 全局变量被一个函数引用
// 现在这个变量从字符串变成了数组,如果有其他的函数引用,会发生无法预见的错误。
var name = 'Ryan McDermott';
function splitIntoFirstAndLastName() {
name = name.split(' ');
}
splitIntoFirstAndLastName();
console.log(name); // ['Ryan', 'McDermott'];

name作为一个全局变量,直接被 splitIntoFirstAndLastName 函数在内部篡改了,而外界未知。

// better code
var name = 'Ryan McDermott';
var newName = splitIntoFirstAndLastName(name)
function splitIntoFirstAndLastName(name) {
return name.split(' ');
}
console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];

好代码没有直接修改全局变量 name,而是返回一个新值,所以 newName 是另外一种打印结果。坏代码破坏了扩展性的开放-封闭原则,好代码就是要有所为,有所不为。

从副作用的角度来讲......

了解了概念,我们继续从副作用的角度讲,具有良好复用性的代码,没有副作用(或副作用是幂等的)。就像一个易相处的妹子,每次和她相处,都不会留下社交阴影,即副作用;反之,如果每次和妹子相处,她都发些小脾气,产生一些副作用,也就称不上易相处了。这种情况在代码中就是复用性差。

等等,“或副使用是幂等的”如何理解?

就是妹子发完脾气,赶快和你道谦,给你送小礼物等,迅速消除了不良影响。

--END--

每天学一点编程,讲述平头老师与程序员小明之间的故事。本文属于《JS Expert 2019》系列中的一篇。本文部分摘自《如何写出优雅耐看的JavaScript代码》,原文链接为:http://t.cn/AinCoA1C

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 艺述论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档