0%

原文:Start from Yes

最近,我到杂果店里买“毛豆”(我对蔬菜种类只是大概了解)。我也无法确定这玩意是在蔬菜区,还是冷藏区,或者罐头区。我放弃了,找了个店员来帮我。结果她也不知道。

这个店员本可以给我其他答复。比如她可以让我一脸懵逼的去别处看看,或者给我个模糊的区域,甚至干脆告诉我他们不卖这个。但她没有,她想抓住机遇一样对待这次询问,争取找出答案帮助顾客。她找来了其他店员并在很短时间内给了我可靠选项——在冷藏区。

在这种情况下,店员看了下请求,然后基于“我们能解决问题并给予满意答复”的前提开始行动的。她从yes开始,而非no。

当我头一次当上技术主管角色的时候,我觉得我的工作就是将那些来自产品经理和商业分析的可笑需求挡在门外,以保护我美丽的软件。我发起的很多谈话,都是将请求视作否定,而非允许。

某一刻,我突然顿悟,或许有不同的方式来工作,只需要把我的观念从no倒转为从yes开始。事实上,我开始相信,从yes开始是一个技术领导者的基本素养。

这个简单的变化彻底改变了我的工作方式。事实证明,有非常多的机会说出yes。当某个人和你说:“呐,如果我们将所有的窗口都做成半透明的,那这app确实就想蜜蜂的膝盖一样!”,你肯定会把它当个笑话给驳回了。当它通常用“为什么?”来开头更好。通常情况下,由于某些必然的原因,人们会要求圆形、半透明的窗口放在第一眼的位置。例如,你可能和一个新的大客户签订了圆形半透明窗口的委托书。

通常,你会发现当你了解的请求的前因后果,新世界的大门就打开了。常见的就是以其他方式利用现有产品来完成请求,不用干活就可以说yes:“事实上,在用户偏好设置里,你可以下载并切换到圆形半透明窗口的皮肤”。

有时候其他人会有一些简单的想法与你的产品视角不同。我发现通常这对于转过来问自己“为什么?”会有帮助。有时候说出原因的行为会清楚的表明你的第一反应是没有道理的。否则,你需要提高一下格局来引导关键决策者。记住,这一切的目标是为了对他人说出yes并使其正常运转,不仅仅对他有利,对你和你的团队也是如此。

如果你能对功能请求与现有产品的冲突给出强有力的解释,那么你很可能对是否构建正确的产品进行高效的谈话。不论谈话是否结束,每个人关注的都是哪些是产品的本质,哪些不是。

从yes开始意味着和同事一起工作,而不是与他们为敌。

2020年的春节,一场战“疫”把大量人员扣留家中,无数公司启动居家办公模式,梦寐以求的好日子终于来啦!于是…上班族们崩溃了,根本不习惯,毫无效率可言。看来事实证明,远程工作终归是痴人说梦。那么,真是这样么?

我倒是觉得,主要是思维习惯停留在集中式办公模式,不论管理层还是普通员工,都不可能做到短期内立即切换到远程办公的思维模式。就好像一个吃惯鲜甜口味的上海人,突然带他去吃一顿麻辣火锅,他并大可能感受到其中的美味。

可以这么说,大部分坐在写字楼里所谓的白领阶层都具备远程工作的条件,因为他们工作中90%的活动和产出都是在电脑上完成的。换句话说,这群人,打开电脑,就能工作。

远程办公有太多好处,最突出的莫过于不用把生命浪费在通勤路上,工作时间和环境都有巨大的弹性。但一个从小受集中式办公影响的人,如果他想切换到远程办公,我觉得至少要有以下三方面的认识。

效率:异步协作与沟通

就拿“讨论问题”来说。我们会习惯于当面讨论,你一言我一语,这样会很快得出结论,然后投入干活,这是我们认为这很“高效”。反之,通过邮件或聊天软件的沟通,不及时,半天得不到结果,所以它很“低效”。

但这根本是两码事!当面讨论是同步的,邮件讨论是异步的。而且,直接用同步和异步来衡量效率也是种愚蠢的错误。评判效率要以事情的结果为标准,而非过程

面对面沟通时,双方都会进入口语化状态,因为要及时回复,思维就比较跳跃,想到什么说什么。一个未经缜密思考的决策,你能说的很完善?

