您现在的位置:首页
--> 梦想风暴
• 战斗HTTP
当客户端要求保持链接时,它还是需要从链接中读取数据的,但应该读取多少,谁能告诉它这个答案呢?如果没有额外的提示,似乎就只能挂住。答案就在Content-Length上,有了这个HTTP头,客户端就知道该读多少了。
• 打开视野
在ThoughtWorks里,我面试过许多应聘者,许多人在原来公司都是公司里的干将、主力。按说,也都算是很优秀的程序员了,不过,在面试过程中,折戟沉沙的也不在少数。
这样的面试者往往是工作时间不长,大约是三五年,在小问题的解决上具备了一定能力,但没有什么机会面对大问题,所以,基本上都是在处理别人嚼碎的具体问题。所以,这样的求职者在面试过程中所展现的能力,以ThoughtWorker的标准看,编程技巧上没有多么突出,陈述问题显得零散而没有重点,至于宏观问题的思考,几乎是没有的。
其实,这不是一个偶然现象,我已经见到不知多少类似的求职者。通过和他们的交流,我会发现,实际上,这些人往往不是不想提高,甚至他们都是非常努力地在工作。只是在我看来,他们所处的环境限制了他们的视野,一叶障目,不见泰山。在工作中,项目负责人给他们的工作就是解决一个具体问题,至于真正有思考的问题,那些负责人自己已经解决了。
在Java世界里,解决空引用问题常见的一种办法是,使用Null Object模式。这样的话,在“没有什么”的情况下,就返回Null Object,客户端代码就不用判断是否为空了。但是,这种做法也有一些问题。首先,我们肯定要为Null Object编写代码,而且,如果我们想大规模应用这个模式,我们要为几乎每个类编写Null Object。
Moco在程序库设计包括两个方面,如何设置服务器和如何让服务器运行起来。
先说简单的,如何让服务器运行。最简单的选择是让用户自己启动服务器,然后,在测试结束之后关闭服务器。小结一番,简化用户接口,设计DSL,利用好类型,区分Publish接口。
• 实践中的重构
许多人问过我这样的问题,要不要拿出专门的时间做重构。作为一个程序员,重构就应该和写代码、写测试一样,是我们日常工作的一部分,只要你写代码,就应该重构。特别是当你在做TDD的时候,如果你只写测试,编代码通过,对不起,那根本不叫TDD,那叫测试先行。目前为止,我还没有见过一个程序员,包括我自己在内,写代码是一遍就写得非常整洁,无需重构的。通常都是第一遍写出的代码只能实现功能,然后,把它重构得符合整洁的要求。这里要说的重点是,别讨论专门拿时间做重构,那就是你日常工作的一部分。
时至今日,如果你的Java项目依然需要启动一个特定的工具,比如IDE,才能编译部署,那你的项目不在本文的讨论之中,因为实在落后得太让人无语了。
好,回归正题。旧时代的Java世界,构建工具等同于两个词Ant和Maven。
Ant源自Make,同JUnit一样,它也是一个航班产物(参见《Ant权威指南》序)。不过,Make的基础注定了它的起点不高,所有一切都要手工打造。我还依稀记得曾几何时,每每开始一个项目都要重新复制一份Ant脚本,修修改改。Maven给了人们新的希望,目录结构的约定、依赖管理、IDE集成,那时看来,几近完美。是的,几近,还差了那么一点点。就是那么一点点,却是致命伤。
Travis CI,是一个专门为开源项目打造的持续集成环境。如果你有一个放在github上的开源项目,Travis CI简直就是一个完美的CI选择。下面以Moco为例,说明如何在自己的项目里添加Travis CI支持。实际上,只要采用的是“标准工具”,支持Travis CI就简单得一塌糊涂。
在ThoughtWorks里面,我经常有机会在不同的项目组间轮换,所以,经常会面对陌生的一切,出去做咨询项目时也是如此。但人们常常会对有经验的人加入项目有所预期,也就需要我能够尽快进入到工作状态中。所以,我也就慢慢摸索出一套适合自己的了解项目的方式。
最近有几篇关于科技公司面试的新闻,这篇格外受瞩目,因为竟然有公司力压Google,成了面试最难的公司,而这个公司居然是ThoughtWorks。这个结果真的让我有些惊讶,作为一个面试过许多人的ThoughtWorker,我之前还真没想过我们的面试到底有多难。既然有人关心ThoughtWorks面试,我就不妨在此分享一下我的“面经”。先来说说,我们的招聘流程。
• 基础设施之殇
你是否有这样的经历: 加入一个新项目,装了一天环境,精疲力竭,但是,我并没有写一行代码。在网上看到了一个自己有兴趣的开源项目,clone下来,构建一下失败,折腾半天环境都没搞定,最初的兴趣荡然无存。我要测试一个东西,但要配A,弄B,折腾C,别人问及进展,还没开始呢!作为项目的主力,每来一个新人,我都要帮他搭建开发环境,这些人咋就不能自己搞定呢?产品环境来bug了,可是,我本地根本重现不了。这群笨蛋,我都根他们说了多少遍,为什么还在用C的命名方式命名Java函数呢?这个要调试必须部署到远端的服务器上才能做。 …… 这样的例子,作为一个软件开发愤青,我还能举出很多。这些年软件做下来,我总能在各种各样的场景下遇到各种各样的问题,究其根源,无非是基础设施出了问题。与其说出问题,不如说是人们忽略了基础设施在软件开发项目中的重要性。
• 翻译杂思
从09年玩票性质地参与了《ThoughtWorks文集》开始,我踏入了图书翻译这一河。 09年下半年和小刀一起翻译了《Programming Scala》,11年又参与了老马DSL的翻译,今年新近接手了《The Joy of Clojure》。算起来,也有了不少的经历。公司邮件列表里看到一封邮件,又是书找译者。在ThoughtWorks,要做这样的事,机会多得很。看到很多小朋友们很踊跃地报名,我就借题发挥一般地总结了一下自己做翻译的一些经验,算是分享吧!首先是选择。兴趣驱动永远是最好的选择,翻译本身是一个非常磨人的工作,做自己不喜欢的事,会倍加痛苦。就我参与的翻译而言,除了第一本玩票外,我选择的主题都是相关的:程序设计语言类。无论是Scala、DSL,还是正在做的Clojure,我都是在给自己一个更好地了解某种语言的机会。
• 实战遗留代码
什么是遗留代码?没有自动化测试的代码就是遗留代码,不管它是十年前写的,还是昨天写的。关于遗留代码,《修改代码的艺术》迄今为止依然是在具体手法上讲得最好的一本书。不过,这本书上来就直奔代码,还有一些东西是技法之外的。搭建基础设施做软件,没有自动化,基本上都算刀耕火织。关于基础设施,我曾写过一篇很长的文章,以我实际的一个项目为例,介绍了一些设施的基本样子。那篇文章很长,具体到面对遗留代码,有哪些特别之处呢?我们的目标是给没有测试的遗留系统增加代码,那么,那么增加代码覆盖率检查是一个不错的选择,各种语言都有自己的测试覆盖率方案。与单纯使用测试覆盖率不同的是,我们需要保证测试覆盖率只能提升,不能降低。所以,这里可能会略有一些开发的工作量。此外,遗留代码的质量往往不高,除了测试覆盖率工具,我们还可以引入各种代码检查工具,同时,采用同上面类似的做法,保证各种错误只能减少,不能增加。
hopesfish评论《那一点的调用》时,问了一个关于Code Review的问题:想请教一下,TW的筒子是如何做code reivew或者鼓励客户做code review的?我在翻阅博主的帖子的时候,似乎对这块没有特别强调,而是更多偏重于TDD,我觉得TDD的问题是一碰到没有责任心的程序猿,就很容易流于形式了谈及TDD的好处时,其中之一就是随时随地的Code Review,所以,貌似TDD是不需要Code Review的。但实际上,TDD和Code Review是两个正交的维度,做TDD并不妨碍Code Review。这里就来聊聊我所在的项目是如何做Code Review的。我们有两种Code Review:Daily Code Review和Weekly Code Review。之所以有两种Code Review,因为每种Code Review的目的是不同的。
书接上文,继续从Go看语言设计。并发编程从多核CPU进入人们的生活,并发编程就成为编程中的新热点。在许多语言里,并发是由库提供的,而对于Go语言,并发则是语言的一部分。曾经,一说到并发编程,就会让人想到多线程/多进程、共享内存等等。Erlang改变了许多人关于并发编程的认识,基于消息的通信模式如今已逐渐成为新的标配,Go语言选择的也是这种模式。
Go语言发了正式版,终于像一个正经的东西了,不再需要每次从版本控制里面拿代码编译了。拿来把玩一番,看到了一些有趣的东西,记录一下。作为一门现代程序设计语言,Go语言从语言设计上反应出现代程序设计语言一些重要变化。函数成为第一类对象函数式编程已经无可阻挡地成为程序设计语言发展的重要趋势,只要是还在演进之中的程序设计语言,函数式编程都已经成为其重要的一部分,即便是Java这个笨重的大象,也会在Java 8中引入lambda。函数式编程的第一步, 就是让函数成为第一类对象,也就是可以把函数作为参数和返回值传递。然后,才会有高阶函数,以及后面的一系列变化。
• 构造函数沉思录
缘起构造函数,是由C++引入主流程序世界的,其用意是在《C++语言的设计与演化》如是表达: 它建立起其它成员函数进行操作的环境基础。在很早的一篇blog《对象的声明》中,我曾探讨过构造函数的来龙去脉。对于面向对语言而言,构造函数似乎是标配。一个语言特性,一旦被扔到真实世界,随之而来的是,其使用往往会超出其设计者的初衷,构造函数亦是如此。事实上,通过前面C++之父的描述,我们依然很难定位构造函数的准确用法。所以,我们常常看到许多人把诸多操作强塞入构造函数,造成构造函数极为复杂,进而关于导致了一些复杂的语法讨论,比如如何处理构造函数抛出的异常。这里要讨论的是构造函数的另一个常见问题。重载构造函数同样是在《C++语言的设计与演化》里,有这样一段描述: 观察发现,允许定义多个构造函数很有价值,因此这也就成了C++重载机制的一个重要应用方面。是的,我要说的就是构造函数重载。
[ 共16篇文章 ][ 第1页/共1页 ][ 1 ]
近3天十大热文
- [70] Twitter/微博客的学习摘要
- [68] IOS安全–浅谈关于IOS加固的几种方法
- [66] 如何拿下简短的域名
- [65] android 开发入门
- [64] find命令的一点注意事项
- [63] Go Reflect 性能
- [61] 流程管理与用户研究
- [60] Oracle MTS模式下 进程地址与会话信
- [59] 图书馆的世界纪录
- [58] 读书笔记-壹百度:百度十年千倍的29条法则
赞助商广告