Loading.. Current Page is Loading.

2010贺卡

8. February 2010

今天有感而发,随意画了一个2010的贺卡,今年春节也是在北京渡过,不过不是一个人,唯一的变化是两个人。总算是要放假了,可能年后会有些变动,不过心情感觉还蛮平静的,希望一切都好。看来不是谁的问题,是我的问题。

这一年来经历的事情不算多,但是也不算少了,这一年我成长了很多,学到了很多东西,但是在获得的时候也失去了一些东西。也会发现,有很多事情是你控制不了的,但是又不愿意去接受的,这个时候我往往会选择逃避,但是逃避的太多了,也会觉得累,所以,也是一个时间好好的静下来,安静的想一想,总结总结。

今年也遇到了和认识了很多人,自己也开始慢慢的变化,例如长胖,有些事情也完全的保留下来了。2009,对我来说是一个平常的不能再平常的年份,但是却发生了很多,可能对于初入职场的我来说,有点措手不及,朋友的离开,加入,选择,逃避,也像戏剧一样的涌上舞台,仿佛世界不知道它的热闹一般。但终究要有个结束,在2010的门槛前,想说点什么,却发现有些话,再也说不出来了。

倒带人生 ,

从何说起

8. February 2010

虽然早就一直在听这张专辑,但是有些歌老是被跳过,第一次听从何说起就感觉到它的内涵,也被深深的感动了。今夜再次相逢,有种说不出的感觉。

如梦令 从何处说起

梦一般剧情凭谁在推移

缘份在偷袭 时间在追逼

那些美好的瞬间 得来不易在

感情还能够感人的时代

为什么有情人 还在颠沛流离

谁辜负过自己 说不上可惜

谁被世道放逐身不由己

谁曾朝不保夕 才为幸福而卖力

才舍得面对镜子 说我可以

月光光 从何处唱起

那圆缺阴晴如何不服气

际遇不讲理 命运没协议

只有从爱人怀抱寻找真理

谁曾朝不保夕 才会死心不息

才舍得万死不辞 说我可以

难题再不成问题 说我可以

鸿爪踏雪泥 还是来得及

对重遇的人说 原来你也在这里

倒带人生, 小分享 ,

Notify2破解版

7. February 2010

在Mac下一直用一个软件,这个软件就是Notify,这个软件主要是提醒你邮件信息,虽然只是一个邮件提醒的功能,但是还是非常实用,在一些细节上做的非常的好,例如UI是我见过至今为止最好的一个提示器,细节也做的相当不错,提示声音我也很喜欢。

可惜今天到期了,竟然要10美元,虽然不算贵,但也不便宜,毕竟是终生的,然后其实有点打算想买(难怪说Mac下的付费用户群体还是很高的),因为做的确实不错,虽然提醒功能平时也没觉得有什么,但是一旦用了哪天没了感觉还真是不太爽。本来都拿出信用卡了,但是还是抱着找一下破解版的目的找了一下,国内的找不到,但是国外的一些社区找到了,马上就丢到dropbox里了,省了10美元。

虽然这样,但还是感谢作者才对,所以。。附上破解程序的下载连接,在程序中选择相应的程序然后点击破解即可。

Notify 2.x [SP].zip (308.57 kb)

Mac, 小分享 , , , ,

Mac开发 - Table View(2)

7. February 2010

我们在Mac开发 - Table View(1)里面使用了Table View这个控件,可是这个控件是一个非常复杂的控件,我们使用于Array Controller绑定的方式去绑定数据有一个明显的缺点,就是只能绑定一个列的数据,这在很多情况下是没有多大的用处的,这个时候我们就需要绑定多个列的数据,当绑定多个列的数据的时候,我们可以使用Dictionary Controller绑定。

我们首先创建一个项目,然后将UI制作如下图即可。

我们在项目中添加一个文件(类),继承自NSObject,注意,这里不需要使用什么NSView的子/派生类,我们只需要使用NSObject类即可。取名NSDicController,然后我们写头文件如下。

#import <Cocoa/Cocoa.h>

@interface NSDicController : NSObject {
    
IBOutlet NSWindow *window;
    IBOutlet NSTableView
*tableView;
    IBOutlet NSDictionaryController
*dictionaryProxy;

}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSTableView
*tableView;


