# 大染志
Go, JavaScript, Ruby on Rails, Java,Docker, CI, CD, Photography

0%

## 我怎么看敏捷

Posted on 2013-11-26 In 我说

去年11月份的时候，我进到了ThoughWorks实习，开始了我的TW生涯，从现在除去今年年初由于毕业论文断断续续的10天左右的请假，我已经到ThoughtWorks1年了，现在我想来我聊聊我眼中的敏捷和我对敏捷的看法。它是比较主观的看法。
首先，我必须得说敏捷并不是完美无缺的，当然也不是所有行业，所有软件项目都适合使用敏捷来开发和管理的。很明显的一个例子就是，你不能用敏捷来开发NASA的航天飞机的软件系统。从敏捷的理念我们会说，我们让开发航天飞机的起飞系统，然后交付给NASA使用，之后再继续交付降落等其他系统，显示这是行不通的，航天飞机不能在仅仅拥有起飞功能的时候就上天啊。敏捷里强调快速交付，快速响应，及时修复bug，因此我们会允许软件存在潜在少量bug的时候让其上线，使用。这在航天飞行系统里面也是行不通的，因为涉及到人的生命，航天飞行系统应该是不允许任何bug的。

> 但我依然会说，敏捷是一种很好的理念和实践，适合大部分IT企业使用，特别是互联网企业和运行互联网产品的企业使用。

在现在互联网时代，天下武功唯快不破。采用敏捷的实践，初期开发MVP（Minimal Valuable Product）产品，快速上线，根据用户的反馈不断更新、改进自己的产品，开发新的功能，这样周而复始，产品把用户最喜欢，优先级最高的功能永远都放在第一时间开发、上线。根据用户的反馈、统计数据的结果不断调整产品的策略，这样才能立于当今互联网。在我们身边也许Github、 Flickr等都是很好的成功例子。
下面是我对于一些是非的意见：

- 结对编程能够明显提升代码的质量，让团队成员对代码的熟悉度大幅提升，但是我不赞成至始至终都是结对编程，应该留时间进行单独编程，这样虽然代码质量也许会有一些下降，但是如果伴以TDD对进行辅佐，是不会下降太多，单独编程有助于让dev独立思考，发挥创造力，很多时候会达到意想不到的结果。另外一点结果编程通常达不到两个dev独立编写代码的效率，就像在《人月神话》中讲到的那样，1一个人如果需要开发一个软件需要100填，那么10个程序员10天肯定不能完成任务的，因为期间还需要算上沟通的成本。
- 关于TDD，确有遇到过几次绞尽脑汁也没想明白怎么测试的case。但是我们如果使用 隔离依赖（即mock依赖，stub行为，如使用mockito中的：given().willReturn();或者when().thenReturn()等）的原则来编写测试，绝大多数情况都会变得豁然开朗，就Java而言，遇到静态方法，我们可以通过间接的调用去测试，对于无返回值的方法（void）我们可以采用验证行为的方法去测试(如使用mockito中的verify（）函数)。使用TDD的好处是不言而喻的，用测试代码描述你的需求，表达你想要的结果，既保证了质量也不用担心会做出多余的功能。不过在开发自己的小点子、小创意时，我通常选择Rails和Node.js进行开发因此TDD做得并不好，通产只是选择性的对重要的部分进行测试保证。
- 沟通胜于一切，跟项目中所有的人频繁沟通，在实际项目中有一次是这样的，对于story中一个对于生效时间信息的描述有些模糊，我没有多想久自己认为肯定的全局的生效时间，但是不曾想到，当多个子产品出现时，就不能依赖全局生效时间，因为全局生效时间是其中最大第一个，而不一定是当前所需准确的生效时间，因此这个sotry在最后给BA 检查的时候才发现这个bug,试想最初如果我没有随便假设，而是马上给BA发邮件沟通，问清楚生效时间，也不会出现返工的情况。我个人认为良好、高效的沟通甚至比写好代码优先级更高。
- 站会（stand up）既是一种对团队成员工作的可视化，了解彼此的进度等情况，也是锻炼表达能力、增强自信心的好机会。为何这样讲，因为在站会上每个人需要用几句话来概括自己前一天所做的一切，当你讲到你前一天做的一些进步时，团队为你真心叫好，难道不会让你你增强自信心吗？对于站会进行的方式，有团队会选择每个人依次讲解前一天的工作内容；也有人会选择采用按照故事墙的方式来进行，依次对每个列（analysis, ready for dev, in development, test, sign off等）进行浏览等，当讲到自己的那个story时，每个人需要更新自己前一天在这个story上的工作，这样的好处是可以对每个story的情况进行可视化。但是我个人更喜欢前者，这样更加自由，但是目前在工作中基本尝试的都是后者。
- 另外一点是尽早集成，这点感触很深，大三的时候在一家公司实习，当时做一个原型系统，两三个人做一个模块，到最后快要演示的时候，才把几个模块尝试连到一起做集成测试。结果就是，所有人坐在一起进行的进行各种接口的连接、调用，bug修补。一旦连接成功就兴奋到难以言表，仿佛很长一段时间的工作都没有这一下来得兴奋。系统可以集成后，一直都提心吊胆，担心其中某个东西会不会莫名挂掉，因为集成测试都是使用人肉测试的啊。在展示的时候，各种紧张，安排专人时时刻刻注意到服务器。在敏捷中，我们要求及早进行系统集成和和创建部署环境的脚本，每次CI的运行都是一次集成测试，都是一次服务器的部署。因此不用担心在realse的时候不能部署的情况。不过有一件事情是需要注意的，那就是数据库的迁移，在开发机器，测试服务器你还能每次部署的时候都干掉之前的数据库，重新创建，但是在部署到产品服务器的时候就需要小心了，在Java中我们可以用Flyway 达到类似Rails中的 rake db migrate的效果。

