软件开发的一些"心法"

从事软件开发也有好几年了,和一开始那个懵懵懂懂的小菜鸟相比,自己也感觉到了一些变化. 也许是熟能生巧,
趟过很多坑,但核心的绝不是这些细节的东西. 打个比方,如果说对某种语言的特性和技巧的掌握属于身法,
那么对应核心的东西,就叫心法. 没有身法,心法难以实战;但是没有心法,身法再炫也不过是无谓的杂耍而已.
今天,就来讲讲多年浸淫软件开发所感悟的一些"心法".

三部曲

软件开发,无论是用什么语言,在什么操作系统,都有其本身不变的东西,称之为编程思想.对我而言,
我所遵循的开发思想其实很简单,却都是血泪的经验所汇结而成. 我将其总结为三点:
1) Make it work, 2) Make it clean, 3) Make it fast. 排序分先后,而且缺一不可.

Make it work (使其可用)

这个规则似乎是显而易见的, 软件开发的目的就是为了解决实际问题. 但是,忘记这个规则的
程序员,也不在少数. 君不见,每次上技术论坛,都有人在问:"我是新手,应该学哪门语言?",
或者讨论"XXX语言怎么臃肿复杂难用","XXX语言怎么语法奇异古怪",等等.

说真的,这些事情重要吗? 我学的第一门编程语言是Verilog,之后转到SystemC做系统仿真,后来顺其自然地学习了C++,
之后才完全转到软件行业. 说这个想说明, 对于新手而言,第一门学习的语言并不重要, 它的作用是让你了解人与机器的交互接口,
也就是条件,循环,函数等基本概念. 再者,学习某一门编程语言,最好的办法就是那句至理名言:JUST DO IT,
纠结于语言,平台,难度这些东西反而是本末倒置, 编程首先要明确的事情是你想做什么.比如想做嵌入式,硬件相关,那C/C++是首选;
想做手机app, 当然是Java(Android)或Objective C;想做些数据处理,或者小工具简化日常工作,那我会推荐Python;
想做网页,除了JavaScript还有其他选择吗?因此, 忘记网上那些讨论吧. 语言圣战,也许只有新手才会热衷于此.
听闻使用不同开发语言的人会互相鄙视,比如C++鄙视JAVA, JAVA鄙视Python, Python鄙视JS, 等等, 这让我深感无聊且幼稚.

对于有经验的软件开发人员,太执着于开发语言更是不必要. 既然是有经验,那至少是对各种类型的语言都有所了解,
比如强类型的C/JAVA, 动态类型的Python以及某种函数式语言如Scala或Haskell等. 多种语言之间虽然语法稍微有所不同,
但大体上都能在上述类型中找到很多相似的地方,也就是说,只要稍微花一两周学习语法,应该要能很快投入到团队项目中.
当然对于特别复杂的语言(如C++),多花点时间了解语言特性也是必要的.

总而言之,好的软件工程师,应该要有举一反三,快速学习的能力. 最为重要的,不要忘记自己出手的目的,
那就是Make it work, 客户端应用也好, 服务端组建也罢, 都是为了实现其功能, 对其他服务或者人进行有效而正确的交付.
在这个阶段, 除了功能无需考虑太多其他事情, 不忘初心, 才能免于掉入效率的陷进之中.

Make it clean (使其整洁)

代码整洁,是每个软件工程师都或多或少听说过的概念. 但是这个概念又不像第一点那样显而易见.
因为我们即使不管代码整洁与否,程序都能实现最初的功能,交付给老板他也很是高兴. 相反,
如果多花时间在代码的整洁性上,那必然会延时交付,从而会使得老板不高兴.因此, 这一条也是
三部曲中分歧最大的.

当然了,对于软件工程师而言,在时间足够的情况下,几乎不会有人反对代码整洁. 但现实是项目的时间
往往紧迫,而且改善代码质量在短期内也看不出有什么收获. 可是如果不注重,等到项目规模扩大之后,
开发者就会陷入代码耦合,结构混乱,难以拓展和难以维护的屎坑之中.

关于代码整洁,细说起来也是内容庞杂. 在这里可以推荐三本书:

  • <<代码整洁之道>>
  • <<重构:改善既有代码的设计>>
  • <<设计模式:可复用面向对象软件的基础>>

在软件功能开发结束之后,我们可以优化现有的代码,将其中的模块和逻辑重新整理,使得整体结构清晰明朗,
一些有用的模块,可以独立出来,可以复用到以后的项目之中,以减少重复造轮子的时间.

值得一提的是, 代码整洁往往离不开重构, 而重构又离不开单元测试. 因为只有单元测试有足够的覆盖率,
你才能在改善代码的时候保证不影响现有的功能. 不论是对现有代码的重构, 还是保证新代码的一致性(coding style),
都需要额外花费时间, 但最后你会发现所付出的小部分时间, 会在将来以10x的效率提升而返还.

Make it fast (使其高效)

