paulwong

#

什么是高内聚、低耦合?

起因:模块独立性指每个模块只完成系统要求的独立子功能,并且与其他模块的联系最少且接口简单,两个定性的度量标准――耦合性和内聚性。

耦合性也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,

模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。

耦合性分类(低――高): 无直接耦合;数据耦合;标记耦合;控制耦合;公共耦合;内容耦合;
1 无直接耦合:
2 数据耦合: 指两个模块之间有调用关系,传递的是简单的数据值,相当于高级语言的值传递;
3 标记耦合: 指两个模块之间传递的是数据结构,如高级语言中的数组名、记录名、文件名等这些名字即标记,其实传递的是这个数据结构的地址;
4 控制耦合: 指一个模块调用另一个模块时,传递的是控制变量(如开关、标志等),被调模块通过该控制变量的值有选择地执行块内某一功能;
5 公共耦合: 指通过一个公共数据环境相互作用的那些模块间的耦合。公共耦合的复杂程序随耦合模块的个数增加而增加。
6 内容耦合: 这是最高程度的耦合,也是最差的耦合。当一个模块直接使用另一个模块的内部数据,或通过非正常入口而转入另一个模块内部。

内聚性又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。

内聚性匪类(低――高): 偶然内聚;逻辑内聚;时间内聚;通信内聚;顺序内聚;功能内聚;
1 偶然内聚: 指一个模块内的各处理元素之间没有任何联系。
2 逻辑内聚: 指模块内执行几个逻辑上相似的功能,通过参数确定该模块完成哪一个功能。
3 时间内聚: 把需要同时执行的动作组合在一起形成的模块为时间内聚模块。
4 通信内聚: 指模块内所有处理元素都在同一个数据结构上操作(有时称之为信息内聚),或者指各处理使用相同的输入数据或者产生相同的输出数据。
5 顺序内聚: 指一个模块中各个处理元素都密切相关于同一功能且必须顺序执行,前一功能元素输出就是下一功能元素的输入。
6 功能内聚: 这是最强的内聚,指模块内所有元素共同完成一个功能,缺一不可。与其他模块的耦合是最弱的。

耦合性与内聚性是模块独立性的两个定性标准,将软件系统划分模块时,尽量做到高内聚低耦合,提高模块的独立性,为设计高质量的软件结构奠定基础。

有个例子很容易明白:一个程序有50个函数,这个程序执行得非常好;然而一旦你修改其中一个函数,其他49个函数都需要做修改,这就是高耦合的后果。
一旦你理解了它,你编写概要设计的时候设计类或者模块自然会考虑到“高内聚,低耦合”。

posted @ 2012-04-16 22:37 paulwong 阅读(348) | 评论 (0)编辑 收藏

员工为什么离开

