tips for improving our learning process

Addy Osmani shared some tips about
improving learning process, and I’d like to share with you all.

he is author of some great free books about javascript, such as
Essential JS Design Patterns.




* Be self-aware: how do you learn best? Do you learn best from documentation,
step-by-step tutorials, hands-on approaches or with a visual aid? Do your
best to modify how you learn to suit your personal preferences. If you can’t
find a knowledge resource in your format of preference, don’t be afraid to
ask if someone would be willing to do it in another form. Perhaps an author
of an existing resource wouldn’t mind doing a video or podcast on the same
topic, especially if the material is still fresh in their minds.

Set learning goals: what are you hoping to get out of learning something new?
Is there a particular weakness you’re trying to address? Define upfront what
it is you’re hoping to do better or be better at by the time you’ve completed
your experience. If this means setting learning “milestones” on a personal
GitHub project, go for it.






Practice: Once you’ve completed a learning experience, create opportunities
to apply what you’ve learned asap. This will help refine your abilities. Some
developers try to find opportunities at work where they can apply what
they’ve learned whilst others create sample projects or tutorials using what
they’ve learned to share with the community.

Do knowledge transfers: If possible, see if you can work with someone with a
skill you wish to develop further. Maybe you can offer to teach them more
about an area they’re weak in in return (e.g “I’ll teach you about LESS if
you teach me about Node”)







Don’t be afraid to ask questions: The most knowledgable people are often
those who weren’t afraid to say “I don’t understand this. Can you explain?”.
Asking questions is an easy way to gain more knowledge. It can be uneasy at
first, but it’s always useful to get other peoples perspectives on topics.

Experiment: Try out new things, even if you find them uncomfortable at first.
It’s amazing how much we can learn from our mistakes as well as our
successes.







Evaluate: We often play around with code and create new things without ever
really stopping to evaluate just how much we’ve really learned. Remember to
make time out to ask yourself “What did I learn from this?”, “What worked?”
and “What didn’t work?”



a simple du clone with nodejs asynchronously

最近一直在关注Node.js,感觉与之前一直用的编程模型有很大的区别。Node.js完全基于异步回调和事件机制的体系,
给如何更好的编写JS带来一些挑战,我也是刚刚进入web编程这个领域,所以有许多概念需要再清晰和明确。昨天尝试用
Node.js写了一个简单的du,一个同步版本,一个异步版本。

同步的比较简单,非常直觉,大家都很熟悉:

du-syncview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/env node
// du clone

var fs = require('fs'),
util = require('util'),
argv = require('optimist')
.usage('Usage: $0 [OPTION]... [PATH]...\n' +
'\t-h, --human \n' +
'\t-c, --total \n' +
'\t--help')
.boolean(['c', 'h', 'count', 'help'])
.argv,
partial_size = 0,
default_unit = 1024,
paths = [],
unit = default_unit;

if (require.main !== module) {
console.error('please run it as standalone app');
}

if (argv.help) {
require('optimist').showHelp();
process.exit(0);
}

function displaySize(bytes) {
console.log(bytes);
}

function traversePath(path, callback) {
var stats, files;

stats = fs.lstatSync(path);
if (stats.isFile()) {
callback(stats.size);
} else {
files = fs.readdirSync(path);
files && files.forEach(function(file) {
traversePath(path + '/' + file, callback);
});
}
}

function collectSize(bytes) {
partial_size += Math.ceil(bytes/unit);
}

if (argv._.length === 0) {
paths.push('.');

} else {
argv._.forEach(function(path) {
paths.push(path);
});
}

paths.forEach(function(path) {
traversePath(path, collectSize);
displaySize(partial_size);
});

异步版本:

du-asyncview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env node
// du clone

var fs = require('fs'),
util = require('util'),
argv = require('optimist')
.usage('Usage: $0 [OPTION]... [PATH]...\n' +
'\t-h, --human \n' +
'\t-c, --total \n' +
'\t--help')
.boolean(['c', 'h', 'count', 'help'])
.argv,
events = new require('events'),
emitter = new events.EventEmitter(),
total_size = 0,
default_unit = 1,
paths = [],
unit = default_unit;

if (require.main !== module) {
console.error('please run it as standalone app');
}

if (argv.help) {
require('optimist').showHelp();
process.exit(0);
}

function displaySize() {
console.log(total_size);
}

function traversePath(path, callback) {

fs.lstat(path, function(err, stats) {
if (stats.isFile()) {
emitter.emit('data', stats.size);
console.log('%d\t%s', stats.size, path);

} else {
fs.readdir(path, function(err2, files) {
files && files.forEach(function(file) {
traversePath(path + '/' + file, callback);
});
});
}
});
}

function collectSize(bytes) {
total_size += Math.ceil(bytes/unit);
}

emitter.on('data', collectSize);

if (argv._.length === 0) {
paths.push('.');

} else {
argv._.forEach(function(path) {
paths.push(path);
});
}

