Archive for 五月, 2011

昨天在ie6下测试了我们的新产品,页面惨不忍睹,还有几个js错误。

由于我用来mootools框架,所以js错误还比较简单。首先要坚信的一点是,mootools的浏览器兼容性很好,问题不会出在框架中。

ie及ie核的浏览器(如360),js句子末尾不能有多余的逗号(,)。

另外,如果报a.window之类为null或不存在,则检查页面源文件,是否有重复的mootools引用。

css的问题比较痛苦,我不是科班前端工程师,也没啥经验,折腾了一晚上,四处问人和google,才搞定。

1、png图片慎用。IE下不论img还是background,如果用了png,都会出现死难看的图片背景。可以通过滤镜调整,但是毕竟麻烦,所以能不用png,就别用png图片。

我现在只会用简单的滤镜,请看DEMO,效果如下:

问题:png图片和gif、jpg图片各适用于什么情况?

问题:滤镜的详解?

参考了这个页面:http://www.jb51.net/css/28992.html

2、ie6下内嵌元素margin加倍

内嵌元素的margin-left会被加倍,请看demo

为了消除这种加倍,可以添加display: inline;样式。

3、table的样式

一般的table都可以这样写:<table border=”0″ cellpadding=”0″ cellspacing=”0″></table>,不使用table的属性去干涉样式,而使用css。

另外,当用table的border或css的border规定边框时,在ie6下,如果td、th内容为空,是不显示边框的,所以可以写成:<td>&nbsp;</td>。

table column width常用指定方式有两种:fixed、percentage。

4、纵margin合并(所有浏览器)

如果两个或两个以上的纵边距紧挨在一起,它们的纵边距会变成两个间较大margin的值,而非其和。

框内部也会发生纵margin合并。比如一个div内部套了一个p,如果div没有border,则在某些浏览器下也会发生margin合并。另外可以看出各個浏览器的默认font-size是不同的,最好自己设置。

请看demo

5、怎样做table thead的圆角背景

先做一个两边有圆角的背景图,应用到thead th上,比如圆角width是10px:

background: url(‘title-bg.png’) no-repeat scroll -10px top transparent;/* -10px 就把圆角隐藏了 */

两边的class:

.tshare thead th.column-left {
background-position: left top; /* or 0px 0px */
}
.tshare thead th.column-right {
background-position: right top;
}
需要注意到是,由于中间的td no-repeat地使用该背景图,所以背景图去除掉两边圆角的宽度必须比最宽的td还要宽。

table默认情况下,会自动根据内容计算th、td的宽度。如果想强制th不换行,使用white-space: nowrap;即可。

请看demo

————————————–

12、清除浮动

如果你想用div(或其他容器)包裹一个浮动的元素,你会发现必须给div(容器)定义明确的height、width、overflow之中一个属性(除了auto值)才能将浮动元素严实地包裹。

#container {border:1px solid #333; overflow:auto; height:100%;}
#floated1 {float:left; height:300px; width:200px; background:#00F;}
#floated2 {float:right; height:400px; width:200px; background:#F0F;}
更多: http://www.twinsenliang.net/skill/20090413.html

13、浮动层错位

当内容超出外包容器定义的宽度时,在IE6中容器会忽视定义的width值,宽度会错误地随内容宽度增长而增长。

浮动层错位问题在IE6下没有真正让人满意的解决方法,虽然可以使用overflow:hidden;或overflow:scroll;来修正, 但hidden容易导致其他一些问题,scroll会破坏设计;JavaScript也没法很好地解决这个问题。所以建议是一定要在布局上避免这个问题发 生,使用一个固定的布局或者控制好内容的宽度(给内层加width)。

14、躲猫猫bug

在IE6和IE7下,躲猫猫bug是一个非常恼人的问题。一个撑破了容器的浮动元素,如果在他之后有不浮动的内容,并且有一些定义了:hover的链接,当鼠标移到那些链接上时,在IE6下就会触发躲猫猫。

解决方法很简单:
1.在(那个未浮动的)内容之后添加一个<span style=”clear: both;”> </span>
2.触发包含了这些链接的容器的hasLayout,一个简单的方法就是给其定义height:1%;

InfoQ:你好,Alex。能向我们的读者介绍一下你自己和目前正在从事的工作吗?

Alex:大家好,我是董洵,目前是Trunk.ly网站的CTO,它是一个专门提供社会化书签服务的站点。由于目前公司的主要员工只有两人,因此,即便我是公司的CTO,我仍然会每天花很多时候编写代码。就网站后端来讲,目前主要做的是搜索;前端则进行一些站点UI的设计和开发。就像大多数创业公司一样,我们非常关注我们的功能特点、站点流量,而且会经常跟投资人打交道。至于架构师这个头衔,其实谈不上,只不过做架构是我们平常工作的一部分吧。在这之前,也曾经用过.net之类的技术做过企业项目。

【编者注:如果想进一步了解Alex,读者可以访问他的个人站点以及《程序员》杂志对他的访谈。关于Trunk.ly域名的含义,@36氪上的这篇文章中有这样一段描述:我问 @alexdong 为什么用 trunk.ly 这个域名,他说:“是个一语双关. 在航海时代,每个周游世界的人随身要带一个箱子,这个箱子就叫trunk。现在英联邦国家仍然叫后备箱trunk。我们就是一个链接的百宝箱。”】