邮件或聊天软件的沟通则相对会正式些,而且人们在发送之前拥有充足的思考时间(吵架时除外😂),此时他对某个决策的观点会有一定的想法,这种讨论的结果更有说服力,并且可作为双方的备忘纪要。

再者,我们认为集中办公“高效”的原因还有一点——及时性。我有一个想法,立刻就能召集人过来讨论,马上就能论证结果。反之,如果我把自己的想法发到聊天群里,半天没人理,如果我是领导,那多半只能得到几个敷衍的“赞”。

可事实呢,诸如视频编辑、程序员、设计师、文案这种知识创作型人才,他们需要足够安静的环境和时间来思考。在办公室里,打断一个人的成本太低了,屁大的事情也会被拉去开个短会,等你回来后会发现,自己的思路全被打乱了。

此外,我们往往会觉得那些重要且复杂的事情只有聚在一起才能完成。可事实上呢?普及数十亿设备的Linux操作系统,mysql数据库…伟大的开源软件大多了数不过来。但它们都是汇集了全球成千上万个程序员的思想,讽刺的是这些程序员分布在不同时区,素未谋面,仅仅靠“留言板”式的交流一起工作,而且大多不要工资。

你还觉得异步协作与沟通的效率低吗?

人才:自律牛人的胜利

相比于集中式办公,远程办公在招揽人才方面似乎有天然的优势,因为它不受地域的限制。换句话说,如果你住在一个三线城市,同样能雇佣一线城市的众多人才。反之,如果你相中的某个大牛就喜欢“隐居”,你也犯不着三顾茅庐。

但,远程办公对人才是极为敏感的。远程办公的员工必须具备两个基本素质:自驱力和较好的协作能力。

我们都知道,在办公室里总会有一堆“闲人”和一堆“看起来很忙的人”。不论他们人缘有多么好,这些人不适合远程,他们是低效的,在公司被监督着也能划水摸鱼,你还指望他在家的时候兢兢业业?

但还会有一帮人,他们属于没事找事型,可以自发地完成工作,给自己制定学习任务并真的完成。说白了,这群人可以从工作中找到快乐,就像为Linux开源做贡献的程序员一样。

一个自律的人,你不需要话太多精力去盯着他,直接给他需求目标,然后等着拿结果,这样的合作关系不好么?

管理:老毛病与新问题

远程办公时代,我们必须摒弃很多旧观念和习惯。比如上下班要打卡,事情必须当面聊,审批要有领导签字,要是不盯着员工他们就会偷懒,坐办公室里才叫工作…其实,这些都是工业时代初期管理流水线的思维模式。它是面向过程的监督式管理。用这种观念去管一帮知识创作的人,搞不好会适得其反。

事实上已经有非常多的软件工具可以把这些任务从线下搬到线上,但这也仅仅是一些方法而已。棘手的是我们的观念——总觉得员工会偷懒,必须监控着。

这种对员工不放心不信任的想法,让管理者即使用上新工具后产生了很多滑稽的现象。比如让员工在家打卡,动不动开个视频会议,写工作汇报,想法设法找点无关紧要的小事给他们做。这种行为并不是为了工作本身,而是为了宣扬权利。说到底就一句话:“我付了工资,又看不见他,不能让他闲着!”

然而呢,远程办公应该是以结果为导向,充分发挥异步协作与沟通的积极面,让员工用自己喜欢的方式施展才华。只要他把活干得漂亮,你管他是坐着还是躺着!再有,如果以事情的结果来评价员工的能力,那群“小白”和“忙人”也会很快浮出水面。

凡事都有两面性

不过我们也要清楚,远程办公会带来很多弊端:

  • 人是社交动物,长期独处一室会让人精神出问题的,还是尽量组织个聚会吧。
  • 长期久坐伤身,为了避免中年油腻,多鼓励员工运动吧。
  • 工作生活不分家,容易思维混乱,鼓励他们做一些仪式感的事情,暗示自己:我在工作,还是在生活。
  • 每个城市的工资标准不同,不能因为他住在三线城市就给他那边的待遇,应当公平公正!
  • 人一旦失去监督都会犯懒,工作文化变得更重要,考验你领导力的时候到了!
  • 狂人也很多,干起活来没日没夜,要提醒他们劳逸结合。

最近看到大家激烈地吐槽远程办公,所以想深入了解这个新鲜的老玩意儿。便读了《重来2:更为简单高效的远程工作方式》。由衷地感叹,未来是个体的时代,未来是创意的时代,未来是信息的时代。或者说,未来已来。

