庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

    怎么让你对象跟Array或者Hash一样,可以使用[ ]操作符来获取属性值或者赋值? 问题其实就是如何定义index操作符,在Ruby中可以这样做:

class Message
   def initialize
    @props
=Hash.new
   end
   def [](key)
      @props[key]
   end
   
   def []
=(key,value)
      @props[key]
=value
   end 
end

m
=Message.new

m[
0]=1
p m[
0]

m[:a]
="hello"
p m[:a]

        注意方法签名。

posted @ 2010-02-01 16:29 dennis 阅读(1050) | 评论 (2)编辑 收藏

    通讯层的改造使用了google protocol buffers作为协议体,效率还是挺让人满意。编辑以.proto结尾的语法文件,没有语法高亮很不习惯,幸好protocolbuf提供了vim和emacs的扩展。下载非win32版本的protocol buffers的压缩包里,解压后有个editors目录,里面就是两个扩展文件:proto.vim是提供给vim爱好者的,而protobuf-mode.el就是提供给emacs控的。
    安装很简单,将protobuf-mode.el加入你的Emacs加载路径,然后在.emacs配置文件里加上这么两行代码:
(require 'protobuf-mode)
(setq auto-mode-alist  (cons '(".proto$" . protobuf-mode) auto-mode-alist))
    require是不够的,第二行将自动把.proto结尾的打开文件以protobuf-mode模式运行。运行时截图:

         
    
    工具栏上多了个ProtocolBuffers菜单,有一些简单功能,如注释某段代码,代码跳转等等。

posted @ 2010-01-20 11:47 dennis 阅读(1737) | 评论 (1)编辑 收藏

    Java Memcached Client——Xmemcached的新版本1.2.2正式released。这个小版本最主要的改进是允许遍历所有在memcached中的key,这是通过stats协议实现,具体信息可以看这里

1.2.2的主要改进如下:

1、添加一个KeyIterator接口,这个迭代器接口用于遍历memcached中的所有key。由于是基于stats协议实现的,因此这个迭代过程并非高效,请慎重使用,并且迭代返回的key也并非实时,而是当前快照。KeyIterator目前仅在文本协议下可用,使用例子如下:
MemcachedClient client=
KeyIterator it
=client.getKeyIterator(AddrUtil.getOneAddress("localhost:11211"));
while(it.hasNext())
{
   String key
=it.next();
}

2、添加一个新类net.rubyeye.xmemcached.Counter,用于封装原始的incr/decr方法,提供类似AtomicLong原子类的API方便计数器的使用:
Counter counter=client.getCounter("counter",0);
counter.incrementAndGet();
counter.decrementAndGet();
counter.addAndGet(
-10);

3、修复BUG,如issue 71,issue 72,issue 70 etc.
4、声明废弃 net.rubyeye.xmemcached.buffer.BufferAllocator,现在哪怕你设置了这一属性也将被忽略,这个类将在以后的某个版本中移除
5、升级yanf4j到1.1.0

   Wiki用户指南都已经更新,欢迎使用并反馈任何建议或者bug报告。

项目主页:http://code.google.com/p/xmemcached/
下载地址:http://code.google.com/p/xmemcached/downloads/list

posted @ 2010-01-12 18:13 dennis 阅读(4497) | 评论 (7)编辑 收藏

   利用这个小工具,可以生成豆瓣上记录的每年读的书,看的电影,听的音乐。我的记录,看过的书


看过的电影:



posted @ 2010-01-11 09:26 dennis 阅读(830) | 评论 (1)编辑 收藏

    《Joel on software》谈到所谓抽象漏洞,简单来说就是抽象能解决90%的一般情况,而其他10%的情况你仍然需要跟抽象层面下的细节打交道,也就是抽象本身只能减少你的工作时间,而无法减少你的学习时间。道理简单,举几个例子。
    以SQL语言为例,SQL是所谓说明性的语言,你所写的语句只是一条what,而how是如何做的无需关心,但是真的无需关心吗?事实上是不行,低效的SQL语句对数据库的性能损害非常大,作为程序员你需要知道SQL这个抽象层次下的部分内容,知道数据库是怎么执行这些语句,知道如何去避免一些最差实践。再比如分布式调用希望做到能跟本地调用一样的透明,但实际上还是不行的,网络的不确定性让RPC调用根本无法做到的类似本地调用那样的透明性。隐藏在RPC这个抽象层次下的网络通信细节,你不能不去care。抽象能帮你解决大多数情况,提高你的工作效率,但是剩下的一公里问题,仍然需要你花费更多时间和精力去了解并解决。这事实上也是一个优秀程序员跟普通程序的差别之一,学习了java编程,知道了collection集合框架,不代表你无需再去学习数据结构和算法。
    Joel将这个现象称为漏洞抽象。事实上,我并不认为这是抽象本身的漏洞,这反而是软件的本质复杂性在作怪,抽象只能去化简偶然复杂性,例如函数、类、模块化等手段去组织代码,而本质的复杂性是无法避免的。举个不是那么恰当的例子,例如我们有这么个方法,传进一个参数list,我们要遍历list做一些事情,(我知道用迭代器才是正途,先允许我犯这么个错误),你可能这么写:

    public void doSomething(List<String> list){
        
for(int i=0;i<list.size();i++){
            String str
=list.get(i);
            
//do something
        }
    }

   这样的代码我估计在1.5有for语句增强之前不少人都写过,这样的代码有什么问题呢?考虑下list是ArrayList和LinkedList这两种情况,List是链表的抽象,但是链表的实现形式却是可以用数组或者引用链接,链表的实现形式不同,List.get(index)这个方法的效率会很成问题。我们都知道ArrayList适宜于随机访问,而LinkedList方便插入添加移除,在这个doSomething方法中,显然随机访问的诉求大于添加移除。在通常情况下,这样写都不会成为问题,但是如果这个doSomething方法被经常调用,并且list是一个LinkedList的情况下,这个方法就很可能成为性能瓶颈。我们寄希望于List这个接口可以让我们无需关心list的具体实现,然而现实是你仍然需要知道各种实现的区别和原理,这就是所谓漏洞抽象。这并非抽象的无力,你肯定不会反对“针对接口编程”这条原则,而是抽象本身解决不了本质复杂性,这里的本质复杂性就是链表的实现方法,随机访问与添加移除的平衡问题。在我们无法找到更好的链表实现方法来平衡随机访问与添加移除之前,这个本质复杂性就不是抽象能够解决的。
    同样的现象出现在String、StringBuffer、StringBuilder的使用上,字符串的实现方法你仍然需要知道,这是绕不过去的本质复杂性。这里谈到的本质复杂性根本上也是现实世界的本质复杂性的反映,扯远些就更虚了。就现实的工作情况来看,不知道其他人有没有这样的经验,就是在自以为解决某个难题的时候,最后却发现难题以另一个面目出现,问题本身没有得到解决,只是以更好的方式被掩盖了。
   无论是过程式、OO、函数式编程,解决的问题都是为了更好的抽象,抽象是个好东西,但是抽象无法解决那些本质性的问题,因此《人月神话》断言没有银弹,我们仍然需要跟狼人作战。

    
  



posted @ 2010-01-10 20:25 dennis 阅读(2943) | 评论 (4)编辑 收藏

    你不得不承认,写代码的效率跟周期性的情绪相关。以我为例,总存在着周期性的情绪波动,那段时间内基本不想写代码,上班就是收收邮件,看看网页,遗憾的是每个月都有那么几天。事实上,我认为在一天8小时的工作中,能有2、3个小时能达到忘我状态的工作,那已经是非常不错的事情。如果你是程序员,你肯定知道我说的忘我状态是什么。我在这里说的局限了,其实任何工作都可能进入这种忘我状态,这种状态下你的思维非常活跃,全神贯注,哪怕有人跟你说话你也会听而不闻,这种状态在你读一本非常有趣的小说的时候也会出现。这种状态下的你效率会非常高,例如我前段时间内就在一周内写了13000多行代码,600多个测试用例,为我们的系统重新实现了一个通信层。

   看过很多讨论程序员工作效率的文章,据称研究表明要进入这种状态是至少要15分钟的时间,因此频繁地打断工作会阻碍你的工作效率,毕竟酝酿情绪也是需要时间的嘛。我有思考过怎么去尽量多地保持这种状态,排除那种对工作厌烦的情绪,毕竟拿着工资不干活心里还是会不安,况且看到周围那么多高效率的人,压力是难免的,让人担心的不是每天只有两个小时的高效工作,而是那段什么都不想干的时间。最后让我发现一个方法,说起来很简单,就是在出现这种低效状态的时候,强迫自己打开eclipse,而不是 firefox,强迫自己去写几行代码,如果这段时间内没有被其他事情打断,那么你还是容易进入一种不那么高效和愉悦的工作状态,至少能做到专心致志。当然,跟自己的情绪对抗可能不是世界上最困难的事情,也是其中之一,不过请你相信,只要你打开eclipse开始写代码并进入思考状态,那么你至少是可以暂时遗忘那些负面情绪的,甚至你的情绪可能因为解决了某个难题而高昂起来。
   这个方法肯定不是什么新发现,我估计很多人会有同样的经验,今早在看《joel说软件》其中一篇文章《开火与运动》也谈到了同样的问题,joel也提到相同的经验:开了头就好。你不知道要费多少劲才能将一辆带齿轮的山地车运转起来,不过一旦它转起来之后,一切都跟骑一辆没有齿轮的自行车没什么两样。Joel还延伸了更多,开火的策略不仅仅是工作效率的问题,也是竞争策略,当你向敌人开火的时候,同时向敌人靠过去,活力会迫使敌人低下头而不能向你开火。竞争也是如此,压迫性的不断推出新东西让你的竞争对手疲于奔命,反而遗忘产品的根本性的目的,这些新东西可能只是为了替换过去不易用的东西,为什么不易用的东西在过去也会被推出来?那只是了为每天进步不断开火,让敌人忘记开火。
   

posted @ 2010-01-09 11:09 dennis 阅读(3128) | 评论 (7)编辑 收藏

    趁着下班前的半小时,回顾下2009年我都干了什么,有什么收获,有什么不足。
    09年最重要的事情是我的儿子出生了,小家伙的到来带给全家很多欢乐,烦恼也不少,比如半夜总要被吵醒,晚上的读书也没办法那么专心读了。此外,我还在学习怎么当爸爸,写过这篇《新爸爸指南》,记录下新生儿遇到的种种问题,逐渐经历自己生命的又一个阶段,这个历程很美好。
    年初从广州公司辞职后,到了厦门一家创业公司,这不是一次很愉快的经历,回想起来我的问题不小。首先不该贸然地想去转换一个语言平台,写C++实在不是很好的编程的体验,乃至于我根本提不起工作热情;其次,心态不成熟,遇到问题和困扰的时候还是比较被动地解决,事实上完全没必要搞成这样,主动提出并且离开公司并不是什么丢人的事情。这次经历告诉我做决定的时候最好再慎重一点,毕竟自己不是一个人了,养家糊口是实实在在的责任。
   在厦门的失败经历后,我投简历到了淘宝,尽管对于待遇并不是很满意,出于对淘宝的向往和有点理想主义的小情怀还是来到了杭州。刚来的时候,工作很顺利,生活比较糟糕,老婆孩子接到杭州后才好了点,生活比较有规律了。在淘宝,我所做的仍然是开发,写代码还是我的最爱,不过做的离业务的比较远,这正符合我的期望。负责的是一个消息中间件的开发,这个产品本身已经成型,并且应用在了淘宝的核心系统当中,现在每天通过这个MQ发送的消息量已经接近两亿,整个系统拥有数个集群,近30台机器。工作不单纯是开发,包括一些方案的设计和日常的维护工作,总体来讲还是很愉悦的体验。不足的地方,我仍然还是将自己视为一个纯粹的技术人员,对淘宝本身的业务、对其他系统的架构设计的了解都比较少,甚至于认识的人还是很局限,不过这个跟我的性格有关了。
    技术上,这一年自我感觉没多大进步,除了将sicp读完之外(我准备再度几遍),一些零零散散的技术书籍也看了不少,很少留下深刻的印象,比较有价值的是《卓有成效的程序员》和《C++网络编程》上下两卷。前者使我开始有意识地将自己一些重复性的工作自动化,提高自己的工作效率,后者让我对网络框架的设计模式有了相对全面的认识,也促进了我对Java网络编程的认识。今年也开发了个Java Memcached Client——Xmemcached,并在大家的鼓励下持续地在改进,总算有不少用户在用,没有枉费精力和时间,也算今年的一个小小自得的地方。这里要特别感谢下曹晓刚,没有他的鼓励和他们公司的使用,xmc还只是个人玩具。09年下半年又将不少精力放在了Erlang,过去学习是跟风,这次总算在项目中了有了个小应用,并且将《Erlang程序设计》和OTP设计原则来回读了几遍,对Erlang的兴趣越来越大,甚至于想是不是该去找份专职做Erlang的工作。对技术的学习,我还是没有一个明确的规划,任凭兴趣在几个领域里转来转去,这不是好现象,明年希望能更有计划和针对性地去学习,能跟自己的工作契合得更紧密一些。明年也希望能将《算法导论》读完,今年读了1/4,发现我的数学都已经抛到了Java国了,算法复杂度的推导总是看不懂,因此又去搞了几本数学书,从头再看看。

   回顾完了,说说明年的愿望:
技术上:读完《算法导论》,继续深入Erlang,探索Erlang在工作中的实际应用,加强对其他系统的了解以及大型网站构建方面的学习
生活上:希望能全家一起去旅游一次,希望能将老爸老妈接过来玩一段时间。







posted @ 2009-12-24 17:29 dennis 阅读(1535) | 评论 (2)编辑 收藏

    昨天收到一个xmc的issue报告,大概的意思是将Xmemcached与spring 2.5集成没有任何问题,但是将spring升级到3.0就会抛出一个异常,并且spring容器无法正常启动,异常信息类似“Couldn't find a destroy method named 'shutdown' on bean XMemcachedClientFactoryBean”。更详细的情况可以看这里,这是这位朋友分析的结果,简单来说就是spring 3.0对于查找destroy method为空的情况处理不同了,过去是打个日志,现在是抛出一个异常。
   问题说完,这里主要是介绍下这个问题的解决方式,事实上Xmemcached有一个没有被文档化的Spring配置方式,没有写入文档的主要考虑是以为wiki介绍的第一种方式已经足够,而builder的方式相对繁琐一些。通过XmemcachedClientBuilder的这个factory bean的factory-method,也就是build方法来构建MemcachedClient,这就可以绕开spring 3.0的这个问题。一个示范配置如下:

<bean name="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
        
<constructor-arg>
            
<list>
                
<bean class="java.net.InetSocketAddress">
                    
<constructor-arg>
                        
<value>localhost</value>
                    
</constructor-arg>
                    
<constructor-arg>
                        
<value>12000</value>
                    
</constructor-arg>
                
</bean>
            
</list>
        
</constructor-arg>
    
</bean>
    
<bean name="memcachedClient" factory-bean="memcachedClientBuilder"
        factory-method
="build" destroy-method="shutdown" />

   memcachedClientBuilder作为一个factory-bean,接受一个InetSocketAddress列表作为构造函数传入,最后MemcachedClient就可以通过factory-method——也就是build方法创建了。

   多个节点情况下,可能你想设置权重,那么传入memcachedClientBuilder的第二个构造函数参数权重数组即可:
<bean name="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
        
<constructor-arg>
            
<list>
                
<bean class="java.net.InetSocketAddress">
                    
<constructor-arg>
                        
<value>localhost</value>
                    
</constructor-arg>
                    
<constructor-arg>
                        
<value>12000</value>
                    
</constructor-arg>
                
</bean>
                
<bean class="java.net.InetSocketAddress">
                    
<constructor-arg>
                        
<value>localhost</value>
                    
</constructor-arg>
                    
<constructor-arg>
                        
<value>12001</value>
                    
</constructor-arg>
                
</bean>
            
</list>
        
</constructor-arg>
        
<constructor-arg>
            
<list>
                
<value>1</value>
                
<value>2</value>
            
</list>
        
</constructor-arg>
    
</bean>
    
<bean name="memcachedClient" factory-bean="memcachedClientBuilder"
        factory-method
="build" destroy-method="shutdown" />


上面的例子将localhost:12000的权重设置为1,而localhost:12001的权重设置为2。除了这些配置外,XmemcachedClientBuilder还有其他选项,如配置一致性哈希算法、连接池等,完整的配置例子如下:

<bean name="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
                
<!-- XMemcachedClientBuilder have two arguments.First is server list,and second is weights array. -->
                
<constructor-arg>
                        
<list>
                                
<bean class="java.net.InetSocketAddress">
                                        
<constructor-arg>
                                                
<value>localhost</value>
                                        
</constructor-arg>
                                        
<constructor-arg>
                                                
<value>12000</value>
                                        
</constructor-arg>
                                
</bean>
                                
<bean class="java.net.InetSocketAddress">
                                        
<constructor-arg>
                                                
<value>localhost</value>
                                        
</constructor-arg>
                                        
<constructor-arg>
                                                
<value>12001</value>
                                        
</constructor-arg>
                                
</bean>
                        
</list>
                
</constructor-arg>
                
<constructor-arg>
                        
<list>
                                
<value>1</value>
                                
<value>2</value>
                        
</list>
                
</constructor-arg>
                
<property name="connectionPoolSize" value="2"></property>
                
<property name="commandFactory">
                        
<bean class="net.rubyeye.xmemcached.command.TextCommandFactory"></bean>
                
</property>
                
<property name="sessionLocator">
                        
<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"></bean>
                
</property>
                
<property name="transcoder">
                        
<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
                
</property>
        
</bean>
        
<!-- Use factory bean to build memcached client -->
        
<bean name="memcachedClient" factory-bean="memcachedClientBuilder"
                factory-method
="build" destroy-method="shutdown"/>



posted @ 2009-12-24 01:51 dennis 阅读(4875) | 评论 (1)编辑 收藏

    最近读数理逻辑方面的资料,感慨自己没有早点接触逻辑学,如果在小学初中阶段就能有逻辑学的系统训练,我想我对数学的理解会完全不一样,对定理证明的思路也将大大开拓。中学时代对数学充满热情,基本上老师讲的都满足不了我,我的学习远远在课堂前面,初中的时候我已经接触了微积分、概率论、立体几何之类,教材是从我舅舅用过的教材垃圾堆里淘出来的,那时候我外婆准备卖了那堆书,就叫我去看看有没有想要的,印象中从那里掏出了不少好东西,武侠小说、马克思恩格斯全集、毛选、数学语文教材之流,在老家那个阅读资料极度缺少的地方,这些书成了我整个初中的精神食粮。上了高中后,家也搬到县城,离书城近了,并且学校有图书馆,更是如鱼得水。扯的太远,回到题目,以数学定理的证明为例,我们熟知的直接证明、反证法、数学归纳法、间接证明、存在性证明、唯一性证明其实背后都有牢固的逻辑定律在支撑,直接证明其实就是蕴含 p-> q,而反证法的原理是¬¬p ↔ p,间接证明则是原命题与逆否命题等价 p-> q ↔ ¬q -> ¬p等等。如果在教授数学的同时,教授给学生背后的逻辑原理,那么将极大地开阔学生的视野并且让数学证明变的有趣。数理逻辑不仅仅对数学学习有益,对软件开发同样有帮助,例如以谓词和量词来精确地描述和分析系统规格,推理逻辑的使用也能启发你的设计思路,帮你找到一个复杂的设计的等价物。此外,你能更快地比别人做出某些逻辑难题,这也挺有趣。

posted @ 2009-12-12 16:35 dennis 阅读(1331) | 评论 (0)编辑 收藏

    Xmemcached  1.2.1正式发布,这是1.2.0发布以来的第一个小版本,主要改进是修复BUG、内部重构以及添加一些新特性。主要改进如下:

1、为Kestrel 1.2添加delete方法支持,kestrel 1.2发布后正式支持memcached delete协议

2、添加了一个新的序列化转换器 net.rubyeye.xmemcached.transcoders.TokyoTyrantTranscoder,专门提供给使用xmemcached连接Tokyo Tyrant的用户,这个转换器默认在value前加上4个字节的flag,因为Tokyo Tyrant不支持flag,所以默认无法存储除String之外的Java序列化类型。

3、添加两个新选项:


    Transcoder.setCompressionThreshold(threshold)
 
    Transcoder接口添加了setCompressionThreshold用于设置压缩阀值,序列化后的value如果超过这个阀值将启用压缩,默认阀值是16K。

  
MemcachedClient.setSanitizeKeys(true|false)  

    setSanitizeKeys用于决定是否启用URLEncoding来编码key,如果你用url作为key存储,这一特性能方便你的使用,默认为开启。

4、添加中文用户指南,比较完整的使用说明和选项说明,在线阅读

5、内部优化,移除一些老代码和一些在1.1中被声明为Deprecated的方法。添加了更多单元测试。

6、BUG修复和对binary协议实现的部分优化。

项目主页:http://code.google.com/p/xmemcached/

下载地址: http://code.google.com/p/xmemcached/downloads/list

 

欢迎试用和反馈。

posted @ 2009-12-04 13:07 dennis 阅读(1800) | 评论 (2)编辑 收藏

仅列出标题
共56页: First 上一页 11 12 13 14 15 16 17 18 19 下一页 Last