分类目录归档:百姓网内部

Github vs SourceForge

最近一直在用GitHub,再看一下SourceForge,对比一下。比如:

比如这个项目:https://github.com/mxcl/homebrew

再看看这个项目:http://sourceforge.net/projects/clisp/

感觉不一样吧?(不是比较两个项目,而是类似的项目放在不同的地方的感觉)

一个2001年闭源,10年没有变化的SF,和一个每天都有惊喜的GitHub,我们要做哪个?

一个千方百计用广告赚钱,把广告商的利益放在前面,而用户的利益放在后面,和一个为了用户着想,用户回来付钱,我们做那个?

我们如果关心的不是熊猫用户,就像SourceForge不关心程序员一样,必死。(虽然需要10年的破败期才会真死,但放弃用户的那一刻这个公司已经死了)。

不好了,池子漏了

周末在杭州给天使湾的十几家移动互联网公司分享,看到他们做的东西,和庞小伟聊了聊,得到如下思考,和大家分享。

2012年是传统互联网公司遇到前所未有的挑战的一年。

从1995年开始,中国的互联网网民就不断的增加,每18个月网民总数翻番的速度几乎没有停下来过。如果看看当年中国最大的门户网站新浪上市的时候日浏览量只有1000万,而现在随便一个网站都有可能超过千万就能知道这十几年的发展速度。不过,坏消息是,这种增长从2011年开始放缓了。现在中国5亿网民,我可以非常自信的预测,中国网民数永远不可能翻番两次了。在之前的10年,每天都有新用户,对于网站来说永远有机会,新用户就算是平均分配也有不错的增长,而增长低于两年翻番就是落后。而这种情况,变了。互联网的人口红利,第一次接近发完,传统互联网增长压力剧增,看看最近的一两年,很多的报表都在显示网站增长速度放缓,从百度,腾讯的网页到第二梯队的大多数网站,都是一样。

屋漏偏逢天下雨。在过去的十几年里面,互联网的网民数只增不减,无论什么时候拉上来的网民,都在一个大池子里面,这个池子从来没有漏过水。但是,从2011年开始,这个池子开始有了一个大窟窿,这个窟窿就是移动互联网。越来越多的用户迁移到移动终端上。虽然不是一去不复返,但是在PC上上网的目的,时长等发生着重要的改变。

看看移动的这个窟窿有多大!现在智能手机大约4000万终端,但这个数字很有可能在未来的3年里面达到4亿(3年还是5年不是关键,关键是短期一定能达到这个数字)。如果真的是这样的话,以Android,iPhone为代表的智能机用户每个月可能就要新增加1000万,这是一个大得不得了的数字,是一个不能忽视的人口红利(天哪,不是红利,就是本金派发了)。

同样,我们看一下智能手机的移动客户端的安装量。现在一般的安装量在100万以下(包括我们的)。一些300万左右的是比较大的,超过1000万安装量的几乎就是人手一个了。新浪微博,微信,大众点等等。但是想想一下,再过3年,会出现什么状况?一个普通的应用的安装量应该在1000万以上,智能手机安装量过亿的将会诞生。这是一个非常大的机会。我们这里仅仅探讨智能手机,就是Android,iPhone,其他的终端暂且不算作移动互联网。

而手机领域,一定和网站领域不同。一定不同。具体的不同我还没有特别的感觉,但需要恶补这方面的知识才能够在这个领域不被甩下。隐约感觉互联网是主机的一张脸,让用户过来看这张脸,而移动互联网是用户的一张脸,用户打开的应用应该就是非常个性化的自己要的东西。移动互联网绝对不应该和PC互联网的体验一致。我们需要重新思考这个问题:我们解决什么问题?我们怎么解决?而完全不需要考虑PC互联网的很多的做法。我们很有可能需要按照你是谁来做程序,比如给房东用的,给工人用的,给白领用的这样的方式做APP。等等等等。需要有很多的思考。

结论:我们需要非常非常的重视移动互联网。这其实是百姓网的第二次创业。被一个大潮甩掉太容易了,能够在两次大潮中间都有所表现的公司,太少见了。按照历史的平均水平来看,如果我们不做些什么,百姓网很快会在移动互联网来到的时候变得无足轻重。

一个建都的计划

