<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="css/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>栀子博客-栀子花驿站 </title><link>http://www.zhizihua.com/blog/</link><description>天天天蓝</description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>栀子花驿站 zhizihua.com . Some Rights Reserved.陕ICP备11009591号</copyright><pubDate>Thu, 17 May 2012 23:21:26 +0800</pubDate><item><title>选择产品经理--写在开始的话</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/选择产品经理--写在开始的话.html</link><pubDate>Thu, 17 May 2012 23:19:29 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/选择产品经理--写在开始的话.html</guid><description><![CDATA[<p>追溯起来是约三四年前的光景，&ldquo;产品经理&rdquo;成为一个似乎从石头里面蹦出的职业，对应届生相对不菲的薪酬，以及貌似可从此开始走上互联网大佬们成功轨 迹的诱人前景，刺激着不少80后的眼球与肾上腺素飞蛾扑火般进入，既而诸如 &ldquo;用户体验&rdquo;&rdquo;数据分析&ldquo; 等专业活计也成为了显学。</p><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对这一新兴的职业，一直以来缺乏系统性和全面性的&nbsp; 职业指南，大佬们的半PR性质读物/讲座 过于煽情且由于大多不是产品出道，可借鉴性欠奉。个别 本身在这一行当中就极为资浅的&rdquo;入门级选手&ldquo;自我pr的博客以及对应的出版物，更是有误人子弟的嫌疑。</div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本博的几位损友，恰逢其时，或从高薪的外企技术工作中转型，或放弃欧洲顶尖咨询公司的丰厚合同，或从上一次创 业失败中寻找一个冬眠蛰伏的栖息地，不约而同的走上这个似乎光鲜而又语焉不详的新兴岗位，亲历作为奠基人与笃行者，构建华语互联网世界最大变现机器与最受 争议产品的艰辛与荣耀，体验这一看似阳光透明行业中，&rdquo;谁痛谁知道&ldquo;的公司政治与职场龌龊，导演以产品之力将一万年阿斗的三流搜索引擎重新拉入主流竞技场 的逆天改名之旅，亦俯首甘为孺子牛的扮演姚晨与驴  背后的那个真正的商业操盘手....在累计近10年的经历当口，何去何从，正彷徨在摸爬滚打之中，切肤的感受&rdquo;产品经理&ldquo;这个职位究竟能干什么，不能干什 么，凭什么吃饭，又为什么被骂娘。消失了不切实际的幻想和期待，积累了些许沉淀后的感受与顿悟，建此园地，将  对于互联网产品的趋势思索，产品经理的职业发展不成结构的给出一点闲言碎语，希望供同行交流斧正，更希望对于在正犹豫是否进入这一行十字路口的年轻人，能 给到一些实在的帮助，扶上马，送一程。</div><div style=""><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;丑话说在前，为了不让被个别被&nbsp;误导型大佬 和 不负责任的HR忽悠到而考虑入行的朋友浪费时间，先把这个职业 皇帝新衣下面的裸体，剥落开来：</div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q：&rdquo;产品经理&ldquo; 是真的 &rdquo;经理&ldquo; 么？&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A：不是，除非你说的&rdquo;经理&ldquo; 是 &rdquo;经常被修理&quot;的意思~ 本质上是个招徕求职者的噱头，好比多数公司的 &ldquo;销售经理&rdquo;其实是个底层小屁兵，所谓的&ldquo;管理培训生&rdquo;很多时候 越培训越生是一样的道理。</div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q：&ldquo;产品经理&rdquo;这行的钱景如何？<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A：中长线看其实一般，如果有 投行咨询的机会，或是靠谱央企，待遇层面可以秒杀 按照发展最顺利速度计算的优秀产品经理。</div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q：&ldquo;产品经理&rdquo;对于有一定的技术背景但协调沟通能力较强，希望发挥这方面特长，不从事单一技术工作...&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A：几年来面试经验来看，您要是这么说话，事情的大概真相是所谓的&ldquo;技术背景&rdquo;只是混来的一个文凭而已，真要你写几段靠谱的代码能要了你的命，是吧...？</div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q：&ldquo;产品经理&rdquo;靠谱么，职业稳定性怎么样？<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A：我见识的某top互联网公司，平均在职年限 2.x年...</div><div style="">&nbsp;</div><div style=""><div style="">&nbsp;&nbsp;&nbsp;Q：&ldquo;产品经理&rdquo;是不是最适合成为未来的ceo或者自己创业？&nbsp;<br />&nbsp;&nbsp;&nbsp;A：国内顶尖互联网公司掌门人中，产品出身的：零</div></div><div style="">&nbsp;</div><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q：&ldquo;产品经理&rdquo;这行当积累性如何？<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A：非常差，一方面因为是作为一个新兴职业其 技能要求和知识结构 都未标准化，招收此岗位的公司一般也没有或是刚刚建立针对性的培训体系，更何况不同公司，不同产品线领域的产品经理工作性质 可移植性并不强。</div><div style="">&nbsp;</div><p>&nbsp;</p><div style="">&nbsp;&nbsp;&nbsp;&nbsp;如果这一番唱衰之后，不怕死的你仍然希望一窥究竟，就请来吧...</div><p>&nbsp;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 选择产品经理，这后面其实是个问号。&nbsp;跨入产品经理（PM）这个行当四五年，看到不少同学美好地一拥而进，一两年后又看到他们的彷徨：看看当初做技 术或咨询的同学要不生活滋润，要不俨然已接近成功人士圈，真是又累又没成就感；PM苦逼啊，说话没人听，自己想搞点东西没技术也玩不转；做了两年，说出去 都学了啥！？</p><div style="">&nbsp;&nbsp;  &nbsp;&nbsp;仔细想想，也不奇怪，国内互联网，能活过两年的产品和网站有多少，又有多少最终能在用户的收藏夹和桌面站牢，可谓大江东去浪淘尽，每个默默无闻的产品 和功能后面都有几个PM悲催地站了青春的岗。这点上还不如开发人员（RD），他们的成就是建立在上线了多少代码，又尝试了几种新的架构上的。产品经理是个 高风险的职业，首先你得认识到这点。</div><div style=""><div style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;怎么降低风险，做个进则造福人类，退则独善其身的PM？几年浮沉下来，感觉有几点是越早想清楚越好：</div><div style=""><strong style="">是做PM还是RD？</strong></div><div style="">&nbsp;  &nbsp;&nbsp;是的，如果你是技术背景且刚刚上PM这条道，仍然要认真的考虑下这个问题。相对来说，RD的成长路线比较稳定，更重内修，跟准主流技术不断实践就成， 而PM不确定因素很多，产品的垮掉或者边缘化、部门的重组、主导权导致的人事倾轧（由于产品一般都是公司各种利益的焦点，这些问题产品部门要多得多）如此 等等随便一个都可能将你的苦心积累直接归零。</div><div style="">&nbsp; &nbsp;&nbsp;如果你是个比较骚动，对创业耿耿于怀的人，直接RD吧。你要知道，那些在微博上忽悠你或没在微博上忽悠你的大佬们前世都是个牛逼的RD，他们是已经CEO了才跟你来玩产品、玩理念的，你现在玩不起！&nbsp;</div><div style="">&nbsp; &nbsp;&nbsp;如果不死心，建议你看下纯银的<a style="" href="http://firecacada.blog.163.com/blog/static/707437620120129213548/" target="_blank">这篇文章</a>，我略带优越感地看完：呵呵，这种苦逼的项目，哥做过两三个了有没有！已经不做有多年！反正以后是坚决不沾了，要不就自己直接code。</div><div style="">&nbsp; &nbsp;&nbsp;如果你是对开发工作能接受，只是对做产品好奇且抱着美好想象的话，我只想说，珍惜生命，远离PM。我见过这样一个哥们，在BAT之一做产品，无比扭曲和纠结，最后沦为拿着产品的工资做技术活，终于幡然醒悟：犯不上啊！回头是岸，去外企做了个快乐的RD。</div><div style="">&nbsp; &nbsp; &nbsp;PM的工作属于那种思路明确、主动选择且内心坚强的人。这是前提，当然你还要有这个能力。只有他们才可能活得好，并有可能在高风险下获得高收益。</div><div style=""><strong style="">是否有足够强的感染力和影响力？</strong></div><div style="">&nbsp;  &nbsp;&nbsp;说到PM的能力，一般PM速成教程和心灵鸡汤文是这样教你的：你需要从用户的角度去考虑问题，需要逻辑分析能力，需要创新和宽广的视角。是的，这些都 需要。但最关键的一点是你能影响和鼓动人进而去推动事情！&ldquo;产品经理&rdquo;是个把你忽悠进来的名号，实际权力在各部门间屁都没有。PM有责任、有义务但没权 力，这就是这个工种的悲情之处！即使所谓产品主导型的部门和公司也一样，最典型就是：我延期你能怎么？我又bug了你能怎样？你要推广BD告诉你现在没资 源你能怎样？一番口舌之后，还是只能带着一张孙子般的笑脸去解决问题。</div><div style="">&nbsp; &nbsp; &nbsp;如果你影响力大，关系活络，这些问题可能少些。PM就一个脑子一张嘴，凭的都是别人的手。如果嘴巴说服不了，脑子指挥不了，做什么都别想。</div><div style=""><strong style="">是做用户产品还是商业产品？</strong></div><div style="">&nbsp; &nbsp;&nbsp;这是一个问题，不少人可能还没深入思考过这点，因为他已经被推到其中一条路并在走下去。</div>&nbsp; &nbsp; 选择哪个都没有问题，关键还是在你的背景和优势。简单的说，你沉迷网络、天天混社区、当过版主、甚至还泡到过个把网友，那么用户产品是不二选；如果脑袋转得快、逻辑思维严密是你的必杀、算术好，那么适合做商业产品。用户感性而商业理性。<div style="">&nbsp; &nbsp;&nbsp;用户产品的外延是运营人员，商业产品的外延是市场人员，他们很多时候和PM同学是难兄难弟，有时是在RD后面装孙子陪笑脸的另外一位，需要脑子更活，为了KPI洋法土法都可以上啊！懂运营或市场是产品经理进阶总监的一道门槛。</div><div style="">&nbsp;  &nbsp;&nbsp;为什么要早作选择？因为PM的核心竞争力是经验。在你入行不久发现其实PM里的东西你什么都懂了一点后，你要做的就是找个方向不停的实践下去了。直到 有一天，你不知偶然还是必然地抓住了一款牛逼产品，就是你这个PM咸鱼翻身的日子，你将和那些菜鸟划清界限，并向其他所有人布道你的产品观，而且惊喜地发 现：他们居然听你的了！</div></div><p>转自：http://qing.weibo.com/2613724775/9bca466733000d90.html</p>]]></description><category>产品经理</category><comments>http://www.zhizihua.com/blog/post/选择产品经理--写在开始的话.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=529</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=529&amp;key=0b6ad489</trackback:ping></item><item><title>中国互联网创业的葵花宝典</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/中国互联网创业的葵花宝典.html</link><pubDate>Wed, 16 May 2012 15:13:43 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/中国互联网创业的葵花宝典.html</guid><description><![CDATA[<p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">一个朋友，在一家软件的大企业做了十年的软件研发，想出来创业，问我要注意什么。我开玩笑说，要想成功，必须学习互联网创业的&ldquo;葵花宝典&rdquo;，第一条就是&ldquo;挥刀自宫&rdquo;。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">大的软件公司有很多资源，研发能力不错，各种推广资源也非常优越，但很少开发出来优秀的互联网产品。初步看上去，原因很多，比如很难调动个人的积极性、内部管理协调非常困难等。我认为还有一个重要的原因，就是方法不得当。大公司资源多，一个互联网创新项目，投入大量资源后，公司期望值高，考虑的问题自然多了，反而不容易做好。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">从大公司离职出来创业，首先要&ldquo;挥刀自宫&rdquo;，干掉大公司这套做法，控制成本尽量少花钱，集中精力和资源解决核心的一两个问题就足够了。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">不要想太多，不做太长时间的计划，尤其是计划不能太复杂！创业成功需要的是发现机会和快速突破的能力，再加一点运气。大公司的工作经验太多，有时候反而会限制自己的做法。 互联网创业，越简单越单纯，越容易成功！</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">1.专注：解决用户一个迫切的需求，解决的问题一句话就可以说清楚。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">(1) 一个明确而且用户迫切需要的产品，很容易找到明确的用户群。这样，产品研发出来后，不容易走偏。(2) 选择的用户需求要有一定的普遍性，这点决定这个产品的未来市场前景。(3) 解决的问题少，开发速度快，也容易控制初期的研发成本和风险。(4) 解决明确问题的产品，容易给用户说清楚，推广也会相对简单。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">2.极致：要在这个功能点上做到所有同类产品的极致，做到最好才能赢。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">(1) 极致是互联网产品的核心，只要极致才能超出用户的口碑，形成口口相传的效应，给后期的推广带来了很大的便利。(2) 专注才能做到极致，做到极致才能击败竞争对手。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">3.快：开发周期一定要控制在三到六个月的时间，一定要快。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">(1) 互联网时代，用户需求变化比较快，而且竞争也比较激烈。快速的开发，容易适应整个市场的节奏，并且节约成本。(2) 用户试用过程中，如果发现问题，反应速度也要快，尽快改善尽快更新。初期，我认为要保持在一两周的更新速度。<br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " /><br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; " /><strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">4.口碑：初期市场营销坚持少花钱甚至不花钱，才能看出产品对用户真正的吸引力。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">(1) 产品完成后，不要着急，先坚持在一个小规模的用户群中试用，听听用户反馈。(2) 大规模的推广会带来如下的两个问题：一、投入大量市场费用后，用户期望值很高，如果产品不完善，很容易引起负面的口碑，为以后的推广留下了隐患。二、大规模市场推广得到的测试效果不准确。如果产品不完善，甚至需求选择有问题，会被数字掩盖。当推广费用停止后，用户量不增长甚至下滑，再改就来不及了。过去几年成功的互联网创业公司，其实在市场营销上花的钱都非常少，但这些公司在市场营销上花的精力并不少。(3) 刚开始最重要的推广技巧是搜索引擎优化和病毒式营销。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><strong style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">互联网创业的葵花宝典就是&ldquo;专注&rdquo;、&ldquo;极致&rdquo;、&ldquo;快&rdquo;和&ldquo;口碑&rdquo;！</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">一次完美的互联网创业，最好是技术、产品高手搭配的两三人创业，三到六个月内完成产品，再用半年到一年的时间测试完善产品，达成初步成功的门槛，再寻求融资，摸索成功的商业模式，然后投入大量的市场资源推广，形成规模化业务。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 1.2em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">初步成功的标准，不同的业务要求不同。我有一个简单的标准供大家参考，就是产品推出半年到一年时间，网站页面过一百万PV，或者客户端产品日净增安装量1万次，而且用户数还在持续增长。达成这个目标之后，需要琢磨的事情，就是在保持增长速度的同时，如何探索好的商业模式。</p><p style="padding: 0px; margin: 1.2em 0px; line-height: 1.5em; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><span style="color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">作者：雷军</span><br style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " /><span style="color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">转自：</span><a style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(0, 102, 0); text-decoration: none; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(0, 102, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " href="http://www.ha97.com/tag/http" title="http">http</a><span style="color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">://</span><a style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(0, 102, 0); text-decoration: none; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(0, 102, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " href="http://www.ha97.com/tag/blog" title="blog">blog</a><span style="color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">.sina</span><a style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(0, 102, 0); text-decoration: none; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(0, 102, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " href="http://www.ha97.com/tag/com" title=".com">.com</a><span style="color: rgb(0, 34, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; display: inline !important; float: none; ">.cn/s/blog_4b0e23c90100c1ok.</span><a style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; color: rgb(0, 102, 0); text-decoration: none; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: rgb(0, 102, 0); font-family: georgia; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 22px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; " href="http://www.ha97.com/tag/html" title="html">html</a></p>]]></description><category>产品经理</category><comments>http://www.zhizihua.com/blog/post/中国互联网创业的葵花宝典.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=528</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=528&amp;key=4ec0aeb4</trackback:ping></item><item><title>企业微博：信息流通以人为本</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/企业微博：信息流通以人为本.html</link><pubDate>Wed, 02 May 2012 20:13:42 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/企业微博：信息流通以人为本.html</guid><description><![CDATA[<p>中国企业的信息化建设正逐渐从以&ldquo;流程+数据&rdquo;为中心，转变为以&ldquo;人&rdquo;为中心。企业微博作为完成此转变的重要载体和平台之一，将实现企业内部沟通交流的平等化、透明化、让信息流通以人为本。</p><p>&nbsp;</p><p><img alt="" src="http://content.businessvalue.com.cn/wp-content/uploads/p124-qywb1.jpg" width="380" height="375" /></p><p>近年来，中国企业管理者要面对的不仅是以客户为中心的市场竞争的挑战，更需要在技术、成本、质量、服务等具体环节不断增强实力。一份来自Value Research的调研报告指出，企业CIO需要解决IT系统和企业整体发展需要之间的矛盾，并利用IT资源更好地服务于企业业务规划。</p><p>该报告同时指出，以往企业IT投资和建设忽略了对企业员工的关注。过去的20多年，中国企业的IT建设主要以满足业务应用需求为主&mdash;&mdash;例如硬件设备的搭建、流程化与结构化数据的处理等。这也直接导致了IT投资没有充分考虑与人的结合，从而不能发挥出最大的效用。</p><p>伴随着国内外市场环境的变化，以及各种新技术的迅猛发展，&ldquo;人&rdquo;的因素越来越受到关注。一场&ldquo;以人为本&rdquo;的信息化建设浪潮正在掀起&mdash;&mdash;让流程和数据为人服务，将企业内部沟通和外部协作紧密结合，充分辅助&ldquo;人&rdquo;去完成相应的业务操作并实现业务价值，从而为企业带来最大的投资回报率。</p><h2>&ldquo;以流程为本&rdquo;到&ldquo;以人为本&rdquo;</h2><p>在这样的大背景之下，过去单纯的以&ldquo;流程+数据&rdquo;为中心的企业信息化建设，已经很难适应企业对组织架构或业务的调整需求，无法支撑企业完成迫切的转型和变革。只有实现从&ldquo;以流程为本&rdquo;到&ldquo;以人为本&rdquo;的转变，IT才能够帮助企业有效应对众多复杂多变中的不确定性因素，以及内外部环境带来的新挑战和新需求。</p><p>从&ldquo;以流程为本&rdquo;到&ldquo;以人为本&rdquo;，意味着以往的传统信息流通模式将被打破&mdash;&mdash;从人为数据和流程服务，变化为让数据和流程为人服务，从而创造更好的商业价值&mdash;&mdash;充分发挥&ldquo;人&rdquo;的主观能动性，重视其在业务操作和价值实现过程中的关键作用。</p><p>因此，企业CIO需要在移动化、云计算、IT消费化的大趋势下，关注员工作为&ldquo;人&rdquo;的基本需求，甚至让这种需求享有优先级，并借助IT的手段来充分激发人的潜能，使员工摆脱传统办公方式和管理模式的束缚和制约。</p><p>&nbsp;&ldquo;下一个10年，ERP+SNS可能会成为企业信息化的一个方向。&rdquo;金蝶中国公司副总裁郝登胜说。SNS作为Web 2.0时代产物，早已风靡互联网。那么，如果将基于个人应用的SNS融入企业级应用，将Web 2.0思想融入传统的企业管理思想，将会如何？基于Web 2.0技术的网络软件在组织和商业中的使用，便被成为 &ldquo;企业2.0（Enterprise 2.0）&rdquo;。</p><p>企业2.0最早由麻省理工学院斯隆管理学院数字商务中心首席研究科学家Andrew McAfee（安德鲁&middot;麦卡菲）提出，并定义为公司内自然出现的社会软件平台，或者公司与其合作者及客户之间自然出现的社会软件平台（Emergent Social Software Platform，ESSP），让人们相互交往中固有的模式和结构变得可视化。</p><p>Andrew认为，企业2.0的核心思想是：当信息的流通和交换愈加畅通时，企业人与同事、团队、客户及其合作伙伴等的沟通也会愈加高效，从而避免囚徒困境的出现。而当沟通变得更加自由和开放时（在合理范围内），企业人就可以从周围得到更多的反馈，从而实现更多的互动（从而产生协作），同时企业人对问题的反应也会愈加迅速、敏捷，因此做出的判断也会愈加准确。</p><p>&ldquo;在企业2.0的模式里，企业里的每一个人都将发挥更大的影响力。这在人力资源成本不断增长而人才又相对紧缺的商业社会里，是一个非常重要的转型。&rdquo;金蝶集团互联网产品事业部总经理王天宇认为，&ldquo;一个成功的社会化管理体制可以帮助企业更加有效地协调资源，快速地分享信息，加强管理的透明度，增强部门之间协同合作，并逐渐改变企业里的官僚文化。&rdquo;</p><p>在互联网从Web 1.0到Web 2.0的转型中，信息流通实现了从&ldquo;一点到多点&rdquo;向&ldquo;多点对多点&rdquo;的传播方式的转变，打破了传统的传播瓶颈。企业从1.0向2.0的转变与此类似：企业1.0管理模式依赖于传统的资源分配型软件，以 &ldquo;记录信息&rdquo; 的模式辅助企业的管理者。而企业2.0则让管理软件逐渐互联网化和碎片化，以企业里人与人之间的关系为主线， 关注企业里的不同部门和不同组织的协同需求， 增加信息分享的速度， 提高企业的综合生产力。</p><p>企业1.0到企业2.0的转变，正是&ldquo;以流程为本&rdquo;向&ldquo;以人为本&rdquo;的转变，&ldquo;人&rdquo;的因素被充分重视起来。通过将分散于企业员工大脑中的知识汇聚起来，降低企业内部信息的沟通成本，形成对外的信息优势。&ldquo;传统ERP的重点是&lsquo;数据+流程&rsquo;，而基于&lsquo;人为核心的社交网络&rsquo;的信息化构建可能是企业信息化很好的补充。&rdquo;郝登胜说。</p><h2>企业微博&ne;微博</h2><p>在Web 2.0时代，社交网络的普及将人与人之间的沟通无限拉近，使得信息更加透明化、信息沟通更加便捷化。在企业2.0时代，企业Wiki、Blog、企业Tagging、企业微博等典型的企业2.0工具，通过&ldquo;多点对多点&rdquo;的信息流通模式，将组织中的每个人充分调动，运用群体的力量和智慧应对业务挑战。</p><p>企业微博是一种基于企业级应用的信息分享、传播、交流平台，当前具有两种存在形式。一种例如新浪微博中的企业微博，其实质是企业专属的品牌页面，主要用于与合作伙伴、供应商、客户等进行&ldquo;弱关系&rdquo;的沟通和交流，能够一定程度上帮助企业实现扩大知名度、提升企业形象、产品品牌推广、上下游业务扩展等目标。</p><p>另一种为Yammer和金蝶微博类的企业微博，其实质是企业内部沟通交流的SNS平台，主要用于企业内部同事间进行&ldquo;强关系&rdquo;的沟通和交流，能够帮助企业实现团队协作、管理透明化、知识管理、创意搜集等目标。</p><p>这种企业微博的属性特征表现为：基于工作性质的商务属性，主要用于企业内部沟通交流，所谈论的内容多与工作相关，不同于新浪微博的媒体属性、腾讯微博的娱乐属性，商务属性有利于公司管理的扁平化和沟通的透明化；基于工作内容的协作属性，主要用于企业内部团队了解彼此工作状况、进行工作协同，注重互动，而公共平台微博更注重分享，协作属性能够降低人际沟通成本、提升人员工作效率，能够聚合集体智慧，降低创新成本、加快创新速度；基于工作范围的私密属性，企业微博只允许企业内部员工实名制访问，为企业用户提供了专属的私密空间，不同于公共平台微博的开放性和公开性，能够帮助企业保护敏感信息，加大沟通的安全感。当然，目前Yammer和金蝶微博虽然允许企业用户建立外部沟通社区，但也需实名邀请。</p><p><img alt="" src="http://content.businessvalue.com.cn/wp-content/uploads/p124-qywb2.jpg" width="480" height="328" /></p><h2>争做企业级twitter</h2><p>企业微博的社交属性，可以帮助企业内部实现从&ldquo;人机互动&rdquo;到&ldquo;人人互动&rdquo;的转变。而在该领域，Yammer和金蝶微博值得关注。</p><p>Yammer成立于2008年9月，在国外企业微博领域具有&ldquo;企业级twitter&rdquo;之称，能够为企业提供社会化的网络服务。据Yammer CEO David Sacks透露，截至2011年底，公司的企业用户数为400万，该数字在2010年底为160万，其目标是在2012年底达到800万到1000万企业用户。</p><p>在国内市场上，2012年1月9日，金蝶正式推出&ldquo;金蝶微博&rdquo;平台。金蝶微博定义为&ldquo;私密的企业社交平台&rdquo;，承诺永久免费，致力于在企业社会化网络的深刻商业变革中为企业提供信息交互的竞争优势，使需要协作的员工更方便、有效的进行交流与分享，降低企业沟通成本，提高工作效率，凝聚专业知识工作者和远程同事。</p><p>在此前两个月的公测中，已有超过5000家的企业用户使用，并呈直线上升趋势。来自Alexa的监控数据显示，金蝶微博目前的日均PV值和IP值均超过其他国内企业微博产品的总和。&ldquo;中国的企业需求已不仅仅停留在软件层面，它们更多的是要求一种全面的整合服务。未来金蝶微博将全面融入ERP产品解决方案，并携手合作伙伴共同转型。&rdquo;金蝶集团董事局主席徐少春表示，金蝶微博是金蝶集团向互联网转型的重要步骤与载体。</p>]]></description><category>互联网</category><comments>http://www.zhizihua.com/blog/post/企业微博：信息流通以人为本.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=527</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=527&amp;key=701de012</trackback:ping></item><item><title>这到底是谁之错？</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/这到底是谁之错？.html</link><pubDate>Sat, 28 Apr 2012 20:11:40 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/这到底是谁之错？.html</guid><description><![CDATA[<p><strong>故事一：</strong><br />背景介绍：RT是一个外包公司，ZWZX是项目承接公司，YD是甲方。</p><p>RT公司每天下班的时候都会接到ZWZX负责人的电话，询问一天的工作情况，然后布置任务要求晚上加班做完，RT公司的员工很无奈也很气愤因为每天 都要加班，员工们就问项目经理：&ldquo;为什么天天加班赶需求，今天才提一个需求，明天就要上线，还让不让人活了?&rdquo;  项目经理无奈的说：&ldquo;我有什么办法啊？这是人家ZWZX负责人说的啊，对方逼得紧。&rdquo;</p><p>多次以后项目经理也忍不住了，就问ZWZX的负责人怎么天天这样啊，ZWZX的负责人就说了:&rdquo;明天就要向YD的负责人展示这个页面，我也没有办法啊？YD那边老总就是这么要求的，我怎么办，我也不想这样啊？&rdquo;</p><p>然后RT的项目经理实在受不了了就辞职了，新上任的项目经理又会走他的老路，因为从开始我们就被培养&ldquo;满足客户的需求是最重要的&rdquo;。RT的员工也就这样一直抱怨着，一直忍受着。天天在心里咒骂YD的老总真是没有人性，不拿人当人看啊！</p><p>人换了一批又一批，加班也就慢慢的变成了应该的，你不加班说明你不敬业，不合格。</p><p><strong>故事二：</strong><br />IE6一直存活着，所有的前端开发人员都痛恨它，都不想兼容它，可是产品经理看到IE6的市场占有率还是这么高，就会要求前端开发人员必须兼容IE6。</p><p>&nbsp;</p><p>矛盾又来了，就像故事一一样，前端开发人员天天抱怨，产品经理也天天抱怨，但是面对IE6的市场份额，产品经理会劝开发人员说：&ldquo;我有什么办法 啊？IE6的市场份额就是这么高，不兼容怎么办啊？我也不想啊！&rdquo;  开发人员也就这样忍受着，然后不断地抱怨用IE6的用户低端，没文化，怎么还用IE6啊！天天兼容IE6就够烦的了，还怎么创新啊！</p><p><strong>这两个故事里出现的问题到底是谁的错误引起的？&nbsp;</strong></p><p>故事一的罪魁祸首是YD的老总吗？</p><p>故事二的罪魁祸首是那些还用着IE6的用户吗？</p><p>从这两个嫌疑最大的罪魁祸首眼中看一下这两个故事：</p><p><strong>故事一：</strong><br />我是YD的老总，我要建立一个网站，找到了ZWZX公司，签订了合同，我提需求他们实现。</p><p>我不懂制作网站，可是我才思敏捷，创意无限，不停的会有好点子从我的脑海里蹦出来，每当有一个好点子蹦出来后，我都会给ZWZX公司的负责人讲清楚 我的想法，让他实现，开始我不知道做一个页面需要多长时间。第一次我试探性的说了一周必须把我这个点子做出来，ZWZX公司负责人很痛快的答应了，一周后 我果然看到了这个功能。</p><p>可是会不会我给他们的时间太长了？对！肯定是，要不也不会答应的这么痛快。这些人啊！天天就是想拖时间，好多骗我点钱。</p><p>点子又来了，这次我要求5天做出来，这个点子和上个点子类似，我倒要看看5天能不能做出来~&nbsp;&nbsp;ZWZX公司负责人一副痛苦的表情，我会不会逼的太紧了，5天是不是真的做不出来？到时候看看吧，如果5天没做出来估计是我给的时间太少了。</p><p>5天过去了ZWZX公司的负责人很高兴的拿出了我要的功能实现，哎，看来开始真的骗了我两天。就是不知道5天会不会还是多了啊？下次给3天~</p><p>又拿出来了，虽然他装的好像时间太紧似的，可别以为我不知道，你第一个功能最多3天就做出来了，我还给了你7天的项目经费，你们多赚了我多少啊！！！！ 真是没良心。 下次1天！！！</p><p>啊啊啊啊啊啊啊啊!!! 1天就出来了，这些人。。。。。&nbsp;&nbsp;有没有良心，原来做这个这么简单，以后就给1天，不 ！ 一天N个功能。</p><p><strong>故事二：</strong><br />我买了个电脑，没什么别的用途，就是打开电脑上上网，上上QQ和儿子聊聊天，QQ是儿子给我装上的，这样我就可以和他视频了。有一次QQ提醒我说我的QQ 版本太低了，不能视频了，我打电话问儿子，儿子说按提示升级一下QQ就行了，呵呵，我按QQ的提示，儿子的指示一步一步的升级QQ成功了，看来电脑也不难 啊！</p><p><strong>到这里您认为开始的两个故事的罪魁祸首是谁啊？</strong></p><p>我们一直以加班，甚至通宵去满足客户不合理的要求，只因为他是客户。只因为人人都认为满足客户的要求是我们最大的<br />价值，可是不合理的要求不能去拒绝吗？套用刘欢说的一句话&ldquo;我们是不是活的应该有些尊严&rdquo;，一味的迎合客户，只会让我们自己越来越痛苦，反而得不到用户的尊重，肯定。</p><p>我一直有个疑惑，很多人说网站不支持IE6，而选择让用户去升级IE，这样的用户体验不好！如果按照按照这个逻辑，是不是我们都应该是Web应用， 而且都应该是IE6下的Web应用呢？为什么微软还要出WIN8，一直XP不是挺好的吗？让用户升级系统，用户体验多么不好啊？QQ，360，搜狗输入 法，等等客户端软件用户体验不都不好吗？ 都还要用户下载。</p><p>实在搞不懂为什么我们做个东西非要去支持IE6呢？检测到用户是IE6，给个提示，给个升级链接不就行了？ 这样做用户体验是有多么不好吗？  你天天去支持IE6，还要天天磨叽用户使用IE6，你不觉的很矛盾吗？再说我一个普通用户，你如果不提醒，我怎么知道要升级IE6啊？</p><p><strong>对于遭遇了故事一，故事二的人只能送上一句话&ldquo;哀其不幸，怒其不争！&rdquo;</strong></p><p>原文链接：<a target="_blank" href="http://hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/">http://hfcc8685.github.com/blog/2012/04/19/shui-zhi-cuo/</a></p>]]></description><category>产品经理</category><comments>http://www.zhizihua.com/blog/post/这到底是谁之错？.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=526</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=526&amp;key=b693976a</trackback:ping></item><item><title>海量用户积分排名算法探讨</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/海量用户积分排名算法探讨.html</link><pubDate>Sat, 28 Apr 2012 09:54:19 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/海量用户积分排名算法探讨.html</guid><description><![CDATA[<div id="cnblogs_post_body"><h3>问题</h3><p>某海量用户网站，用户拥有积分，积分可能会在使用过程中随时更新。现在要为该网站设计一种算法，在每次用户登录时显示其当前积分排名。用户最大规模为2亿；积分为非负整数，且小于100万。</p><p>PS: 据说这是迅雷的一道面试题，不过问题本身具有很强的真实性，所以本文打算按照真实场景来考虑，而不局限于面试题的理想环境。</p><h3>存储结构</h3><p>首先，我们用一张用户积分表user_score来保存用户的积分信息。</p><p>表结构：</p><p><img title="" alt="user&lt;em /&gt;score&lt;/em&gt;schema" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_user_score_schema.png" /></p><p>示例数据：</p><p><img title="" alt="user&lt;em /&gt;score&lt;/em&gt;sample" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_user_score_sample.png" /></p><p>下面的算法会基于这个基本的表结构来进行。</p><h3>算法1：简单SQL查询</h3><p>首先，我们很容易想到用一条简单的SQL语句查询出积分大于该用户积分的用户数量：</p><pre><code>select 1 + count(t2.uid) as rank from user_score t1, user_score t2 where t1.uid = @uid and t2.score &gt; t1.score </code></pre><p>对于4号用户我们可以得到下面的结果：</p><p><img title="" alt="sql_1" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/o_sql.png" /></p><p>算法特点</p><p>优点：简单，利用了SQL的功能，不需要复杂的查询逻辑，也不引入额外的存储结构，对小规模或性能要求不高的应用不失为一种良好的解决方案。</p><p>缺点：需要对user_score表进行全表扫描，还需要考虑到查询的同时若有积分更新会对表造成锁定，在海量数据规模和高并发的应用中，性能是无法接受的。</p><h3>算法2：均匀分区设计</h3><p>在许多应用中缓存是解决性能问题的重要途径，我们自然会想能不能把用户排名用Memcached缓存下来呢？不过再一想发现缓存似乎帮不上什么忙， 因为用户排名是一个全局性的统计性指标，而并非用户的私有属性，其他用户的积分变化可能会马上影响到本用户的排名。然而，真实的应用中积分的变化其实也是 有一定规律的，通常一个用户的积分不会突然暴增暴减，一般用户总是要在低分区混迹很长一段时间才会慢慢升入高分区，也就是说用户积分的分布总体说来是有区 段的，我们进一步注意到高分区用户积分的细微变化其实对低分段用户的排名影响不大。于是，我们可以想到按积分区段进行统计的方法，引入一张分区积分表 score_range：</p><p>表结构：</p><p><img title="" alt="score&lt;em /&gt;range&lt;/em&gt;schema" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_score_range_schema.png" /></p><p>数据示例：</p><p><img title="" alt="score&lt;em /&gt;range&lt;/em&gt;sample" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_score_range_sample.png" /></p><p>表示[from_score, to_score)区间有count个用户。若我们按每1000分划分一个区间则有[0, 1000),  [1000, 2000), &hellip;, [999000,  1000000)这1000个区间，以后对用户积分的更新要相应地更新score_range表的区间值。在分区积分表的辅助下查询积分为s的用户的排 名，可以首先确定其所属区间，把高于s的积分区间的count值累加，然后再查询出该用户在本区间内的排名，二者相加即可获得用户的排名。</p><p>乍一看，这个方法貌似通过区间聚合减少了查询计算量，实则不然。最大的问题在于如何查询用户在本区间内的排名呢？如果是在算法1中的SQL中加上积分条件：</p><pre><code>select 1 + count(t2.uid) as rank from user_score t1, user_score t2 where t1.uid = @uid and t2.score &gt; t1.score and t2.score &lt; @to_score </code></pre><p>在理想情况下，由于把t2.score的范围限制在了1000以内，如果对score字段建立索引，我们期望本条SQL语句将通过索引大大减少扫描 的user_score表的行数。不过真实情况并非如此，t2.score的范围在1000以内并不意味着该区间内的用户数也是1000，因为这里有积分 相同的情况存在！二八定律告诉我们，前20%的低分区往往集中了80%的用户，这就是说对于大量低分区用户进行区间内排名查询的性能远不及对少数的高分区 用户，所以在一般情况下这种分区方法不会带来实质性的性能提升。</p><p>算法特点</p><p>优点：注意到了积分区间的存在，并通过预先聚合消除查询的全表扫描。</p><p>缺点：积分非均匀分布的特点使得性能提升并不理想。</p><h3>算法3：树形分区设计</h3><p>均匀分区查询算法的失败是由于积分分布的非均匀性，那么我们自然就会想，能不能按二八定律，把score_range表设计为非均匀区间呢？比如， 把低分区划密集一点，10分一个区间，然后逐渐变成100分，1000分，10000分 &hellip;  当然，这不失为一种方法，不过这种分法有一定的随意性，不容易把握好，而且整个系统的积分分布会随着使用而逐渐发生变化，最初的较好的分区方法可能会变得 不适应未来的情况了。我们希望找到一种分区方法，既可以适应积分非均匀性，又可以适应系统积分分布的变化，这就是树形分区。</p><p>我们可以把[0, 1,000,000)作为一级区间；再把一级区间分为两个2级区间[0, 500,000), [500,000,  1,000,000)，然后把二级区间二分为4个3级区间[0, 250,000), [250,000, 500,000), [500,000,  750,000), [750,000, 1,000,000)，依此类推，最终我们会得到1,000,000个21级区间[0,1), [1,2) &hellip;  [999,999,  1,000,000)。这实际上是把区间组织成了一种平衡二叉树结构，根结点代表一级区间，每个非叶子结点有两个子结点，左子结点代表低分区间，右子结点 代表高分区间。树形分区结构需要在更新时保持一种不变量(Invariant)：非叶子结点的count值总是等于其左右子结点的count值之和。</p><p><img title="" alt="range_tree" src="http://images.cnblogs.com/cnblogs_com/weidagang2046/359580/r_ranking_tree.png" /></p><p>以后，每次用户积分有变化所需要更新的区间数量和积分变化量有关系，积分变化越小更新的区间层次越低。总体上，每次所需要更新的区间数量是用户积分 变量的log(n)级别的，也就是说如果用户积分一次变化在百万级，更新区间的数量在二十这个级别。在这种树形分区积分表的辅助下查询积分为s的用户排 名，实际上是一个在区间树上由上至下、由粗到细一步步明确s所在位置的过程。比如，对于积分499,000，我们用一个初值为0的排名变量来做累加；首 先，它属于1级区间的左子树[0, 500,000)，那么该用户排名应该在右子树[500,000,  1,000,000)的用户数count之后，我们把该count值累加到该用户排名变量，进入下一级区间；其次，它属于3级区间的[250,000,  500,000)，这是2级区间的右子树，所以不用累加count到排名变量，直接进入下一级区间；再次，它属于4级区间的&hellip;；直到最后我们把用户积分精 确定位在21级区间[499,000, 499,001)，整个累加过程完成，得出排名！</p><p>虽然，本算法的更新和查询都涉及到若干个操作，但如果我们为区间的from_score和to_score建立索引，这些操作都是基于键的查询和更 新，不会产生表扫描，因此效率更高。另外，本算法并不依赖于关系数据模型和SQL运算，可以轻易地改造为NoSQL等其他存储方式，而基于键的操作也很容 易引入缓存机制进一步优化性能。进一步，我们可以估算一下树形区间的数目大约为200,000,000，考虑每个结点的大小，整个结构只占用几十M空间。 所以，我们完全可以在内存建立区间树结构，并通过user_score表在O(n)的时间内初始化区间树，然后排名的查询和更新操作都可以在内存进行。一 般来讲，同样的算法，从数据库到内存算法的性能提升常常可以达到10^5以上；因此，本算法可以达到非常高的性能。</p><p>算法特点</p><p>优点：结构稳定，不受积分分布影响；每次查询或更新的复杂度为积分最大值的O(log(n))级别，且与用户规模无关，可以应对海量规模；不依赖于SQL，容易改造为NoSQL或内存数据结构。</p><p>缺点：算法相对更复杂。</p><h3>算法4：积分排名数组</h3><p>算法3虽然性能较高，达到了积分变化的O(log(n))的复杂度，但是实现上比较复杂。另外，O(log(n))的复杂度只在n特别大的时候才显出它的优势，而实际应用中积分的变化情况往往不会太大，这时和O(n)的算法相比往往没有明显的优势，甚至可能更慢。</p><p>考虑到这一情况，仔细观察一下积分变化对排名的具体影响，可以发现某用户的积分从s变为s+n，积分小于s或者大于等于s+n的其他用户排名实际上 并不会受到影响，只有积分在[s,s+n)区间内的用户排名会下降1位。我们可以用于一个大小为100,000,000的数组表示积分和排名的对应关系， 其中rank[s]表示积分s所对应的排名。初始化时，rank数组可以由user_score表在O(n)的复杂度内计算而来。用户排名的查询和更新基 于这个数组来进行。查询积分s所对应的排名直接返回rank[s]即可，复杂度为O(1)；当用户积分从s变为s+n，只需要把rank[s]到 rank[s+n-1]这n个元素的值增加1即可，复杂度为O(n)。</p><p>算法特点</p><p>优点：积分排名数组比区间树更简单，易于实现；排名查询复杂度为O(1)；排名更新复杂度O(n)，在积分变化不大的情况下非常高效。</p><p>缺点：当n比较大时，需要更新大量元素，效率不如算法3。</p><h3>总结</h3><p>上面介绍了用户积分排名的几种算法，算法1简单易于理解和实现，适用于小规模和低并发应用；算法3引入了更复杂的树形分区结构，但是 O(log(n))的复杂度性能优越，可以应用于海量规模和高并发；算法4采用简单的排名数组，易于实现，在积分变化不大的情况下性能不亚于算法3。本问 题是一个开放性的问题，相信一定还有其他优秀的算法和解决方案，欢迎探讨！</p></div><p>更多信息请查看原文：http://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html</p>]]></description><category>算法</category><comments>http://www.zhizihua.com/blog/post/海量用户积分排名算法探讨.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=525</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=525&amp;key=68a95e9b</trackback:ping></item><item><title>An introduction to WebGL</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/AnintroductiontoWebGL.html</link><pubDate>Thu, 26 Apr 2012 21:09:56 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/AnintroductiontoWebGL.html</guid><description><![CDATA[<h2>Introduction</h2><p>This is the first in our series of articles about WebGL. The objective of this series is to provide the information and resources you'll need to get started learning WebGL. In this piece, we will discuss how WebGL works, what you need to create WebGL applications, and what a simple example looks like.</p><h2>What is WebGL?</h2><p>WebGL is a JavaScript API that allows us to implement interactive 3D graphics, straight in the browser. For an example of what WebGL can do, take a look at this <a href="http://www.youtube.com/embed/KDQbXLXM_l4">WebGL demo video</a> (viewable in all browsers!)</p><p>WebGL is a web standard developed by the <a href="http://www.khronos.org/">Khronos group</a>; Opera is an active participating member along with Google (Chrome), Mozilla (Firefox), Apple (Safari), and other 3D graphics developers.</p><p>WebGL runs as a specific context for the HTML <code>&lt;canvas&gt;</code> element, which gives you access to hardware-accelerated 3D rendering in JavaScript. Because it runs in the <code>&lt;canvas&gt;</code> element, WebGL also has full integration with all <acronym title="Document Object Model">DOM</acronym> interfaces. The API is based on <a href="http://www.khronos.org/opengles/2_X/">OpenGL ES 2.0</a>, which means that it is possible to run WebGL on many different devices, such as desktop computers, mobile phones and TVs. You can <a href="https://www.khronos.org/registry/webgl/specs/1.0/">view the WebGL specification</a> at the Khronos site.</p><h2>How do I run WebGL?</h2><p id="implementations">To access WebGL content you need to have a browser that supports it.</p><ul>    <li><a class="draft" href="http://www.opera.com/browser/next/">Opera 12.00</a></li>    <li><a href="http://www.google.com/chrome/">Chrome 9 or higher, on Linux, Mac and Windows</a></li>    <li><a href="http://www.mozilla.org/en-US/products/download.html">Firefox 4 and higher</a></li>    <li><a href="http://www.apple.com/safari/">Safari 5.1 or higher on Leopard, Snow Leopard, or Lion</a> (make sure you enable WebGL in Safari &mdash; go to <em>Preferences &gt; Advanced</em> and check &quot;Show develop menu in menu bar&quot;, then go to <em>Develop &gt; Enable WebGL</em>)</li></ul><p>Also, having a good graphics card will likely improve WebGL performance on your computer. If you don't already have it, get the <a class="draft" href="http://www.opera.com/browser/next/">latest Opera release</a> and check out the above video example running as a <a href="http://aleksandarrodic.com/p/jellyfish">live demo</a>. Another great demo to check out is <a href="http://helloracer.com/webgl">Hello Racer</a>.</p><h2>What is WebGL used for?</h2><p>WebGL allows developers to put real-time interactive 3D graphics in the browser. WebGL can be applied to interactive music videos, games, data visualization, art, 3D design environments, 3D modeling of space, 3D modeling of objects, plotting mathematical functions, or creating physical simulations.</p><div style="padding-bottom: 50px; padding-left: 10px; width: 624px; padding-right: 30px; height: 624px; clear: both; padding-top: 30px" id="grid"><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://inear.se/beanstalk"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/DNMEw.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Interactive music videos</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://operasoftware.github.com/Emberwind/"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/OnJ15.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Games</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://senchalabs.github.com/philogl/PhiloGL/examples/temperatureAnomalies/"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/mbMDS.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Data visualization</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://mrdoob.github.com/three.js/examples/webgl_materials_cubemap_escher.html"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/1MHN5.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Art</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://veditor.plopbyte.net/"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/vnEAW.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">3D design environments</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://mrdoob.github.com/three.js/examples/webgl_panorama_equirectangular.html"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/XOpwr.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">3D modeling of space</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://alteredqualia.com/three/examples/webgl_materials_skin.html"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/yLMt9.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">3D modeling of objects and textures</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://senchalabs.github.com/philogl/PhiloGL/examples/explorer/"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/DxjtI.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Plotting mathematical functions</p></div><div style="border-bottom: medium none; position: relative; border-left: medium none; margin: 2px; width: 200px; float: left; height: 200px; border-top: medium none; border-right: medium none"><a href="http://www.cake23.de/traveling-wavefronts-lit-up.html"><img style="width: 200px; height: 200px" alt="" src="http://i.imgur.com/9PY49.png" /></a><p style="position: absolute; padding-bottom: 1px; background-color: white; margin: 0px; padding-left: 1px; bottom: 3px; padding-right: 1px; font-size: 80%; right: 3px; padding-top: 1px">Creating physical simulations</p></div></div><h2>How does WebGL work?</h2><p>WebGL is slightly more complicated than your typical web technologies because it's designed to work directly with your graphics card. As a consequence, it's pretty low level. This is what allows it to rapidly do complex 3D rendering involving lots of calculations.</p><p>You don't need to fully understand the inner workings of WebGL. There are <a href="http://dev.opera.com/articles/view/an-introduction-to-webgl/#webgllib">several WebGL libraries</a> available to take some of the complexity out of your hands. However, gaining an understanding of it can be useful in case you want to spice up your code with features that are not in your library of choice, or you feel that having a better grasp of the technology will help you find your way around what the libraries have to offer.</p><p>When programming in WebGL, you are usually aiming to render a scene of some kind. This usually includes multiple subsequent draw jobs or &quot;calls&quot;, each of which is carried out in the <acronym title="Graphics Processing Unit">GPU</acronym> though a process called the rendering pipeline.</p><p>In WebGL, like in most real-time 3D graphics, the triangle is the basic element with which models are drawn. Therefore, the process of drawing in WebGL involves using JavaScript to generate the information that specifies where and how these triangles will be created, and how they will look (colour, shades, textures, etc). This information is then fed to the GPU, which processes it, and returns a view of the scene. Next we will look in more detail at how this last bit happens.</p><h3>The rendering pipeline</h3><p class="note">Note that this section is adapted from <a href="http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-1:-The-Graphics-Pipeline.html">Joe Groff's explanation of the graphics pipeline in OpenGL</a>.</p><p><img class="left" alt="" src="http://dev.opera.com/articles/view/an-introduction-to-webgl/rendering_pipeline.jpg" /></p><p>The process starts with the creation of the vertex arrays. These are arrays that contain vertex attributes like the location of the vertex in the 3D space and information about the vertex' texture, colour or how it will be affected by lighting (vertex normal). These arrays and the information they contain are created in JavaScript in one or more of these ways: processing files that describe a 3D model (for example .obj files), procedurally creating the data from scratch, or using a library that provides vertex arrays for geometrical shapes.</p><p>Then the data in the vertex arrays is sent to the GPU by feeding it into a set of one or more <strong>vertex buffers</strong>. When a rendering job is submitted, we also have to supply an additional array of indices that point to the vertex array elements. They control how the vertices get assembled into triangles later on.</p><p>The GPU begins by reading each selected vertex out of the vertex buffer and running it through the <strong>vertex shader</strong>. The vertex shader is a program that takes a set of vertex attributes as inputs and outputs a new set of attributes. At a minimum, the vertex shader calculates the projected position of the vertex in screen space. But it can also generate other attributes such as colour or texture coordinates for each vertex. You can code your own vertex shader or use one provided by a WebGL library.</p><p>The GPU then connects the projected vertices to form triangles. It does this by taking the vertices in the order specified by the indices array and grouping them into sets of three.</p><p>The <strong>rasterizer</strong> takes each triangle, clips it, discards parts that are outside of the screen, and breaks the remaining visible parts into pixel-sized fragments. The vertex shader's outputs for other vertex attributes are also interpolated across the rasterized surface of each triangle, assigning a smooth gradient of values to each fragment. For example, if the vertex shader assigns a colour value to each vertex, the rasterizer will blend those colours into an appropriate colour gradient across the pixelated surface.</p><p>The generated pixel-sized fragments then pass through another program called the <strong>fragment shader</strong>. The fragment shader outputs colour and depth values for each pixel, which then get drawn into the <strong>framebuffer</strong>. Common fragment shader operations include texture mapping and lighting. Since the fragment shader runs independently for every pixel drawn, it can perform the most sophisticated special effects; however, it is also the most performance-sensitive part of the graphics pipeline. As with the vertex shader, you can code your own fragment shader or use one provided by a WebGL library.</p><p>The <strong>framebuffer</strong> is the final destination for the rendering job's output. A framebuffer is more than a single 2D image: in addition to one or more colour buffers, a framebuffer can have a depth buffer and/or stencil buffer, both of which optionally filter fragments before they are drawn to the framebuffer. Depth testing discards fragments from objects that are behind the ones already drawn, and stencil testing uses shapes drawn into the stencil buffer to constrain the drawable part of the framebuffer, &quot;stencilling&quot; the rendering job. Fragments that survive these two filters have their colour value alpha blended with the colour value they're overwriting. Final colour, depth, and stencil values are drawn into the corresponding buffers. The buffers' outputs can also be used as texture inputs to other rendering jobs.</p><h2 class="get_started">How do I get started using WebGL?</h2><p>The first thing you have to do is <a href="http://dev.opera.com/articles/view/an-introduction-to-webgl/#implementations">get a browser that supports WebGL</a>. You can code WebGL using your favourite JavaScript development environment.</p><p>For your first WebGL project, I'd suggest using a WebGL library. If you have read the previous section you can probably imagine why directly using the WebGL API can be a bit exhausting. Unlike other web APIs, &quot;naked&quot; WebGL can be pretty low level. The people who designed WebGL decided to make it that way to keep it flexible and applicable to any use case, with the idea that libraries would later add a layer of convenience to accelerate and simplify development.</p><p>Most libraries provide a selection of ready-made models, vertex shaders and fragment shaders that can drastically decrease the amount of code you need to write. If you are still not convinced, have a look at the code for an example <a href="http://learningwebgl.com/lessons/lesson11/index.html">3D model of the Moon</a> &mdash; <a href="https://gist.github.com/818017">with a library</a> and <a href="https://github.com/gpjt/webgl-lessons/blob/master/lesson11/index.html">without a library</a>. Even if you just take a quick look, the difference in length and complexity of code is apparent and makes a good case for using a library.</p><p>There are many WebGL libraries. What most do is build on top of WebGL to create elements intuitive to a 3D environment like a scene, a camera, a light source, ambient light, ready-made shapes, materials, textures, and effects such as fog, and floating particles. The idea of these elements remains pretty much the same across libraries. How they are used, however, depends on the library's architecture. Because WebGL can be interactive, most libraries provide easy ways to handle events as well. Finally, most libraries also provide some vertex and fragment shaders. When you do your own library exploration you'll see that this is by no means an exhaustive description of what libraries have to offer, but it gives you a good idea to start with.</p><h3 id="webgllib">Choose a WebGL library!</h3><p>(Not a comprehensive list)</p><dl><dt><a href="https://github.com/mrdoob/three.js#readme">Three.js</a> (<a href="https://github.com/mrdoob/three.js">Three Github repo</a>) </dt><dd>Three.js is a lightweight 3D engine with a very low level of complexity &mdash; in a good way. The engine can render using &lt;canvas&gt;, &lt;svg&gt; and WebGL. This is some info on <a href="http://www.aerotwist.com/lab/getting-started-with-three-js/">how to get started</a>, which has a nice description of the elements in a scene. And here is the Three.js <a href="https://github.com/mrdoob/three.js/wiki/API-Reference">API documentation</a>. Three.js is also the most popular WebGL library in terms of number of users, so you can count on an enthusiastic community (<a href="http://webchat.freenode.net/?channels=three.js">#three.js on irc.freenode.net</a>) to help you out if you get stuck with something. </dd><dt><a href="http://senchalabs.github.com/philogl/">PhiloGL</a> (<a href="https://github.com/senchalabs/philogl">PhiloGL Github repo</a>) </dt><dd>PhiloGL is built with a focus on JavaScript good practices and idioms. Its modules cover a number of categories from program and shader management to XHR, JSONP, effects, web workers and much more. There is an extensive set of <a href="http://senchalabs.github.com/philogl/lessons.html">PhiloGL lessons</a> that you can go through to get started. And the <a href="http://senchalabs.github.com/philogl/doc/index.html">PhiloGL documentation</a> is pretty thorough too. </dd><dt><a href="http://www.glge.org/">GLGE</a> (<a href="https://github.com/supereggbert/GLGE">GLGE Github repo</a>) </dt><dd>GLGE has some more complex features, like skeletal animation and animated materials. You can find a list of <a href="http://www.glge.org/about/">GLGE features on their project website</a>. And here is a link to the <a href="http://www.glge.org/api-docs/">GLGE API documentation</a>. </dd><dt><a href="https://github.com/drojdjou/J3D#readme">J3D</a> (<a href="https://github.com/drojdjou/J3D">J3D Github repo</a>) </dt><dd>J3D allows you not only to create your own scenes but also to export scenes from <a href="http://unity3d.com/">Unity</a> to WebGL. The <a href="https://github.com/drojdjou/J3D/wiki/How-to-create-a-cube">J3D &quot;Hello cube&quot; tutorial</a> can help you get started. Also have a look at this <a href="https://github.com/drojdjou/J3D/wiki/Unity-exporter-tutorial">tutorial on how to export from Unity to J3D</a>.</dd></dl><p class="note">As mentioned, you can also write your own WebGL from scratch, using no libraries. Find out how at <a href="http://learningwebgl.com/blog/?page_id=1217">the Learning WebGL blog</a>.</p><h3>Looking at WebGL code</h3><p>Now it's time to have a look at some actual WebGL code. To make it simpler, this code has been created using a WebGL library. For the following example I have chosen <a href="http://senchalabs.github.com/philogl/">PhiloGL</a> because it has very good <a title="PhiloGL documentation" href="http://senchalabs.github.com/philogl/doc/index.html">documentation</a>, making it a great library for someone who wants to get started with WebGL.</p><p>This code shows some of the basic WebGL features that you may want to include in a simple program. The accompanying notes provide ample explanation, and links to the PhiloGL documentation for further details. You should take this example and experiment, making changes to what's there already and maybe even adding a few things of your own design. If you're curious you can compare this PhiloGL implementation with <a title="3D moon model, in raw WebGL" href="http://learningwebgl.com/blog/?p=1253">its equivalent in &quot;raw&quot; WebGL</a>.</p><p>This scene has been translated into PhiloGL from <a href="http://learningwebgl.com/blog/?p=1253">Learning WebGL lesson #11</a>. It shows a 3D model of the Moon, with textures applied from <a href="http://maps.jpl.nasa.gov/">a NASA Moon map</a>. The Moon can be rotated using drag-and-drop. You can <a href="http://senchalabs.github.com/philogl/PhiloGL/examples/lessons/11/">see the moon example running live</a>.</p><p>The next code snippet shows what your HTML file should look like. We import the PhiloGL script, as downloaded from the <a href="http://senchalabs.github.com/philogl/">PhiloGL website</a>, and the <code>index.js</code> file where we will write our code. We also create a <code>&lt;canvas&gt;</code> element where we want the WebGL scene to be rendered. When the document is loaded, <code>webGLStart();</code> will be called. This function resides in <code>index.js</code> and will initialize the WebGL application.</p><p>&nbsp;</p><p>&nbsp;</p><p>Now Let's walkthrough the code inside <code>index.js</code>. The <code>webGLStart();</code> function is the entry point for creating the WebGL application.</p><p>&nbsp;</p><p>&nbsp;</p><p>The moon is created using the PhiloGL <a href="http://senchalabs.github.com/philogl/doc/o3d.html">O3D module</a>. O3D provides model management and 3D primitives, like the sphere used in this case. The number of parallels (<code>nlat</code>) and meridians (<code>nlong</code>) and the radius are specified. A texture is applied to the sphere from an image file:</p><p>&nbsp;</p><p>&nbsp;</p><p>Next, the WebGL application is created by calling the <a href="http://senchalabs.github.com/philogl/doc/core.html#PhiloGL:constructor">PhiloGL constructor</a>. The PhiloGL constructor automatically creates a WebGL context, a program, a camera, a scene, options for loading textures via IO, events handlers, and more. In this example we are going to use the default shaders, so no <a href="http://senchalabs.github.com/philogl/doc/program.html">program</a> needs to be specified in the constructor. The <a href="http://senchalabs.github.com/philogl/doc/scene.html">scene</a> is also left unspecified. It will be created with its default values. The <a href="http://senchalabs.github.com/philogl/doc/camera.html">camera</a>'s position is modified. We declare a texture from an image source (<code>moon.gif</code>), and use some <a href="http://senchalabs.github.com/philogl/doc/event.html">event</a> handlers: drag-and-drop to rotate, and the mouse scroll to zoom the model.</p><p>&nbsp;</p><p>&nbsp;</p><p>Once the application is created successfully (the WebGL program is compiled, images are loaded and converted to textures, etc.), the <code>onLoad</code> callback will be executed. The first argument to the <code>onLoad</code> callback is a <a href="http://senchalabs.github.com/philogl/doc/webgl.html#WebGL:Application">WebGL application</a>. The WebGL Application class has useful methods to manipulate the program, the camera, the scene, etc. We also get a handle to the WebGL context through the <code>gl</code> property, in case we want to do some fine tuning at the WebGL API level:</p><p>&nbsp;</p><p>&nbsp;</p><p>In this example, users can dynamically modify the lighting values (ambient light colour, point light colour, and position) using a form on the page. Here we get a handle to those form elements:</p><p>&nbsp;</p><p>&nbsp;</p><p>Next we define some basic WebGL setup information: we set opaque black for background colour when clearing the canvas, we enable depth testing (this hides objects that are &quot;behind&quot; other objects in the scene), and we set the viewport to occupy the total width and height of the canvas.</p><p>&nbsp;</p><p>&nbsp;</p><p>Now we add the moon to our scene, and draw it. For each frame in the scene, the <code>draw()</code> function clears the screen, sets up the lighting, renders the moon and makes a request for the next frame to be drawn:</p><p>&nbsp;</p><p>&nbsp;</p><h2>Summary</h2><p>I hope this article gave you a good idea of what WebGL is about and how to get started building a simple WebGL application. Most importantly, however, I hope it got you excited about trying it yourself. We expect to publish more about WebGL in the near future. Stay tuned!</p><p>Useful links for more information:</p><ul>    <li><a href="http://www.khronos.org/message_boards/viewforum.php?f=34">The Khronos WebGL forum</a></li>    <li><a href="http://learningwebgl.com/cookbook/index.php/WebGL:_Frequently_Asked_Questions">Frequently asked questions about WebGL</a></li>    <li><a href="http://learningwebgl.com/blog/">The Learning WebGL blog</a>, a cool place for WebGL news and resources</li></ul><p>Then the data in the vertex arrays is sent to the GPU by feeding it into a set of one or more /aThen the data in the vertex arrays is sent to the GPU by feeding it into a set of one or more</p><p class="note">Read Part 2 of this series: <a href="http://dev.opera.com/articles/view/porting-3d-graphics-to-the-web-webgl-intro-part-2/">Porting 3D graphics to the web</a>.</p><p>&nbsp;</p><pre>   </pre><p>&nbsp;</p><p>原文：http://dev.opera.com/articles/view/an-introduction-to-webgl/</p>]]></description><category>HTML5</category><comments>http://www.zhizihua.com/blog/post/AnintroductiontoWebGL.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=524</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=524&amp;key=724a7078</trackback:ping></item><item><title>开发者应该关注的五项Web 新兴技术</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/开发者应该关注的五项Web新兴技术.html</link><pubDate>Thu, 26 Apr 2012 19:23:41 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/开发者应该关注的五项Web新兴技术.html</guid><description><![CDATA[<p><strong>Bruce Lowson是Opera开放web标准的撰写人员之一，一些没有包含在HTML5之内的浏览器技术十分奇妙，包括WebGL和SVG，作者希望通过本文与共同爱好者们分享。</strong> 最近一位HTML5专家Rich Clark（作者的好朋友）为大家做了一个HTML5 APIs的简介，在文章中为大家指向了一个令人迷惑的网页（web平台：浏览器技术http://platform.html5.org/），其中包含两 个很长的专栏和小正文并提及到一些让人感到迷茫的技术，例如&ldquo;window.crypto.getRandomValues&rdquo;和&ldquo;DOM Mutation observer&rdquo;。</p><p><br />别担心，咱们不去管那些啦，因为有些还远远没有完成呢，在浏览器中见到它们还要等一阵子。然而，其它已经在浏览器中，或者距离您很近，或者马上就要 出现。人们可能将称之为&ldquo;HTML5&rdquo;，尽管它们并不是。其实，它们都属于令人激动的新兴Web技术（New Exciting Web Technology），值得每个开发者关注。<br /><br />&nbsp;<br /><strong>WebGL</strong> <br />WebGL是一种基于Web的Graphic库，由非盈利组织Khronos运营,目前结合HTML5&lt;canvas&gt;元素广泛应用在3D图形开发中。<br /><br />学习WebGL比较困难，因为它是底层开发&mdash;&mdash;它运行在GPU上面，而且它实际上是一个OpenGL的JavaScript port，是一种游戏开发者使用的已经长期建立的API集。WebGL的主要受众是哪些已经拥有丰富OpenGL经验的游戏开发者，他们可以通过 WebGL为web平台编写游戏。<br /><br />好在有很多资源可以帮助您学习WebGL，这些资源不仅仅是关于游戏开发的，还有很多奇幻的图形、视觉和音乐视频等方面。作者个人比较推荐的是：<br />&nbsp;</p><ul>    <li>Introduction to WebGL。<a href="http://dev.opera.com/articles/view/an-introduction-to-webgl/">http://dev.opera.com/articles/view/an-introduction-to-webgl/</a>作者Luz Caballero，简介可以获得的各种库。</li>    <li>Raw WebGL 101。<a href="http://dev.opera.com/articles/view/raw-webgl-part1-getting-started/">http://dev.opera.com/articles/view/raw-webgl-part1-getting-started/</a>适合那些不使用库的用户。</li>    <li>Learning WebGL。<a href="http://learningwebgl.com/">http://learningwebgl.com/</a>一个非常好的引导网站。</li>    <li>WebGL 101。http://www.youtube.com/watch?v=me3BviH3nZc一个由Erik Moller制作的介绍视频（2.5小时）。</li>    <li>See Emberwind。http://operasoftware.github.com/Emberwind/一个由Erik Moller做的WebGL游戏port，您可以深入Github或看代码。 <br />    <a href="http://www.webapptrend.com/wp-content/uploads/2012/03/11.jpg"><img class="alignnone size-large wp-image-2238" title="1" src="http://img.cnbeta.com/newsimg/120323/1558580777418302.jpg" width="614" altheight="452" alt="" /></a><br />    <br />    &nbsp;<br />    <br />    WebGL目前在所有桌面浏览器（发布版和开发频道）中都支持，除了IE10（微软表示不支持）。对于移动产品来说，已经在Opera Mobile 12中发布了，最终会出现在Android，BlackBerry Playbook 2.0，Nokia N900，SonyEricsson Xpertia Android Phones等以及Firefox移动浏览器中。<br />    <strong>SVG</strong> <br />    SVG（Scalable Vector Graphics）已经在Opera，Firefox，Chrome中存在多年了，但是直到IE9开始支持它之后才渐渐变得主流一些它在 HTML5&lt;Canvas&gt;的光环下显得有点暗淡，尽管SVG和HTML5&lt;canvas&gt;是面向不用应用的不同工具。<br />    <br />    Canvas2D可以迅速paint图形到屏幕上面，这一点很犀利。但是其全部功能就是paint了，没有内存来做那些（位置，顶层或其他）其他功 能。如果您需要那种book-keeping工作，就只能自己用JavaScript实现，因为Canvas2D不会把DOM保存到内存中，也正因为如此 Canvas2D速度快，十分适合第一人称射击类应用。<br />    <br />    与Canvas2D不同，SVG在您需要保存DOM的时候就给力了。使用JavaScript，所有的Objects都可以移动并且与动画无关。您 可以试试Daniel Davis做的复古类SVG游戏Inbox Attack（http://people.opera.com/danield/svg/inbox-attack.svg）来体验一下，并且看看源代 码来了解如何完成动画效果。<br />    <br />    <a href="http://www.webapptrend.com/wp-content/uploads/2012/03/21.jpg"><img class="alignnone size-full wp-image-2239" title="2" src="http://img.cnbeta.com/newsimg/120323/15585811732801265.jpg" width="597" altheight="384" alt="" /></a><br />    <br />    因为shape和path是用Markup来描述的，所以他们可以用CSS来定型。与&lt;canvas&gt;不同，text在SVG中保持 text格式并且更加的灵活，更加可扩展，更加易于访问。在Canvas中，text变成了像素，就像Photoshop中的图形text。<br />    <br />    SVG最强大的特性是它基于矢量，这样您的插图，图形和UI图标等都是矢量图了，这样无论是在50英寸的电视屏还是手机屏幕桌面上，看上去感觉都是 一样的清晰。在当今这样一个web应用无处不在的时代，SVG图形甚至可以包括媒体查询（http://my.opera.com/ODIN/blog /2009/10/12/how-media-queries-allow-you-to-optimize-svg-icons-for- several-sizes），可以是响应式的，可以根据不同的目标设备做尺寸的调整。<br />    <br />    综上所述，在最新的桌面浏览器中SVG已经能被广泛支持了。在移动产品方面的支持总体上来说也很好，以及预期在Android 3.0版本之前原生浏览器也会支持它了。<br />    <br />    Daniel Davis有一些SVG 介绍性的资源（http://my.opera.com/tagawa/blog/learning-svg），作者个人也推荐一本免费的电子 书：Learn SVG（http://www.learnsvg.com/book-learnsvg/），您也可以看看《SVG or Canvas？Choosing Between the Two》（http://dev.opera.com/articles/view/svg-or-canvas-choosing-between- the-two/）来了解二者的区别。<br />    <br />    <strong>getUserMedia</strong> <br />    <br />    不像那些被错误地称为HTML5的API，getUserMeida（在下文中简写为gUM）有个相对正当的理由：起初它是HTML5&lt;device&gt;元素，之后它改名了然后离开了W3C WebRTC规范集合。<br />    <br />    gUM允许访问用户的摄像头和麦克风，本来是在WebRTC规范中在浏览器中进行P2P视频会议的，当gUM拥有了其他的用途，就离开了WebRTC。<br />    <br />    摄像头的访问最终在Opera12安卓版，Opera桌面实验室和Google Chrome Canary里面实现了，不过Opera和Chrome都还没有实现麦克风的接入。<br />    <br />    W3C规范依然在用，所以Opera和Webkit有不同的语法规范，这样的麻烦被一个叫做The gUM Shield（https://gist.github.com/f2ac64ed7fc467ccdfe3）的小JavaScript片段搞定了。如果 您想更深入地了解这方面请看作者的另一篇文章：It&rsquo;s Curtains for Marital Strife Thanks to getUserMedia（<a href="http://html5doctor.com/getusermedia/">http://html5doctor.com/getusermedia/</a>）<br />    <br />    当视频从设备开始流传输的时候，源数据可以被做成变成了&lt;video&gt;元素，如果需要的话还可以被定为到屏幕外面，然后拷贝 到&lt;canvas&gt;里面进行所需要的操作。Paul Neave写的《HTML5 变成玩具！》（http://neave.com/webcam/html5/）为了方便操作把流媒体数据拷贝到WebGL中。作者在.net 杂志的226话有采访他的报导（<a href="http://www.netmagazine.com/shop/magazines/april-2012-226">http://www.netmagazine.com/shop/magazines/april-2012-226</a>）。<br />    <br />    <a href="http://www.webapptrend.com/wp-content/uploads/2012/03/3.jpg"><img class="alignnone size-full wp-image-2240" title="3" src="http://img.cnbeta.com/newsimg/120323/15585821835695776.jpg" width="559" altheight="392" alt="" /></a><br />    <br />    如果想把web app的功能做得像native app，gUM需要做很多的工作。试了一下Neaver的gum和WebGL 在Opera Mobile 12上面的demo，感觉和平台独有的app一样富有响应式并且很时髦。当在浏览器产品中其功能被广泛应用的时候，作者语言会有很多基于web的QR代码 阅读者以及很多增强现实的应用。<br />    <br />    <strong>File APIs</strong> <br />    <br />    W3C File APIs允许JavaScript访问本地文件，其中最常用的API是FileReader，可以从Opera，FireFox，IE10平台等的预览版看到（不包括Safari）。<br />    <br />    这一份W3C规范&ldquo;为了在web应用中提供API来代表文件对象，以及编程选择和访问数据&rdquo;。例如：你可以上传文件到浏览器中，并本地查找相关信息 （例如文件名，尺寸，类型）而不需要到服务器端。您也可以打开文件，操作内容，这样可以加强基于浏览器的应用的交互性，用起来更像是本地应用。<br />    <br />    另一个常用的用途是使传统的图像上传兑换狂更具有Web2.0特色：通过允许在浏览器内部的Drag and Drop，而不是本地文件系统中改变。<br />    <br />    您可以通过使用一个普通的&lt;input type=&rdquo;file&rdquo;&gt;开始，然后循序渐进地提高。HTML5 Drag&amp;Drop支持特征检测，如果存在的话就使用&lt;div&gt;替换&lt;input&gt;，那就是您的drag图像目标了。当 图像被drag到目标的时候，使用File Reader API来显示一个指甲盖大小的图像。您可以看一下Remy Sharp的demo（http://html5demos.com/file-api）。<br />    <br />    还有很多写文件和操作文件系统的规范，不过这些对目前的跨浏览器应用来说还不太够：<br />    <br />    W3C文件API：（http://dev.opera.com/articles/view/the-w3c-file-api/）非常基础的介绍。<br />    <br />    开发文件系统API：（http://www.html5rocks.com/en/tutorials/file/filesystem/）HTML5 Rocks文章，（仅限Chrome）。<br />    <strong>Feature-detecting, progressive enhancement and upgrade messages（特征检测，渐进式增强和消息通知）</strong> <br />    诚然，在没有那些奇幻的API的时候，大家总是试图使用渐进式增强和HTML语义的方法让网站照常工作。然而有时候却不能这样，例如Paul Neaver的《HTML5变成玩具》中，如果gUM和WebGL现在不存在的话，其网站不能有什么补救措施了，整个网站的核心都没了。<br />    <br />    在这样的情况下有两种典型的惯例：要么是显示一条消息说&ldquo;你的浏览器太垃圾了，塞油哪啦&rdquo;或者说&ldquo;你必须用Chrome6/Firefox 4/Opera10等[插入能支持你应用的浏览器]才能访问&rdquo;。第一种方法又没用又粗鲁，没有建议和补救措施；第二种方法是个临时办法，因为六个月之内所 有浏览器可能都能支持你现在使用的技术了，让你在网站上留下的信息过时：例如您写的解决方案是建议使用Firefox4来访问，可是半年后用户安装着 Firefox7回来访问你的页面了，这可就真的没救了。<br />    <br />    如果您真的不能使用渐进式增强，那么就用新型的HTML 5 Please API吧（http://api.html5please.com/）。这是Jon Neal，Divya Manian和其他几位大虾创作的。通过使用它，可以先查询caniuse.com然后返回一个最新（能支持你的新特性的）的浏览器版本列表。<br />    <br />    如果您已经做了一个需要Canvas或WebSQL DB技术的DEMO或者网站，恐怕你已经处在一个这样的尴尬境地了：您只是在告诉访问者们他们的浏览器不咋地。但是您不能只推荐他们使用一个能支持这些特 性的浏览器来补救，例如&ldquo;找个支持WebRTC性能的浏览器再来吧&rdquo;，这样对于大家都没啥效果。<br />    <br />    HTML5 Please API把开发人员的语言（和特性）翻译成用户能理解的语言（浏览器）。通过调用这个API你就可以得到一些HTML返回值来告诉访问者，或者返回一个带有 相关数据的JSON对象（包括浏览器Logo及下载介绍等信息）。这样您可以根据不同的客户来显示不同的补救信息了。<br />    <br />    使用这种方式最令人欣慰的是：如果所有新特性在客户当前浏览器的升级版都能支持的情况下，Please API值建议访客对浏览器升级，而不是让访客单纯为了访问你这个页面而更换浏览器。效果图如下：<br />    <br />    <a href="http://www.webapptrend.com/wp-content/uploads/2012/03/41.png"><img class="alignnone size-full wp-image-2241" title="4" src="http://img.cnbeta.com/newsimg/120323/15585831183969994.png" width="563" altheight="75" alt="" /></a><br />    <br />    <strong>结束语：</strong><br />    <br />    正如您所看到的，大量的令人惊喜的新技术正在接踵而至，您着手研究上述某项技术的时候恐怕又要担心更新鲜的技术到来了吧。希望您开发得愉快，请记得让您所开发的应用在尽可能多的浏览器上面测试一下。<br />    <br />    &nbsp;</li></ul>]]></description><category>HTML5</category><comments>http://www.zhizihua.com/blog/post/开发者应该关注的五项Web新兴技术.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=523</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=523&amp;key=3248fd92</trackback:ping></item><item><title>利用SVN hook机制 限制提交必须填写注释</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/利用SVNhook机制限制提交必须填写注释.html</link><pubDate>Wed, 18 Apr 2012 21:53:41 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/利用SVNhook机制限制提交必须填写注释.html</guid><description><![CDATA[<p>&nbsp;<span style="color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; font-size: 14px; line-height: 20px; ">进入svn data文件夹下你的repos</span></p><div class="content" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 0px; padding-bottom: 0px; padding-left: 5px; line-height: 20px; overflow-x: hidden; overflow-y: hidden; font-size: 14px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">会发现里面会有这些文件夹</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.iamued.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(244, 245, 247); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; background-position: 3px 3px; background-repeat: no-repeat no-repeat; ">|-- README.txt|-- conf|-- dav|-- db|-- format|-- hooks`-- locks</pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">此次我们会用到的就是hooks<br />SVN已经为我们提供了一些hook模板<br />cp pre-commit.tmpl pre-commit 复制一份<br />chmod +x pre-commit 增加可执行权限<br />然后修改其内容<br />ok啦！<br />内容如下</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.iamued.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(244, 245, 247); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; background-position: 3px 3px; background-repeat: no-repeat no-repeat; ">REPOS=&quot;$1&quot;TXN=&quot;$2&quot;RES=&quot;OK&quot;# Make sure that the log message contains some text.SVNLOOK=/app/subversion/bin/svnlook$SVNLOOK log -t &quot;$TXN&quot; &quot;$REPOS&quot; | egrep &quot;[^[:space:]]+&quot; &gt;/dev/null || unset RESif [ &quot;$RES&quot; != &quot;OK&quot; ]then    echo &quot;You must input some comments for you commit&quot; &gt;&amp;2    exit 1fi# All checks passed, so allow the commit.exit 0</pre><div class="fixed" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; clear: both; ">&nbsp;</div></div><div class="under" style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 0px; padding-left: 5px; height: 25px; line-height: 25px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(232, 232, 232); border-right-color: rgb(232, 232, 232); border-bottom-color: rgb(232, 232, 232); border-left-color: rgb(232, 232, 232); border-image: initial; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; ">&nbsp;</div>]]></description><category>软件开发</category><comments>http://www.zhizihua.com/blog/post/利用SVNhook机制限制提交必须填写注释.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=522</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=522&amp;key=ec49e096</trackback:ping></item><item><title>OneRing桌面应用框架</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/OneRing桌面应用框架.html</link><pubDate>Sun, 15 Apr 2012 22:59:14 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/OneRing桌面应用框架.html</guid><description><![CDATA[<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font: normal normal normal 12px/normal 'Microsoft YaHei'; "><span style="font: normal normal normal 12px/normal Helvetica; ">OneRing&nbsp;</span>是由豆瓣首席架构师洪强宁开发的一款跨平台桌面应用框架,它支持使用前端技术 开发桌面客户端。即将发布的豆瓣电台桌面版(<span style="font: normal normal normal 12px/normal Helvetica; ">PC/Mac</span>)便是基于&nbsp;<span style="font: normal normal normal 12px/normal Helvetica; ">OneRing&nbsp;</span>完成的,<span style="font: normal normal normal 12px/normal Helvetica; ">HTML5&nbsp;</span>新增的<span style="font: normal normal normal 12px/normal Helvetica; ">&lt;audio&gt;</span>元素与相应的&nbsp;<span style="font: normal normal normal 12px/normal Helvetica; ">API&nbsp;</span>在其中发挥了重要的作用,相信很快就会和大家见面。&nbsp;<span style="font: normal normal normal 12px/normal Helvetica; ">OneRing&nbsp;</span>项目主页:<span style="font: normal normal normal 12px/normal Helvetica; color: rgb(71, 75, 255); ">http://code.google.com/p/onering-desktop/</span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font: normal normal normal 12px/normal 'Microsoft YaHei'; "><span style="font: normal normal normal 12px/normal Helvetica; color: rgb(71, 75, 255); "><br /></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font: normal normal normal 12px/normal 'Microsoft YaHei'; "><span style="font: normal normal normal 12px/normal Helvetica; color: rgb(71, 75, 255); "><br /></span></p><h2 style="margin-top: 10px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; font-family: Verdana, 'BitStream vera Sans'; font-size: medium; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); color: rgb(85, 85, 85); line-height: 17px; ">框架目标</h2><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; "><a href="http://code.google.com/p/onering-desktop/wiki/OneRing" style="color: rgb(41, 112, 166); text-decoration: none; ">OneRing</a>是一个跨平台的桌面应用框架。和Adobe AIR类似，它支持用html/js/css制作用户界面，与之不同的是，它的应用为本地程序，可以直接访问操作系统的数据。</p><h2 style="margin-top: 10px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; font-family: Verdana, 'BitStream vera Sans'; font-size: medium; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); color: rgb(85, 85, 85); line-height: 17px; "><a name="架构" style="color: rgb(41, 112, 166); text-decoration: none; "></a>架构</h2><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">一个<a href="http://code.google.com/p/onering-desktop/wiki/OneRing" style="color: rgb(41, 112, 166); text-decoration: none; ">OneRing</a>应用程序分为两个部分：框架部分和应用部分。</p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: 18px; color: rgb(85, 85, 85); line-height: 17px; "><a name="框架部分" style="color: rgb(41, 112, 166); text-decoration: none; "></a>框架部分</h3><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">框架部分为通用框架，各应用都一样。其提供各操作系统上的界面展现，为本地窗口内嵌一个WebKit浏览器，并提供一致的js接口让应用和操作系统功能进行交互。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">框架以运行时库的形式提供。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">框架以系统原生语言编写，提供其他语言的绑定。</p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: 18px; color: rgb(85, 85, 85); line-height: 17px; "><a name="应用部分" style="color: rgb(41, 112, 166); text-decoration: none; "></a>应用部分</h3><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">应用部分为一个web server，负责应用逻辑，用html/css描述界面，用js提供用户交互。</p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: 18px; color: rgb(85, 85, 85); line-height: 17px; "><a name="运行流程" style="color: rgb(41, 112, 166); text-decoration: none; "></a>运行流程</h3><ol style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 10px; padding-left: 40px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">应用启动时，会加载框架的运行时库，注册应用url的访问方法（如WSGI），并调用框架的loop函数。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">loop函数会访问应用的&nbsp;<tt>/init</tt>&nbsp;URL，得到一个json数据，描述初始应用窗口的相关参数，如位置、大小、窗口属性、初始页面url等。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">框架根据该数据创建窗口，并让该窗口内的浏览器访问初始页面url，渲染用户界面，然后等待UI事件。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">用户在界面上操作时，可以通过超链接改变整个窗口内容，也可以使用AJAX技术更新窗口内部分内容。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">应用可以让浏览器调用<tt>ONERING</tt>名字空间下的<a href="http://code.google.com/p/onering-desktop/wiki/OneRingJsInterface" style="color: rgb(41, 112, 166); text-decoration: none; ">js函数</a>，和操作系统进行交互，该名字空间由url&nbsp;<tt>onering://onering/onering.js</tt>&nbsp;加载。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">应用通过&nbsp;<tt>bind(event, function)</tt>&nbsp;函数监听窗口更改大小、移动等操作系统UI事件。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">可以使用pub/sub机制主动推送消息给浏览器。</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">调用&nbsp;<tt>ONERING.exit()</tt>&nbsp;可以退出应用；所有窗口都关闭后也会退出应用。</li></ol><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: 18px; color: rgb(85, 85, 85); line-height: 17px; "><a name="Python应用示例" style="color: rgb(41, 112, 166); text-decoration: none; "></a>Python应用示例</h3><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="com">#!/usr/bin/env python</span><span class="kwd">import</span><span class="pln"> json</span><span class="kwd">import</span><span class="pln"> web</span><span class="kwd">import</span><span class="pln"> onering urls </span><span class="pun">=</span><span class="pun">(</span><span class="pln">&nbsp; &nbsp; </span><span class="str">'/init'</span><span class="pun">,</span><span class="str">'init'</span><span class="pun">,</span><span class="pln">&nbsp; &nbsp; </span><span class="str">'/'</span><span class="pun">,</span><span class="str">'index'</span><span class="pun">, </span><span class="pun">)</span><span class="kwd">class</span><span class="pln"> init</span><span class="pun">:</span><span class="pln">&nbsp; &nbsp; </span><span class="kwd">def</span><span class="pln"> GET</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">&nbsp; &nbsp; &nbsp; &nbsp; web</span><span class="pun">.</span><span class="pln">header</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">,</span><span class="str">'application/json'</span><span class="pun">)</span><span class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="kwd">return</span><span class="pln"> json</span><span class="pun">.</span><span class="pln">dumps</span><span class="pun">({</span><span class="str">'width'</span><span class="pun">:</span><span class="lit">400</span><span class="pun">,</span><span class="str">'height'</span><span class="pun">:</span><span class="lit">300</span><span class="pun">,</span><span class="str">'url'</span><span class="pun">:</span><span class="str">'/'</span><span class="pun">})</span><span class="kwd">class</span><span class="pln"> index</span><span class="pun">:</span><span class="pln">&nbsp; &nbsp; </span><span class="kwd">def</span><span class="pln"> GET</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">):</span><span class="pln">&nbsp; &nbsp; &nbsp; &nbsp; web</span><span class="pun">.</span><span class="pln">header</span><span class="pun">(</span><span class="str">'Content-Type'</span><span class="pun">,</span><span class="str">'text/html'</span><span class="pun">)</span><span class="pln">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="kwd">return</span><span class="str">&quot;&quot;&quot;&lt;html&gt;&lt;head&gt;&lt;script type=&quot;</span><span class="pln">text</span><span class="pun">/</span><span class="pln">javascript</span><span class="str">&quot; src=&quot;</span><span class="pln">onering</span><span class="pun">:</span><span class="com">//onering/onering.js&quot;&gt;&lt;/script&gt;&lt;/head&gt;</span><span class="str">&lt;body&gt;</span><span class="str">&lt;p&gt;</span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> world</span><span class="pun">!&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pun">&lt;</span><span class="pln">button onclick</span><span class="pun">=</span><span class="str">&quot;javascript:ONERING.exit()&quot;</span><span class="pun">&gt;</span><span class="typ">Exit</span><span class="pun">&lt;</span><span class="str">/button&gt;&lt;/</span><span class="pln">body</span><span class="pun">&gt;&lt;/</span><span class="pln">html</span><span class="pun">&gt;</span><span class="str">&quot;&quot;&quot; app = web.application(urls, globals()) if __name__ == '__main__':&nbsp; &nbsp; onering.register_wsgi_app(&quot;</span><span class="pln">demo</span><span class="str">&quot;, app.wsgifunc())&nbsp; &nbsp; onering.loop(&quot;</span><span class="pln">demo</span><span class="str">&quot;)</span></pre><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: 18px; color: rgb(85, 85, 85); line-height: 17px; "><a name="各组件之间的交互" style="color: rgb(41, 112, 166); text-decoration: none; "></a>各组件之间的交互</h3><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">一个<a href="http://code.google.com/p/onering-desktop/wiki/OneRing" style="color: rgb(41, 112, 166); text-decoration: none; ">OneRing</a>应用中，存在三个需要互相通讯的组件:</p><ol style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 10px; padding-left: 40px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">操作系统 OS ，控制窗口行为（如最小化窗口），及操作系统相关界面元素（如系统通知图标）</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">运行在WebKit内的javascript，控制界面内元素（如程序界面里的按钮）</li>    <li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 20px; list-style-position: inside; ">WSGI应用，控制HTML/JS的生成逻辑，以及应用相关的后台逻辑</li></ol><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: x-small; color: rgb(0, 136, 0); line-height: 17px; "><a name="js_-&gt;_os" style="color: rgb(41, 112, 166); text-decoration: none; "></a>js -&gt; os</h4><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">当js需要通知os对js所在窗口做某个行为（如最小化），通过调用 onering.js 中的get_current<br />_window()返回值（为Window对象）的相应方法实现：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="kwd">var</span><span class="pln"> current_window </span><span class="pun">=</span><span class="pln"> ONERING</span><span class="pun">.</span><span class="pln">get_current_window</span><span class="pun">();</span><span class="pln">current_window</span><span class="pun">.</span><span class="pln">minimize</span><span class="pun">();</span></pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">当js需要os执行整个应用层面的操作时（如结束应用），通过调用 onering.js 中的函数实现：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">ONERING</span><span class="pun">.</span><span class="kwd">exit</span><span class="pun">();</span></pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">当js需要os创建一个新窗口时，通过调用createWindow函数实现，并获得新建窗体的句柄实例：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">new_window </span><span class="pun">=</span><span class="pln"> ONERING</span><span class="pun">.</span><span class="pln">createWindow</span><span class="pun">(</span><span class="str">'/a_dialog'</span><span class="pun">,</span><span class="lit">400</span><span class="pun">,</span><span class="lit">300</span><span class="pun">);</span></pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">当js需要向另一个窗口做某个os行为时（如隐藏另一个窗口），通过调用窗体的句柄实例的方法实现：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">new_window</span><span class="pun">.</span><span class="pln">hide</span><span class="pun">();</span></pre><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: x-small; color: rgb(0, 136, 0); line-height: 17px; "><a name="os_-&gt;_js" style="color: rgb(41, 112, 166); text-decoration: none; "></a>os -&gt; js</h4><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">js可以通过bind机制，关注操作系统发生的时间（如窗口大小改变）：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">current_window</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'resize'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">)</span><span class="pun">{</span><span class="pln">&nbsp; &nbsp; </span><span class="kwd">if</span><span class="pun">(</span><span class="kwd">event</span><span class="pun">.</span><span class="pln">width </span><span class="pun">&lt;</span><span class="lit">300</span><span class="pun">)</span><span class="pun">{</span><span class="pln">&nbsp; &nbsp; &nbsp; &nbsp; $</span><span class="pun">(</span><span class="str">'#sidebar'</span><span class="pun">).</span><span class="pln">hide</span><span class="pun">();</span><span class="pln">&nbsp; &nbsp; </span><span class="pun">}</span><span class="pun">});</span></pre><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: x-small; color: rgb(0, 136, 0); line-height: 17px; "><a name="js_-&gt;_app" style="color: rgb(41, 112, 166); text-decoration: none; "></a>js -&gt; app</h4><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">js可以通过类AJAX调用，从app获取数据。</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">ONERING</span><span class="pun">.</span><span class="pln">getJSON</span><span class="pun">(</span><span class="str">'/userdata.json'</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pun">{</span><span class="pln">&nbsp; &nbsp; </span><span class="pun">...</span><span class="pun">});</span></pre><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: Arial; font-size: x-small; color: rgb(0, 136, 0); line-height: 17px; "><a name="app_-&gt;_js" style="color: rgb(41, 112, 166); text-decoration: none; "></a>app -&gt; js</h4><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">app希望向窗体内的js主动推送消息时，可以采用pub/sub机制。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">首先js通知框架自己关注的事件:</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="pln">current_window</span><span class="pun">.</span><span class="pln">subscribe</span><span class="pun">(</span><span class="str">&quot;a_file_scanned&quot;</span><span class="pun">,</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">fileinfo</span><span class="pun">)</span><span class="pun">{</span><span class="pln">&nbsp; </span><span class="pun">...</span><span class="pun">});</span></pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">然后当app希望发送消息时，调用onering框架提供的publish方法：</p><pre style="margin-top: 5px; margin-bottom: 5px; padding-top: 8px; padding-right: 12px; padding-bottom: 8px; padding-left: 36px; background-image: url(http://www.webguo.com/wp-content/themes/inove/img/blockquote.gif); background-attachment: initial; background-origin: initial; background-clip: initial; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-image: initial; color: rgb(85, 85, 85); line-height: 17px; background-position: 3px 3px; background-repeat: no-repeat no-repeat; "><span class="kwd">for</span><span class="pln"> fileinfo </span><span class="kwd">in</span><span class="pln"> scan_files</span><span class="pun">():</span><span class="pln">&nbsp; &nbsp; onering</span><span class="pun">.</span><span class="pln">publish</span><span class="pun">(</span><span class="str">&quot;a_file_scanned&quot;</span><span class="pun">,</span><span class="pln"> fileinfo</span><span class="pun">);</span></pre><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: rgb(85, 85, 85); font-family: Verdana, 'BitStream vera Sans', Tahoma, Helvetica, sans-serif; line-height: 17px; ">其中的fileinfo为可以转化为JSON的python对象（即 json.dumps(fileinfo) 不会抛出异常）。</p>]]></description><category>软件开发</category><comments>http://www.zhizihua.com/blog/post/OneRing桌面应用框架.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=521</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=521&amp;key=3ce38197</trackback:ping></item><item><title>Protocol Buffers, Avro, Thrift &amp;amp; MessagePack</title><author>zhnwyz@gmail.com (zhizihua)</author><link>http://www.zhizihua.com/blog/post/ProtocolBuffers,Avro,Thrift&amp;amp;MessagePack.html</link><pubDate>Fri, 13 Apr 2012 22:20:07 +0800</pubDate><guid>http://www.zhizihua.com/blog/post/ProtocolBuffers,Avro,Thrift&amp;amp;MessagePack.html</guid><description><![CDATA[<p>&nbsp;</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; "><img src="http://www.igvita.com/posts/11/avro-fb-gb-json.png" class="left" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; float: left; margin-right: 1em; " alt="" />Perhaps one of the first inescapable observations that a new Google developer (<em>Noogler</em>) makes once they dive into the code is that&nbsp;<a href="http://code.google.com/p/protobuf/" style="color: rgb(102, 17, 204); ">Protocol Buffers</a>&nbsp;(PB) is the &quot;language of data&quot; at Google. Put simply,&nbsp;<strong style="font-weight: bold; ">Protocol Buffers are used for serialization, RPC, and about everything in between</strong>.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">Initially developed in early 2000's as an optimized server request/response protocol (hence the name), they have become the de-facto data persistence format and RPC protocol. Later, following a major (v2) rewrite in 2008, Protocol Buffers was&nbsp;<a href="http://google-opensource.blogspot.com/2008/07/protocol-buffers-googles-data.html" style="color: rgb(102, 17, 204); ">open sourced by Google</a>&nbsp;and now, through a number of&nbsp;<a href="http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns" style="color: rgb(102, 17, 204); ">third party extensions</a>, can be used across dozens of languages - including Ruby, of course.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">But, Protocol Buffers for&nbsp;<em>everything?</em>&nbsp;Well, it appears to work for Google, but more importantly I think this is a great example of where&nbsp;<strong style="font-weight: bold; ">understanding the historical context in which each was developed is just as instrumental as comparing features and&nbsp;<a href="https://github.com/eishay/jvm-serializers/wiki/" style="color: rgb(102, 17, 204); ">benchmarking speed</a></strong>.</p><h2 style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; ">Protocol Buffers vs. Thrift</h2><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">Let's take a step back and compare Protocol Buffers to the &quot;competitors&quot;, of which there are plenty. Between PB,<a href="http://thrift.apache.org/" style="color: rgb(102, 17, 204); ">Thrift</a>,&nbsp;<a href="http://avro.apache.org/" style="color: rgb(102, 17, 204); ">Avro</a>&nbsp;and&nbsp;<a href="http://msgpack.org/" style="color: rgb(102, 17, 204); ">MessagePack</a>, which is the best? Truth of the matter is, they are all very good and each has its own strong points. Hence, the answer is as much of a personal choice, as well as understanding of the historical context for each, and correctly identifying your own, individual requirements.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">When Protocol Buffers was first being developed (early 2000's), the preferred language at Google was C++ (nowadays, Java is on par). Hence it should not be surprising that PB is strongly typed, has a separate schema file, and also requires a compilation step to output the language-specific boilerplate to read and serialize messages. To achieve this, Google defined their own language (<a href="http://en.wikipedia.org/wiki/Interface_description_language" style="color: rgb(102, 17, 204); ">IDL</a>) for specifying the proto files, and limited PB's design scope to efficient serialization of common types and attributes found in Java, C++ and Python. Hence,&nbsp;<strong style="font-weight: bold; ">PB was designed to be layered over an (existing) RPC mechanism</strong>.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; "><img src="http://www.igvita.com/posts/11/facebook-thrift.png" class="left" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; float: left; margin-right: 1em; " alt="" />By comparison, Thrift which was&nbsp;<a href="http://www.igvita.com/2007/11/30/ruby-web-services-with-facebooks-thrift/" style="color: rgb(102, 17, 204); ">open sourced by Facebook in late 2007</a>, looks and feels very similar to Protocol Buffers - in all likelihood, there was some design influence from PB there. However, unlike PB,&nbsp;<strong style="font-weight: bold; ">Thrift makes RPC a first class citizen</strong>: Thrift compiler provides a variety of transport options (network, file, memory), and also tries to target&nbsp;<a href="http://wiki.apache.org/thrift/LibraryFeatures?action=show&amp;redirect=LanguageSupport" style="color: rgb(102, 17, 204); ">many more languages</a>.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">Which is the&nbsp;<em>&quot;better&quot;</em>&nbsp;of the two? Both have been production tested at scale, so it really depends on your own situation. If you are primarily interested in the binary serialization, or if you already have an RPC mechanism then Protocol Buffers is a great place to start. Conversely, if you don't yet have an RPC mechanism and are looking for one, then Thrift may be a good choice.&nbsp;<em>(Word of warning: historically, Thrift has not been consistent in their feature support and performance across all the languages, so&nbsp;<a href="http://floatingsun.net/articles/thrift-vs-protocol-buffers/" style="color: rgb(102, 17, 204); ">do some research</a>).</em></p><h2 style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; ">Protocol Buffers vs. Avro, MessagePack</h2><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">While Thrift and PB differ primarily in their scope,&nbsp;<strong style="font-weight: bold; ">Avro and MessagePack should really be compared in light of the more recent trends: rising popularity of dynamic languages, and JSON over XML</strong>. As most every web developers knows, JSON is now&nbsp;<a href="http://json.org/" style="color: rgb(102, 17, 204); ">ubiquitous</a>, and easy to parse, generate, and read, which explains its popularity. JSON also requires no schema, provides no type checking, and it is a UTF-8 based protocol - in other words, easy to work with, but not very efficient when put on the wire.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; "><strong style="font-weight: bold; ">MessagePack is effectively JSON, but with efficient binary encoding.</strong>&nbsp;Like JSON, there is no type checking or schemas, which depending on your application can be either be a pro or a con. But, if you are already streaming JSON via an API or using it for storage, then MessagePack can be a drop-in replacement.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; "><img src="http://www.igvita.com/posts/11/avro.png" class="left" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-image: initial; float: left; margin-right: 1em; " alt="" /><strong style="font-weight: bold; "><a href="http://avro.apache.org/" style="color: rgb(102, 17, 204); ">Avro</a>, on the other hand, is somewhat of a hybrid. In its scope and functionality it is close to PB and Thrift, but it was&nbsp;<a href="http://www.igvita.com/2010/02/16/data-serialization-rpc-with-avro-ruby/" style="color: rgb(102, 17, 204); ">designed with dynamic languages in mind</a></strong>. Unlike PB and Thrift, the Avro schema is embedded directly in the header of the messages, which eliminates the need for the extra compile stage. Additionally, the schema itself is just a JSON blob - no custom parser required! By enforcing a schema Avro allows us to do data projections (read individual fields out of each record), perform type checking, and enforce the overall message structure.</p><h2 style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; ">&quot;The Best&quot; Serialization Format</h2><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">Reflecting on the use of Protocol Buffers at Google and all of the above competitors it is clear that there is no one definitive,&nbsp;<em>&quot;best&quot;</em>&nbsp;option. Rather, each solution makes perfect sense in the context it was developed and hence the same logic should be applied to your own situation.</p><p style="color: rgb(51, 51, 51); font-family: 'Open Sans', sans-serif; font-size: 14px; line-height: 22px; ">If you are looking for a battle-tested, strongly typed serialization format, then Protocol Buffers is a great choice. If you also need a variety of built-in RPC mechanisms, then Thrift is worth investigating. If you are already exchanging or working with JSON, then MessagePack is almost a drop-in optimization. And finally, if you like the strongly typed aspects, but want the flexibility of easy interoperability with dynamic languages, then Avro may be your best bet at this point in time.</p>]]></description><category>C&amp;amp;C++</category><comments>http://www.zhizihua.com/blog/post/ProtocolBuffers,Avro,Thrift&amp;MessagePack.html#comment</comments><wfw:comment>http://www.zhizihua.com/blog/</wfw:comment><wfw:commentRss>http://www.zhizihua.com/blog/feed.asp?cmt=520</wfw:commentRss><trackback:ping>http://www.zhizihua.com/blog/cmd.asp?act=tb&amp;id=520&amp;key=1147b899</trackback:ping></item></channel></rss>

