<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>彦路的博客</title>
	<atom:link href="http://zyanlu.com/feed" rel="self" type="application/rss+xml" />
	<link>http://zyanlu.com</link>
	<description>Mobile Web Dev</description>
	<lastBuildDate>Thu, 26 Apr 2012 03:53:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>rm -rf 大悲剧！</title>
		<link>http://zyanlu.com/p/274</link>
		<comments>http://zyanlu.com/p/274#comments</comments>
		<pubDate>Thu, 26 Apr 2012 03:53:10 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[没用的]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=274</guid>
		<description><![CDATA[今天手欠本来想 rm -rf _* 结果敲成了 rm -rf _[空格]* 小半天的代码没有了。。。 以后必须 sudo apt-get install trash-cli alias rm=&#8217;trash&#8217; 啊啊啊啊啊啊]]></description>
			<content:encoded><![CDATA[<p>今天手欠本来想 rm -rf  _* 结果敲成了 rm -rf  _[空格]*  小半天的代码没有了。。。</p>
<p>以后必须<br />
sudo apt-get install trash-cli<br />
alias rm=&#8217;trash&#8217;</p>
<p>啊啊啊啊啊啊</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/274/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>twisted  +  thrift  +  php client</title>
		<link>http://zyanlu.com/p/266</link>
		<comments>http://zyanlu.com/p/266#comments</comments>
		<pubDate>Wed, 21 Mar 2012 10:40:58 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[没用的]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=266</guid>
		<description><![CDATA[首先安装twisted 跟 thrift ，这个官方都有文档，注意先装依赖关系就行了 奇怪的是我的thrift-ruby 死活编译不通过，还好我不用ruby,直接&#8211;without-ruby就好了 报这个错，不懂ruby，也google不到，烦请大侠们指点迷津： Making all in rb make[3]: Entering directory `/home/zyanlu/soft/thrift-0.8.0/lib/rb' /usr/local/bin/rake rake aborted! no such file to load -- spec/rake/spectask 装完以后还需要给语言装扩展，我这里是php做客户端 跟py.twisted通信，所以需要编译一下php扩展跟python扩展 php： cd thrift-0.8.0/lib/php/src/ext/thrift_protocol phpize ./configure --enable-thrift_protocol make make install 然后配置一下extension=thrift_protocol.so 就可以了 注意要使扩展起作用的话必须使用TBinaryProtocolAccelerated，这个官方tutorial例子里没有 python &#8230;<p class="read-more"><a href="http://zyanlu.com/p/266">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>首先安装twisted 跟 thrift ，这个官方都有文档，注意先装依赖关系就行了</p>
<p>奇怪的是我的thrift-ruby 死活编译不通过，还好我不用ruby,直接&#8211;without-ruby就好了</p>
<p>报这个错，不懂ruby，也google不到，烦请大侠们指点迷津：</p>
<pre class="brush:shell">Making all in rb
make[3]: Entering directory `/home/zyanlu/soft/thrift-0.8.0/lib/rb'
/usr/local/bin/rake
rake aborted!
no such file to load -- spec/rake/spectask</pre>
<p>装完以后还需要给语言装扩展，我这里是php做客户端 跟py.twisted通信，所以需要编译一下php扩展跟python扩展</p>
<p>php：</p>
<pre class="brush:shell">cd thrift-0.8.0/lib/php/src/ext/thrift_protocol
phpize
./configure --enable-thrift_protocol
make
make install</pre>
<p>然后配置一下extension=thrift_protocol.so 就可以了<br />
注意要使扩展起作用的话必须使用<span style="color: #ff0000;"><strong>TBinaryProtocolAccelerated，这个官方tutorial例子里没有</strong></span></p>
<p>python 装就比较简单了，直接就好使</p>
<pre class="brush:shell">cd thrift-0.8.0/lib/py
py setup.py build
py setup.py install</pre>
<p>现在我们来跑一个demo来看看，python的官网tutorial里直接可以跑通</p>
<pre class="brush:shell">cd thrift-0.8.0/tutorial
thrift -r --gen py tutorial.thrift
thrift -r --gen py:twisted tutorial.thrift
thrift -r --gen php tutorial.thrift</pre>
<p>turial里的PhpClient.php 不能直接运行成功，是include的路径不对(看一下源码跟生成的代码就行了)<br />
把php-gen/* 拷贝到 thrift-0.8.0/lib/php/src/packages</p>
<p>帖一下我的PhpClient.php</p>
<pre class="brush:php">$GLOBALS['THRIFT_ROOT'] = '../../lib/php/src';

require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
#require_once $GLOBALS['THRIFT_ROOT'].'/transport/THttpClient.php';
#require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
require_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php';

/**
 * Suppress errors in here, which happen because we have not installed into
 * $GLOBALS['THRIFT_ROOT'].'/packages/tutorial' like we are supposed to!
 *
 * Normally we would only have to include Calculator.php which would properly
 * include the other files from their packages/ folder locations, but we
 * include everything here due to the bogus path setup.
 */
// error_reporting(0);
$GEN_DIR = $GLOBALS['THRIFT_ROOT'].'/packages';
require_once $GEN_DIR.'/shared/SharedService.php';
require_once $GEN_DIR.'/shared/shared_types.php';
require_once $GEN_DIR.'/tutorial/Calculator.php';
require_once $GEN_DIR.'/tutorial/tutorial_types.php';
error_reporting(E_ALL);

//try {
  if (array_search('--http', $argv)) {
    $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php');
  } else {
    $socket = new TSocket('localhost', 9090);
    $socket-&gt;setRecvTimeout(2000);
  }
  $transport = new TFramedTransport($socket);
  $protocol = new TBinaryProtocolAccelerated($transport);
  $client = new tutorial_CalculatorClient($protocol);

  $transport-&gt;open();

  $client-&gt;ping();
  print "ping()\n";

  $sum = $client-&gt;add(1,1);
  print "1+1=$sum\n";

  $work = new tutorial_Work();

  $work-&gt;op = Operation::DIVIDE;
  $work-&gt;num1 = 1;
  $work-&gt;num2 = 0;

  try {
    $client-&gt;calculate(1, $work);
    print "Whoa! We can divide by zero?\n";
  } catch (tutorial_InvalidOperation $io) {
    print "InvalidOperation: $io-&gt;why\n";
  }

  $work-&gt;op = Operation::SUBTRACT;
  $work-&gt;num1 = 15;
  $work-&gt;num2 = 10;
  $diff = $client-&gt;calculate(1, $work);
  print "15-10=$diff\n";

  $log = $client-&gt;getStruct(1);
  print "Log: $log-&gt;value\n";

  $transport-&gt;close();</pre>
<p>大功告成，后续测试一下性能是不是有宣传的那么给力</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/266/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ubuntu server dev setup</title>
		<link>http://zyanlu.com/p/236</link>
		<comments>http://zyanlu.com/p/236#comments</comments>
		<pubDate>Thu, 08 Mar 2012 09:31:53 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[没用的]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=236</guid>
		<description><![CDATA[ubuntu server的好处是体积小，很快就能下好装上，但是开发常用的包都木有。(我是os x里弄了个linux vm来开发⋯ air的硬盘太小了&#8230;) 以下列表，不断更新中⋯⋯ apt-get install zlib1g-dev apt-get install gcc apt-get install dpkg-dev apt-get install libssl-dev apt-get install libxml2-dev apt-get install libxslt-dev apt-get install ntp apt-get install libpcre3 libpcre3-dev apt-get install libreadline5-dev apt-get install exuberant-ctags apt-get install mysql-client &#8230;<p class="read-more"><a href="http://zyanlu.com/p/236">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>ubuntu server的好处是体积小，很快就能下好装上，但是开发常用的包都木有。(我是os x里弄了个linux vm来开发⋯ air的硬盘太小了&#8230;)</p>
<p>以下列表，不断更新中⋯⋯</p>
<pre class="brush:shell">apt-get install zlib1g-dev
apt-get install gcc
apt-get install dpkg-dev
apt-get install libssl-dev
apt-get install libxml2-dev
apt-get install libxslt-dev
apt-get install ntp
apt-get install libpcre3 libpcre3-dev
apt-get install libreadline5-dev
apt-get install exuberant-ctags
apt-get install mysql-client libmysqlclient-dev
apt-get install libbz2-dev
apt-get install zlib1g-dev
apt-get install libjpeg62-dev
apt-get install libfreetype6-dev
apt-get install liblcms1-dev
apt-get install libcurl3-dev
</pre>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/236/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java 小陷阱</title>
		<link>http://zyanlu.com/p/262</link>
		<comments>http://zyanlu.com/p/262#comments</comments>
		<pubDate>Sat, 28 Jan 2012 08:42:54 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[没用的]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=262</guid>
		<description><![CDATA[下面这段小程序是否输出true呢？ public long countRectangles(int width, int height){ long x = (width*(width+1)/2) * (height*(height+1)/2); long a1 = (width*(width+1)/2); long a2 = (height*(height+1)/2); System.out.println(x == (a1*a2)); } public static void main(String[] args) { new RectangularGrid().countRectangles(592, 964); } 结果坑爹了，打印出来x只有38960016，一看就是溢出了⋯ 问题就在于 long = int*int的效果等同于long &#8230;<p class="read-more"><a href="http://zyanlu.com/p/262">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>下面这段小程序是否输出true呢？</p>
<pre class="brush:java">
public long countRectangles(int width, int height){
		long x = (width*(width+1)/2)
				* (height*(height+1)/2);
		long a1 = (width*(width+1)/2);
		long a2 = (height*(height+1)/2);
		System.out.println(x == (a1*a2));
}
public static void main(String[] args) {
		new RectangularGrid().countRectangles(592, 964);
	}
</pre>
<p>结果坑爹了，打印出来x只有38960016，一看就是溢出了⋯<br />
问题就在于 long = int*int的效果等同于long = (long)(int*int)<br />
int*int返回值仍旧是int，所以修改成为long = (long)int*(long)int 就可以了。<br />
这个其实是个很基础的问题，但是有时候敲代码一不留神还是很容易写错。</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/262/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sqlalchemy utf8 quickstart</title>
		<link>http://zyanlu.com/p/260</link>
		<comments>http://zyanlu.com/p/260#comments</comments>
		<pubDate>Wed, 25 Jan 2012 18:04:17 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[没用的]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=260</guid>
		<description><![CDATA[先把mysql全都配成utf8,比较坑爹的是table charset貌似没法指定默认utf-8,必须create的时候指定 [client] default-character-set=utf8 [mysqld] collation-server = utf8_general_ci character-set-server = utf8 验证一下: SHOW VARIABLES LIKE ‘character_set_%’; SHOW VARIABLES LIKE ‘collation_%’; # -*- coding: utf-8 -*- import sqlalchemy from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, BigInteger,String,Text from sqlalchemy.orm import &#8230;<p class="read-more"><a href="http://zyanlu.com/p/260">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>先把mysql全都配成utf8,比较坑爹的是table charset貌似没法指定默认utf-8,必须create的时候指定</p>
<pre class="brush:plain">[client]
default-character-set=utf8
[mysqld]
collation-server = utf8_general_ci
character-set-server = utf8</pre>
<p>验证一下:</p>
<pre class="brush:plain">SHOW VARIABLES LIKE ‘character_set_%’;
SHOW VARIABLES LIKE ‘collation_%’;</pre>
<pre class="brush:py"># -*- coding: utf-8 -*-
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, BigInteger,String,Text
from sqlalchemy.orm import sessionmaker

Base = declarative_base()
class Node(Base):
    __tablename__ = 'node'
    __table_args__ = {'mysql_engine':'InnoDB','mysql_charset':'utf8'}
    id = Column(Integer, primary_key=True)
    path = Column(String(255), index=True)
    name = Column(String(255))
    data = Column(Text)
    datatype = Column(String(255))

if __name__ == '__main__':
    engine = sqlalchemy.create_engine('mysql+mysqldb://root:123456@127.0.0.1:3306/dbname?charset=utf8', echo=True)

    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine) 

    Session = sessionmaker()
    Session.configure(bind=engine)
    session = Session()
    session.commit()

    n = Node()
    n.path = "/"
    n.name = "汉字"

    session.add(n)
    session.commit()</pre>
<p><span style="color: #ff0000;">__table_args__</span>指定了表编码，这样就可以很好支持中文了⋯ 如果有能在mysql配置里指定编码的方法请留言⋯</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/260/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nginx配置geoip</title>
		<link>http://zyanlu.com/p/246</link>
		<comments>http://zyanlu.com/p/246#comments</comments>
		<pubDate>Sun, 15 Jan 2012 07:20:41 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[写码]]></category>
		<category><![CDATA[geoip]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=246</guid>
		<description><![CDATA[按照http://wiki.nginx.org/HttpGeoIPModule就可以了 有一个坑，就是 http { geoip_country /path/to/GeoIP.dat; #这里一定要写绝对路径 geoip_city /path/to/GeoLiteCity.dat; 查了一下手册，好像没有$nginx_home这样的变量，所以需要写死?.. 总结一下： 1.先安装依赖libgeoip-dev 2.去下载需要的ip库http://geolite.maxmind.com/download/geoip/database/ 3.重新编译nginx 4.修改nginx配置]]></description>
			<content:encoded><![CDATA[<p>按照<a href="http://wiki.nginx.org/HttpGeoIPModule" title="http://wiki.nginx.org/HttpGeoIPModule">http://wiki.nginx.org/HttpGeoIPModule</a>就可以了</p>
<p>有一个坑，就是</p>
<blockquote><p>http {<br />
geoip_country /path/to/GeoIP.dat; <span style="color: #ff0000;">#这里一定要写绝对路径</span><br />
geoip_city /path/to/GeoLiteCity.dat;</p></blockquote>
<p>查了一下手册，好像没有$nginx_home这样的变量，所以需要写死?..</p>
<p>总结一下：<br />
1.先安装依赖libgeoip-dev<br />
2.去下载需要的ip库http://geolite.maxmind.com/download/geoip/database/<br />
3.重新编译nginx<br />
4.修改nginx配置</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/246/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>python读取arc文件的小脚本</title>
		<link>http://zyanlu.com/p/230</link>
		<comments>http://zyanlu.com/p/230#comments</comments>
		<pubDate>Sun, 01 Jan 2012 06:25:56 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[写码]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=230</guid>
		<description><![CDATA[import gzip,re file = "/arcs/some.arc.gz" ARC_PATTERN = re.compile("(^.*:[^ ]*)\\s([0-9.]+)\\s(\\d+)\\s(\\S+)\\s(\\d+)$") def readchunk(fp): meta = ARC_PATTERN.match(fp.readline()).groups() page = fp.read(long(meta[4])+1) return (meta,page) def main(): f = gzip.open(file,'rb') print readchunk(f) print readchunk(f) if __name__ == '__main__': main() windows下注意加rb，不然会坑。]]></description>
			<content:encoded><![CDATA[<pre class="brush:py">import gzip,re

file = "/arcs/some.arc.gz"

ARC_PATTERN = re.compile("(^.*:[^ ]*)\\s([0-9.]+)\\s(\\d+)\\s(\\S+)\\s(\\d+)$")

def readchunk(fp):
    meta = ARC_PATTERN.match(fp.readline()).groups()
    page = fp.read(long(meta[4])+1)
    return (meta,page)

def main():
    f = gzip.open(file,'rb')
    print readchunk(f)
    print readchunk(f)

if __name__ == '__main__':
    main()</pre>
<p>windows下注意加rb，不然会坑。</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/230/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个管理ssh tunnel的小脚本</title>
		<link>http://zyanlu.com/p/226</link>
		<comments>http://zyanlu.com/p/226#comments</comments>
		<pubDate>Sat, 31 Dec 2011 04:27:27 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[tip]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=226</guid>
		<description><![CDATA[首先在本机跟远程服务器建立信任关系，可以使用这个小脚本。 然后使用这个小脚本来管理ssh tunnel，都放在$HOME/bin下。 用法： tunnel on tunnel off 在mac下可以使用脚本来管理链接,这样就不用鼠标去点设置->无线.. alias sock='networksetup -setsocksfirewallproxystate Wi-Fi' sock on sock off 两个脚本配合起来使用还是很方便的。]]></description>
			<content:encoded><![CDATA[<p>首先在本机跟远程服务器建立信任关系，可以使用<a href="http://zyanlu.com/bin/make-ssh">这个</a>小脚本。</p>
<p>然后使用<a href="http://zyanlu.com/bin/tunnel">这个</a>小脚本来管理ssh tunnel，都放在$HOME/bin下。</p>
<p>用法：</p>
<pre class="brush:shell">tunnel on
tunnel off</pre>
<p>在mac下可以使用脚本来管理链接,这样就不用鼠标去点设置->无线..</p>
<pre class="brush:shell">alias sock='networksetup -setsocksfirewallproxystate Wi-Fi'
sock on
sock off
</pre>
<p>两个脚本配合起来使用还是很方便的。</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/226/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>中国特色之APNs connection reset</title>
		<link>http://zyanlu.com/p/214</link>
		<comments>http://zyanlu.com/p/214#comments</comments>
		<pubDate>Sat, 24 Dec 2011 18:29:47 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[写码]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=214</guid>
		<description><![CDATA[最近在捣鼓 iPhone Push Notification 基本上就是TLS连一下APNs，但是鉴于TLS连接会受到随机阻断（goo.gl/KCMR8），消息将很难确保一定成功发送。 当APNs收到一条它认为有误的信息时就会立即断开连接，并且放弃后续的所有消息，同时会返回一条消息告诉Povider哪条消息有误。因此我们需要有一个错误恢复机制。 但是在一个TLS连接随时可能被切断的情况下，我们还需要不断恢复TLS连接。如果这时恰好有错误发生，那么我们将无法从APNs获取错误信息，因此也无法进行错误恢复，一部分消息将丢失。实际测试中差不多发送几十到几百条消息时，就会被reset一次，频率还是很高的。 有趣的是我将代码部署到海外服务器的时候，完全没有影响，消息发送速度也要高很多。 解决办法？ 如果有条件的话，使用海外服务器来进行你的消息推送， Amazon EC2就是一个不错的选择。结合ssh -D -N，你懂的。 如果没有条件，那么我建议将发送窗口调小点，比如发送100条消息就关闭当前连接，重新与APNs建立连接。这样消息丢失的损失就可以控制在100条以内。当然这么做苹果会很不高兴，苹果官方推荐在一个链接里面尽可能多发送消息以节省资源。 &#160;]]></description>
			<content:encoded><![CDATA[<p>最近在捣鼓 iPhone Push Notification</p>
<p>基本上就是TLS连一下APNs，但是鉴于TLS连接会受到随机阻断（<a title="goo.gl/KCMR8" href="http://goo.gl/KCMR8">goo.gl/KCMR8</a>），消息将很难确保一定成功发送。</p>
<p>当APNs收到一条它认为有误的信息时就会立即断开连接，并且放弃后续的所有消息，同时会返回一条消息告诉Povider哪条消息有误。因此我们需要有一个错误恢复机制。</p>
<p>但是在一个TLS连接随时可能被切断的情况下，我们还需要不断恢复TLS连接。如果这时恰好有错误发生，那么我们将无法从APNs获取错误信息，因此也无法进行错误恢复，一部分消息将丢失。实际测试中差不多发送几十到几百条消息时，就会被reset一次，频率还是很高的。</p>
<p>有趣的是我将代码部署到海外服务器的时候，完全没有影响，消息发送速度也要高很多。</p>
<p>解决办法？</p>
<p>如果有条件的话，使用海外服务器来进行你的消息推送， Amazon EC2就是一个不错的选择。结合ssh -D -N，你懂的。</p>
<p>如果没有条件，那么我建议将发送窗口调小点，比如发送100条消息就关闭当前连接，重新与APNs建立连接。这样消息丢失的损失就可以控制在100条以内。当然这么做苹果会很不高兴，苹果官方推荐在一个链接里面尽可能多发送消息以节省资源。</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/214/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>入度与出度</title>
		<link>http://zyanlu.com/p/208</link>
		<comments>http://zyanlu.com/p/208#comments</comments>
		<pubDate>Tue, 20 Dec 2011 14:07:51 +0000</pubDate>
		<dc:creator>zyanlu</dc:creator>
				<category><![CDATA[写码]]></category>

		<guid isPermaLink="false">http://zyanlu.com/?p=208</guid>
		<description><![CDATA[前几日QA同学给我们讲代码可测性，提到了一个很好的概念：代码的入度与出度。 入度就是说其他模块调用你的模块的次数，出度就是说你的当前模块调用其他模块的次数。 -&#62;  入度 -&#62;  &#124; Module &#124;  -&#62; 出度 -&#62; 简单来说，就是可测性好的模块一定是入度更大，为别的模块提供了丰富的功能，而又很少依赖其他模块。 我们把模块级别拓展到服务级别，这个道理也是一样的。 好的服务一定是提供的丰富的功能及接口，而又没有太复杂的关联关系及服务依赖。 同理，上升到业务级别的时候，如果你的入度更大，很有可能就属于所谓 “核心业务” 那部分。就以amazon云服务为例，amazon把自己的“核心业务”做成公有服务拿出来卖：虚拟化、存储、计算、网络服务，更上层的有消息服务，支付服务等等。 看起来好像这些东西在一个大一点的公司应该都有，前几日的g+上的 “google 工程师大吐槽” 大致的意思就是amazon有的我们都有，为啥人家弄得那么好都可以拿出来卖了而我们却是一团团？ amazon把自己的“核心业务”拿出来晒，在整个业内增加自己的入度，google自然看了着急啊。 代码总是人写的，当具体到一个工程师的时候，这个法则似乎也适用。很多工程师都觉得每天忙到累到不行行，但是却感觉没什么收获，别人对自己的评价也不高呢？为什么只剩苦劳没有功劳呢？ 回顾一下自己做的工作，是入度更大，还是出度更大？ 那些出度更大的工程师，通常需要经常与各种人沟通，寻求各种帮助，约定各种接口，这通常是一个极消耗精力的过程 &#8212;- 比如面对各种异构系统解决自己的问题。 这时候就需要反思了，如何才能增加自己的入度，给别人提供服务？ 或许从每一行代码就可以开始增加自己的入度吧： 我的代码是不是可以复用的？ 我写的模块是不是可以作为公共库使用？ 我目前的业务线是否可以做成公共服务供别人很方便地调用？ 我的业务经验是不是可以share的，哪些是对别人有价值的？ &#8230;. 顺着这个思路，我相信你一定能成为“高入度”的NB工程师。]]></description>
			<content:encoded><![CDATA[<p>前几日QA同学给我们讲代码可测性，提到了一个很好的概念：代码的入度与出度。</p>
<p>入度就是说其他模块调用你的模块的次数，出度就是说你的当前模块调用其他模块的次数。</p>
<blockquote><p>-&gt;  入度 -&gt;  | Module |  -&gt; 出度 -&gt;</p></blockquote>
<p>简单来说，就是可测性好的模块一定是入度更大，为别的模块提供了丰富的功能，而又很少依赖其他模块。</p>
<p>我们把模块级别拓展到服务级别，这个道理也是一样的。 好的服务一定是提供的丰富的功能及接口，而又没有太复杂的关联关系及服务依赖。</p>
<p>同理，上升到业务级别的时候，如果你的入度更大，很有可能就属于所谓 “核心业务” 那部分。就以amazon云服务为例，amazon把自己的“核心业务”做成公有服务拿出来卖：虚拟化、存储、计算、网络服务，更上层的有消息服务，支付服务等等。 看起来好像这些东西在一个大一点的公司应该都有，前几日的g+上的 “<a href="http://coolshell.cn/articles/5701.html">google 工程师大吐槽</a>” 大致的意思就是amazon有的我们都有，为啥人家弄得那么好都可以拿出来卖了而我们却是一团团？</p>
<p>amazon把自己的“核心业务”拿出来晒，在整个业内增加自己的入度，google自然看了着急啊。</p>
<p>代码总是人写的，当具体到一个工程师的时候，这个法则似乎也适用。很多工程师都觉得每天忙到累到不行行，但是却感觉没什么收获，别人对自己的评价也不高呢？为什么只剩苦劳没有功劳呢？</p>
<p>回顾一下自己做的工作，是入度更大，还是出度更大？</p>
<p>那些出度更大的工程师，通常需要经常与各种人沟通，寻求各种帮助，约定各种接口，这通常是一个极消耗精力的过程 &#8212;- 比如面对各种异构系统解决自己的问题。</p>
<p>这时候就需要反思了，如何才能增加自己的入度，给别人提供服务？</p>
<p>或许从每一行代码就可以开始增加自己的入度吧：</p>
<p>我的代码是不是可以复用的？</p>
<p>我写的模块是不是可以作为公共库使用？</p>
<p>我目前的业务线是否可以做成公共服务供别人很方便地调用？</p>
<p>我的业务经验是不是可以share的，哪些是对别人有价值的？</p>
<p>&#8230;.</p>
<p>顺着这个思路，我相信你一定能成为“高入度”的NB工程师。</p>
]]></content:encoded>
			<wfw:commentRss>http://zyanlu.com/p/208/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