导读:如今,很多优秀员工不顾企业的挽留,翩然而去;潜力员工不顾企业的期待,悄然远去;甚至重点培养的员工,也不顾企业的重托,撒手而去,留给领导者无尽的懊恼和叹息。让领导者百思不得其解的是,似乎总是该走的没有走,不该走的却走了;平凡的没有走,优秀的却走了。于是,也总能听到领导者一遍又一遍无奈的歌谣:我拿什么来留住你?我的员工!

  咱们先从一个故事开始说起:

  楚国有个好吃懒做的人,他整天想着怎样不出力气,或者少出点儿力就可以拣到大便宜的窍门。他想,养蜜蜂的人能得到蜂蜜,养鱼鹰的人能得到鱼,我为什么不养些猴子呢?猴子会采果子呵!

  于是,他买了一群猴子,把它们关在一所空房子里,又买了很多装果子用的篓子,教猴子扛篓子。他手拿皮鞭,严加训练。然后又买了许多果子教猴子装篓子,哪个猴子毛手毛脚地吃上一口果子,或者把果子碰伤了,他便举起皮鞭,乱抽一顿。没多久,便把猴子整治得服服帖帖,说一不二了。这时,他才把猴子放到山里,去给他采果子。

  不错,猴子们挺驯服,每天早出晚归,背驮肩扛地给他采来各种各样的鲜果。他只要把这些鲜果拿到集市上卖出去就行了。从此他的日子过得宽宽松松,逍遥自在。

  这个不劳而获的人很苛刻,他每天早上把猴子赶上山去采果子,不管采下多少果子,每只猴子只发给一个。猴子们劳累一天,一个果子怎么能吃饱肚子呢?

  猴子们对主人的苛刻虐待很反感,但谁也不敢吭声,因为它们很知道皮鞭的味道。

  这天,猴子们照常上山去采果子,虽然肚子空空的,但受过训练,采下果子来,只往篓子里装,不敢往嘴里放。他们饿极了,主人又不在面前,有一个大胆点儿的,便吃起果子来,其它的猴子看见了,都一直咽口水。后来,实在耐不住了,也学着它的样子吃起来了。

  一个野生老猴子看见它们这般模样,不禁大笑起来:“猴儿们,这都是野生野长的果子,放心大胆地吃吧,看你们被人整治得没点儿猴性了,吃吧,吃吧。”

  猴子们互相看看,也七嘴八舌地吱哇起来:“这果子不是主人的,谁都可以采,谁都可以吃。”“主人懒得上山来,他又看不见,咱们放开肚子吃呗。”

  它们边吃边议论:“敢情在这山上采果子的权利,不单是只有主人才有呀!”“我原来还以为是主人养活咱们呢,现在才弄明白是咱们养活他呀!”“山是大自然的山,谁都可以上山来,果是野生的果,谁都可以摘,他懒得劳动,鞭打咱们给他干活,咱们何必受他那样折磨呢?”“可不是吗?我们是自找苦吃!”

  猴子们长时间挨饿,吃饱后一个个东倒西歪地睡着了。一觉醒来,太阳已快落山了,篓子里还没有装满呢。

  一个小猴子说:“今天回去,保准得吃皮鞭,哼!就是吃皮鞭,我也不给他干活了,我要和他讲理!”另一个小猴子说:“主人从来不讲理,咱们要不给他干活,他会把咱们再卖掉!”大伙抓耳挠腮,扑闪着眼睛,一时不晓得该怎样是好。

  还是老一点的猴子精灵,它说:“干吗要回去呢?这大山没有头,森林没有边,到哪里没有我们吃的果子?生活的路子就在我们脚下,我们应该当机立断,立刻离开这里!”那个野生的老猴儿又插话了:“这就对了,走,一块走哇!”

  大伙儿一个个扔掉手里的篓子,欢跳着,嘻笑着,钻进那无边无际的山林里去了。

  那个主人到了晚上,左等右等不见猴子们回来,到山上一看,除了横躺竖倒的篓子以外,一个猴儿也不见了。

  他气坏了,但仍旧好吃懒做。后来,他终于饿死在自己的床上了。

  点睛:

  现在不少领导者普遍反映人难管,最根本的原因是“领导者与员工的关系”没有摆正关系造成的。究竟员工在领导者心里,是一种达成目的的工具,还是具有个人特色的个体?过去的员工毫无条件地信任公司,将他的一生奉献给公司,唯一微薄的希望,就是当公司赚钱时,能够分一些给员工。可是这家公司遇到困难时,毫不犹豫就抛弃这些员工,有些更恶劣的居然不是先告知,早上员工上班时才通知“今天是最后一天”!现在的员工总算让还活在机器时代的公司吃到苦头,员工不再是呼之即来挥之即去的零件,使用一大堆的命令和规章,即使能约束员工上班时间,一到下班时间,员工很自然的收好文件离开,员工没有必要对企业忠诚,因为企业先不尊重员工,员工只好自己先尊重自己,只顾自己不顾公司了。

  我们许多领导者在分配给下属工作时,把下属当一台机器一样看待。只告诉下属要做什么,其余的什么都不说,导致下属不知工作份量的轻重,结果不知自己到底做得怎么样,根本谈不上有任何成就感。因此对工作也失去了干劲。

  员工不是成本,而是公司的资本,是公司的核心资源。员工是活生生的人,不是机器,应该受到尊重。不能用按钮随意控制。毫无疑问,人是会受外界刺激影响的,但绝对是不可以控制的。只有自己才能改变自己。

  现如今,很多优秀员工不顾企业的挽留,翩然而去;潜力员工不顾企业的期待,悄然远去;甚至重点培养的员工,也不顾企业的重托,撒手而去,留给领导者无尽的懊恼和叹息。让领导者百思不得其解的是,似乎总是该走的没有走,不该走的却走了;平凡的没有走,优秀的却走了。于是,也总能听到领导者一遍又一遍无奈的歌谣:我拿什么来留住你?我的员工!

  领导者必须从“员工靠老板”的思想转变为“老板靠员工”。没有员工,就没有老板,从内心深处想通这个问题。否则就容易产生碰撞和矛盾。其实员工只要求在一个和谐、轻松、公正、公平、进取、团结的团队里工作,他就开心,就精神舒畅。但很多企业的企业文化缺乏人性化,企业领导的管理风格强硬化、观念僵硬化、都和现代企业要求的以人为本作为管理的核心,事事尊重人的需求,处处调动人的积极性,实现人的自我价值为中心的管理原则相背离。

posted @ 2012-04-16 22:34 paulwong 阅读(255) | 评论 (0)编辑 收藏

项目管理资源

http://www.cnblogs.com/ldcsaa/category/353927.html

posted @ 2012-04-16 00:57 paulwong 阅读(241) | 评论 (0)编辑 收藏

解释TOMCAT框架

1. Tomcat的整体框架结构

Tomcat的基本框架, 分为4个层次。
Top Level Elements:
Server
Service
Connector
HTTP
AJP
Container
Engine
Host
Context
Component
manager
logger
loader
pipeline
valve
...
站在框架的顶层的是Server和Service

Server: 其实就是BackGroud程序, 在Tomcat里面的Server的用处是启动和监听服务端事件(诸如重启、关闭等命令。

在tomcat的标准配置文件:server.xml里面, 我们可以看到“<Server port="8005" shutdown="SHUTDOWN" debug="0">”这里的"SHUTDOWN"就是server在监听服务端事件的时候所使用的命令字)

Service: 在tomcat里面, service是指一类问题的解决方案。 通常我们会默认使用tomcat提供的:Tomcat-Standalone 模式的service。 在这种方式下的service既给我们提供解析jsp和servlet的服务, 同时也提供给我们解析静态文本的服务。

Connector: Tomcat都是在容器里面处理问题的, 而容器又到哪里去取得输入信息呢?

Connector就是专干这个的。 他会把从socket传递过来的数据, 封装成Request, 传递给容器来处理。