我们所看到的远程工作没有那么美好,那是因为我们早已习惯了现实世界的生活。但,趋势来了,你难道就打算这么看着?

原文:The Single Responsibility Principle

好的设计的一个最基本原则是:

将改变原因相同的事物放到一起,将改变原因不同的事物分开。

这个原则常被认为是单一职责原则,或者说SRP。简而言之,它是说一个子系统、模块、类、甚至是一个函数,不应该有超过一种以上的改变原因。下面这个例子是一个拥有分别处理业务规则、报告和数据库的方法的类:

1
2
3
4
5
public class Emloyee {
public Money calculatePay() ...
public String reportHours() ...
public void save() ...
}

有些程序员可能会觉得把这三个函数放到同一个类中是非常完美的。毕竟,类被认为是执行公共变量操作的函数的集合。然而,问题在于这三个函数是对完全不同的原因作出的改变。calculatePay函数是作用于薪酬计算时的业务规则。reportHours函数作用于某人期望得到不同格式的报告。save函数作用于数据库管理员变更数据库时。这三种变化原因的结合会让Employee变得不稳定。其中任何原因都会使其发生变化。更重要的是,任何依赖于Employee的类也会跟着受到影响。

好的系统设计意味着我们可以把组件独立部署到系统里。独立部署意味着即使我们修改了某个组件,也没必要去重新部署其他部分。然而,如果Employee被大量地应用到其他组件的类中,每次我们改变Employee都会使其他组件被重新部署,从而抵消了组件设计(或着说SOA,如果你喜欢髦的术语)的好处。下面这种简单的分离就能解决这个问题:

1
2
3
4
5
6
7
8
9
10
11
public class Employee {
public Money calculatePay() ...
}

public class EmployeeReporter {
public String reportHours(Employee e) ...
}

public class EmployeeRepository {
public void save(Employee e) ...
}

每个类都有属于自己的归属。确切地说,所有的报告类都可以放在报告组件中。所有的关系数据库类都可以放在资料库中。所有的业务规则都可以放在业务规则组件中。

精明的读者可能注意到,上边的解决方案仍然是依赖关系。Employee仍然受其它类的依赖。如果Employee被修改了,其他类似乎也不得不重新编译和部署。因此Employee做不到修改后独立部署。然而,其他的类是可以做到修改后独立部署的。对它们当中任何一个的修改都不会迫使其它的重新编译部署。甚至Employee通过谨慎地使用依赖倒置原则(DIP)也能够独立部署,但这是另一本书的主题了。

谨慎应用SRP,把不同变化原因的事物分离开来,是创建具备独立可部署的组件结构的设计关键之一。

原文:Simplicity Comes from Reduction

“这个重做…”

我老板一边说着一边把他的手指去按Delete键。当我的代码(一行一行的)灰飞烟灭后,我盯着电脑屏幕在哪发呆。

我老板,Stefan,并不总这样直言不讳,但他看得出什么是烂代码。并且他很清楚如何对付它。

我的定位是一名程序员初学者,体力充沛且富有激情,就是不知道如何变成。我有种可怕的思维倾向,即解决任何问题都是去某些地方增加变量,或者在行内throw。那是糟糕的一天,本来是要通过每次修改来优化这项逻辑的,但我的代码逐渐增大,越来越复杂,已经不能像原来一样工作了。

自然的,尤其是当你很焦躁的时候,本来只是想对现有代码进行最小修改,却越改越糟糕。大部分程序员都会维持烂代码,相比于恢复原状,重来明显要花费更多精力。对于那些可以正常工作的代码而言,这是正确的选择,但对于那些“跑飞”的来说,则无济于事。

浪费在挽救不良工作上的时间已经超出了它应有的。一旦某项事物变成了资源包袱,它就应该被抛弃。尽快!

并不是说所有的类型、命名、格式都简单粗暴的扔掉。我老板的反应太极端了,但它却是强迫我第二遍(偶尔第三遍)重新思考代码。当然,代码被无情地重构、转移或删除的机制,确实是修复烂代码的最佳方案。

代码应该简洁。应该最小化变量、函数、声明,以及其他必要语言语法的数量。多余的行、多余的变量…多余的任何事,确实,应该立即清除掉。剩下的那些足够完成算法或性能计算的工作即可。除此以外都是多余的,不必要的噪音,偶然的引入,掩盖了流程也隐藏了重要的内容。

