2009年12月3日

例子下载在此

最近搞了个小实验,发现Eclipse 插件的类加载的一个问题。Eclipse使用Equinox实现OSGi的框架,可以在插件的配置中确定哪些类expose出去,哪些类不能为外部所见。我发现的问题是,可以通过ClassLoader绕过这个限制,在外部插件中加载到插件里那些不为外部所见的类,并且能够创建类的实例,可以通过反射调用其方法(当然,如果被加载的类实现了某些接口,也可以通过接口的引用直接调用相应的方法)。

为了演示这个问题,先在eclipse中创建一个插件UtilityLibrary

其中utilitylibrary.expose包中的类会暴露给外部,而utilitylibrary.hide包中的类不会暴露给外部。在MANIFEST.MF中增加这个设置:


VisiableClassVisiableClass类的内容很简单:
package utilitylibrary.expose;

public class VisiableClass {
    
public VisiableClass() {
        System.out.println(
"This is VisiableClass");
    }

    
public String getMessage() {
        
return "From VisiableClass:\r\n"
                
+ this.getClass().getClassLoader().toString() + "\t";
    }
}

package utilitylibrary.hide;

public class InvisiableClass {
    
public InvisiableClass() {
        System.out.println(
"InvisiableClass");
    }

    
public String getMessage() {
        
return "From InvisiableClass:\r\n"
                
+ this.getClass().getClassLoader().toString() + "\t";
    }
}


其实主要就是打印出相应的信息。类代码几乎是一样的。

下面创建另一个插件UsePlugin,依赖并使用UtilityLibrary中的类。插件其实就是Eclipse自带的Hello World程序,它会在eclipse 的toolbar上增加一个按钮,点击后会弹出一个MessageBox。好,MessageBox上显示的就是从UtilityLibrary中类的方法的返回值。首先增加插件依赖关系:


在SampleAction中的Run方法里,如果直接使用InvisiableClass,插件完全找不到这个类,修改建议里面建议expose这个类:


当然,使用VisiableClass是没问题的。下面通过VisiableClass来将InvisiableClass拽出来,SampleAction类的源代码如下,只要关心run方法就可以了:

package useplugin.actions;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

import utilitylibrary.expose.VisiableClass;

