作者:
中文JavaBeat
时间:
2007年08月22日 星期三
这是一篇译文,你可以参看本文在TSS上的 英文原文,这是我的第一篇译文,有很多不当之处请见谅,若能指出则更好了。
在GoF的设计模式那本书中作者清楚的指出在使用设计模式的时候所使用的语言是非常重要的:
The choice of programming language is important because it influences one’s point of view. Our patterns assume Smalltalk/C++ language-level features, and that choice determines what can and cannot be implemented easily. (Design Patterns, p.4)(程序设计语言的选择非常重要,它将影响人们理解问题的出发点。我们的设计模式采用了 Smalltalk 和 C++ 层的语言特性,这个选择实际上决定了哪些机制可以方便的实现。)
不幸的是,这一点经常被忽略,程序员们经常把设计模式和方法混用。Martin Fowler 解释了两者的不同:
Recipes tend to be more particular, usually tied to a particular programming language and platform. Even when patterns are tied to a platform, they try to describe more general concepts.(方法依赖于特定的编程语言和平台使它更加的特殊。即使是当模式依赖于平台的时候,他们也只是去描述更加一般的概念。)
如果你曾经看见一个看起来象C++方法集合的Java或者C#的应用程序,你就知道了混合这两个概念所产生的坏处了。不管你对模式和方法这两个概念之间的差异理解到何种程度,你所能想到的程序设计语言就只是你设计时所使用的程序语言。这也是Prags鼓励每一个人每年学习一门新的语言的一个原因。你可以结合你所知道的所有程序设计语言来进行设计,但至少你不是一个绝望的“乡下人”(?)。
编程语言的发展弱化了模式和方法之间的概念模糊。在1998年,Peter Norvig 辩驳道大部分的 GoF 模式在 Dylan 和 Lisp 中都看不到踪影或者非常简单的使用。在那以后,Greg Sullivan 也对 Scheme 做出相同的观点。Jan Hannemann 也指出 Java+AspectJ 也是如此。设计模式表现的不如方法那样好。他们至多平分秋色。
在编码层,大部分的设计模式都是有代码异味的。当程序员在 Review 代码的时候看到了一个设计模式,他们陷入了睡梦般的熟悉。醒醒吧!那是设计模式呢还是来自某种古老的语言的一种陈旧的方法?
作者:
中文JavaBeat
时间:
2007年08月18日 星期六
今天在做项目中脚本解析部分的时候,突然闪出了一个概念,就是语言中对变量名的定义,且看我在网上搜索出来的关于Java变量名的一段定义:“变量名是一个合法的标识符,它是字母、数字、下划线或美元符”$”的序列,Java对变量名区分大小写,变量名不能以数字开头,而且不能为保留字。合法的变量名如:myName、value-1、dollar$等。非法的变量名如:2mail、room#、class(保留字)等,变量名应具有 一定的含义,以增加程序的可读性。”定义中说的很清楚变量名不能以数字开头,其实不但是Java语言这样定义,所有的语言应该都是这样定义的。那么它为什么不能以数字开头呢?这应该要从编译原理的角度来解释了吧。
这是我今天在做脚本解析时突然想到的。先来说明一下我们的这个语法解析工具,要解析的脚本很简单,只包括了&,|,~,=,!=,()和{}等操 作符。开始时采用了编译原理的那一套,画NFA、DFA,找出状态然后再写词法分析生成Token,接着语法分析将生成的Token根据语义生成语法树, 最后求值。后来想一想,这个脚本很简单只需要一个一个字符判断遇到不同类型的字符就进入到不同的子函数中进行处理,同时完成词法解析和语法分析以及求值的 过程。不过无论使用那种方法都需要根据读入的字符来判断当前进入到哪个Token里了,这就是问题的关键所在。
为什么说判断字符属于哪个Token是关键呢?假设我们取消掉了变量名定义中不能以数字开头的限制,这时当词法分析器进入到一个Token分析的起始状态 时,如果读取的第一个字符为数字,那么词法分析器是无法判断它当前要分析的这个Token是变量名还是数字常量了。好,如果你说分析器可以根据后面的字符 来判断的话,那么如果下一个字符为字母,那么很容易就判断出当前Token属于变量名(我们暂且忽略保留关键字),但是当如果接下来的字符全都是数字那怎 么办?分析器将无法判断,因为变量名的定义中允许数字的存在。
呵呵,上面也许说的比较绕口难于理解,用句简单的话来讲就是:当分析”123″这个字符串的时候,如果变量名允许第一个字符为数字,分析器就不知道“123”该是数值常量还是变量名了。
总而言之,编译器在解析程序的时候,读到一个单词的第一个字符就需要知道当前这个单词属于那一类,这样方便于解析,不用回溯。
以前只知道学过的语言中变量名的定义都是不能以数字开头的,但是没有深究其中的原因,实际上根本就没在意这里面还有原因。今天只是写脚本解析的时候想到了这一点,呵呵,希望已经知道了的兄弟不要拿板砖扔我:)另外,如果你还知道其中其它的内幕,就提出来跟大家分享一下。
唉,还真是没有没有原因的事情,任何事情只要有人规定成文了,必定有其原因所在,也就是有其合理性所在,而我们在学习的过程中应该多多想为什么,不要放过 每一个细节。其实每个细节后面都隐藏着极深极大的原理或者说是内幕,了解了这些细节我们在做其他事情的时候才能游刃有余。
作者:
中文JavaBeat
时间:
2007年08月17日 星期五
看到一篇文章感觉很不错,可以开阔一下某些思路,转贴在此:
今天碰到一个很有意思的问题:用户在数据库中存有N张照片(照片是有顺序的),然后用户可以任意调整照片之间的顺序,照这样的话,每一次用户调整某一张照 片的顺序后相应地要想多米诺骨牌一样要影响他后面照片的顺序,这样在数据库中有M张照片的顺序编号都需要去Update,这样的话对数据库的压力太大。比 如第8张照片要移动到第二位,那么第7、6、5、4、3、2都要相应地改变,也就是在数据库中有7条记录需要去Update,代价太大。
最后这个问题是这样巧妙解决的:照片在数据库的编号不是1,2,3……这样连续的自然数,而是使用1024、2*1024、3*1024……这样跳跃的数 字来代表,当再有移动的时候,比如把8*1024移动到第二位也就是1024和2*1024之间的话,只需要在数据库中做一次Update,让 8*1024变成(1024+2*1024)/2,后面的那些编号都可以维持不变。这样数据库的压力就小多了!
当然时间久了后可能某一区段的数据编号太密集,甚至都无法插入了,嗯就像女人变老了后连上的皱纹都挤到一起去了,当然就需要去拉皮了,也就是当插入的时候发现没有位置了,这时候可以让前后两个位置向外围扩张一下,恩就像女士拉皮一样,呵呵,很形象吧。
当然要说这种算法怎么想到的,那多看看我们平时的生活,比如我们排队的时候,如果站的非常稀疏插一个人进来的话对整个队伍影响不大,但是如果一个紧靠一个的话,差一个进来大家都要相应地挪动一下,呵呵,所以说很多算法都可以从生活中受到启发的!比如Google的PageRank算法(我的一篇关于PageRank的原理和实现的文章)就是由论文质量的衡量很大程度上是由该论文被其他论文所应用的次数来决定的。
还有那个PK算法(也可以称作是多数派算法),比如一个字符串中一定有一个字符的数量超过了整个字符串长度的一半,怎么样找出这个字符?那么可以你可以在 这个字符串中不断取两个字符不一样的话这两个字符同时删除,一样的话只留下一个,一直到最后,剩下的那个就是所要找的那个(当然有一些的特殊情况需要处 理、优化),这种解决的思想就是非常形象的超女比赛的PK制度,哈哈,太有意思了吧。
所以我很多时候碰到很优美的算法的时候老是在想这个算法人家是怎么想到的?这个算法背后所代表的原理或者思想又是什么?这种思想还能够用在哪里?我觉得这才是最关键,能够让你不断地在算法领域越来越有悟性。 阅读这篇文章的其余部分 »
最新评论