当然,如果这样不行,那就把它们删掉并重来。通过这种方式抽出一个人的记忆,通常可以帮助消除大量不必要的混乱。

《重来:更为简单的商业思维》的作者是37signals的合伙人,这是一家软件开发商,只有十多名员工——遍布于两大洲的8座城市里老死不相往来,他们“拒绝长大”,没有财务规划和5年计划,办公开支甚少,却盈利颇丰。好神奇,这么“小”的一家公司,是怎么活下来的。

一、放下陈旧观念吧

失败不一定是成功之母,失败只能帮你鉴别掉过的坑,还有很多从没见过的坑等着你掉呢。

不要被“现实世界”束缚,信息爆炸的时代,却要强迫一群平庸的人定时定点聚在一起混日子,真的好么?

工作狂不是英雄,透支身体只会出更多的错,还会给身边的人造成不必要的压力。

少去做中长期规划,所谓的中长期计划大多是拍脑袋瞎猜而已!你要知道人们对工作量的预估其实是非常不靠谱的。

公司大了,变革性降低,精力分散,灵活度下降,成本升高,你确定自己驾驭得了?

二、做一个行动派

“没时间”只是你的借口,那句话怎么说来着…就像乳沟,挤一挤总是有的。

当然,你还有很多堂而皇之的借口,比如喜欢开会,目标宏大、追求大而全、过早关注细节等等。这些借口的背后都指向了同一个因素——效率。

效率是指事情从0到1完成的投入产出比,一定要记住这个大前提——事情完成

如果你喜欢半途而废,那你追求效率就毫无意义。如果你真的像有效率,应该从产品的核心出发,速战速决,把产品做出来,跑起来,然后接着改进和扩展。

如果你的团队一开始就关注产品外包装该用什么字体,立项流程改怎么走,人员绩效考核方式,并总是以研究讨论的名义开会闲聊,你就知道这活是干不下去的。

所以,团队里务必警惕那些懒散的伪装,有想法行动起来,把它做出来。

三、兵不在多而在精,将不在勇而在谋

现在创业的套路是“融资+烧钱+疯狂扩张”,似乎只有大体量才是王道——大而不倒,强者恒强。但是这么做的后果是公司会养的很“胖”,而不是“壮”。

如果是一家正在成长的小公司,会根据业务需求本能地选择招兵买马,但你确定人人都有活干吗?一个公司百把号人相互连名字都对不上号,每天上班像是来参加化妆舞会,一哒哒二哒哒…领导说啥我做啥,领导走了我睡觉。

所以,一定要在受不了的时候再招人。

然后,小公司更需要独当一面的人才,有执行力的人不需要制度的鞭策,混日子的人你就是牵只老虎来盯着,他也能摸鱼。

其次,招聘和留住的人才,除了有执行力,还要有能力。但要注意,不是每一个牛人都适合你。比如人家是世界500强副总裁,你一个不到10个人的小公司花重金把人家挖来又能如何?放过彼此吧。

如何识别一个人是否有能力呢?其一:在实际工作中观察,对于两个披萨就能养活的团队,你要相信,谁有几斤几两大家心知肚明;其二:看他写的文章,虽然“写作能力”不等同于“工作能力”,但一篇文章写得好至少说明他思路清晰,一个思维是杂乱无章的人,你还指望他把事情做得漂亮?

最后,你会发现网上招聘要求几乎都是一个模式:学历、工作年限、所在城市…你仔细想想,一个人工作是否热情和他的学历及工作年限真的相关吗?而他的工作就非得朝九晚五呆在办公室完成?

很多精兵强将,明明是你自己放弃的。

四、要成就事业,不能只是创业

你的创业动机是什么?赚钱?这太庸俗了吧。梦想?毒鸡汤喝多了吧。

选择创业,就会有员工、业务、客户等事物的出现。所谓梦想,就是通过这些事物的力量让世界变得更好;所谓赚钱,就是通过经营这些事物让公司盈利。梦想和赚钱应该兼而有之。只想赚钱,容易走邪门歪道;只谈梦想,一定是江湖骗子。

不过现在有很多创业者走上了另类的“盈利”模式——故事融资。