InfoQ:作为互联网的创业者,在同行业中有哪些站点的架构会引起你的注意,让你觉得值得钦佩?

Alex:这一点怎么说呢,像Google。就我个人讲,我会花些时间(虽然我也没有太多的空闲时间)去读Google Research上发表的这些论文。像一些大的互联网公司,比方说Google、Yahoo和Amazon都有自己的research部门,他们经常会把自己解决某个问题的经验写成论文发表出来。对于一些架构上的实际问题,比方说Timeline,这些公司会做一些科研实验,比较各种实现方式的优劣,最终把这些内容总结成文。我会比较多的看这些论文,从中了解这些公司如何解决架构中的某个问题,以及这些问题都有哪些解决方案,以及每种解决方案的好坏。从网站的架构来说,我会比较关注这些内容。除此之外,还有一些东西的架构我也会比较关注,这也是我个人比较感兴趣的方面。比如说MongoDB、Linux或者是HyperTable,像这些新型的数据库、应用服务器等,我也花了不少时间去研究了解它们的架构是如何演进的。

就钦佩这个词来讲,可能有点不太准确。在我看来,它更多的是一种静态的感觉。比方说,当你看到大概有5年或10年历史的一个架构,第一眼看上去可能会觉得“了不起,想得真是很全面。”,这时你会产生出一种钦佩的感觉。但对我来讲,像MongoDB,在它还是1.0的时候,我就在自己的系统中用它们。更多的时候,我看到了它发展的轨迹。在这种情况下,说钦佩可能不太合适。更多的一种感觉是他们做的这些事情很有意思,很有特点。这也是为什么我会在邮件中提到,相比起架构本身,我会更关注架构背后的人,觉得他们更有意思。通过这些,你可以看到,同样一个问题,由不同的人来解决,最后的解决方案会特别的不一样,而且对应于它的社区,你会发现用这些解决方案的人也特别的不一样。所以这些事情是最令我感兴趣的。

InfoQ:是的,架构本身也是动态发展而来的。人本身有其自身的缺陷,很难设计出来一种面面俱到,一劳永逸的架构。就架构决策而言,应该是架构师在当时环境所能做出的最好决策了。随着时间的发展,周围的环境也会发生变化,这时就需要他来根据环境进行调整。

Alex:没错,这也是我觉得一位好的架构师,他真正的价值不在于从第一天开始就拿出一个蓝图,它有多漂亮、多干净。我认为好的架构师首先应该是知识面比较宽广,需要清楚有哪些选择,每个选择在解决当前问题的同时还会带来哪些影响,也就是每种解决方案好的一面和坏的一面。其次,当遇到架构上的问题时,能够通盘的考虑,发现问题的本质,进而提出自己的解决办法。比如像Linus,他实现的Git其实已经融合了他对于分布式开放源代码项目的管理以及协作方式的思考和理念。

InfoQ:那么做架构决策时,就有点像权衡各方面的因素,从而使架构达到一个比较好的状态?

Alex:说达到一个比较好的状态可能有点欠妥。我可以举一个反面的例子。我之所以说它反面,并不是说这个抉择或决定本身不好,而是说它有不可忽视或是很致命的缺点。像Python、Ruby和V8 Engine它们都使用了GIL(Global Interpreter Lock),它的问题在于若是我用Python写一个计算密集型的多线程程序,它的性能可能会比不使用多线程还要差。这就是它的运行环境或者说编程语言本身设计理念中埋下的引子。像Python之所以用GIL,是因为Van Rossum一开始最主要的设计目标是要非常容易的写C Extension,即写一个C模块,在Python中可以很容易的去调用它。有了这个锁之后,使得写C模块变得非常的容易。假如没有这种锁,要想实现从C调用Python或是从Python调用C,就没法做。在我看来,这是Python为了实现这种设计目标而不得不做出的极大牺牲。而这一点,就目前看来,其实还是非常致命的,对我们自己应用的影响也很大。

我举这个例子的原因在于,权衡这个词在很多时候看上去很优美,没有负面感觉。可就对我个人来说,很多架构的决定,包括我现在用的很多软件,权衡这个词实际上有着很大的负面感觉,或者说你接受它【架构决策】时不得不承受很大的痛苦。而且很多时候是现实情况下不得不接受,或者说是一种对现实的妥协。因为,就当前情况而言,面对各式各样的约束条件,已经没有其他更好的选择了。假设我有充足的时间和资源,我可能会要求做得更好。

InfoQ:的确,每种工具或架构有其本身适应的环境或者说是前提条件。假设你当前应用的环境跟这个前提或环境有冲突时,就会造成你刚才所说的那种在应用上非常痛苦的一面。

Alex:你说得非常的准确,就是这种感觉。每个架构决策就会使架构僵硬一点,将你推向某个极端或某条路。当然,实在不行的时候,我就会必须将某些东西扔掉。我们做Trunk.ly也是沿路扔了不少东西,而且每次也都是在实在没有办法不得不这样做的情况下采取的这项行动。

InfoQ:这些优秀的架构给你的工作带来的怎样的影响?

Alex:对于这个问题,我想通过《设计模式》来谈一谈。我读这本书大约是在8、9年前的事情了,当时的第一感觉是,这些模式设计得真是不错,真的很好。由于当时我用C++/C#的机会比较多,在之后的几年里,我都尽量地去使用它们。可后来我认识到,这些模式其实是只是一种规则。我觉得最理想的,作为架构师,你在读这些规则或者是在用这些规则的时候,要知道这些规则之后的规则是什么。然后将这些背后的规则去用到自己的工作中,而不是单单生搬硬套,为用而用。

