10

你竟然写出这样的代码

 4 years ago
source link: https://blog.csdn.net/x359981514/article/details/107328881
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

上周开会时,跟同事在讨论,什么是好的代码。

什么是好的代码,怎么定义好的代码。

往简单了说,自己刚写的代码都是好的代码,别人写的都是垃圾。往复杂了说,高内聚,低耦合,OCP、SRP、ISP,各种概念能写一本厚厚的书。其实这事就跟评价程序员的工作一样,一天写1000行代码的程序员一定比一天写100行代码的程序员好吗?

大佬们闲着无聊也在讨论这个问题,而已已经争论了几十年,其中以Martin大叔的这句话最为经典。

衡量代码质量的唯一有效标准:WTF/min —— Robert C. Martin

再配上这幅经典的图,几乎可以完美的定义,什么是好的代码。

maM32mJ.jpg!web

没有最好的代码,只有挨骂的代码,挨骂的多少,决定了代码的好坏。

那么怎么才能写出少挨骂的代码呢。

从宏观上来讲,就是「整洁」二字,这也是《代码整洁之道》这本书的核心。

整洁的代码有几个核心:

  1. 风格整洁

  2. 逻辑整洁

首先,写代码最好有一些洁癖,变量命名前缀、函数名、换行空行,这些最基本的格式,最好能做到团队统一,至少是个人统一,每次写完一部分代码,通过格式化来统一风格。

整洁的代码如同优美的散文。—— Grady Booch

写代码其实跟文学创作一样,古人作诗,首先看的平仄对仗,音律押韵,只有风格统一,才能在看的时候有一种赏心悦目的感觉。

其次,写代码要先思考,程序员写的代码其实并不是给机器看的,而是给人看的。好的代码、不好的代码,在机器看来,其实并没有太大的区别(除了效率以外),无非都是机器码。

任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。—— Martin Fowler

写代码不是为了炫技,一段难读的代码,总是会招致更多的WTF。这也是为什么Kotlin的语法糖在有些场合经常被WTF的原因,团队内的每个人的思考角度、思路可能都不相同,所以有时候最简单的代码反而是最好的代码,Java的代码虽然语法冗长,废话多,但是读上去就像是白话文,更容易理解、维护。而反观Kotlin,如果对语法糖理解不够深入、对函数式编程的理念模棱两可,就很容易写出四不像的代码,俗称Java风格的Kotlin代码,很多人写Kotlin,仅仅是为了使用那些语法糖,少写几行代码而已。

以上,我们可以总结下,从宏观上看,怎么写好代码。

  1. 规范命名风格,比如说公开变量与私有变量的区分,资源命名统一拼音还是翻译,至少不要写出generateWoDeDaiMa这样的命名

  2. 通用流程统一代码模板,比如说请求接口,展示列表数据,刷新与加载更多,这样的操作尽量统一一种写法,避免千人前面

  3. 函数单一职责,尽量函数式编程,做到函数无副作用,减少成员变量、全局标记变量的使用

那么再具体一点,从移动端的角度来看看什么是好的代码。

移动端,或者说是大前端,与后端有很大的不同,后端代码偏逻辑代码,界面很少,大部分的维护,也是逻辑上的改动,而大前端则相反,UI和逻辑几乎绑的很死,大部分时间的修改,都是在处理UI。

在理解了这一点之后,你就能站在一个更高的维度来嘲笑那些为了选择使用MVC、MVP、MVVM还是MVVVVVIP而争论不休的人了,其实这些争论的出发点就有问题,站在前端的角度,这些所谓的分层,很难在所有代码中都合适,借助大佬的一句话「软件工程没有银弹」。

在后端架构中,通过MVC这些分层架构的解耦,确实可以让整体利于维护、拓展,但是在前端,不管是MVC还是MVP,都必须针对特定的使用场景。

移动端的业务场景,大致可以分为两类,业务逻辑代码和功能逻辑代码。

对于功能逻辑代码来说,与后端类似,良好的架构可以让这部分代码变的更加健壮,而对于业务代码来说,这些架构反而容易显得多余,相信很多人都有被Presenter弄疯的经历,原本非常简单的业务逻辑,由于使用了MVP,在修改的时候,需要冗余的修改一堆代码。所以,偏业务逻辑的代码,我们的思路是——写容易删除的代码。

业务逻辑代码通常不包含太多复杂的逻辑(如果有,那就应该拆入功能逻辑代码),而且大部分情况下,这些要处理的逻辑和UI绑定在一起,所以,这个时候,写容易删除的代码,可以让业务变得更加容易维护,毕竟在现在的迭代条件下,没有一段无辜的代码可以活过下个大版本。

