本文原发在巴别诺瓦,把上篇BLOG没有细说的设计说清楚了。
最近没有去用太多时间研究Haskell,而是又把很多精力放回到已经工作了将近10年的Java了。原因很简单,这些日子和公司的一位老手合作,才豁然发现其实自己编程的基本功很差。
对程序员来说,语言的选择只是问题的一个方面,更重要的是他如何对待自己写出的每一行代码,境界的差别全在其中。就拿我这一两天学到的为例。
public static String format(Object[] arguments, String pattern) { return java.text.MessageFormat.format(pattern, arguments); } public static void test() { format(new Object[]{"a", "b"}, "{0}_{1}"); }
比如,上面这段普通不过的代码如何改进?我看到了下面的代码才明白自己没有真正理解变参函数的长处:
public static String format(String pattern, Object... arguments) { return java.text.MessageFormat.format(pattern, arguments); } public static void test() { format("{0}_{1}", "a", "b"); }
这只是一个小的细节。下面再举一个设计的例子,关于一个代码生成器:
需求很简单,输入一个格式类似 “${a.b.c}” 的字串,把它按照一定的业务规则,输出为另外一段代码。
上面描述的过程在业务类里面大量重复出现,一个可以设想的解决办法是把重复的代码提升到父类里面。
public String generate(Context ctx) { Reference ref = resolveReference(m_ref); String clazz = ctx.getClass(ref.getFirstPart()); String variable = getVariable(ref, "url"); String scriptlet = getScriptlet (ref, clazz, "url"); ctx.setAttribute(variable, scriptlet); return "${" + variable + "}"; }
然而因为父类导致抽象层次的增加,很多时候这种做法并不一定导致最好的解决方案,反而让代码变得难懂。有时候引入一个恰当的记法和工具类,可以使得代码变得异常的清晰。
public String generate(Context ctx) { Object[] parts = FormatHelper.parse(m_ref, "$'{'{0}.{1}.{2}'}'"); String clazz = ctx.getClass((String) parts[0]); String variable = FormatHelper.format("_url_{0}_{1}_{2}", parts); String scriptlet = FormatHelper.format( "{0}.url({3}.{1}.{2})", parts[0], parts[1], parts[2], clazz); ctx.setAttribute(variable, scriptlet); return "${" + variable + "}"; }
这样是不是清晰了很多呢?更多的好处还在于工具类没有破坏业务类的完整,对业务逻辑的控制权始终掌握在业务类里面,提高了代码的内聚性。
这位老手的话不多,但他评审代码的意见都很到位,让我心悦诚服。
更多想说的是,热爱编程的程序员应该要精益求精,追求代码的完美。只有多磨练,才能出真功夫。
第一个例子只是展现了可变参数的使用
第二个例子,没有类的上下文,让人很难理解改变后的好处
或许还应该再加一条,那就是多多阅读世界上最出色的程序员写的代码
变长参数在 Java 里的笨重的记法,似乎已经抵销掉它原本带来的好处了,想想 C 中的 printf 在调用时是多么的优雅:
printf(“Inserted %d out of %d.\n”, i, count);
JavaScript/Perl 里当然就更容易了,所有函数默认都是变长的,呵呵,不仅调用方便,定义也方便
Haskell 里没有类似的变长参数,毕竟在那里变长参数的调用记法已挪为他用--服务于 curry 了
)
Hi mingli,
现在 Babelnova 发表文章支持 publishing options,如果你希望自己发表的某些文章站外全文可见(比如你需要索引,或者和朋友在站外讨论),可以uncheck 那个”非成员用户限制访问”的选项,具体参见用户手册。
HTH.
我也没有特意花时间去学习Haskell,但是以后要有用到的可能就得慢慢学起来。
有个小小的建议,字体是否可以适当加大一些,尤其是代码,看着有点吃力。