另外，我认为 switch pair(变还你结对同事)、 code review（团队成员坐到一起对团队前一天提交的代码进行浏览、解读），这些都可以让整个团队共享更多的上下文，还可以检查出不到的代码，学习好的代码。
也许明年这个时候我对敏捷的看法又有不少新的见解，到时候再来分享。

## 使用Gradle 运行jetty 7, 8

Posted on 2013-11-05 Edited on 2014-09-28 In gradle , java

为什么我有这个需求呢？ 作为一个使用Gradle的新手，今天在尝试将我之前的一个小应用从maven转向 gradle的时候，发现官方的jetty gradle plugin 不能正常运行我的应用，抛出的异常是：

> java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getServletContext()Ljavax/servlet/ServletContext;

经过搜索后发现，这是因为 jetty容器中的 servlet API 不是3.0 版本的缘故，继续查证，发现 目前gradle 官方的jetty plugin 版本只支持jetty 6,而 jetty 6 里面的servlet 的版本是2.5。这是从一个Gradle的核心developer那里得到的答案。

> Gradle’s Jetty plugin is outdated and only supports Jetty 6.

因此我只能转而向其他途径去解决这个问题，最终发现了Cargo,其官方网站中对Cargo 的解释是：

> Cargo is a thin wrapper that allows you to manipulate Java EE containers in a standard way.

简单讲Cargo是一个包装器，让你可以很简单的将你的应用使用类似的配置部署在各种应用服务器上运行。这里我们将使用cargo-gradle-plugin来解决问题:

首先应用插件，在你的build.gradle中添加对plugin的导入和添加依赖。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    apply plugin: 'cargo'

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            classpath 'org.gradle.api.plugins:gradle-cargo-plugin:0.6.1'
        }
    }

    dependencies {
        def cargoVersion = '1.3.3'
        cargo "org.codehaus.cargo:cargo-core-uberjar:$cargoVersion",
              "org.codehaus.cargo:cargo-ant:$cargoVersion"
    }

其次是就是cargo的详细配置了，如，选择你希望运行的WEB 容器，部署的应用和端口等。下面是我的配置：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    cargo {
        containerId = 'jetty8x'
        port = 8080

        deployable {
            file = file('build/libs/MessagePushX-0.0.1-SNAPSHOT.war')
            context = '/'
        }

        local {
            installer {
                installUrl = 'http://mirrors.yun-idc.com/eclipse//jetty/stable-8/dist/jetty-distribution-8.1.13.v20130916.tar.gz'
                downloadDir = file("$buildDir/download")
                extractDir = file("$buildDir/extract")
            }
            // homeDir = file('/Users/twer/Documents/lib/jetty-8.1')
        }
    }

containerId这是选择运行的容器ID，ID可以在Cargo的官方网站找到。基本上主流的java 服务器都支持，Tomcat, Jboss, Jetty等。
port 应用运行的端口
deployable 填入你希望运行的WAR包的地址，可以一次部署多个war包，如果部署多个就需要多个deployable节点。
local 这里是你的配置你的WEB 容器的地址，你可以选择installer从远程下载，cargo会自动帮你解压，安装，运行；另外一种是homeDir 填写本地的WEB容器所在的文件夹。

当这一切都完成后，你就可以使用 Gradle cargoRunLocal来运行你的应用了。
我今天测试过 Jetty 7,Jetty 8,Tomcat 7这些都是可以正常运行的，另外一个不能正常运行的是 Jetty 9,报的错误是，没有设置jetty.home 的值。但是我们有Jetty 8，应该能满足你的需要了吧，当然最希望的还是Gradle 官方升级jetty plugin的版本吧！

** 附录：**
Cargo
Cargo-gradle-plugin
我的示例地址

## 毕业生成长记——如何成长为一个合格的程序员

Posted on 2013-10-28 In 我说

            上周六去成都Open Party 讲了自己怎么从一个毕业生成长为一个合格的程序员的感想吧，的确自己还有很多问题，最主要的是对自己写的东西和对自己的演讲不够自信，然后分享的的东西有些零零散散，希望以后可以在这方面做得越来越好。

还是把PPT分享出来吧，也算做是一篇博客，这个东西还是花了我不少心思在里面的。

## 部署一个独立的Jar包到远端maven 仓库

Posted on 2013-10-24 Edited on 2014-07-22 In maven , java

必备环境：

- 推荐Java jdk 1.6及以上
- 推荐maven 3.0.0以上

假定我们需要将C:/ sqljdbc4.jar部署到我们的仓库服务器（http://yourrepo.com/nexus）
首先我们需要在本地配置maven的server节点，该节点用于从仓库下载或者上传包时用于进行身份验证。（下载是可能会用到，视仓库服务器设置而定。）
通常允许上传到两种仓库：Snapshots、Releases,分别为快照版仓库，主要用于存放不稳定的开发包，后者用于存放稳定版本的包。
在<servers>节点内添加如下内容：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    <server>
      <id>snapshots</id>
      <username>你的用户名</username>
      <password>你的密码</password>
    </server>
     <server>
      <id>releases</id>
      <username>你的用户名</username>
      <password>你的密码</password>
    </server>

打开cmd，将其定位到你要上传的jar包的文件夹：
类似地输入以下命令：

    1

    mvn deploy:deploy-file –DgroupId=com.huacloud.jar –DartifactId=sqljdbc4 –Dversion=1.0.0 –Dpackaging=jar –Dfile=sqljdbc4.jar –DrepositoryId=snapshots –Durl=http://222.197.188.5:9000/nexus/content/repositories/snapshots

