代码的艺术
本门课程为《代码的艺术》将
大家快准本好小本本听讲吧~
《代码的艺术》目的解读
了解公司与学校写代码的不同
在公司写程序和在学校写程序有很大的不同。
在学校写程序时,对于代码的质量要求比较低。
当进入公司之后,做的是工业级的产品,服务用户量可能会到达亿万级,所以相对而言对于代码的质量要求比较高。
消除对于程序员这个职业的误解
很多人都对程序员这个职业有误解,认为程序员就是码农,认为程序员35岁之后就写不出代码了。还有人认为程序员未来的唯一出路是以后做管理。
希望通过这门课程的学习,能使大家对于程序员有一个新的认识,消除误解。
建立对软件编程的正确认识
在做一件事物时,我们常说“知”与“行”要合一。即:我们需要对这件事物有一个正确的认识,才会有正确的行动。同理,
明确作为软件工程师的修炼方向
艺术品是由艺术家创造的。艺术家的修炼是有方式方法的。同样,软件工程师的修炼也是方式有方法的。希望通过这门课程,能使大家对软件工程师这个职业有一个全新的认识。
代码与艺术之间的关系
代码是可以被称为艺术的
艺术,是多种多样、丰富多彩的。同时艺术也是有多个层次的,其实,在我们编写代码时,我们的脑海中也会有类似的感觉。
艺术就是人类通过借助特殊的物质材料与工具,运用一定的审美能力和技巧,在精神与物质材料、心灵与审美对象的相互作用下,进行的充满激情与活力的创造性劳动,可以说它是一种精神文化的创造行为,是人的意识形态和生产形态的有机结合体。
写代码也恰恰要经历这样的一个过程。
在编写代码的过程中:
我们
同样,编写代码需要激情。而且,编写代码是一件非常具有创造性的工作。
代码是人类智慧的结晶,代码反映了一个团队或一个人的精神。
艺术可以从不同的角度进行解读、研究与创造
达芬奇有多幅著名的画作。拿著名的《蒙娜丽莎》这幅画来举例:

站在观众的角度,可能只是在欣赏画中的人物微笑。但是对于画家来说,可能就会考虑画画的手法、构图、光线明暗、色彩对比等等方面。
在艺术方面,可以站在很多不同的角度进行解读。
但是如果要成为一名创作者,我们需要的不仅仅是欣赏的能力,更重要的是
写代码如同艺术创作
写代码就如同艺术创作一般,并不是一件容易的事情。
写代码的内涵是:
①写代码这个过程是一个
②写代码需要把现实问题转化为数学模型。在写代码的过程中,我们需要有很好的模型能力。
③写代码实际是一个认识的过程。很多时候,编码的过程也是我们认识未知问题的过程。
④在写代码的过程中,我们需要综合的全方位的能力。包括把握问题的能力、建立模型的能力、沟通协助的能力、编码执行的能力等等。
⑤在写好代码之前,首先需要建立品位。品味是指我们首先要知道什么是好的代码,什么是不好的代码。这样我们才能去不断地调整自己的行为,然后去学习,去提高我们的编码能力,写出具有艺术感的代码。
软件工程师不等于码农
软件工程师不能只会写代码,更需要具有综合的素质。这个综合的素质包括:
1、技术
2、产品
要对产品业务有深刻的理解,需要了解产品交互设计、产品数据统计、产品业务运营等。
3、其他
要了解一些管理知识,需要知道项目是怎么管理的 ,如何去协调多个人一起去完成一个项目。有一些项目需要具有很强的研究与创新方面的能力。
以上这些能力素质,是一个软件工程师需要具有的综合素质。要成为一个全部掌握这些素质系统工程师至少需要8~10年的时间。
所以,软件工程师绝对不是一个只会简单编写代码就可以的职业。
正确认识代码实践方面的问题
什么是好代码,好的代码有哪些标准
将以上十条标准进行总结精简,可以归纳为:
(1)代码的正确和性能;
(2)代码的可读和可维护性;
(3)代码的可运维和可运营;
(4)代码的可共享和可重用。
了解完好代码的标准,接下来我们来看一下不好的代码主要表现在哪些方面:
(1)不好的函数名
比如,在函数名中,加my等单词,这属于很不专业的用法。
(2)不好的变量名
比如,看不出任何含义的a,b,c,j,k,temp等变量名。
(3)没有注释或注释不清晰
没有注释的代码是非常难读懂的。注释不清晰往往是因为文字功底或者描述能力欠缺,从而导致无法通过注释把代码的执行原理讲解清楚。
(4)一个函数执行多个功能
比如LoadFromFileAndCalculate()函数,它既执行了文件中去加载数据,还执行了计算功能。像这样的函数,我们建议把它切分成两个单独的函数。
(5)不好的代码样式排版
代码的样式排版在某种程度上体现了代码的一种逻辑。好的代码排版能增强代码的可读性和逻辑性。我们在写代码时,要规避不好的代码样式排版。
(6)难以测试的代码
代码没法测试,难写测试用例,这些都是一些不好的表现。
好的代码从哪里来
代码不只是“写”出来的。实际上,在整个项目中,真正的编码时间约占项目整体时间的10%。
这些环节包括:
①在编码前,要进行需求分析和系统设计。
②在编码过程中,要注意做单元测试。
③在编码后,要做集成测试,要上线,要持续运营,要迭代改进。
一个好的系统或产品,是以上几个环节持续循环的结果。
接下来我们着重介绍一下重点环节——
(1)认识需求分析和系统设计的重要性
需求分析和系统设计在软件开发中经常被忽略或轻视,但是这两点都是非常重要的环节。
人们的直觉往往是拿到一个项目就想尽快把它写出来并运行,感觉这样的路径是最快的。
但是实际上在软件前期需求分析和系统设计投入更多的成本,会在后期节省更多的消耗。即:
原因是:如果我们开始的设计做错的话,那么后期开发、测试、上线、调试这些成本都会被浪费掉。
(2)清楚需求分析和系统设计的差别
需求分析和系统设计是有泾渭分明的区别的,为了避免这两者相互混杂,我们需要清楚需求分析和系统设计各自的内涵。
(3)需求分析的注意要点
要点一:清楚怎么用寥寥数语勾勒出一个系统的功能。
每个系统都有自己的定位,我们可以从简洁的总体描述,展开到具体的需求描述。
①系统类型描述
②系统规模描述
③系统定位和系统差异描述
④系统对外接口功能描述
要点二:需求分析需要用精确的数字来描述。
需求分析中会涉及大量的数据分析,这些分析都需要精确的数字来进行支撑。
(4)系统设计的注意要点