其实,不到万不得已不要融资。你虽然是创始人,可投资人进来后,你就有了“领导”,他只想尽早获利退出,要是弄不好就会带你走邪门歪道。此外,烧钱一时爽,你却上瘾了,不断回避公司如何真正赚钱的问题,这游戏还玩得下去么?

赚钱不耽搁你的梦想,有梦想的公司才会伟大。所以,从创业之初就应该问题。

其次,不要听风就是雨。要关注不变因素,拥抱经典,把自己的公司经营好。投资热潮随时再换,你跟得过来么。网红年年有,退潮后——尸横遍野。

The Road to Performance Is Littered with Dirty Code Bombs

通常,对系统性能调优需要你修改代码。当我们需要修改代码时,每处过于复杂或高耦合的代码块都是脏代码炸弹,等着蓄谋(让程序)跑飞。脏代码造成的第一批伤亡就会成为你的日程表。倘若前进的道路是平坦的,那你很容易预估完成时间。倘若遇到那些意外的脏代码,想要做出合理的预估就难咯。

试想一下你发现了某个执行热点的情况。常规的做法是将低基础算法的强度。假设你对经理的要求给出了预计3-4小时的答案。然后着手开始修复,你会很快意识到某个依赖部分被破坏了。通常关系密切的事物都是高内聚的,这次破坏更像是找到了原因并得到了解决。但如果把这里的依赖结果修复掉,那其他还在破损的抵赖部分又会发生什么呢?此外,这项依赖离它的发生出越远,你就越不可能在预估中辨别并解决它。很快,你的3-4个小时就会膨胀为3-4个星期。通常,这些意外会在日程表里放大到一两天。需要数月才能完成的“快速”重构并不常见。在这些情况中,一个有责任的团队的信誉及政治资本都会遭到极大(甚至是终极)的损害。如果我们能有个工具帮我们识别并量化这些风险。。。

事实上,我们有很多量化和控制代码耦合度及复杂度的方法。软件指标可以用来计数我们代码中具体功能出现的次数。这些计数与代码质量息息相关。衡量耦合度的指标之二即扇入和扇出。类中所谓的扇出:定义为直接或间引用感兴趣类的次数。你可以理解为你的类被编译之前需要编译的其它类的数量。另一方面,扇入就是指所有其它类对这个感兴趣的类的引用次数。知道了扇入和扇出,我们就使用I = fo / (fi + fo)计算一个不稳定因素。若结I趋近于0,这个包就会很稳定。若I趋近于1,这个包就不稳定。稳定的包对于重新写代码是低风险的,而不稳定的包更像是充满脏代码的炸弹。重构的目标当然是使I更接近于0.

使用指标时必须记住,它们只是经验法则。基于纯粹的数学,我们可以在fo不变的情况下增大fi,照样可以使I接近0.然而,又一个非常高的扇入值是很糟糕的:如果破解依赖关系,很多类就难以再修改。当然,如果不解决扇出问题,你就不可能切实降低风险,所以必须保持一定平衡。

软件指标的一大缺点是,计量工具所产生的大体量的软件指标数字可能会震惊到初学者。就是说,软件指标可以变成我们争取干净代码的利器。它们可以帮助我们辨别并消除脏代码炸弹,以免它们严重影响性能调整工作。

早在很多年前,曾国藩这个名字就如雷贯耳。当然,我听到的情况是,人们歌颂他“尚拙”的作风与“结硬寨打呆仗”的军事思想。总之就是不去投机取巧,一门心思脚踏实地把自己的基础打扎实,以达到无招胜有招,战无不胜的境界。

脚踏实地——当然是政治正确的口号,但试问有几个人会真的贯彻执行。我之前从未读过曾国藩相关书籍,但是听到他这种精神后,自然对其产生迷之崇拜。就像一个愤青面对自己的祖国,总是一副恨铁不成钢的样子。往深了,也说不来为什么,就只能人云亦云地喊喊口号罢了。

所以我想认真了解一下这个人,便通读了张宏杰这本《曾国藩传》。坦白讲,对于读过那么几本书的我而言,能识别出出作者在本书中有浓烈的个人主观色彩,但这并不影响它成为一本好书,也不影响我对曾国藩个人的判断。

我眼中的曾国藩

我觉得,曾国藩的伟大在于——平易近人。

怎么说呢?

