The Good Code

回家在XP上写东西,惊喜的发现连国产软件也都开始嫌弃和逐渐放弃XP和IE了。恩,慢归慢,只要不倒车,车轮总还是向前走的。

技术总是在飞速的更新。但无论技术怎么革新、新概念如何吹嘘,一行行的源代码始终是整个软件生态系统中最重要的根基。就像猎命师靠收命格,海贼靠热血,绝地武士靠原力,写代码才是程序员安身立命之本。

写了差不多五年代码,多多少少能沉淀一点跟《Clean Code》和《Refactoring》不太一样的东西了。

一记:

read more

Functional Thinking

标题起得有点大。

说不上来到底是幸运还是不幸,总之就是年底有空超前完成了一下明年的KPI——Learning Haskell。完成度还算满意,就连传说中的monad也算是有个感性的认识了。

强推这个教程,基本上是我所有看过的教程里最良心的了。

第一次听说Functional Programming还是好几年前刚刚开始写代码营生的时候,那时的我还是初级代码搬运工,冷不丁搬运到了.Where(=>).Select(=>).ToArray()这种第一眼看不明白多看两眼又觉得好厉害的代码,瞬间就惊为天人。这好几个for都写不出来的代码,一个chain就做完了。顺手多google了一下linq的东西,也就无可避免的学到了一个新单词——Functional Programming

平凡人类认知那些first impression不错新事物,大多会经历从overestimate到underestimate的一个或多个反复。反正我对C#中的linq的认知是经历了“linq == silver bullet”和“linq == performance hit”的起伏的,现如今再看,当然是能明白具体问题具体分析才是重点,只是写过的那些代码里就不免一时都是linq又一时连using System.Linq都不见。

不过对于FP的好感一直是有,一是因为不懂,二是因为直观看来代码确实精简。这两年给自己安排的KPI都是FP相关的(去年是lisp,今年的lua相关性弱一点,之后的haskell可是自喻为pure FP呢),嗯,这叫IDL(Interest Driven Learning)。

今年眼看就要结束,总算是能沉淀一些在我看来能算作是Thinking的东西,还挺好的。

read more

Reading Lua (1) 准备工作

如果说后面几篇对lua源码的分析是干货的话,这一篇应该可以说是“废话”了。但事实上,看完了这篇,后面几篇你都不用看了。
因为这一篇跟后面几篇的关系——简单来说就是——渔和鱼。
在这一篇,我只写自己是怎样读代码的,而不提具体的代码。之所以把自己<b>了,是想要强调此处的渔是非常主观和个人化的东西,必须不适合所有人,就权当自己的经验总结和采坑大全了。

想要来一顿美味的Lua源码阅读大餐,你需要准备以下食材:

  1. 一个Visual Studio (不是说GDB不好,只是在断点的时候直接就转到上下文中函数的定义或实现,这种体验谁用谁知道)
  2. 一份原汁原味的Lua5.1.4源代码(这个版本可参考的资料最多,虽然Lua各种总的loc都不多,但简单而完备的版本看起来肯定更爽)
  3. 各种参考资料适量(云风的GC系列文章、ANoFrillsIntroToLua51VMInstructions、Mike Paul在各种地方留下的阅读指引)
  4. 足量的耐心
  5. 足量的时间

有了以上几种食材,烹饪的过程就异常简单了——F5!

没错,是他,是他,就是他:

F5

跟广为流传的MikePaul推荐的Reading Order不同的是,我觉得还是一上来就F5靠谱的多。默念函数名也是读F10也是读,running code总是比plain code更生动易懂(还有一种可能是我水平太low,大神都是可以直接通读脑中构建running state的上下文的)。当然,所谓“F5读代码大法”,并不是直接在main的第一行打上一个断点以后就不停的F10F11就行了。而是要在了解源代码大体结构(下一篇具体来写)的基础上:

  1. 确定一个feature
  2. 根据初读代码和猜测(怎么猜?靠函数名和变量名呗),在大致的位置打上断点
  3. 构造Lua代码
  4. 观察程序是不是会跑到这个断点
  5. 验证feature,整理整个流程

For example: 我想研究Lua的GC,看文章,大致Scan代码,发现GC是分好几个步骤的比如GCSsweepstringGCSsweep,那么当垃圾不包含string的时候,在一次GC里还会执行GCSsweepstring这个步骤吗?

构造lua代码如下:

local foo = {}
for i=1,1000 do
	foo[i/10] = { a = i, b = i+1 }
end

断点当然是打在lgc.c的这个位置:

	case GCSsweepstring: {
		lu_mem old = g->totalbytes;
		sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);

然后,F5走起。到断点了么?Callstack是什么样的?LuaState相关的field都是怎样的?解答自己的疑惑,再不停发问,继续解答。如此递归,就离这道大餐上桌的时间不远了。

一些PS:

  • VS中的Compile as C Code或者Command Argument怎么设置,google一下就知道
  • 宏没法打断点,实在搞不懂里面的实现就只能手动inline了,记得ctrl+z回来就好,虽然不改回来也没什么大问题
  • 接上一条,大胆的改代码做实验写注释,弄坏重新下一份源代码就好
END

Reading Lua (0)

跟去年的Learning Lisp遥相呼应,作为今年自我KPI完成的总结文来写,这次逼格高点,第一次在Blog写个series。

计划的Content Table如下:

  1. 准备工作
  2. 代码结构
  3. Lua有AST么
  4. 此VM非彼VM
  5. GC
  6. TODO

还有一些泛泛的感悟,放在这一篇抒发比较合适:

Lua的源代码写的太DIAO了!Lua的源代码写的太DIAO了!Lua的源代码写的太DIAO了!重要的事情说三遍。跟原来读了好多次都没读下去的Ruby源代码不一样,一共就50+的文件和20000W左右注释详细结构清晰的CodeBase,给人心里压力小太多了。虽然语言的复杂程度不是一个量级的,但麻雀虽小五脏俱全,Lua作为一门完美实现了设计初衷的语言,代码肯定是同样值得一读的。
Lua的实现没有任何依赖,而是用的是纯的Ansi-C!终于不用在Mac上make了,终于在Windows上也能out-of-the-box的跑起来了,对我们这种Windows低端程序员来说——太!开!心!了!
指针对我们这种低端程序员来说还是好难,虽然终究能看懂,但是花时间略久。Macro虽然写的很花哨,但我会手动inline,所以也还好。

END

Remove Vs RemoveAll

有个feature需要比较高频率的从集合中移除一部分元素,稍微脑洞了一下,感觉用for-loop+Remove应该比RemoveAll要快(可能是RemoveAll的example里用了lambda,影响了判断)。

BUT,test dont lie,写了个测试试了下:

var list = new List<int>();
for (int i = 0; i < 1000; i++)
{
    list.Add(i % 3);
}

var iter = 1000;

Profile("Remove", iter, () => 
{
    var l = list.ToList();

    for (int i = l.Count - 1; i > -1; i--)
    {
        if (l[i] == 0)
        {
            l.RemoveAt(i);
        }
    }
});

Profile("Remove All", iter, () => 
{
    var l = list.ToList();

    l.RemoveAll(item => item == 0);
});

结果RemoveAll效率要比Remove高好几倍,找了源代码扫了一下:RemoveAllO(n)且只有一次Array.ClearRemoveAt却每次都要Array.Copy(压缩空隙的操作),结果显而易见。严格来说,我是在Unity做的测试,但读的是.Net的源代码,好像有点不严谨

So,Once More:Test dont lie,Code dont lie。

END

My Tool Chain

timediff(now, lastpost).month > 6

这半年其实收获良多,各种language和各种runtime加上各种platform玩来玩去,想写的能写的值得一写也挺多,不急,慢慢来,记着就好。

念念不忘,必有回响。再拖拉我还是会写

这篇的主题是ToolChain——也可以叫——当我重装Windows/Mac时我弄些什么。

Alfred/Launchy

Alfred已经太有名了,无需多言。在windows上我能找到的(用过的)最好的替代品就是Launchy了。
实话实说,win7点了win键以后输入程序名相对xp来说已经有了很大提升了,但比起launchy这种专业的软件来说还是差了一大截。
特别是可以自定义程序搜索路径和记住最近打开的程序(e.g:我现在alt+space | c就是conemu,alt+space | ch就是chrome,alt+space | u就是unity)这两个feature,真心好用。
关于这种全局快捷键app的必要性,上古大神Alan Kay(可能记错)就说过:newbie用鼠标,frequent user用快键盘+鼠标,pro只用键盘。不用鼠标带来的效率逼格可以详询*nix over Windows党。
最后再说一个Launchy的好:donate只要2$,对比起sublime的70$(我觉得sublime也很好,但是没有好到35倍 || 如果我的工资发的不是¥而是$我就买),就是买买买啊。