要点一、清楚什么是系统架构
进一步解读系统架构,
①系统要完成哪些功能
②系统如何组成
③功能在这些组成部分之间如何划分
要点二、注意系统设计的约束
要点三、清楚需求是系统设计决策的来源
精确定义需求中的各个细节,以及量的定义,对系统设计的决策起着重要的作用。
要点四、系统设计的风格与哲学
一个好的系统是
子系统或模块之间的关系应该是
值得注意的是,使用全局变量就是在增加系统的耦合,从而增加系统的复杂性,所以
要点五、清楚接口的重要性
①模块对外的函数接口。
②平台对外的API。这些API很多是基于RPC或者是基于Web API来实现的。
③系统间通信的协议。
④系统间存在依赖的数据。比如给另一个系统提供的词表。
这些都是接口,都需要我们去重视,去很好地定义。
①接口定义了功能。如果定义的功能不正确,那么系统的可用性与价值便会大打折扣。
②接口决定了系统和系统外部之间的关系。相对于内部而言,外部关系确定后非常难以修改。
接口的修改需要非常慎重且要考虑周全。
第一,合理好用。新改的接口应该是非常合理好用的。不能使调度方感觉我们做的接口非常难以使用。
第二,修改时需要向前兼容。新改的接口应该尽量实现前项的兼容。不能出现当新接口上线时其他程序无法使用的情况。
如何写好代码
关于具体怎么写代码,我们主要
(1)代码也是一种表达方式
在一个项目中,软件的维护成本远远高于开发成本,而且超过50%的项目时间都是用于沟通。
常规意义的沟通方式主要有面对面交流、Email、文档或网络电话会议等。但是其实
在计算机早期,我们使用机器语言或汇编语言,更多的是考虑代码如何更高效率地执行。
然而,随着技术的进步,代码编译器的逐渐完善,我们写代码时更多的是要考虑如何让其他人看得懂、看得清楚。于是,
① 如何规范的表达代码。
② 语言使用的相关注意事项。
①看别人的代码,感觉和看自己的代码一样。
②看代码时能够专注于逻辑,而不是格式方面。
③看代码时不用想太多。
(2)代码书写过程中的细节问题
关于代码书写过程中的细节问题,我们将
①关于模块
每一个模块需要有明确的功能。需要符合
切分模块的方法:
先区分数据类的模块和过程类的模块。
数据类的模块:主要是要完成
过程类的模块:本身不含数据。过程类模块可以
编写程序时,我们需要注意减少模块间的耦合。
②关于类和函数
类和函数是两种不同的类型,有他们各自适用的范围。另外,遇见和类的成员变量无关的函数时,可以将该函数抽出来,作为一个独立的函数使用,这样便于未来的复用。
③关于面向对象
面向对象,是一个优秀的编程方法和范式,但是真正理解的人并不多。
面向对象的
我们需要注意一个普遍的错误认知,即:C语言是面向过程的,C++是面向对象的。
实际上,
C++是一个经常被滥用的语言。因为C++有太强的功能。
作为软件工程师,我们最重要的任务是去实现出我们所需要的功能,语言只是我们的工具。
另外,在系统中,我们应该
有这样一个悖论:很好的继承模型是基于对需求的准确把握,而在我们在初始设计阶段往往对需求理解的不透彻。系统在初始阶段可能只是一个很简单的原型,然后通过不断地迭代完善,才逐步发展起来变好的。
④关于模块内部的组成
一个模块,比如.py、.c或.go这样一个模块,它的内部组成主要是:在文件头中,需要对模块的功能进行简要说明。需要把文件的修改历史写清楚,包括修改时间、修改人和修改内容。在模块内,内容的顺序尽量保持一致,以方便未来对内容的搜索查询。
⑤关于函数
函数的切分同样是非常重要的。对于一个函数来说,要有明确的单一功能。
函数描述三要素包括
→ 功能描述是指描述这个函数是做什么的、实现了哪些功能。
→ 传入参数描述是指描述这个函数中传入参数的含义和限制条件。
→ 返回值描述是指描述这个函数中返回值都有哪些可能性。
在函数头中,需要对函数的语义做出清晰和准确的说明。我们需要
在这里,推荐一种函数的书写方式:
⑥关于代码注释
要重视注释,书写注释要做到清晰明确。在编写程序的过程中,
⑦关于代码块
代码块的讨论范围是在一个函数内的代码实现。书写代码块的思路是
⑧关于命名
命名包括系统命名、子系统命名、模块命名、函数命名、变量命名、常量命名等。
我们要清楚命名的重要性。
一是“望名生义”是人的自然反应。不准确的命名会使人产生误导。
二是概念是建立模型的出发点。好的命名是系统设计的基础。
命名中普遍存在的问题有:
一是名字中不携带任何信息。
二是名字携带的信息是错误的。
命名不是一件容易的事情,
⑨关于系统的运营
在互联网时代,系统非常依赖运营。并不是我们把代码写完调试通了就可以。
在系统运营过程中,
对于一个系统来说,
数据收集很重要,数据量够大才能知道这个项目或这个系统的具体收益。
关于系统的运营,我们在设计和编码阶段就需要考虑。即:在设计和编码阶段,提供足够的状态记录,提供方便的对外接口。
怎样修炼成为优秀的软件工程师
通常人们在判断一名软件工程师的水平时,都会用工作时间、代码量、学历、曾就职的公司等等这类外部因素作为评判标准。
但是事实上
1、学习-思考-实践
2、知识-方法-精神
3、基础知识是根本
学习-思考-实践
(1)多学习
软件编写的历史已经超过半个世纪,有太多的经验可以借鉴学习。要不断的学习进步。
(2)多思考
学而不思则罔,思而不学则殆。对于做过的项目要去深入思考,复盘写心得。
(3)多实践
要做到知行合一,我们大部分的心得和成长其实是来自于实践中的经历。在学习和思考的基础之上,要多做项目,把学到的理论运用到真正的工作中。
知识-方法-精神
互联网的发展日新月异,对于软件开发来说,知识永远在增加,所以在变化快速的知识世界中,
方法就是用来分析问题和解决问题的。虽然说起来简单,但是适合每个人的方法都需要自己去寻找和总结。
在大多数人的成长过程中,并不单单只是鲜花和掌声,更多的时候是在和困难荆棘做斗争。而真正能做出成就的人,都有着远大理想和宏伟志向。所以,光有知识和方法往往是不够的,还需要有精神作为支撑。
在这里
(1)自由精神、独立思想。
人一定要有自己的思考。不要人云亦云,不要随波逐流。
(2)对完美的不懈追求。
不要做到一定程度就满意了,而是要去不断的追求一个更好的结果。
基础知识是根本
唐朝著名宰相魏征曾经对唐太宗说过:“求木之长者,必固其根本;欲流之远者,必浚其泉源”,充分表达了基础乃治学之根本。
对于一个软件工程师来说,需要掌握的基础是非常全面的。

包括数据结构、算法、操作系统、系统结构、计算机网络。包括软件工程、编程思想。包括逻辑思维能力、归纳总结能力、表达能力。还包括研究能力、分析问题、解决问题的能力等。这些基础的建立,至少也要5~8年的时间。
欲速则不达,