通常我们会用到两种Connector,一种叫http connectoer, 用来传递http需求的。 另一种叫AJP, 在我们整合apache与tomcat工作的时候, apache与tomcat之间就是通过这个协议来互动的。 (说到apache与tomcat的整合工作, 通常我们的目的是为了让apache 获取静态资源, 而让tomcat来解析动态的jsp或者servlet。)

Container: 当http connector把需求传递给顶级的container: Engin的时候, 我们的视线就应该移动到Container这个层面来了。

在Container这个层, 我们包含了3种容器: Engin, Host, Context.

Engin: 收到service传递过来的需求, 处理后, 将结果返回给service( service 是通过 connector 这个媒介来和Engin互动的 ).

Host: Engin收到service传递过来的需求后,不会自己处理, 而是交给合适的Host来处理。

Host在这里就是虚拟主机的意思, 通常我们都只会使用一个主机,既“localhost”本地机来处理。

Context: Host接到了从Host传过来的需求后, 也不会自己处理, 而是交给合适的Context来处理。
比如:
<http://127.0.0.1:8080/foo/index.jsp>
<http://127.0.1:8080/bar/index.jsp>
前者交给foo这个Context来处理, 后者交给bar这个Context来处理。

很明显吧! context的意思其实就是一个web app的意思。

我们通常都会在server.xml里面做这样的配置
<Context path="/foo" docBase="D:/project/foo/web" />
这个context容器,就是用来干我们该干的事儿的地方的。

毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, 是不那么容易掌握TOMCAT的框架的。 所以得实践、实践、再实践。 建议下载一份TOMCAT的源码, 调试通过, 然后单步跟踪其启动过程。 如果有不明白的地方, 再来查阅本文, 看是否能得到帮助。 我相信这样效果以及学习速度都会好很多!

posted @ 2012-04-15 23:47 paulwong 阅读(443) | 评论 (0)编辑 收藏

alfresco集群负载均衡配置

机器两台:
A机器:172.16.48.26:用于Alfresco服务器(集群节点1)
用于数据库服务器、文件服务器(共享)、

B机器:172.16.48.27:用于Alfresco服务器(集群节点2)
负载均衡服务器


第一步:创建共用数据库
在A机器:172.16.48.26 上安装MySQL,建立名为alfresco的数据库;
#create database alfresco
#grant all privileges on alfresco.* to root@'%' identified by 'alfresco'

第二步:创建共享目录
在A机器:172.16.48.26上建立可写的共享目录 /alfresco;
在/下创建目录 alfresco
#mkdir /alfresco

第三步:设置共享目录
在A机器:172.16.48.26 上安装Samba,修改/etc/samba/smb.conf,增加以下内容
security = user
[alfresco]
comment = alfresco data & log
path = /alfresco
public = yes
writable = yes
write list = @root

第四步:建立Samba用户
在A机器:172.16.48.26建立Samba用户root
#smbpasswd -a root

第五步:建立共享
在B机器:172.16.48.27上创建/alfresco目录并挂载A机器的 共享目录//172.16.48.26/alfresco
# mount -t smbfs -o username=root,password=alfresco //172.16.48.26/alfresco /alfresco

第六步:安装tomcat并修改配置
A机器:172.16.48.26 上安装tomcat,并修改conf/server.xml
maxThreads="20000"
emptySessionPath="true"
protocol="org.apache.coyote.http11.Http11NioProtocol"
enableLookups="false"
redirectPort="8443"
connectionTimeout="20000"
disableUploadTimeout="true" />


在B机器:172.16.48.27 上安装tomcat,并修改conf/server.xml,内容同上,然后将jvmRoute改为tomcat2;

第七步:部署alfersco
将alfresco.war分别拷贝到A机器:172.16.48.26和B机器:172.16.48.27的webapps目录下,并解压缩到alfresco目录
#jar -xf alfresco.war

第八步:修改alfresco配置
分别对两台机器的alfresco的配置做修改

1、修改WEB-INF/classes/alfresco/repository.properties文件
dir.root=./alfresco_data
db.name=alfresco
db.url=jdbc:mysql://172.16.48.26:3306/${db.name}
db.username=root
db.password=alfresco

2、拷贝extension目录(在repository项目的config中)下的内容分别到172.16.48.26和172.16.48.27的WEB-INF/classes/alfresco/extension目录下,
包括:
custom-hibernate-dialect.properties
custom-repository-context.xml
custom-repository.properties
ehcache-custom.xml
replicating-content-services-context.xml
以及自己定义的content的配置

3、修改custom-hibernate-dialect.properties文件
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

4、修改custom-repository.properties文件
dir.root=./alfresco_data
index.recovery.mode=AUTO
index.tracking.cronExpression=0/5 * * * * ?
index.tracking.reindexLagMs=10000
db.driver=org.gjt.mm.mysql.Driver
db.name=alfresco
db.url=jdbc:mysql://172.16.48.26:3306/${db.name}
db.username=root
db.password=alfresco

5、修改ehcache-custom.xml文件
properties="port=40001, socketTimeoutMillis=300000"/>

6、修改replicating-content-services-context.xml文件


./alfresco_data/contentstore




/alfresco/contentstore



第九步:启动tomcat

修改172.16.48.26的bin/catalina.sh文件,启动tomcat
export JAVA_OPTS='-Xms512m -Xmx2048m -XX:MaxPermSize=512m -server'
#./bin/startup.sh