需要注意的是 –Dversion 、 -DrepositoryId 、-Durl 是对应的,如版本是snapshot ，仓库id 也应该是snapshot仓库的ID，仓库地址也需要填写snapshot仓库的url。
如果cmd 当前路径与jar包的路径在同一文件夹下，-Dfile 直接写文件名即可，如果不在同一个目录下，需要在-Dfile 后面写上文件的绝对路径。

如果当你运行上述命令时出现如下的错误：
The goal you specified requires a project to extcute but there is no POM in this directory. Please verify you invoked Maven from the correct directory.

通常是由于操作系统之间的差异，你可以尝试这样：

    1

    "–DgroupId=com.huacloud.jar"

给所有的参数就加上双引号包起来。应该就可以解决问题了。

## 3rd week in TWU

Posted on 2013-09-22 Edited on 2017-10-13 In twu , 我说

这个系列的感受都是我在印度参加TWU的所有感受，感受来自我，难免比较主观，当然我也尽可能的表达我所观察到的客观的东西，第三周，基本上是我最累的一周，这周有忙项目的事情，有忙计划出去玩的事情，也有忙小session的事情，几天晚上都是凌晨1点才睡，所有导致这一周整体来说，状态不太好。当然还是有不少感受的。

##### 疲惫

首先说疲惫吧，为什么会疲惫，当然原因是多方面的，一方面TWU 的安排还是比较满的，早上7点办起床，吃早饭，8点坐上车到HOTEL，开始一天的培训和工作，基本上晚上7点到7点半下班。上午，下午分别有Tea Time可以休息，不过这一周我没有在Tea Time休息，事情比较多。一方面我们还有P3 case study 需要我们花些时间在上面，还有如同我之前说的，因为我自己和其他几个同学在计划周末外出游玩的事情，也花了不少时间，还有我发现Pair 是相当消耗体力和脑力的，特别是当Pair 高度集中，并且Pair之间有一些能力差异的时候，花在解释上的时间会不少。不过经过周末的休整，状态好了不少。而且想到接下来是倒数第二周了，开始变得期待回国了。

#####项目改进

上一周也提到，经过第一个Release的失败的经验教训后，我们项目组本身也在不断的完善改进自己，项目组给自己提了不好action，来对团队进行流程上的规划，还有有一定作用，不过这个东西也产生了一个负面影响，那就是我们决定在Sign up story之前不做假设，不盲目开始开发story，这导致本来就只有一周的release，我们丢掉了不少时间来完成story，我们利用那段时间修改了一些release 1的story的bug,又交付了一些。不好的地方就是，我们星期五才sign up story，这一周星期二又要进行release 2 的show case,也就是我们只有不到两天的时间进行开发，测试，还不包括这之间一些session 和class 会占用我们一些时间。
此外，也许因为时间的关系，上周星期五，QA希望我完成一个story，但是那个story里面还有一个很重要的点，是没有确定的。 QA希望我先做确定的点，后面再来改，但是我拒绝了，因为不确定的那点就是这个story中相对比较复杂的一点，而且我也认为这样做assumption容易导致项目返工，最终没有接受那个story。今天在和一个同学pair的时候，又发生一件让我很纠结的事情，我发现这个story之前的部分，很多地方都没有测试，而且我们今天的时间和任务很紧，当我们希望在这个基础上添加新的功能的时候，我的pair告诉我，他认为我们现在应该尽快完成现在的这个story，测试可以后面来写，我很疑惑的望着他。 是的我知道，我们小组中，有些同学的目标不一样，更何况今天是我们的show case之前的最后一天，想尽快story 是对的，但是保证质量也是对的。最终在大部分地方，我们采用了测试驱动开发，有小部分地方因为需要做spike的时候，TDD做得不好。代码也没有进行重构，时间已经来到了下午7点。
其实这个时候我是很纠结的，一方面我自己在这次TWU中，希望聚焦好的代码质量，另外一方面我们身处在团队之中，团队成员的coding能力不一致，更何况我们面临的是很零碎的工作时间，当然也是很紧的工作时间，我们必须从中进行取舍，这算是我在印度TWU面临的比较大的困惑了。

##### 关于P3

来之前我们就听说了P3在如今的TWU的重要性，还有也听说了我们中国的童鞋大部分对这方面不太感冒，这次来，我也算颇有感触。我们中国的同学在这方面的确表现得不是很好，首先，讲话的流畅性是个很大的挑战，其实我还是觉得有文化的因素在里面，感觉我们没有特别强烈的愿望想表达自己的意见。当然在P3的session上表现得不那么好，并不代表我们什么都没做，就我自己而言，在两次P3 case stuudy 中，我都和电话那头的Thoughtworks同时，讲述我们中国的情况，介绍了我曾经干的类似的事情。我承认我可以做得更好。

##### 关于积极参加项目管理的工作