前天晚上我们打破了一个世界。面对我们自己给自己设置的边界,我摔了第一个盘子,大家都看到了,知道原来那些桌子架子上的碍着自己事儿的盘子是可以摔的。于是大家有跃跃欲试,准备跟着摔盘子。但问题是,不是摔了盘子就能解决问题的。我们重建的是什么,怎么重建?这是一个计划。

1. 兵分两路。

现在公司需要立刻成立一个小分队,开始筹划重新搭建我们可以依赖的系统。这部分开始只需要很少的人做先锋队。为了速度,我们可以用独立的服务器,新的架构,不考虑和老程序兼容。另外,所有的其他开发和业务,在现有基础上继续推进。原来所有的目标和计划不变。我们的老都城朝歌还要继续存在2年以上,我们需要完善它。这两路兵,对于百姓网都至关重要,我们在变革的时候决不能停下来。

2. 快速推进,长期并存

我们需要快速的推进新都城的建设。我们会在路由器那一层尽快的把第一个页面指向新系统,比如说用户页面。当我们可以看到一个新页面在新的服务器上运行的时候,第一面红旗就已经开始飘扬了。只要有第一个人完成了第一个页面,其他各个页面,比如Listing Page,View Ad Page,Home Page,User Page都可以沿着这条路或快或慢的迁移过去,因为路已经通了。

我们以最高的质量要求建设新页面(code review等流程随之建立),但选择非常小的功能集。所有的没有实现的功能,依然由老的朝歌系统完成。所有的写操作(发帖,付费,信息审核等)都在老朝歌。朝歌作为陪都会一直保留,直到几年后最后一批功能和用户迁移出去。而有一些功能,比如赤壁,牧野以及大多数的管理工具,近期没有改变的计划。

3. 先读后写

这是给技术人员的注释。我们的新都城会先实现读的功能,让主要页面都跑起来。因为读的难度较低,对用户影响最大,对错误容纳度非常高,可以让我们的功能平稳过渡。我们应该可以很快的把80%的流量迁移到新代码上来。当读全部迁移到新代码以后,会逐步小心的把写分步迁移过来。直到全部完成。

我们这几天正在筹划这个新的团队,其实有些工作,在3周前已经开始了。我需要大家这个时候打起精神,在各条线推进;同时要有耐心,罗马不是一天建成的,我们的新都城也不是。

加油!

192行

//wangjianshuo@baixing.com
namespace Graph;

class CompanyAccount {
…function occuredRevenue($startTime, $endTime) {
……$money = 0;
……
……if($endTime > time())
………throw new Exception(“Refuse to tell you future, because that may be inaccurate”);
……
……$s = new Searcher(
………new AndQuery(
…………new Query(‘type’, ‘Order’),
…………new Query(‘paid’, 1),
…………new RangeQuery(‘startTime’, null, $endTime),
…………new RangeQuery(‘endTime’, $startTime – 1, null)
………)
……);
……
……foreach($s as $order)
………$money += ($order->occuredRevenue($endTime) – $order->occuredRevenue($startTime));
………
……return $money;
…}
}

class UserAccount {
…public $balance; // money + credit;
…public $ratio; // money / balance;

…function in($money, $credit){
……$this->ratio = ($this->balance * $this->ratio + $money) / ($this->balance + $money + $credit);
……$this->balance += $money + $credit;
……$this->save();
…}

…function out($mondit) { //mondit = money + credit
……$this->balance -= $mondit;
……$this->save();
…}

…function pay($order) {
……$order->pay($order->listPrice * $this->ratio);
……$this->out($order->listPrice);
…}

…function partialCancel($order, $time) {
……$order->particalCancel($time);
……
……$refund = $order->price – $order->occuredRevenue($time);
……$ratio = $order->price / $order->listPrice;

……$this->in($refund, $refund / $ratio * (1 – $ratio));
…}
}