也就是说,我希望架构师能够理解这些规则之所以呈现出现在这个样子的原因。一名优秀的架构师,当然是要多看别人设计的架构,但是在看的同时,需要了解到使其架构成型的现实的限制和现实的原因。除去你看到的架构本身,你需要看到一种动态的架构,知道其背后的推理和它的思维。这样,等遇到问题时,就可以应用这些思维方式,而不是简单的应用架构。以Trunk.ly的后台搜索引擎的存储为例,到目前为止总共经历了4次大的变更,从最初的MySQL,到Sphinx,到Lucene和Solar,再到目前的HyperTable。每次修改都是因为我们知道我们遇到了哪些问题,又因为知道业界都有哪些解决方案,每个解决方案的优缺点是什么,最后有针对性的进行抉择和行动。我举这个例子想说明,正是因为我关注业界目前的动态,以及每种解决方案的优缺点,这样,当我遇到问题时,我就能想得起来去用它们。而作为架构师,是需要通过这种方式去建立起自己的工具箱,而不是单单让自己的手中就握着个锤子。

InfoQ:前面你曾提到相比起架构本身,你对于导致当前架构成型背后的人和故事更感兴趣。能详细谈谈吗?

Alex:我觉得这是件挺有意思的事情。当你做架构做到某一天,就会遇到所谓“治理(Governance)”的挑战。尤其对于开源软件,在这样一种松散的组织结构,谁也不能将自己的设计理念强迫别人接受的条件下,要保证设计目标的达成、版本、特性不断地推陈出新,这时所面临的挑战和协调的艺术,要远比企业内实现同样目的要难得多。大部分的开源软件,到最后都会有一个所谓的“善意的独裁者(benevolence dictator)”,他们来决定特别艰难的决定该如何做。但是,不同的人做“独裁”决定的时候会特别的不一样。

像Linux社区,这个“独裁者”会要求你在邮件中把自己的设计理念讲得特别清楚,然后他会通过邮件来进行讨论。但像Python就不一样,它一开始就确定了一些理念。作为社区,如果你要贡献源代码就必须承认它们,否则就不会被接受。还有一些开源软件则采用了“不同意就fork”的道路,假设一两年之后,他们觉得这些fork不错,这些fork还有可能会重新被接受。比如Python社区就有几个著名的fork,如pypy,它是用Python来写Python,现在的性能也越来越好了。

通过看这些开源社区的意见领袖如何用“非强制”的手段来保证架构的一致性,消除意见分歧,我觉得是一件特有意思的事情。这就类似在现场看一个直播,对我来讲这比起架构本身成为什么样子要有意思得多。而且在这个过程中,你也可以了解这些软件解决方案诞生的全过程,大家对于问题/特性应用场景的讨论和投票,给你带来一种参与感,这是特别过瘾的一件事情。

InfoQ:刚才说了那么多其他人的故事,现在是不是可以说一下你们自己的故事?谈谈Trunk.ly经历了几个阶段,每个阶段都有哪些,未来它准备朝什么方向发展?

Alex:做创业公司是有两个阶段的。第一个阶段是摸索阶段,在这个阶段,我还不清楚我的商业模式是否行得通,不知道今天的用户是否就是给我带来收益的那些用户。这个阶段是非常重要的,英文叫做“product/market fit”,在之前的所有架构都不是为了架构本身,也不是为了站点的Scale,而是为了能让我尽快的去做实验,更快地验证我的假设。

InfoQ:更像一个原型?

Alex:是的,但它不是那种可抛弃的原型,因为我没有这个奢侈去把它抛弃重头再来。我们在去年12月份Trunk.ly上线的时候,我们对其的定位是一个书签服务,但它是一种透明的书签服务。跟传统的delicious不一样的是,你不需要显式地给它去打标签,它会自动收集你在Facebook、Twitter和Delicious上共享的链接,把它们弄进去进行全文检索。这样,当你想找以前的链接时,你可以通过我们的搜索引擎去找到它。所以,在第一阶段时,为了满足这个商业目标,我们就拿Django和MySQL快速地把它给实现了。后来数据库就有点顶不住了,于是就换成了MongoDB,同时有一部分功能就采用了异步的方式实现。

接下来,我们发现之前的商业目标虽然不错,但是这个市场的价值并不是特别的大。然后,通过日志和分析用户的行为特征,我们发现有些用户经常会去看别人共享了哪些链接,所以我们很快就增加一个Timeline的功能,这样你在一个地方就能看到你关注的人每天都共享了哪些链接,这样用户就不用跑到每个人那里去看了。这个时候,关于网站的商业目标和定位就有了一点点的变化。这个时候,我前面说的那些网站的论文提供了一些帮助。而且,这个时候大概每周都有百分之二三十的用户增长,比起原来要快多了。而且,很多人会邀请他的朋友来注册Trunk.ly。你要是在Twitter上搜索trunkly,你会看到每天有四五十条这样的信息,这就是我们的第二个阶段。

第三个阶段就是我们发现这个市场还是不够大。因为,要想把Trunk.ly做成一个让人们每天都来的地方,这样做的市场开销特别大,而且不是每个人都有这样的需要。所以,我们开始着手做Social Search。与Google这样把所有人的链接都搜索出来不同,我们的这个功能允许你搜你朋友的链接,这样搜出来的结果相比起前者来讲要更准确,而且跟你的相关性更强。我自己在测试这个功能的时候,也经常因此而“走神”,开始访问起那些链接的内容来。