没人喜欢慢吞吞的代码. 对于面向用户的服务更是如此. 如果每次打开一个APP或者渲染一个页面,都需要5,6秒的时间,
那很可能这个用户就流失掉了. 除去I/O的原因, 程序运行的效率也是一个重要的考量因素.

影响程序运行速度的原因有很多,比如算法的复杂度,内存分配/拷贝的频率,以及系统上下文切换等.
很多时候我们也不能想当然地就进行优化. 正确的做法是通过profiler来进行分析. 现代的集成开发环境(IDE),
应该都会提供对应的profiler. 以Linux的c/c++程序为例, 我们就可以用gprof对应用程序进行分析.
其提供了每个函数的运行时间(百分比)/累计运行时间,调用次数等有用的信息,帮助我们查找程序热点,
从而改善程序的执行效率. 毕竟,根据二八定律,程序运行所消耗80%的时间,大都产生于20%的代码之中.

改善效率,有可能是减少某个具体算法函数的时间复杂度(比如替换random函数),有可能是用引用取代复制减少内存拷贝,
也有可能是增加缓存减少网络/磁盘的IO频率. 具体的方法取决与程序的热点所在. 一些看起来似乎有用的做法,
比如循环展开,函数inline以期减少堆栈开销等, 简直是大腿上把脉——瞎搞.

乱序陷阱

上面讲了软件开发过程中的三部曲,但是有一点非常重要,即三部曲的顺序是严格从上倒下的. 而其中一些乱序错误,
也成为了如今常见的开发阻碍:

提前优化

如果开发时第一步考虑的不是使其可用,而是使其高效,那么很有可能就掉进了提前优化的陷阱. 相信大家对
"提前优化是万恶之源"这句话也不会陌生. 如果开发者在八字还没一瞥的时候就说, 我要弄三级缓存减少数据库访问,
或者我要整合xxx-kqueue支持C1000K的高并发, 那么这个项目可能就危险了. 且不说优化是否能成功地work around,
即便这个针对性的优化达到其性能要求,也未必是最终应用的热点所在. 花了大把时间, 最后可能缓存命中率极低,
或实际最高并发数还不到500, 那这些功夫就有点得不偿失了. 再者,提前的优化为初期开发套上了枷锁,
从某种程度上说,也降低了项目的开发效率.

滥用"设计模式"

上面第二点代码整洁中提到了,软件开发,特别是面向对象的软件开发,其好处在于可以切分模块边界,使得代码可以复用.
但是我却不提倡对此过于执着. 首先想代码能够重用, 就必须给模块提供对应的灵活性, 也就是说单一模块的功能应该尽量
简单且通用. 事实上功能越具体的模块就越难以重用, 只有一些抽象的功能才值得花功夫去提炼.

设计模式, 通常指的是GoF的23中面向对象的设计模式. 有的程序员看过此书后,就急着上手应用,每次项目刚开始,就考虑
要用哪几个模式,这来个Factory,那来个Delegate. 这其实有点本末倒置,无异于拿着锤子找钉子. 设计模式的初衷是
改善代码结构,减少耦合提高扩展性. 这只在项目到了一定规模才会有实际好处, 如果只是中小型项目, 增加的这些间接层,
很有可能反而提高了复杂性,纯属画蛇添足.当然, 如果你是个非常有经验的程序员, 对于这些模式的best practice了然于胸,
在某些情况下一开始就采用某种结构也无不可, 但我还是建议对其采用保守态度, 毕竟‘Simple is better than complex‘.
设计模式最好还是在重构的阶段再按情况决定是否采用为好.

除了重构,代码整洁的一个重要方面是编码规范,这倒是要在项目开始前制定好的,比如变量命名,大括号换不换行,
用空格还是TAB缩进,每个公司或者小组都应该有固定的规章,这样可以免去为这些细枝末节的事情操心,从而专心投入功能开发之中.

总结

综上所述,一个高效的软件开发过程应该是这样的:

  1. 明确开发需求.
  2. 针对需求切分不同功能模块.
  3. 针对每个模块编写代码/单元测试.
  4. 对每个模块进行结构整理(即重构).
  5. 对每个模块进行性能优化(可选).
  6. 整合所有模块,如果需要可以再次进行重构,提炼公共部分.
  7. 最终测试/交付.

最后,这只是笔者的一家之言,对于本人来说确实可以显著提高开发效率, 但每个人的经验和习惯可能并不相同,
也许细节上也会有所不同, 但即便道路不同,我们想要"做出点东西"的心情也都是一样的. 所以需要做的则是摒弃偏见,
兼听并济,取长补短,最终形成属于自己的高效开发模式.

博客地址:

时间: 2024-10-08 19:35:10

软件开发的一些"心法"的相关文章

结构化方法和面向对象方法在软件开发中的对比