class Order {
…public $unitTime = 24 * 60 * 60; // 1 day
…public $paid = false;

…function occuredRevenue($time) {
……$money = 0;
……$unitPrice = round(($this->price) / ($this->endTime – $this->startTime) * $this->unitTime, 2);
……for($i = 0; $occuredTime = $this->startTime + $this->unitTime * $i, $occuredTime < min($time, $endTime); $i++)
………if($this->endTime – $this->occuredTime <= $this->unitTime)
…………$money += ($this->price – $unitPrice * $i);
………else
…………$money += $unitPrice;
……return $money;……
…}

…function place() {
……$pa = new BiddingPrice();
……$this->listPrice = $pa->price($order);
……$this->save();
…}

…function partialCancel($time) {
……if($time >= $this->endTime)
………throw new Exception(‘Cannot cancel completed order’);
……
……$neg = clone $this;
……$neg->startTime = max($this->startTime, $time);
……$neg->price = $this->occuredRevenue($time) – $this->price;
……$neg->save();
…}

…function attributes() {
……$ad = graph($this->adId);
……
……return array_merge(
………parent::attributes(),
………’categories’ => cg_array_upto(array_reverse($ad->category->path()), $this->category),
………’areas’ => cg_array_upto(array_reverse($ad->area->path()), $this->area)
…}
}

function cg_array_upto($arr, $c) {
…$result = array();

…foreach($arr as $a) {
……$result[] = $a;
……$if($a == $c)
………break;
…}
…return $result;
}

class DingPrice extends BiddingPrice {
…public $capacity = 12;
…public $sensitivity = 0.5;
…public $bottom = 3;
…public $tolerance = 30; // day
…public $basePrice = 10; // RMB
}

class RefreshPrice extends BiddingPrice {
…public $capacity = 12;
…public $sensitivity = 0.5;
…public $bottom = 3;
…public $tolerance = 30; // day
…public $basePrice = 10; // RMB
}

class BiddingPrice {
…function price($order) {
……$s = new Searcher(
………new AndQuery(
…………new Query(‘type’, ‘Order’),
…………new Query(‘paid’, 1),
…………new Query(‘area’, $order->area),
…………new Query(‘category’, $order->category)
………),
………array(‘order’ => ‘startTime DESC’)
……);
……
……if(count($s) == 0)
………return $this->basePrice;
……
……$currentPrice = $s[0]->listPrice;
……
……if(count($s) > $this->capacity) {
………foreach(array_slice($s, 0 floor($this->sensitivity * $this->capacity) as $o)
…………if($o->listPrice != $currentPrice)
……………return $currentPrice;
………return $this->increase($currentPrice);
……}
……
……if(count($s) <= $this->bottom &&
………time() – $s[0]->startTime > $this->tolerance)
………return $this->decrease($currentPrice);
………
……return $currentPrice;
…}

…function increase($price) {
……return $price + 10;
…}

…function decrease($price) {
……return $price – 10;
…}
}

class DingAds {
…function ads() {
……$v = new Visitor();
……$s = new Searcher(
………new AndQuery(
…………new Query(‘type’, ‘Order’),
…………new Query(‘paid’, 1),
…………new RangQuery(‘startTime’, null, time() + 1),
…………new RangeQuery(‘endTime’, time(), null),
…………new Query(‘categories’, $v->category),
…………new InQuery(‘areas’, $v->area->path())
…………)
………)
……);
……
……$dingAds = array();
……$negAds = array();
……
……foreach($s as $o)
………if($o->price >= 0)
…………$dingAds[] = $o->id;
………else
…………$negAds[] = $o->id;
…………
……return array_diff($dingAds, $negAds);
…}
}
/**
* 1. AccuralBasedAccouting DONE
* 2. Ding (Category, Filter, City, Province, China) DONE
* 3. Place order, pay, refund, partialCancel DONE
* 4. Pricing (Ding bidding based pricing, Refresh bidding, list bidding) DONE
* 5. User Account, real money, fake money DONE
* 6. Ding display DONE
* 7) Refresh 5 RMB
* 8) listing fee 10 RMB
* 9) Sales tools
* 10) Automatic invoice
* 11) Port service
*
* o—–o—–o—–o—–ø–
* ^ time
* o—–o—–o—–o—–o—-
*
*……………………………o—–o—–
*
* |——|——|——|——|——|——|——|
* ^ startTime ^ endTime
*
* Order
* =====
* orderId
* starTime
* endTime
* listPrice
* price
* paid
* area
* category
* adId
*
* 1. Order never change after paid.
* 2. Range [startTime, endTime)
* 3. price, money refer to real money,
* 4. listPrice, $credit refer to fake money.
*/

一艘没有人有浆的船

付费是我们众多代码泥潭的一个。5个工程师耗时半年,2万2千行代码,却bug不断,每天都有用户付了钱没置顶,对账对不清,退费消耗整个公司大量的精力,而我们的付费工程师还在抱怨业务过于复杂,对于新增的业务需求,没有人有信心完成。

昨天晚上,我召集所有工程师看我从一个空白页开始一个字一个字的敲代码。把我们大多数现在的业务需求(置顶,竞价,权责发生制记帐,退款等),以及现在还根本没有希望近期支持的业务需求(真钱假钱,刷新竞价等)实现了一遍。代码总共192行,耗时1个小时。

一个192行代码解决的问题,我们花了这么多工程师这么长时间还没有解决!!!这,就是我们的代码质量!这,就是我们的技术?这,就是一家号称技术公司做的事情?!我真想用最脏的话来骂这些该死的代码!

昨晚,我们安静的看着一行一行代码产生的一个小时,其实是我们集体默哀的一个小时。这是对于我们浪费掉的时间,我们浪费掉的机会,我们给所有其他部门带来的痛,以及我们失去的这家技术公司的灵魂,默哀。。。。。

一艘没有人有浆的船

在过去的7年里面,我从来没有觉得公司象今天这样危险,这个公司从来没有象今天这么差,差到真正优秀的,有血性的人,在考虑离开。

大家对于方向迷茫的抱怨由来已久,对于部门之间协作的抱怨也从来没有停止,但我明确的告诉大家,我们现在最大的问题,不是船划向何方的问题,不是如何配合的问题,而是在这条船上的所有人手中,没有一个人拿着浆!

现在的百姓网业务部门的人,只要没法动代码,就几乎什么也做不了。这是互联网公司的特质。

但大家可能不知道的是一个事实是,我们现在的工程师,也根本动不了代码。一个功能工程师不是不给你做,是做不出来。

面对代码的泥潭,没有人敢跳出来整理,只好随之沉下去。我没有说错。我再说一遍,在这个公司里面,工程师现在也没有办法改动我们的代码了。如果一个192行代码可以完成的功能,已经用了2万2千行了,在上面再加上2万2千行,局面只会越来越不可收拾。

现在的核心问题是,在这艘船上,无论业务还是Dev都苦恼得要死,都喊破了嗓子,对于方向达成或者不达成任何一致,我们依然没有看到我们的船向任何一个方向有进展。为什么?因为这艘船上,没有一个人手里面有浆!这就是我们最大的问题!

重建一个有Hacker精神的团队

大家看到我从3周前开始阶段性的闭关,看我们的代码,也写了些代码。用一种对自己很残忍的方式把付费的代码敲给大家看, 昨晚也已经是第四次了。我这样做就是为了消除业务人员对代码的恐惧,让工程师看到,除了2万行,还有一个192行的解决方案。我需要让大家的注意力放到,我们可以做什么上面,而不是不能做什么上面。

我需要立刻开始抽人重新构建我们的百姓网基础代码。我需要立刻开始以最高的标准来搭建我们的技术架构,我需要我们的技术能够第一个稳稳的拿起第一把浆,并且逐步把浆交到每一个业务部门的手中。我需要这条船开始启动,哪怕开始是慢的,我们必须起航。

我们的PM们原来多是优秀的Developer,甚至比现在很多Dev的代码写得更漂亮。我们公司有非常多可能的Dev,非常多业务部门的人本来就是工科毕业。花花和丰胸都看得懂代码的大概意思。我们的程序员很多有着非常深邃的对世界的认知,有着创造性的想法,如果愿意并有机会,他们可能比业务更了解用户,了解生意。我们是一家没有边界的Hacker组成的公司,我们会有更多人投入基础的代码工作,我们会让业务部门更直接和我们的Dev工作,让Dev和大家一起动脑子,一起搭建一个伟大的系统。我不信我们真的只能组成瘸子和瞎子互相搀扶才能前行的团队。

一个时代的结束的开始

晓良把我们的付费代码打印出来,贴在了会议室里,让大家永远记住在百姓网的历史上,有这样一段耻辱的时刻。我们知耻而后勇,我们一定能重新站到最棒的技术公司的前沿。我发誓!

昨晚,我说,“今晚不会是一个时代的结束。我们需要一起努力结束它。但今晚一定是一个时代的、结束的、开始。”

这的确会是百姓网的一个糟糕的时代的结束的开始!放心,我们在一起!

写代码这件事

晚上花了两个小时给丰兄和花花展示一次如何写代码,从第一个字符开始,用199行代码完成付费的如下功能:

  1. 权责发生制的记帐
  2. 置顶的产生和显示逻辑
  3. 类目置顶,筛选置顶,全省置顶,全国置顶,区县置顶
  4. 部分订单取消
  5. 置顶竞价,端口竞价
  6. 送天数逻辑,买100送20块这样真钱假钱逻辑

很累。

结论和大家分享:

1. 会代码不等于会逻辑

代码只是一种语言,一种更加精确的语言。会写代码仅仅是会写代码。一个汉语讲不明白话的人用英语也不见得讲明白。一个海明威要是学会了意大利语,估计小说也写得不错。代码仅仅是表达。一个代码写不明白的人,事情一定想不明白。事情想明白的人,就差一点点培训,就能写好的代码。

2. 边界

我们已经在停止学习了。停止学习是创业公司的死亡之日,也几乎是一个人的死亡之日。业务人员为什么不能看代码?我拉丰兄和花花(你没看错)来看代码,而且是看我一个字一个字敲出来,就是用一种残酷的方式打破大家对代码的恐惧。哪有那么复杂?就是一些数学表达式而已。

现在的状态让我感觉警察追小偷,一超过自己的区域,就嘎然而止,看着小偷扬长而去而不敢跨越雷池半步。我们不要讨论边界好不好,讨论一下小偷怎么还逍遥法外的问题好不好?不要骂对面地界的警察无能。骂自己无能,没办法走过去好不好?

3. 跨界

代码逻辑和业务逻辑本来就是在一起的,认为的分在两个人脑子里让谁都想不清。我们怎么可能在一点不知道财务怎么算帐的情况下把帐理清楚呢?怎么可能在不知道代码的情况下把付费逻辑理清楚呢?对不起,我不相信分工,我相信hacker精神,我相信聪明。

最后的底线是,不要告诉我不能做的原因,告诉我怎么可以做。代码理不清楚我来写。199行的代码虽然离上线还有距离,但距离已经不远了。我们的付费复杂吗?要得了两万多行的代码吗?两万行的代码解决问题倒也罢了,还没解决问题。。。。

我又想骂人了。就此打住。。

 

看代码的愤怒

刚才花时间看了些代码,怒了。

程序员是思考的人,象画家和作家一样,不是码农,不是通过体力完成功能的人,绝不是!看代码和看书一样,是能感觉到写代码的人的思想。看一篇优美的散文和诗歌,跟看报纸上干巴的公关稿,感觉就是不一样,跟看帐本更不一样。

我刚才看到大量的hardcode的东西,没有逻辑,没有层次,多次拷贝粘贴而成的东西,怒!虽然完成了功能,但根本就是垃圾的代码,是没有灵魂的代码,写这样的东西,真的只能叫码农,不能叫程序员。

代码是有灵气的东西。它是对与世界的抽象。之所以需要有灵气,是因为在复杂的需求和优美的实现中间有一个巨大的矛盾,这个矛盾的解决之道是程序员的能力。

千万不要抱怨现实的复杂。现实必然复杂!画人像的画家从来不应该抱怨模特的脸为什么不长成严格的正方体,好让自己画阴影的时候容易点。试图用正方体去画人像必然失败,会被骂。在现实的复杂和纸面上的优雅之间的巨大冲突,需要由画家的技巧来弥补。

不是复杂的世界一定会导致恶心的代码。精致的代码不见得出来的就是简化得现实。但两者兼得的确来之不易,需要能力!

怎么做到用精致得代码构造复杂的现实呢?