在这个功能完成上线之后,我们还准备做的一件事情是“Topic”,即允许用户自己来建立自己的主题页面和链接。我们相信,从广告和利润分成来说,这对我们是一个非常大的市场。从我刚才说的这些内容,你可以看出Trunk.ly的整个发展过程。我们目前还处在“product/market fit”之前,我想如果一旦证明我们设想的商业模式是正确的话,可能架构还要再变,到时候可能就会更Scalable一些,而且架构挑战也就不一样了。

InfoQ:对于未来的互联网架构师,作为过来人,你有什么经验之谈是值得他们注意和避免的?

Alex:我想我上面讲的内容应该已经是我的经验之谈了。如果非要总结的话,那就是,视野放宽一点,不要手里拿着榔头就满眼尽看到钉子;另一点就是好的架构都需要一个过程,多关注一下架构背后的事情。这就是我能想到的经验之谈,也不是什么非常了不起的道理。

InfoQ:非常感谢你能抽空接受我的采访,谢谢!

Alex:不客气。

zz from: http://www.infoq.com/cn/articles/dx-on-architecture

今天尝试一个oauth授权,发现其总是返回 401 错误的token。

oauth的原理是,先根据appkey和appkey_secret获取到一个request token,将该token发送给服务提供方,并获取accesstoken,如果前后两者匹配,则说明授权成功。

我首先把request token存储在cookie中,获取到accesstoken后,再从cookie取出request token进行验证。而401错误,说明两个token不匹配!检查cookie,发现很奇怪的现象:页面dump出的request token与浏览器cookie不一致!通过firebug查看该页面header返回值中的cookie与dump出的request token是一致的!

换了chrome浏览器,授权成功,没问题。同时,也记得在firefox升级前,授权也是没问题的。这时,检查web log,发现刷新一次页面http://test.com/index.php,firefox向后台发了两次请求,即log里有两条几乎同时响应的http://test.com/index.php请求!

怀疑是firefox扩展的问题,首先禁用了所有扩展,再次授权成功!之后逐步恢复扩展,将问题定位于YSlow!,启用它即授权失败,禁用则授权成功!

(当你的身边,没有工程师,只有几个销售、运营和产品,无人讨论的感觉,真是恶劣。一个人做事,得不到理解,欢喜和挫败都没有人分享。别人觉得你应该很快做完,却完全看不到其中复杂的逻辑,甚至包括产品设计方面逻辑的缺失。不过我忍,就把今年当作锻炼,我要作出好网站。)

出于开发效率和速度角度,我希望选择一款开源电子商务系统,来搭建我们的新网站。

我的需求为:

1、可二次开发,基础代码质量好

2、社区活跃,有较多插件可用

3、性能优秀,可分布式部署web server和数据库(最好是mysql)

4、希望用户登录是基于cookie而非session的

5、统一的页面风格,便于添加新模块

具体的产品需求为:

1、前台:

  • 首页,类似cms系统,基本内容由运营控制
  • 列表页,可按多级分类展示产品,简单搜索(基于数据库即可)、排序,可展示用户评论、分享等
  • 详情页,除了展示产品相关信息、用户评论、分享之外,还可以插入购买过程中的自定义流程,比如问卷调查等
  • 购物车,购买记录,快递单查询
  • 可根据用户属性,展示不同的列表页信息,限制其购买产品的行为等
  • 能够方便的接入到sina微博等平台,connect或app形式
  • 用户可针对单个商品发表评论;今后可能允许用户发布新帖等。最好是富编辑器。
  • 有简单的用户Home页
  • 照片上传功能
  • 漂亮时尚的模板,因为我实在懒得写css和html,而且缺乏美感

2、后台:

  • 可添加产品,支持自定义字段;并支持预览功能!
  • 可管理多级分类,并灵活添加分类
  • 可查看产品的点击、购买、评论信息及汇总统计信息
  • 用户管理
  • antispam系统

在纳兰映像上看到推荐了10款php开源电子商务系统,挑了几个逐一考察。

osCommerce

osCommerce 是一套基于GNU GPL授权的开源在线购物电子商务解决方案。该系统具有易于操作的可视化安装界面、完善的前台商品展示和户在线购物车功能、强大的后台管理和维护功能模块简单易用、70,000人的官方社区用户和活跃的论坛、121,300家已经注册的在线商店的解决方案3,000个成熟的插件供你选择。

在它的showcase里看到一些电子商务网站的例子在线文档做的也比较齐全。但是它应该是用到了session。

其文档里有前端页面加载的顺序:

  1. Base catalog file requested (eg, catalog/index.php)
  2. Application initialization through catalog/includes/application_top.php
  3. Control logic executed for actions performed
  4. Template design layout initialization through catalog/includes/template_top.php
  5. Page content loaded
  6. Template design layout finalized through catalog/includes/template_bottom.php
  7. Application finalized through catalog/includes/application_bottom.php

从文档看,功能方面还是挺齐全的,基本满足需求。

但是查看其代码,没有进行分层架构,比如根目录下的index.php,甚至直接包含了大量的sql句子。虽然这样显得逻辑紧凑,但是对于功能扩展和写作开发,显然都是不利的。所以放弃。