你要是从后往前看,会看到曾国藩面对晚清颓势,力挽狂澜,创湘军、灭太平、兴百姓、办洋务,近乎以一人之力为当朝续命五十年。同时,他朋友门生遍天下,且多是社会中流砥柱,无不对他敬佩有加。此外,他修养极高,毕生弘扬儒理思想,身先士卒,又在权盛至极时甘于为朝廷做出牺牲。正所谓立德立功立言三不朽,他全做到了,堪称完人。

这样的人,不免让人觉得太遥远,我平民百姓只配瞻仰,哪能相提并论。

但你要是从前往后看,会发现曾国藩出身一般,顶多算现在所谓的中产阶级家庭,无背景无权势只能啃老。而且天资平庸,当年的“高考”考了七八次才考上。上了大学(翰林院)后,抽烟喝酒打牌,喜欢看人杀头,调戏美女,混日子。刚踏入社会(当官和创建湘军)后,对政府当局各种愤恨,直骂皇帝、弹劾同事、抱怨家人,总喜欢站在道德的制高点贬低他人来抬高自己,为人处事总要摆出一副舍我其谁的姿态。

这样的人,其实离我们挺近的。可如果把他的故事说成是“屌丝逆袭”,又好像不伦不类。

曾国藩并没有给我一种励志的感觉,反而是结局本该如此。

读书不行,那么就拼命学习嘛;
考试不行,那就钻研应试技巧嘛;
没有学问,那就读圣贤书嘛;
品行不端,那就严于律己嘛;
要打仗了,那就征战沙场嘛;
朝廷迂腐,那我不学就是了嘛;
受人排挤,那就善于人下嘛;
上司无能,那自己争点气嘛;
遭人妒忌,别往心里去嘛;

总之一句话——错了,那就改嘛!

是啊,知错能改,善莫大焉。问题是“知错”不易呀,试问有几个人能做到常自省,又有几个人听得进他人的忠言。即便真的意识到自身问题了,又有多少人贯彻“能改”。就好像“吸烟有害健康”对烟民而言,不过是句正确的废话。

一边自我感觉良好,一边得过且过。或许这就是为什么曾国藩能成为圣人,而我们只能沦为平庸的原因吧。

观其一生,曾国藩的伟大就在于此。他身先士卒,用自己的一言一行,在那个腐朽的王朝,没落的年代里,为这个古老的文明再次竖起灯塔,让那些优秀的思想得以继续在这片土地传承。

从愤青到圣贤

晚清以来,有一个规律性现象,那就是在对外交往中,凡是主张强硬,甚至主张“蛮不讲理”的人,通常都会获得民众的热烈欢呼,被称为“民族英雄”“扬我国威”。而主张和洋人“讲理”“妥协”的,几乎都会被骂卖国,被称为汉奸,声名尽毁。

书中这段评价很有意思,哪怕放到现在也未必过时。愤青的逻辑其实不在于政治正确,而是情绪宣泄。为了发泄自己的“爱国”情绪,所做之事一样蛮不讲理。

曾国藩年轻时候的表现却是像个愤青。他理直气壮地批评皇帝,压迫同僚,为人处事一根筋,只为证明自己是对的。当然,这也比现在的“键盘侠”要高级一点,至少人家是真刀真枪的干!

后来在官场上被别人玩得头破血流,方才恍然大悟。自己从前凡事据理力争,且不说容易得罪人,就是那种得理不饶人的态度,也无形中伤害了很多想对他好的人。所以他后来变得恭谦礼让,能够体谅别人的难处,能居人于下。“于理”的同时兼顾“于情”。但这只是其一。

曾国藩是个高级愤青,他可不是一介匹夫。在“救国”方面他有战略、有目标、有思想、有行动。只不过前些年忽略了自身环境和游戏规则。现在他已得要领,这也是为何在官场上他选择同流合污,却不自甘堕落的原因。他需要借助整个清政府体系的力量,但不是为了肥自己,而是为了兴国家!

关于“尚拙”

其实我个人的价值观是很能接受尚拙的,毕竟我也是这么要求自己的。简单来说,就是用一些看似笨拙的方法去完成那些重要的事情,骨子里就是不要想着耍小聪明,脚踏实地才是正道。尚拙精神非常值得推崇,但要小心,小心人性,稍不注意就会本末倒置。因为尚拙有一个很致命的前提,就是你的格局是否高。

难以戒掉的既得利益