学习过C语言和JAVA的同学们一定清楚,这两种语言代表了两种不同的开发方式,即以C语言为代表的结构化开发方法和JAVA代表的面向对象的开发方法.由于二者在程序结构上有着很大的区别,因此,在软件开发领域中,根据自己的需求来选择合理的开发方式就显得尤为重要. 开发软件通常有三个层次: 1.满足用户需求 2.可维护性,即可修改性,让软件能随着用户需求的变更而容易改变 3.可重用性(在其它软件中,能尽量重用该软件的模块) 通过对软件的这三个主要层次的分析,我们就能在实际开发中确定我们的选择. 结构化方法

敏捷软件开发简述

前言:由于我读了邹欣老师的<构建之法:现代软件工程(第二版)>,因此对敏捷软件开发有了比较大的兴趣.于是我在网上找了一些论文,比如Requirements Engineering and Agile Software Development.A decade of agile methodologies: Towards explaining agile software development.在读了这些论文之后,对敏捷软件开发有了大致的了解.这篇博文主要是简单介绍敏捷软件开发,重点集中在主

敏捷软件开发VS传统软件工程

敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同,相对于"非敏捷",更强调程序员团队与业务专家之间的紧密协作.面对面的沟通(认为比书面的文档更有效).频繁交付新的软件版本.紧凑而自我组织型的团队.能够很好地适应需求变化的代码编写和团队组织方法,也更注重软件开发中"人"的作用. 本文将介绍敏捷软件开发的历史背景与发展,

全新的跨平台app软件开发工具——Lae软件开发平台

Lae是一款运行于windows的界面开发工具,具有所见即所得.开发跨平台.UI布局自由.机制简单.维护容易等诸多优点,可以开发同时运行在windows.Linux.MacOX.iOS.Android等系统平台的软件,windows桌面工具软件.管理软件.游戏界面;  linux系统桌面工具软件.管理软件.游戏界面; Mac OSX系统上桌面工具软件.管理软件.游戏界面:安卓系统的APP软件.2D游戏:iOS系统上的APP软件.2D游戏. 感兴趣的朋友请搜索知乎上的Lae软件开发平台介绍,或加入

怪不的软件开发这么挣钱,原来是有这么多职位

说起软件开发,现在是无人不知,无人不晓.好多人可能以为软件开发就是做一样工作的,其实不然,软件开发也分很多种类型,很多方向.做为一个过来人,简单介绍一些常见的开发方向. 1. 桌面程序:Java.C++.C#.VB.C均可. 现在大家办公使用的还是桌面程序占多数,不管是OA,ERP等等,都是通过PC来操作,桌面程序开发是一个重要的方向.只要PC还在,桌面程序开发就会一直存在. 2. 网站服务器端开发:JSP(Java语法).PHP.ASP(C#语法).Web App框架等 互联网发展的一个重要部

对软件开发中uml建模的理解和图形整理(一)

由于uml(统一建模语言)在开发中经常会用到,特别是在软件开发中的OOAD阶段,因此要理解和使用uml显得尤为重要.在uml开始之前,咱先回顾一个OOAD.OOP的主要特征. OOAD:根据面向对象的方法学来对软件系统进行分析和设计的过程.它包括OOA 分析阶段和OOD设计阶段.其中分析阶段主要解决"What to do?"的问题,而设计阶段主要解决"How to do?"的问题.具体来说就是:在OOA分析阶段咱要做的主要工作就是建立对业务问题域的视图(建立模型).

让你提前认识软件开发(46):首先是为人编写程序,其次才是计算机

第3部分 软件研发工作总结 首先是为人编写程序,其次才是计算机 "首先是为人编写程序,其次才是计算机",这是软件开发的基本要点,软件的生命周期贯穿于产品的开发.测试.生产.发布.用户使用.版本升级和后期维护等长期过程中,只有易读.易维护的软件代码才具有生命力. 在实际的软件开发过程中,可能是由于工作很忙的原因,很多开发人员只注重实现程序的基本功能,而忘记了编程规范,因此写出来的代码只能让计算机看懂,人要看懂很不容易.更有甚者,有些项目组为了赶进度,明确要求组员以实现产品功能为主,代码能

【转载】软件开发启示录——迟到的领悟

作者: John Sonmez  来源: IDF实验室博客  发布时间: 2013-10-20 15:47 转自(http://blog.idf.cn/2013/09/4-things-i-wish-i-would-have-known-when-i-started-my-software-development-career/) 我的软件开发生涯开始于15年前. 但是直到最近的5年,我才真正开始看到自己在软件开发领域的巨大进步. 这里有一些感悟是我希望能够在我进入软件开发领域时所知道的事情,如

软件开发质量管理的一些思考

PMBOK里关于质量管理主要有3个过程: 制定质量管理计划 质量保证(QA) 质量控制(QC) 书看了5-6次,还是发现比较抽象,难以理解. 实际项目中,如何才能合理的考虑各种资源制约,更好的执行质量管理呢? 一般的正规流程大致如下: 需求分析-> 客户评审与确认-> 概要设计->内部评审-> 详细设计->内部评审->编码-> 代码审查->单体测试 -> 集成测试->问题修复-> 代码评审-> 测试确认-> alpha测试-&g