Linux VPS CentOS 5 实例图解网站搭建
详细图文解说下linux vps CentOS 5 搭建wordpress网站:
1,从VPS服务商那里获得 IP(购买后服务商分配给你) 、SSH密码(VPS管理面板可以修改)、SSH名(基本都是root) ,确保你的VPS系统为 linux CentOS 5 32bit(也可以是64bit) ,其他系统请绕行。如果不是CentOS,进入VPS管理面板重新做系统;
2,本地电脑 安装 Xshell 4.0 SSH管理 :http://www.chinaz.com/web/2011/1026/216023.shtml ;然后进入 Xshell 4.0 在你的VPS上安装LNMP ,详情点击 :http://www.chinaz.com/web/2011/1026/216027.shtml;安装好后退出页面 Xshell 页面;
3.1,下载 WinSCP SSH客户端 ;安装到你的电脑上;
3.2,登陆 WinSCP SSH 客户端,如图所示:
3.3,在WinSCP下可清晰可见VPS服务器上所有安装的文件,下面是lnmp的常用文件夹说明:
默认网站文件夹 /home/wwwroot/ ,进入这个文件夹,里面就是你的网站所有文件了,里面包括安装lnmp时默认的 phpmyadmin 、ftp;
默认伪静态文件夹 /usr/local/nginx/conf/ ,已经有了Discuz、Wordpress、typecho、emlog等伪静态;
默认绑定的域名文件夹 /usr/local/nginx/conf/vhost/ , 这里是你添加绑定的所有域名地址;
默认MYSQL文件夹 /usr/local/mysql/var/ ,这里就是你所有建立的MYSQL文件了,当然你也可以用你的phpmyadmin 来管理它;
4.1,如果你已经完成了上面所有步骤,现在就来实例图文演示添加网站和管理。
譬如:
绑定的域名 cn.weidao.net
绑定的文件夹为 /home/wwwroot/china/
绑定域名时也添加了伪静态 /usr/local/nginx/conf/wordpress.conf
已经绑定域名列表 /usr/local/nginx/conf/vhost/ 里面有一个文件 cn.weidao.net.conf ,说明cn.weidao.net 已经绑定好了,双击打开确保添加域名时配置正确。
4.2,打开 http://你的IP/phpmyadmin/ 登陆,如图所示 新建一个MYSQL数据库;
4.3,下载最新版本 wordpress 3.2.1 中文版 : http://cn.wordpress.org/wordpress-3.2.1-zh_CN.zip到本地上传至 VPS 域名绑定的文件夹里;
4.3.1,下载好 wordpress3.2.1 后,本地解压下,将 wordpress 文件夹下所有的文件用 ZIP 格式打包为 wordpress.zip ,然后用 WinSCP 上传至 VPS域名绑定的文件夹china里面, 如图所示:
4.3.2,右键上传好的文件,选择“自定义命令” – “输入(E)” 如图所示:
输入口令 unzip wordpress.zip 进行解压文件包;
4.3.3,返回上一层,右键 china 文件夹,选择“自定义命令” – “输入(E)” 如图所示:
输入口令 chown www -R china 批量改变文件为 www 属性,不然网站无法安装,提示属性问题。
5,现在你可以打开你绑定的域名地址,进行安装wordpress了。
6,OK!收工!一个简单的Linux下VPS搭建的wordpress网站已经成功了。
Python 入門語法和類型
Python的设计目标之一是让源代码具备高度的可读性。它设计时尽量使用其它语言经常使用的标点符号和英语单词,让源代码整体看起来很整洁美观。它不像静态语言如C、Pascal那样需要重复书写声明语句,也不像它们的语法那样经常有特殊情况和惊喜。
缩进
Python开发者有意让违反了缩进规则的程序不能通过编译,以此来强制程序员养成良好的编程习惯。并且在Python语言里,缩进而非花括号或者某种关键字,被用于表示语句块的开始和退出。增加缩进表示语句块的开始,而减少缩进则表示语句块的退出。缩进成为了语法的一部分。例如
if
语句:
if age < 21: print("你不能買酒。") print("不過你能買口香糖。") print("這句話處於if語句塊的外面。")
根据PEP的规定,必须使用4个空格来表示每级缩进。使用Tab字符和其它数目的空格虽然都可以编译通过,但不符合编码规范。支持Tab字符和其它数目的空格仅仅是为了兼容很旧的Python程序和某些有问题的编辑器。
语句和控制流
if
语句,当条件成立时执行语句块。经常与else
,elif
(相当于else if
)配合使用。for
语句,遍历列表、字符串、字典、集合等迭代器,依次处理迭代器中的每个元素。while
语句,当条件为真时,循环执行语句块。try
语句。与except
,finally
配合使用处理在程序运行中出现的异常情况。class
语句。用于定义类型。def
语句。用于定义函数和类型的方法。pass
语句。表示此行为空,不执行任何操作。assert
语句。用于程序调试阶段时测试运行条件是否满足。with
语句。Python2.6以后定义的语法,在一个场景中运行语句块。比如,运行语句块前加锁,然后在语句块运行结束后释放它。yield
语句。在迭代器函数内使用,用于返回一个元素。自从Python 2.5版本以后。这个语句变成一个运算符。
表达式
Python的表达式写法与C/C++类似。只是在某些写法有所差别。
- 主要的算术运算符与C/C++类似。
+, -, *, /, //, **, ~, %
分别表示加法或者取正、减法或者取负、乘法、除法、整除、乘方、取补、取模。>>, <<
表示右移和左移。&, |, ^
表示二进制的AND, OR, XOR
运算。>, <, ==, !=, <=, >=
用于比较两个表达式的值,分别表示大于、小于、等于、不等于、小于等于、大于等于。在这些运算符里面,~, |, ^, &, <<, >>
必须应用于整数。 - Python使用
and
,or
,not
表示逻辑运算。 is, is not
用于比较两个变量是否是同一个对象。in, not in
用于判断一个对象是否属于另外一个对象。- Python支持"列表推导式"(list comprehension),比如计算0-9的平方和:
>>> sum(x * x for x in range(10))285
- Python使用
lambda
表示匿名函数。匿名函数体只能是表达式。比如:
>>> add=lambda x, y : x + y>>> add(3,2)5
- Python使用
y if cond else x
表示条件表达式。意思是当cond
为真时,表达式的值为y
,否则表达式的值为x
。相当于C++和Java里的cond?y:x
。 - Python区分列表(list)和元组(tuple)两种类型。list的写法是
[1,2,3]
,而tuple的写法是(1,2,3)
。可以改变list中的元素,而不能改变tuple。在某些情况下,tuple的括号可以省略。tuple对于赋值语句有特殊的处理。因此,可以同时赋值给多个变量,比如:
>>> x, y=1, 2 #同时给x,y赋值,最终结果:x=1, y=2
特别地,可以使用以下这种形式来交换两个变量的值:
>>> x, y=y, x #最终结果:y=1, x=2
- Python使用'(单引号)和"(双引号)来表示字符串。与Perl、Unix Shell语言或者Ruby、Groovy等语言不一样,两种符号作用相同。一般地,如果字符串中出现了双引号,就使用单引号来表示字符串;反之则使用双引号。如果都没有出现,就依个人喜好选择。出现在字符串中的\(反斜杠)被解释为特殊字符,比如
\n
表示换行符。表达式前加r
指示Python不解释字符串中出现的\。这种写法通常用于编写正则表达式或者Windows文件路径。
- Python支持列表切割(list slices),可以取得完整列表的一部分。支持切割操作的类型有
str, bytes, list, tuple
等。它的语法是...[left:right]
或者...[left:right:stride]
。假定nums
变量的值是[1, 3, 5, 7, 8, 13, 20]
,那么下面几个语句为真:
-
nums[2:5] == [5, 7, 8]
从下标为2的元素切割到下标为5的元素,但不包含下标为2的元素。nums[1:] == [3, 5, 7, 8, 13, 20]
切割到最后一个元素。nums[:-3] == [1, 3, 5, 7]
从最开始的元素一直切割到倒数第3个元素。nums[:] == [1, 3, 5, 7, 8, 13, 20]
返回所有元素。改变新的列表不会影响到nums。nums[1:5:2] == [3, 7]
函数
Python的函数支持递归、默认参数值、可变参数,但不支持函数重载。为了增强代码的可读性,可以在函数后书写”文档字符串“(Documentation Strings,或者简称docstrings),用于解释函数的作用、参数的类型与意义、返回值类型与取值范围等。可以使用内置函数help()
打印出函数的使用帮助。比如:
1 >>> def randint(a, b): 2 ... "Return random integer in range [a, b], including both end points." 3 ... 4 >>> help(randint) 5 Help on function randint in module __main__: 6 7 randint(a, b) 8 Return random integer in range [a, b], including both end points.
对象的方法
对象的方法是指绑定到对象的函数。调用对象方法的语法是instance.method(arguments)
。它等价于调用Class.method(instance, arguments)
。当定义对象方法时,必须显式地定义第一个参数为self
,用于访问对象的内部数据。self
相当于C++, Java里面的this
变量。比如:
class Fish: def eat(self, food): if food is not None: self.hungry=False #构造Fish的实例: f=Fish() #以下两种调用形式是等价的: Fish.eat(f, "earthworm") f.eat("earthworm")
Python认识一些以”__“开始并以"__"结束的特殊方法名,它们用于实现运算符重载和实现多种特殊功能。
类型
Python采用动态类型系统。在编译的时候,Python不会检查对象是否拥有被调用的方法或者属性,而是直至运行时,才做出检查。所以操作对象时可能会抛出异常。不过,虽然Python采用动态类型系统,它同时也是强类型的。Python禁止没有明确定义的操作,比如数字加字符串。
与其它面向对象语言一样,Python允许程序员定义类型。构造一个对象只需要像函数一样调用类型即可,比如,对于前面定义的Fish
类型,使用Fish()
。类型本身也是特殊类型type
的对象(type
类型本身也是type
对象),这种特殊的设计允许对类型进行反射编程。
Python内置丰富的数据类型。与Java、C++相比,这些数据类型有效地减少代码的长度。下面这个列表简要地描述了Python内置数据类型(适用于Python 3.x):
类型 | 描述 | 例子 |
---|---|---|
str | 一个由字符组成的不可更改的有串行。在Python 3.x里,字符串由Unicode字符组成。 | 'Wikipedia' "Wikipedia" """Spanning multiple lines""" |
bytes | 一个由字节组成的不可更改的有串行。 | b'Some ASCII' b"Some ASCII" |
list | 可以包含多种类型的可改变的有串行 | [4.0, 'string', True] |
tuple | 可以包含多种类型的不可改变的有串行 | (4.0, 'string', True) |
set, frozenset | 与数学中集合的概念类似。无序的、每个元素唯一。 | {4.0, 'string', True} frozenset([4.0, 'string', True]) |
dict | 一个可改变的由键值对组成的无串行。 | {'key1': 1.0, 3: False} |
int | 精度不限的整数 | 42 |
float | 浮点数。精度与系统相关。 | 3.1415927 |
complex | 复数 | 3+2.7j |
bool | 逻辑值。只有两个值:真、假 | True False |
除了各种数据类型,Python语言还用类型来表示函数、模块、类型本身、对象的方法、编译后的Python代码、运行时信息等等。因此,Python具备很强的动态性。
数学运算
Python使用与C、Java类似的运算符,支持整数与浮点数的数学运算。同时还支持复数运算与无穷位数(实际受限于计算机的能力)的整数运算。除了求绝对值函数abs()
外,大多数数学函数处于math
和cmath
模块内。前者用于实数运算,而后者用于复数运算。使用时需要先导入它们,比如:
>>> import math >>> print(math.sin(math.pi/2)) 1.0
fractions
模块用于支持分数运算;decimal
模块用于支持高精度的浮点数运算。
Python定义求余运行a % b
的值处于开区间[0, b)
内,如果b
是负数,开区间变为(b, 0]
。这是一个很常见的定义方式。不过其实它依赖于整除的定义。为了让方程式:b * (a // b) + a % b = a
恒真,整除运行需要向负无穷小方向取值。比如7 // 3
的结果是2
,而(-7) // 3
的结果却是-3
。这个算法与其它很多编程语言不一样,需要注意,它们的整除运算会向0的方向取值。
Python允许像数学的常用写法那样连着写两个比较运行符。比如a < b < c
与a < b and b < c
等价。C++的结果与Python不一样,首先它会先计算a < b
,根据两者的大小获得0或者1两个值之一,然后再与c进行比较。
PHP的简单正则判断字符串类型
前两天写PHP代码的时候遇到要判断一个变量是否为数字,所以就把相关的文章简单的摘抄了过来:
php 正则验证字符串是否为数字
方法一:
php中利用正则表达式验证字符串是否为数字一件非常容易的事情,最主要的是如何写好正则表达式以及掌握正则表达式的写法,在此利用正则表达式的方式来列举一下判断数字的方法。
<?
if($str){
if(eregi("^[0-9]+$",$str)){
$str=(int)$str;
}else{
echo "获取到的数据不是有效的数字类型,操作将停止!";
exit();
}
}else{
echo "需要验证的数据为空,操作停止!";
exit();
}
?>
方法二:
建议大家对关键的参数必须做过滤。
如数字正则过滤
if(preg_match("/^\d*$/",$fgid)) {echo('是数字');}else{echo('不是数字');}
或者用函数
if(is_numeric($fgid)) {echo('是数字');}else{ echo('不是数字');}
这两种方法的区别是
附一些常用的正则运算:
验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0)
验证非正整数(负整数 + 0)
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$
验证用户密码:^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&‘,;=?$\” 等字符:[^%&‘,;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5],{0,}$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\(\d{3,4}\)|\d{3,4}-)?\d{7,8}$:–正确格式为:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数
非正浮点数(负浮点数 + 0) ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数
浮点数
腾讯TNT解码1-209期
搜狐回购阿里所持搜狗股份_邵珠庆_shaozhuqing.com
雷军大战周鸿祎_邵珠庆_shaozhuqing.com
中国概念股泡沫初破_邵珠庆_shaozhuqing.com
腾讯暴雪合作启示_邵珠庆_shaozhuqing.com
iPad mini要打谁的7寸?_邵珠庆_shaozhuqing.com
Twitter十字路口_邵珠庆_shaozhuqing.com
HTC高端策略显“畸形”_邵珠庆_shaozhuqing.com
广电视听新政解读_邵珠庆_shaozhuqing.com
优酷土豆并购背后_邵珠庆_shaozhuqing.com
分类信息网中国学徒:团购梦碎_邵珠庆_shaozhuqing.com
揭秘刘强东阎焱旧日恩怨_邵珠庆_shaozhuqing.com
Digg卖身入土_邵珠庆_shaozhuqing.com
《名利场》:微软“失落的十年”_邵珠庆_shaozhuqing.com
还原阿里腐败案主角阎利珉_邵珠庆_shaozhuqing.com
当当跌出电商第一阵营_邵珠庆_shaozhuqing.com
离开诺基亚:MeeGo悲情重生_邵珠庆_shaozhuqing.com
新东方VIE调整风暴_邵珠庆_shaozhuqing.com
陈一舟再度转身_邵珠庆_shaozhuqing.com
苹果热在华退烧_邵珠庆_shaozhuqing.com
Facebook被低估?变现能力受质疑_邵珠庆_shaozhuqing.com
三月之痒:华为与360合作现裂痕_邵珠庆_shaozhuqing.com
国内游戏机市场年内或开放_邵珠庆_shaozhuqing.com
电子书阅读器退烧 当当抄kindle_邵珠庆_shaozhuqing.com
宏碁王振堂困局:奥运营销受挫_邵珠庆_shaozhuqing.com
智能机中国厮杀:洋手机现颓势_邵珠庆_shaozhuqing.com
Zynga灾难上演:积重难返?_邵珠庆_shaozhuqing.com
互联网手机争夺战:销售遇冷_邵珠庆_shaozhuqing.com
携程衰退论蔓延_邵珠庆_shaozhuqing.com
海外移动互联企业图谋中国_邵珠庆_shaozhuqing.com
国内手游进入爆发前夜!_邵珠庆_shaozhuqing.com
奢侈品电商:货源成致命问题_邵珠庆_shaozhuqing.com
Facebook手机不是镜花水月_邵珠庆_shaozhuqing.com
苹果快车逼近十字路口_邵珠庆_shaozhuqing.com
诺基亚中国变局:渠道模式调整_邵珠庆_shaozhuqing.com
落寞盛大:陈天桥只是战略家_邵珠庆_shaozhuqing.com
天猫流量大 京东品质优_邵珠庆_shaozhuqing.com
少年知乎烦恼:内遇困外遇敌_邵珠庆_shaozhuqing.com
电商物流互通之路:物流跟错觉走_邵珠庆_shaozhuqing.com
百思买衰败:已沦为线下体验店_邵珠庆_shaozhuqing.com
第一代手机厂商波导放贷科健拍卖_邵珠庆_shaozhuqing.com
孵化器模式遇困 创新工场转型_邵珠庆_shaozhuqing.com
分众私有化 或引发中概股退市潮_邵珠庆_shaozhuqing.com
京东国美苏宁三国大战_邵珠庆_shaozhuqing.com
重审京东苏宁国美价格战_邵珠庆_shaozhuqing.com
摩托罗拉移动陷裁员风暴_邵珠庆_shaozhuqing.com
电商淘汰战复盘:估值体系崩溃_邵珠庆_shaozhuqing.com
《纽约时报》数字脱困记_邵珠庆_shaozhuqing.com
开发者反思诺基亚衰退_邵珠庆_shaozhuqing.com
优酷土豆版权与广告整合细节曝光_邵珠庆_shaozhuqing.com
360搜索蝴蝶效应:与搜狗必战_邵珠庆_shaozhuqing.com
电商公司升级迫在眉睫_邵珠庆_shaozhuqing.com
360搜索进攻路线猜测_邵珠庆_shaozhuqing.com
优酷土豆并购异常交易遭调查_邵珠庆_shaozhuqing.com
百度360攻防战升级_邵珠庆_shaozhuqing.com
百度战360后招猜想_邵珠庆_shaozhuqing.com
360通用搜索是借尸还魂_邵珠庆_shaozhuqing.com
摩托罗拉十年分拆变卖_邵珠庆_shaozhuqing.com
硅谷生物科技梦_邵珠庆_shaozhuqing.com
58同城革命:两条战线并行_邵珠庆_shaozhuqing.com
百度移动新战略:云与端结合_邵珠庆_shaozhuqing.com
3B大战会让百度改变吗?_邵珠庆_shaozhuqing.com
围剿苹果!手机巨头9月开火_邵珠庆_shaozhuqing.com
凡客危机未解除:乱象丛生_邵珠庆_shaozhuqing.com
解读联想PC并购图谱_邵珠庆_shaozhuqing.com
告别XP时代:微软孤注一掷_邵珠庆_shaozhuqing.com
诺基亚押宝WP8赌未来_邵珠庆_shaozhuqing.com
iPhone 5特性不足 苹果变平庸_邵珠庆_shaozhuqing.com
阿里云自主研发炒作惹怒谷歌_邵珠庆_shaozhuqing.com
中移动引入iPhone破冰_邵珠庆_shaozhuqing.com
移动支付十年 依然概念大于实质_邵珠庆_shaozhuqing.com
阿里云OS迷雾:急删Google字样_邵珠庆_shaozhuqing.com
视频网站自制内容生存调查_邵珠庆_shaozhuqing.com
电商导购网站遭淘宝打压_邵珠庆_shaozhuqing.com
土豆患并购综合症_邵珠庆_shaozhuqing.com
阿里云幕后:独立OS到兼容模式_邵珠庆_shaozhuqing.com
三星被判侵权苹果:输不起的战争_邵珠庆_shaozhuqing.com
Zynga为何走向困境:高层心态急_邵珠庆_shaozhuqing.com
谷歌音乐关闭幕后_邵珠庆_shaozhuqing.com
红孩子折戟多元化 传苏宁收购_邵珠庆_shaozhuqing.com
红孩子幕后隐秘交易_邵珠庆_shaozhuqing.com
iPhone5接口芯片已被破解_邵珠庆_shaozhuqing.com
独立位置服务平台面临困境_邵珠庆_shaozhuqing.com
陈年:自我膨胀致凡客失控_邵珠庆_shaozhuqing.com
飞机上能不能开手机_邵珠庆_shaozhuqing.com
华为海外布局 十年内融入美国_邵珠庆_shaozhuqing.com
谷歌市值超微软沃尔玛_邵珠庆_shaozhuqing.com
默多克向谷歌低头_邵珠庆_shaozhuqing.com
Instagram大爆炸_邵珠庆_shaozhuqing.com
连线FINRA:发过优酷土豆调查函_邵珠庆_shaozhuqing.com
Kickstarter:从梦想到生意_邵珠庆_shaozhuqing.com
二维码悄悄野蛮成长 向O2O探路_邵珠庆_shaozhuqing.com
揭秘网易手机半年流产内幕_邵珠庆_shaozhuqing.com
破解O2O:业内焦躁痛苦_邵珠庆_shaozhuqing.com
莫言获诺贝尔奖_邵珠庆_shaozhuqing.com
三星成功秘诀_邵珠庆_shaozhuqing.com
社交大数据掘金之路_邵珠庆_shaozhuqing.com
中兴通讯巨亏幕后_邵珠庆_shaozhuqing.com
YY野蛮生长_邵珠庆_shaozhuqing.com
中电信基地独立运作幕后_邵珠庆_shaozhuqing.com
苹果地图使命探秘_邵珠庆_shaozhuqing.com
苹果富士康联盟面临危机_邵珠庆_shaozhuqing.com
专访盛大文学CEO侯小强_邵珠庆_shaozhuqing.com
3D打印从梦想到现实_邵珠庆_shaozhuqing.com
音乐网站酝酿下载收费_邵珠庆_shaozhuqing.com
盛大果壳生变_邵珠庆_shaozhuqing.com
平板战争2.0_邵珠庆_shaozhuqing.com
亚马逊VS沃尔玛_邵珠庆_shaozhuqing.com
短信没落_邵珠庆_shaozhuqing.com
谷歌小绿人遭遇微软WP8赌徒_邵珠庆_shaozhuqing.com
亚马逊中国7年之痒_邵珠庆_shaozhuqing.com
邹胜龙还原迅雷真相_邵珠庆_shaozhuqing.com
团购乱局下众生相_邵珠庆_shaozhuqing.com
eBay卷土重来_邵珠庆_shaozhuqing.com
百度收购爱奇艺股份_邵珠庆_shaozhuqing.com
华为美国梦_邵珠庆_shaozhuqing.com
YY音乐产业链调查_邵珠庆_shaozhuqing.com
天猫双11大促遇反弹_邵珠庆_shaozhuqing.com
MSN坠落记_邵珠庆_shaozhuqing.com
运营商转型加速_邵珠庆_shaozhuqing.com
电商平台乱战_邵珠庆_shaozhuqing.com
美国新能源困局_邵珠庆_shaozhuqing.com
京东阻击天猫枪打出头鸟_邵珠庆_shaozhuqing.com
双11大战推动生态转移线上_邵珠庆_shaozhuqing.com
盛大转型投资集团:游戏渐受冷落_邵珠庆_shaozhuqing.com
雷军:粉丝批评让人痛心_邵珠庆_shaozhuqing.com
轻博客热闹过后_邵珠庆_shaozhuqing.com
客厅娱乐归来_邵珠庆_shaozhuqing.com
移动时代的搜索危机_邵珠庆_shaozhuqing.com
圣诞大战斗争图谱_邵珠庆_shaozhuqing.com
阿里巴巴入股新浪微博或成定局_邵珠庆_shaozhuqing.com
欧德宁时代落幕_邵珠庆_shaozhuqing.com
惠普的并购丑闻 谁该买单?_邵珠庆_shaozhuqing.com
新浪微博业务调整_邵珠庆_shaozhuqing.com
争议窝窝团徐茂栋_邵珠庆_shaozhuqing.com
小米盒子监管疑云_邵珠庆_shaozhuqing.com
IT“茫一代”转型记:创业维艰_邵珠庆_shaozhuqing.com
科技巨头生态系统战_邵珠庆_shaozhuqing.com
龚宇:视频行业烧钱还要两年_邵珠庆_shaozhuqing.com
解读人人:游戏私有化“太麻烦”_邵珠庆_shaozhuqing.com
魅族复仇之战:目标直指小米_邵珠庆_shaozhuqing.com
手机大会战:诺基亚对决苹果三星_邵珠庆_shaozhuqing.com
中移动WLAN烦恼:内斗4G_邵珠庆_shaozhuqing.com
联通电信iPhone5将12月14日上市_邵珠庆_shaozhuqing.com
任天堂沉浮录_邵珠庆_shaozhuqing.com
京东快速布局讲中国亚马逊故事_邵珠庆_shaozhuqing.com
中移动谋划九大基地公司化运作_邵珠庆_shaozhuqing.com
好耶释放冲击IPO信号_邵珠庆_shaozhuqing.com
中美审计分歧 中概股危机空前_邵珠庆_shaozhuqing.com
1号店狂飙背后_邵珠庆_shaozhuqing.com
库克应该如何重新打造苹果电视_邵珠庆_shaozhuqing.com
9158和YY效应_邵珠庆_shaozhuqing.com
苹果中国渠道调整_邵珠庆_shaozhuqing.com
网秦林宇回应:国内调研数据混乱_邵珠庆_shaozhuqing.com
SNS电商试验梦碎:淘宝投入减弱_邵珠庆_shaozhuqing.com
iPhone5国内开售 联通电信对阵_邵珠庆_shaozhuqing.com
国内电商仿美国Decide仍是传说?_邵珠庆_shaozhuqing.com
媒体业颠覆 老牌媒体如何防守_邵珠庆_shaozhuqing.com
乐淘转型阵痛:供应链换血裁_邵珠庆_shaozhuqing.com
新浪微博联合云云布局移动搜索_邵珠庆_shaozhuqing.com
新浪变局猜想:曹国伟仍掌大局_邵珠庆_shaozhuqing.com
魅族求变应对小米竞争_邵珠庆_shaozhuqing.com
RIM错失移动互联网_邵珠庆_shaozhuqing.com
新浪移动互联布局遭质疑_邵珠庆_shaozhuqing.com
垂直B2C生死时刻_邵珠庆_shaozhuqing.com
O2O冷思考_邵珠庆_shaozhuqing.com
啪啪:许朝军的下一个路口_邵珠庆_shaozhuqing.com
京东高层变动幕后:技术偏保守_邵珠庆_shaozhuqing.com
新浪人事调整细节曝光_邵珠庆_shaozhuqing.com
Rovio前世今生_邵珠庆_shaozhuqing.com
陌陌:需避走51失败之路_邵珠庆_shaozhuqing.com
别了!上网本!_邵珠庆_shaozhuqing.com
互联网广告新三国大战_邵珠庆_shaozhuqing.com
微软危局_邵珠庆_shaozhuqing.com
传统媒体突围新媒体_邵珠庆_shaozhuqing.com
万达电商业务慢行_邵珠庆_shaozhuqing.com
联想保卫进攻战_邵珠庆_shaozhuqing.com
周鸿祎“温故”3721_邵珠庆_shaozhuqing.com
赶集“出逃者”狙击老东家_邵珠庆_shaozhuqing.com
中移动试水互联网电视业务_邵珠庆_shaozhuqing.com
揭秘黄宏生隐性回归_邵珠庆_shaozhuqing.com
网络垄断新势力涌现_邵珠庆_shaozhuqing.com
诺基亚2013期待重生_邵珠庆_shaozhuqing.com
苏宁重组红孩子_邵珠庆_shaozhuqing.com
百度投资金山大战360_邵珠庆_shaozhuqing.com
马云卸任阿里巴巴CEO_邵珠庆_shaozhuqing.com
三四线移动互联网用户价值凸显_邵珠庆_shaozhuqing.com
苏宁易购三大争议_邵珠庆_shaozhuqing.com
2013将成平板手机年_邵珠庆_shaozhuqing.com
FB移动为先战略见成效_邵珠庆_shaozhuqing.com
浏览器抢票软件火热背后_邵珠庆_shaozhuqing.com
谷歌归来?释放重返中国信号_邵珠庆_shaozhuqing.com
独家专访科技预言家安德森_邵珠庆_shaozhuqing.com
苹果利润增长神话终结_邵珠庆_shaozhuqing.com
塞班之死:曾经辉煌成绝唱_邵珠庆_shaozhuqing.com
Twitter掘金移动终端_邵珠庆_shaozhuqing.com
Facebook图谱搜索争议_邵珠庆_shaozhuqing.com
91无线带“原罪”启动上市_邵珠庆_shaozhuqing.com
国美变局:黄光裕控盘启动转型_邵珠庆_shaozhuqing.com
苹果建中国研发中心传闻诞生记_邵珠庆_shaozhuqing.com
新浪微博商业化争议_邵珠庆_shaozhuqing.com
携程大变革前夜_邵珠庆_shaozhuqing.com
唱片已死音乐永生_邵珠庆_shaozhuqing.com
视频免费时代渐行渐远_邵珠庆_shaozhuqing.com
中移动开启4G试商用_邵珠庆_shaozhuqing.com
“酷讯派”创业记_邵珠庆_shaozhuqing.com
“酷讯派”创业记 唱吧、食神摇摇这些热门应用是如何诞生的
“当个拳击手,要不然就根本不要到场。”
这是一群声名并不算太显赫的连续创业者。他们曾经试图开创大场面,却经历了惨痛的教训,不少人随后也在创业路上几度蹉跎。但如同《铁甲钢拳》里被人遗弃却最终闪耀全场的小个子机器人,他们并不是生来的陪练者,移动互联网就是他们重新迸发能量的舞台。
陈华和吴世春曾经是一对创业搭档,7年前这两人联合创办了酷讯,以“生活搜索”概念闪亮一时,但又在公司陷入低谷时双双出局。几经换道,他们先后进入移动互联网,前者做了现在火爆的手机K歌应用“唱吧”,后者则成为美食搜索应用“食神摇摇”的创办者。
出身酷讯的创业者并非只有陈吴二人,还有一批在酷讯动荡期离开的产品和技术精英。相比国内赫赫有名的“谷歌创业帮”,抑或颇受关注的网易系创业者,“酷讯派”略显低调,但这群曾在一起战斗过的人却在经历了不同挫折之后集体选择了移动互联网作为新的战场。
张一鸣,原酷讯技术委员会主席,他离开酷讯后做了房产搜索网站99房(合并原酷讯房产),但后因政策变化无法继续为继,他转而创办了字节跳动公司,专注做社交数据挖掘类移动应用,如已拥有750万活跃用户的个性阅读应用《今日头条》。
曾廷坤,曾经在酷讯做技术开发。农场游戏最火的时候他离开酷讯,和他人联合成立了游戏公司玩蟹科技,任CTO。这家公司去年推出的手机游戏《大掌门》,目前是苹果应用商店最畅销的游戏之一,月收入超过2000万人民币。
周青松,原酷讯房产搜索产品经理;严峻,原酷讯高级工程师。他们曾经从酷讯过渡到99房工作,去年则一起创办了517旅行网,最近推出了手机应用“旅行记”。
不完全统计,2008-2009年间先后出走的前酷讯员工近一两年已经创办了十几家公司。尽管大多数仍在大众视线之外,但上述几个集中爆发的明星应用产品,却已经开始让人关注起这个以早期酷讯工作经历为情感纽带的创业群体。
一群失意于互联网垂直搜索的创业者,如今集体在移动互联网上焕发青春。他们从过去数年的跌宕起伏中吸取了哪些教训?
出酷讯记
陈吴时代的酷讯完美演绎了一家“热钱宠儿”的起落曲线,这家曾声名鹊起的创业公司以火车票搜索起家,拥有梦幻开局:一年时间就融到了过千万美元资金,并试图在生活搜索领域开创大场面。但不过三年,美妙幻梦即遭遇现实挫折,找不到商业模式,资金耗尽,裁员,2008年中,酷讯宣布放弃原定路线转型在线旅游,陈华和吴世春先后黯然离职。
离开酷讯之后,他们一开始都没有能摆脱搜索心结和路径依赖。陈华去了阿里巴巴继续做搜索研发,之后又跳出来继续创业,他先是基于搜索技术做了电商导购促销网站最淘,没过几个月就失败了。吴世春也折腾了一段时间后创立乐呵互动,最初产品形态有点像原来的酷讯的餐饮搜索,但又做成了一个SNS社区,做的也并不顺利。直到陈华做了唱吧,吴世春改做食神摇摇,才开始慢慢火了。
其他“酷讯派”创业者也多来搜索或酷讯情结。张一鸣做的阅读应用《今日头条》,与信息订阅派的路径相左,核心是信息聚合和数据挖掘。“他做的产品还是用搜索引擎的技术,跟原来酷讯(的思路)是一样的。”在陈华看来,张一鸣是“酷讯派”中最专注搜索的人。即使是周青松和严峻,他们创办的517旅游网看似和搜索无关,实际上也从陈华当年在酷讯时立项的旅游社区“一起玩”中萌发了灵感。
但他们已经不可能再走与酷讯相似的道路。这是个移动互联网的时代,也是一个全新的时代。
“互联网已经没有太大的机会了,在互联网上再想建立一个新的品牌非常困难。不是个人能力的问题,跟能力已经没有关系了。”
陈华对腾讯科技说。
唱吧2012年5月31上线,数月间用户超过千万。在陈华看来,移动互联网是一片空白,没有东西是已经确定的,每一个应用都有生存的价值空间,只要切到一部分用户,那部分就会有价值。
曾廷坤之所以选择手机游戏创业,也是出于同样的原因。现在页游和端游的格局已经很稳定,新加入者面临的门槛会很高,而且推广成本不菲,相较之下,手机游戏刚刚开始,充满了机会。
但真正要做成一件事并不容易。曾廷坤创业路上过了三四年苦日子,用吴世春的话说是“憋大招”,直到去年推出《大掌门》。公开的数字显示,在去年12月苹果App Store中国区收入榜上,《大掌门》以423万美元的收入排名第二,这在国内手机游戏产品中可谓首屈一指。
酷讯的基因
每个公司都有自己的基因。酷讯系创业的人基本都是清一色的技术人员,最初是工程师,后转型公司的掌舵人。
这与酷讯创立时的状态有关。2005年底,陈华跟吴世春创立酷讯,从一开始这就是一家技术型、产品型的公司。陈华当时不到30岁,招的很多人都是技术很强、有想法、有激情的同龄人,这种工程师文化贯穿在酷讯早期的创业氛围中。而且,酷讯当时采用事业部独立核算,每个团队都要考虑怎么做品牌、产品、市场和开发,团队成员经常一起分析和讨论,而不是像大公司那样角色分明。
“那个时候其实他们已经在积累独立创业的经验。”陈华指出。毕业即进入酷讯工作的曾廷坤回忆,他当时在空闲时间也会考虑自己未来要做的事情,打算等时机成熟自己单独创业。
这种共同作战的经历形成了“酷讯派”的特殊感情,也让他们在行事风格中非常一致。
比如,唱吧团队和食神摇摇的推广模式如出一辙,食神摇摇比唱吧早半年进行推广,后来唱吧也参考其经验进行推广,微博营销公司甚至都是同一家公司。后来,张一鸣也找这家公司进行推广。陈华做唱吧,从酷讯挖了一个人,现在是唱吧的市场部总监。吴世春那里也有两三个酷讯的人,其中之一原来负责酷讯市场,张一鸣团队中负责市场的人也是出自酷讯市场部。
“我们是一条路数,所有的营销方式、营销话语很像。”陈华说。甚至在图标设计上,“酷讯派”做的几个应用也非常相像,食神摇摇占了“吃”字,唱吧占了“唱”字。旅行记占了“旅”字。
吴世春提倡”酷讯派“的创业者多相互分享一些经验。他常挂在嘴边的话是,创业就像消防队天天都面临不一样的火情,只要你经历过这些事情的话,别人再经历过的话就可以给他一些意见,可以少走一些弯路。
这种交流常常能开拓思路。前不久,陈华请曾廷坤到唱吧做讲座。“不是我要做游戏,我想知道我唱吧手机上的产品,能不能参考游戏上的思路,使得我更好赚钱。”陈华说。
经验和教训
陈华和吴世春都是连环创业者,现在产品红了,背后各有一把辛酸泪,也有很多经验以及教训。
“很大的经验就是一个公司不能有那么多的方向。”陈华说,“尤其是一个公司很小的时候,玩事业部就是浪费精力。”吴世春也认为,选准方向是最重要的。小公司创业,肯定要做一些相对比较垂直的,在合适的时间做合适的方向。
“不要梦想着一口吃个胖子。非得去做一个淘宝出来,或者非得做一个QQ出来。这个梦想很大,但是你的资源不支持这种梦想。”吴世春说。
“酷讯派”创业者很强调团队作战。吴世春认为,缺少什么,就要找到匹配的合作方,一起来成立核心创始团队。
陈华以自己现身说法。他当时选择做唱吧是个很大的的冒险,一个唱片公司的人不认识,一个明星不认识,公司里面唱歌唱得好的都没有。但优势是团队,“我们最后发现,这个团队的执行力,技术团队很强,产品团队很强,市场团队很强,三个东西结合在一起,在这个市场上一打,别人连影子都不见了。”
对于做过多次天使投资的吴世春而言,他强调管理好公司的发展节奏也很重要。
他认为,快速扩展对公司不利。怎么管理预期,比如说对于行业的波动的把握,每两三年出现一次波峰波谷,融资环境也在极寒与极热之间转化。怎么能够在极热的时候融到钱,在极寒的时候积蓄一点,这是很重要的。
更加技术宅的曾廷坤似乎无法像陈、吴两位一样讲出创业的大道理。“我自己没想那么多,只是希望给这个团队带来一些成就感。坚持做就行了。”谈及自己的创业时他说。
曾廷坤的愿望很朴素且真诚,他说了最重要的:坚持。
-
疑问:
“酷讯派”有谁?
-
解读:
酷讯联合创始人陈华和吴世春;原酷讯技术委员会主席张一鸣;原酷讯工程师曾廷坤;原酷讯房产搜索产品经理周青松;原酷讯高级工程师严峻。
-
疑问:
他们创业做了啥?
-
解读:
《唱吧》、《今日头条》、《食神摇摇》、《大掌门》等。
-
疑问:
酷讯有啥基因?
-
解读:
这与酷讯创立时的状态有关。2005年底,陈华跟吴世春创立酷讯,从一开始这就是一家技术型、产品型的公司。陈华当时不到30岁岁,招的很多人都是技术很强、有想法、有激情的同龄人,这种工程师文化贯穿在酷讯早期的创业氛围中。而且,酷讯当时采用事业部独立核算,每个团队都要考虑怎么做品牌、产品、市场和开发,团队成员经常一起分析和讨论,而不是像大公司那样角色分明。
- TMT解码:系腾讯科技频道鼎力打造深度报道栏目,力求过滤信息干扰,还原科技事件和趋势背后的本源力量。
- 我们坚持:
- 深度:挖掘事件真相,梳理产业大势,探索实践真知;
- 独家:倾力提供首次进入公众领域的热门科技新闻;
- 独到:反传统智慧,不人云亦云;化繁为简,走在曲线前面;
- 权威:小心求证,谨慎思辨;去伪存真,一锤定音。
- 责任编辑:黄顺芳
- 设计制作:于春慧 杜连强
《Head First 设计模式》代码之PHP版
《Head First 设计模式》是本不错的讲解设计模式的书,不像F4写的那么枯燥,应该算是比较容易理解的好书。书中的例子都比较浅显易懂,不过由于是外国佬写的,所以例子的习惯不是很附合中国特色,可能偶尔看起来有些别扭,还有语言习惯也不是中国风。当然看过这本书之后,你才能深刻理解设计模式到底能为你解决哪些题,不能为你解决哪些问题(比如不能代替你的编码)。
策略模式
- <?php
- /**
- * 策略模式
- * 定义了算法族,分别封装起来,让它们之间可以互相替换,
- * 此模式让算法的变化独立于使用算法的客户。
- */
- //飞行行为接口
- interface FlyBehavior {
- public function fly();
- }
- //呱呱叫行为接口
- interface QuackBehavior {
- public function quack();
- }
- //翅膀飞行
- class FlyWithWings implements FlyBehavior {
- public function fly() {
- echo "I'm flying!!/n";
- }
- }
- //不会飞
- class FlyNoWay implements FlyBehavior {
- public function fly() {
- echo "I can't fly!/n";
- }
- }
- class FlyRocketPowered implements FlyBehavior {
- public function fly() {
- echo "I'm flying with a rocket!/n";
- }
- }
- class Qquack implements QuackBehavior {
- public function quack() {
- echo "Quack/n";
- }
- }
- class Squeak implements QuackBehavior {
- public function quack() {
- echo "Squeak/n";
- }
- }
- class MuteQuack implements QuackBehavior {
- public function quack() {
- echo "<< Silence >>/n";
- }
- }
- abstract class Duck {
- protected $quack_obj;
- protected $fly_obj;
- public abstract function display();
- public function performQuack() {
- $this->quack_obj->quack();
- }
- public function performFly() {
- $this->fly_obj->fly();
- }
- public function swim() {
- echo "All ducks float, even decoys!/n";
- }
- public function setFlyBehavior(FlyBehavior $fb) {
- $this->fly_obj = $fb;
- }
- public function setQuackBehavior(QuackBehavior $qb) {
- $this->quack_obj = $qb;
- }
- }
- class ModelDuck extends Duck {
- public function __construct() {
- $this->fly_obj = new FlyNoWay();
- $this->quack_obj = new MuteQuack();
- }
- public function display() {
- echo "I'm a model duck!/n";
- }
- }
- $model = new ModelDuck();
- $model->performFly();
- $model->performQuack();
- //提供新的能力
- $model->setFlyBehavior(new FlyRocketPowered());
- $model->setQuackBehavior(new Squeak());
- $model->performFly();
- $model->performQuack();
- ?>
单件模式
- <?php
- /**
- * 单件模式
- * 确保一个类只有一个实例,并提供一个全局访问点。
- */
- class MyClass {
- private static $uniqueInstance;
- private function __construct() {
- }
- public static function getInstance() {
- if (self::$uniqueInstance == null) {
- self::$uniqueInstance = new MyClass();
- }
- return self::$uniqueInstance;
- }
- }
- $myClass = MyClass::getInstance();
- var_dump($myClass);
- $myClass = MyClass::getInstance();
- var_dump($myClass);
- ?>
工厂方法模式
- <?php
- abstract class PizzaStore {
- public function orderPizza($type) {
- $pizza = $this->createPizza($type);
- $pizza->prepare();
- $pizza->bake();
- $pizza->cut();
- $pizza->box();
- return $pizza;
- }
- public abstract function createPizza($type);
- }
- class NYPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new NYStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new NYStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new NYStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new NYStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- class ChicagoPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new ChicagoStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new ChicagoStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new ChicagoStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new ChicagoStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- abstract class Pizza {
- public $name;
- public $dough;
- public $sauce;
- public $toppings = array();
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- echo "Yossing dough.../n";
- echo "Adding sauce.../n";
- echo "Adding toppings: /n";
- for ($i = 0; $i < count($this->toppings); $i++) {
- echo " " . $this->toppings[$i] . "/n";
- }
- }
- public function bake() {
- echo "Bake for 25 minutes at 350/n";
- }
- public function cut() {
- echo "Cutting the pizza into diagonal slices/n";
- }
- public function box() {
- echo "Place pizza in official PizzaStore box/n";
- }
- public function getName() {
- return $this->name;
- }
- }
- class NYStyleCheesePizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and cheese Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano Cheese";
- }
- }
- class NYStyleVeggiePizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and veggie Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano veggie";
- }
- }
- class NYStyleClamPizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and clam Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano clam";
- }
- }
- class NYStylePapperoniPizza extends Pizza {
- public function __construct() {
- $this->name = "NY Style Sauce and papperoni Pizza";
- $this->dough = "Thin Crust Dough";
- $this->sauce = "Marinara Sauce";
- $this->toppings[] = "Grated Reggiano papperoni";
- }
- }
- class ChicagoStyleCheesePizza extends Pizza {
- public function __construct() {
- $this->name = "Chicago Style Deep Dish Cheese Pizza";
- $this->dough = "Extra Thick Crust Dough";
- $this->sauce = "Plum Tomato Sauce";
- $this->toppings[] = "Shredded Mozzarella Cheese";
- }
- public function cut() {
- echo "Cutting the pizza into square slices/n";
- }
- }
- $myStore = new NYPizzaStore();
- $chicagoStore = new ChicagoPizzaStore();
- $pizza = $myStore->orderPizza("cheese");
- echo "Ethan ordered a " . $pizza->getName() . "/n";
- $pizza = $chicagoStore->orderPizza("cheese");
- echo "Ethan ordered a " . $pizza->getName() . "/n";
- ?>
工厂模式
- <?php
- abstract class PizzaStore {
- public function orderPizza($type) {
- $pizza = $this->createPizza($type);
- $pizza->prepare();
- $pizza->bake();
- $pizza->cut();
- $pizza->box();
- return $pizza;
- }
- public abstract function createPizza($type);
- }
- class NYPizzaStore extends PizzaStore {
- public function createPizza($type) {
- $pizza = null;
- $ingredientFactory = new NYPizzaIngredientFactory();
- if ($type == "cheese") {
- $pizza = new CheesePizza($ingredientFactory);
- $pizza->setName('New York Style Cheese Pizza');
- } elseif ($type == "veggie") {
- $pizza = new VeggiePizza($ingredientFactory);
- $pizza->setName('New York Style Veggie Pizza');
- } elseif ($type == "clam") {
- $pizza = new ClamPizza($ingredientFactory);
- $pizza->setName('New York Style Clam Pizza');
- } elseif ($type == "papperoni") {
- $pizza = new PapperoniPizza($ingredientFactory);
- $pizza->setName('New York Style Papperoni Pizza');
- }
- return $pizza;
- }
- }
- class ChicagoPizzaStore extends PizzaStore {
- public function createPizza($type) {
- if ($type == "cheese") {
- return new ChicagoStyleCheesePizza();
- } elseif ($type == "veggie") {
- return new ChicagoStyleVeggiePizza();
- } elseif ($type == "clam") {
- return new ChicagoStyleClamPizza();
- } elseif ($type == "papperoni") {
- return new ChicagoStylePapperoniPizza();
- } else {
- return null;
- }
- }
- }
- interface PizzaIngredientFactory {
- public function createDough();
- public function createSauce();
- public function createCheese();
- public function createVeggies();
- public function createPepperoni();
- public function createClam();
- }
- class NYPizzaIngredientFactory implements PizzaIngredientFactory {
- public function createDough() {
- return new ThinCrustDough();
- }
- public function createSauce() {
- return new MarinaraSauce();
- }
- public function createCheese() {
- return new ReggianoCheese();
- }
- public function createVeggies() {
- $veggies = array(
- new Garlic(),
- new Onion(),
- new Mushroom(),
- new RedPepper(),
- );
- return $veggies;
- }
- public function createPepperoni() {
- return new SlicedPepperoni();
- }
- public function createClam() {
- return new FreshClams();
- }
- }
- class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
- public function createDough() {
- return new ThickCrustDough();
- }
- public function createSauce() {
- return new PlumTomatoSauce();
- }
- public function createCheese() {
- return new Mozzarella();
- }
- public function createVeggies() {
- $veggies = array(
- new BlackOlives(),
- new Spinach(),
- new EggPlant(),
- );
- return $veggies;
- }
- public function createPepperoni() {
- return new SlicedPepperoni();
- }
- public function createClam() {
- return new FrozenClams();
- }
- }
- abstract class Pizza {
- public $name;
- public $dough;
- public $sauce;
- public $veggies = array();
- public $cheese;
- public $pepperoni;
- public $clam;
- public abstract function prepare();
- public function bake() {
- echo "Bake for 25 minutes at 350/n";
- }
- public function cut() {
- echo "Cutting the pizza into diagonal slices/n";
- }
- public function box() {
- echo "Place pizza in official PizzaStore box/n";
- }
- public function getName() {
- return $this->name;
- }
- public function setName($name) {
- $this->name = $name;
- }
- public function __toString() {
- }
- }
- class CheesePizza extends Pizza {
- public $ingredientFactory;
- public function __construct(PizzaIngredientFactory $ingredientFactory) {
- $this->ingredientFactory = $ingredientFactory;
- }
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- $this->dough = $this->ingredientFactory->createDough();
- $this->sauce = $this->ingredientFactory->createSauce();
- $this->cheese = $this->ingredientFactory->createCheese();
- }
- }
- class ClamPizza extends Pizza {
- public $ingredientFactory;
- public function __construct(PizzaIngredientFactory $ingredientFactory) {
- $this->ingredientFactory = $ingredientFactory;
- }
- public function prepare() {
- echo "Preparing " . $this->name . "/n";
- $this->dough = $this->ingredientFactory->createDough();
- $this->sauce = $this->ingredientFactory->createSauce();
- $this->cheese = $this->ingredientFactory->createCheese();
- $clam = $this->ingredientFactory->createClam();
- }
- }
- $nyPizzaStore = new NYPizzaStore();
- $nyPizzaStore->orderPizza('cheese');
- ?>
观察者模式
- <?php
- /**
- * 观察者模式
- * 定义了对象之间的一对多依赖,当一个对象改变状态时,
- * 它的所有依赖者都会收到通知并自动更新。
- */
- interface Subject {
- public function registerObserver(Observer $o);
- public function removeObserver(Observer $o);
- public function notifyObservers();
- }
- interface Observer {
- public function update($temperature, $humidity, $pressure);
- }
- interface DisplayElement {
- public function display();
- }
- class WeatherData implements Subject {
- private $observers = array();
- private $temperature;
- private $humidity;
- private $pressure;
- public function __construct() {
- $this->observers = array();
- }
- public function registerObserver(Observer $o) {
- $this->observers[] = $o;
- }
- public function removeObserver(Observer $o) {
- if (($key = array_search($o, $this->observers)) !== false) {
- unset($this->observers[$key]);
- }
- }
- public function notifyObservers() {
- foreach ($this->observers as $observer) {
- $observer->update($this->temperature, $this->humidity, $this->pressure);
- }
- }
- public function measurementsChanged() {
- $this->notifyObservers();
- }
- public function setMeasurements($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->pressure = $pressure;
- $this->measurementsChanged();
- }
- }
- class CurrentConditionsDisplay implements Observer, DisplayElement {
- private $temperature;
- private $humidity;
- private $weatherData;
- public function __construct(Subject $weatherData) {
- $this->weatherData = $weatherData;
- $weatherData->registerObserver($this);
- }
- public function update($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->display();
- }
- public function display() {
- echo "温度:" . $this->temperature . "; 湿度:" . $this->humidity . "%/n";
- }
- }
- class StatistionsDisplay implements Observer, DisplayElement {
- private $temperature;
- private $humidity;
- private $pressure;
- private $weatherData;
- public function __construct(Subject $weatherData) {
- $this->weatherData = $weatherData;
- $weatherData->registerObserver($this);
- }
- public function update($temperature, $humidity, $pressure) {
- $this->temperature = $temperature;
- $this->humidity = $humidity;
- $this->pressure = $pressure;
- $this->display();
- }
- public function display() {
- echo "温度:" . $this->temperature . "; 湿度:" . $this->humidity . "%; 气压:" . $this->pressure . "/n";
- }
- }
- $weatherData = new WeatherData();
- $currentDisplay = new CurrentConditionsDisplay($weatherData);
- $statistionDisplay = new StatistionsDisplay($weatherData);
- $weatherData->setMeasurements(10, 20, 30);
- $weatherData->removeObserver($currentDisplay);
- $weatherData->setMeasurements(30, 40, 50);
- ?>
命令模式
- <?php
- class Light {
- public function __construct() {
- }
- public function on() {
- echo "Light On/n";
- }
- public function off() {
- echo "Light Off/n";
- }
- }
- interface Command {
- public function execute();
- }
- class LightOnCommand implements Command {
- public $light;
- public function __construct(Light $light) {
- $this->light = $light;
- }
- public function execute() {
- $this->light->on();
- }
- }
- class SimpleRemoteControl {
- public $slot;
- public function __construct() {
- }
- public function setCommand(Command $command) {
- $this->slot = $command;
- }
- public function buttonWasPressed() {
- $this->slot->execute();
- }
- }
- class RemoteControlTest {
- public static function main() {
- $remote = new SimpleRemoteControl();
- $light = new Light();
- $lightOn = new LightOnCommand($light);
- $remote->setCommand($lightOn);
- $remote->buttonWasPressed();
- }
- }
- RemoteControlTest::main();
- ?>
装饰者模式
- <?php
- /**
- * 装饰着模式
- * 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
- */
- abstract class Beverage {
- public $description = "Unknown Beverage";
- public function getDescription() {
- return $this->description;
- }
- public abstract function cost();
- }
- abstract class CondimentDecorator extends Beverage {
- //JAVA代码里这里是个抽象类,PHP不允许这么做
- public function getDescription() {
- return $this->description;
- }
- }
- class Espresso extends Beverage {
- public function __construct() {
- $this->description = "Espresso";
- }
- public function cost() {
- return 1.99;
- }
- }
- class HouseBlend extends Beverage {
- public function __construct() {
- $this->description = "HouseBlend";
- }
- public function cost() {
- return .89;
- }
- }
- class DarkRoast extends Beverage {
- public function __construct() {
- $this->description = "DarkRoast";
- }
- public function cost() {
- return .99;
- }
- }
- class Mocha extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Mocha";
- }
- public function cost() {
- return .20 + $this->beverage->cost();
- }
- }
- class Whip extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Whip";
- }
- public function cost() {
- return .10 + $this->beverage->cost();
- }
- }
- class Soy extends CondimentDecorator {
- public $beverage;
- public function __construct(Beverage $beverage) {
- $this->beverage = $beverage;
- }
- public function getDescription() {
- return $this->beverage->getDescription() . ", Soy";
- }
- public function cost() {
- return .15 + $this->beverage->cost();
- }
- }
- $beverage = new Espresso();
- echo $beverage->getDescription() . "/n";
- $beverage2 = new DarkRoast();
- $beverage2 = new Mocha($beverage2);
- $beverage2 = new Mocha($beverage2);
- $beverage2 = new Whip($beverage2);
- echo $beverage2->getDescription() . " $" . $beverage2->cost() . "/n";
- $beverage3 = new HouseBlend();
- $beverage3 = new Soy($beverage3);
- $beverage3 = new Mocha($beverage3);
- $beverage3 = new Whip($beverage3);
- echo $beverage3->getDescription() . " $" . $beverage3->cost() . "/n";
- ?>
状态模式
- <?php
- class GumballMachine {
- const SOLD_OUT = 0;
- const NO_QUARTER = 1;
- const HAS_QUARTER = 2;
- const SOLD = 3;
- public $state = self::SOLD_OUT;
- public $count = 0;
- public function __construct($count) {
- $this->count = $count;
- if ($count > 0) {
- $this->state = self::NO_QUARTER;
- }
- }
- public function insertQuarter() {
- if ($this->state == self::HAS_QUARTER) {
- echo "You can't insert another quarter!/n";
- } else if ($this->state == self::NO_QUARTER) {
- $this->state = self::HAS_QUARTER;
- echo "You inserted a quarter!/n";
- } else if ($this->state == self::SOLD_OUT) {
- echo "You can't insert a quarter, the machine is sold out!/n";
- } else if ($this->state == self::SOLD) {
- echo "Please wait, we're already giving you a gumball!/n";
- }
- }
- }
- $obj = new GumballMachine(0);
- print_r($obj)
- ?>
jQuery 中使用 JSON
JSON 格式
json 是 Ajax 中使用频率最高的数据格式,在浏览器和服务器中之间的通讯可离不开它。
JSON 的格式说明可以在可以这里看到,非常详细,还是中文的。
需要特别注意的是,在 JSON 中的属性名是需要使用引号引起来的。
jQuery 中使用 JSON
jQuery 是现在使用广泛的脚本库,那么,在 jQuery 中如何使用 JSON 呢?
解析 JSON
在 jQuery 中已经提供了对于解析 JSON 的内在支持,
jQuery.parseJSON 函数提供了解析的支持,详细的说明见这里。
var obj = jQuery.parseJSON('{"name":"John"}');
alert( obj.name === "John" );
使用对象生成 JSON 格式串
在 jQuery 中并没有提供直接将普通的 JavaScript 对象转换为 JSON 串的方法,可以使用下面的扩展库来完成。
jquery-json 扩展库
这个库用来扩展 jQuery ,对于 JSON 的使用,扩展了两个方法。
toJSON 方法用来将一个普通的 JavaScript 对象序列化为 JSON 串。
var thing = {plugin: 'jquery-json', version: 2.3}; var encoded = $.toJSON( thing ); // '{"plugin":"jquery-json","version":2.3}'
evalJSON 方法将一个 JSON 串解析为一个普通的 JavaScript 对象。
var thing = {plugin: 'jquery-json', version: 2.3}; var encoded = $.toJSON( thing ); // '{"plugin":"jquery-json","version":2.3}' var name = $.evalJSON( encoded ).plugin; // "jquery-json" var version = $.evalJSON(encoded).version; // 2.3
这个扩展的下载地址:http://code.google.com/p/jquery-json/
使用 jQuery 配合 WCF
客户端
jQuery 中的 $.post 可以直接向服务器发出请求,将服务器返回的数据按照 JSON 方式进行解析,不过,需要注意下面几点:
请求的内容类型必须为 json 格式,这可以通过上面的 jQuery-json 扩展库来完成,需要特别注意的在请求的 contentType 也必须使用 text/json 进行说明,默认的 post 使用普通的名值对方式请求,因此 contentType 是: application/x-www-form-urlencoded,可以通过 $.ajaxSetup 来进行设置:
// Ajax 设置 $.ajaxSetup({ contentType: 'text/json' });
这样,请求的内容类型就设置为需要的类型。
其次,实际的请求内容必须使用 JSON 方式,这可以通过扩展库的 $.toJSON 来实现,例如:
$.toJSON({ x: 2, y: 3 })
这样,如果服务器端提供了一个服务方法 Sum,定义如下:
public int Sum(int x, int y) { return x + y; }
就可以如下调用了。注意,WCF 返回的数据在属性 d 中。
// Ajax 设置 $.ajaxSetup({ contentType: 'text/json' }); $("#wcfBtn").click(function () { $.post("Service1.svc/Sum", $.toJSON({ x: 2, y: 3 }), function (data) { alert(data.d); }); });
服务器端的配置
首先,为服务增加标签:[System.ServiceModel.Activation.AspNetCompatibilityRequirements(RequirementsMode = System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
然后,在网站的配置文件中,如下配置。
<system.serviceModel> <!-- 为了支持在浏览器端调用 WCF 服务的特定配置 --> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"> <serviceActivations> <!-- relativeAddress 服务的地址 service 实现服务的类型,全名,包含命名空间,甚至程序集 factory 是 WCF 系统提供,直接使用 --> <add relativeAddress="Service1.svc" service="MServer.Service1" factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" /> </serviceActivations> </serviceHostingEnvironment> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
各大IT公司、软件公司员工等级(级别)及薪资
信息来自互联网(很多是猎头的post中包括了薪水信息)
数据很可能已经过时,准确性很不高,仅供参考
主要对象职位:技术类,工程师
IBM员工等级(级别)
Band |
Non-ManagementTitle |
ManagementTitle |
6 |
SalesSpecialist |
|
7 |
AdvisorySalesSpecialist |
|
8 |
SeniorSalesSpecialist |
SalesSpecialist-Manager |
9 |
ConsultingSalesSpecialis |
ConsultingSalesSpecialis |
10 |
SeniorConsultingSalesSpe |
SeniorConsultingSalesSpe |
|
|
|
6 |
ITSpecialist |
|
7 |
AdvisoryITSpecialist |
|
8 |
SeniorITSpecialist |
SeniorITSpecialist-Manager |
9 |
ConsultingITSpecialist |
ConsultingITSpecialist-Manager |
10 |
ExecutiveITSpecialist |
ExecutiveITSpecialist-Manager |
|
|
|
6 |
SoftwareEngineer |
|
7 |
StaffSoftwareEngineer |
SoftwareEngineering-DepartmentManager |
8 |
AdvisorySoftwareEngineer |
SoftwareEngineering-Manager |
9 |
SeniorSoftwareEngineer |
SoftwareEngineering-SeniorManager |
10 |
STSM-Software |
ManagerofSoftwareEnginee |
|
|
|
6 |
Consultant |
|
7 |
SeniorConsultant |
|
8 |
ManagingConsultant |
ManagingConsultant-Manager |
9 |
SeniorManagingConsultant |
SeniorManagingConsultant |
10 |
ExecutiveConsultant |
ExecutiveConsultant |
部门结构
GBS 前端咨询..有战略咨询 有ERP咨询...流程咨询比较多
GTS 后端 为4大国有银行做维护
CDL 研发中心 (CSDL & CSTL)
ISSC 外包中心
GDC工资低于GBS,那是肯定的,GDC需要的是大量的工人,而不是个个都是行业顾问专家。
GDC里面一半都是刚刚毕业没两年
GBS比ISSC名气好,顾问性质,IBM 50%利润来源于此。
GBS:Band 7, GBS 14-20K, 14薪,+15% 住房补贴,满10万上限。
Band 8 20-30K,福利同上
ISSC Band 7 理论上16K到顶,可以突破。13薪,签约奖金两个月,10%住房补贴,
Band 8 也是比GBS低一些,有猎头说,基本上低半级。
出差: GBS,250一天。 Fly Back
GDC:包月的形式,一月7500给你
IBM 里的朋友都认为,ISSC不是IBM的。虽然理论上,ISSC应该是的...
两个公司的HR是不同的...
以前GBS做实施,ISSC做维护。据说ISSC也开始和GBS一起做项目了。
18摸得薪酬到底怎么样,我给大家一个参考值,不同的部门同一个band 差距较大,这里给出同一个band的上下值。2012.10 版(睡前月基本工资)band7 1.24W ~2.76W , band8 1.9w ~4.2w, band9 3.3w ~7.7w , band10 5.28w ~12.3w ,全公司均值 band7 2w, band8 3w band9 5.5w band10 8.8w,你在哪个水平
发信人: wayy (wayy), 信区: WorkLife
标
发信站: 水木社区 (Mon Apr 15 21:54:25 2013), 站内
我俩小弟一个去年到9,一个今年到9
都不到60万,base都在3万出头
18摸工资很低,不过胜在worklife balance强
我知道lab 里边有个band 10, package大约65万
【 在 reflection (闲爱孤云) 的大作中提到: 】
: 9的话幅度就比8大多了。越往上差距越大。18摸认为核心员工最低的级别就是10,所
: 以9以下的就没必要以18摸为荣了,都是边角料。
薪水结构
同Band的技术和销售,MBS的范围都是一样的,不同的只是incentive plan不同,销售141%,技术119%
销售的收入的141%,其中的的77.5%部分是稳定的,其他的是浮动bonus
Band7最高的MBS是21K
Band 8的MBS range是18K~34K
Band9 mbs
一个offer例子:
1. your reference monthly salary is 24,000
2. monthly allowance is 800
3. 10% housing fund
4. 15% saving fund
5. 141% incentive plan (55/45 paymix)
6. 14 months reference salary annually => 14个月工资
7. total annual package is 525,813.
微软 Microsoft 员工等级(级别)
(发表于2010-07-22)
59,60被称作SDE/SDET/PM, 61,62是SDE2/SDET2/PM2, 63,64是Senior SDE Senior SDET, Senior PM, or Senior ****,取决于你的普通title。65开始叫做principle。68开始叫做partner,70是distinguished engineer,有些VP也是这个级别。但大多数VP,techinical fellow都是80级。据说billg的级别很高。大多数人混到senior就止步了,有人开玩笑说,只要到了senior就是大锅饭,不会layoff。有些人能混到principle。再有些牛人,才能到principle之上,算是微软的厉害人物。
59之下的级别,主要是给那些stuff和秘书之类的。以前有手工测试的时候,他们的级别都是57。微软研究院的研究员是另外一套体制,他们的级别基本是同阶段engineer的级别+3. 还是很爽的。
59级的薪水,几年前大概在7万6左右。每增长一级工资,base大概能增长大几千将近1w,cash bonus的增加并不多,但stock award跟级别关系很大,比如62级的award就将近是61级别2倍。66又将近是65的两倍。但62,63,64变化不甚大。
HP
5c对应于spe 1,
5b 对应于spe 2,
5就对应于spe 3了。(月薪参考:10k-20k)
6对应expert。expert分exp 1和exp 2.
exp后升master是走技术路线,升manager是管理路线。
Oracle员工等级(级别)
技术岗 |
管理岗 |
|
||
Level |
Title |
Level |
Title |
|
ic1 ic2 |
Junior Engineer Staff Engineer |
|
||
ic3 |
Senior Engineer |
m2 |
Manager |
|
ic4 |
Principle Engineer |
m3 |
Senior Manager |
|
ic5 |
Senior Principle Engineer |
m4 |
Director |
|
Oracle R&D (研发中心) ic3参考年薪20w+
ic4参考年薪30w+
O记的software engineer(IC2)相当于IBM的band 6, senior(IC3)相当于band 7, principle(IC4)相当于band 8, consultant principle(IC5)相当于band 9吧
从package讲,O过去是靠谈,现在貌似要求你提供上一家的薪水,根据那个涨幅不超过20%,超过30%就要走特殊流程了。
路透员工等级(级别)
方舟大厦研发中心的待遇年薪 12个月工资,1个月年终奖,年薪15%的奖金,基本是15个月薪水
principal software engineer 22w-25w之间
senior software engineer 18w-22w之间
principal QA >22w
Senior QA <22w
software engineer 18w
QA engineer 16w
associate software engineer 15w
associate qa engineer 14w
trainee software engineer 10w
trainee qa engineer 10w
intern 2200/月
software team manager <30w
QA team manager <30w
specialist = team manager
project manager <30w
teachinal writer 16w
腾讯
T1-T4
T2和T3和T4之间有3个小等级 就是T2-1,T2-2,T3-3
T2-T3 15-30w
T3-T4 30-60W左右 可能有股票
VMware员工等级(级别)
R&D QA Manager ,35W以上,最低20k/m (2010-8-31)
QA Manager
Senior Engineer 25万-32万/年,股票。20天年假,全家保险,100%报销。(2011-10-19)
Adobe员工等级(级别)
QE developer-RMB 118,200 – RMB 171,300
QE lead- RMB 145,200–RMB313,650
华为:
员工级别 |
职位名称 |
配股 |
标准岗位工资 |
||
C岗 |
B岗 |
A岗 |
|||
13 |
|
2W |
5500 |
6500 |
7500 |
14 |
工程师B |
5W |
7500 |
9000 |
10500 |
15 |
工程师A |
20W |
10500 |
12500 |
14500 |
16 |
高级工程师B |
30W |
14500 |
17000 |
19500 |
17 |
高级工程师A |
50W |
19500 |
22500 |
25500 |
18 |
主任工程师 |
80W |
25500 |
29000 |
32500 |
19 |
技术专家B |
120W |
32500 |
36500 |
40500 |
20 |
技术专家A |
200W |
40500 |
44500 |
49500 |
21 |
高级技术专家 |
300W |
49500 |
54500 |
59500 |
22 |
资深技术专家 |
500W |
59500 |
|
|
23 |
|
1000W |
|
|
|
阿里巴巴:员工等级(级别)
p5 工程师
p6 高级工程师
p7 初级专家
p8 专家
p9 初级研究员
p10 研究员
p11 初级科学家
p12 科学家
p14
p14
一般硕士毕业是P5,博士毕业是P6
p6 月薪 7.5K – 17K 开始有期权或者股票
p8 差不多部门老大,月薪25K,年终奖11,股票另算。大多在50w左右
m是管理路线
m1 主管与p5相当
m2经理 与P7相当
m3高级经理 p8
m4 总监
m5高级总监
马云是m10,阿里巴巴m10就他一个
新浪:员工等级(级别)
4-1
3-3
3-2
3-1
2-3
…
有效控制项目进度的几点技巧
软件开发的项目周期大体分为3个阶段:获取需求和定义产品、开发和测试、部署和运维。
在获取需求和定义产品阶段,需要防止 的不是进度太慢而是过快、过草率。特别是对于创业公司的产品经理来说,很可能因为看到开发人员无事可做而感到压力,所以尽快完成产品定义,而没有充分了解 市场和竞争对手信息,没有与合作伙伴充分沟通,没有做深入的思考。
这些因仓促而隐藏的问题,发现得早则导致开发阶段大量返工,发现得晚则导致产品上线后不 受欢迎。常听一些人说现在互联网开发,讲究快速迭代和敏捷,边做边想,返工也正常。这是一个误解。快速迭代指的是将不同版本之间的周期缩短,小步快跑,而 不是在一个版本的周期内来回折腾。
在开发和测试阶段,项目管理重在跟踪进度和保持沟通—用集成和演示跟踪进度,基于Bug沟通问题。
要做到各个模块外部接口相对清晰稳定,并尽早完成各个模块间的集成,最晚不超过开发周期的1/4时间。第一次集成之后,就应该开始每日集成和每周演示。每日 集成使得测试团队每天能同步测试最新的代码,帮助开发团队尽早发现问题并及时了解技术细节上的进度;每周演示使产品经理、项目经理和管理层能从用户的角度 感受产品,使他们对产品有信心。集成和演示是项目管理的心跳,合理利用它们,有助于及时把握项目的健康程度。
无论开发流程多敏捷,工程师能 力多强,记录和跟踪Bug都是必不可少的。开发团队和测试团队的沟通都应该基于Bug,才能言之有物。开发工程师每次提交代码都应该记录是针对哪个Bug 的,每日工作简报都应该写今天关/开了哪些Bug。要在每日晨会(站着开,一般15分钟内)时说好,今天打算解决哪些Bug,其中有哪些点不清楚,需要和 谁沟通。
在后期部署和维护阶段,要快速响应。考验的是团队成员的责任心和抗压能力。系统运维工程师要深夜工作,因为部署可能要在流量低的时 候进行;项目经理要保持能随时沟通,做出快速而准确的决定,鼓励团队并做出表率;一旦出现高危害Bug,开发团队要在24小时内准备好补丁。Amazon 的做法比较有趣:在产品刚上线一段时间内,开发工程师要保持24小时开机。如果自己负责的模块中出现高危害Bug,那么很可能会在深夜被系统运维工程师叫醒。这样不仅能保证快速响应,还能让工程师意识到:前期代码不好好写,后期就别指望能好好睡觉了。