人本能会追求及时满足,要达成某个目的,渴求马上达到。可惜决定一个人命运的往往是那些需要“慢慢消化”的小事。

这就好像跑步减肥一样,累死累活一天下来毫无变化,明天也是,后天也是,人就会放弃,去追逐那些轻松速效减肥之法。

再如工作中大谈人脉、选择、技巧等,而忽略了最基本的认真做事原则。学习上质疑读书无用,挑挑拣拣,只想学习那些马上看见成效的拳脚功夫,不肯修炼内力。

总之,尚拙需要一颗持之以恒的心,每天看似不重要且朴实的坚持,久而久之就会变得非同凡响。

用勤劳来掩盖懒惰

人本能会躺在舒适区,你可能觉得自己很努力,但那不过是无脑的机械重复罢了。

这就像奉行资历主义的人,以为只要工作年限够就会升职加薪。又或者只会墨守成规按流程办事,出多少力气都行,但别让自己动脑子,只做自己会的,永远不去探索自己未知的。

其实这种状态是很容易让人舒服的,生活一帆风顺,无忧无虑。可惜经不起半点风霜。

总之,尚拙需要一颗“天天向上”的心,经常自省,挑战自我,渐进式的努力才是有意义的。

Resist the Temptation of the Singleton Pattern

单例模式可以解决你的很多问题。你会认为只要单例模式就够了。这可以保证实例在初始化之前就能使用。通过一个全局指针访问就能保持你的设计简洁。这么经典的设计模式还有什么不对的地方吗?

其实太多了。它们可能很有诱惑力,但根据经验来看,其所带来的损害要大过好处。它们阻碍了可测试性和可维护性。不幸的是,这种认识应该还没有得到广泛的传播,单例模式仍然吸引住广大程序员中的。但它们值得被抵抗:

  • 单例需求是被幻想出来的。很多情况下,它只是对未来不会再有新增实例的纯粹推测。把这种推测贯穿到整个应用程序设计势必会在某些地方引起痛苦。需求总会变。好的设计拥抱这一点,单例模式不会。
  • 单例导致概念上独立的代码单元之间存在隐式依赖。所造成的问题是单例在单元之间是隐藏的,并引入了不必要的耦合。当你尝试写个松耦合的单元测试有选择性地来模拟真实情况的时候,这种代码闻起来相当刺鼻。单例简单粗暴地阻碍了这种模拟。
  • 单例还会带有隐式的持久状态,再次阻挠了单元测试。单元测试是彼此独立了,因此测试可以在任何情况下运行,程序在每次测试执行前也可以设置为一个已知的状态。一旦你在可变状态下引入单例,就很难达到效果。此外,这种全局访问的持久状态将会使代码变得更难以查找问题,尤其是在多线程环境。
  • 多线程进一步加大了单例模式的陷阱。简单的加锁访问不是很有效率,被称作双重验证锁的模式(DCLP)广受欢迎。不幸的是,这可能是一种致命吸引力的形式,不论在哪里,都仍然有可能弄巧成拙。

清除单例也存在着最终的挑战:

  • 不支持显式杀死单例。在某些情况下这是个很严重的问题,例如,在插件架构中,一个插件只有在所有对象都被清理干净后才能被安全写在。
  • 不支持在程序退出后隐式清理。对于含有相互依存的单例将会非常麻烦。当应用程序关闭时,某个单例可能会去访问其他已经被销毁的(对象)。

这其中的一些缺陷可通过引入额外的机制来解决。但无不如何,这样做的代价是增加了代码本可以用其他设计来避免的复杂度。

所以,把你使用的单例模式限制在永远不会实例化超过一次的类上。不要在含糊不清的代码里使用单个全局访问指针。相反,对单例的直接访问应该来自几个定义明确的地方,可以通过接口传递给其他代码。这里的其他代码是不知道它的,不需要依赖单例或其他类的实现接口。这就破除了单元测试的依赖性,并提高了可维护性。所以,下次你想要实现和访问单例的时候,我希望你能三思而后行。

Reinvent the Wheel Often

仅使用已存在的事物——就是在重新发明轮子…

你是否时常听到这种或类似的声音?确定你有!每个开发者或学生都会经常听到类似的评论。为什么呢?为什么重新发明轮子就这么愁眉不展?因为,很多时候,现有的代码是有效的。它已经通过了某种质量控制和严格的测试,并被成功地应用。此外,相较于使用现有的产品或代码库,把时间和精力投入到重新发明是不大可能有回报的。你还应该重新发明轮子么?为什么?什么时候?