paths.forEach(function(path) {
traversePath(path, collectSize);
});

process.on('exit', displaySize);

可以看出两个版本在结构上其实有很大的区别。在使用callback的异步方案中,我使用了EventEmitter,当然不是必须的,
然后在进程的exit事件时,输出总大小。这里的问题是,这种方法我无法准确的以某个顺序输出参数列出的每一个路径的大小,
比如
./du.js dirA dirB dirC
如此来调用,就不能用exit事件去处理了,这是Node.js中异步编程的一个困难所在。
为了解决这种问题,有很多不同的方案。有一种模式叫promise,node实现node-promise
据说老版本的Node.js中提供了promise语义,后来被去除了,promise对我来说比较难理解,也是第一次接触,所以打算做更多的
探索再说。

inventing on principle inspires a lot

前不久偶然在reddit上看到有人推荐一个Vimeo视频Inventing on principle(如果看不了,
这里有youku的),作者是Bret Victor。看名字其实
不太明白它要讲什么,所以下载后放着没看。后来一个晚上闲来无事,就翻出这个视频,
没想到彻底被作者的思想所折服。他表达了一种观点,就是当我们在进行创作的时候,应
该以一种交互式的可以立即反馈的方式去进行。他在视频中使用了几个软件开发中的例子,
这些例子太震撼了,他几乎发明了一种崭新的编程方式。
很多人都觉得this is a new world to invent
有人说道:

That’s already a good candidate for the technical talk of the year, if not the decade IMO.
Ok, I’m getting a bit too enthusiastic here but this is so inspiring.

许多人受到巨大鼓舞和启发,在很短的时间里已经有很多基于Bret Victor的原则所创造的
原型出来,比如这个超酷的Light Table,完全颠覆你对IDE的概念。这里还谈到了一个
Frogatto and Friends的游戏,完全基于Bret的原则,还有
mozilla自己的一个实验性质的编辑器Live Scratchpad

5月9号更新:

这里又有一个叫Tributary的,作者称为响应式可视编程,给的例子倒是挺有意思。另外听说Light Table
kickstater上受到热捧啊。

我强烈推荐大家看看这个视频,也许能得到不少启发,英语不好也没关系,光看看演示你也
能感受到那种强烈的冲击。

Nodejs: notes from introduction to Nodejs

I just watched Introduction to Node.js with Ryan Dahl, here are some quick notes.

  • There are no dom and window global object, cause it’s not in web browser environment.
    Nodejs is used to do server side javascript, and as it promise do web the right way.
    It basically provides a common api and a way to communicate with system. such as get
    pid by accessing global object process.

  • old setTimeout is provided. so anyone who is familiar with browser side js should be feel
    comfortable. node implicitly starts the event loop after all things setup. so

1
2
3
4
5
6
#!/usr/bin/env node
// simple hello-world.js demo
console.log('Hello');
setTimeout(function() {
console.log('World');
}, 2000);

when you call it with node hello-world.js, it ends right after two seconds. Node knows when
to drop out once all callbacks and all timouts get done.

  • write a simple http server with Node is just like something below:
    1
    2
    3
    4
    5
    6
    7
    #!/usr/bin/env node
    // simple hello-http.js demo
    var http = require('http');
    http.createServer(function(req, resp) {
    resp.writeHead(200, {'content-type': 'text/plain'});
    resp.end("Hello, World\n");
    }).listen(8000);

start it with node hello-http.js and use curl -i http://localhost:8000/, you will get response

1
2
3
4
5
6
HTTP/1.1 200 OK
content-type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked

Hello, World

Notice that header include Transfer-Encoding: chunked, it means streamming which makes it possible to
encode chunks to send a variable length respone.

  • then here comes a simple chat server, and I rewrite it a little bit but remains the spirit.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/usr/bin/env node
    var net = require('net');
    var connections = []

    function broadcast(msg, skip) {
    for (i = 0; i < connections.length; i += 1) {
    if (connections[i] !== skip)
    connections[i].write(msg);
    }
    }

    net.createServer(function(conn) {
    connections.push(conn);

    conn.on('data', function(chunk) {
    broadcast(chunk, conn);
    })
    .on('end', function() {
    connections.splice(connections.indexOf(conn),1);
    });

    }).listen(8000);

Nodejs: first impression

Nodejs is incredible, especially for a front-end developer. what is Node,
I just quote from website:

Node.js is a platform built on Chrome’s JavaScript runtime for easily
building fast, scalable network applications. Node.js uses an
event-driven, non-blocking I/O model that makes it lightweight and
efficient, perfect for data-intensive real-time applications that run
across distributed devices.

After some digging, I wrote a simple wc clone, here is it:

wc.jsview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env node

/**
* simple wc clone written in JS.
* need optimist for options parsing.
* Sian Cao <[email protected]>
*/


