敏捷的工作模式强调个体及团队的互动和频密交流,为了及早反馈和频密交付。但这对于分布在不同办公室甚至不同国家的团队成员带来不小的沟通和合作方面的挑战,很多人会觉得沟通的负担超重,或者浪费无谓的等待时间。基于我们的经验,如何应对其实也没有什么大秘密,只要遵循以下一些原则和策略,就能减少分布式的合作之痛,同时确保良好的敏捷交付效果。
Arduino初探
那天看了极客范DIY系列:便携式树莓派报警装置深受启发,于是从深圳带了个Arduino回来,重温当年的模电数电!不过确实比当年的单片机更容易玩,可以集中精力发挥创造力!另外这有个基于RaspBerryPi的视频,老子教儿子做报警器。http://t.cn/8kkOmnn
是从taobao买的A货,型号标注为Arduino Uno. 从arduino.cc/en/Main/Software 下载官方IDE。用USB线连上MacBook,发现ArduinoIDE无法上传程序到板卡,搜了一下官网,得知Uno本来是免驱动的,但我买的这卡上面带有明显的FTDI芯片一枚,所以又去http://www.ftdichip.com/Drivers/VCP.htm 下载MacOS驱动,然后终于连上了USB串口,做了呼吸灯和光敏灯。
官方函数手册:http://arduino.cc/en/Tutorial/HomePage
用Arduino制作光控呼吸灯
用Arduino做了一个光控呼吸灯,并接有一个自锁总开关。当光线弱的时候,灯会急促闪烁,光线亮的时候就会均匀地“呼吸”。
附实物图和手绘电路图。
源码:https://github.com/mebusw/Arduino/tree/master/breathing_led_with_button
Learn Python in 10 minutes
(用了好几年python,发现还是有个别语法没用到,比如 a,b=b,a 比如@classmethod 比如 dict.get(“x”, 1) 比如dict.setdefaults()。本文没有提到yield语法。)
示例代码 learnpython-zh.py
Python 由 Guido Van Rossum 在90年代初创建。 它现在是最流行的语言之一 我喜爱python是因为它有极为清晰的语法,甚至可以说,它就是可以执行的伪代码
很欢迎来自您的反馈,你可以在@louiedinh 和 louiedinh [at] [google’s email service] 这里找到我
注意: 这篇文章针对的版本是Python 2.7,但大多也可使用于其他Python 2的版本 如果是Python 3,请在网络上寻找其他教程
Git - 简易指南
敏捷之旅2012天津站活动组织心得
今年2012,是天津软件本地社区的第二次举办敏捷之旅活动。去年的破冰之旅还历历在目,经过一年的时间,天津有更多的朋友开始接触敏捷,实践敏捷,讨论敏捷,并加入软件社区积极参加和回馈,也使得天津软件行业更加繁荣和具有竞争力。
今年共有四位组织者@Eugene_Xerox@King费事 @申导 @柴阿峰 ,大家来自不同公司,但都愿意为组织软件社区活动贡献自己的一份力量,一直在张罗着“天津软件沙龙”线下活动。
9月份开始,大家开始着手研究敏捷之旅活动,经过几轮讨论,先要考虑赞助、场地等硬件问题。一次机会,得知天津软件评测中心要在11月举办一次天津测试大会,于是经过沟通,对方对我们的活动非常支持,愿意提供下午3点以后的时间段给免费活动,还赞助了一些门票供参加上午的活动。这样,拿下了假日酒店的场地,最大的一笔开支消于无形。
接下来是书籍,经过敏捷之旅支持小组的指点,成功联系上清华和图灵,拿到了一部分书籍。(ps:上周参加北京的敏捷之旅,有幸见到清华出版社的文工。文工表示继续支持天津的活动,还希望能有些读书会性质的活动,这点我们也会考虑的。)应该还有禅道软件的赞助。
其余现场需要的文具物品等就不说了。
宣传部分,首先是天津软件沙龙的微群和邮件列表,然后再扩散到各个公司。新浪微博也是重要的宣传阵地。事先申请了新浪大屏幕,另外还准备了现场要摆放的海报。
话题部分,大家突发奇想,为什么一定要演讲题目呢?有没有更加活跃的互动形式。于是我们联系上另一位嘉宾 @卡爾文_Q ,决定以对话形式来进行观点的碰撞,引发台下的讨论。今年敏捷之旅恐怕只有天津用了这个创新的形式。当然对话之前还是准备了两个闪电演讲来引出讨论。
最后,台上嘉宾分为两组,一组代表敏捷派,一组代表传统派,由主持人来引导话题和台下讨论:
- 15:00-15:30,闪电演讲:《敏捷测试》
- 15:00-16:30,对话:《敏捷转型让测试人员很受伤?》
- 16:30-17:00,闪电演讲:《实例化需求》
- 17:00-18:00,对话:《自动化测试 传统 vs 敏捷》*
最终战况,假日酒店200人会议厅,上午的天津测试大会基本坐满,下午一部分领导和听众提前退场空出的座位,被来参加社区活动的50多人重新填满,整个会场座无虚席。粗略统计,一线开发测试人员与管理人员大约1:1.
和上午的商业学术气氛相比,敏捷之旅一开场,首先是新浪大屏幕进行微博滚动,现场气氛一下子不同了。
台上的观点碰撞,强烈的引发台下听众的参与的欲望,纷纷提问、发微博互动。台下的一位项目经理提了一个非常尖锐的问题:“我觉得PO、PM不要和团队走的太近,这样团队容易将责任都推给PM”。这个话题很有代表性,于是我们将他请到台上和嘉宾一起互动,全场讨论热情达到一个小高潮。
可以看出,天津还是有很多软件从业人员,而且非常愿意参加此类活动的,只是缺乏组织者的缘故,大家不太能聚集起来。
事先联系的《今晚报》记者也来了,虽然由于担心报道的方向和主旨不清的原因没能见报,但毕竟意味着报社今后还会有机会进行报道的。
晚饭自理,然后的OpenSpace没有预期那么多人。在水游城的costa咖啡,10来个人又继续进行讨论,从7点多一直说到10点多,仍然意犹未尽。
个人一些总结:
其一,有钱好办事,场地、宣传都是砸钱的事情,如果像北京那样管饭,或者从外地请讲师,也都需要费用。期望随着影响的扩大,会有更多人关注,更多人参与,更多公司来赞助。没钱的话,也要善于借力打力
其二,即使今年4位组织者,仍然力不从心,精力、人脉都有限,而且不能持续。今后要吸收更多志愿者进来。
其三,宣传力度,各种渠道的宣传未能形成猛烈攻势。
其四,组织形式可以多样,更多的互动内容和参与者之间的讨论,有时比单纯的演讲来的更实际。
将Sonar引入 Jenkins
Sonar是一个集成的代码质量工具,主要用于Java,但现在也可以通过支持多种其他语言,例如javascript, C#等。
Jenkins是最流行的持续集成工具。
有两种方式在Jenkins Job中建立Sonar步骤: Standalone sonar runner 或 sonar-maven-plugin
(本文假设你已经安装了Jenkins)
参加敏捷之旅北京2012的一些记录
作为敏捷之旅2012天津站的组织者,和老曹一起去了北京去学习一下。
参加了几个session的心得:
段念的《生长出来的敏捷》
敏捷提升效率:更多的活?还是组织集中精力做有意义的事情?
核心价值观-》原则-》实践
敏捷生长的土壤(自发的) vs. 规划好的敏捷架构(缺乏感情)
douban.com团队 120开发人员,5专职测试(实际上是技术很好的,有大量CI、自动化经验)
豆瓣团队的自发实践:
1. happy day,比赛写代码解决某个问题
2. 资源池(仅fix bug)<—> 机动队A(新开发) + 机动队B(新开发)
3. pull request of GIT. CI先跑pull request,成功后才能提交到master,中心CI只跑master。因为人工review是静态的,不能保证发现所有问题。
4. git enterprise 不好用,于是二次开发自己的code管理工具,还能发徽章,及内部问答系统。
5. 60%喜欢用trello
生长的阳光土壤空气:
1. 工程师文化、吐槽文化 vs. 公司文化、规划
2. 季度目标(避免提到绩效):哪三件事情最需要做?为什么要做?如何衡量?
3. 对老板的一些介入和要求:“挺好的,我先考虑一下”。直到他再而三的找你。
种子:
不招对代码不负责、不认可甚至阻碍改进文化的开发人员
伍斌:担水砍柴皆能悟道
中国式管理:曾仕强
日本一分法,集体主义,长官意志
美国二分法,制度+个人主义
中国三分法,太极,情绪好的时候讲道理
==》 先由情入理,再依法办事
==》解决冲突:给双方面子,再化解。比如:“A的想法不比B差,为了锻炼,可以让他去试试”
驱动敏捷:中国人的专业精神。生于忧患死于安乐
南怀瑾。世上苦难根源:贪痴(无明)嗔
项目中的无明
1. 浪费
2. 先作对(道)还是先做好(术)? 目标vs.方法
先改变理念,再改变方法。
Mike Long & Juven – Code Retreat
题目: Tic-Tac-Toe
四个简单设计的原则
pair programming + TDD
3x 45min sessions, each of those need to switch pair and delete all code
Retro:
even I’ve TDD experiece, still I found different ideas(tests, design etc) when pair with different people
a good female programmer surprised me (we’ve rushed out a PHP test framework!)
need to prepared well for computer and common languages, better with WIFI in the room
手工安装 grunt.js/npm/phantomJs 一些经验
grunt.js是node.js的一个组件,本身还带有很多plug-in,用于javascript应用程序的构建管理及依赖管理,诸如lint, copy, concat, minify, unit test等,有点象Maven。
有连接外网的机器,可以很方便的利用其本身的依赖管理NPM安装。但是企业内网就有一些限制,下面就如何在无外网连接的linux主机安装grunt.js等进行说明。
主机是centOS,之前已经安装了RPM包的gcc。
下载node.js源码,拷贝到目标机,然后make,这个还好。
下载grunt.js,同样拷贝到目标机。注意grunt.js应该使用(npm -g install grunt)作为全局安装。在linux系统下,结果是在/usr/lib/node_modules下。在winXP下,是在 C:\Documents and Settings<username>\Application Data\npm\node_modules 下。其他grunt的plugin,如果不是全局module,一般都是安装在项目下,即<project>/node_modules。
我们希望grunt的这些module能被目标机的多个项目共享,毕竟没有网络,也不想拷来拷去。在https://npmjs.org/doc/link.html 提供了一种npm link的方法,不太好使。其实不用它这么麻烦。将所需的grunt module都拷到目标机的某个目录下的node_modules,然后直接在每个项目下新建个指向该目录的符号链接:
cd <project>
ln -s <somewhere>/node_modules/ node_modules
ok,在项目下运行grunt吧!
(要是使用了jasmine进行单元测试,还需要安装grunt-jasmine-runner模块及PhantomJS)
1. Grunt.js/node.js should be quite easy toonce-click install if this centOS5 server has a internet connection, but, forthis server, I have to copy the .tar manually, then copy all modules andplugins by finding the right place to put
2. Grunt-jasmine-runner require phantomJs to rununit test. At first, I tried to run the complied version for linux, but itrequires libgc v2.9+ , which finally I realize centOS5 can’t afford such highversion (even forcely compile that lib with low version gcc compiler, possiblywill make the low version linux core crash).
3. Then I tried to compile phantomJs 1.7 manually,which depends on 30+ libs. Those can be download fromhttp://mirror.centos.org/centos/5/os/x86_64/CentOS/then copy to server, and run with rpm command in turn. Fortunately, it works
4. The last tricky one, the passed unit test failson that server by run ‘grunt jasmine’.
<pre>Running “jasmine” task
Testing jasmine specs via phantom
…
[D] [“phantomjs”,”onResourceReceived”,”GET http://127.0.0.1:8888/test/spec/CommonTest.js"]
[D] [“phantomjs”,”onError”,”ReferenceError: Can’t find variable: describe”,[{“file”:”http://127.0.0.1:8888/test/spec/CommonTest.js","line":31,"function":""}]]
ReferenceError: Can’t find variable: describe
…</pre>
At last, it’s caused by that: I createda symbolic link for “node_modules” to re-use common module, but it preventgrunt-jasmine-runner to fetch sth. (not sure yet). To resolve it, need to copythe “node_modules” files directly under project folder.
基于HTML5的EasyXDM组件实现浏览器兼容的跨域资源请求
同源策略(http://baike.baidu.com/
HTML5 XDM
近年不断发展的HTML5规范对XDM-跨文档消息传送机制进行
_postMessage(message, targetOrigin, transfer)_函数有三个参数。第一个message表示要
比如下面的例子简单演示了使用postMessage()向内嵌
var iframWindow = document.getElementById(“
iframWindow.postMessage(“
接收方www.html5.org收到XDM消息会异步触发wi
window.addEventListener(“
if (event.origin == “http://www.infoq.com“) {
processMessage(event.data);
event.source.postMessage(“
}
});
easyXDM (https://github.com/
easyXDM包含两个基本对象。
easyXDM.Socket对象包装了传输栈,
服务端首先建立Socket:
var socket = new easyXDM.Socket({
onMessage**:function**(message, origin) {
//do something with message
}
});
var socket = new easyXDM.Socket({
remote**:** “http://path.to/provider/“, // the path to the provider
onMessage**:function**(message, origin) {
//do something with message
}
});
socket.postMessage(“hello world”);
easyXDM.Rpc对象允许创建带有代理对象进行远程方法调
在服务端配置被调用的远程对象:
var rpc = new easyXDM.Rpc({},
{
local**:** {
helloWorld**: function**(one, two, three, successFn, errorFn){
// here we expose a simple method with three arguments
// that returns an object
return {
this_is**:** “an object”
};
}
},
remote**:** {
helloWorld**:**{
// here we tell the Rpc object to stub a method helloWorld for us
}
}
});
rpc.helloWorld(1,2,3, function(response){
// here we can do something with the return value from helloWorld
}, function(errorObj){
// here we can react to a possible error
};
跨域资源请求
在web开发中跨域资源请求相当常用。借助XDM,
下面举例如何使用easyXDM来跨站点文件请求:站点clie
在客户端client.com/index.html引用eas
var socket = new easyXDM.Socket({
remote: “http://remote.com/agent.html“
onMessage:function(message, origin) {
var data = $.parseXML(message);
//do something with message data
}
});
在被请求的远程服务端remote.com/agent.
$.ajax({
type: “GET”,
url: “list.xml”,
dataType: “text”,
success: function (data) {
var socket = new easyXDM.Socket(
{
onReady: function(message, origin){ }
}
);
socket.postMessage(‘’ + data);
}
});
小结:easyXDM开源组件封装和支持HTML5的postM