@end

写完头文件之后,写内容代码。

#import "NSDicController.h"

@implementation NSDicController
@synthesize window;
@synthesize tableView;


@end

写到这里都不是那么难理解,好,我们现在先连接一下我们的元素,因为前几篇文章我已经说的很清楚了,所以这里我就不再详细的讲解如何连接了,我这里给出一些示例即可。首先我们还是加一个object,如下所示。

加完之后,我们更改为我们的相应的类即可,更改之后,我们再连接相应的内容到UI上,依旧还是Control+鼠标连接,连接后连接器如下所示。

这样,我们就连接了我们的基本要素,连接完成后,我们就需要编写代码来实现多列的功能实现了,这里我们需要使用的一个方法是awakeFromNib,连接后,当应用程序启动会自动调用和执行awakeFromNib这个方法,我们更改方法如下,代码可能不那么好理解,我加了一些注释。

#import "NSDicController.h"

@implementation NSDicController
@synthesize window;
@synthesize tableView;

- (void)awakeFromNib
{

    
//清空现有的table的列
    NSArray *tableColumns = [NSArray arrayWithArray:[tableView tableColumns]];
    
    
for (NSTableColumn *tableColumn in tableColumns)
        [tableView removeTableColumn:tableColumn];
    
    
//新增加一个列
    NSTableColumn *keyTableColumn = [[[NSTableColumn alloc] initWithIdentifier:@"key"]
    autorelease];
    [tableView addTableColumn:keyTableColumn];
    
    
//新增加一个列
    NSTableColumn *valueTableColumn = [[[NSTableColumn alloc] initWithIdentifier:@"value"]
    autorelease];
    [tableView addTableColumn:valueTableColumn];
    
    
//初始化字典
    dictionaryProxy = [[NSDictionaryController alloc] initWithContent:nil];
    
    
//设置绑定
    [keyTableColumn bind:NSValueBinding toObject:dictionaryProxy withKeyPath:@"arrangedObjects.key"
    options:nil];
    [valueTableColumn bind:NSValueBinding toObject:dictionaryProxy withKeyPath:
@"arrangedObjects.value"
    options:nil];
    
    
//更改字典后自然更改绑定的数据
    [dictionaryProxy setContent:[NSDictionary dictionaryWithObjectsAndKeys:@"obj 1", @"key to obj 1",
    @"obj 2", @"key to obj 2", nil]];
}


@end

通过上面的代码,我们就能够自动的在程序启动的时候添加相应的列,最后效果如下所示。

虽然我们这里使用的是启动时就绑定并添加了数据,但是我们很多时候需要执行按钮按下的方法之后才添加数据,不过不要紧,当我们设置了控件于一些数据的绑定之后,我们只需要更改相应的数据源即可。例如现在这里我们讲table的两个列绑定了一个dictionary,以后我们需要更改列的值的时候,只需要更改这个数据字典即可,系统会自动帮我们更新View。例如可以连接button并写相应的代码去进行操作。

- (IBAction)buttonClicked:(id)sender
{
    
//更改字典后自然更改绑定的数据
    [dictionaryProxy setContent:[NSDictionary dictionaryWithObjectsAndKeys:@"obj 1", @"key to obj 1",
    @"obj 2", @"key to obj 2", nil]];
}

只要在相应的作用域之内,我们只需要更改相应的dictionary的数据即可,无须关心其他部分。

PS:在这里我们就看到一个MVC的一个非常好的地方,就是视图只管视图,数据只管数据,控制器只管控制器的一个优点。

Mac开发 , , , , ,

JavaScript Typo Generator Class

4. February 2010

什么是TypoGenerator?TypoGenerator就是把正确的字符转换为错误的字符的一个东西,例如我在搜索ipod的时候,有可能输出成ipid,这样就输错了。不过这里你会有疑问,为什么我们要把正确的字符输成错误的呢。当我们购买一些物品的时候,还是ipod,很多人会低价的卖,但是不小心输错了,成了ip0d了,这样我们搜索ip0d的时候就可以搜到这个低价的东西。国外就有一个公司专门搜索eBay的这些东西,其他人关注度很低,这个价格自然就起不来,然后这个公司就收购这些低价的物品,然后卖,赚差价。

