More Joel on Software 读书笔记

P4. Excel的日期函数:1900年2月29日?

无论开发操作系统还是个人网站,不要停留在API的表层,要看到它的背后。如果我是微软的Excel程序经理,我能回答Bill的“最难的问题”吗?99%的时候不能!如果我是Bill,我能在一个晚上看完500页的SPEC、在每一页上留下评注并最终问出那个“最难的问题”吗?100%不能!这就是区别。

So What? 虽然很想想当然的说:“看源码”,但如何操作真的很难。也许对于那门必须“精通”的手艺,我得看看它背后到底是什么了。

PS1. (至少在高科技领域)管理真的是通用职能吗?不懂得技术的人,真的能管好一家IT公司吗?更加现实的问题是,一个与电脑绝缘的CEO,真的能招募到一个超绝的CIO,然后让公司“信息化”吗?我深表怀疑。这好像让一个没有品位的地产商去发掘艺术家一样。尤其是在IT和其它高新技术领域,最近5年的发展足以让最近50年的成功失色,而最近10年的进步足以埋葬100年前所有的教条,对于这样的领域,口碑和多数派的意见都是毫无意义的指标!所以,最可能发生的是,多数中小型企业永远也无法招募到像样的信息化团队(因为那帮HR和C*O不知道啥是像样的IT),不过这不要紧,因为多数人都没有见过真正的好东西,所以差一点的他们也会接受。推论是什么?如果呆在一家非IT公司,我的职业发展方向究竟是什么?也许必须结束坐井观天的生活了:(

P10. 优秀的程序员是不会出现在招聘市场上的

是的,优秀的程序员(系管、DBA以及其它若干职位)不需要到处投简历。在我最近收到的一千封简历里,我从来没有找到一个100%符合要求的候选者,哪怕只是要招一个系统管理员。(必须说部分原因是如今的IT技术分化太细,几乎无法要求一个候选人符合所有的要求,除非你只是需要一个“专家”。但当你无法随身携带所有的扳手和钳子的时候,你确实需要一把瑞士军刀。这也是个令人头痛的现实,如果你要做个专家,那么如果你没能成为TOP100,那么别人不会甩你,你可能会失业;而如果你要做个通才,那么你注定拿不到TOP100的薪资……头痛)多数求职者的简历充满了各种笑料(或悲剧),有的简历甚至成了老朋友,每个星期都能看到一次(这也许就是为什么他们必须留在招聘市场的原因)。好的求职者不用到处发简历,同理,好的职位也不需要到处贴招聘启事——黑客们有他们自己的圈子,内部消化这些空缺永远都是第一选择。

P13. 走出去

所有IT人都有阿斯伯格综合征(亲爱的老板,如果你不幸看到这段话,请不要怀疑我的精神有问题,这是个比喻),总是希望只在自己住处的方圆一公里内活动。但如果你需要雇一个杀手,那你一定没有理由在社区里贴寻人启事。想象一下你需要的人会去什么地方,走出去,逮一群回来。更重要的是,既然我想获得一份好的差事(亲爱的老板,如果你不幸看到这段话,请不要怀疑我的忠诚有问题,这是个比喻……OK,其实不是),想象一下我需要变成的那种人会去什么地方,走出去……被别人逮去。

P14. 实习生

如果10年以前看到这段文字,我的人生绝对不会一样(按蝴蝶效应推理,此系废话)。不过话说回来,Joel的人才观……有远见!

P19. 建立社区*

Joel给这个方法加了个星号,表示很难。换个角度,如果你希望被人注意,加入一个社区,弄点动静出来!

P19. 员工推荐:小心陷阱

聪明的程序员一定认识其他聪明的程序员?可能确实认识,但是他们的亲密朋友中也会有人不是非常优秀的程序员……无法回避的巨大风险,就是竞业限制(Noncompete agreement)……你可能雇了一堆人,他们的前雇主都是同一家,那门你将承担非常巨大的风险……如果人事经理决定为有效的推荐提供一点奖金……突然之间,你手下的整个大军都在设法让你雇佣一个对你毫无用处的人。

PS2. 做IT的人不比别的行业聪明,但玩起逻辑则几乎所向无敌(另一类逻辑大师是律师,两者都擅长逻辑,区别在于,IT的规则是不可逾越的,你不可能通过一个另类的“诠释”来让系统从宕机中恢复过来,也不可能通过舆论来让C编译器忽略你的错误,而法律的规则虽却总能“诠释”)。所以当HR们上完MBA课程后试图“绩效奖励”,回报他们的通常总是杯具——更杯具的是这些HR们根本不会发觉发生了什么事。

P28. Hit-and-run

大多数时候我们都被上司扔在那里(同时我们也把下属扔在别的什么地方),但是偶尔他们也会介入,追问一些极小的细节(我们则介入下属的某些细节),这就是多数团队中可以看到的Hit and run。但如果你要雇佣聪明人(或你雇佣的已经都是聪明人),你就必须小心,因为不管什么技术问题,“经理们知道的很可能不如在壕沟里干活的工人们”,当你雇佣专家的时候,让他们在专业领域里去做决定,尊重他们。

P31. 使用非必要的热门新技术

嗯,接触新技术确实可以让我开心。

P32. Identity Management

世界上只有一个苹果公司。事实上,大多数公司都能有效的实施自我认同管理,只不过不是针对所有员工罢了——通常是销售部门。

P36. 军事化管理

亲密不会让士兵面对危险时挺身而出,恐惧才会。(腓特烈大帝)

IT人很自负,不愿意被管;和军队不同,IT团队每个人做的事都不一样,无法进行微观管理;将军们总比士兵知道更多的情报,而经理们知道的永远比程序员少。结论:军事化管理是为了让18岁的年轻人在地雷阵里发起冲锋,对IT团队无用。

P40. The Econ 101 Management Method

等于鼓励IT人与制度博弈。参考Measuring and Managing Performance in Organizations,Robert D. Austin.

P46. 认同法

创造一个有凝聚力的团队;向员工提供必要的信息。

P50. Java……太简单

指针、递归、函数编程,Joel坦率的说,除了那些“令人激动”的任务,大多数情况下都不需要使用它们。的确,我从来没有在单位里使用过指针(最近学Go语言,情况有变,但Go只是“具有指针”但不允许“指针运算”,所以我想Go也不符合Joel的标准,唉,复习C吧),很少用递归(一般只在元编程和有自包含结构的情况下使用),而函数式语言则根本没有使用过(但按照Joel的描述,他指的并非是纯粹的函数编程,像闭包这样的操作也被包含在其中,这样的话,Groovy是支持的,还特别好用)。但总的来说,重新审视一下C或者Haskell这样的语言,哪怕是把它们当作智力测验,也会对一个程序员有莫大的帮助吧。(也许还要学习State machine)

P61. 当程序员遇到问题的时候,他们会把问题重新定义

……使其可以用算法解决,从而把问题转化成他们可以解决的形式。但实际上解决的只是问题的某种外在形式。

P61. 务实派 vs. 技术派

考虑到边际效用递减原则,一味追求“没有错误”的代码将得不偿失。另外,规格说明书永远也不可能完美,总是存在Shannon Entropy。

P67. 内用软件

1. 永远不能用正确的方法做事(只能用最保险的);2. 永远做不出优秀的产品(一旦一个项目可以运行了,你就得转战下一个项目,而不是精益求精);3. 管理层永远不会依赖你。我原本以为我的战场就应该是内用软件,但现在,我觉得Joel是对的。

P77. 微观经济学

这是书里最重要的建议之一,学习它,搞清楚生意为什么是那么做的,要懂得基本的商业规则。

P88. 用户喜欢哪一种处理方法?

……反映了一个事实,如果你问人们喜欢什么样的风格和设计,除非这些人受过专门训练,否则他们一般会选择自己最熟悉的品种。引申:当我说A比B好的时候,很可能只是在说我更熟悉A而已。引申2:没事别让你的客户选择,他们会选自己以前见过的,而不是他们需要的。

P92. 微小的改进

为了发现可以改进的地方,你必须有一个思维定势,始终如一地用批判的眼光看世界。随便找一样东西,如果你看不出它的缺点,那么你的思维转型还没有成功。呃……讲那么复杂,不就是鸡蛋里挑骨头吗,我擅长。

P95. 总是觉得自己看到了全部,即使事实不是如此

在软件开发中,这是一个特别危险的陷阱……形成了一个整体的设想,想好了下一步要做什么,一切看上去都清晰无比……马上一头扎入工作……

P99. 阅读列表:

Soul of a New Machine
Show Stopper

P101. The Paradox of Choice: Why More Is Less – by Barry Schwartz

太多的选择最终限制了我们的自由,而不是解放

P119. ……不顾一切的想要逐句驳斥……

编程工作要求一个人在每个i上面点上一点,在每个t中间画上一横,所以他们形成了一种思维定势,就是绝对不能不回应争论。
这确实是我的风格,原来这种风格还有一个学名:Fisking(源于一个从来不上网并认为Email和Blog属于浪费时间的英国佬的名字)

P137. 关于鲁棒性原则

Jon Postel的Robustness Principle经常导致部署上的难题,原因是对他方的行为宽容(liberal)的后果是导致他方软件的错误暴露之前已经大规模部署,从而造成既成事实,最终导致问题被发现时已经没有合适的解决方案。
我猜想鲁棒性原则还是会被大量使用,毕竟现实中垃圾输入太多,如果坚持严于律人的话,很快就没啥活好干了。

P147. 不要试图读写Office二进制文件

使用COM自动化让Office为你干脏活;使用更简单的格式生成文件。
无论我是多么固执的Unix学派,了解COM组件的操作都是非常有必要的。(再顽固也不会比Mac Fans顽固吧。最近看了13年前Jobs重组苹果董事会时进行的演讲,讲到一半Jobs说要和MS合作,会场内立刻嘘声一片,讲到将支持IE,嘘声一片,播Gates的讲话,还是嘘声一片,但唯有宣布Office支持的计划时,全场掌声雷动。任何一个有理智的人都不会否认MS Office早已成为事实上的标准,如果你玩不转Word或Excel,那么多半在求职市场上你也玩不转。)

P156. 为什么软件开发者不太愿意做日程规划

第一个原因是做起来比较麻烦;第二个原因是, 没人相信日程规划是可行的。

P157. Evidence-Based Scheduling

基于已知的历史记录(足够多的预期/实际比对数据),使用Monte Carlo simulation对任务的完成时间做出预测。
PS. 目前(我所知的)唯一实现EBS的管理软件就是Joel的FogBugz,你可以注册FogBugz的试用帐号并将其切换到2用户以下的免费模式。

P177. 你的编程语言做得到吗

很意外,我的编程语言做得到,事实上,即使是Java也能在某种意义上(痛苦的仿函数API)实现MapReduce。对于Groovy而言,闭包几乎可以满足你的一切。
PS. 当看到182页的时候,Joel指出,Java允许使用functor,当然,他也同意说着很痛苦。

P19*. 书写规范与匈牙利命名法

我并不完全赞同Joel的说法。Joel的目标很明确,无论是否使用匈牙利命名法,对于一个指定的实例而言,不应该对其进行语法上正确但语义上错误的操作。但在实践中,Joel的办法是更多的依靠人,让人眼睛一看到变量名就会意识到某些操作是允许的而另一些则要被禁止,但无法防止编译器放过人的疏漏;而大多数OO语言的方法则是从语法(确切的说是语句上下文)上把无语义的操作定为错误,但无法强迫人去做此类设计。在现实情况下,多数的Java程序员(尤其是OO新手)都不能做出正确的OO设计来防止非法的语义操作,但很不幸的是,让他们去使用匈牙利命名法的后果将一样的糟糕(因为他们将无法正确使用命名策略)。事实上我认为在如今强测试的编程风潮下,两种做法的带来的唯一显著区别将是OO语言(比如Java)将被迫对程序做最细致的切割。这在一定程度上会导致设计难度的提高,但我认为对后续的维护而言,细致的OO设计将胜过Joel的推荐方法。

P210. 本质上,软件的复制成本为0

这意味着如果软件的销量大,质量的改进几乎不会造成单位成本的增加,但却会创造出远远超出其开销的价值。

P221. 仿生学办公室

你的办公室不会和Fog Creek的一样好。但是有几点是可以做到的:许多许多的电源接口(而且和电脑桌齐高);许多各式各样的数据线桥架;预算内能买到的最舒适的椅子。
目前我的期望是:两个巨大的接线板、高速的无线AP、两块白板(挂在我身后的玻璃墙上,这样老板就再没法透过玻璃看到我在睡觉了)、一个靠垫。(老板,可以派一个按摩师吗)

P226. 他山之石

对你最重要、最关键的部分,一定要使用更原始的工具。这也是我的习惯之一,但是要小心,注意只有“最重要”的部分才适合这么做,否则,你会发明一大堆的非标准轮子。(我的军火库已经超过米其林了)

P241. 一次性支付

当客户遇到一个技术问题的时候,合理的做法让开发团队一次性解决它,而不是让技术支持团队一遍又一遍的去处理。

P280. SLA

最大的问题是缺乏制定标准必须的统计资料。另外,对于服务稳定性而言,无法避免黑天鹅难题(Nassim Taleb),即小概率事件。对此,应该学习丰田的五个为什么。

Others

关于软件定价,这是一个我即将考虑的问题,我喜欢开源,但我需要钱:(

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


背景:    8月29日,凌晨4点左右,某服务告警,其中一个节点直接down掉,收到告警的同事让运维重启。    9点左右,内存监控上发现内存异常,堆内存涨速很快,即便GC也没有什么效果,频繁GC。    9点38,服务各种超时,影响整个app使用。处理方式:    当时由于很想要
https://support.smartbear.comeadyapi/docs/soapui/steps/groovy.htmlGettestcaseobjectToobtaintheobjectwhichreferstothecontainingtestcase,usethefollowingcodesnippet:Groovy def case=testRunner.testCase; Byusingthe tes
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能。查看最流行的扩展机制,比较性能并分析哪一个是最好的。  这是乐队之战,JMeter风格。 BeanshellV.JSR223V.JavaRequestSampler 在我们之前的帖子中,  JMeterPerformance和TuningTips  ( 由fantastik
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,同时支持面向对象Groovy:jvm上的脚本,较好兼容java语法,Groovy加强了Java集成。 可配置化的优势,可以将一些简单的逻辑公开给外部编辑和使用,增强了互操作性,复杂逻辑来说,可配置化代码的调试则会比较麻烦 Scala和Java
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部元件的访问testRunner.testCase开头1、向下访问testRunner.testCase.testSteps[testStepName]testRunner.testCase.getTestStepByName("新增一个空间")2、向上访问,用于访问同一项目中的其他testSuites和testCase下
在运行groovy的junit方法时,报了这个错误:java.lang.ExceptionInInitializerError atorg.codehaus.groovy.reflection.ClassInfo.isValidWeakMetaClass(ClassInfo.java:271) atorg.codehaus.groovy.reflection.ClassInfo.getMetaClassForClass(ClassInfo.java:241) atorg.codeha
基本语法1.Grovvy的注释分为//和/**/和java的一样.2.Grovvy语法可以不已分号结尾.3.单引号,里面的内容严格的对应java中的String,不对$符号进行转义.defs1='iamastudent$'printlns1iamastudent$4.双引号“”的内容中如果有$号的话,会先对表达式先求值.de
Tiobe发布了最新一期(3月份)编程语言欢迎度榜单,其榜单根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube统计出排名数据。TOP5几乎没有变化,Java和C语言牢牢占据前两名。Python相较去年上升一位进入TOP3,C++下
我有一个Google地图组件,作者可以在其中指定纬度和经度.我正在使用带有正则表达式的常规“输入”类型控件来验证它们是否是数字,但是,当试图解决指定范围的问题时(经度验证该值在[-180,180]内并且纬度[-90,90])但是,通过正则表达式进行验证似乎很麻烦,而且利用inputtype=“numb
我正在为未来的应用程序评估SpringBoot,并希望使用Groovy模板来实现其纯粹的可读性.不幸的是,我在迭代我添加到控制器返回的ModelAndView对象的对象列表时遇到了麻烦.这是我的控制器:@RestController@RequestMapping("/ships")publicclassShipsController{@Autowired
我有一个基于Spring的java应用程序,其中包含一些有用的组件.作为系统的一部分,我有一个groovy脚本,来处理一些报告.我想从groovy脚本中调用spring组件.当我用Java编写时,我需要在@Component中使用@Autowired注释,即@ComponentclassReporter{@AutowiredSearchServicesearchS
在Grailsi18n插件definedthusly中定义了一个messageSourcebean:messageSource(PluginAwareResourceBundleMessageSource){basenames=baseNames.toArray()fallbackToSystemLocale=falsepluginManager=manager....}是否可以覆盖我的resources.groovy中的fa
我正在寻找一种方法来反向工程RDBMS表(MSSQLServer)并生成JPA@EntityGroovy类.我们目前没有选择使用Grails和/或GORM,因此Grailsdb-reverse-engineer插件似乎很接近但不太正确.它生成符合GORM的类而不是JPA实体类.我们目前有一个gradle构建,它利用org.hibernate.tool.ant.Hibe
https://blog.csdn.net/Gdeer/article/details/83062523一、直接运行groovy程序因为groovy插件和android插件不兼容,所以不能在原始项目上使用groovy。 新建module,创一个JavaLibrary,取名lib。  修改lib/build.gradleapplyplugin:'java-library'depe
一、自动生成GET请求脚本1、配置Createascript在ngrinder管理台主页,点击script–>Createascript,并填写脚本名称和请求的url,如下所示:点击Create按钮,nGrinder会自动生成对应的脚本结构,如果没有参数需要设置的话,可以直接运行了。二、详细解析GET请求脚本ngrinder自动生成的脚本
我正在关注使用列表和地图作为构造函数的this博文.为什么以下列表无法强制反对?classTest{staticclassTestObject{privateinta=1;protectedintb=2;publicintc=3;intd=4;Strings="s";}stati
Information:java:Errorsoccurredwhilecompilingmodule'security'Information:javac1.8.0_131wasusedtocompilejavasourcesInformation:2019/6/98:31-Buildcompletedwith1errorand0warningsin3s116msError:java:读取E:\repository\org
ngrinder中的groovy脚本结构类似junit,同时在junit的基础之上封装了自己的注解,用来控制脚本的运行。一、运行逻辑图如下:此处只列出了groovy脚本的逻辑,jython脚本是类似的,在此不再单独介绍。二、各注解的使用比较三、关注点在ngrinder中,通常使用单进程多线程就足够大部分测试了,所以:
我有一个switch语句来处理javaenumfoo,并使用spock编写一些groovy单元测试.我已经添加了一个测试,它验证当前是否处理了每种类型的foo而没有抛出异常.现在我想测试一个无法识别的foo类型会导致抛出异常.要做到这一点,我将不得不嘲笑枚举,并已经看到这里概述的解决方案:MockingJ
我有一个groovy实体ClientInvoiceAttachmentExt,它扩展了java实体ClientInvoiceAttachment.ClientInvoiceAttachment具有@Id注释,但仍然看到“没有为实体指定的标识符”错误这是我的堆栈跟踪[Mar0317:11:54]ERROR|org.springframework.web.context.ContextLoader|Contex