This post is password protected. To view it please enter your password below:
This post is password protected. To view it please enter your password below:
总的来说,IBM在我学生生涯占据了一个很重要的位置,从大二加入学校的IBM俱乐部,其间参加过IBM的全国大学生创新大赛,去过九寨参加IBM夏令营,一直到研二来到CDL实习。2009年7月14号,我从一个实习生转成了正式员工,bluepathway还在沿续。
进入公司做的是数据挖掘产品相关的开发,工作还是在一种轻松愉快的氛围下有条不紊地进行着。感觉有无尽的资源你可以学习,从到SQL的执行优化,到clearcase best practice;有数不清的大牛你可以请教,从OSGi到EMF,因为很多这些技术标准的制定者就能在bluepage上查到。
对一年的表现来说,我自己觉得也跟大多数新人的PBC一样吧,solid contribution,但并未有太多让人吃惊,为之眼前一亮的东西。生活中的一些事情也占据了这一年的一些时间吧,比如房子等等。接下来的一年,希望生活上能逐步稳定下来,这样才能对长久的工作和生活都是非常重要的。
接下来说一些一年内自己觉得比较有意思的东西吧:
据说这是一个美国二线经理在你伸手要技术文档常说的一句话。看起来很不讲道理,但从个人coding能力的角度来看,读代码的能力是非常非常重要的。如果你看过很多开源框架的源代码,对设计模式知道个所以然,那么你在了解整个产品方面并不会遇到太大麻烦,因为你在读代码时看到一个inner Mediator类时,就知道它接下来要做什么事情了。而只有基于正确的源码级理解,才能形成良性的迭代开发循环,否则,改regression还来不及呢。
想升band光有solid contribution是不够的,你还得在你经理期望的范围之外,体现你的added value。
一开始还经常把自己当作新人看待,但当最近一次不小心弄坏build时才意识到,当某些错误发生时,借口是没有用的。如果道歉有用,还要警察干嘛。。。做错了就是做错了,IBM更相信process leads to success。所以要是再担心弄坏build,写一个自动化pde ant脚本就好了。
这是写邮件陈述问题的一些看法,尤其是在给一些国外同事写信的时候,最好在信的开头就把这封信的意思说清楚,因为并不是每个人都愿意知道的那么详细,也不是对你很紧急的事情在他们也同样很紧急。to的人可能比较仔细地看,cc的人可能就只是看个大概。所以把相当一部分信息highlight出来,对你获得你想得到的回复是非常有必要的。
一个QA同事说过这么一句话:QA主要是帮助Dev找出问题的,也就是说,Dev的工作正是由于QA的保证,才会显得高质量。而QA本身是再没有QA对他们的代码质量进行保证的,这些代码可能包括测试用例,测试脚本等等。所以如果以一个开发者的角度来看待QA的代码,以Dev的一些专业知识对这些进行refine,那么保证了QA的工作的同时,也保证了最终产品的质量。其实很多开源框架发展到一定阶段,都是由框架本身来cover部分quality,比如EMF和Hibernate的validation模块。
这条也是每个人都知道,都并不是每个人都能做好的。每天都有不同的事情,不同的想法企图在你的大脑中永久地占据一片内存,如果不记录,要么选择性遗忘,要么就等着out of memory。在解defect时,有新想法时,走新的流程时,有时候只需要简单的一个wiki page,一个teamroom comment或者一个shell脚本,记录不仅让你在下次同样的事情只需要O(1)的时间定位,也在与同事分享时show出了你的价值。
Blog又经历了一阵空白期,很是惭愧。。翻了翻这个blog的历史,其实也经历过好几个不写blog的阶段——或许自己可以找这样那样的借口,比如感情,玩Wow,找实习,但其实都可以归结成一个原因:懒。
没错,生活或者工作,懒得思考,懒得总结,懒得记录,结果就是日子如白驹过隙般,没有留下一丝印迹。
要说来,其实工作这半年多来还是积累了一些东西的,技术上的大部分都记录在公司内部的teamroom里了,而更多沟通或处理问题上的方式本以为自己能牢记在心里,其实则不然。我想这也就是为什么《走出软件作坊》和《和时间作朋友》之类的书,如此畅销的原因。大脑的内存就那么一块地方,你的缓存算法不可能总是命中。。你总得学会从别人身上学习优点,学会总结,学会记录,千万别学会无理由的遗忘。纵使做不到GTD那般精准和万无一失,但亦不致于那般眼高手低。
0 box here I come,这恐怕是GTDer行为方式的缩影吧。对于我这种懒人来说,GTD并非不可,不过恐怕总有些强弩之末的感觉。问题不在于是否GTD,而在于克服人性的懒惰和集中精力坚持做有意义的事情。今日事今日毕,则是一个基本的观点。
用老刘的话来说,我的本命年过的很顺。。。可能是穿了红内裤的原因哈XD不过这本命年一过,好像运势就有些偏转的迹象,春节就开了一个不太妙的头。
新的一年想到了以下目标:
读更多的书;
坚持更多的总结和记录;
在与工作或技术相关的范围内更让多的人知道我。
立此存照。
今年过年回家,我用实习的工资第一次给外婆买了礼物,内联升的布鞋。
昨天,北京罕见的下起了大雪。白色的世界,有一个很美的词叫做银装素裹。
可白色,其实也有另一层很独特的意义。
今早,一觉醒来,再平常不过的一个星期一,却罕见并清晰记得梦里梦到了ex。
我无法不相信冥冥之中自有天意。
晚上,本以为是妈妈家常的问候电话,可电话那头格外清晰的哭腔告诉我:外婆永远的走了。
外婆年初查出是胃癌晚期,病情一直在恶化。虽然有心理准备,可是此刻,我的脑子仍然一片空白。
妈妈说外婆走的很突然,并没有太大的痛苦,也让我不用担心外公。
妈妈说外婆快走的时候已经说不出话,只是指着她的手镯,外公问是不是要把它给我未来的媳妇,外婆微笑地点了点头。
妈妈说外婆平时并不舍得穿我买的那双内联升,却在今天永远地穿上了它,安祥地走了。
此时的我,再也无法抑制,放声大哭。
此时的我,宁肯相信凤凰涅槃,相信死亡只是重生。
童年时候在外婆家的一幅幅画面在眼前掠过:
每周五坐在舅舅的自行车去外婆家,我晃着腿在上坡时给自行车“加速”;
睡觉前去鸡窝里把鸡蛋给掏出来递给外婆,就好像那是我的产品一样;
外婆在地上划一个圈,说不要跑出去,她一会就回来。我就静静地坐在圈里,等着外婆回来;
晚上在木板桥上乘凉,外公教我识别天上的北斗星;
夏天每天下午盼着那个半点响一次的大钟拨到4点,便跳下渠道去洗澡;
每周天要回家前,外公都会把我叫到屋里,给我一点零花钱,嘱咐不要告诉外婆;
外婆家的钥匙有一副是备用的,就放在门口的窗台上,拿着小铁盒盖着;
外婆家天花板上吊着很多篮子,小时候我跳起来也够不着,现在我已经要低着头以免碰着;
……
如果说内心有一丝安慰的话,可能就是我上大学后第一次在今年十一回家,否则我将后悔一辈子。很多朋友知道我回家,却很少知道我的目的。
外婆,你在天堂还好吗?
由于Qi组织了一个提高代码质量的学习过程,也强制性向我们提出了每篇两周blog的要求。对于写blog,一直是个比较懒的人,有时候会心血来潮地写上一些,但更多的时候是有些想法在脑子里一闪而过,却并没有及时记录,读书亦如此。正好借这个机会,将我在读重构这本书时的一些感悟记录下来。
P15. 任何一个傻瓜都能写出计算机可以理解的代码。惟有写出人类容易理解的代码,才是优秀的程序员。
这可以从两个方面来看,一是代码的格式,没有多余的空格,没有多余的tab,正确的注释等等。对于一个团队来说,制定一定统一的代码默认规范是很有必要的,Eclipse已经支持这一功能,如{是在函数同一行还是另起一行,final string用大写单词和_连接,if和后面的(…)必须接空格等等。虽然你可以用Ctrl+Shift+F来格式化,但这并不是不注意代码规范的借品,在写代码时初始便将这一套规则印在脑海中。在这一点上,我自己便是一个非常偏执的人。
另一点便是程序的逻辑结构,类结构化的书写方式亦或是故弄玄虚的show设计模式都不足取。作为一个程序员,最重要的是弄清楚究竟我们要的结果是什么,再进一步,面对最有可能的变化,我们所写的代码是否准备好了?思考有可能的变化与过度设计并不是矛盾的,XP提倡先动手做做看,但不是不经思考便挽起胳膊仓促上阵。以前在Deshi实习的时候另一个实习生写的代码经常会比较长,一个regular忍不住说:你这个函数有几米长。。。人不是机器,当他看到这种冗长的代码,首先就不会太高兴,如果没有好的工具支持,看这些代码是很痛苦的事情。
C-H-A-N-G-E
让我们首先将这6个字母在心里完整的默念几遍。如果一个程序写出来之后需求永远不会有变化,那么对于这个程序本身来说,在效率不至于太差的情况,它确实无所谓要求多高的OO结构技巧。但是事实上呢?绝对不是。而实际上大部分软件工程的理论,MDA也好,Design Pattern亦或Refatoring也罢,都直面并试图解决需求变化的问题。对于重构来说,它并不是从设计角度来解决的。按照Kent Beck等人的思想,重构就是重构,它只管更加合理的重新组织代码;而添加新功能就是添加新功能,它只是纯粹的往现在代码中添加新功能的代码。二者不要也不应该混淆。
基本的重构方法
第一章中由一个案例引出了一些重构的基本方法,如extract method,move method,replace temp with query等。
而在上一个GPS项目中,面对多个GPS厂商的标准支持时,我也不知不觉地用到了replace conditional with polymorpohism的重构方法。什么,你不相信?好吧,我承认是在新需求到来后我添加新功能时的写法。MS同时戴了Kent Beck所言的两顶帽子:D
更多的重构方法详解及在Eclipse中的支持,在读到第五章后再详细阐述。
严格的说来,这并不是Flex的初体验了。最早听到Flex这个名词是从Cowoo口中,那还是四年前的事了,之后也看过一些电子书。不过,总是徘徊在入门者周围。而最近有一个月的时间在实际项目用到,虽说只是个demo,但还是很不错的。
项目的需求是将DB2的xml特性运用在BI分析上,由于xml的动态性,相应的也就能动态地展示维度信息。而从技术上来说,一分为二,前台的Flex与后台的Service实现方式。这里就只谈Flex了,项目中涉及到的有以下几个:
前后台通信
Flex提供了几种方式,无论是HttpService,WebService,还是RemoteObject,交互方式只是在协议的不同。说到底无非也就是二进制流的来回传送,究竟是怎样交互,甚至你自己也可以定义一套。
这种将前后台严格区分开的通信方式较为灵活,比如你可以把前后台程序部署下两台不同的机器,同样的缺点在于你必须严格定义好通信协议,否则你不能保证传给后台的参数的有效性,也就不能保证后台返回的数据的正确性。还有一点,返回的数据的处理与显示应当按MVC适度分层。
现在越来越多的系统不用采用单一语言从前台写到后台的方式,各是各种语言各负其责,如Flex,JS等更适合做些browser端的操作,而后台的业务逻辑可以采用强类型的语言如Java,C#,然后二者之前通过某种协议串联起来,如restful webservice在Ruby就有良好的API支持。
XML处理与显示
ActionScript的XML API让我非常非常震惊,它是如此的顺手,以至于得到XML中任意条件的数据几乎只需一条语句就能搞定。只有想不到,没有做不到,其便捷性远远超过了Java语言中处理XML那种一板一眼的方式。而Flex的组件也与XML无缝地集成,比如Explorer Tree, Column Chart以及OLAPDataGrid。
事件处理机制
从AS的整体处理上来说,统一采用了事件监听机制,与Java Swing非常相似,只不是Flex中响应事件的是函数,而在Java中是一个对象(一般习惯写成匿名对象)。Flex中一般的可视化对象都已经有内制的事件处理机制,例如
<mx:Button id="searchButton" label="Search" click="search();"/>
而对于非可视化对象,一般的做法是继承flash.events.Event创建自己的Event类并创建与事件相关的属性,在这个事件触发时dispatchEvent()。而这个Event由谁来处理,它并不关心。注册了监听事件的组件则会收到相关通知,进而处理相关逻辑。其实对于可视化对象这套方法同样适用,甚至你都可以在mxml里面的click里面直接写某些简单的代码。而究竟是再抽象一层,还是相对暴露地写在mxml里,那就看你自己的考量咯。
优点及缺点
# 由于AS的动态性,Flex Builder有些地方是无法进行语法提示或者自动补齐的。比如没有自动导入所需包等。
# 没有一个简单的AS语法测试环境,最简单的Hello World也要基于MXML程序或者FLA程序来显示之后才能测试。
Reference
# Flex 3 Cookbook
# Programming Actionscript 3
# http://examples.adobe.com/flex3/componentexplorer/explorer.html
今天无意登到WP后台逛了逛,一巨干尸赫然在目。。。扫了一眼,貌似重见天日沿能存活,赶紧发出这篇两个月前写的draft。
============================不愿烂在草稿堆里的分割线=================================
书接上回,补上上次没写完的。
他山之石,可以攻玉
通过自己动手写的client和socket能细致地了解一些细节,但这个山寨版的产品还远远不能放到项目的生产环境上去。而成熟的开源API能为我们省去重复制造轮子的时间。
HttpClient
这个出自Apache的API包很好地封装了一个Http Client的全部细节。比如Header的拼装,发送正文的数据,接收回来报文的解析。有些动作是隐式的,看一些源代码会更清楚些,比如如果设置了Content-Type,它会用这个来编码正文流;并进而设置Content-Length的字节数。
1. 尽量不要用deprecated的方法。比如setRequestBody(String s),然后你send一个UTF-8的流,那么HttpClient做的动作就是给Content-Length的值设置为s.lengh(),这显然是不对的。length。既然length都没设置正确,要是还能在server端得到正确流就是奇闻了。正确的做法是使用**RequestEntity,例如这样:
RequestEntity entity = new ByteArrayRequestEntity(s.getBytes("UTF-8"));
postMethod.setRequestEntity(entity);
类似不被推荐的方法还有一样,这些大多是基于ASCII设计的,而现在的做法更好考虑了I18N编码的需求。
Servlet
用Servlet来当做你的Server当然是很方便的了,就它来当做客户端access的service。doGet()和doPost()方法接收客户端,然后Servlet规范提供了足够傻瓜的方法供你调用,比如servlet.getInpuStream()。这个方法和jdk socket API提供的socket.getInputStream()相比,区别在上篇文章中已经从实践结果上看到了。如果要问为什么会这样,就只能看看各web/app server对Servlet规范的实现源码了,比如Tomcat中的CoyoteInputStream。作为Servlet规范中request.getInputStream()方法的具体实现,CoyoteInputStream里的read()及相关方法都可以看看。
PS: 本想把Tomcat的这段代码实现贴些上来,可是看了一晚上仅仅是有些眉目,离清晰地剖析实现还是有段距离,所以也没能完全佐证那些结果。今晚的最大收获就是把tomcat在eclipse编译了一遍,然后打下断点,单步跟踪,还是能发现一些tomcat的原理,诸如启动流程,收到请求的处理周期等等。这些经验总结还是等有精力了再来做吧。
雕虫小技
Https
如果server端要求SSL的连接方式,在client端需要首先得到server端的证书,然后用jre的一个工具导入,然后在运行时将这个值设为临时的某个system property。这方面的文章google就有一大把,就不在此赘述了。
Concurrency
作为server端,要么用Servlet来做,它本身是多线程的。要么自己写一个standalone的java application来做server端,也不费事,这部分就不说了。
而作为client端,可以尝试一下jdk 1.5引入的Doug Lea的concurrent包。我在项目中是这样实现的,send处理逻辑部分:
public void run() {
while (!stopFlag) {
try {
// judge condition
if (…..) {
/* access to the pool */
semaphore.acquire();
Runnable run = new Runnable() {
public void run() {
// sending reqeust logic ……
}
};
pool.execute(run);
}
else {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
getLogger().warn("Thread is interrupted.");
}
}
} catch (Exception e) {
getLogger().fatal("***", e);
this.stopFlag = true;
}
}
pool.shutdown();
getLogger().info("*** is terminated.");
}
而semaphore和pool在这个类的构造方法里初始化:
public class *** implements Runnable {
……
private int poolSize;
private final Semaphore semaphore; /* initial a thread pool */
private ExecutorService pool; /* set the limit to access the pool */
public ***() {
super();
……
poolSize = Integer.parseInt(propService.getProperty(
"***_pool_size", "4"));
pool = Executors.newFixedThreadPool(poolSize);
semaphore = new Semaphore(poolSize);
}
……
}
Concurrent包还有很多实用的功能与技巧,遇到再与大家分享:D