当然,这虽然不是很好,但也在某些情况下帮助了用户,当然,这个TypoGenerator还有其他的作用,例如可以查找哪个词被输入的错误的次数更高,例如ipod,当你按p的时候,有好多情况会按到o或l或[,这样也可以通过统计的方法去计算一些数据。

网上好像没有JavaScript版本的TypoGenerator,这里我写了一个,提供使用,使用方法如下。

var test = new typoGenerator();
//返回ip0d,ippod,iopd等
test.getAllKeyTypos(“ipod”);

其中有四个方法,分别作用如下:

  1. getMissedCharTypos:ipod => iod
  2. getWrongKeyTypos: ipod => ip0d
  3. getTransposedCharTypos: ipod => iopd
  4. getDoubleCharTypos: ipod => ippod

代码下载

typoGenerator.zip (1.30 kb)

JavaScript ,

Firefox Dev Package for Windows/VIM 0.1.2

3. February 2010

今天花了一点时间更新了一下FFPackage,支持XUL应用程序的开发(Firefox就是用XUL平台开发的),也就是说使用FFPackage进行开发的话,你可以开发一个Firefox应用程序而不是Firefox扩展插件

MDC官方中文关于XULRunner的翻译(我翻译的,英文不好,但是中文资料太少了,见谅)如下。

FFPackage 0.1.2修正一些bug

FFPackage 0.1.1新的1个命令:

  • xulnew:创建一个XULRunner应用程序。

FFPackage 0.1.1新增1个VIM插件:

  • xunrunner.vim

新增的环境变量:

  • 将xulruntime置于PATH变量下。

如何使用FFPackage 0.1.1创建一个XULRunner应用程序,并用VIM开发编译。

  1. xulnew
  2. :compiler xulrunner
  3. :make

同样可以在FFPackage的Release Note.txt中找到相应的说明。

下载

ffpackage.zip(Zh-cn/En-US) (9.17 mb)

FFPackage, Work , , , , , , ,

我在那7%里头

2. February 2010

作者: Regina Brett, 90岁, 来自美国俄亥俄州, 克里夫兰, Plain Dealer城。

“为了庆祝变得更老了, 我曾经写下人生教我的45个功课. 这是我写过最叫座的专栏.” 我这把老骨头8月就要90岁了, 所以, 再一次, 我在这里呈现这一个专栏。据估计, 93%的人不会将这一个邮件转寄。如果你是那7%会的人, 请用”我在那7%里头”作标题, 将它转寄出去. 说明你会认真对待你的人生,我在那7%里头。

虽然我不会发邮件转发,最后弄的像病毒垃圾一样,但是我还是写在了我的博客,把他当做我人生中的座右铭。

1. 人生是不公平, 但还是好得很.

2. 怀疑的时候, 朝着未来踏出一小步.

3. 人生太短, 短到来不及浪费时间去恨任何一个人.

4. 生病的时候, 你的工作不会照顾你. 你的朋友和父母会. 保持联络.

5. 每一个月付清你的信用卡.

6. 你不需要每一次都吵赢. 同意你不同意的.

7. 找人一起哭. 它比独自啜泣更加疗愈.

8. 对上帝生气没有关系. 祂受得了.

9. 退休存款从你的第一张薪水条开始.

10. 讲到巧克力, 抗拒只是徒劳无功.

11. 和你的过去和解, 它不会搞砸你的当下.

12. 让你的孩子看到你哭没有关系.

13. 别拿自己的人生和他人做比较. 你根本不清楚他们的人生是怎么一回事.

14. 如果一段亲密关系要偷偷摸摸, 你根本不应该涉入.

15. 一眨眼的功夫什么都会变. 但是别担心: 上帝从来不眨眼.

16. 深吸一口气. 它会安定你的大脑.

17. 没用的, 不美的, 或不喜悦的东西都丢掉.

18. 没让你死的事情,真的会让你更坚强.

19. 重拾快乐童年永不嫌晚. 但这第二次只能靠你不靠人.

20. 当关乎追求你生命的所爱, 不要把不要当答案.

21. 点蜡烛, 用好的床单, 穿上炫丽的内衣. 不要特殊场合才用. 今天就是特别的一天.

22. 准备要周全, 然后随遇而安.

23. 现在就离经叛道. 不要一把年纪了才开始穿上紫色

24. 最重要的性器官是脑袋.

25. 除了你, 没有人在主宰你的快乐.

26. 把你所有的不幸用这一句话把它表框起来:”五年后, 这还重要吗?”

27. 永远选择快乐地生活

28. 原谅每一个人每一件事.

29. 别人怎么看你根本不关你的事.

30. 时间会痊愈几乎每一件事. 给时间,时间.

31. 无论情况多好或多坏, 它都会变的.

32. 不要那么认真的看待自己. 没有人会这样看待你的.

33. 相信奇迹.

34. 上帝爱你是因为祂就是爱你这个人, 不是因为你做了什么或是没做什么.

35. 不要谨慎地稽查人生. 现在就呈现出你最大的发挥.

36. 变老了是胜利,它打败了另一种选项- 死得早.

37. 你的孩子只有一个童年.

38. 真正最重要的是你爱过.

39. 每一天都出门.奇迹在四处等着.

40. 如果我们都把我们的问题都丢成一堆, 然后看看其它人的,我们会把我们的捡回来.

41. 别忌妒别人浪费时间. 你已经拥有你所需要的了.

42. 相信你最好的都还没来.

43. 不管你感觉如何, 起来, 穿好和呈现.

44. 善待每一个人.

45. 人生最终不会被打上蝴蝶结, 但它仍然是一份礼物.

倒带人生

Firefox Add-on IO读写安装包内文件

1. February 2010

原来写过一个File类,这个类的作用就是在Extension中读写本地文件,不过作为浏览器插件,读写本地文件到磁盘就会有一些很不好的问题,这些问题可以总结如下。

  • 写文件要写绝对路径。
  • 不同操作系统有不同的路径。
  • 卸载插件的时候需要手动找到路径删除。

这三点是非常麻烦的,也会造成后期的维护的困难。当然,我们希望的是用户卸载插件的时候连同配置文件一起删除,读写文件也写到安装包路径中。

在Firefox中,有一个XPCOM可以解决这个问题,我们可以通过以下代码获取路径。

const id = "test@test.com";

var extension = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager)
.getInstallLocation(id)
.getItemLocation(id);