PrestaShop

PrestaShop是一个功能丰富,基于PHP5开发的Web2.0网上购物系统。PrestaShop具有可定制,稳定等特点。整个系统只有5.8MB,易于快速安装。

它提供了一个可登录操作的前后台demo,showcase很齐全。

在其后台里,看到有category和group的概念。

但是它使用了smarty引擎,我并不打算学习它的特殊语法,也排斥其引入的性能损耗,所以也放弃。

网络拓扑为:

使用的是联通4G宽带,由于pc机较多,先使用Dlink链接internet(同时支持有线和wifi),再用另一台路由器连接该Dlink。每台路由器上都挂载了多台pc机。

现象是:上午刚上班,网速较快,ping baidu时间大约为20-30ms。下午网速越来越慢,ping baidu的时间达到2000ms甚至更久。

在其中一台pc机上traceroute 正常时候,结果如下:

traceroute to t.sina.com.cn (202.108.5.122), 30 hops max, 40 byte packets
1  localhost (192.168.0.1)  10.904 ms  10.870 ms  10.843 ms
2  123.120.128.1 (123.120.128.1)  46.567 ms  50.405 ms  51.352 ms
3  bt-208-001.bta.net.cn (202.106.208.1)  48.311 ms  53.269 ms  54.231 ms
4  61.148.157.181 (61.148.157.181)  56.191 ms  56.897 ms  68.844 ms
5  124.65.60.57 (124.65.60.57)  75.792 ms  105.400 ms  116.063 ms
6  61.148.143.30 (61.148.143.30)  132.835 ms  28.660 ms  24.794 ms
7  210.74.176.138 (210.74.176.138)  32.304 ms  38.996 ms  44.813 ms
8  202.108.5.129 (202.108.5.129)  50.600 ms  58.833 ms  66.087 ms
9  202.108.5.129 (202.108.5.129)  1457.853 ms !H  24.439 ms !H *

网速慢时,结果如下:

traceroute to t.sina.com.cn (202.108.5.122), 30 hops max, 40 byte packets

1  localhost (192.168.0.1)  2.992 ms  2.731 ms  2.693 ms

2  123.120.128.1 (123.120.128.1)  2990.059 ms  2990.080 ms  2990.066 ms

3  bt-208-001.bta.net.cn (202.106.208.1)  2990.009 ms  2996.500 ms  2997.330 ms

4  61.148.157.181 (61.148.157.181)  3004.611 ms  3010.622 ms  3017.851 ms

5  124.65.60.57 (124.65.60.57)  3027.297 ms  3031.242 ms  3045.573 ms

6  61.148.143.30 (61.148.143.30)  3045.560 ms  2622.158 ms  504.448 ms

7  210.74.176.138 (210.74.176.138)  511.720 ms  518.801 ms  526.567 ms

8  202.108.5.129 (202.108.5.129)  549.004 ms  548.768 ms  548.731 ms

9  * * *

10  * * *

11  * * *

12  * * *

13  * * *

14  * * *

15  202.108.5.129 (202.108.5.129)  864.125 ms !H  945.124 ms !H *

ps:我在本机抓过包,没有发现太多的arp。但是没法在路由器上抓包。

问题出在哪里呢?

创业网友提问:

我有一个新的社会网络应用的构想。我并不期望这个应用可以获得巨大成功,但我想还是有些潜力的。我找过一些好友和同事交流过这个想法,他们都十分喜欢这个构想。还有些朋友甚至提出想作为合作伙伴加入一起进行开发,把想法变为一个可用的软件。

我无法用自己的钱给他们支付工资(他们也不期望那样),而且大家都打算把这项工作作为我们平时晚上或周末的业余项目。因为我认为这个想法有潜力可以 变为成功的企业,我想从目前这个阶段开始,就解决企业所有权/薪酬的问题,免得将来因为没界定清楚导致真正的问题。我倾向于把公司所有权在我们三个创始人 当中平分,而且基于这个分配规则来确定将来盈利后如何分配。这个选择对吗?如果对,怎么才算公平的股权分配?这是我自己提出的想法而且已花了不少时间做规 划(而且我很确定我将自己负担所有开发过程中发生的费用),所以我感觉我应该理所当然持有更大的股权。这个要求是否合理?

我还同时企图想办法按付出的努力来激励我的合伙人。我不担心有人加入后什么都不干,但我的确认为我们当中有一个或多个人也许将十分努力付出,比其他人付出更多。如果情况是这样,我想这类合伙人应该获得更多的股份。在规划股权架构方面,您有何建议?

Joel Spolsky回答:

这个问题实在是太普遍了,我打算对这个为题给出这个世界上最详细的回答。我希望,将来如果这个坛子上有人问到类似的问题,大家只需要引用我的回答。

最重要的(股权分配)原则:公平,而且可感知到的公平,比真正拥有大的股份更有价值。在一个创业公司,几乎所有 可能会出错的地方都会出错,而且会出错的问题当中最大最大的问题是创始人之间巨大的、令人气愤的、吵到面红耳赤的关于“谁更努力工作”的争论,谁拥有更多 股份,谁提出的想法等等。这也是我总会与一个朋友50-50平分一个新公司的股权,而不是坚持自己拥有60%的股权,因为“这是我的想法”,或者因为“我 比你更有经验”,或者任何其它原因。为什么呢?因为如果我把股权拆分为60-40,公司将在我们(创始人)不断争吵当中走向失败!如果你只是说,“去他妈 的,我们永远也无法知道正确的股权分配比例,我们还是像哥们儿那样50-50平分”,你们将继续是朋友而且公司将生存下去。