那么有钢筋会说了,难道这些大师这么多年的经验都毫无用处了吗?

当然不是,架构必须结合具体的业务来设计,前面讲了,逻辑功能业务,该怎么架构怎么架构,设计模式什么的,能写多少写多少。而纯业务功能,设计模式,则是能写多少写多少。

对于业务功能来说,通常只在合适场景的局部使用这些设计模式或者说分层架构思想。

举个例子,APP中有些组件的设计是有异曲同工之妙的,这些东西,可以被称之为组件,比如统一弹窗、统一按钮、对话框、再比如大一点的,起点读书,书架列表中的一栏,这些东西可能在很多地方都有使用,这时候,MMVM中的VM,就可以派上用场了,通过抽取ViewModel,可以让UI的复用性加强,通过builder、策略模式、工厂模式等设计模式,能让代码的复用度更高、使用性更好。

那么再再具体一点,具体的代码,要怎么写,才是好的代码呢

资深程序员杨过曾经也在思考什么是好的代码这个问题,想不通跳崖了,不过好在最后因祸得福,朝闻道,夕可死矣。

紫薇软剑,三十岁前所用,误伤义士不祥,乃弃之深谷

玄铁重剑,重剑无锋,大巧不工,四十岁前恃之横行江湖

四十岁之后,不滞于物,草木竹石均可为剑,自此精修,渐进于无剑胜有剑之境

这实际上就是程序员的真实写照,刚毕业的程序员,意气风发,拿着键盘准备开天辟地,代码怎么写牛逼就怎么写,套上各种框架、各种分层、各种设计模式,写完还不忘加上注释,这是一段独孤求败的代码。再之后,被业务的毒瘤磨平了棱角,开始返璞归真,每一行代码都写的稳如狗。最后,写代码已经进入忘我的摸鱼境界,经常几天不写一行代码,一写就是好几行。

所以,杨过在四十岁的时候才理解的真谛,我们现在要早点理解了,不然35岁可能就失业了。

首先,没有一种思想是永恒的。十年前,面向对象才是编程的王道,十年后,函数式编程异军突起。十年河东十年河西的事情,在软件开发界太多了,谁能想到C#中的协程概念,居然在多年后,被Kotlin带火了,年轻的程序员们不要为了站队那种思想而争论不休,能解决问题的思想才是好的思想,多去了解不同的思想,让它们在你体内碰撞碰撞,说不定就一团浆糊了(完全理解了)。

其次,想好再码,先做到胸中有码,才能眼中无码,写代码前先花点时间整理下逻辑,理清楚分支情况和异常情况,然后再去动手,不急着那一点时间,又不是比谁敲得快。

再次,慎用继承,这个要单独拎出来说了。

继承,面向对象开发的三大核心原则之一。继承,规范了子父类具有类似行为的类,但是也带来了著名的香蕉猴子丛林(Banana Monkey Jungle)问题,相信很多开发者都遇到过这种问题,当你准备从另一个项目中copy一个类到现有的工程,或者修改一个新引入的类时,你会发现,还需要copy它的父类,甚至还有父类的父类,以及一连串的类,更不要提继承的菱形问题了。

面向对象语言的问题在于,每个类都随身携带了一个隐形环境。您想要香蕉,但是得到的是一只拿着香蕉的猴子和整个丛林。

所以,继承要慎用,但是怎么解决呢?其实可以从两方面来解决,一个是通过修改架构,尽可能避免无效、过度的继承设计,另一个是通过接口来进行行为的约束而不是通过继承,尽可能通过组合的方式来进行架构。

在Flutter/Dart中,这种方式被表现的淋漓尽致,Flutter的整体设计思想就是组合,万物基于组合,另外还提供了mixin来提供功能的混入,在毫无压力的情况下使用其它类的功能,而不是通过继承。

古今之成大事业、大学问者,必经过三种之境界:“昨夜西风凋碧树,独上高楼,望尽天涯路。” 此第一境也。“ 衣带渐宽终不悔,为伊消得人憔悴。” 此第二境也。“ 众里寻他千百度,蓦然回首,那人却在,灯火阑珊处。”此第三境也。

说了这么多,你学废了吗?

顺便打个广告,我的开源项目FlutterDojo

https://github.com/xuyisheng/flutter_dojo

对Flutter感兴趣的朋友可以加入我的Flutter修仙群,加我微信即可。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK