十一 03

但愿不用等太晚:)

#!/usr/bin/python
 
import urllib2
import sys
import time
 
def alarm():
	while True:
		sys.stdout.write('\a')
		sys.stdout.flush()
 
def poll():
	count=0;
	while True:
		count = count + 1
		now = time.localtime( time.time() )
		print '%02d:%02d:%02d %d' % (now.tm_hour, now.tm_min, now.tm_sec, count)
		try:
			urllib2.urlopen('http://store.apple.com/hk-zh/browse/home/shop_iphone/family/iphone/iphone4s')
			alarm()
		except urllib2.HTTPError as error:
			pass
			#print error
 
		try:
			iphone4 = urllib2.urlopen( 'http://store.apple.com/hk-zh/browse/home/shop_iphone/family/iphone/iphone4' )
			html = ''.join( iphone4.readlines() )
			if html.find( 'iPhone 4S' ) != -1 :
				alarm()
		except:
			pass
 
		#time.sleep(1)
 
if __name__ == '__main__':
	poll()
Tagged with:
04

算法的思想来自与和同事的一次聊天,做了改进,使得精度可以通过参数控制。

Frequence.h

#pragma once
 
class Frequence 
{
  public:
	Frequence( int precision = 10 );
	~Frequence( );
 
	int Check( );
 
  private:
	int		_precision;
	int 	_slot_num;
 
	struct stSlot
	{
		int count;
		int time;
	};
 
	stSlot *_slot;
 
	inline int calculate( int now );
 
	inline int get_current_slot_num( int now );
};

Frequence.cpp

#include "Frequence.h"
 
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
 
static const int kMinute = 60;
 
Frequence :: Frequence( int precision )
	:	_precision( precision )
{
	if( _precision > 60 ) _precision = 10;
	if( _precision <= 0 ) _precision = 10;
 
	_slot_num = kMinute / _precision + 1;
	_slot = ( stSlot * )calloc( _slot_num, sizeof( stSlot ) );
}
 
Frequence :: ~Frequence( )
{
	free( _slot );
}
 
int Frequence :: Check( )
{
	int now = time( NULL );
	int current_slot_num = get_current_slot_num( now );
	stSlot *current_slot = _slot + current_slot_num;
 
	int diff = now - current_slot->time;
	if( diff > kMinute )
	{
		current_slot->count = 1;
	}
	else
	{
		current_slot->count++;
	}
 
	current_slot->time = now;
 
	return calculate( now );
}
 
int Frequence :: calculate( int now )
{
	int current_slot_num = get_current_slot_num( now );
	stSlot *last_slot = NULL;
 
	int total = 0;	
	int index = 0;
	while( index < _slot_num - 1 )
	{
		int last_slot_num = ( _slot_num + current_slot_num - index ) % _slot_num;
		last_slot = _slot + last_slot_num;
		int diff = now - last_slot->time;
		if( diff > kMinute )
		{
			last_slot->count = 0;
		}
 
		total += last_slot->count;
		index++;
	}
	return total;
}
 
int Frequence :: get_current_slot_num( int now )
{
	return ( now % ( _slot_num * _precision ) ) / _precision;
}
24

好吧,大家(看到这些文字的地球人)都知道Nginx是什么用的了。
这里只是希望可以稍微详细的记录下收集到的信息。
毕竟在一头扎进源码的深潭之前,先在水面观察一阵并不是什么坏事:)

Nginx不是一个普通HTTP Server,它还是一个免费、开源和高效的HTTP Server。
免费和开源是显然的事实,因为源码可以从官网上下载;
高效不能一眼看出,但也有测试数据和市场份额做间接的支持。

Nginx不仅仅是一个HTTP Server,它还可以用作Reverse Proxy和Mail Proxy。
作为Reverse Proxy,主要用于负载均衡、SSL支持、Cache等方面;
Mail Proxy了解不多,暂不妄言:)

根据官网的数据,目前Nginx的市场份额为7.5%。这个数据也和netcraft.com上的调查结果一致。
详细数据可以参考http://news.netcraft.com/archives/2011/01/12/january-2011-web-server-survey-4.html

顺便截下最新的分布。Nginx排名第三,而且势头良好。
不过如果想对领先的Apache和IIS构成威胁,则还是非常遥远的梦想。
nginx market share

项目从2002年开始,2004年开源。
初始作者和主要维护人名叫Igor Sysoev,俄罗斯人,70年生,目前在莫斯科。
可以在http://sysoev.ru/en/找到更多的资料。
不过如果想对个人有更更多的了解,最好懂点俄文。
这对东北的同学来说可能不是难事:)

对这位牛人的相貌比较好奇,Google到的结果让人无从选择。
好在这个星球上,除了Google,还有一个叫Facebook的网站:)
igor
据他在Facebook上的资料显示,他和Intel有某种联系,莫非跳槽了?

发音方面,和Linux一样,最好还是采用发明人的说法,“Engine X”。
挺酷的样子。

作为一个服务器,Nginx的优点非常突出。
http://wiki.nginx.org的说法,高性能、稳定、功能丰富、配置简单,并且节省资源。
难道世界上真有只好不坏的东西?

它使用事件驱动的异步模型,而不是多进程/线程竞争接入请求的架构,解决了C10K的问题。
从官网的描述可以看出,Igor对此架构非常自豪。
不过从现在看来,这样的架构被没什么超凡入圣之处,公司内可以看到很多类似的实现。
甚至可以说,这已经是常规的做法了,
可能回到2002年的时候会是一个非常创新的设计。
事件驱动模型在《Unix Network Programming》里也有详细的阐述,
只是没有提到epoll、kqueue等新的方法,原理都是相通的。

现在,Nginx的最新稳定版本是0.8.54,可以在http://nginx.org/en/download.html下载。
http://nginx.org/的更新历史看,作者非常活跃,每个月起码更新一次。
开发版本已经到了0.9.5。

最后,对于想分析Nginx源码的中国人,http://code.google.com/p/nginxsrp/wiki/NginxCodeReview似乎是个不错的开始。
英文方面,可以看http://nginx.org/en/docs/introduction.html,是Igor写的三篇文章。
美中不足的是,这三篇文章主要都是介绍配置方面信息的,对架构、代码甚少涉及。

Tagged with:
22

分析Nginx源码这个念头曾经出现过,也用GDB配合Source Insight跟踪过两天时间。
之后由于其他事情占据了时间,就搁置了下来,一晃就几个月。

做事过于随性是老毛病了,不过就像许多其他事情,虽明知不妥,却总也戒不掉,改不了。
借着写Nginx模块的惯性和余温,但愿这次可以一口气完成吧。
//Mac OS自带的输入法真不好用,公司们(Google, Tencent, Sogou, Baidu …)大发慈悲,做一个输入法吧

Nginx的代码写得好是出了名的:命名规范、模块化划分、函数简短、适当注释⋯⋯
虽然有如此多的好处,但要对其代码做详细分析,既可俯瞰架构、又能深入细节,却实属艰难。
单单是内存池、回调机制、多重指针等之前几天让我费劲脑汁的技巧,已经让我超出预算。
况且了解细节易,纵观全局难,注定了是一个上下求索的过程。
//这个说法也适用于程序员生涯。

为免自己半途而废,写下以上文字,算是立字为据,也权当之后笔记的前言吧。

Tagged with:
13

by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!

just “import this”:)

Tagged with:
14

升级到Snow Leopard的时候,找到的是dmg文件。
Mac自带的磁盘工具支持将dmg写入到USB stick,并用USB stick来引导安装。

当时就想,是不是iso文件也可以这样做?
今天准备装Ubuntu 10.10的时候,在Ubuntu的安装向导中找到了答案:

  1. Download the desired file
  2. Open the Terminal (in /Applications/Utilities/ or query Terminal in Spotlight)
  3. Convert the .iso file to .img using the convert option of hdiutil (e.g.,hdiutil convert -format UDRW -o ~/path/to/target.img ~/path/to/ubuntu.iso)
  4. Note: OS X tends to put the .dmg ending on the output file automatically.
  5. Run diskutil list to get the current list of devices
  6. Insert your flash media
  7. Run diskutil list again and determine the device node assigned to your flash media (e.g. /dev/disk2)
  8. Run diskutil unmountDisk /dev/diskN (replace N with the disk number from the last command; in the previous example, N would be 2)
  9. Execute sudo dd if=/path/to/downloaded.img of=/dev/rdiskN bs=1m (replace /path/to/downloaded.img with the path where the image file is located; for example, ./ubuntu.img or ./ubuntu.dmg).
  10. Using /dev/rdisk instead of /dev/disk may be faster.
    If you see the error dd: Invalid number '1m', you are using GNU dd. Use the same command but replace bs=1m with bs=1M.
    If you see the error dd: /dev/diskN: Resource busy, make sure the disk is not in use. Start the ‘Disk Utility.app’ and unmount (don’t eject) the drive.
  11. Run diskutil eject/dev/diskN and remove your flash media when the command completes
  12. Restart your Mac and press alt while the Mac is restarting to choose the USB-Stick

从第5步起,也可以直接用“磁盘工具”代替
原文地址:http://www.ubuntu.com/desktop/get-ubuntu/download

另外,上文也提到了在Windows下将iso做成可引导USB stick的方法。用这个小工具应该比UltraISO要方便吧。

Tagged with:
14

三年前,我刚进腾讯,是在Qzone的商城组,职位是后台开发。
顾名思义,商城是卖东西的地方,涉及到的业务有装扮、购买、扣费等逻辑。
当时Team里没有专门的前端工程师,前端的工作都由后台工程师兼任。
从技术的角度看,就是从前端的JS、HTML、CSS,到中间的CGI,都后台的服务器,都有涉及。
其实这是一个挺好的职位,对增加技术的广度很有好处。

刚到Qzone的时候,我的导师Welkin,就对我说:
”现在的代码很烂,但也就这样了,到有人忍受不了的时候,自然会重写的“,而且说了不止一次。
他当时在做套装,可能改得比较苦闷吧。

当时我刚进去没几天,不太理解他的意思,而且也有点不以为然,心想:
”只要自己严谨一点,总不至于写出很烂的代码吧?“
后来我才知道,原来写代码和打篮球一样,也是团体运动,一个人是赢不了球的。

做完一个相对独立的小活动,赚了一百万之后(很夸张),开始真正接触商场的项目。
第一步当然是看已有的代码,当时只是觉得不太容易看懂,也并不算很烂。
到了后来,当我有一次要改购物车的代码时,才体会到Welkin当时的痛苦。

基本上是过程式的JS,存在不少全局变量,嵌套关系过于复杂。
以至于单纯看代码已经很难了解实际的运行流程,必须要用调试器来单步跟踪了。
显然,Welkin还能忍受这种代码,因为他做套装的时候,并没有重写这些代码。
必须承认,当时我也容忍了这些代码,只是修改了部分,以求完成功能。
当然我可以给自己借口:当时业务逻辑和前端技术都不太熟悉,想改也无从下手。
但是总之,我容忍了这种代码的存在。

再后来要对大头贴做改版,再次碰到了这种无从下手的代码。
从代码的风格可以看出,明显经过三个人以上的修改。
这次我把流程整理了一下,但也没有重写。
或者说,一定程度上,我又容忍了。

08年10月,我来到了邮箱,早期的主要工作是对阅读空间的CGI做重构。
经过几轮的重构之后,程序的流程变得比较让人满意,在这个基础上做新功能的速度也有了提升。
但是经过一段时间的开发之后,现在代码里的坏味慢慢开始散发出来。

所以我的结论是,代码也符合热力学定律,自然就处于熵增的状态,必然会慢慢变得腐烂。
一个团队的代码质量,并不决定于你能写出多好的代码,而是决定于你能容忍多烂的代码。

18

还是写点东西吧,不管有什么用,起码没有坏处。
– 写在最前面

在互联网这个快速变化的行业,要跟上每天都可能改变的需求,传统的瀑布开发模式显然不合适。
于是有“敏捷软件开发”这样的新开发模式被应用到互联网的日常开发当中,而这也是在腾讯内常用的模式。

根据《敏捷软件开发宣言》,四个最重要的价值观是:

  • 人和交互重于过程和工具。
  • 可以工作的软件重于求全责备的文档。
  • 客户协作重于合同谈判。
  • 随时应对变化重于循规蹈矩。

由以上的价值观所强调的部分,其实可以归纳出两个要点:人本身,以及人之间直接、快速、有效的沟通

从人的角度考虑,最起码的要求是,需要整个开发过程中的每个角色都可以在其位,谋其事。
至于角色的划分,可能不同公司有不同的方法。在Web方面,根据我的理解,大致可以分为以下几种:

产品经理:

基本上是各个角色中和人打交道成份最高的一个,所以对沟通能力的要求会比较高;另外良好的策划能力也是必须的
负责产品的整体方向,收集用户需求(包括来自用户和老大的),协调各种资源⋯⋯
常用的工具是Word、PPT、各式各样的沟通工具(IM、Email、SMS、BBS、广播⋯⋯)

项目经理:

跟踪项目的开发进度,保证版本的准时交付
负责规划产品的整体开发,划分需求,分配任务⋯⋯,
常用的工具可是各种各样的协作平台(例如TAPD)

UI设计师:

最具艺术家气息的角色
打交道的对象是布局、色彩、字体等等UI相关的元素
用户对网站的第一印象主要源自于UI设计师对产品的设计和感觉
常用的工具是PhotoShop

页面设计师:

将UI设计师的设计图切分为浏览器可以解析的页面
打交道的对象是HTML、CSS
最麻烦之处在于要兼容页面在各种浏览器上的表现,尤以个性独特著称的IE为甚
常用的工具是Editplus、Notepad++等编辑器(我没见过有人用Dream Weaver或者FrontPage),IE Dev Tool、Firebug等调试工具

交互工程师:

处理页面上的动态效果,浏览器和HTTP Server之间的通信,以及浏览器上的业务逻辑
打交道的对象主要是JavaScript(VBScript极其少见)
最麻烦之处在于要兼容脚本在各种浏览器上的表现,尤是以个性独特著称的IE为甚
常用的工具是Aptana等IDE;调试会用Visual Studio脚本调试器,Firebug等,当然也不会禁用alert,虽然比printf更不优雅

前端工程师:

串联浏览器和后台服务间的数据传输,产品逻辑的主要控制者
打交道的对象是PHP、JSP、ASP、CGI等动态程序
这里的前端主要是指后台服务的前端,充当了表现和数据间的桥梁。
对应到MVC模型,属于Controll部分。相应的,前面提到的三个角色属于View
常用的工具是Eclipse、Visual Studio、Source Insight、TextMate等IDE(可能SI和TM不算IDE,因为本身没有编译功能,不过可以定制)

后台工程师:

实现后台服务,为网站的数据存储提供支持,是系统性能、可靠性的主要保障者
打交道对象是OS、API、网络、文件系统、MySQL等
MVC模型里的Model
常用的工具是VIM、Emacs

UI设计师、页面设计师、交互工程师、前端工程师、后台工程师之间的关系,有点类似于网络模型中的各个层次:使用下层提供的服务,并为上层提供服务。
用户可以直接感受到部分,大部分都是UI设计师、页面设计师和交互工程师完成的。
因为关乎用户体验,所以他们的工作需要处理非常多的细节效果,这许多细节的叠加,就构成了用户对网站的感觉,决定了用户是否会喜欢上我们的产品。
而前端工程师和后台工程师的工作很多是用户不能直接看到的,有点类似于海面下的冰山。虽然不能直接看到,但系统的速度和稳定性都依赖于两者的工作。

而产品经理和项目经理基本上和上面的五个角色都会打交道。

在实际的工程中,并不一定每个角色都有一个或多个人担任,往往是一个人身兼数职。例如,在项目的起步阶段,1经理、1设计师和1工程师就可以构架出基本的功能和服务。

看了上面这么多文字,如果让你想办法提升一个团队的产能,你会有什么建议?
在我看来,不外乎两个途径:提升个人能力,降低沟通成本。

先说提升个人能力。这和每个人的基本素质、学习欲望、工作态度等自身因素有关,也受公司的氛围、培训以及行业的状况等外部因素的影响。这些都不是朝夕之间可以改变的,所以如果希望短期看到成效,还是看看沟通方面可以做些什么。(当然,如果有充足的资金,人也不是问题)

关于降低沟通成本,我觉得有几个方法,效果从好到差分别是:

上策:将上述的各个角色都放到一个真实的Team里

这在小团队或者创业团队里比较容易实现,但是当人员日益增加,小组按照职能划分之后,就很难维持了。

中策:成立一个虚拟团队,并让他们坐在一起

如果不能保证组织架构上的整体性,其他保证名义上和空间上的吧。但如果人员来自不同的部门,这一条也很难实现。

下策:定期会议

其实很多无谓会议都是低效的根源,但如果没办法做到以上的两点,唯有牺牲一些个人工作的效率,来提升沟通的效率了。

上面的种种方法,终极目的都是“让每个人自始至终都参与其中”,有了归属感之后,自然就不会把实现产品仅仅当成是自己的工作了,其实这也是QQ邮箱能够做到敏捷的秘诀吧。

Tagged with:
01

原以为在Putty里设置几个宏就行,
结果一个Hardcode的输入框和几个Disable的复选框之外,找不到其他有用的东西。

答案还是在Google里:)
需要在Server上设置一个环境变量,
现在的写法是:


PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007"';

不单Putty,SecureCRT之类的终端应该也适用吧。
可以加到~/.profile,每次登陆自动生效。

Tagged with:
十二 30

第一章

     Xcode需要运行在基于Intel的Leopard之后的Mac OS之上
     Cocoa Touch使用Objective-C 2.0
     编写iPhone应用程序的特别之处
          只有一个正在运行的程序
          只有一个窗口
          访问受限     沙盒
          有限的响应时间     按下Home后5秒内没完成清理,将被强制退出
          有限的屏幕大小     480*320
          有限的系统资源     内存不足时,应用程序会收到通知。如果不能及时释放内存,可能被强制退出
          缺少Cocoa工具     不支持垃圾收集
          新属性     定位、摄像、图片库和加速计
     本书内容
          2 Interface Builder基础
          3 基础交互
          4 基本控件
          5 方向感应
          6 多视图
          7 工具栏
          8 TableView
          9 分层列表
          10 应用程序设置
          11 数据管理     SQLite
          12 绘图     Quartz和OpenGL ES
          13 多点触摸
          14 Core Location
          15 加速计
          16 摄像头和图片库
          17 I18n

第二章
     Project的目录结构,仅为逻辑结构
          Classes     存放大部分代码
          Other Sources     其他源代码
               .pch     预编译的头文件 precompiled header
               main.m     main函数,通常不需修改
          Resources     非代码文件,图标、图像、音频、视频文本
               .xib     Interface Builder用到的信息
               Info.plist     应用程序相关属性列表
               MainWindow.xib     主Interface Builder文件
          Frameworks     框架和库
          Products     编译生成的应用程序
     Interface Builder
          支持.nib(旧)和.xib(新)两种格式,统称nib或nib文件
     nib文件的构成
          File’s Owner     所有nib文件的第一个图标,表示加载nib文件的对象,控制器类是与之同名的nib文件的Owner
          First Responder     用户当前正在与之交互的对象,随用户与界面的交互而变化
          其他图标表示将在nib文件加载时创建的对象实例
     图标
          png     57*57
          放到Resources文件夹中
          在Info.plist中设置
     仿真器
          删除~/Library/Application Support/iPhone Simulator以清空主屏幕图标

第三章
     MVC模型
          M     Objective-C类
          V     Interface Builder
          C     NSObject,更多的是通用控制器类,如UIViewController
     控制器
          控制器类试用一种特殊的实例变量(输出口,outlet)来引用nib中的对象
          输出口可以看成是指向nib中的对象的指针
          可以通过绑定操作方法,设置nib文件的界面对象触发控制类中的特殊方法
     输出口
          IBOutlet     一个没有内容的宏,唯一作用是告诉Interface Builder此实例变量将被连接到nib中的对象
     操作
          IBAction     告诉Interface Builder,此方法是一个操作,且可以被某控件触发
          - (IBAction)doSomething:(id) sender;
     Outlet与Action的声明
          @property (retain, nonatomic) IBOutlet UILabel *statusText;
          retain 对象在内存中驻留
          nonatomic 无须支持多线程?
          myVar = [someObj foo] 等价于 myVar = someObj.foo
          someObj.foo = myVar 等价于 [someObj setFoo:myVar]
     Outlet与Action的实现
          @synthesize statusText
          [statusText release] in dealloc(),照应retain
     应用程序委托
          每个iPhone应用程序有且仅有一个UIApplication实例,负责应用程序的运行循环以及处理各种应用程序级功能
     连接输出口
          Control+拖动,从File‘s Owner到相应的控件对象
     指定操作
          Touch Up Inside
          拖动,从Event到File‘s Owner
          

Tagged with:
preload preload preload

无觅相关文章插件,快速提升流量