Chrome

也算做过一段时间的web开发,各种浏览器出于工作也好个人喜好也罢,都用过一圈了,最后还是觉得Chrome最顺手(这类软件没有什么最好,只有最顺手)。
好像原来的原来还写过firefox plugin的post,插件这玩意也就是锦上添花,firefox现在跟Chrome比已经算不上了。
具体的有多就不表了,现在必须的只有手势这一朵了(还是稍微一提:Chrome的帐号系统确实好用,至少不用像以前的firefox一样每次重装都折腾一次插件了)。

VisualStudio/Sublime

Visual Studio出了community版本以后,Windows上最强的IDE基本就没任何争议了,随着MS越来越拥抱开源,其在社区里的口碑也越来越好了,现在我黑MS的欲望都越来越弱了。
Sublime作为Mac/Windows上都通用的Editor,对于我们这类小白开发(大神的Vi/Emacs都是比VS还厉害难用的多呢),着实是比其他文本编辑器好用了一大截。
这两个共同的优点就是1.feature多 2.插件多 3.GUI功能也很好用。诚然用鼠标的效率比不上用键盘,但鼠标悬停显示各种变量怎么也比用printpp让人愉快很多吧。

Python/Ruby/Github

Python和Ruby优先级高于其他运行时(Mac预装了)的原因在于很多小工具都是基于这两个runtime的,其他lua lisp node什么的就看心情了。关于ruby gem有个小tips:

gem sources --remove https://rubygems.org/    
gem sources -a https://ruby.taobao.org/    
gem sources -l

必须要赞一下taobao,在国内的开源界确实比其他公司走的要早要远。
Github for Windows这个GUI我觉得比tortoise还要好用,for Mac就更不用说了,Mac能战的SVN GUI根本就没有。

ConEnu

在Windows下——支持tab页+自定义font+支持ctrlc+ctrlv+最大化窗口的命令行工具——就我用过的——只此一家,所以没得选了。

What’s More

TODO

END

Learning Lisp

(MEMBER `TRY `(DO DO-NOT))

QQ签名从["do","do not"].include? "try"改成了上面的,眼看今年给自己的KPI——learning a language every year完成在即,心情大好。感觉自己编程功力又上升了一个小段位,下半年剩下的时间好好啃下SICP (看亚马逊评论说中文翻译的不太好,看来又只有原版走起了),争取能给自己打个S。

Lisp,逼格最高的编程语言之一(比他逼格更高的没人出来炫耀,比他逼格低的那就太多了)。在没TRY过之前,我觉得我肯定也是DO-NOT了。好好看了下,发现对我们这些C语系出身的程序员来说,Lisp真心可以算的上是mind-blowing了。极简的规则(上面那个quote已经包含了Lisp语法中所有最基本的元素了),一切都是list,而一切又都是执行(evaluating)。道生一,这似乎在哲学上更容易生出万物,也更有道法自然的感觉。

对lisp理解还停留在感性层面,道的出的牛逼也只有上面这些了。

