|
标签:it |
一. 软件规模度量的必要性
软件项目规模的度量,是软件项目中相当重要的一环.
只有相对合理和相对准确地度量软件规模,才能对项目的计划进度安排,资源分配,等等各个环节进行合理的部署.这样才能尽可能地保证软件项目的进度和质量.
原因是:
1.
2.
3.
二.软件项目规模度量的相关方法及其局限
l
代码行度量的方法,是通过各种手段,统计出软件项目的代码行.从而按代码行的数量为单位度量出软件的规模.
一般使用代码行度量自动化工具来进行度量,要度量的文件类型包括软件项目中交付用户使用的各种文件. 一般来说,如果项目的配置管理是使用CVS的话,可以使用StatCVS进行代码行度量.
LOC方法的优点是:
1.
2.
规模度量的方法缺点是非常明显的.
1.
2.
3.
l
功能点法是一种面向功能的软件度量方法。一般来说,功能点法的计算根据软件需求规格说明书进行计算,在计算过程中需要充分利用DFD、E-R或UseOase图等提供的信息。
面向功能的软件度量是对软件和软件开发过程的间接度量。面向功能度量的关注点在于程序的“功能性”和“实用性”,而不是对LOC计数。一种典型的生产率度量法叫做功能点度量,该方法利用软件信息域中的一些计数度量和软件复杂性估计的经验关系式而导出功能点FPs(Function Points)。
功能点通过。首先确定五个信息域的特征,并在表格中相应位置给出计数。信息域的值以如下方式定义:
用户输入数:各个用户输入是面向不同应用的输入数据,对它们都要进行计数。输入数据应有别于查询数据,它们应分别计数。
用户查询数:查询是一种联机输入,它导致软件以联机输出的方式生成某种即时的响应。每一个不同的查询都要计数。
通过对上面几个重要信息域的收集,可能定义出软件项目的功能点的数量,再使用如下的关系式:
(其中,总计数是由表2所得到的所有加权计数项的和;Fi(i = 1到14)是复杂性校正值,它们应通过逐一回答表2所提问题来确定。SUM(Fi)是求和函数。上述等式中的常数和应用于信息域计数的加权因数可经验地确定。Fi是对影响产品规模的14个因素进行分析确定的“复杂度调整值”,取值范围是0-5)
就可以计算出FP的数量
FP方法的优点
放弃了依赖于技术细节的LOC方法简单线性标准,通过功能点来进行估计,这样一来甲方对发包产品的成本估算、乙方对自身开发成本的预测提供了便利, 比如,A软件项目的规模是100功能点,我们根据行业基准(Benchmarking)知道平均成本是5000元/功能点,那么本项目的成本预测就是50万元;我们又根据行业基准知道平均生产率为1功能点/人天,则计算得到项目需要投入100个人天的工作量,这些计算的结果将成为签定合同的依据和软件项目管理的基础
其缺点,仍然是没有考虑到不同的开发项目团队和开发条件下的不同状况,只是从一些平均普遍的方法上去进行度量,因为和实际项目的差距,造成了这种方法的缺陷.
三.软件规模度量的目标的再次明确
脱离了这个目标,笔者认为,再好的软件度量方法也是没有意义的.因为软件开发的过程,受到影响的因素太多,包括开发人员的熟练程序,水平,配置管理环境的完善与否,所使用的技术和设计方案合理与否,测试机制合理与否,都有关系.
而这些因素,每个软件项目开发的团队都是不一样的,这些因素本身就难以度量.
传统的功能点和代码行的度量方法.在实际的开发中,往往脱离了对实际项目环境,因此盲目的使用传统的度量方法进行度量工作,往往是白费的.
四.软件项目度量在实际项目中的认识.
l
不同的开发团队,由于其开发软件项目所熟练和精通使用的技术不同,因为软件项目的度量,必须要以这些团队自身特长的技术作为基础,如果使用通用的度量方法,是必然会引起偏差的.
l
l
五.软件项目度量在实际项目中的手段
1.建立软件规模度量的历史数据库(面向团队).这个数据库必须由团队每一个成员共同维护,每个项目的分任务完成后,要将完成的时间,所使用的资源记录在数据库中.特别是要记录任务的使用条件.例如,完成任务一使用的是Hiberante技术,而完成任务二使用的是ibatis技术等.完成任务三使用的是loadrunner工具(测试),完成任务四是使用jmeter工具等.
2.在项目计划中,进行任务分解的时候,一定要注意任务的粒度不能太大,一般要求在三天到一周之内.如果任务粒度太大,会增加规模度量的误差.同一个任务,当开发人没的熟练程度改变时, 就能引入误差,而粒度越大,引入的误差也会越大.
同样地. 记录于历史数据库中的任务粒度,也要保持三天到一周的标准
3.软件规模的度量要集合全体团队成员一起进行.团队成员中每人有自己的特长,要因应其特长进行估算,才能获得最大效果.
4.度量的时候,一定要将所有的度量单位,转化为时间人力成本和固定投资成本两种单位,只有这样,才能使软件规模的度量,贴合到甲乙方的生产资源利用的实际情况,才能保证项目的顺利完成.
5.必须要将软件生产中,硬生产内容和软生产内容所占用的时间都计算在度量范围内
硬生产内容,是指软件项目的设计,编码,调试,测试等内容,这些内容生产出来的成品,是可以交付给甲方的.属于最终产品的一部分.
软件生产内容,是指软件开发过程中,乙方硬件配备,开发环境的搭建,配置管理环境的搭建等,开发必不可少,但又不会有成品产生交付给甲方的工作内容.但这些内容,也实际占用了软件开发的时间,因此是必须将其纳入度量范围,才能更准确度量出软件项目的规模.
6.必须每周都要根据项目的实际情况,进行新的度量,如果度量的结果和预计有偏差,应该向要让甲乙双方所有项目参与人员通报,并制定相应的方案.
7.由于缺陷(Bugs)的清除,通常会占项目开发时间30%以上,因此缺陷(Bugs)的度量在整个项目的规模度量中,是占最重要的位置的.许多项目的度量忽视了对缺陷量和程度度量,往往会造成了项目时间和成本度量的巨大偏差.
六.总结
参考资料: 软件产品的规模度量-功能点与代码行 [肖鹏]
《功能点分析方法与实践》李帜等编著 清华大学出版社 2005
功能点法在软件项目早期规模估算中的运用 [陈兵]
二.
当要从Action中执行的loadCity方法,要返回到jsp页面时,要在页面上指定一个return的页面.我们在admin-action.xml配置中可以看到一句
<result name='city'>/admin/city.jsp</result>
而在loadCity方法中有这样一句
return 'city';
这样,当loadCity执行完后,就会返回到http://localhost/admin/city.jsp页面.
由于在action中,cityId和mthCity.cityId是被前一个提交过来的jsp页面赋值过,所以当程序执行转到city.jsp页面的时候,这几个值是能被使用的.我们使用jstl来获得这些值
1.
这个问题比较特殊.
我的工程中,建立了一个类cityService.这个类是进行数据库操作的,也就是和hibernate打交道的.而这个类在hibernate的设置中设置为被一个hibernate Session管理的范围.
这个cityService中有一个方法,用于更新city的信息的
baseHibernateDAO.update(icity);//这个baseHibernateDAO只是一个封封装了hibernate
大家可以看到,方法中并没有直接update从参数传进来的city,而是新建了一个icity,装了city中的信息再进行update.
这是因为,cityService这个类被hibernate管理,所以在这个类中创建的内容,才能被更新.所以我们必须使用一个新的MthCity类实例来装着外面传进来的内容,才能更新.否则就会出现类似have the same id object in the session的错误,也就是说session中有其它相同id的对象的错.
当然,有另一个处理办法,就是使用baseHibernateDAO.merge来更新内容,而还是用update
这里就可以写成
public void updateCity(MthCity city) throws DataAccessException,
baseHibernateDAO.merge(icity);
}
2.
在我的项目中,city有一个属性是timestamp,对应的是mth_city这个表,这个表通过hibernate的映射,映射成一个POJO对象
public class MthCity implements java.io.Serializable {
}
大家可以看到,类中有一个属性是timestamp,定义为Date类型.
这个类型是用于记录数据库操作的日期的,数据库中的对应字段也叫timestamp.看一下hibernate的映射配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC '-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
<!--
-->
<hibernate-mapping>
</hibernate-mapping>
大家可以看到,cityid对应数据库表中的CITY_ID字段,其值由oracle sequence生成
而timestamp属性,对应的是数据库的TIMESTAMP字段,并且这个属性在mapping中定义为<version>属性
这样,就会出现两点要注意的地方
l
org.hibernate.StaleObjectStateExceptio
l
mthCity.setTimeStamp(new Date());
否则也会引起hibernate的出错.
由于开发任务紧张,因为这里的开发笔记,仅用于记录遇到的几个struts2和hibernate结合开发的现象.不对其做分析.
1.
这是struts2和struts1最大的区别.
Struts2中,action和jsp页面之间的信息交互,是通过 action中定义的成员变量来实现的.
例如,我在一个名为EstateAction的类中有如下定义
public class CityAction extends BaseAction {
}
然后,这里上面的类中的成员类MthCity的定义如下
public class MthCity implements java.io.Serializable {
}
这是一个Hibatenate使用的数据对象 POJO类.
有了这两个类后,我们来看看Struts2的Action和JSP页面之间是如何交互的
一.
Jsp页面
l
<%@ page language='java' contentType='text/html; charset=gbk'%>
<%@ include file='/common/taglibs.jsp'%>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=gbk' />
<title>提交</title>
</head>
<script>
</script>
<body>
<form name=”myform” >
</form>
</body>
</html>
大家可以看到,这个页面只有一个按钮,将页面提交到struts的一个action中,这是为什么呢.
l
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE struts PUBLIC
<struts>
</struts>
这是一个struts2的典型配置文件.
上面有几处要注意的
首先是namespace = “/admin” 这是一个struts模块名,可以不写,但如果写了,能比较方便的将struts2的action按配置来分模块.(何谓分模块呢?struts2有个特性,是action定义不需要像struts1一样写在同一个struts.xml文件中.而是可以使用include的形式.例如我使用的项目的struts.xml文件就是这样写的:
<struts>
</struts>
这样include了一系统的xml配置,而上面的admin-action.xml文件就是其中一段,因此将这一段中涉及的action类设定为一个模块,就定namespace = “/admin”
)
其次
<action name='city/*' method='{1}'
这一句配置的意思,就是,当用户提交一个符合struts2格式的申请时(所有包含.do形式的http链接)
例如http://localhost/admin/city/loadCity.do
这一条是特定的struts2请求链接.
所以struts会通过配置解析,这里要特别提一下的是,这链接中的admin,就是struts定义中的namespace='/admin'中的admin. 要访问这个action的方法,就一定要按namespace 中定义的名称来访问.
其中包含了/city/那么在配置 文件中,只要定义action name=”city/*”,那么所有包含有/city/的do,都会提交到action定义的类中来,也就是类om.mytophome.admin.representation.struts.action.CityAction中,那么提交到这个类的哪个方法中呢? 因为选择的是city/*.而且mothed={1},所以方法名由链接指定
也就是loadCity.do所指定的.loadCity方法.
l
http://localhost/admin/city/loadCity.do?cityId=9
这样,在loadCity方法中,如果你访问cityId,就可以发现cityId的值是9
System.out.println(Long.toString(cityId));
但这里有一个条件,就是CityAction中,必须要有cityId变量的getter/setter方法(这两个方法可以用MyEclipse自动生成)
这样才能在jsp页面提交时,由struts为cityId赋值.(当然,getter方法就方便当action返回到jsp页面时,cityId的值能在页面取到.)
l
例如http://localhost/admin/city/loadCity.do?cityId=9&mthCity.cityId=8
这条链接提交后,会和上面一样调用CityAction的loadCity方法,但这里,action的成员mthCity会被创建实例,并为mthCity的一个属性cityId赋值,也就是说,在action中,大家可以通过mthCity.getCityId()来获得这个属性的值.
当然,一定要在action设置mthCity的getter setter,jsp上的内容才能传到action中
l
这样,当用以下语句表单提交的时候
doucment. myform.submit();
就能在Action中创建一个mthCity实例,并为mthCity.cityName设置值为:广州.
原因是在页面的表单元素中,设置了name= mthCity.cityName,而action中刚好有成员类叫mthCity,而这个类中刚好有属性叫cityName.,就是通过这样的方法,能将表单的内容,提交到Action中.
|
标签:it/科技 |
我们在一般的apache + tomcat的组合下配置虚拟主机的文章很多,但当我需要在Windows2000下,要配置IHS (IBM Http Server) + Websphere 的虚拟主机时,却发现资料严重不足,而配置过程也并非我想像中容易.因为HIS的配置是要由Websphere的配置去影响和传播的.特写文章记录.
1. httpd.conf
将 NameVirtualHost 61.145.126.83 注释掉
将 # Win32DisableAcceptEx 注释去掉对性能有帮助
2.对管理控制台:
环境 ->虚拟主机-〉default_host -> 将主机别名里的 * 80 *443 去掉
对 proxy_host,如果没有人用就删除,如果有人用,要将 *:80, *:443 改为特定的名字 :80 或 ip:80,不能用 *
3. 然后创建4个新的虚拟主机,名字例如为
dg_host 然后主机别名为 dg.mysite.com 和端口 80, 以及 dg.mysite.com 和端口 443
gz_host 然后主机别名为 gz.mysite.com 和端口 80, 以及 gz.mysite.com 和端口 443
sz_host 然后主机别名为 sz.mysite.com 和端口 80, 以及 sz.mysite.com 和端口 443
zh_host 然后主机别名为 zh.mysite.com 和端口 80, 以及 zh.mysite.com 和端口 443
保存配置, 停止服务器
4. :<%WebSphereHome%>AppServer/profiles\AppSrv01/config\cells/applications/dgweb.ear/deployments/dgweb/dg.war/WEB-INF
将 ibm-web-bnd.xmi 里的 default_host 改为 dg_host
将 <%WebSphereHome%>/AppServer/profiles\AppSrv01/config\cells/applications/dgweb.ear/deployments/dgweb/META-INF/applications.xml 里的 <context-root>dg</context-root> 改为 <context-root>/</context-root>
对另外3个也一样,只是 default_host 分别为 gz_host, sz_host, zh_host
或者可以在管理控制台->企业应用程序->选择应用程序->将虚拟主机映射到web服务.
在里面改虚拟主机和应用程序的关系也可以
5.启动服务器,管理控制台-〉服务器-> webserver1->重新生成插件
重起 IHS
1.
在WebSphere运行的时候,如果出现了内存溢出,那么原因是多样的.可能是因为程序中有不良的代码,引致申请了的内存不能在使用后被释放. 可能因为程序结构不善,引致websphere容器花费大量开销用于优化造成.
这里有一点要特别注意,内存溢出的时候,通常的表现是Websphere的服务没有了响应,所以当服务没有响应的时候,我们可以假设其为内存溢出,然后按步骤做相应的信息收集.
无论哪种原因. 内存溢出的问题可以分成两类.
先说一下,出现NATIVE类内存溢出的时候要如何处理.
步骤如下.(Webshpere版本 6.0.2.7)
在浏览器中输入http://服务器ip:9060/ibm/console 进入Websphere 管理控制台-> 登录->服务器->应用程序服务器->在服务器列表中选择需要调试的服务器->java和进程管理->进程定义->java虚拟机->将详细垃圾回收选项选上.
首先运行netstat -an > netstat_before.out 将收集数据时的网络状态记录下来.
打开Websphere的SystemOut.log文件,将文件最近的一次服务器启动记录找到.在这个记录中会找到现在正在运行并发生内存溢出的java进程的进程号.(如果最近一次启动服务器是失败的,那么在服务器对应的log目录中能找到一个server_name.pid文件记录中找到对应的进程号.)
然后在windows的命令行模式下,运行
userdump PID
这个PID就是先前的步骤中找到的websphere进程号
这样会生成一个叫java.dmp的文件. 将其改名成java1.dmp.
两分钟后再运行多一次userdump.生成的文件改名为java2.dmp.
两分钟后再运行多一次userdump.生成的文件改名为java3.dmp.
这样就能生成用于分析的系统内存映像文件.
(如果上面的步骤出现了问题,例如生成java.dmp的过程不能完成.还可以使用dr. watson强制生成userdump文件.方法如下:
在命令行中运行:
drwtsn32 -p pid
生成的userdump文件会放在
operating_system_root\Documents and
Settings\
All Users\Application Data\Microsoft\Dr Watson
但这种做法的会同时停止java.exe进程.因此只有其它的生成userdump方法失效的情况下才合适使用.)
2.
如果在WebShpere运行的过程中出现了高CPU占用率的引起的原因是多样的.但这里要分清楚瞬时高CPU占用率和占用率居高不下两种情况. 前者是正常的,因为有很多不同的程序在系统中运行,因为进程间的优先级,和CPU的能力所致,很多时候会出现一小段时间内CPU占用率的大幅提高.我们这里要描述的问题,是指CPU占用率高上去之后下不来的情况.
在Windows的管理工具中选择 性能
点击工具栏上的”添加”增加监控内容,将右边方框中所有的java线程都进行选择.左边则选择Processor Time , ID Process ,ID Thead,如图
同样的操作,在计数器日志中要设置.
选择性能监控器中的计数器日志,点击右键->新建日志设置->输入名称->确定->添加计数器->然后仍是将所有的java线程选中,也选上Processor Time , ID Process ,ID Thead
如是图
这样做的目的,是让性能监控中内容,能在固定的log文件中记录下来.
这个命令用于记录生成javacore时的网络状况.
在没有开启websphere soap安全方式情况下,使用
wsadmin.bat
打开websphere管理台.
如果在SOAP方式下,就要加入参数,命令行格式如下:
wsadmin.bat [-host host_name] [-port port_number] [-user userid[-password password]
在启动了wsadmin的状态后,运行以下命令设置好环境
wsadmin>set jvm [$AdminControl completeObjectName type=JVM,process=server1,*]
上面的server1就是要生成javacore的服务器的名称
环境设置好后,在wsadmin状态下运行
wsadmin>$AdminControl invoke $jvm dumpThreads
这样会生成一个javacore.
然后2分钟后再次运行
然后2分钟后再次运行
这样,就能在%Websphere%/AppServer/profiles/服务器名/ 这个目录下找到手动生成的三个javacore
ID Thread中就是占用率高的线程号. 这个号是十进制的,将其转换成16进制的数字.例如图中的数字的十六进制形式是0xD98
这样我们能在刚才生成的javacore中找到这样的句子
'SoapConnectorThreadPool : 0' (TID:0x10A25A98, sys_thread_t:0x24A31B30, state:R, native ID:0xD98) prio=5
这个十六进制的进程号就是对应javacore中native id = 0xD98的内容,这样我们就能大致知道这个引起cpu占用率高的线程在做什么,然后进行排错调试.
3.
这个工作需要借助Dr.Watson,
点击开始菜单->运行….->运行
drwtsn32
打开dr.Watson程序的窗口
对Dr.Watson的设置如图中所视,特别注意的内容是设置故障转储目录.当程序中止,我们在所设置的目录中找到需要的userdump文件.
设置好后
点击开始菜单->运行….->运行
drwtsn32 –i
这样,dr.Watson被设置为系统默认的调试器,会在程序中止时生成内存映像
至于Heap类型的内存映象,因为在Webshpere在中止时,会自动生成javacore文件,因为在程序中止后,直接到
%Websphere%/AppServer/profiles/服务器名/ 这个目录下找到自动生成的最新javacore就可以了
以上三个问题中所收集的数据,可以进行自己分析,对于javacore文件,分析工具是mddfj.IBM的网站上有相关文章介绍,在这里不再赘述.
也可以将这些文档发给IBM的客户服务中心,让他们的技术人员帮助分析.
希望这个文档,能帮助大家初步认识当Websphere出问题后,应该如何反应.欢迎批评指导…