所以,我郑重向大家推出:Joel的适用于任何创业公司创始人完全公平划分股权的秘笈!

为简单起见,我将假设你们不打算拿风险投资,而且你们将不会有外来的投资人。随后,我再解释如何处理风险投资,但目前我们暂时假设没有投资人。同样 为简单起见,我们临时假设所有创始人都辞掉了他们的全职工作,而且同时开始全职为新公司工作。随后,我再解释如何处理后来加入的创始人。

来啦,原则是这样的:随着你们公司的成长,你们将一层一层/一批一批地加入新员工。公司的首批员工就是第一个创始人(或者第一批创始人)。也许有1 个,2个,3个或者更多,但你们都同时开始在新公司工作,而且你们要冒一样的风险……例如辞掉你们的工作加入一个未被市场认可的新公司。

第二批进来的人就是首个(批)真正的员工。当你聘任这批人时,你已从某个来源获得现金(投资人或者客户,这个无所谓)。这些人不需要冒多大风险因为他们从工作的第一天开始就拿了工资,而且,老实说,他们不是公司的创始人,他们是加入公司打工的。

第三批的人是更后来加入到员工。他们加入公司时,公司已运作得不错。

对于很多公司而言,每隔大约1年将进来一“批”员工。当你的公司规模大到可以卖给谷歌或上市或是其它,你公司员工也许已经有了6批:创始人1批,员 工大约5批。每一批员工人数都比上一批更多。也许有2个创始人,第二批当中有5名最早的员工,第三批有25名员工,而第四批有200名员工。越迟加入公司的员工需要冒的风险越低。

好啦,你将这样利用上述信息:创始人应该最终拿整个公司大约50%的股份。首层下面的5层员工的每一层最终都分别分到大约10%的公司股份,每一层的员工都将平分这10%的股份。

例子:

  • 2个创始人启动公司。他们每人拿2500份股份。公司总市值按5000股算,所以每个创始人拿一半。
  • 第一年,他们聘用了4名员工。这4名员工每人拿250份股份。公司总市值按6000股算。
  • 第二年,他们又聘用了一批20名员工。这些员工每人拿50份股份。他们获得更少股份因为他们要承受的风险更少。因为公司给每一批员工派发的股份是1000股,所以他们每人拿到50股。
  • 直到公司员工有了6批,你已给出10000股。每个创始人最终持有公司25%的股份。每个员工“层级”持有10%的股份。所有员工当中,最早进入公司的员工,因为他们与迟来的相比要承担的风险最大,在所有员工中持有最多股份。

靠谱吗?你不必严格按照这个公式来规划股份,但基本思路是:你设立不同的资历“层”,最高的层级中的员工承受最大的风险,最低层层级的员工承担最少的风险,而每个“层”的员工平分公司分配给这个层级的股份,这个规则神奇地让越早加入到员工获得越多的股份。

使用“层级”的一个稍微不同的方式是“资历”。你的顶部层级是公司创始人,再下一层,你需要预留一整层给将来招聘牛逼哄哄并坚持需要10%股份的 CEO;再下一层是给那些早期进来的员工以及顶级经理人的,等等。无论你如何组织你的层级,它们应该是设计清晰明了,容易理解,不容易产生纷争。现在,你 搞定了一个公平的份股系统,但还有一个重要的原则:你必须执行“股份绑定(vesting)。股份绑定期最好是4到5年。任何人都必须在公司做够起码1年才可持有股份(包括创始人)。好的股份绑定计划一般是头一年给25%,然后接下来每个月落实2%。否则,你的合作创始人将加入公司3个星期后跑掉,然后7年后又出现,并声称他拥有公司的25%的股份。没有“股份绑定”条款,你派股份给任何人都是不靠谱的!没有执行“股份绑定”是极其普遍的现象,后果可以十分严重。你看到有些公司的3个创始人没日没夜地工作了5年,然后你发现有些混蛋加入后2个星期就离开,这混蛋还以为他仍然拥有公司25%的股份,就因为他工作过的那2个星期。

好了,让我们清理一下整个设计蓝图中没搞定的小问题。如果你的公司融资了,股份如何分割?投资可以来自任何方向,一个天使投资人,一个风险投资公司,或者是某人的老爸。基本上,回答很简单:新的投资将“稀释”所有人的股份。

沿用上面的例子,我们有2个创始人,我们给了自己每人2500股股份,所以我们每人拥有公司的50%股份,然后我们找了个风投,风投提出给我们 100万换取1/3的公司股份。公司1/3的股份 = 2500股。所以,你发行2500股给了风投。风投持有1/3公司股份,而你和另外一个创始人各持1/3。就这么多。如果并不是所有早期员工都需要拿工 资,怎么办?很多时候,有些公司创始人有不少个人积蓄,她决定公司启动后的某个阶段可以不拿工资。而有些创始人则需要现金,所以拿了工资。很多人认为不拿 工资的创始人可以多拿一些股份,作为创业初期不拿工资的回报。问题是,你永远不可能计算出究竟应该给多多少股份(作为初期不拿工资的回报)。这样做将导致 未来的纷争。千万不要用分配股权来解决这些问题。其实,你只需要针对每位创始人拿的工资做好记帐:不拿工资创始人就给 她记着工资“欠条”。当公司有了足够现金,就根据这个工资欠条补发工资给她。接下来的几年中,当公司现金收入逐步增加,或者当完成第一轮风险投资后,你可 以给每一位创始人补发工资,以确保每一位创始人都可从公司得到完全一样的工资收入。

