[email protected]:~$

  • 从《失控》中进化的scrum方法论

    智能系统大致可以理解为 输入 -> 处理 -> 评估改进 -> 输出 这样流程的重复迭代 这里的系统可以指一个人或团队,公司,以较为熟悉的IT业作为比方。 对产品的管理需要不断的接收用户反馈,调整产品定位与体验,并且持续改进,再次的输入给用户。 对于项目开发,以scrum为例,在每次sprint(迭代周期)都会进行评估改善, 并且按需调整下一次的输入(sprint目标),而scrum的理论则可以陈述为提升迭代速度从而提升整个系统的反应与灵活性。 简单而言可以把这种流程套入到任何的工作方式(和scrum不谋而合,或许只是相同概念的另一种陈述),所有的智能系统都有相同的工作方式。 在阅读过一些scrum概念后,联想到了《失控》中的“分布”概念,二者实在是有很多异曲同工之处。 在我理解的scrum是把不同的team(为了陈述方便全以开发为例)作为一个自组织的智能系统, 并且在单个系统进行这种迭代时鼓励不同team开发者互相交流, 外部的参与使得单一系统输入和评估的部分得到了增强(更为可观,多样化), 并且在一个大的组织内部,这种互相交流的模式也很大的提升了系统输出的利用率(可以作为另外系统的输入)。 甚至可以采用更佳灵活的方式,管理者可以组织各种虚拟团队来解决特定问题, 通过划分出更多的“独立”系统,每个小型系统可以更快的改变/迭代, 而通过人员交流和重组(重组成另外的虚拟团队)使得交换信息更佳畅通,把经验和技术(甚至迭代本身的改进)的价值变得最大化。 跨team的虚拟团队与重组看似混乱,但小的团队往往容易维护,易于沟通,分工明确,并且更好的达成改进的共识。 还有一个好处正是敏捷原则所鼓励的团队成员需多交流, 在不同的虚拟团队,大家通过跨团队的重组来吸收经验。 同时因为虚拟团队的时效性,与现在的团员交流也有助于以后的跨虚拟团队交流。

  • 从 PM 到 PM

    打开这份四年前开始的博客,回忆起了在不安与浮躁中追求着上进的自己。 几年过去内心已经成长了不少,周末不会因担心未来守在电脑旁疯狂的学习,逐渐的摆脱迷茫认清对自己重要的事,了解了社会组织的运作方式从而知道如何参与其中。 人的成长是螺旋式的,在迷茫和坚定之间来回摇摆。 可能现在看来成熟的思考在明天就会被新的认知打破,而在迷茫中的一点点积累却又是形成坚定意志的原料。 这种成长方式使得我们在迷茫时变得不再恐慌,在坚定时也会不断的审视自己。 之前的一个月因为自认对产品的洞察力而主动请缨 Product Manager 的位置。 一是认为公司的成长过程中的确到了需要这样一个角色的时候, 二是认为自己有胜任的能力, 三则是总干一样的工作有些厌倦 想要换个角色体验下。 刚开始的工作的确很顺利,之前欠缺的 Road Map, Product Plan, Product Design 进展的非常好,而且也受到大家认同。 在愉快的新工作中我却感觉被渐渐的拖入泥潭 我发现了在之前位置没有发现的事情 团队的执行能力不足! 每日疲于应对客服与企业需求,无法做到对于功能的改进与新产品的投入 这种情况令我非常苦恼,大家聚在一起讨论未来远景时总是信心满满 迸发无数的idea 但是在执行时却有严重的问题, 大量的工作由手动完成,程序没有健全的自动化监控和纠错 导致在本可自动化的事情上投入大量人工 阻碍了开发效率 这使我认清了一个事实,无伦设想或潜力有多好,现实的执行才是最重要的! 现在已经有了 Road Map,我需要转交用户反馈收集,文档撰写,可用性测试等 Product Manager 的周期性工作 投入全身心在 Project Manager 角色上工作,毕竟吹牛很容易,做出实事的人却很少(这让我理解了 idea 不重要那句话!)。 对于技术型公司,相比产品周期性调查,对开发团队能力的提升和对开发架构的改进更为重要,技术与创新上的领先才是技术型公司的优势。 拿起了以前不屑的 敏捷 与 Scrum 的书籍,认识到了团队和个人作战的巨大差异,理解了团队管理与运作的理论。羞愧于经常讲段子嘲笑敏捷开发...

  • 通过Razor管理Virtual box虚拟机

    打算在mac上用虚拟机玩下云。之前工作中用到了Razor,于是萌生了用Razor来管理虚拟机的想法(顺便试验下最近很火的docker)。 为了让开发机尽量保持”干净”,决定用docker来做个razor-server的镜像(docker pull jjy0/razor 可以下载到) 制作镜像还算顺利,没想到在虚拟机的网络配置和IPXE boot上栽了跟头,记录在此引以为戒,同时期望能帮助到他人(没接触过PXE boot或Razor的朋友就此别过!) 用docker启动 razor-server非常简单 docker run -d -p 8080:8080 jjy0/razor start 在本地安装razor-clientgem install razor-client 已经完成了razor的安装! 接下来根据官方教程配置PXE boot VMware Fusion的坑 刚开始我使用的是Vmware Fusion,在一台虚拟机中设置好了razor和DHCP server,却无法被同网络其他机器探测到。 没能找到解决办法,之后使用Vmware自带的DHCP server redirect到razor,发现Vmware自导的dhcpd版本过低(2.x)不支持chain命令,只好作罢 Virtual Box的坑 转战到Virtual Box 我搜索了一番,发现已有前人尝试过比较简单的方法(把dhcp-server假设在host上)。决定使用这种方法 先按照上文链接中得做法建立host-only net 查看现有dhcp serverVBoxManage list dhcpservers 禁用相应网络的dhcp serverVBoxManage modify --netname HostInterfaceNetworking-vboxnet0 --disable 按链接中方法配置dhcp server...

  • 开发编辑器的过程中遇到的一些浏览器差异

    测试新编辑器时发现在firefox下会有很高几率出现一个神奇的bug。 当光标在block元素(blockquote, pre, etc..)中时,按‘下’或‘右’或‘回车’键后,光标会选中block元素中第一段文本。刚开始怀疑是在FF下rangy设置selection的bug,但在注释所有js中keydown的处理事件后,还是会有此bug。 之后百思不得其解,甚至想到用scribe重写编辑器… 在观察scribe的demo在FF下的表现后,终于找出了这个很愚蠢的bug… 在blockquote中我特地的把p标签转换成text + <br>,但实际上在html4中是要求blockquote等块状元素中需要存在p标签(这是来自stackoverflow的一个回答,我没有看html4标准..),所以我特地的去除p标签反而是画蛇添足之举。 在chrome, IE等浏览器下对于<blockquote>test<br></blockquote>这种html没有特殊限制,浏览器的默认行为完全可以正常工作。 但是在firefox下,当光标在test文本末端时,按下回车,本应换行,但是firefox会去寻找当前的p标签(这是html4规范,Firefox依赖了此规范,chrome等则没有),但是我错误的没有把文本放入p标签,所以造成浏览器默认行为出现bug。 正确的标签应该是<blockquote><p>test<br></p></blockquote>这样才符合html规范。 在开发编辑器的过程中,接触到了很多这种浏览器默认行为不一致的问题。 比如firefox下偶尔会对br标签加上type="_moz"的属性。 chrome和safari下拖拽block中元素浏览器会把拖拽的文本放入span并且自动添加很多style属性。 在webkit内核浏览器中block元素里按回车会在下一行自动添加同样的block元素,在FF中则是自动换行。 如果一行中有br,在IE下光标在br之后,其余的浏览器则是在br之前(偶然通过range对象观测到的,在block末尾时IE中的endoffset会多1) 浏览器的很多上层API加上跨平台库已经让人很少能感受到js编程的平台差异,但是在contenteditable中诸如此类html中并无规定的默认行为在不同浏览器上的表现却是千差万别。尤其是号称跨平台的selection库rangy实际上在不同平台上还是会有很多bug与不一致,举例来说最基本的获取range对象,在webkit浏览器上取得range,start和end会优先是textElement,但是在FF上则会得到ElementNode。 html规范毕竟不可能涵盖所有情况,各种标签的嵌套以及不同情况下用户的操作,这些规范之外的情况只能靠具体的实现来决定行为。 就像各种的markdown解析器,在规定之下会输出相同的结果,但若在规定之外,每个parser都会有些许的差别。 看来浏览器距离完美的平台还有不短的距离..

  • javascript学习笔记(二)

    1, 函数中this的四种情况 //1. 函数绑定到对象上时, this为对象 a = {func: function(){ console.log(this)}} a.func() // this是a //2. 没有绑定到对象时,this为全局对象 (function(){ console.log(this) })() //上面的this在浏览器中是window(全局对象) //3. 用new调用时this绑定到新构造的对象 //4. 函数对象的apply方法 (function(){console.log(this)}).apply("hello") //通过apply可以指定function的this值 2, 原型 //javaScript中的原型继承必须通过函数来完成 //function有一个很重要的prototype属性,默认值为{} (function(){}).prototype //=> Object {} //函数的prototype属性是javascript中原型的关键 //用new去调用function时,会以该函数的prototype为原型构建对象(常用此行为来模拟继承) a = {hello: function(){return "world"}} //现在来构建一个链接到a的对象,首先需要一个function A = function(){} A.prototype = a //用new调用A时会构建出以对象a为原型的对象 b =...

  • javascript学习笔记(一)

    以前没怎么用过javascript(仅停留在简单的dom处理与ajax上),身为后端程序员对其印象仅有杂乱 完成简书新richtext编辑器的基本功能后,感到js也没这么不堪,反而基于原型的模型能很轻易的应对反射,动态定义Function/Object等‘元编程任务’ 并且和ruby中的’元编程’不同,在js中这些就是通常编程 “原型”的表达力不弱于OO,并且复杂程度远小于OO。当然在javascript中的实现还是略微杂乱..虽然这门语言很多细节部分的设计让人匪夷所思,但是其核心的原型功能还是兼具了精简与好用这两处优点 遂打算好好学习下js, 并在阅读《JavaScript语言精粹》时把一些知识要点记录下来 本文会以tips的方式罗列从书中获取的知识要点,以及一些我自己的理解和对这门语言的想法 所有内容基于ECMAScript-262 (javascript 1.5) false,js的条件判断中 0, -0, null, false, "", undefined, NaN 均为 false(coffeeScript中的?操作符编译为typeof a !== "undefined" && a !== null;使其行为接近一般语言) Number,js中数字储存为(相当于java中的)double, 所以1/2会等于0.5 基本类型,js中有 Number, Boolean, String, Array, Object, undefined几种类型,Boolean, String, Array, Object都属于Object(因为可以用原型系统, null比较特殊) 对比,js中==仅对比值,===更为严格,要求类型也一致(coffeScript把这两个颠倒了过来,更加接近一般语言的行为) 注释,js中单行注释用//,导致你无法用//来表示一个空的正则,/**/也是 原型继承,js中通过键来获取对象中的值时,如果该对象无此键,则会到对象的原型链中去查找,直到Object的prototype,任何对象都隐含链接到Object.prototype,该值默认是{} 更改对象的键时不会影响到原型 delete操作符,用来删除对象的键(不会影响到原型),这时对象原型的相应键会暴露(如果有的话),再次delete会被忽略并返回true(这代表如果原型上有key,则没办法在对象上删除该键,但是可以赋值为undefined) for..in 语句可以用来遍历对象的所有key hasOwnProperty方法用来判断对象是否有该key(从原型中继承的不算)

  • Yet Another Markdown Parser, 没想到还原度还挺高的

    最近写了个markdown parser练手, 发现这种有规范的东西非常适合TDD, 照着markdown语法来写spec, 然后一个一个将其通过, 之前从未试过这么彻底的TDD 是写代码写的很爽时顾不上测试 是spec一定要事先定下,如果是创造性的编程, spec没法确定, 在代码和spec间来回改动就失去了TDD的意义 托TDD的福,写好各个语法的parse后跑了下GFM的source页,没想到还原度还挺高的 之后fix了几个小地方,parse的效果已经比较完善了,而且因为TDD 保证了测试的覆盖率(2k行左右的代码估计1k多都是spec),可以放心的修改代码,只要可以pass spec基本就是没问题的 之前一直感觉TDD有点名副其实, 经过这次实践感觉这种编程方式真的能帮助你写出可靠的代码 当然关键还是要事先确定spec, 如果不能确定spec我是绝不会用TDD的方式去开发的, 实际上我把minidown改成支持GFM时就改动了一些spec, 当然相应之前的所有代码也需要修改,相当于白写了一遍测试 benchmark了下各种markdown parser解析14000篇文章的效率 跑在the ruby racer 上的marked大概3.8s可以完成 minidown 大概16s可以完成 maruku报错.. kramdown 大概200+s可以完成…(这货README里写着fast..) 后3种都是pure ruby的markdown parser marked考虑到主要是前端使用,可能没有太多考虑效率,看得出ruby和v8差距还是挺大… 对于后边两个结果到是很惊讶, 没想到minidown在pure ruby的parser里还挺快的..

  • ruby中的lambda为什么是Proc类

    当然写之前我试着在网上搜了下, 果然没有搜到类似的问题。 lambda为什么不是Function, Method 而是Proc ? 这个问题当然没有标准答案,于是我做了一番推(猜)测 lambda和proc都是Proc类,这样已经可以看出一些端倪,proc既然叫proc当然是Proc类的主角,所以lambda只是Proc的一个附属,因为已经实现了proc,所以就顺手实现了lambda。 proc是用来代表block的(双飞燕中的话是proc更接近block), 如果我们在参数中用&block,我们会得到一个代表block的proc对象, 并且proc和block在各种行为上几乎都是一致的。 再来看下lambda,双飞燕中说lambda更接近method 当然…其实他们的区别是很大的,ruby中method必须bind到一个object上才可以调用,method(消息)必有接收者 而lambda就很异端了,仅仅是一段可执行代码,没有什么可与之对应的(python中的method可以对应为第一个参数为self的lambda) 而与proc的区别仅仅是传参和上下文跳转上更像method,并且在block的压力之下几乎没有任何用处.. “虽然很鸡肋, 但是实现上很简单(把proc稍微改下?) 干脆一起实现了,说不定谁可以用得上” -————————-(我猜测的实现lambda时matz的想法) 于是就同归于Proc类了

  • Celluloid中的任务中断和Condition

    ######Celluloid有个很神奇的机制(<–示例代码) Celluloid每次任务(方法调用)会用Fiber去包装 当一个FiberTask因为某些代码被中断时,此时Celluloid可以回到线程执行任务的方法 相当于中断的任务已经结束 之后Actor线程继续的从mailbox取任务 ######某些代码! FiberTask会因某些方法被中断,上面的示例代码中中断当前Fiber的是sleep方法,这个方法由Celluloid做了覆盖 sleeper = Sleeper.new(@timers, interval) Celluloid.suspend(:sleeping, sleeper) Celluloid.suspend这行代码就起到中断作用,(知道它会中断当前Fiber即可,实际会根据后边的参数调用一些callback) ######中断了。。如何恢复? def before_suspend(task) @timers.after(@interval) { task.resume } end 这就是参数sleeper的callback,可以看到利用定时器来执行恢复的task 如果Fiber.resume的时候当前正在执行别的FiberTask会怎么办?岂不是会乱掉? after定时器也是通过FiberTask来执行的,所以到时间后我们的block会被传到mailbox中,就像一个新任务被调用一样,完全没有问题! ######某些方法能中断? actor当然不是再任何情况下都可以自己中断..上文sleep方法是之一,另外Celluloid还提供了Condition类来进行中断 Condition类和ConditionVariable行为类似 ######Condition ConditionVariable主要是用来在线程间统一资源的,README很详细 在Celluloid中应该用Celluloid::Condition来完成这件事,他们的行为是差不多的 Celluloid::Condition的好处是会中断当前的FiberTask, 这样Actor可以去执行之后的Task,而不是一直block住,基本原理和之前sleep是差不多的 Condition可以很好用的去做些同步操作,而且不会浪费线程

  • ruby-stdlib-delegate

    一直对delegate效率抱有疑问(虽然从未做过牛X到需要改进这里效率的项目..) SimpleDelegate使用的果然是method_missing方法 method_missing据说是很慢的。。因为ruby要查询很多层方法 ActiveRecord采用的改进方案是method_missing中去创建方法,这样第二次调用就会命中创建的方法了 不过不到框架的级别应该是不需要在意这些的.. DelegateClass方法会返回一个匿名类,并且作为参数的类的实例方法都会在其中定义一遍 所以没有method_missing,当然用起来不是那么Simple.. delegate库解决了像是equal?, methods, instance_methods等等很多类似的小问题