或许你看过一些有关软件开发模式的刊物或软件设计书籍。先让这些书去睡觉吧,不管它们包含了多么精彩的内容。观看航海电影和真的去航海是非常不同的,正如使用现有代码对应了从头设计一个属于自己的软件,(需要)测试它、破坏它、修复它,然后逐步完善它。

重新发明轮子并不仅仅是代码从哪构建的练习:它是为了充分了解现有不同组件的内部工作原理。你知道内存管理机制?虚拟页呢?你能自己实现这些吗?什么是双向链表?动态数组类?ODBC客户端?你能写出一个你喜欢的流行图形界面吗?你会创建属于自己的web浏览器插件吗?你知道何时写一个多线程系统与多线程本身?如何决定使用文件数据库还是内存数据库呢?

大部分开发者根本没有自己创造过这些核心软件实现的类型,对其如何工作的也未必了然于胸。其结果就是这类软件看起来不过是个会运行的神秘黑盒。浅尝辄止是看不到潜藏在下方的危险的。不更生层次的了解软件开发将限制你创造出色作品的能力。

重新发明轮子并碰壁要比一用到底更有价值。通过试错学到的教训会有感性的成分,是阅读技术书籍无法给予的。

学习书本和实践至关重要,但要成为一个伟大的程序员则更多的要从实践中总结经验。重新发明轮子对开发者的教育和技能,就如同健身队举重运动员一样重要。

Read the Humanities

在所有的开发项目中,人与人共事。在除了抽象领域研究中,人们编写软件以到达他人的某些目标。人们编写软件给人用。所以这是人的生意。不幸的是,教导程序员如何处理与他们的服务对象间的关系却非常困难。幸运的事,这里有一整套有用的秘籍。

例如,Ludwig Wittgenstein (路德维格·维特根斯坦)就在哲学研究中讲了个很好的例子,我们所用的任何与别人交流的语言(都不是)一种序列化格式,无法将一个人的思维、或想法、或图片直接放入另一个人的脑袋里。因此,当我们在“收集需求”的时候,就应该注意防止误会。Wittgenstein还表明。我们相互理解的能力根本不来自描述共享,而是来自经验共享,来自生活的形式。这或许也解释了为什么喜欢浸泡在自己问题领域的程序员比那些浅尝辄止的程序员做得更好的原因。

Lakoff和Johnson向我们展示了《我们赖以生存的隐喻》(芝加哥大学出版社),暗示语言在很大程度上是隐喻的,这些隐喻为我们如何理解世界提供了见解。即使我们在谈论金融系统时也可会遇到看似具体的术语,例如“现金流”,可以把它视为隐喻:“钱是一种流体”。隐喻是如何影响我们对货币处理系统的思考的?又或者我们可能会谈论协议栈中的各层,有高层有底层。这是个很强力的隐喻:用户是“高层”而技术是“底层”。这也暴露了我们搭建系统结构的思想。这也可能标志着一种懒惰的思维习惯,而我们时不时的会从中获益。

Martin Heidegger 仔细研究了人们体验工具的方法。程序员会构建并使用工具,我们思考、创建、修改、重构工具。工具是我们感兴趣的对象。但对于它的用户,Heidegger在《存在的时间》所展示的那样,工具变成了一种看不见的东西,只有在使用时才能理解。对于用户来说,当工具不工作时,它就会变成一个感兴趣的对象。每当讨论可用性时,都应该牢记这种差异的重要性。

Eleanor Rosch 通过组织我们对世界的理解,推翻了Aristotelean 的分类模型。当程序员向用户询问系统需求时,我们倾向于要求他们以谓词来定义。这对我们来说是非常方便的。谓词中的术语可以很方便的变成类中的属性或数据表中的列。这些分类是清晰的、不相交的、整洁的。不幸的是,像Rosch 在“自然分类”及其之后的作品中所展示的一样,这并不是人们通常对世界的理解。他么需要通过实例来理解。一些实例,所谓的原型,要比其它方式更好,其分类结果是模糊的,重叠的,内部结构是丰富的。若坚持Aristotelean的观点,我们在用户的世界里对他们提出正确的问题,并难以达成共识。