然后,我们可以通过相应的IO类去进行文件的读写,代码如下。

var io = new jguoer.IO();
var file = io.open(extension.path+"\\file.txt");
io.write(file,
"test");
alert(io.read(file));

同样,附上我写的IO类,可以读写文件以及进行一些编码转换,代码我就不贴出来了,好的命名已经解释了一切了。

IO.rar (1.45 kb)

Firefox Addon , , , , ,

敏捷开发不是万能

31. January 2010

今天在微软年终Party中分享了敏捷开发的观点,让我真正的开始反思敏捷开发这个词,原来我一直都不知道自己的公司是在进行敏捷开发,不知道是喜是悲。也从这一段时间的开发过程中知道,其实敏捷并不是万能的,项目的速度和质量最重要的还是靠整个团队的协作。有人曾经说微软的敏捷做的不好,其实仔细想想自己的敏捷实践其实更烂,因为敏捷有几点是需要关注的。

  • 合格的自觉的编码规范。
  • TDD,先写单元测试再编码。
  • 客户参与项目。
  • 团队的平等性。

其实要做到上面的很难,无论是大公司还是小公司,其中最有趣的一点是,敏捷的团队要保持创新力和持久力,每周不能工作超过40小时,相比起来,不加班已经够幸运了,更不要说那种没有理由的或者瞎编理由让你加班的了。

所以,要知道敏捷并不是万能的,实践敏捷之前,还要考虑自己的团队能不能敏捷起来。另外要提醒一点的是,如果不能真正保证自己能实践的成功,就不要在实践之前鄙视某些其他的公司,其实以五十步笑百步才是最让人鄙视的,谦虚一点也没什么不好的。