参加这次TWU，我在参加项目管理以及与客户沟通方面，我是有不少期望的，但是事实说明到目前位置我做的并不好，一个事实就是，今天我和我的pair去跟PO确定细节，PO问我叫什么名字，说没有在之前的会议里面听到太多发言，我才意识到我在这方面做得多么不好，其实上周Coach JK也给我提过这一点。我的“借口”就是，项目里面不知道什么时候突然就冒出两个在这方面特别主要的童鞋，做了很多这方面的事情，我不太好再去插手这方面的工作，此外我觉得跟PO的交流、沟通很重要，我怕自己跟PO交流沟通不好，会影响团队。
当然这一切都是借口，其实现在这个环境，即使我们跟PO交流，沟通得不好，对我们的好处也是远远大于给我们的影响的，因为PO也是thoughtworks，我们不用太忌讳，太拘束，当然也要当人家PO那样正式对待，另外其他两个同学主动去承担了那些工作，为什么我没有积极的参加？其实说来，还是没有完完全全跳出舒适区，其实就像我在成都的项目里面类似，我在做编程之前的事情，我自己也知道并不好，比如跟BA交流，当然这并不是说我的开发的代码工作就做得多么好，而是我因为coding是我喜欢的工作，我觉得挑战更小，所有在上面更称心一点。还是继续加强在和客户、BA、QA方面的工作吧。增加能力的宽度。

##### 总结

我觉得，我在第一周，第二周的表现是要明显好于第三周的，也许是因为疲劳，也许也有一些松懈在里面吧，然后跟不同的人聊天，体会到公司搞这个Thoughtworks University是多么不容易，是花了多少的人力物力，我想我们每个人都应该珍惜这段时光，当然也不得不说，有很多是需要继续改进的，部分Session的质量我觉得还是可以更好的，此外我觉得最恼火的问题就是公寓的网络问题（公寓是公司花钱租的，算是公寓式酒店），基本上一直处于瘫痪的状态，除了可以聊QQ、Skype，有些时候能打开网页以来，基本上一直都处于在刷新页面的状态。希望可以早点解决，以后的童鞋也不用这么恼火了。

## Second week in india

Posted on 2013-09-17 Edited on 2013-09-20 In twu

上周是TWU的第二周，Session 变少了，取而代之的是我们的项目“Freewheels”，这一周给人的感觉的很累，每天很努力的做Story，也帮其他同学解决一些问题。

##### Session

这一周我们还是有几个Session, 加上上周学习的有 TDD, Mock与Stub, 重构，非技术的有 TW Finance, Story的生命周期。也许是因为Story的原因，让我对某些Session的印象都模糊了。最清楚了应该算是Mock与Stub了。
来印度之前一直没有搞明白Mock与Stub的区别，我只是知道他们都是用假的对象来模拟真实的对象。而通过这次的Session算是搞明白了。
Coach 给了个题目，这里有三个类 CashRegister（接口）, Printer（接口）, Purchase, 现在在CashRegister中会调用 Printer打印 Purchase，现在需要测试该方法，问如何测试， CashRegister， 和printer 的执行方法 均为 void,无返回值。不能用Mockito 框架。
拿到这个题目，我是完全没有头脑，因为我之前用过的 测试都是通过结果来测试数据的，而这次测试的方法不仅没有返回值，而且被测试的类还是接口。
就这样按照coach的指导，基本模拟出了简单版的Mockito来测试这个方法，如果使用Mockito我们只需要使用：

    1

    verify(cashRegister,times(1)).process();

最后coach总结出了，Mock和Stub的区别在于，Mock会验证，而Stub则是你让他干什么，他就给你什么。瞬间感觉豁然开朗的感觉。

##### 项目

从这周开始，项目就是TWU生活的主体内容了，当然coach们是希望我们把session中学到的东西全部利用到项目上面来，但是结果是残酷的，第一周我们表现得并不好。在项目正式开始之前，我们两两Pair做了一个在用户注册表单中添加地址、城市、国籍、邮编等信息，当然也需要在用户详情页面中显示。有人半天时间几乎完成了大部分story，我和我的pair完成了1/3左右的工作量，其他同学也或多或少都完成了一些。演示代码的时候，做得很快的那对pair，他们将所有用户地址相关信息也都全部添加到用户表中，其他实现也都是在之前的基础上进行复制，粘贴，修改，添加。从这个时候开始我就明白了，每个人来TWU 的目的真的是不一样的，有些人是想提升自己的技术能力，能多学一点东西，有些人希望用自己的能力帮助团队提高效率，解决问题，有些人希望帮助管理、组织团队。
在之后的Iteration planing meeting上面，大家普遍对小组完成story的能力比较乐观，我们小组计划在一周内交付40点。
何为1点，在界面上为登录用户显示欢迎信息为1点。为用户注册、用户详情查看、管理员详情查看页面，当然包括编写funtional测试，这个story是5点。按照我们自己的计划我们一周内可以交互 3/5 * 6 * 5 = 50点。大家想到每天可能会有session会耽误时间，所以将点数减去10点，因此我们需要交付40点。我们小组来自中国的两个同事，包括我在内，是反对交付40点的。也许是因为在项目上滚过一段时间吧，知道40点没这么容易。
在接下来的这一周里，大家也意识到了时间的紧迫，我们也知道了我们小组是计划了最多交付点数的小组，同学们都非常努力，每天的standup 也很积极，story 墙上的story也在墙上快速流动，似乎我们就可以完满完成我们的交付点数了。
但是，我们很多地方并没有按照session中学到的东西来做，在讲story挪到ready for dev 的时候我们并没有对AC进行详细检查，所有story也没有mockups,所以必须靠我们自己来想象。比如dev在拿新卡的时候，基本上没有和QA(因为我们项目中没有BA，所以QA既当妈，又当爹)对story进行kick off,遇到story里面描述得不清楚的地方也许首先会自己想想怎么样最好，然后再去问QA和PO，有时候我们也在做assumptions,dev开发完story后有时候并没有跟QA进行演示和确认。所以我们看到墙上的story流动的比较快。
到了showcase的那一天，在showcase 之前的10分钟，不少同学都还在提交代码，我也在其中，当然我们的QA也在很负责的进行代码的手工测试，那天我做聪明做了很多UI的美化工作，但是结果是把两个地方弄巧成拙了，一个地方是我自己做了assumptions ，给商品的展示进行切换排序，在修改一个按钮的css样式的时候，我也没想到那居然会影响到其他一个页面，当然之所以没影响，是一个一个同学copy另外一处的代码，并且没有修改。
毕竟因为我们项目的细节大部分没有测试到，最后我们只交付了4点。当然有很多story是因为bug的原因不能交付。