创业构想是我提出的,难道我不应该多拿股份吗?不拿。构想基本上是不值钱的。仅仅因为提出创业构想就获得更多股 权,因此导致纷争是不值得的。如果你们当中有人首先提出的创业构想,但你们都同时辞工并同时开始创业,你们应该拿同等的股份。为公司工作才是创造价值的原 因,而你洗澡的时候突发奇想的“创业点子”根本不值什么钱。

如果创始人之一不是全职投入创业公司工作,该怎么办?那么,他(们)就不能算是“创始人”。在我的概念中,如果 一个人不全职投入公司的工作就不能算是创始人。任何边干着他们其它的全职工作边帮公司干活的人只能拿工资或者工资“欠条”,但是不要给股份。如果这个“创 始人”一直干着某份全职工作直到公司拿到风投,然后辞工全职过来公司干活,他(们)和第一批员工相比好不了多少,毕竟他们并没有冒其他创始人一样的风险。

如果有人为公司提供设备或其它有价值的东西(专利、域名等),怎么处理?很好啊。按这些东西的价值支付现金或开个“欠条”咯,别给股份。你准确算一下他给公司带来的那台电脑的价值,或者他们自带的某个聪明的字处理专利的价格,给他们写下欠条,公司有钱后再偿还即可。在创业初期就用股权来购买某些公司需要的东西将导致不平等,纷争和不公平。

投资人、创始人和雇员分别应该拥有多少股份?这都要看市场情况来确定。现实地看,如果投资人最终获得超过50% 的公司股权,创始人将感觉自己不重要而且会丧失动力,所以好的投资人也不会这样干(拿超过50%的股权)。如果公司能依赖自我积累来发展而不依靠外来投 资,创始人和员工一起将拥有公司100%的股权。有趣的是,这样的安排将给未来投资人带来足够的压力,以平衡投资人与创始人/员工。一条老经验是:公司上 市时(当你雇佣了足够的员工而且筹集了足够的投资后),投资人将拥有50%股份,创始人+员工将拥有50%股份,但是就2011年热门的网络公司而言,他 们的投资人最终拥有的股份都比50%少得多。

结论

虽然创业公司股权分配原则这个问题没有一刀切的解决方案,但是你得尽可能让它简单化,透明化,直接了当,而最重要的是:要公平。只有这样你的公司才更有可能成功。

zz from: 36氪, Joel Spolsky: 创业公司如何公平分配股权

1、自用型与非自用型应用的区别

自用型应用:  淘宝客就是自用型应用。指开发者基于TOP所开发的应用仅仅为自己使用,而不销售或免费送给第三方使用,如淘宝商家自身技术团队或聘请外包技术团队所开发的仅用于自己店铺进销存管理的应用 、淘宝客所开发的用于推广的淘客网站等。自用型应用可以绑定session的方式调用top api,而不需要人工授权操作(也无法供他人授权使用)。后台定时任务就可以使用这种应用。

非自用型应用:在线订购应用、买家应用都是非自用型的。指开发者所开发的有偿或无偿提供给第三方使用的应用,如店铺统计软件、店铺装修软件、快递查询软件等 。

2、一个key跳转至多个页面,兼顾前后台应用

虽然top平台要求授权后跳转至应用里配置的callback url,但是container会把用户自己的GET参数也传递给callback,所以可以在callback页面里根据传入的不同参数,做不同的处理。

比如,默认的callback是:http://test.com/callback.php, appkey是12345678。

那么当用户访问container.open.taobao.com/container?appkey=12345678时,授权后,会跳转至http://test.com/callback.php,我们可以做前台页面的展现。

而如果用户访问的是container.open.taobao.com/container?appkey=12345678&action=background,授权后,会跳转至http://test.com/callback.php?action=background,callback.php检测到action参数,就可以header to后台页面了。

3、店铺营销模块的参数

除了top官方文档里写的top_parameters等参数外,我们还可以获得当前店铺的shop_id、seller_nick,从而获悉应用当前关联的店铺信息。同时,由于top_parameters里含有visiter相关信息,我们也可以根据登录者的情况,做相关处理。

另外,还会传入envMode参数,根据此参数能判断该店铺营销模块是位于正式展现模式(prod),还是店铺后台预览模式(edit)等。

4、店铺营销模块允许用户未登录查看

当用户未登录时,在线营销模块等会要求其先登录到淘宝,再授权,所以传递给app的top_session是肯定不为空的。

而店铺营销前台模块,由于需要挂载到店铺页面里,根本不在乎用户是否登录,所以淘宝也允许授权给未登录用户,故top_session可能为空。

不过比较丑陋的是,店铺营销后台模块,居然也允许未登录用户查看。所以如果后台有特殊要求,就需要自己在代码里判断。

ps:在发布前,自己测试预装时,在店铺后台的iframe里会看到淘宝授权页面,因为url中没带上appkey。正式发布之后,就不需要授权了,淘宝会自动在url中加上授权后传递的参数。

现在的网站大多系统提高用户的停留时间,比如微博类的应用,会实时加载新发布的微博,使用户即使不刷新页面,也有东西可看。查看demo