  1. 分层。
  2. 抽象。
  3. 迭代

首先是分层。

举个做菜的例子。中国菜馆的菜单动辄几十种,若是没有合适的分层,连原料存储都成了问题:总不能厨房里面放着几十个格子,每个格子里面放着一样菜的所有原料吧。分层,或许可以分为“配菜层”,“制作层”,“调料层”。

  1. “配菜层”又分成“肉”和“菜”并列的两类。肉里面有牛肉,羊肉,鸡肉等,菜里面几种蔬菜。
  2. “制作层”其实就只有炒,烧,蒸,爆,煮等有限的几种;
  3. “调料层”是放油,盐,辣椒,香菜等等。

分了层,几十种菜就变成可以掌控的几组选择的组合。不管什么菜的肉都放在冷冻箱里,不管什么菜都用有限的几种锅子就做得出来,不管什么菜都是一样的几种辣椒。分了层,就把复杂的东西简化了。好的厨师不是宣布我为了简化只做三种菜,也不会因为几十种菜而需要1000平米的厨房来存货,而是通过分层化繁为简,再由简至繁。

别跟我说复杂,说恶心。线团不缠在线轴上当然复杂,像猫一样在乱麻里面搅和当然很复杂。

第二就是抽象。

数据结构就那几种经典的,设计模式也这么多年没有发现新的了,控制逻辑更是几乎从代码生成到现在无外乎一只手数得过来的。如何在纷繁的世界里面看到后面的逻辑,从Listing页面看到后面可以抽象成collection,复杂的关系抽象出“图”,把相互关联抽象成“边”,把看似毫不相关的东西抽象成一样,把看起来几乎一模一样的东西看透必须是不同的类来表示,这些都是抽象能力。

不努力去抽象,就会平庸的大段拷贝粘贴代码,就只会顺序执行,再加一点 if { } else { },只会字符串拼接而形成HTML,只会无休止的写代码,就只能自己干体力活。不会写循环的程序员小明才会熬夜写:

print(“1”);

print(“2”);

print(“3”);