在项目上的第一周，就给我们的感触很多，当然教训也是很多，现在已经太晚了，已经凌晨1点了，这里只想提几个问题：

- 在这样的情况下，我们到底是更多的关注与每个人定的自己不同的目标，还是全心全意把所有的心思都放在项目上？
- 在这个情况下，到底是项目的正常交付重要，还是保持代码的质量更重要。
- 在TWU中4个小组，共享一个client，只有一个印度同事来担任PO适合足够？因为很多和story相关的事情都需要和client确认。
- 在这样的情况下，能力稍强的同学是否应该快速自己的速度，帮组团队完成交付目标，而放弃与某些编程能力相对较弱的同学pair、交流？
- 在这个情况下DEV 是不是只应该关注自己的开发和单元测试、functional测试任务？ 在我们项目中没有BA,12个DEV，2个QA
- 很多同学为了尽快完成story，通常晚上也会pair到较晚的时候，最近逐渐发现，不少同学已经开始疲劳了，早上的session的活跃度感觉有点下降，这样到底是不是对的？

这些都是我自己心里面的问题，我有一些想法，但是肯定里面有些是很主观的，不对的。所以就不写自己的想法了，暂且提及问题。

## First week in India

Posted on 2013-09-11 Edited on 2013-09-12 In twu

来印度已经快两周了，完全没有不适的感觉，每天都很充实而又忙碌，就连周末都是各种安排。只有在聊天的时候才会有思念的情绪涌上心头。这里记录下第一周的感受。
总的来说第一周很多Session，从很入门的session 逐步深入，到接触到一些之前没有了解到或者没有深入的东西。每天的收获还是很多的。就像coach们说的那样，你来TWU不是为了和别人比较，而是和自己比较，让自己有成长。今天中午我们中国童鞋吃饭的时候还在聊，一个童鞋说，感觉和老外Pair让自己的编程速度更慢，因为你需要先解释你的意图，在你coding的还需要不断的解释。其实我有时候也会有这样的感觉。但是我心里很清楚，我作为一个来公司几个月的毕业生，在coding方面可能会比一些grads好一些，但是我这次来的目的是体验和全世界不同国家的同事一起工作、写代码、生活，更多的是这种经历、同事之间彼此的分享，各种方面的分享。即使完成某些代码对我来说相对比较容易，但是我能不能用更好的方式，我能不能把我的想法完整的表达给我的Pair,我能不能分享一些快捷键、一些思路给我的Pair。这些都是我很看重的，他们都是我的目标。
另外一方面，几乎现在所有认识我的人都不会说我很内向，但是我其实自己知道，我真的是算是一个内向的人，很多时候我没有勇气去做一些事情，所以这次我给自己的目标也有在小组里面更活跃一些，多多表达、贡献自己的意见，虽然我的英语单词量不大，但是并不妨碍我表达出我的意思，我还清楚的记得，昨天上午session的时候，我中途因肚子不舒服去上厕所，我还在马桶上摸出手机查“拉肚子”这个单词怎么说。一些都是这么不可思议。哈哈。

##### Feedback

言归正传，首先聊聊Feedback Session，在我们公司大家都知道，这个很重要，但其实很多时候，至少我在这方面做得并不好，不太敢当面向其他人要Feedback，怕别人指出自己不好的地方，会尴尬，。这些都是需要提高的。在来印度之前，在成都听过Feedback 的session,当时真的是深有感触，这次再听一次后，加深了理解。

- 如果你想要给一个人Feedback，请一定要记得营造一个安全的环境，一定要让接受者感到安全，在你给一些消极的Feedback的时候，一定要根据事实来，而不是直接就说，我觉得你怎么怎么不好，此外不要带着责备、埋怨的口吻。当然一次不要给太多的Feedback，不要让接受者感到沮丧。总之，不管怎么样，你应该给予接受者信心和鼓舞，给予他改变的力量。
- 作为接受者，当然很重要的是不要一听到别人消极的Feedback 就一味的抵触、狡辩，有则改之无则加勉。要知道一个人要给出消极的Feedback远比给出积极的Feedback难上很多，所以不管怎么样，我们都要怀着一个感恩的心，谢谢给你Feedback的同事。
- 快速、主动的 给和接Feedback

##### 咨询师

接着是咨询师的session，我们每个人都是咨询师，而不是只有DEV才是。根据我在项目中的经历有一点我印象特别深刻，那就是“Domain Language”，大多数情况下我们面对的客户都是没有太多IT和敏捷 context的人，我们不能用我们在公司内部讨论的那一套去给他解释，而是要学习客户的Domain Language, 要用用户懂得的语言去给他解释。 此外当你在项目上工作时，要时刻记得，你这样做能为客户带来什么样的 Business Value,能带来多少的Business Value,如果你的工作不能给客户带来Business Value,那人家为什么要让你做，要为你做的付钱呢。
在这个session的 角色扮演游戏中，我就扮演了一个客户，几位咨询师想要花5天时间去重构代码，然后他们试图说服我同意重构。我就抓住我不懂重构，让他们给我解释什么是重构、为什么代码可以使用要重构，他们怎么能保证重构的代码运行起来更好，为什么我要花5天时间多支付那么多钱去让他们去重构我可以使用的代码。结果是我这个可恶的客户赢得了讨论，他们回答不上来我的这些问题。
仔细想想，也许我们在遇到其他客户的时候也许遇到这样的问题，怎么样让重构体现出客户的Business Value,怎么样用客户容易理解的语言去说服客户，这真是一件很有挑战性的事。