Talk is cheap, show me the code。我懂,这个repo里有四个版本(Lisp Javascript Ruby C#)的代码,都只在干一件事情——计算一个多层嵌套的数组的和。先只贴Lisp的版本出来:

(DEFVAR *L* `(1 2 3 (1 (2 3))))

(DEFUN SUM-ALL (LIST)
       (COND ((ENDP LIST) 0)
             ((NUMBERP (FIRST LIST))
              		(+ (FIRST LIST) (SUM-ALL (REST LIST))))
             (T (+ (SUM-ALL (FIRST LIST)) (SUM-ALL (REST LIST))))))

(SUM-ALL *L*)

这段简单的递归能很好的体现出Lisp的表现力。平心而论,对于C#这种不支持异构数组的强类型语言来说,这对比似乎不怎么公平,因为C#版本里很大部分篇幅都用来构造数组了。而且递归这种东西好像本来就是从Lisp来的,写递归函数不就是在扬长避短么。对于你们这种怀疑我专门用特别的实例厚此薄彼的行为,我只想说,泥垢了

再次总结一下,现阶段Lisp于我来说炫酷得没朋友的特性就两点:极简的定义&&自顶向下的表现力。

PS1:入门看的是德国某大学的Common Lisp的在线教程,整个课程的设计简直是良心,还有statistic:

learn_lisp_statistic

PS2:Lisp的方言选择也是装逼活门艺术,以后就用Scheme了。我又不需要practical(我的武器库很牛逼,不要惹我),Common Lisp对我来说就太大了点。

SICP我来了。

END

Embedding Mono

前后折腾了好几天,终于把Demo跑起来了,全部的代码见这个repo,虽然行数不多,基本意思算是表达的比较清楚了(cpp里的注释都用心在写了,在我大Windows上跑起来的方法见上一篇post)。在天天用.NET的时期找了各种借口一直都没好好研究过hosting,这次用Mono做了个demo,算是把这个念想给圆了。

嗯,念念不忘,必有回响。

心得我只捡重要的,一个OL说完好了:

  1. 学好C很重要,不看Linux (实际上是看不懂),看个ruby mono什么的还是需要的。还是觉得#define什么的好难懂,想吐槽都不知道从何吐起。
  2. 对比unity的MonoBehavior,觉得我的Lib的设计更合理啊!毕竟virtual不就是干这个的吗,而且,在子类写完override就能出智能提示也要比光靠记忆去写Start()更科学啊。unity这样设计,应该是出于简单的考虑(这性能的提升可以忽略不计吧)?

  3. 在unmanaged的环境里去找method其实跟在managed环境里用反射做的事情和做的结果都挺相似的,当然,如果有很多假设(custom code的命名方式命名规则等等),就会少了很多读metadata的麻烦事儿。

  4. 设计framework/library确实比application要难得多,抽象和设计的重要性/关键性是做application比不了的。

  5. 开源就是好,你在想知道细节的时候可以去看,而不是猜。

  6. unity studio更像是photoshop而不是visual studio,没的辩。unity用mono做script engine也就是看上了它的跨平台而已,如果ruby python什么的跨平台做的足够好,可能也轮不到mono了。

做这个Demo感觉经验值涨了不少,不过还是要过两天用build on mono的形式写个一样功能的Demo,才算圆满。

END

为啥Unity3d没xx.designer.cs

winform时代,在vs的designer里拖啊拖啊,总是可以自动生成一个designer.cs,够(xiang)叼(si)的话你还能自己去改designer里的代码,运气好了vs的designer还能正常的识别,然后再继续拖拖拖。

unity3d的designer没有生成.cs,简直是,耍!流!氓!

先猜个原因再来做点实验:

前方高能预警(纯YY向)

read more

Callbacks 和(han) Promise 和 Rx*

想想还有几个月就去台湾了,心里还有点小激动呢,标题卖个萌。


回头看了一下,发现自己最近几个月对callback和async这些玩意儿出奇的关心。原因无它,各种callback和async操作实在是太反 人 类了(此处人类特指地球上某统治级灵长类生物中跟其祖先最接近的一群——程序猿,BTW,反正都扯蛋了就多扯两句:人人都知道user-friendly重要,但却没有人比微软更注重programmer-friendly,就这一点,简直要为M$点赞,以后蛋疼了一定要写一篇关于大微软爱护程序员的软文),而如何抽象这些反人类的东西,正是计算机和编程领域里最有魅力的部分。

read more

六月七日

写点啥

正好六月七号,按高考作文的套路来——总分总,记叙文,安全牌,力保上40。

总:莫忘初心,莫失匠心。

分:对不住,语文老师,我要开始散文了。

read more

无论如何,id还是比class快

http://jsperf.com/queryselector-id-vs-class

虽然这种结论用小脚趾头想也能得出来,还是jsperf了一下,92%的slower还是挺出乎意料的,基本上就跟sql有索引和没索引的差距一样大了(其实应该原理也类似才对)

END

不作死就不会死——重装OS X记

不作死就不会死,简直真理。

一个新的MBA,被我折腾了一天时间,直接就变成砖头了……

read more

Backbone.js初探

运气不错,有时间可以研究一些新玩意,就抓起了原来一直没好好看看的Backbone(严格来说,Backbone是现在流行的MV* javascript大军里资历最老的几个了,只是对我来说是新而已)

一边code一边看posts一边就开始写文章好了,前戏都省了,直接就是Pros/Cons:

read more

This is the new sheet

其实应该算是2013年的流水账总结文的,在< new Date("2014-1-10")的时候写下来应该还不算晚。

read more