几天前想写这篇 blog 的时候感觉有超级多的话要说,可是搁置了两天再来就感觉全都忘了,什么都想不起来了。看来这东西当时想到了起码要记下些东西呀,不然感觉走的可真快。不过还是硬着头皮写吧,不然过几天忘得更干净了。
番茄工作法之前就听说过的。但是一直都没有什么导火线让我去主动的尝试,知道听了一期 teahour 里面提到了一个 gem pomo
一个命令行下的番茄计时器。然后,我就在我的 ubuntu 下尝试了一下,可是行不通,于是就转而去使用早就知道的那个 https://pomotodo.com/ 了。
这个网站的标题叫做 番茄土豆,在没有仔细学习番茄工作法之前,我一直以为 pomotodo
是一个 番茄 和 土豆 的结合体。但是为了写这篇 blog 介绍下自己使用的这个方法我还专门看了那本 The Pomodoro Technique 了解了下真正的番茄工作法应该是个什么样子的,甚至还做了个笔记。这才发现这个就是叫做番茄工作法,和土豆没什么关系。名字的来源是因为作者是靠一个番茄样子的厨房计时器来计时的。而且 番茄
在意大利语中叫做 pomodoro
是不是也是导致大家把这个和土豆联系在一起的原因呢。
这个站点基本满足了计时以及写 todo 的需求,是够用了的。于是就很快的开始做番茄了。刚开始我不像书中那个作者说的那样很难,而是恰恰相反,我对这种新的工作方式非常的感兴趣而导致我的工作效率大增。我为了追求更少的番茄做更多的事情而非常努力的工作着。每次完成一个番茄都非常有成就感。而且我一直追求我的一切是可追朔的,我很希望有一个这样的工具可以记录我每天的工作学习进度。那么,我就开始了欢乐的做番茄的新生活。
3月 11 日是第一次正式的做番茄,到现在已经将近一个月的时间了,在这个过程中发现了很多的问题,值得反思。
虽然很多书都会讲这种问题,我也不是第一次听到这种说法。但是真正追朔自己的番茄进度才能看出来这个问题的严重性。稍微的走神或者是突发奇想的事情都会导致大量时间的流逝。尤其是当你这些新奇的问题在解决的过程中遇到问题的时候,那就更悲剧了。闷头做这种事情甚至让自己忘记之前在做的正经事到底是什么了。
而番茄计时器的滴答声让自己的工作有了更明确的目的性,那么在跑神的时候就多了戒备心,让自己更多的考虑番茄。而方法的创造者也在书中说了这种问题的解决方法:
我几乎没在哪一天做到过这么多的番茄。而且,大部分时间都远小于这个数目。并且那些做够 16 个番茄的时候的工作时间绝对远超 8 个小时。这么说来,传统的 8 小时工作制真正工作的时间是非常的有限的。
最近在做 rails 的站点开发。本来想好的一两个番茄就能搞定的事情结果可能是四五个番茄才行的。很多时候都是这个样子。那些看似琐碎的东西却很有可能花费很长的时间。这确实让我很沮丧,感觉自己的效率很低下。同时,也在想解决办法:采用更好的工具,采用更好的方法,提升自己的水平等等。
测试驱动开发似乎是一个不错的方法,可以尽量的控制 debug 的时间。让该出的问题尽早的出现。当然,测试越来越多,我也会想办法去提升测试的速度。减少时间无谓的浪费。
工具方面就是要敢于去折腾。多看多找多尝试。
然后就是思维和做事方式的改进了。想好了再做或者想的差不多了再做是个不错的注意。而且特别避免不想就做。好的设计绝对是成功的保障,不论是物理方面的或是心理方面的。可是我似乎一直对这方面很欠缺。总是会走弯路。不过没关系,这也是和经验有关系的,走过的弯路记下来,避免以后再走就是了。
坚持就是胜利,才一个月那么就要坚持下去。虽说好的方法可以让自己更容易的坚持做某项事情,但是强大的自制力始终是不可或缺的。
我经常不明缘由的被 logout 然后丢失番茄。这让我很郁闷。而且我一直觉得目前的站点有点无人监管状。虽说有人在豆瓣小组回复,但是开发方面似乎没有太大进展。
然后就是移动端空缺。
我都想自己做一个了。
大概就是这样了吧,以后有了再补充好了。
刚刚看了 js 类继承这部分的东西。其实,这不是我第一次看类继承这个内容了,一次又一次的看,一次又一次的忘,最主要的问题是从来没有在实际的代码中用过...在 backbone 中是有使用这个内容的,但是每次就是直接使用人家封装好的方法罢了,对于内部的实现并不关心。其实我一直觉得学习和那种比较流行的 TDD 的开发方式一致也挺好的。那种测试驱动开发的方式强调每次你要做的就是让你的代码通过测试。那么,不论我用什么方式,我就是让你通过测试我就算是编码完成了。但是我的测试会不断的进化,越发的复杂,每次测试添加了新的逻辑,那么代码就需要跟进,让你的代码可以通过更复杂的测试,并最终在测试的促进下完成整个项目。而整个测试就是对于需求的体现,这样就是让自己的代码保持与测试高度的一致,一方面保证了需求的达成,另一方面保证测试是高覆盖的。
而学习我其实也比较倾向于类似的方法论。就是什么时候用,什么时候学,而不是说在完全没有应用环境的时候盲目的学习,这样学习的效率并不高,很快就会忘记。虽然我说过,其实以前学过的东西永远都是有意义的,但是当我隔很久时间用到这些知识的时候发现只知道个大概、甚至只是看到书上各种图画的痕迹却一直怀疑自己从来没有看过这些内容的时候还是会觉得沮丧。后来想了想,这种没有效率的学习通常都是因为比较盲目的学习一些没有背景的知识造成的。我觉得学习应该是在自己已经熟识的领域自然的延伸会比较有效率,比如我做前端,那么对 http 请求的了解是比较自然的。如果我突然觉得 C++ 比较有意思,自己去写,那么除非说我有什么实际的项目要使用这个技能以推动我,那么,我想这部分技能的提升是非常困难的。
我记得以前看过一些讲帮助提升记忆效果的东西,大多是说要把需要记忆的东西尽量和已经熟悉的东西建立关联,关联越多那么记忆的效果就越好,那么这种延伸式的学习也算是有利用这个点吧。
我觉得比较理想的情况就是当我做东西需要某部分知识的时候,我就抽出一些时间快速的熟悉这部分内容并在实际的开发中使用之。我想这样的效果应该是最好的。
使用才会驱动你去学习,但是如果仅仅是为了临时的项目,遇到问题仓促的 google stackoverflow 然后暴力遍历所有解决方法解决之后头也不回的走了,那么再次遇到类似的问题依然还是要重新走类似的流程。有的时候实际的项目并不一定可以帮助我们快速的成长,没有对知识进行良好的消化吸收,那么这个经历的意义就小了很多。
不知道是不是我的心态不太好,每次做项目都很有压力,希望尽快的做完,做完了才安心。那么,当遇到问题之后,我就会先用 google + stackoverflow 的方法迅速解决之,然后快速推进。但是这会失去一个消化吸收的机会。虽然事后想起来会去进一步学习,但是那个时候与当即遇到问题当即学习的感觉是不大一样的。
有的时候感觉这就是像是打红白机的对打游戏。尽量用这些熟悉的招数,而不敢在对打过程中去尝试的招数,因为这是有成本的,随便尝试招数很有可能被对手快速打爆。反而是没人对打的时候自己偷偷去练习一下才会有很好的提高。
其实我的理想是可以不紧不慢的按照自己的安排去学习。但是我后来觉得,人,是很难靠自觉去生活的。就像政府是很难靠自觉去抵制腐败一样。人都有一个向着懒惰的趋势。如果没有比较强硬的措施加以阻止是很难控制的。给国家立法或者是给自己外界压力才会保证自己不停的努力。总是把自己放在最舒适的地方希望靠自律是完全不靠谱的。
其实这部分我觉得最好的实践就是 coffeescript 的代码。coffee 自带了类继承。那么,解析成 js 后其代码就一目了然了。不过我还是自己练习了一下。解释都在注释里,废话不多说了。coffee 关于 extend 的部分在 https://coffeescript.org/
var __hasProp = {}.hasOwnProperty;
var __extend = function(child, parent) {
// property inherit
for(var prop in parent) {
if (__hasProp.call(parent, prp)) {
child[prop] = parent[prop];
}
}
// method inherit
var cot = function() {
};
// use the method without call parent constructor
cot.prototype = parent.prototype;
child.prototype = new cot();
// set constructor to child itself
child.prototype.constructor = child;
// set the super with parent.prototype
// so we can call child.__super__.method.call
// to invoke parent method.
child.__super__ = parent.prototype;
return child;
};
var Animal = (function() {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function() {
console.log(this.name + ' move');
};
return Animal;
})();
var animal = new Animal('test');
animal.move();
var Snake = (function(_super) {
function Snake() {
// here is an example to call super method.
Snake.__super__.constructor.apply(this, arguments);
}
__extend(Snake, _super);
return Snake;
})(Animal);
var snake = new Snake('snk');
snake.move();
在 backbone 中的 extend 方法如下
// Helper function to correctly set up the prototype chain, for subclasses.
// Similar to `goog.inherits`, but uses a hash of prototype properties and
// class properties to be extended.
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent's constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function.
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
return child;
};
代码里我有一个比较晕的地方
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
这是要把 protoProps 一坨东西全部给 子类的 prototype 啊,那如果我修改了子类一个实例中继承来的属性或者方法,会不会导致其他子类示例方法的变动呢?答案是不会。
var View = function() {
};
View.prototype['type'] = 'abc';
var v1 = new View();
var v2 = new View();
console.log(v1.type); // abc
console.log(v1.hasOwnProperty('type'));// false
// 这种赋值会导致 v1 不会追朔到 View.prototype.type
// 而是重新建立自己的 property. 并不影响 prototype
v1.type = 'bcd';
console.log(v1.hasOwnProperty('type'));// true
console.log(v2.type);// abc
最后 _.extend
// Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};