另一方面,页面的跳转在某些情况下也是可以避免的,比如注册类的应用,希望用户完成某些步骤后,再在当前页面展现下一步骤的内容。查看demo

以上两个demo,都是利用mootools的Fx.Morph做的,由于我是一个js新手,不知道该用怎么的名字来形容这两种效果,暂且称呼第一个demo为Fx的动态内容加载,第二个demo为Fx的次第内容展现。

Fx的动态内容加载

原理很简单,就是new好一个新的、待展现的element,这里是newE的一个clone,并且初始化其height为0px,然后使用Fx.Morph将其height慢慢增加到指定高度,这里是45px,从而做出动态展现的效果。

每次新增元素时,可以将parent element(这里是jwrapper)的最后一个child删除,但是这样会造成整个parent先向上缩,再向下伸展。看了下sina微博,也没有删除child,所以暂时保留。

demo

Fx的次第内容展现

这个的原理同样很简单。待展现的内容,可以在页面加载的时候就准备好,仅将其height置为0px(当然也可以之后再生成,那就类似上面的动态内容加载了)。然后当触发click事件后,再慢慢增加其height,这里还morph了element的border属性。

demo

IE显示utf-8编码页面空白的原因及解决办法

最近遇到这样的问题,UTF-8的编码在IE8中显示空白,这篇文章讲的很透彻,很不错

zz from:http://hi.baidu.com/2356/blog/item/1acb5beee6e170eab2fb959e.html

E-Dragon CMS 默认生成的所有物理文件都是UTF-8编码。UTF-8 的便利性不可多言,而随着 Blog 也跟着开始变成网站必备的服务之一的 RSS 出现,UTF-8 编码更是搭配 XML 以及全球各种不同语系的网站,可以说是现阶段的最佳编码选择。
再随着 Web 2.0 世代的来临,XML 的使用率也会开始从普及到变成标准,如果你的网站还在使用本地的编码,你可能会随时就会被排除在网站之间交流的便利之外。

从一些知名的 opensource 软件来看,已经纷纷将 UTF-8 设为默认或是建议编码,也可以见到这样的迹象,终于可以不用每每自己再去修改编码。不过必竟这些知名的软件多半是国外生产的,总是会东少一点西少一块。

其实我要说的是,最近一些软件都开始有大幅度的更新,以致于在升级的时候会变得更麻烦,尤其并不是所有的社群都有放出各种方式的升级档,当然遇到大幅度架构的更新,要做 patch 也的确麻烦,所以跟着的就是在使用 UTF-8 时,反而有很多档案须要修正。

这篇要说的问题就是,原本一些在本地编码的页面可以正常的执行,在转换到 UTF-8 之后,只剩下空白的一片,还须要手动指定浏览器所使用的编码为 UTF-8 才可以正常。其实这个问题很单纯,问题就出在以往的习惯在 HTML 的标头的部份我们会这么写

<head>
<title>非英文数字开头的页面标题</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
</head>

在逻辑上这并没有任何的问题,不过随着浏览器技术的演进,以前是将整份的 HTML 文件读完后,才显示在浏灠器的窗口上,所以你可以这么说,你所看到的画面已经是浏览器经过解读后的结果,所以你也获得了正确的结果。但是在各种浏览器出现之后,网页显示的速度也变成一个比较的重点,所以页面不再是完整读完后,才全部一次显示,而是边下载的过程中,就边显示在浏览器的窗口上,这时就产生问题了,我们再看一次这段 HTML code.

<head>
<title>非英文数字开头的页面标题</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
</head>

当浏览器收到标头的信息时,最先收到的时页面的标题 title 然后送给浏览器显示,这时候浏览器已经错误的解读了这串文字,然后才收到整份文件的编码是 UTF-8 已经来不及了,以致于最后显示的结果可能是错误的编码,或是一个空白的页面(虽然看起来是空白,但是检视原始码时你会发现,还是完整的 HTML 文件内容)。如果你有各类 script language 实作的经验,你可以更清楚的了解,在输出标头之前,是不能输出任何字符的,以 PHP 的例子,你会得到一个 Warning: Cannot modify header information – headers already sent by… 的警告讯息。

多半 script language 都会自动处理送出标头的动作,以节省写程序的时间,再以 PHP 的例子来解释:
<?php
echo “Hola!”;
?>

其实在这之前 PHP 已经预先帮你处理 Content-type: text/html; 等等的信息了。如果你用 Perl 写过 CGI 就更清楚任何内容输出之前,都要先输出正确的 HTTP Header 才可以得到正确的结果。

回到正题,其实你也应该知道怎么解决了,只要先送出编码就不会有问题了,没错! 所以只要将编码移到第一行,就可以解进这个问题了。
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>非英文数字开头的页面标题</title>
</head>

如果你跟我一样是 Hard Coder 问题应该不大,如果你是依赖 Dreamweaver 这类工具,那么请养成输出后再确认一次的好习惯。

注一:
我指的标头即 header,也有档头的说法,我也不知道哪个说法比较正确或通用,大多数都直接说 header,不过为了避免过多的中英夹杂会造成阅读的困扰,所以这边都说标头。
注二:
另一个比较消极的做法,也可以直接设定 Web Server 的默认编码为 UTF-8,这样在预先处理标题时也会送出正确的编码。不过如果你的 Web Server 同时 hosting 多个不同语系的网站,这就不是好方法了。