Ideas, 软件开发

微软2009年年终Party

31. January 2010

今天作为版主的身份去参加微软2009年年终Party,总体来说因为是新办公室,比去年要宽敞一点,大中华地区的一些IT服务方面的leader都来了,可以看得出来微软对开发人员来说是非常照顾的,也是投入了很多成本,今天上去简单的介绍了一下自己,其实我现在慢慢的已经不在微软阵营了,因为我是程序员,所以什么都用嘛,所以会逐渐淡出微软论坛版主,当然希望这个论坛还是能越来越好。微软今年的礼物就是Key而已,而且还是Office 2007的,所以,无语,不过送一个MVP的杯子,还不错。

刚去的时候别人还以为我们是媒体。。哈哈,搞笑。。下面是照片。

倒带人生 , , , ,

杯具的人生

31. January 2010

今天终于了解到什么叫杯具的人生了,人不是傻子,不会什么都不知道,不说只是觉得算了,还好理解,也是对于长辈的尊重,但是不能太逼人太甚了。狗急也跳墙。

倒带人生

2010

31. January 2010

很久没有动笔去涂鸦了,其实涂鸦现在对我来说是写程序之外最好的休闲方式了,可以休息大脑还可以锻炼一下绘画。其实本来想去线条上色然后成为插画形式的,但是没有数码板,就算了,下次有钱买个数码板,然后再买一只笔,至少画的顺畅一点。对于2009,我没什么好说的,2010,我倒是希望可以脱离旧的自我,找到一个新的天地,祝我好运吧。

倒带人生

Mac开发 - Table View(1)

31. January 2010

Text View算是Mac里面最常用但是最复杂的控件之一,我也是用了一下午的时间才知道如何使用这个控件,Mac控件并不像VC或者C#一样直观上是消息通信模式,也不是通过事件,添加相应对象的子节点去增加控件内容。Text View算是比较特别的控件,复杂的Text View控件可以做出很多复杂的效果,在iPhone上更是如此,最有名的软件如Twitterrific的Mac版本和iPhone版本显示Twits都是使用的Text View。Text View就好像C#中的Gridview,或者C++的listbox。

首先我们创建一个项目叫TextViewTest,创建好之后,我们在Class文件夹下面添加一个类,取名叫Controller(这里可以创建位NSObject或者位NSView的子类都可以)。

创建好之后,我们打开MainWindow.xib文件,然后制作UI如下图所示,我们的需求很简单,单击按钮添加一行数据。

编写好了UI之后,我们就需要连接一些基本的东西,这里我们拖动一个Object对象进来,并改成相应的Class。

拖动过来还需要更改为相应的Controller。

更改后,我们的这个Controller就是我们的Controller类的一个对象了。这里我们需要写一下Controller类,头文件我们可以定义如下。

#import <Cocoa/Cocoa.h>

@interface Controller : NSView {
    
//定义数据源数组
    NSMutableArray *array;
    
//定义数据
源数组的Controller,连接用
    IBOutlet NSArrayController *arrayController;
    IBOutlet NSButton
*button;

}

@property (nonatomic,retain) IBOutlet NSButton
*button;

- (void) buttonClicked:(id)sender;


@end

然后我们实现的代码很简单,每次点击都添加一个test字符串。

#import "Controller.h"

@implementation Controller

@synthesize button;

- (void) buttonClicked:(id)sender
{
    
//添加字符串
    [arrayController addObject:@"test"];
}


- (id)initWithFrame:(NSRect)frame {
    self
= [super initWithFrame:frame];
    
if (self) {
        
// Initialization code here.
    }
    
return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    
// Drawing code here.
}

@end

编写完成后,我们还需要连接各个对象,例如button连接到代码中的button,button的按下的事件连接到buttonClicked。这里我就不累述了。

Text View是一个可以进行数据绑定的控件,所以前面我才说和C#的GridView很像,不过没有VS那么智能了,这里Text View绑定的是类似数组的对象,所以这里我们还需要拖动一个Arrray Controller,进行数据的连接。

拖动完成之后,我们就需要连接Controller和Array Controller,这两个对象组成一个类+数据源的结构。