/**
 * Our sample action implements workbench action delegate. The action proxy will
 * be created by the workbench and shown in the UI. When the user tries to use
 * the action, this delegate will be created and execution will be delegated to
 * it.
 * 
 * 
@see IWorkbenchWindowActionDelegate
 
*/
public class SampleAction implements IWorkbenchWindowActionDelegate {
    
private IWorkbenchWindow window;

    
/**
     * The constructor.
     
*/
    
public SampleAction() {
    }

    
/**
     * The action has been activated. The argument of the method represents the
     * 'real' action sitting in the workbench UI.
     * 
     * 
@see IWorkbenchWindowActionDelegate#run
     
*/
    
public void run(IAction action) {
        
try {
            Class
<?> clazz = VisiableClass.class.getClassLoader().loadClass(
                    
"utilitylibrary.hide.InvisiableClass");
            Object obj 
= clazz.newInstance();
            Method method 
= clazz.getMethod("getMessage");
            Object ret 
= method.invoke(obj, new Object[] {});
            System.out.println(ret);
            MessageDialog.openInformation(window.getShell(), 
"UsePlugin", ret
                    .toString());
        } 
catch (ClassNotFoundException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (InstantiationException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (IllegalAccessException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (SecurityException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (NoSuchMethodException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (IllegalArgumentException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        } 
catch (InvocationTargetException e) {
            
// TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    
/**
     * Selection in the workbench has been changed. We can change the state of
     * the 'real' action here if we want, but this can only happen after the
     * delegate has been created.
     * 
     * 
@see IWorkbenchWindowActionDelegate#selectionChanged
     
*/
    
public void selectionChanged(IAction action, ISelection selection) {
    }

    
/**
     * We can use this method to dispose of any system resources we previously
     * allocated.
     * 
     * 
@see IWorkbenchWindowActionDelegate#dispose
     
*/
    
public void dispose() {
    }

    
/**
     * We will cache window object in order to be able to provide parent shell
     * for the message dialog.
     * 
     * 
@see IWorkbenchWindowActionDelegate#init
     
*/
    
public void init(IWorkbenchWindow window) {
        
this.window = window;
    }
}


在run方法里面,直接使用VisiableClass.class.getClassLoader().loadClass("utilitylibrary.hide.InvisiableClass");来加载本不应该被外部所见的Invisiable类。因为在Eclipse中,每个插件使用一个ClassLoader,所以用来加载VisiableClass类的ClassLoader也同样负责加载在同一个插件中的InvisiableClass类。这样InvisiableClass就在插件外部被加载成功了。类加载成功后,剩下的事情就是顺水推舟了,创建个实例然后使用反射调用相应的方法。
程序运行的时候,点击toolbar上那个button,会弹出如下对话框:


程序运行也没啥错误。


问题分析:
其实我觉得这个问题是很难绕过去的。对于同一个插件,因为内部的类需要互相引用和互相使用,所以必须使用同一个类加载器来加载。所以,这个插件只要expose出来一个包,那么外部的插件就可以通过包中的任何一个类来得到加载这个插件中的类的类加载器,然后就可以通过reflect爱做啥做啥了。

换一个角度可能更好理解这个问题为什么难以绕过去。假设VisiableClass需要用到InvisiableClass,虽然InvisiableClass没有暴露出来,但是在正常的使用VisiableClass的时候,需要先加载VisiableClass类,而加载VisiableClass的时候JVM就会隐式的加载InvisiableClass。这个过程和例子里现式的加载InvisiableClass没啥本质不同。也就是说,从ClassLoader的角度,很难判断一个类的加载是正常的代码还是为了突破bundle的访问限制——它们都是在执行run方法时发生的类加载行为。

或者是我有什么地方没设置好?求解答。例子下载在此

posted @ 2010-05-17 12:09 深夜两点 阅读(4779) | 评论 (8)编辑 收藏

宅能量终于爆发了,书终于出版了。China Pub有售http://www.china-pub.com/196571

posted @ 2010-04-27 20:47 深夜两点 阅读(1660) | 评论 (1)编辑 收藏

在设计一个多线程程序的时候,首先要考虑好线程模型是怎样的。设计线程模型的时候可以有多个考虑,比如使用线程池,使用多个线程处理任务,或者使用类似AWT/Swing中事件处理机制那样,使用单个线程处理同一类的任务。

posted @ 2010-04-26 16:33 深夜两点 阅读(235) | 评论 (0)编辑 收藏

rt

posted @ 2010-04-11 11:21 深夜两点 阅读(233) | 评论 (0)编辑 收藏

自己写的一个小程序,做个视频冒充一下技术宅……


程序经多次优化,终于能够达到一个可以接受的性能了……莫言Java无效率,其实重要的还是要精雕细琢。至 少就绘制Julia Set而言,我这个程序比我见过的几个cpp版本的要快的多。
项目主页地址:http://code.google.com/p/juliasetcreator/
程序下载地址:http://code.google.com/p/juliasetcreator/downloads/list

posted @ 2010-03-20 17:25 深夜两点 阅读(2616) | 评论 (2)编辑 收藏

转自http://static.icybear.net/%5BCN%5DProgrammer%20competency%20matrix.htm

[译文]程序员能力矩阵 Programmer Competency Matrix

注意:每个层次的知识都是渐增的,位于层次n,也蕴涵了你需了解所有低于层次n的 知识。
计算机科学 Computer Science
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
数据结构 不知道数组和链表的差异 能够解释和使用数组, 链表,字典等,并且能够用于实际的编程任务。 了解基本数据结构时间和空间的折中,比如数组vs 链表,能够解释如何实现哈希表和处理冲突,了解优先队列及其实现。 高等的数据结构的知识,比如B-树、二项堆、斐波那契堆、AVL 树、红黑树、伸展树、跳跃表以及前缀树等。
算法 不能够找出一个数组各数的平均值(这令人难以置信,但是我的确在应聘者 中遇到过) 基本的排序,搜索和数据的遍历和检索算法。 树,图,简单的贪婪算法和分而治之算法,能够适度了解矩阵该 层的含义。 能够辨识和编写动态规划方案,良好的图算法知识,良好的数值估算的知识,能够辨别NP问题等。 Working with someone who has a good topcoder ranking would be an unbelievable piece of luck!
编程体系 不知道何为编译器、链接器和解释器。 对编译 器、链接器、解释器有基本的了解。知道什么是汇编代码以及在硬件层如何工作。有一些虚拟内存和分页知识。 了解内核模式vs用户模式, 多线程,同步原语以及它们如何实现,能够阅读汇编代码。了解网络如何工作,了解网络协议和socket级别编程。 了解整个程序堆栈、 硬件(CPU+内存+中断+微码)、二进制代码、汇编、静态和动态链接、编码、解释、JIT(just-in-time)编译、内存碎片回收、堆、栈、存 储器编址…
软件工程 Software Engineering
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
源码版本控制 通过日期备份文件夹 VSS和初级的 CVS/SVN用户 熟练地使用CVS和SVN特性。知道如何分支和归并,使用程序库补丁安装特性等 有分布式VCS 系统的知识。尝试过Bzr/Mercurial/Darcs/Git
自动化编译 只知道在IDE下编译 知道如何编译在命令行 下编译系统 能够安装一个脚本构建基本的系统 能够安装一个脚本来构建系统并且归档,安装程序,生成发布记录和给源 码控制中的代码分配标签。
自动化测试 认为所有的测试都是测试员的工作。 能够编写 自动化的单元测试,能够为正在编写的代码提出良好的测试用例。 按照TDD (Test Driven Development)方式编写代码。 了解并且能够有效自动化安装,载入/性能和UI测试
程序设计 Programming
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
问题分解 只有直线式的代码,通过复制粘贴来复用 能够把 问题分散到多个函数中 能够想出可复用的函数/对象来解决大题的问题 使用适宜的数据结构和算法,写出通用的/面向 对象的代码来封装问题的易改变的层面。
系统分解 N想不出比单一的文件/类更好的层面 如果不在 同一平台或没采用相同的技术,能够把问题空间和设计方案分解。 能够设计跨技术/平台的系统。 能够在多个产品线和 与外部体系一体化中虚拟化和设计复制的系统。同时也能够设计支持系统监视、报告、故障恢复等。
交流 不能向同伴表达想法/主意。匮乏拼写和语法的能力。 同 伴能了解你在说什么。有良好的拼写和语法能力。 能够和同伴进行高效的交流 能够使用清晰的方式了解和交流想法/设计 /主意/细则,能适应每种环境的交流 This is an often under rated but very critical criteria for judging a programmer. With the increase in outsourcing of programming tasks to places where English is not the native tongue this issue has become more prominent. I know of several projects that failed because the programmers could not understand what the intent of the communication was.
同一文件中代码组织 同一文件中组织没有依据 按照逻辑 性或者易接近的方法 代码分块和对于其他源文件来说是易于是释,引用其他源文件时有良好的注释 文档头部有许可声 明,总结,良好的注释,一致的空格缩进。文档外观美观。
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
跨文件代码组织 没够想过给代码跨文件组织 相关文件按文件 夹分组 每个物理文件都有独立的目的,比如一个类的定义,一个特性的实现等。 代码在物理层组织紧密,在文件名上与 设计和外观相匹配,可以通过文件分布方式洞察设计理念。
源码树组织 一切都放在一个文件夹内 初步地将代码分散进 对应逻辑的文件夹。 没有循环依赖,二进制文件,库,文档,构建,第三方的代码都组织进合适的文件夹内。 源码树的 物理布局与逻辑层次、组织方式相匹配。可以通过目录名称和组织方式洞察设计理念。 The difference between this and the previous item is in the scale of organization, source tree organization relates to the entire set of artifacts that define the system.
代码可读性 单音节的名称 (在国内应该是那些类似用汉语拼音命名的习惯) 对文件、变量、类、方法等,有良好的命名。 没有长函数、注释解释不常规的代码,bug修复,代码假设。 代 码假设验证使用断言,自然的代码流,没有深层嵌套的条件和方法
防御性编码 不知道这个概念 检查代码中所有的参数,对关键 的假设进行断言 确保检查了返回值和使代码失败的异常。 有自己的库来帮助防御性编程、编写单元测试模拟故障
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
错误处理 只给乐观的情形编码 基本的代码错误处理,抛出 异常/生成错误 确保错误/异常留在程序中有良好的状态,资源,连接,内存都有被合适的清理。 在编码之前察觉可能 出现的异常,在代码的所有层次中维持一致性的异常处理策略,提出整个系统的错误处理准则。
IDE IDE大部分用来进行文本编辑 了解其周围的接 口,能够高效地通过菜单来使用IDE 了解最常操作的键盘快捷键 编写自定义宏
API 需要频繁地查阅文档 把最频繁使用的API记在脑 子里 广阔且深入的API知识。 为了使实际任务中常用API使用更加便捷,编写过API的上层库,填补API之间 的缺口。 E.g. of API can be Java library, .net framework or the custom API for the application
框架 没有使用过主平台外的任何框架 听过但没用过平台下 流行的可用框架 在专业的职位中使用过一个以上的框架,通晓各框架的特色。 某框架的作者
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
需求分析 接受给定的需求和代码规格 能对规格的遗漏提出 疑问 了解全面情况,提出需要被规格化的整体范围。 能够提出更好的可选方案,根据经验的浮现给出需求
脚本 不具备脚本工具的知识 批处理文件/shell脚本 Perl/Python/Ruby/VBScript/Powershell 写过并且发表过可重用的代码
数据库 认为Excel就是数据库 知道基本的数据库概 念,规范化、ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)、事务化,能 够写简单的select语句 能够牢记在运行时必要查询中设计良好的规范化数据库模式, 精通用户视图,存储过程,触发器和用户定义类型。知道聚集与非聚集索引之间的差异。精通使用ORM(Object Relational Mapping对象关系映射)工具 能做基本的数据库管理,性能优化,索引优化,编写高级的select查询,能够使用相关sql来替 换游标,理解数据内部的存储,了解如何镜像、复制数据库。知道两段数据提交如何工作
经验 Experience
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
专业语言经验 命令式语言和面向对象语言 命令式语言,面向对象语言和说明型语言(SQL),如果了解静态类型vs动态类型,弱类型vs强类型则有加分 函数式语言,如果了解延 缓求值,局部套用函数,延续则有加分 并发语言(Erlang, Oz) 逻辑语言(Prolog)
专业平台经验 1 2-3 4-5 6+
专业经验年龄 1 2-5 6-9 10+
领域知识 没有该领域的知识 在该领域中曾经至少为一个 产品工作过 在同一领域中为多个产品工作过 领域专家。在该领域设计和实现数种产品/方案。精通该领域使用的标准条款 和协议
学识 Knowledge
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
工具知识 仅限于主要的IDE(VS.Net, Eclipse等) 知 道一些流行和标准工具的备选方案 对编辑器、调试器、IDE、开源的备选方案有很好的了解。比如某人了解大多数Scott Hanselman的威力工具列表中的工具,使用过ORM工具。 实际地编写过工具和脚本,如果这些被发布则有加分
语言接触 命令式语言和面向对象语言 命令式语言、面向对象 语言和说明型语言(SQL),如果了解静态类型vs动态类型、弱类型vs强类型则有加分 函数式语言,如果了解延缓求值、局部套用函 数、continuations (源于scheme中的一种高级控制结构)则有加分 并发语言(Erlang, Oz) 逻辑语言(Prolog)
代码库知识 从来没有查询过代码库 基本的代码层知识,了 解如果构建系统 良好的代码库工作知识,实现过几次bug修复或者完成了一些细小的特性 实现了代码库中多个大型特 性,能够轻松地将多数特性的需求变更具体化,从容地处理bug修复。
下一代技术知识 从来没听说过即将到来的技术 听说过某领 域即将到来的技术 下载过alpha preview/CTP/beta版本,并且读过一些文章和手册 试用过预览 版而且实际地构建过某物,如果共享给其他人的话则有加分
  2n (Level 0) n2 (Level 1) n (Level 2) log(n) (Level 3) Comments
平台内部 对平台内部毫无所知 有平台基本的内部工作的 知识 深度的平台内部知识,能够设想平台如何将程序转换成可执行代码。 编写过增强平台或者为其平台内部提供信息的 工具。比如,反汇编工具,反编译工具,调试工具等。
书籍 菜鸟系列,21天系列,24小时系列,蠢货系列... 《代 码大全》,《别让我思考》, 《精通正则表达式》 《设计模式》,《人件》,《代码珠玑》,《算法设计手册》,《程序员修炼之道》, 《人月神话》 《计算机程序设计与解释》,《事务处理:概念与技术》,《计算机程序设计模型》,《计算机程序设计艺术》,《数据库系统 导论》 C.J Date版,《Thinking Forth》 ,《Little Schemer》(没找到其中译本)
博客 听过但是从来抽不出空去接触 阅读一些科技/编程 /软件工程的博客,并且经常的收听一些播客 维护一些博客的链接,收集博主分享的有用的文章和工具 维护一个在编程方 面,分享有个人见解和思考的博客
Creative Commons License
程序员能力矩阵 by XGuru is licensed under a Creative Commons 署名-非商业性使用-相同方式共享 2.5 中国大陆 License. 原文请看 这 里
Thanks to bearice for debugging.
Thanks to John Haugeland for a reformatting of it that works much more nicely on the web.

posted @ 2010-03-14 23:35 深夜两点 阅读(232) | 评论 (0)编辑 收藏

(转自http://coolshell.cn/?p=1903

问答

Q:你是怎么区分一个内向的程序员和一个外向的程序员的?
A:外向的程序员会看着你的鞋和你说话时。

Q:为什么程序员不能区分万圣节和圣诞节?
A:这是因为Oct 31 == Dec 25!(八进制的31==十进制的25)

刹车失灵

有一个物理学家,工程师和一个程序员驾驶着一辆汽车行驶在阿尔卑斯山脉上,在下山的时候,忽然,汽车的刹车失灵了,汽车无法控制地向下冲去,眼看前 面就是一个悬崖峭壁,但是很幸运的是在这个悬崖的前面有一些小树让他们的汽车停了下来,而没有掉下山去。三个惊魂未定地从车里爬了出来。

物理学家说,“我觉得我们应该建立一个模型来模拟在下车过程中刹车片在高温情况下失灵的情形”。

工程师说,“我在车的后备厢来有个扳手,要不我们把车拆开看看到底是什么原因”。

程序员说,“为什么我们不再找相同的车再来一次以重现这个问题呢?”

关于编程语言

如果C++是一把锤子的话,那么编程就会变成大手指头。

如果你找了一百万只猴子来敲打一百万个键盘,那么会有一只猴子会敲出一段Java程序,而其余的只会敲出Perl程序。

一阵急促的敲门声,“谁啊!”,过了5分钟,门外传来“Java”。

如果说Java很不错是因为它可以运行在所有的操作系统上,那么就可以说肛交很不错,因为其可以使用于所有的性别上。

自行车

一个程序员骑着一个很漂亮的自行车到了公司,另一个程序员看到了他,问到,“你是从哪搞到的这么漂亮的车的?”

骑车的那个程序员说,“我刚从那边过来,有一个漂亮的姑娘骑着这个车过来,并停在我跟前,把衣服全脱了,然后对我说,‘你想要什么都可以’”。

另一个程序员马上说到,“你绝对做了一个正确的选择,因为那姑娘的衣服你并不一定穿得了”。

火车

一个年轻的程序员和一个项目经理登上了一列在山里行驶的火车,他们发现列车上几乎都坐满了,只有两个在一起的空位,这个空位的对面是一个老奶奶和一 个年轻漂亮的姑娘。两个上前坐了下来。程序员和那个姑娘他们比较暧昧地相互看对方。这时,火车进入山洞,车厢里一片漆黑。此时,只听见一个亲嘴的声音,随 后就听到一个响亮的巴掌声。很快火车出了山洞,他们四个人都不说话。

那个老奶奶在喃喃道,“这个年轻小伙怎么这么无礼,不过我很高兴我的孙女扇了一个巴掌”。

项目经理在想,“没想到这个程序员居然这么大胆,敢去亲那姑娘,只可惜那姑娘打错了人,居然给打了我。”

漂亮的姑娘想,“他亲了我真好,希望我的祖母没有打疼他”。

程序员坐在那里露出了笑容,“生活真好啊。这一辈子能有几次机会可以在亲一个美女的同时打项目经理一巴掌啊”

问路

有一个驾驶热气球的人发现他迷路了。他降低了飞行的高度,并认出了地面上的一个人。他继续下降高度并对着那个人大叫,“打扰一下,你能告诉我我在哪吗?”

下面那个人说:“是的。你在热气球里啊,盘旋在30英尺的空中”。

热气球上的人说:“你一定是在IT部门做技术工作”。

“没错”,地面上的人说到,“你是怎么知道的?”

“呵呵”,热气球上的人说,“你告诉我的每件事在技术上都是对的,但对都没有用”。

地面上的人说,“你一定是管理层的人”。

“没错”,热气球上的人说,“可是你是怎么知道的?”

“呵呵”,地面上的那人说到,“你不知道你在哪里,你也不知道你要去哪,你总希望我能帮你。你现在和我们刚见面时还在原来那个地方,但现在却是我错了”。

警告

有一个小伙子在一个办公大楼的门口抽着烟,一个妇女路过他身边,并对他说,“你知道不知道这个东西会危害你的健康?我是说,你有没有注意到香烟盒上的那个警告(Warning)?”

小伙子说,“没事儿,我是一个程序员”。

那妇女说,“这又怎样?”

程序员说,“我们从来不关心Warning,只关心Error”

posted @ 2009-12-07 10:24 深夜两点 阅读(305) | 评论 (0)编辑 收藏

(http://www.yeeyan.com/articles/view/115732/71484)

阅读软件开发相关书籍,是程序员在技能和职业上为自己投资的好办法。但是,需要阅读那些书?应该按照什么顺序来进行?这份书单适合那些刚刚开始,一心想要提高自己的编程能力,想要以程序员为职业的人。

我之前曾说,阅读软件开发有关的书籍,是在你技能和事业上投资的好办法。 但是哪些应该阅读呢?而且该按照什么顺序阅读呢? 我已经编制了一份书单,我认为它能真正大幅提高你的能力。 我已经安排好它们的顺序,分为3个阶段,我相信这种顺序是最有成效的。这份书单主要是为那些刚刚起步的开发人员编写的,当然专业的开发者也可参照,它对周围那些想获得提高的人来说都是相当有用的。

首先,你应该关注的是提高书写干净,毫不含糊的,可维护代码的能力。 下列书籍应该大大有助于您:

  1. 测试驱动开发(肯特·贝克)
  2. 重构(马丁·福勒)
  3. 实现模式(肯特·贝克)
  4. 代码大全:第二版(史蒂夫·麦康奈尔)
  5. Working Effectively With Legacy CodeMichael Feathers
  6. Clean Code (Robert C. Martin)

上述的读书顺序可能使有些人感到惊讶,但我敢打赌,这是最有效的阅读顺序。

当你学会了如何书写伟大的代码,你应该开始以简洁的设计和架构为重点。 这并不是说,你应该只集中于设计和架构,但你越了解它,你会变得越好:

  1. 设计模式(Gang Of Four 
  2. 企业应用架构模式(马丁·福勒)
  3. 领域驱动设计(埃里克·埃文斯)
  4. 企业集成模式(格里高·Hohpe,鲍比·沃尔夫)
  5. Release It! Design and deploy production-ready software(Michael T. Nygard)
  6. 97 Things Every Software Architect Should Know (edited by Richard Monson-Haefel)

这一阶段可能值得说明的是在这部分列出的一些图书中可能是有点'争议'的。 如果您已经阅读了第一阶段的书籍,那么你应该有能力用你自身的观点看待第二阶段的这些书籍。 你会了解到,你不应该仅仅仿照那些模式,但了解它们的存在肯定是一件好事。

最后,您需要了解如何在团队环境下工作并理解团队的动力。 下面的书籍不是具体介绍团队中的工作,但包含了众多的智慧和洞察力,这一定会帮助您在专业的团队环境中工作:

  1. 极限编程,第二版(肯特·贝克)
  2. The Art Of Agile Development (James Shore & Shane Warden)
  3. 人月神话,20周年纪念版(弗雷德里克·布鲁克斯)

这本书可能也需要一点说明。 我并不是说你应该做极限编程。 但你了解它肯定不会有害处,至少你应该在你认为有意义的时候去尝试采用这种做法。 你并不会真的需要去采用所有的做法(虽然你这样做会获得额外的好处,或者至少假装这样做),但它们中的一些,每个人都应该至少了解一下。

所以就是这样了...尝试用上述方式阅读这些书,不要忘了以后感谢我 

A Reading Guide To Becoming A Better Developer

I’ve stated previously that reading software development books is a good way of investing in your skills and your career. But which ones should you read? And in what order should they be read? I’ve compiled a list of books that i think can truly increase your skills substantially. I’ve put them in the order in which i believe they will have the most effect, and grouped them in 3 ’stages’. I primarily have young developers who are just getting started as professional developers in mind with this list, but it should be just as useful to developers who’ve been around for a while and simply want to improve.

The first thing that you should focus on is improving your ability to write clean, unambiguous, maintainable code. The following books should greatly help you with that:

  1. Test-Driven Development (Kent Beck)
  2. Refactoring (Martin Fowler)
  3. Implementation Patterns (Kent Beck)
  4. Code Complete: 2nd Edition (Steve McConnell)
  5. Working Effectively With Legacy Code (Michael Feathers)
  6. Clean Code (Robert C. Martin)

The order of this stage might surprise some people, but i’m willing to bet that this is the most efficient order to reading those books.

After you’ve learned how to write great code, you should really start focusing on clean design and architecture. That’s not to say that you should focus solely on design and architecture, but the more you know about it, the better off you will be:

  1. Design Patterns (Gang Of Four)
  2. Patterns Of Enterprise Application Architecture (Martin Fowler)
  3. Domain-Driven Design (Eric Evans)
  4. Enterprise Integration Patterns (Gregor Hohpe, Bobby Woolf)
  5. Release It! Design and deploy production-ready software (Michael T. Nygard)
  6. 97 Things Every Software Architect Should Know (edited by Richard Monson-Haefel)

This stage probably deserves a bit of clarification as some of the books listed in this part might be somewhat ‘controversial’. If you read and learned from the books in the first stage, then you should be capable of putting everything you read in the second stage in perspective. You will have learned that you shouldn’t just apply as many patterns as possible, but it’s certainly a good thing to know about their existence.

Finally, you need to learn about working in a team environment and understanding team dynamics. The following books aren’t about working in teams specifically, but contain a tremendous amount of wisdom and insight that will definitely help you when it comes to working in a professional team environment:

  1. Extreme Programming Explained, Second Edition (Kent Beck)
  2. The Art Of Agile Development (James Shore & Shane Warden)
  3. The Mythical Man-Month, 20th Anniversary Edition (Frederick P. Brooks)

This one probably needs a bit of clarification as well. I’m not saying that you should do Extreme Programming. But it certainly won’t hurt you to learn about it, and at least try to apply the practices that you believe in when it makes sense to do so. You don’t really need to apply them all (though you will get bonus points from the cool kids if you do so, or at least pretend to), but there are a few of them that everyone really should do regardless of which agile variant you subscribe to.

So there you have it… try those books out in that order, and don’t forget to thank me later



posted @ 2009-12-05 21:48 深夜两点 阅读(267) | 评论 (0)编辑 收藏

(上一篇:计算机中的加密和认证http://www.blogjava.net/deepnighttwo/archive/2009/12/03 /304631.html
A公司开发了一个软件,打成了一个jar包,然后发布出去liao。作为一个用户,如何来确认这个jar包确实是A公司发布的哪个?而且,如何确定这个jar包没有被别有用心的一小撮篡改过?这就需要Java中的签名来保证。

Java中的可执行代码就是class文件。直接使用class文件是很naive的。通常的做法是是对一个jar包中的所有class文件进行签名。过程可以分为如下步骤。
  1. 首先使用JDK自带的keytool工具生成一个keystore,命令如下: keytool -genkey -keystore keystore文件 -alias 别名。回车后还有一些信息需要填写。keystore里面包含了很多信息,包括公钥和私钥信息。当然可以使用keytool命令从keystore文件里面导出公钥和私钥。keytool命令还有很多参数,比如你可以指定使用的摘要算法等。(具体用法可以Google之)。
  2. 然后,第二步当然是找个CA给公钥签名。自娱自乐的用途就可以不用这一步了。
  3. 第三步是给jar包签名。JDK中提供了给jar包签名的工具,叫做jarsinger。命令各式如下:jarsigner -keystore keystore文件 jar文件 别名(就是生成keystore时用的那个别名)。回车后要输入密码,也跟生成keystore时候的密码一样就行了。
好,到这里就算签名结束了。命令执行完毕后,jar包会陡然多出几k来。这几k就是签名的内容。


Java(或者说是Java Runtime)是支持签名和认证的。也就是说一个jar包一旦被签名了,Java Runtime会对这个jar包进行验证。下面是验证签名的过程。
首先需要知道签名后jar包里面多出了什么。签名并不会改变jar包中已经有的内容,而是添加了一个.DSA(说明使用的是DSA算法)文件和一个.SF(signed file)文件,然后在.MF文件里面增加一些内容。验证的过程是这样的(我猜的。。。觉得不对可以去http://java.sun.com/javase/6/docs/technotes/guides/jar /jar.html,Sun公司的jar包规范,自己看自己猜),首先是DSA文件,它里面存储了公钥内容和对SF文件摘要的加密内容,所以,首先验证公钥(跟https里面的那个验证是一样的过程),验证完毕证书后,用公钥解密加密的内容,然后得到SF文件的摘要值,把这个值和实际 SF文件的摘要值比较,这样就可以保证SF文件没问题了。SF文件里面的内容包含了很多条目的签名值。首先是对MF文件的签名值,这就是验证MF文件了。而MF文件里面对每个class文件都有一段描述的内容,比如:
Name: common/class2.class

MD5-Digest: (base64 representation of MD5 digest)

SHA-Digest: (base64 representation of SHA digest
它代表这个class文件对应摘要算法的摘要值。这个条目在SF里面有一个对应的条目:
Name: common/class2.class
MD5-Digest: (base64 representation of MD5 digest)


注意,SF文件中的这个摘要值不是class文件的,而是MF文件里面对应条目的。也就是说,SF里面的签名值统统是用来验证MF文件或者MF文件中的条目的,而MF文件中的摘要值才是用来验证class文件的。真绕。。。

总之,最后一层层的验证后,整个jar包中的内容都被验证了。过程:CA的证书->自己的公钥->SF文件签名 ->MF文件签名和MF文件每个条目的签名->jar包中的每个文件(当然主要是clas文件。别的文件应该也会被验证的,至少properties文件会被签名认证)

验证完了之后,就可以保证jar包确实出自某公司之手,也确实没有被别有用心的一小撮人篡改过。如果你信任某公司,那就可以用这个jar包了。

同样,如果一个applet的jar包是签名了的,而且在启动applet的时候用户选择信任这个签名,那么这个applet就拥有了访问本机资源的权限,如果选择不信任,那么applet就不会被启动。如果一个applet没有被签名,那么applet可以启动,但是不会被允许访问本机资源(文件等)。

如果一个证书没有被CA的证书认证,比如说,对于我写的这个applet,它就是用我自己搞出来的没认证过的证书签了名的:http://appletfarm.appspot.com/juliaappletsigned.html
这时候Java会提示说:

“该应用程序的数字签名无法验证”,因为我没给过VeriSign年费。如果证书是验证过的,对话框就会是询问你是否信任“某公司”,这个意思就是说,此jar包确实是“某公司”搞出来的,信任那个公司就可以运行它了。

posted @ 2009-12-03 23:17 深夜两点 阅读(1108) | 评论 (0)编辑 收藏

大学时候学网络安全,不知道是老师太脱离实际,还是当时我上课睡太多了,反正学了个糊里糊涂。上机实验比着葫芦画瓢在JBoss上搞了个EJBCA的什么东西,就觉得已经混过去了。不过该学的还是得学,躲不过。现在开始还大学睡觉的债。。。。前段时间看了一阵子的Java安全编程,回过头来总结总结。

首先是跟Java没关系的,是加密和认证。加密的算法可以分为三类:
  • 摘要算法(指纹算法,哈希算法等):摘要算法其实不算加密。算法以数据为输入,生成一串等长的输出。这个输出就是这段输入的指纹,或者说是摘要。算法不管输入有多长,1G或者一个byte,输出都是一样长的。指纹算法比较形象。我们可以认为,只要数据不同,生成的摘要就是不同的(或者说,想根据一个摘要来生成特定的数据是很难的,所以这个摘要可以唯一的确定数据的身份)。当然是无法从这个简短的摘要还原原始数据的。比较常用的摘要算法有MD5,SHA-1,DSA之类的。摘要算法是公开的,任何人都可以通过摘要算法来计算一段数据的摘要。所以,如果一个文件传输给你,同时也给你一个这个文件的MD5摘要,那么你收到文件后,计算一下文件的MD5,然后和别人给你的MD5摘要比较一下,就知道文件在到你手上之前是不是被人改动过了。
  • 对称加密算法:对称加密算法是使用相同密钥加密和解密数据的一种加密算法。密钥可以认为就是一段数据。使用相同的密钥这点很重要。对称加密算法很多,加密解密也很快。最入门的对称加密算法就使凯撒密码。工业中使用的加密算法很多,比如用于流加密的RC4,还有AES,DES等。只有有密钥,那么就可以对加密后的数据进行解密,得到原始的数据。从这里可以看出,密钥是对称加密的关键,如果密钥的传输无法保证安全,对称加密就是形同虚设的。
  • 非对称加密算法:非对称加密算法是计算机加密和认证中最关键的一环。非对称加密的特点是,它有俩密钥,用密钥1加密的数据需要使用密钥2解密,同样,用密钥2加密的数据需要用密钥1解密。如果公开密钥1,那么密钥1就成为公钥,即公开的密钥,同时,密钥2就使私钥,必须好好保存不能让别人得到。非对称加密算法有数学证明来保证它几乎不可能在一个有意义的时间段内被破解。但是非对称加密也有致命的弱点——加密解密计算量大,不适合用来处理大量的数据。非对称加密算法有RSA,DSA等。
计算机加密体系需要保证——保密性、完整性、认证性和不可抵赖性。保密性就是说,数据是使用加密算法加密过的(一般是使用对称加密算法加密)。完整性可以用摘要算法保证,因为一段数据一旦被人改动过了,那么摘要就肯定不同了。但是,这两者如果没有非对称加密算法保护,一切就都是空谈。因为,密钥总归要通过 internet传输的,如果被人窃取了咋办?摘要?大不了黑客篡改了数据之后,生成一个新的摘要。好,非对称加密上场了,认证性和不可抵赖性这两点也是非对称加密来保证的。它如何来保证前面这些呢?

先看看什么是证书。有了这些算法之后,就有了证书这个概念。啥叫做证书呢?证书其实就是一个文件。文件内容挺多,需要关心的有:
  • 非对称加密的公钥。它可以用来解密那个秘密的私钥加密过的数据。
  • 用别的私钥加密过的非对称加密的公钥的签名。上面说的非对称加密的公钥也是一段数据呀,用摘要算法计算一下它的摘要。然后用别的私钥加密一下这个摘要。注意,这里说的是用别的私钥加密。
  • 所谓的别的私钥的标识。有了这个标识,才知道是谁加密了公钥的签名。
问题越来越多了。什么叫做别的私钥?哪儿来的私钥?对于一个有效的证书来说,这里说的别的私钥,就是那些专门来提供证书加密服务的公司(比如 VeriSign)的私钥。这些公司会全副武装的保护好自己的私钥(公司的命根子呀)。下面来叙述一下这个过程:
  1. 首先,A公司想要一个证书,用来在internet上证明自己确确实实是A公司。于是公司通过工具生成了一对密钥(这个很简单,谁都可以轻松的生成一对密钥)。
  2. 然后他拿着公钥去找VeriSign,计算了公钥的MD5值,请求VeriSign拿出自己的宝贝私钥,来对这个公钥的MD5值进行加密。
  3. VeriSign很专业,他们会要求A公司出具相应的证明,核实无误后,VeriSign此才会拿出私钥,把A公司公钥的MD5值进行加密。这个就叫做签发证书。
  4. 这不是一锤子买卖,A公司为了这个事儿,须要按年给VeriSign付钱。
  5. 好,A公司的公钥的MD5值被VeriSign的私钥加密过了,得到了一段加密后的数据,只有VeriSign的公钥才能解密这段数据,得出正确的值。
  6. A公司屁颠屁颠的可以生成自己的证书了,证书的内容包括:
  • A公司的公钥。
  • VeriSign的私钥对A公司的公钥的MD5值加密后,所得到的数据。再次提醒一下,这个密钥只有VeriSign的公钥才能解密。
  • 一段文字,说明证书是VeriSign验证的,公钥的指纹算法是MD5。这段文字不用加密,谁爱看谁看。
终于A公司有了自己的证书,但是,VeriSign的私钥加密过的东西,须要使用VeriSign的公钥来解密,咋办?不用急,VeriSign这种提供证书服务的公司早就和各种操作系统提供商协商好了,他们的公钥早就一经包含在了每一个操作系统中,在我们安装操作系统的时候,VeriSign这些公司的公钥就已经包含在计算机里了。

下面以https来解释一下计算机中的安全体系(保密性、完整性、认证性和不可抵赖性)是如何工作的。
A公司有了一个站点,浏览器使用https来访问这个站点的时候,大概的过程就是这样的(下面的过程基本是Https协议的运作过程):
  1. A公司站点首先给客户端发送自己的宝贝证书。(数据传输的时候被人从中间截获了?不怕,想听就听吧)
  2. 认证性:客户端得到证书之后,开始验证这个证书:
    • 首先,客户端从证书中知道,这个证书是被VeriSign公司签发的。所以客户端从操作系统中拿出来VeriSign公司的公钥,待用。
    • 客户端还知道,A公司公钥是使用MD5算法计算的签名,OK,客户端读取出来证书中A公司的公钥,使用MD5值,待用。
    • 下面是重要的一步了,客户端从A公司的证书中抽取出那段加密后的数据(也就是A公司公钥的MD5值VeriSign公司的私钥加密过的那段数据),然后再拿过来第一步中找到的VeriSign公司的公钥,非对称加密的特点就是私钥加密,公钥解密之。所以,当当当当当,解密之,得到的值就应该是A公司的公钥的MD5值。< /li>
    • 那到底是不是呢?跟第二步中客户端自己计算出来的MD5值比对一下就知道了。
    • 如果通过比较,发现确实是,那么安全体系中的认证性就得到保证了,也就是说,客户端可以完全相信对方就是A公司,访问的站点也就是A公司的站点。(等等,A公司的公钥不是公开的吗?那岂不是任何站点都可以伪装成A公司?不急,这不是个事儿,在下面不可抵赖性会说到)当然,如果验证不通过,说明对方是个“李鬼”。浏览器会有提示,说这个站点提供的证书没有通过验证思密达(还有一种情况就是,证书过期了,还记得前面说的每年给VeriSign的年费吗)。
  3. 好,客户端验证通过了,下面就是开始传输数据了。传输数据的过程有保密性、完整性和不可抵赖性三点需要保证。
  4. 首先,客户端浏览器悄悄地生成一个随机数。然后使用A公司的公钥加密这个随机数,发送给A公司的站点。因为是A公司公钥加密的,所以不怕被人窃听。为啥不怕被窃听,因为窃听了也没用,因为窃听者肯定没有A公司的私钥,没有私钥也就没法对窃听到的数据解密。
  5. A公司站点收到这个数据后,开始使用自己的私钥解密数据。到了这个时候,肯定是只有客户端和A公司的站点服务器知道这个随机数的。
  6. 接下来,客户端浏览器和A公司站点根据相同的算法,生成对称加密使用的密钥(实际上是一组密钥,当然在这里不用深究这个)。以后的数据传输就全使用这个对称加密密钥进行了。这就是保密性
  7. 保密性得到了保证,完整性如何保证呢?如果攻击者虽然不能够获得数据,但是他想捣蛋,偷偷篡改数据来破坏数据的完整性。这个时候也没啥问题,在https 协议中,每条消息在加密之前都包含了消息内容和消息的hash值(比如,消息的MD5值),这样在消息的接收端,就可以对这条消息进行验证了。通过验证就可以知道消息是不是被篡改过。当然,如果被篡改过,也使没办法回复的,不过知道消息被篡改过,那么就可以要求对方重新发送消息了,总之攻击者是没法办得逞的。这就是消息的完整性
  8. 好的,在这里我们来看一下不可抵赖性。因为只有A公司有私钥,这也就是说,只有A公司可以把这个数据成功解密,来得到这个随机数,从而来计算对称加密使用的密钥。所以,如果A公司想抵赖说那个站点不是自己,是不可能的事情。因为只有A公司有这个用于解密的私钥,不是A公司是谁。同样,就好像在前面说的,如果有人用A公司的公钥冒充A公司,那么这个李鬼其实没有A公司的公钥,也就没有办法解密数据(注意,客户端产生的随机数是使用A公司的公钥加密的,须要使用A公司的私钥解密),所以这个是徒劳的。
好,保密性、完整性、认证性和不可抵赖性都在上面的过程中都得到保证了。这个过程的核心就是非对称加密的特性:公钥加密私钥解密,私钥加密公钥解密。本篇到此结束,下一篇中将涉及Java中的认证和加密。

关于https的具体内容可以参考这篇文章:http://www.infoq.com/cn/articles/HTTPS-Connection-Jeff-Moser





posted @ 2009-12-03 17:55 深夜两点 阅读(778) | 评论 (0)编辑 收藏

(转自http://weblogs.java.net/blog/2007/09/27/why-i-dont-use-swing-hacks-production-code)

Why I don't use Swing hacks (in production code)

Posted by alexfromsun on September 27, 2007 at 7:03 AM PDT

One of the big part of my work is fixing bugs in Swing but not all of them are to be fixed, some of them are closed because they describe the situations when someone uses Swing in undocumented way or trying to make Swing do something which it doesn't support.

My favourite example is so-called "Blocking GlassPane". If you file a bug with a description that you implemented a GlassPane to block your frame and it doesn't work, most likely it will immediately be closed as "not a bug". The reason is simple - glassPane is an internal feature of Swing and the library may use wherever it is necessary, for example currently we make it visible during resizing of internal frames to show a correct mouse cursor above any existing components.

Swing does it well if you just paint something on a GlassPane but when your GlassPane affects the processing of events it becomes what I call a "hack". There are many definitions what a "hack" is, either positive or negative, but I want to give a definition what I mean by this word


Hack is an approach when you use something in an unexpected way

Hacks don't have to be alway good or bad. Some of them are creative and effective, some of them are just creative, but they are always different from recommended or well-known solutions.

Going back to Swing I want to mention the main feature of a code which uses hacks:


If you use recommended techniques and something doesn't work as it should 
Swing team is to be blame.

If you use a hack and something doesn't work - it is you to be blame.

Hacks usually work well for a presentation or a blog entry, but very few of them work as good and stable as the core library code. When you think it is good enough, someone else finds a problem whith your code and when you fix it, another issue appears so when you fix the "last" problem you know enough to write another valid test case which will be broken with your code.

Even if you are pretty sure that your hack works well on your computer, there usually no guarantee that it doesn't fail for another OS or with some custom components which use similar hack.

The "Blocking GlassPane" is an interesting example because it is a well-known hack which has never worked well. It is easy to put a fancy animation to a GlassPane and add an empty MouseListener to block the MouseEvents but people tend to forget about KeyBoard events and it is usually possible to type something in a TextField under a Blocking GlassPane.

I already blogged about this issue and offered some solutions to make this hack more robust however a month ago I got a message from one of my readers, he told me that my improved Blocking Glasspane fails to block the menu accelerators, so if you use Alt+MenuShortCut the menu will appear.

Problems like that is a usual thing when you use hacks. The most straightforward fix for this particular problem would be to disable frame's JMenuBar before showing GlassPane and enabling it again when the GlassPane is gone, but don't ask me how give user a chance to interrupt the time-consuming operation which blocks his frame or how to ignore keyboards actions for other components.


Modal dialog is the only recommended solution to block a top level frame

During my work on JXTransformer I used any kind of hacks to make transformed components work as well as usual ones. I managed to make it work for unsigned applet however I used some fishy techniques which I can hardly recommend. And again I realized that it might work for the most usual cases but there will always be some cases when transformed components behave incorrectly and the only right fix is to change the Swing itself to support AffineTransform for JComponents.

After that I added a special note that JXTransformer has several known limitations and decided that my next project will use only recommended techniques which always work well.

That's the reason why I don't use any hacks in JXLayer component. When I started this project it was tempting to add some creative hacks to implement some unique features but I keep following the "no hacks rule" because I don't want to be blame if JXLayer wouldn't work for your project.

When hacks are welcome

If you think that I don't use hacks at all, it's not true. There are some situations where hacks (even the dirty ones) are welcome, I am talking about testing and debugging. Let's say you need to find a cause of a bug, and in this case all means which may help are good (until they are not a part of production code).

On SwingHelper project you can find a CheckThreadViolationRepaintManager which helps finding a Event Dispatch Thread violation in Swing applications as well asEventDispatchThreadHangMonitor to catch time-consuming tasks on Event Dispatch Thread. 
I would hardly use custom RepaintManager or EventQueue for my components, but they work very well when it comes to debugging.

Testing is a similar story, when I have a choice between a manual regression test with no hacks and automated one with hacks, I always choose the last one, just because manual tests don't have much sense

Conclusion

I am a realist and I know that unfortunately it is almost impossible to make a big project without any hacks. The only recommendation I can give for this matter is do not use hacks just because you know them, try to follow the documented patterns as often as possible and you code will be more reliable

To be continued...



posted @ 2009-12-03 14:35 深夜两点 阅读(268) | 评论 (0)编辑 收藏