##### QA

在一个关于QA的session中，通过一个画画的游戏我第一次了解到QA和DEV 也应该pair，而且他们一起pair的效率比 dev做完以后，交QA检查，再交回DEV改进有很大的提高。另外一点，QA 不仅仅是tester，QA 也应该参与story生命周期的绝大部分，比如和BA一起写story，这样更能保证 acceptance criteria 是可测试，容易测试的。瞬间对QA肃然起敬。

##### Agile 团队

每个任务都可以多个团队成员来共同负责，一个团队成员应该在团队中承担多种角色，而不是仅仅一种。 时刻记得你是团队中的一员，而不是一个人在战斗！！

##### 我的生日party

很荣幸在印度过了自己的一个在国外过的生日，我的室友是第二天，所以我们一起过了生日。很感动，我们的中国妹子们交了老外们学用中文唱生日快乐歌，很感动。这个生日party，绝大部分的twu grads 都来了，也许40多个人吧，还来了一个coach。每个人都带来零食、饮料和我们一起分享，而我们准备一个大大的蛋糕、美味的中国方便面、一些筷子、中国钱币。整个party的高潮应该是我被满脸摸上蛋糕，被人抬起踢屁股吧（话说这是印度的一个传统）。总之很开心的生日。

##### 番外篇

就像我之前说的，他们叫外国童鞋唱中文歌，我们也教了很多人学中文，很多人都是很主动的让我们教他们一些中文单词，我们这次去的中国童鞋我感觉大家都还是比较合伙吧，大家都会主动去融入这个集体中，至于我这次只有我一个男生，所以我只有到处跟大家一起去吃饭，活动了。我也很享受在团队中的感受，这次还有两个从澳大利亚和新加坡来的华裔女生大家都玩得比较来。

据我所知我们大家也没有遇到对于吃的东西不习惯的！这这边吃的公司负责的早餐和午餐都是相当美味、可口的感觉。很幸福的感觉。

期待我们这周星期五的 Chinese Hot Pot Night，我们邀请了所有人。 唯一很担心的是电力负荷的问题，因为我们希望可以准备4口火锅。在这边已经遇到几次跳闸了。
加油！

## 印度初印象

Posted on 2013-08-31 Edited on 2013-09-01 In tw , 我说

来印度已经三天了。感觉其实还好，有时候欧洲人和老美说的英语太快了，会有点跟不上的感觉，其他倒没发现有多大的沟通障碍。虽然我的英语单词量比较小，但是大概意思他们还是懂的。

##### 提纲：

- 对印度的印象
- 对TWU同学的印象
- 在TW Pune的所见所闻

##### 对印度的印象

以前在网上看到关于印度的各种消息，大家都惊叹印度人是开了挂的。从我来的这三天来看，对印度的印象还是有不少变化。
首先是在成都机场遇到的印度人，没有跟他们有过语言交流，但是感觉他们的穿着还是很休闲的，和我们大多数中国人一样，当时觉得没有太多的感觉。到了孟买，当时因为机票的愿意，我们是凌晨1点到孟买，然后需要在机场等9个小时然后才能坐上另外一趟到普纳（PUNE）的飞机，首先遇到的是在孟买机场两个穿机场工作人员服的印度人万分热情的带我们去打印机票，帮我们去办理check in手续，结果办理完之后，找我们要小费，当时瞬间觉得怎么机场工作人员也这样，因为我们没有兑换卢比所以我给了他们1人10元人民币（后来从Coach 口中得知，通常在印度吃饭这些都是已经包含了小费的，所以大多数情况都不需要给小费，而且给小费通常是20，30卢比，最多都不会超过100卢比，所以我给她买10元，就等于100卢比，还是算很多的了。），也许他们不知道这个到底是否值钱的关系，他们最终还了给了我。不过我当时对他们的行为还是很吃惊的。
到了孟买机场的候机大厅，孟买基本上算印度至少前三的城市，他们的国内候机大厅很小，大概相当于国内的最多4个登机口的样子，而且他们国内航班全部都是摆渡车，瞬间觉得孟买很掉价。不过让我很惊讶的是，在孟买机场看到很多商务人士都是穿的西装，两件的那种，大多数人都穿得比较正式，也许是我感觉的原因，感觉他们穿得反而比国内正式。还有就是我们那天的航班没有延迟，这点感觉很好，那天上午从孟买飞的飞机都没有延迟。这点觉得做得比国内好。还有一点印度的机场安检人员全都是来印度的军队在安检，他们的老大是随身带着手枪的，当时突然觉得有点吓人。
到了普纳，机场真的很小，相当于中国三四线城市的机场吧，不过还好的是行李这些都没遇到什么问题，出了机场觉得印度的基础设施真的想对比较差，马路可能还不如中国的县城。今天下午我们去了普纳的可能是市中心的地方去买东西，一路上对印度的了解更多了。
总的来说：

