我们很少看到有人公开谈论自己的错误。
人非圣贤,孰能无过?虽然难言出口,但反思过去所犯的错误可以让人不会在未来——至少是短期的未来,犯同样的错误。
Mohamed Barouma是位工作5年的专业程序员,但和任何人一样,他也犯过错误。
他这么说:“通常情况下,我不会马上意识到自己做错了什么;只有在接触到正确的做事方法后,我才知道犯了哪些错。”
结合他的原文,本文总结了他犯下的七大误区。
1、没有使用合适的ORM
数据访问层代码总是混乱、乏味和无聊的。不幸的是,往往这点到最后才能发现。
Mohamed和ORM有着一段孽缘。ORM,即Object Relational Mapping,它是对象关系模型的简称。它的作用是在关系型数据库和对象之间作一个映射,使程序能够通过操纵描述对象方式来操纵数据库。
当Mohamed第一次做一个简单的内部会计应用程序时,他发现只是为了完成基本的程序,就不得不编写大量的代码。于是他开始埋头于ADO.NET,并手动编写了一个自制的、具有非常特殊的、自定义的表模式的ORM,来满足目的。
在一段时间里,这个ORM工作的相当不错,直到几个月后,公司的业务需求发生了一些变化,这导致了整个表格模式的变化,然后,就是对ORM的反复修改。这个流程的痛苦之极,让Mohamed最终选择了强类型数据集适配器。
虽然这件事因此解决,但如果能找到一个更合适的ORM(比如NHibernate)来完成工作,Mohamed仍会义不容辞,至少当他的用户数量增加时,不必担心更改数据库的供应商。
2、没有学会使用泛型
Mohamed Barouma的职业程序员生涯始于Net 1.1。而在当时,Net 1.1的主要问题在于它没有泛型支持,这代表它不能有一个强类型列表,只能满足于乏味的ArrayList。但是使用Arraylist在Java代码中进行类型转换和装箱,会导致读写起来十分痛苦。
因此,Net 1.1的程序员们使用CodeSmith生成一个强类型集合列表。
但随着代码库的增长,那些定制生成的列表本身就变成了一个无法收拾的怪物。只要经常为了创建对象或调用方法去达到目的,随后就会因为修改代码导致混乱和错误。
如果切换到Net 2.0,并在它可用时立即开始使用泛型,而不是创建越来越多的难以维护的自定义集合列表,那么一切问题都将迎刃而解。
3、没有放弃“造轮子”
这是个老生常谈的话题,“反复造轮子”(Reinvent The Wheel)。新程序员总是喜欢反复“造轮子”,自认为当前的实现不够好,所以不得不从头重写整个东西。
为什么叫“造轮子”?就像真正的的轮子早在几千年前就被确定是圆形的一样,很多数据库也早就已经成熟易用了,但还是有数不胜数的程序员们锲而不舍的去“造轮子”,有的人飞蛾扑火、蚍蜉撼树,有的人别具一格、推陈出新,这就是“造轮子”魔法一般的吸引力。
这其中也不乏Mohamed,他想重新编写自己的UI控件,因为Windows Forms UI控件实在是太简单了。最后,他造的GUI工具被商业化成体系的.Net UI控件轻松打败,又一辆新生程序员造的“轮子”被击沉到了代码海洋里。
4、没有精简过多的文档
很多刚入行的程序员,会在一开始觉得代码文档很好,因为它用简单的英语注释了代码在做什么。但事实上这些文档通常在修改了几次代码之后变成了一摊废纸,变得陈旧、过时亦或是完全错误。
常常有人花了很多时间编写代码文档——比如XML文档,结果发现在更改代码时需要更新文档。因为它的功能可能都已经改变了。更新代码是必须的,但更新XML文档不是必须的:这是一种负担,它消耗时间,而且毫无用处。
最终,反复地更改XML文档使人逐渐失去耐心,转而做其他事情。
5、没有使用自动化构建
应用程序的部署和打包比编程相对容易,所以它往往被放在了非常低的优先级上。但很快,粗制滥造的构建就会因为无法工作,受到各式各样的投诉:
“先决条件缺失,该如何修复?”
“dll没有更新,你能给我一个补丁吗?”
“我的图标怎么不见了?”
紧接着,电话像雪崩一样源源不断地打到桌旁。这是Mohamed的真实经历,并让他那天精疲力尽——不是因为编程,而是因为令人麻木的重新部署和重新包装过程。
而这一切,本可以通过编写自动化脚本节省一些时间,否则在事后debug浪费的时间绝对比可以节省的时间多上数倍。应该让软件可以一键构建,否则再多都是一种浪费。
6、没有停止对视觉检测和debug的依赖
Visual Studio让人们可以很容易地调试代码并进行动态检查,这也使得创建一个表单并显示输出非常简单。但如果太沉迷于调试器,这项好处就要变成坏处了。
为什么呢?想象一下,如果一个方法只在应用程序启动并运行45分钟后才被调用,那难道要打算等45分钟再开始调试吗?
所以,动动手将应用程序分解为可以独立调用的子模块,这样就可以准备产生错误输出的输入值,并从那里开始测试它。
7、没有做单元测试
不少程序员可能这么想过:“我的这个应用程序微不足道,它可以很容易地被手工测试覆盖;单元测试是针对大型和复杂的东西,而不是针对我的程序。”
可想而知,这会直接亲手创造一个没有关注点分离,难以重构,完全不可维护的代码库。
“蹑手蹑脚”几乎是许多小白程序员的通病,害怕对代码进行哪怕是最轻微的修改,因为任何更改都可能导致或不会导致破坏性的更改。结果到最后一发不可收拾,出现的问题无法解决。使用这种遗留代码不仅仅是无聊和紧张,而且精神上也有压力。
但是使用单元测试,能让代码的寿命大大提高。Mohamed希望自己能学会单元测试的“艺术”,从入学第一天开始练习单元测试,可惜学校并不教这个。
世界上,无数令人为之一振的创新发明都源自无数次的试错,但即便如此,避免基础性的错误依旧是很有必要的。在你的程序人生中,还遇到过哪些令人啼笑皆非的“常见误区”?亦或者是创造了一些百思不得其解的“致命误区”?欢迎下方留言,分享你学习编程时的心得体验。
参考文献:
https://betterprogramming.pub/7-big-mistakes-i-have-made-in-my-career-as-a-software-engineer-f14ef540be10