拖动完成后,我们需要绑定相应的对象,例如上面绑定的是arrayController,也是我们前面代码定义的一个变量,否则看不到这个连接项。这个时候我们连接前面定义的arrayController,就连接了Array Controller。连接后,我们还需要设置绑定,我们在Array Controller的属性窗口中设置即可。

上图我们就将Array Controller绑定了Controller里的array变量。也就是说Array Controller现在已经成为了数据源,任何array对象的改变都会影响到这个Array Controller。

现在我们再打开UI,找到相应的一列,选中该列(而不是选中大的控件,是其中一列,如下图)。

选中该列,然后在属性窗口中绑定相应的数据源即可,如下图。

绑定完成后,我们只需要操作arrayController里面的元素就可以了,而不需要关心如何绑定到Text View中的,如下代码。

[arrayController addObject:@"test"];

 连接完成后的Controller和Array Controller里的连接如下两图所示。

小结一下:

使用Text View的基本步骤如下。

  • 写Controller,并连接。
  • 创建Array Controller并绑定。
  • 绑定相应的Text View的列。

虽然看上去很简单,但是实践起来还是有一定难度的,建议各位自己动手实践一下。

TextViewTest.zip (29.47 kb)

Mac开发 , , ,

接吻挎包

30. January 2010

今天看到一个挎包,很有个性,名字叫接吻挎包,不过我想应该没有情侣会喜欢用一个包弄到头上然后接吻吧,还不如直接接吻来的直接,不过这东西看上去还蛮有意思的。

Ideas, 小分享 ,

命令行和自动化的魅力

26. January 2010

本来想写这样一篇文章很久了,虽然也有时间去写,但是这样的貌似纯理论的东西感觉还是很难下笔,今天晚上想着还是写下来好,以后自己看也是一个值得回忆的技术过程。因为我自己使用命令行比较多,所以对我来说,任何机器首先最重要的是命令行环境了,在Windows下面,使用cmd和一些alias工具去使用命令行,在Mac或者Linux下面,命令行更是鼓励的一种方式,可见命令行虽然在历史上很久了,但还是非常重要的。

其实我原来一直都是在微软的.net平台下进行开发的,C#固然强大,但是帮你做的事情太多了,你不需要关心内存泄露,也不需要关心垃圾释放,也不需要关心指针问题,更不用关心自动化等等了。当然,好是很好,但是对程序员的自身提高还是有一定阻碍的,特别是对那些从C#入门的开发人员来说更是这样,所以就会很难理解命令行和自动化为什么好了。当有一个新语言或者新的东西发布的时候,如Chrome插件,iPhone开发等等,很多依赖平台或者IDE很强的人就茫然了,无从下手了。

但是很多人让他们去写这样的东西,用记事本什么的,也可以写出来,但是效率那就是很低的了,这也就是对命令行等等不太熟练造成的,为什么国外的很多程序员很厉害,因为他们基础很好,高层的自然就好了,当遇到问题的时候,自然就会找到简单的,高效的方式去解决。

说了这么多废话,还是举例最快了。例如当我们进行软件开发的时候,我们大部分的流程是这样的。

这个过程貌似是传统的软件开发过程,比如有人做数据库,有人写后端逻辑,进行性能优化,有人做中层开发,封装后端的复杂的逻辑,然后有人做前端开发,调用中层开发的封装的逻辑。当然,任何一个步骤都是复杂和难以控制的,前端要考虑用户体验,UI,UE等等,中层要考虑类的封装和设计,考虑到扩展性和实用性,后端要考虑到性能处理等,DBA数据库开发要考虑到数据读取,IO优化,索引等等,既然各个步骤都是复杂的,但是是什么让我们的过程更加复杂呢,那就是teamwork。

在teamwork中,各个成员依赖于不同的成员,也可以说依赖于不同的成员的结果,例如使用其他成员的代码或者库,这就考虑到协同的问题,所以这就是为什么会有版本控制和流程控制了。当然,当只有一个项目的时候,这虽然也很麻烦,但是还算是比较好解决,但是当项目越来越大,产品线越来越长的时候,一些问题就突出的显现出来了。