- 他们的街道很窄，我见过的大部分是小于等于双向4车道的（我的意思是一条街总共），基本上没看到沥青路面，有些地方坑坑洼洼的。
- 街道上的红绿灯比较少，大部分过街靠抢时间。路上的车，感觉绝大部分车都没有看到人要减速的样子，有给人直接朝你开过来的感觉，所以在人多的地方，感觉是在用生命过马路。
- 有些地方有乞讨的人，而且如果你多看他几眼，基本上他会紧跟着你，第一天到的时候，当时看到街上很可怜的一个小朋友望着我找我要钱，被她那眼神感染了，但是苦于当时没有卢比，所以没给，但是看到她一直在追其他人逼着要强，又觉得他们为什么会这样呢?真的是很难说清。
- 大部分印度人还是比较友好，比较热情的，至少不会看起来对外国人凶神恶煞，但是今天遇到很特别的例子，我们一行三个人乘坐Rickshow(简单讲是机动三轮车)的时候，因为一个女童鞋拍了另外一个人一张照片，那个人就一直很凶狠的看着我们，感觉想打我们的样子，不过还好，最终没有发展到那一步。
- 印度整体基础设施并不好，感觉可能像我们的2000初期吧，街上跑的车豪车很少，如果看到丰田、大众、本田之类的也许就是中等偏上的车了，不过我也看到一些宝马、一辆保时捷的车。还是觉得他们贫富差距比较大，比如我们乘坐的Rickshow,感觉坐了很远很远的路，至少10公里，结果才80卢比左右，换成人民币才8块钱，去稍微好一点的餐馆吃饭，每个人点一个吃的，大概也需要花掉至少30，40人民币左右，还是比中国便宜一些。
- 印度的空气比较好，至少感觉比中国好，不过他们的rickshow 尾气很严重，特别是刹车或者停住的时候，看到的全是蓝灰色的烟，喂到的是燃料没有燃尽的味道，很浓。
- 水，我不知道印度的自来水到底是什么样的一个情况，反正所有人都告诉我们不要喝自来水，烧开的也不行，只能喝纯净水。去餐馆吃饭喝的也是纯净水。没有餐馆会上自来水煮开的开水。不过坐车时候看到的印度的河流，还是比较脏。

总的来说，对印度的印象还是比较可以吧。

##### 关于TWU 同学

这次我们中国的同学比较少，北美的同学比较多，目前来讲没看到比较严重的什么分割情况。就我而言，我觉得大部分同学都还是比较友善，我想我大概知道1/2 - 2/3 左右人的名字吧。每个人都见过，都有印象。有时候英语母语国家的同事聊到某些话题的时候，由于英语单词的原因，我会出现lost的情况，不过还好吧，比我意料中的好了不少。来了3天合外国童鞋吃过三次饭，大家关系在逐步升温。It’s wonderful.
我带了些中国的小东西，送给了一起住的几个同学，大家都比较喜欢中国的东西。

##### 关于TW Pune

今天很有幸去了TW Pune Office,让我收获很多，而且发现他们有办公司里面的有两个应用都是我做过的，分别是图书馆管理系统，和sohub，他们都有我值得借鉴的地方。具体的留到后面的博客在细讲，今天之所以会去办公司，是因为他们今天正在举行XConf，大概就是一个IT人士的各种分享吧，今天来的人很多，感觉可能超过了100个。普纳办公司的确气氛还是很活跃的，今天虽然是星期六，但是好像很多员工都来了。今天的session大概都有10几20个，因为同时有3个session在不同的办公司举行。气氛绝对足够。中午在办公司吃了午餐，那叫一个丰盛啊，应该是我来印度吃得最丰盛的午餐了，大概有10以上的菜供你选择。而且很多肉，还有甜点，他们的饮料除了可乐和雪碧之外，还有不少果汁，让人感觉很不错。
另外一点想说的是，他们用了单独的一台电脑来运行他们的图书管理系统，一台电脑来显示他们目前所有项目的编译状态，一个大屏幕显示器来显示twitter消息。感觉这些都是我们成都办公司也许可以学习的地方。
当然今天也体会到了ThoughtWorks 包容、活泼、自由的文焕氛围。

## Moco使用心得分享

Posted on 2013-06-13 Edited on 2013-09-01 In java

##### Moco是个什么东西呢？

Moco是Thoughtworker @Dreamhead 写的一个用于Mock服务和和进行相关测试的框架。在Moco的官方介绍中是这样描述的：“Moco is an easy setup stub framework, mainly focusing on testing and integration, inspired by Mock framework, e.g. Mockito, and Playframework。”在我要讲的这个应用中，我们主要用Moco来mock第三方、应用外部的服务。保障我们进行高效和稳定的开发。

##### 为什么我们要使用Moco：

我们的应用主要的数据来源和持久化等操作都不是在应用内完成，而主要是通过调用外部的Web service来达到目的。在使用Moco之前我们经常遇到这样的问题，外部的服务挂了，我们本地获取不到数据，就直接导致我们不能进行开发工作，集成测试不工作，就导致我们不能验证自己的工作是否是正确的。我们就期望有一个东西，能在我们进行开发时，屏蔽我们对外部外部的高度依赖。然后我们只需要通过每天定期跑集成测试，以保证我们的工作是正常的，有效的。Moco则满足我们的条件，于是我们在项目中加入了Moco。

##### 我们如何使用Moco：

Moco可以使用java代码API和外挂json配置文件两种形式进行使用，在我们项目中我们使用后者的方法，这样可以保持项目本身和Moco的低耦合，我们只需要在我们需要Moco的时间段——functional test、验收测试段让其加入进来即可。

我们将Moco和外部服务的 base domain（域和端口）写入到一个配置文件中，我们可以根据我们的需要在自行选择是否使用Moco来mock服务。
然后我们需要为被mock的每个服务的endpoint编写监听请求和回应。一个简单的例子如下：

    {
            "request": {
                "method": "get",
                "uri": "/hello"
            },
            "response": {
                "file": "xml-folder/sample.xml"
            }
        }