修改172.16.48.27的bin/catalina.sh文件,内容同上,启动tomcat;

第十步:安装文件服务器

在172.16.48.26上安装apache httpd server到目录/usr/local/apache目录下,
拷贝从apache网站找到的 mod_jk.so到modules目录下

修改conf/httpd.conf
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
JkMount /* loadBalancer
JkMount /jkstatus status
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-default.conf

添加文件conf/workers.properties
worker.list=tomcat1, tomcat2, loadBalancer, status
worker.tomcat1.port=8009
worker.tomcat1.host=172.16.48.26
worker.tomcat1.type=ajp13
worker.tomcat2.port=8009
worker.tomcat2.host=172.16.48.27
worker.tomcat2.type=ajp13
worker.loadBalancer.type=lb
worker.loadBalancer.balance_workers=tomcat1, tomcat2
worker.loadbalancer.sticky_session=true
worker.loadbalancer.sticky_session_force=false
worker.status.type=status

修改conf/extra/httpd-default.conf文件
Timeout 300
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 300

修改conf/extra/httpd-mpm.conf文件

StartServers 5
MinSpareServers 5
MaxSpareServers 10
ServerLimit 4096
MaxClients 2048
MaxRequestsPerChild 0


ThreadsPerChild 1024
MaxRequestsPerChild 0


启动apache httpd server

第十一步:测试

在A机器创建用户test
使用test用户创建文件 file1.txt
在B机器使用test用户搜索 file1;

在B机器使用test用户创建文件 file2.txt
在A机器使用test用户搜索 file2;



原文链接:http://blog.csdn.net/wangxiaojing123/article/details/6682706

posted @ 2012-04-15 20:41 paulwong 阅读(742) | 评论 (0)编辑 收藏

给开发维护大型项目开发者的建议

假设你是正在开发和维护一个包含2000个类并使用了很多框架的Java开发人员。你要如何理解这些代码?在一个典型的Java企业项目小组中,大 部分能够帮你的高级工程师看起来都很忙。文档也很少。你需要尽快交付成果,并向项目组证明自己的能力。你会如何处理这种状况?这篇文字为开始一个新项目的 Java开发者提供了一些建议。

0. 不要试图一下子搞懂整个项目
好好考虑一下,为什么理解项目代码是第一位的?大部分情况是你被要求修复一个bug或者加强系统已有功能。你要做的第一件事情不是理解整个项目的架构。当对项目进行维护时,这样(理解整个项目架构)可能会对你造成巨大的压力。

即便是有着10年可靠编程经验的Java开发者可能也没有理解项目的核心工作机制,尽管他们可能已经在这个项目工作超过一年(假设他们并非原始开发人员)。比如,对于认证机制或事务管理机制。

他们是怎么做的?他们对于自己负责的部分非常了解,并且能够交付价值给小组。每天的交付价值远比了解一些以后还不确定有没有的东西重要的多。

1. 关注于尽快交付价值
那我是否定了你对于项目架构理解的热情了么?完全不。我只是要求你尽早的交付价值,一旦你开始一个项目,搭建了开发环境,你就不应该花一两周时间才交付什么,无论他的规模大小。假如你是一个有经验的程序员却两周都没有任何交付,你的经理怎么会知道你是真的在工作还是在看新闻。

所以交付可以使大家都轻松起来。不要认为你能够做有价值的交付前必须理解整个项目。这是完全错误的。加一段javascript的验证代码对业务就很有价值,经理能够通过你的交付达到对你的信任。这样能够向上级领导证明你的贡献以及员工价值。

日复一日,在你不断修复bug及增强功能之后,就能够慢慢开始理解项目架构。不要低估对系统方方面面理解时需要花费的时间。花3-4天理解认证机 制,2-3天理解事物管理。这些都是依靠之前的相似项目的经历,但关键还是要花时间才能透彻的理解。要在日常工作中挤出时间,不要向经理要求特定的时间来做这些。

找找项目是否有一些不断维护的单元测试用例。有效的单元测试用例是理解大型项目代码的很好途径。单元测试能够帮助理解代码片段,包括一个单元的外部接口(单元如何被调用以及返回内容)及其内部实现(调试单元测试比调试整个实际用例简单许多)。

你如果能够很好的理解一些内容,写一些笔记,或者画一些类图、时序图、数据模型图,以便你或日后其他的开发者维护。

2. 维护大型项目所必须的技能
你能从事当前的工作,必然已经具有良好的java技术。我们来谈谈能够让你在新项目中良好表现的其他技能。大部分时间,你在项目中的任务是修复bug和增强功能。

有两项很重要的技能能够协助你维护大型项目代码。

2.1 能够迅速发现需要的类
在任何维护活动中,无论是修复bug或增强功能,第一个动作就是识别出当前修复或增强的用例中调用的类。当你定位到需要修复或增强的类/方法,就已经完工了一半。

2.2 能够分析变更的影响
当你在完成必要的修改或增强工作后,最重要的就是要确认你的修改没有破坏代码的其他部分。你要用你的java技术及对其他框架的理解找出变更可能影响的部分。下面有两个简单的例子详细描述了最后提及的情况:

a)当类A的equals()方法变更后,调用一个保护A实例的List的contains()方法时就会被影响到。若Java知识不够,很难考虑到这样的影响。

b)在一个web项目中,我们假设“user id”保存在session中。一个新入程序员可能在“user id”中加入一些信息作为bug修复的方法,但是却不知道会影响到那些关联“user id”的用例。

当你提高了如上两个技能,尽管你对项目不是非常了解,但大部分的维护任务会变得简单很多。若你修复一个bug,你会定位并修复这个bug,并且保证变更不会破坏项目的其他部分。若你增强或加入一个特性,基本上你只需要模仿现有的特性使用相似的设计。

在一个在线银行项目中,为什么“查看账户摘要”和“查看交易历史”的设计需要巨大的差别呢?如果你理解了“查看账户摘要”的设计,完全可以模仿开发出“查看交易历史”的功能。

就修复bug和增强来说,你不必完全理解所有2000个类的工作内容和代码如何运行来推动系统。你若有上面的技能,就能很快定位需要修改的代码的部分,使用良好的java和框架技能修复,保证变更不会破坏项目的其他部分并交付,尽管你可能只知道一小部分项目的设计。

3. 使用工具找到需要的变更内容以及变更产生的影响
继续我们尽快交付的主题,你应当寻找那些能够通过尽量少的了解项目但能帮助你尽快实施交付的工具作为辅助。

3.1 迅速发现需要变更内容的工具
无论是修复bug还是系统增强,首先都要找到该用例调用的你需要修改的类及方法。基本有两种方式理解一个用例的工作方式,静态代码分析和运行时分析。

源码分析统计扫描所有代码并且展示类之间的关系。市场上有很多设备与工具。比如:Architexa, AgileJ, UModel, Poseidon等。

所有的静态代码分析工具缺点在于无法确切展示用例中类或方法的运行时调用情况。因此Java新加入了特性,如回调机制(callback patterns)。如静态分析工具无法推断出当页面提交按钮被点击时哪个Servlet被调用了。

运行时分析工具能够展示类和方法在用例运行时的状态。工具包括:MaintainJ, Diver,jSonde,Java Call Tracer等。这些工具可以捕获运行时的堆栈状态,并以此为一个用例生成序列图和类图。

序列图展示了该用例在运行时所有调用的方法。若你在修复一个bug,那这个bug很可能就是这些被调用的方法之一。
若你在增强已有功能,利用序列图理解调用流程然后再修改。可能是新增一个验证,修改DAO等。

若你在新增功能,找到一些相似的特性,利用序列图理解调用流程然后模仿开发新功能。

要小心挑选运行时分析工具。信息过多是这类工具的主要问题。选择一些提供简单过滤无效信息并能够方便的查看各种视图的工具。

3.2 迅速发现需要变更内容的工具
若单元测试有效,可以通过运行单元测试发现变更有没有破坏其他测试用例。有效维护并且覆盖大型企业应用的单元测试还是比较少的。下面有一些针对该情况的工具。

仍然是有两种技术静态代码分析和运行时分析可以使用。市场中有很多静态代码分析工具可用。如:Lattix, Structure101, Coverity, nWire and IntelliJ’s DSM。

给定一个变更后的类,上述工具均可识别对该类存在依赖的类的集合。开发者需要根据这些信息“猜测”可能产生影响的用例,因为这些工具无法展示运行时类之间的调用关系。

市场上的可以用于运行时影响分析的工具并不多,除了MaintainJ。MaintainJ先捕获在一个用例中调用的所有类和方法。当所有用例的上 述信息都被捕获之后,就很容易发现类的变更对用例的影响。MaintainJ能够有效工作的前置条件就是项目的所有用例都应当先运行一遍,以便能够获得运 行时的依赖关系。

总之,目前你在迅速准确分析变更影响方面,还是可以从工具中获得有限的帮助。首先根据需要实施一些影响分析,然后根据自己或小组其他高级成员评审来判断变更的影响。你可能需要上面提到的工具对你的判断进行反复确认。

4. 对上述内容的两个忠告
4.1 不要降低代码质量
为了快速交付,所以没有全盘理解架构,但绝不能以降低代码质量为条件。下面是一些你可能因为只考虑快速交付而引发的代码质量问题。

因为修改代码涉及到很多的依赖,所以新增代码相对而言风险较小。例如,有5个用例都调用了某个方法。为了改进某个用例,你需要修改这个方法的实现。 最简单的做法就是复制这个方法,重命名,然后在改进的用例中调用新方法。千万不要这么做。代码冗余绝对是非常有害的。尝试对方法进行包装或者重写,甚至是 直接修改,然后重新测试所有用例,通常停下来想一想,然后亲手去实施,是一个比较好的方式。
code quality 
( 伯乐在线配图)

另一个例子是将“private”方法改为“public”,使得别的类也可以调用。尽量不要将非必须的部分暴露出来。假如为了更好的设计需要重构,就应当着手去做。

大部分应用都有确定的结构和模式来实施。修复或增强程序时,确认你没有偏离这样的模式。若对约定不确定,请其他的高级开发者来审核你的变更。若你必须做一些违背约定的实施,尽量放置于一个规模较小的类中(一个200行代码的类中的私有函数应当不会影响应用的整体设计)

4.2 不要停止深入理解项目架构
按照文章列出的方式,假设你能够在对项目了解较少的情况下进行交付并以此持续下去,可能你会停止对项目架构的深入了解。这样从长远角度来说对你的职 业生涯没有帮助。当你的经验增加时,你应当承担比较大的模块任务。如构建一个完整的新特性或者修改项目的一些基础设计等较大的改进。当你能够做这些改进 时,你对项目的整体架构应该相当了解。文中列举的方法是让你在最短的时间内提升自己,而不是阻止你完整理解整个项目。

5. 结论
整篇文章集中在对项目进行必要了解的前提下进行快速交付。你可以在不降低代码质量的前提下这么做。
若修复一个bug,迅速定位并修复。有必要可以使用运行时分析工具。若新增一个特写,可以寻找相似特写,理解流程(有必要使用工具)并编写。

或许这些听起来很简单,但是实用吗?当然。但前提是你有良好的java技术以及对框架足够了解才能先修改代码,然后对变更影响进行分析。对变更影响的分析比实施变更需要更多的技巧。你可能需要高级开发人员协助你分析变更影响。

大约有50%的IT可操作预算用于简单的bug修复和功能增强。根据文中的建议,对于维护活动中的经费的节省应当还是很有帮助的。

作者 Choudary Kothapalli 也是 MaintainJ 项目的建立者。

posted @ 2012-04-15 20:37 paulwong 阅读(233) | 评论 (0)编辑 收藏

转一个J2EE开发时的包命名规则,养成良好的开发习惯

代码编写规范目的:能够在编码过程中实现规范化,为以后的程序开发中养成良好的行为习惯。
代码编写规范使用范围:J2EE项目开发。
包命名规范:
目的:包的命名规范应当体现出项目资源良好的划分

servlet类所在包命名规范:公司名称.开发组名称.项目名称.web.servlet
例如:net.linkcn.web.servlet

自定义标签类所在包命名规范:公司名称.开发组名称.项目名称.web.tags
例如:net.linkcn.web.tags

过滤器类所在包命名规范:公司名称.开发组名称.项目名称.web.filter
例如:net.linkcn.web.filter

Action类所在包命名规范:公司名称.开发组名称.项目名称.web.struts.action
例如:net.linkcn.web.struts.action

ActionForm类所在包命名规范:公司名称.开发组名称.项目名称.web.struts.form
例如:net.linkcn.web.struts.form

Javabean所在包命名规范:公司名称.开发组名称.项目名称.web.struts.service.impl
例如:net.linkcn.web.service.impl

Javabean实现接口命名规范:公司名称.开发组名称.项目名称.web.service
例如:net.linkcn.web.service

DAO类所在包命名规范:公司名称.开发组名称.项目名称.dao.impl
例如:net.linkcn.dao.impl

DAO类所实现的接口在包中命名规范:公司名称.开发组名称.项目名称.dao
例如:net.linkcn.dao

POJO类与hbm文件所在包命名规范:公司名称.开发组名称.项目名称.dao.hbm
例如:net.linkcn.dao.hbm

全局公共类、接口类所在包命名规范:公司名称.开发组名称.项目名称.global
例如:net.linkcn.global

全局工具类所在包命名规范:公司名称.开发组名称.项目名称.util
例如:net.linkcn.util

类命名规范
基本命名规范:

类、接口命名

命名规范:以大写字母开头,如果有多个单词,每个单词头字母大写
例如:StudentInfo
接口命名

命名规范:以大写字母"I"开头,如果有多个单词,每个单词头字母大写
例如:IStudentInfo

接口实现类命名:
命名规范:将实现的接口名称的首字母"I"去掉,以"Impl作为结尾",如果有多个单词,每个单词头字母大写。
例如:StudentInfoImpl

J2EE+SSH框架命名规范
servlet类命名:
命名规范:以Servlet单词结尾
例如:LoginServlet

POJO命名:
使用hibernate自动生成的类即可

DAO类命名:
使用hibernate自动生成的类即可

Action类命名:
命名规范:Action的命名以POJO名称来制定,POJO名称Action
例如:
一个POJO名称为Diary,其对应的action为DiaryAction

ActionForm类命名:
命名规范:ActionForm的命名以POJO名称来制定,POJO名称Form
例如:
一个POJO名称为Diary,其对应的actioForm为DiaryForm

业务逻辑接口命名:
命名规范:业务逻辑接口的命名以POJO名称来制定,IPOJO名称Service
例如:
一个POJO名称为Diary,其对应的业务逻辑接口为IDiaryService

业务逻辑实现类命名:
命名规范:业务逻辑接口实现类的命名以POJO名称来制定
例如:
一个POJO名称为Diary,对应的业务逻辑接口实现类名为DiaryServiceImpl

类变量命名:
命名规范:变量名首字母必须小写,如果该变量名有多个单词组成,后面的单 词首字母大写,单词与单词之间不要使用"_"做连接,变量名访问控制必须为私有, 可以对其增加setter与getter方法。
例如:
private int studentAge;
public int getStudentAge(){
return studentAge;
}
public void setStudentAge(int studentAge) {
this.studentAge=studentAge;
}

常量命名:
命名规范:所有字母大写,如果有多个单词组成,单词与单词之间以” _“隔开。而 且该变量必须是公共、静态、final类型
例如:public static final String USER_NAME=”userName“;

方法命名
命名规范:首字母必须小写,如果该变量名有多个单词组成,后面的单词首字母 大写,单词与单词之间不要使用"_"做连接。单词不要使用名词。
例如:public int checkLogin(String name,String pwd){}

注释规范:注释规范是整个开发规范中最为重要的组成部分,必须严格执行。

类的注释:
作用:注释整个类,简单概述该类作用。
书写规范:类的注释必须写在该类的声明语法之前。在注释中要描述该类的基 本作用,作者,日期,版本,公司名称,版权声明。
格式:

类的声明语法

例如:

public class AdminDAO

变量、常量注释:
作用:简单描述该变量的意义。
书写规范:变量注释必须写在变量定义之前,简单描述其代表的意义。
格式:


例如:


public int age;
方法注释:
作用:对该方法功能简单描述,其参数、返回值意义的注解。
书写规范:方法注释必须写在方法定义之前。该注释包括:方法其功能的简单 描述,方法的参数、返回值类型、返回值意义简单的描述。
格式:


例如:

public booleaneditAdminPassword(int adminId,String oldPassword,
String password) throws UserException,ServiceException;

Jsp页面命名:
命名规范:jsp页面名称要以小写字母开头,如果有多个单词组成,后面的单词以 大写字母开头。名称要体现出该页面的意义,最好能够与模块名称联系在一起。
例如:
login.jsp --登录页面
register.jsp --注册页面
message.jsp --客户留言页面

J2EE项目工程文件夹组织规范:
目的:规范学员web应用程序的资源组织形式,形成良好的文件组织习惯。文件的组织形式应当体现模块的划分。

根据eclipse工具的特征,项目的目录结构为:
src
----存放java文件
WebRoot
|--images --存放web程序所需的公共图片
|--css --存放web程序所需的公共样式表
|--js --存放web程序所需的公共js文件
|--commons --存放web程序所需的公共文件
|--功能模块文件夹(存放与某个功能模块相关的资源)
|--images --存放与该功能模块相关的图片
|--css --存放与该模块相关的样式表文件
|--js --存放与该模块相关的js文件
|--jsp、html页面
|--WEB-INF
|--classes
|--lib
|--tld文件

J2EE项目提交规范
项目完成时要将项目作为一个产品交付用户,良好的项目组织规范可以使用户可以方便的找寻项目中需要的资源,同时也是一个公司专业性的体现。项目提交时,要按照下列文件格式进行提交。

项目主文件夹:
作用:存放项目其他资源文件。
命名规范:时间_班级编号_第X小组。
例如:070706_GS2T18_第四小组。
项目主文件夹下面包括以下文件夹和文件:
|--src:保存.java文件。
|--database:保存数据库的脚本文件或者数据库备份文件。
|--source:保存eclipse工程中WebRoot目录下的所有文件。
|--depend:保存编译该程序必须依赖的其他jar文件。
|--javadoc:保存所有类生成的javadoc api文档。
|--war:保存程序的归档文件
|--xx.war:已经打包好的工程文件,可以直接运行。
|--project:保存开发项目原工程代码及文件。
|--产品说明书.doc:图文方式展现该产品使用方法。
|--build.xml:ant脚本,用于生成运行的war文件。
|--项目解说.ppt:进行项目讲解的ppt(ppt仅供在校模拟项目使用,不用于其他商业用途)
注:一个完整的项目中,数据库必须有一定量的有效的测试数据来支持该程序的运行

包的命名 
Java包的名字都是由小写单词组成。但是由于Java面向对象编程的特性,每一名Java程序员都可以编写属于自己的Java包,为了保障每个 Java包命名的唯一性,在最新的Java编程规范中,要求程序员在自己定义的包的名称之前加上唯一的前缀。由于互联网上的域名称是不会重复的,所以程序 员一般采用自己在互联网上的域名称作为自己程序包的唯一前缀。
例如: net.frontfree.javagroup

类的命名
类的名字必须由大写字母开头而单词中的其他字母均为小写;如果类名称由多个单词组成,则每个单词的首字母均应为大写例如TestPage;如果类名 称中包含单词缩写,则这个所写词的每个字母均应大写,如:XMLExample,还有一点命名技巧就是由于类是设计用来代表对象的,所以在命名类时应尽量 选择名词。   
例如: Circle

方法的命名
方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头。
例如: sendMessge

常量的命名
常量的名字应该都使用大写字母,并且指出该常量完整含义。如果一个常量名称由多个单词组成,则应该用下划线来分割这些单词。
例如: MAX_VALUE

参数的命名
参数的命名规范和方法的命名规范相同,而且为了避免阅读程序时造成迷惑,请在尽量保证参数名称为一个单词的情况下使参数的命名尽可能明确。

Javadoc注释
Java除了可以采用我们常见的注释方式之外,Java语言规范还定义了一种特殊的注释,也就是我们所说的Javadoc注释,它是用来记录我们代 码中的API的。Javadoc注释是一种多行注释,以结束,注释可以包含一些HTML标记符和专门的关键词。使用Javadoc 注释的好处是编写的注释可以被自动转为在线文档,省去了单独编写程序文档的麻烦。
例如:

在每个程序的最开始部分,一般都用Javadoc注释对程序的总体描述以及版权信息,之后在主程序中可以为每个类、接口、方法、字段添加 Javadoc注释,每个注释的开头部分先用一句话概括该类、接口、方法、字段所完成的功能,这句话应单独占据一行以突出其概括作用,在这句话后面可以跟 随更加详细的描述段落。在描述性段落之后还可以跟随一些以Javadoc注释标签开头的特殊段落,例如上面例子中的@auther和@version,这 些段落将在生成文档中以特定方式显示。

变量和常量命名
变量命名的方法采用匈牙利命名法,基本结构为scope_typeVariableName,它使用3字符前缀来表示数据类型,3个字符的前缀必须 小写,前缀后面是由表意性强的一个单词或多个单词组成的名字,而且每个单词的首写字母大写,其它字母小写,这样保证了对变量名能够进行正确的断句。例如, 定义一个整形变量,用来记录文档数量:intDocCount,其中int表明数据类型,后面为表意的英文名,每个单词首字母大写。这样,在一个变量名就 可以反映出变量类型和变量所存储的值的意义两方面内容,这使得代码语句可读性强、更加容易理解。byte、int、char、long、float、 double、boolean和short。
变量类型和首字母对照关系如下表:
数据类型/对象类型 / 变量前缀 / 备注
byte bye
char chr
float flt
boolean bln 做布尔变量时,使用bln
Integer/int int
String str
Single sng
short sht
Long/long lng
Double/double dbl
Currency cur
Variant bln astr obj vnt 做布尔变量用时,用bln,做字符串数组用时,用astr,做为对象使用时,用obj,不确定时,用vnt。
对于数组,在数据类型的前缀前再增加一个a,例如字符串数组为astr。对于在多个函数内都要使用的全局变量,在前面再增加“g_”。例如一个全局的字符串变量:g_strUserInfo。

在变量命名时要注意以下几点:
· 选择有意义的名字,注意每个单词首字母要大写。

· 在一段函数中不使用同一个变量表示前后意义不同的两个数值。

· i、j、k等只作为小型循环的循环索引变量。

· 避免用Flag来命名状态变量。

· 用Is来命名逻辑变量,如:blnFileIsFound。通过这种给布尔变量肯定形式的命名方式,使得其它开发人员能够更为清楚
的理解布尔变量所代表的意义。

· 如果需要的话,在变量最后附加计算限定词,如:curSalesSum。

· 命名不相包含,curSales和curSalesSum。

· Static Final 变量的名字应该都大写,并且指出完整含义。

· 如果需要对变量名进行缩写时,一定要注意整个代码中缩写规则的一致性。例如,如果在代码的某些区域中使用intCnt,而在另一些区域中又使用intCount,就会给代码增加不必要的复杂性。建议变量名中尽量不要出现缩写。

· 通过在结尾处放置一个量词,就可创建更加统一的变量,它们更容易理解,也更容易搜索。例如,请使用 strCustomerFirst和strCustomerLast,而不要使用strFirstCustomer和strLastCustomer。常 用的量词后缀有:First(一组变量中的第一个)、Last(一组变量中的最后一个)、Next(一组变量中的下一个变量)、Prev(一组变量中的上 一个)、Cur(一组变量中的当前变量)。

· 为每个变量选择最佳的数据类型,这样即能减少对内存的需求量,加快代码的执行速度,又会降低出错的可能性。用于变量的数据类型可能会影响该变量进行计算所产生的结果。在这种情况下,编译器不会产生运行期错误,它只是迫使该值符合数据类型的要求。这类问题极难查找。

· 尽量缩小变量的作用域。如果变量的作用域大于它应有的范围,变量可继续存在,并且在不再需要该变量后的很长时间内仍然占用资源。它们的主要问题是,任何类 中的任何方法都能对它们进行修改,并且很难跟踪究竟是何处进行修改的。占用资源是作用域涉及的一个重要问题。对变量来说,尽量缩小作用域将会对应用程序的 可靠性产生巨大的影响。
关于常量的命名方法,在JAVA代码中,无论什么时候,均提倡应用常量取代数字、固定字符串。也就是说,程序中除0,1以外,尽量不应该出现其他数 字。常量可以集中在程序开始部分定义或者更宽的作用域内,名字应该都使用大写字母,并且指出该常量完整含义。如果一个常量名称由多个单词组成,则应该用下 划线“_”来分割这些单词如:NUM_DAYS_IN_WEEK、MAX_VALUE。

posted @ 2012-04-15 18:53 paulwong 阅读(4531) | 评论 (0)编辑 收藏

工作流引擎Activiti使用总结

http://www.kafeitu.me/activiti/2012/03/22/workflow-activiti-action.html


源码来了:
https://github.com/henryyan/kft-activiti-demo

posted @ 2012-04-09 16:39 paulwong 阅读(2039) | 评论 (0)编辑 收藏

调优思路

1、使用剖析器,如jvisualvm等工具抓快照,分析调用次数最多,和耗时最多的Java代码;

2、如果数据库是Oracle,可以把数据库迁移到11G进行测试,11G里面也有一个剖析工具抓快照,可以分析出哪条SQL语句执行最频繁,哪条SQL执行最耗时;

3、如果是WebApp,可以自己去修改clickstream的filter抓取和记录所有的用户请求,统计记录结果中的访问次数和耗时;

posted @ 2012-04-09 00:37 paulwong 阅读(244) | 评论 (0)编辑 收藏

基于ZooKeeper的分布式Session实现

http://my.oschina.net/jsan/blog/52151

posted @ 2012-04-02 00:14 paulwong 阅读(351) | 评论 (0)编辑 收藏

仅列出标题
共110页: First 上一页 79 80 81 82 83 84 85 86 87 下一页 Last