举例说明,假设,微软的Windows和SQL Server都要读取XML,但是都使用相同或差不多的逻辑,但是每个团队都有自己的方法,当过了5年或10年,出了BUG,有人修改了SQL Server里的XML读取的方法,但是忘记更改Windows里的,但是Windows团队以为改了Windows里的库,就发布了,但用户一旦一使用,发现出现了崩溃的情况,这是非常正常的,也是无论在大公司还是小公司都会发生的情况,这个时候用命令行可以优化整个过程。

例如当Windows团队和SQL Server团队的发现都写了一个相同功能的类的时候,可以将这个代码放到一个公共库里面去,然后每次使用命令行,在编译的时候自动拷贝最新的库,以保证代码的正确性和兼容性。这样就会有几个好处。

  • 代码维护简单:只在一个地方。
  • 应用程序最新:每天build的程序都是最新的,每个团队成员都是使用的最新的库,不会有错误。
  • 更改维护简单:更改一个地方,所有的代码都会更改为使用最新的代码,而不会这个程序是0.1版本,另一个是0.2,再一个是0.3。
  • 跨应用程序维护:所有的应用程序都可以使用这个库,例如Expression或者VS就同样可以使用这个类。

其实将上面的需求联系到我的实际,就是我在平常的工作中会开发好多东西,例如Firefox插件,Chrome插件和一些Widget,但是这些东西的开发都是大同小异的,都是用HTML和JavaScript,这个时候,就要考虑这样的需求了,是不是所有的软件都可以公用一些东西?如下。

例如我有一些库,而且都可以使用到Firefox,Chrome和Widget里,怎么办,难道我每次都要自己手动从库中拷贝吗?那么如果是这样的话肯定会遇到这样的问题。

  • Boss:Hey GuoJing,你这个可以运行吗。
  • GuoJing:当然可以,只要XXX就可以运行了。
  • Boss:哦,不错,不过另一个好像不工作,这两个代码应该是差不多的。
  • GuoJing:额,寒,我记得我上次拷贝过来了,忘记了,这次再拷一下就行了。
  • Boss:我们不能这样,我们要有一个自动化的系统。

这样的事情会经常发生,有些是显性的,例如你项目不能用了,不能工作了,有些却是隐性的,例如发布了1年之后才发现这个严重的BUG,那就真的就是一场灾难了。

所以命令行和自动化系统能帮我们自动的处理这些烦人的问题,我可以这样做。当需要打包或编译一个项目的时候,自动化的拷贝其他的项目的依赖库到我的应用中,如果其他项目需要编译,那么就先编译其他的项目,然后将最新的依赖库拷贝到我的应用中,如果依赖的库有问题无法编译,自动的通知负责人告知相应的BUG。也就是说,你的一个命令,会做很多的事情,而这么多的事情,仅仅只是一个命令而已。

命令行还有一个显著的特点就是,当你写对了一次,就不会再错了。这样就能保证我们系统的健康性和完整性还有一定的可重用性。

当然,这也可以不需要使用命令行,但是命令行是最简单,最轻便,成本最低的一种方式,如果一个团队的人都熟练使用相应的命令的话,效率会提升不只一倍。

其实,我们使用命令行和自动化的最主要的原因,不是为了耍酷或者说自己是一个真正的程序员,而是在项目中,更多的考虑重用,简单,依赖,可持续性的问题,对于小的公司,小的项目,可能这样的需求不是很高,甚至一个产品都不怎么测试的就发布了,但是对于大一点的公司和项目,自动化的处理,测试,编译,运行和发布都是非常重要的,这也是为什么微软会有用WTT自动化测试和Daily Build了,也是为了保证项目的完整性,健壮性和可持续性(例如微软的有些项目每天都会用很多机器自动的编译,然后自动的测试,自动的将结果发送到每个团队成员邮箱中,这样每个人都会知道哪里的问题,而不是打电话说,喂,好像你那里有问题,我们什么时候看看吧)。

命令行和自动化,其实就是为了简单,自动,高效。虽然一些小公司不太需要这样的概念,甚至可以说我的成本弄不起,但是为了将来的发展,和一个企业的习惯,尝试一下也不是不可以的。:)

软件开发 , , , ,