其大致的意思是：监听“/hello” 这样的GET请求，一旦收到这样的请求即返回某目录下的一个xml文件。

在运行 functional test的时候，我们也使用了Moco来代替真实服务。也许你会问这样做能保证做出来的功能正确吗？答案是肯定的。
首先Moco中所有的数据都是真实的，只是它是某次请求的数据，因此它是固定的。其次我们在项目中每天定期跑集成测试，集成测试保证了我们调用外部服务的接口是正常工作的，数据是准确的。

Moco给我们的优点或者说给我们带来的好处：

- 集成简单、方便，隔离开发对外部服务的高度依赖，使得我们在任何时间都能进行开发，即使所依赖的服务挂了。
- 与Maven、Gradle良好集成，有maven和Gradle插件为我们保驾护航，使得我们可以在Concoridion Test等中轻松使用Moco
- 使得我们的测试运行速度更快，经测试单个接口请求和响应时间至少减少50%以上，节省程序员等待CI状态的时间。

更详细的Moco使用说明，请移步Moco Github repo

## 记'U'项目

Posted on 2013-05-17 Edited on 2013-09-01 In 我说

U（省去真名）是我进公司以来的第一个交付项目，与他相遇也应该用巧来形容，因为原本我们应该去另外一个项目的。当听到我马上要做的项目是五马时，还是很高兴，毕竟我马上就可以上我的第一个项目了。不过心里面也有些疑惑，因为这个项目基本上是处理偏向前端的项目，去调用后台提供的服务，我们本身不提供任何数据的持久化操作或者对外提供服务。不过的确这个项目相比与公司内部的其他项目真的算小的了。我们团队总共4个人，外加澳洲share的两位同事吧。时间也只有3个月左右。不过由于这个项目是从0开始做，而且是大牛@Jeff带着我开发，我学到了很多东西，不仅仅是编程，更是如何去进行敏捷项目的开发，如何推动敏捷项目的正常的进行，如何在团队之中发挥作用。
我们的团队成员：大熊、弘、梦秋、以及在项目shadow过一段时间的青。

- 大熊，技术大牛，不仅仅教会我们了如何写好代码，他在很多时候，还把一些事情放给我让我去track、去push，并告诉我怎么样去和澳洲的同事、同事沟通、合作才能把这些事做好。在他的丰富的经验的熏陶和潜移默化之下，我感受和体会颇多。
- 弘，我们项目的QA兼职BA，看吧，从这点就可以看出我们项目的之小了吧。不过这也辛苦了孙弘了，感觉在我们团队里面又当爹又当妈的。感谢孙弘教我怎么样写测试用例才是最好的。
- 梦秋，从我们的Drupal Team过来的孩纸，比我早一年的公司，我们项目的大部分前端的架子都是她搭起来的，在她身上我也学到了很多前端方面的知识，我想我再也不会胡乱的写css selector了。梦秋童鞋有一股很较真的劲。
- 青，在项目中途进来的孩纸，谢谢你免费帮我们项目做了这么多Story，也恭喜你马上就Billable了。

在项目中要求的几点，从项目开始到现在，我觉得是很有感触的：

- 代码测试覆盖率100%。的确，如果我们是真正严格按照测试驱动开发，先写测试代码，再实现，基本上是不会遇到测试覆盖率不过的（基本上>=90%）。你也许会说，如果遇到某些方法不能测试怎么办，在项目中我遇到过两三次觉得代码不能测试的情况。但是由于我们的测试覆盖率要求100%，所以我不得不去寻找测试代码的方法，所以即使经过多次尝试最后发现代码的确不太好测试，那么我对那段代码也是相当熟悉了，也基本上保证了代码的正确性。当然最后面对那个我认为不能测试的方法，我写了一个很屎的代码去通过覆盖率要求。但绝大多数最初我认为不能测试的代码，最终都表明是可以测试的。比如Spring中的 HandlerInterceptorAdaptor。

- 大熊的三层设计：如何测试系统的外部服务，同时还要保证外部服务挂掉的时候，不影响我们正常的开发。用Integration Test保证外部服务的真实、正常、可用性，用本地的缓存的真实的服务器相应数据来进行一般的本地代码的测试。用Mockito来进行controller级别的测试。为了保证我们本地的应用可以正常跑起来运行，我们还用了校长@dreamhead开发的Moco,保证我们本地的应用可以正常运行和测试的。更详细的文档可以看大熊写的两篇文档《都是为了半夜能提交》1,2。我也希望后面可以另外写博客用自己的话讲述我们在项目中怎么做这些测试的。

在这个项目中，当大熊不在的两周，我们剩下的人需要负责更多的事，以前可能很多问题需要找大熊才能解决的，现在也许就需要我自己来处理了。不过所幸的是，经过和澳洲的同事打电话，聊天，两天下班以后加了点小班，问题都被一一搞定。这两周也是我最独立、主动的两周。承担了应该承担的Responsibility。
在这个项目期间，我看了《Rework》和《程序员职业素养》这两本书，也对程序员的身份有了更多的认识。让我明白，一个程序员需要对自己写的代码负责，而不是写一坨自己都不认识的屎。
当前天得知自己马上就要离开小组时，刹那间突然很舍不得，舍不得这个团队，舍不得自己写的那些代码。不过，从一个项目到另一个项目是很正常的，项目总有自己的生命周期，把他当作是一个学期的大学课程就好了。这学期快结束了，下学期也不远了。
下周星期一就到新项目了。加油！恨自己，写得那么烂的文字。