var argv = require('optimist')
.usage('Usage: $0 [OPTION]... [FILE]...\n' +
' -c count chars\n' +
' -l count lines\n' +
' -w count words')
.boolean(['c', 'l', 'w', 'h'])
.argv,
fs = require('fs'),
util = require('util');

function processChunk(chunk, collects) {
var i = 0, inword = false;
for (i = 0; i < chunk.length; i += 1) {
collects.nr_chars += 1;
if (/\w/.test(chunk[i])) {
if (!inword) {
inword = true;
collects.nr_words += 1;
}
} else {
inword = false;
}

if (chunk[i] == '\n') {
inword = true;
collects.nr_lines += 1;
}
}
}

function printCounts(collects) {
if (argv.l) {
util.print(collects.nr_lines + ' ');
}

if (argv.w) {
util.print(collects.nr_words + ' ');
}

if (argv.c) {
util.print(collects.nr_chars + ' ');
}

if (!(argv.l || argv.c || argv.w)) {
util.print(collects.nr_lines + ' ' + collects.nr_words + ' ' + collects.nr_chars);
}

util.print('\n');
}

if (argv.h || argv.help) {
require('optimist').showHelp();
process.exit(0);
}

if (argv._.length > 0) {
argv._.forEach(function(file) {
var collects = {
nr_lines: 0,
nr_words: 0,
nr_chars: 0
};

var fstat = fs.statSync(file);
if (fstat.isFile()) {
fs.createReadStream(file, {encoding: 'utf8'}).on('data', function(chunk) {
processChunk(chunk, collects);

}).on('end', function() {
printCounts(collects);
});
}
});

} else {
(function() {
var collects = {
nr_lines: 0,
nr_words: 0,
nr_chars: 0
};

process.stdin.resume();
process.stdin.setEncoding('utf8');

process.stdin.on('data', function(chunk) {
processChunk(chunk, collects);
});

process.stdin.on('end', function() {
printCounts(collects);
});
})();
}

You need to install optimist npm install optimist to run this file.

update:
a really great sum-up of resources for you to dive into node

mosh is awesome

I occasionally came across mosh yesterday, and try it today, and found it
really awesome. It does what it promised

to keeps the session alive if the client goes to sleep and wakes up later,
or temporarily loses its Internet connection.

that is power enough to draw your mind and it also supports roaming

Mosh allows the client and server to “roam” and change IP addresses,
while keeping the connection alive.

I just get a chance to try that cool feature some days ago. My wired network accidentally
losted, and my wireless connection took in charge a few seconds later, and as wireless got
connected, my mosh tunnel reestablished.

If you see a log mosh requires a UTF-8 locale when running mosh, it means
there is something wrong with your ssh config. try this:

1
mosh --server="LANG=$LANG mosh-server" user@ip [your cmd]

or FYI, see this issue

If you ever use tmux or gnu screen, here comes the power

1
mosh sonald@remote-server tmux attach-session

This saves me a lot of trouble.

nepomuk and fulltext indexing

Just a reminder of some confusing things about Nepomuk in KDE4.

A few of googling tell that it supports fulltext-indexing of variant types of files,
including pdf file. Unfortunately I failed to witness it in my KDE4 env. So I dig more
and get some info.

First newer KDE4 version uses virtuoso to do indexing work instead of old strigi, and
for pdf-indexing to work, you may need to install pdftotext. According to this post,
pdf should be supported. To check if a file has been indexed, go to info panel in Dolphin and
see if there is a ‘has hash’ property. and here is an explaination of some parts related to
Nepomuk infrastructure.

For trouble-shooting, there are some ways to try(see Nepomuk, re-indexing),
here are some quick excerpts.

index a file manually from console:
nepomukindexer /path/to/file

call dbus service to re-indexing a folder(only work for KDE 4.8):
qdbus org.kde.nepomuk.services.nepomukfileindexer /nepomukfileindexer org.kde.nepomuk.FileIndexer.indexFolder afolder 0 1

octopress with twitter bootstrap

哈哈,刚才找到一个整合了twitter bootstrap的octopress的主题,太帅了,立马换上。
细节还需要调整,不过比默认的主题方便多了。猛击这里
当然如果你用的是原生的jekyll,可以参考这里
bootstrap是twitter的一个轻量级的前端框架,使用非常方便,去这里可以看看效果。

zsh gem(1)

zsh is my favorate shell, super powerful. there are a lot of blogs about it, and I recommend
a book From bash to z shell, and the site also contains some wonderful references.

Here I just wanna show some cool quick snippets of what zsh capable of, just for fun.
So guess what this does?

compare_dirs.shview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/zsh

if [ $# -lt 2 ]; then
echo "need src dest dir to compare"
exit 1
fi

pushd $1
print -l *(e:'[[ ! -e $2/$REPLY ]]':) 2>/dev/null
popd


#pushd $2
#print -l *(e:'[[ ! -e $1/$REPLY ]]':) 2>/dev/null
#popd