 print(“100”);

一行一行的写,写呀。。写呀。。写呀。。。写呀。。。写呀。。。!!!一边写还在抱怨:“为什么活儿真他妈的多,我真他妈的苦。”写出来的东西还老多的bug,修bug的时候还不服气:“要不是有这些bug拦着我,我早就写到1000了。。。” 实在是不动脑子加嘴硬的典型代表。

但想想,会了循环和用函数封装,你就比小明高级很多了吗?

最后是迭代。

文章是一点点改出来的,不是写一遍再重写一遍的,不要期待啥时候一个来一个新架构,新框架就能解决问题。前后端分离不是专门的工作,是一种思想,需要立刻操练起来,从自己的每一行新代码开始。

推倒重建在任何领域都不是好主意。因为推倒重建是一种习惯。如果解决问题的办法是大规模重建,在三个月后建成必然会有更多的理由再次推倒建成的,因为这是一种习惯。

也不要等待。程序员不能等待,因为程序是分层的,是可改动的,是可以在一层很乱的情况下封装好把上层做好,之后再更改下层的。工程中的脚手架在代码世界可以用得天衣无缝。必须学会在垃圾堆里建设一个茅屋,在茅屋堆里建大楼。因为除此以外的情形,是不现实的,是追求不到的。

程序会呼吸的。会变化的,会一点点的变好的。看看佛罗伦萨的那些古建筑,450年来,一些建筑里面从泥巴已经变成了不锈钢了,或者表面已经加了防氧化膜了,那个建筑已经不是那个建筑了,却依然美丽。你推倒重建一个大教堂就牛了吗?保持表面不变换结构,或者保持里面不变换外观,土木工程师在现实世界都能做得出来,代码这种思想的东西难道做不出来?

分层,抽象,迭代,就是这些。

希望大家好好看看程序,在自己能心平气和的写出自己觉得漂亮的程序之前别跟别人说自己是程序员了。

提正确的问题,用聪明的办法解决

刚才我们一起过了一下付费,抱歉,我又非常气愤。气愤在于大家的智慧没有发挥,而在一个乱麻中间搅和,完全是在浪费生命。我期望百姓网的程序员都是Hacker,如下是我的期望:

1. 要有追求。

程序员是非常神圣的职业,拥有和建筑师,作家,画家一样的魔力,可以构建一个不存在的世界,而比起那些职业,程序员的工具更多,世界更加绚丽。大家要有追求,成为一名hacker。Hacker的定义是非常聪明的,能够创造世界的程序员。Hacker绝不会有祥林嫂一样的被动的,只知道抱怨的倾向。Hacker会不惜一起代价解决一切问题,没有的回去写,不会的要去学,会像福尔摩斯一样拿到一个线索追问下去直到解决。这就是hacker喜欢开源的原因。我们所有的问题都可以找到根源解决。今天关于置顶的讨论,一个如此简单,4个小时应该就完美解决的东西,被搞成几个人几个月还纠缠不清的一个漩涡,就是因为不敢破,不敢去看搜索,不敢越界,把没有的界限当作自己的界限。Hacker会打破沙锅问到底,Hacker会创造。好的Hacker不会忍受空调过冷而没有行动,更何况是代码这个纯思想的世界。

2. 要问正确的问题。

问正确的问题比解决问题更重要。今天我看到大家问的问题都是如何在Ad上打标签,如何补一个有一个漏洞的问题。我问大家为什么需要在这里纪录,大家说是因为另一个设计。但有没有问如果不是这个设计会是怎样?可能会需要解决的问题更多,或者会更少。但不敢去质疑设计,把自己捆在一个地方,让我感觉到大家在思想的世界里面走动的速度好似一个80岁的老头在现实社会走动的速度,半年过去了还没有走出自己的院子。

3. 要聪明的解决。

大家都是聪明人。问问自己,你的解决办法聪明吗?我们不提代码的事情。代码是思考的一种记录而已。聪明,不是脑子好不好用,而是你是不是真的思考过了。什么叫思考过了?如果对于一个问题,你没有进入过面部没有表情,目光呆滞,梦游一样的在办公室里面踱步的状态,我真不觉得你曾经思考过。思考需要象拼图一样,一些清楚了,先放在那里不要动,去看另外一块,然后再半个小时以后把那个想清楚了,再和这一块拼起来(所以最好我还记得那一块,这就要求没有打断)这种快感是Hacker解决问题的方法。现在的做法不聪明。我看到了苦力的影子。我看到了码农在工作,没有看到思想。代码里面没有思想。告诉大家一个非常简单的判断依据:以百姓网现在的代码复杂度,如果你的大多数函数都超过7行,八成你从来没有思考过问题。

我对于百姓网的程序员抱有极大的期望,现在的代码让我及其失望。我愿意和大家一起花时间来理。

最后加一句:好的程序员需要大量的时间才能磨练出来,需要刻苦。我和小排有一个有趣的讨论,小排说,关于Graph API,我周末花了7个小时,为什么下层还没有理清楚,而你却把上层全写好了?我说:我周末写了8遍,40个小时。

就这么简单。

我思考的百姓网类目用户模型

我把用户分类三大类,并使用如下态度

* 坚决保护熊猫用户

* 允许核心用户发展

* 收费限制污染用户

(骗子违法坚决打击,不在用户模型里面)

熊猫用户是我们想要的用户。

* 在二手里面,就是哪些处理东西的宅男,卖宝宝东西的妈妈等等;
* 在二手车里面,卖自家二手车的车主;
* 在工作类目,直招的50人以下的小企业;
* 在房屋类目,房东直接租房,卖房的用户;

实在找不到一个更好名字,来表达,姑且用熊猫来代指。他们是相对弱小的群体。

在未来,我们有可能会为了收入等压力转变我们专注的重点,我们现在就要想好去除这种可能性。

这些本地的,个人化,社区化的熊猫用户是我们的根基,服务他们是我们建立百姓网的原因。我们需要尽一切我们可能去保护他们,让他们享受到我们能够提供的最好的服务。这包括:

* 用户产品以这些用户为原型,为这些用户优化;
* 市场上把这些用户作为目标用户,获取和激活这样的用户;
* 销售原则上不需要打扰他们,通过在线自助完成;

另外一类是污染用户。这部分用户是会威胁到其他用户生存的那种类型。

* 在二手里面,就像回收,全国卖山寨电脑等商家意味非常浓的商家;
* 在二手车里面,是高危的黄牛(??需要确认)
* 在工作里面,是职介,这类高危
对于这部分用户,哪怕他们全都消失,我们问题不大(但没必要有洁癖和人家作战);他们如果过于繁荣,其他用户的生活空间将被污染。对于他们,我们将进行限制,并且大胆的,大力的收费,通过收费控制污染。

中间的核心用户层是仔细考虑过的。我们必须在清晰的内外两圈内设置足够大的一个缓冲区间,以避免非此即彼;如果没有这个区,就会出现只要确定不是我们要的熊猫,就一定污染这样的问题。核心用户是生态系统中必然存在的。我们不为他们优化,但必须允许他们生存。

* 二手车里面,他们是车商
* 工作里面,他们是中大型企业,连锁企业,派遣公司
* 房屋里面,他们是中介
对于核心用户,我们的态度是“允许核心用户发展”,但一定不是“专注核心用户”。我们所有的优化,应该以熊猫用户为主。

我们在用户和listing层面,不再做角色划分,不分为“个人,商家”,或者按入上三者分层。拿出一个用户辩论到底是三种情况的哪一种是没有意义的。我们实施的方法是按照每一类用户的喜好做产品,做市场,设计规则。比如按照熊猫用户的使用来限制总发帖数让他们正好很好用。就好像我们只管扔竹子,而不用区分下面的是狼还是熊猫。

这个层次对于各个组织的影响:

* 战略组:断分析市场情况,确认我们的三层各是哪些人,确认我们战略正确
* 市场组:获取和激活熊猫用户;吸引核心用户;忽略污染用户
* 产品组:为熊猫用户做产品
* 营收组:对污染用户重度收费;对于核心用户收费;对于熊猫用户,自助收费

为什么大家都在加功能

小排问了我一个问题,为什么各个创业公司的产品都要拼命加功能。我当时还没有特别好的回答这个问题。现在我有了更完整的答案。
说到功能,我们先要从技术开始。技术就是做事情的方法。如果你找到了一种比大多数人更好地做事情的方法,你就有了更先进的社会生产力。比如1200年的佛罗伦萨,它的财富就是由发明了一整套的先进的纺织机开始的,作为一个城市,他们比欧洲全球任何国家都能够更便宜的织出更好的布;1500年的荷兰,开始仅仅因为发明一个小刀可以一刀切的剖开鲱鱼的肚子,去除内脏并且直接放到盐里保存;之后他们又发明了肚子大,甲板小,不带火炮的专用商船,把运输成本降低到英国人的一半,成为海上马车夫;更不要说1700年以后英国的以蒸汽机为代表的工业革命,以及以电气为代表的第二次工业革命,以及发端于美国的以计算机信息技术为代表的第三次工业革命。简而言之,科技不断发展,生产率逐渐提高,就是过去发生的事情。

但问题时,技术的前沿移动得非常快,非常非常快。在过去曾经让自己占据先机得技术,很快就会成为社会的平均生产力。现在有一台蒸汽机,或者大肚子商船仅仅是复古,而不是科技得象征。科技不断向前飞奔,这就要就大家都要努力向前跑,不断寻找现在最难的问题,应用最广泛的问题,去解决它。这个竞赛中,跑在最前面得一定是创业公司,不是因为他们小,是因为他们快。

在互联网领域,技术的前进更加明显。越来越多的高科技在几年里面就民用,现在一个iPhone的技术能力和存储空间几乎是互联网开始时候的一台服务器,以前公司起家的核心的技术,非常快的变成大家都能用的东西,比如搜索,比如数据库,比如BI,比如前端框架。

以存储为例。原来有一个数据库(FoxBase啥的),先进得不得了了,现在普通的MySQL,NoSQL存储已经司空见惯,连上T的存储都易如反掌了,我们必须努力去解决更难的问题,无论是更大还是更快,或者更方便。以分类为例。

作为中国第一家,建一个网站,让大家可以在网上自己交易已经远不是什么新的生产力了,大数据量的时候保证信息质量,同时又可以最简单的发布,这是难题,需要解决;我们不断的面临以前从来没有人解决过的问题。不持续解决这个问题,其实就是把科技前沿让出来给别人解决。

技术的前进,就是做事情的方法的提高是必然的,而这种必然常常以功能表现出来。有大量的提高时没有界面的功能,比如Google的搜索,百姓网的骗子比例减少,的;还有大量的更好的做事情的方法是有界面的功能,比如按地域产照等等。加功能后面,必须是更好的做法来给用户他们要的东西。

理解这点,我们需要做到:1)挑难的做。有两件事情可以做,一件相对容易,对用户的帮助也小一些;一件相对难很多,对用户的帮助也大很多。我们一般情况下应该挑更难的。难的常常就是技术发展的地方。2)加没界面的功能也是加功能。3)从这个角度来说,的确我们需要不断的添加功能。创业公司如果不往前冲,很快会远离生产力最高的前沿,离开了这个阵地,创业公司就没有什么活路了。毕竟,创业公司有些象荷兰的商船,或者动物界的蚊子,是放弃了所有的武装,为了更快的速度而选择没有任何自卫能力,如果速度也没有了,就什么也没有了。