??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
其历史顺序应该SCSI->FC(用于SCSI)->ISCSIQ?br />
最初是从SCSI开始的Q它也是存储领域最为广泛的协议QSCSI的命令和数据Q可以直接在SCSI接口中传输,也可以通过装q行传输Q比如用USBQ?394QFCQ以及iSCSI{方式?
׃在传l的SCSI接口中,其传输的距离有限Q因此用FC来扩大传输距d应运而生Q从而封装SCSI的FC接口行hQ物理上它只是加上的FC的电路,其核心的SCSI部分基本不做修改Q因此Y件上ULSCSI HBA到FC的HBA实现隑ֺq不大?nbsp;
同样Q由于FC的成本和传输距离问题QiSCSI横空ZQ它用TCP/IP协议来封装和传输Q物理上加上TOE电\(或者用软g来实现这部分)Q同样其
核心仍然是SCSI的处理,方式和FC查不错。至于iSCSI的流行,q和软硬件厂商的推广(需要在存储的各个应用环境中都加入iSCSI的支?Q以?
市场的接受程度相兟?br />
从物理上来讲Q对于FC和iSCSI需要特D的IC来完成处理;而Y件上Q改变会比较,在windows下面QPCI
RAID卡、FC卡、iSCSI卡的驱动Q都是采用Port/MiniPort驱动架构Q其中Port
driver(是硬件无关的)由微软提??003以前叫SCSIPORT,现在叫StorPortQ在windows的系l目录下可以看见q该?
?Q而Miniport包含了上面所说的三种卡,其架构都一P只是要针对各U卡做对应的处理而已。对于其他的操作pȝQ这3U卡的Y件处理方面也是类
似的。因为最主要的差别都在物理传输上Q所以基本在g上完成;而Y件上Q都是以处理SCSI命o和数据ؓ核心Q然后围l传输接口做相关的处理?br />
个h对iSCSIQ比较看好!
]]>
作者:来自ITPUB论坛 2008-01-24
向大家介l一U很不错Q也是Linux中的权限理法?
定义a^b为:a的bơ方
假如Q我们ؓ每一个操作设定一个唯一的整数|比如Q?/p>
删除A---0
修改A---1
dA---2
删除B---3
修改B---4
dB---5
。。?/p>
理论上可以有N个操作,q取决于你用于储存用h限值的数据cd了?/p>
q样Q如果用h权限Q添加A---2;删除B---3;修改B---4
那用L权限?purview =2^2+2^3+2^4=28Q也是2的权的和?/p>
化成二进制可以表CZؓ11100
如果要验证用h否有删除B的权限,可以通过位与q算来实现?/p>
在Java里,位与q算q算W号?amp;
xQint value = purview &((int)Math.pow(2,3));
你会发现Q当用户有操作权限时Q运出来的l果都会{于q个操作需要的权限?
原理Q?/p>
位与q算Q顾名思义是对位q行与运:
以上面的式子ZQpurview & 2^3 也就是 28&8
它们化成二q制?/p>
11100
& 01000
-------------------
01000 == 8(十进? == 2^3
同理Q如果要验证是否有删除A---0的权?/p>
可以用:purview &((int)Math.pow(2,0));
卻I
11100
& 00001
------------------------
00000 == 0(十进? != 2^0
q种法的一个优Ҏ速度快。可以同时处理N个权限,讄NU角?
如果想验证是否同时有删除A---0和删除B---3的权?/p>
可以用purview&(2^0+2^3)==(2^0+2^3)?true:false;
讄多角色用戗根据权限值判断用L角色。。?/p>
下面提供一个java的单操作权限判断的代码:
//userPurview是用户具有的L?br /> //optPurview是一个操作要求的权限Z个整?没有l过权的!)
public static boolean checkPower(int userPurview, int optPurview){
int purviewValue = (int)Math.pow(2, optPurview);
return (userPurview & purviewValue) == purviewValue;
}
当然Q多权限的验证只要扩展一下就可以了?/p>
几点注意事项Q首先,一个系l可能有很多的操作,因此Q请建立数据字典Q以便查阅,修改时用。其ơ,如果用数据库储存用户权限Q请注意数值的 有效范围。操作权限D用唯一的整?Java的intcd最多可以储?1个权限和.如果过Q可以选择其它数据cdQ而且不同模块Q用多个权? 变量.
http://www.textcn.com/jishuwz/prosj/netnet/200612/55186.html
大家可能都有q样的体会,要满_U各L客户Qƈ且客L需求经常变化,E序员就是这L辛苦命,整天改过来改q去Q特别用一些非面向对象的语a写的代码Q函数的参数变得来长Q里面的Case情况慢慢增加Q函数变得很大。Y件几q之后就变得难于理解和维护,软g的生命周期好像就要终止。如果能够扩展模块的功能Q同时又不修改原来已l测试通过的代码,那多好啊Q?
q完全是可以实现的,关键是抽象。把可能的变化用抽象来隔d。面向接口编E,而不是面向对象编E,能增强程序的灉|性;如Clientc调用Server c,如果我们希望Client对象使用另外一个不通的Server对象Q就必须修改Client中用Servercȝ地方Q如果Client调用 Server的接口就可以避免q种修改Q只要生成新的接口实现类Q修改Main{初ơ用新子类的地方而不需要修改Clientc;使用Strategy 模式和Template Method模式是满OCP的最常用Ҏ?
如果需要适应某种变化需要对q种变化q行抽象Q会增加E序的复杂度。所以设计h员应该熟悉业务和了解客户需求,预测到需要进行抽象的变化?
敏捷建模不徏议提前进行各U假想的变化抽象Q而是当变化发生第一ơ的时候抽象这U变化,以后同样的变化就变得很容易。对代码q行重构以保持良好的l构是很重要的,每次抽象都不应该使Y件变得越来越僵化。这是非面向对象的语a不具备的优势?
参考:Health King的专?/a> 满OCP的设计给pȝ带来两个无可比拟的优? hq两个优点的软gpȝ是一个高层次上实C复用的系l?也是一个易于维护的pȝ.那么,我们如何才能做到q个原则?不能修改而可以扩?q个看v来是自相矛盾?其实q个是可以做到的,按面向对象的说法,q个是不允许更改系l的抽象?而允许扩展的是系l的实现? 解决问题的关键在:抽象?我们让模块依赖于一个固定的抽象?q样它就是不可以修改?同时,通过q个抽象体派?我们可以扩展此模块的行为功?如此,q样设计的程序只通过增加代码来变化而不是通过更改现有代码来变?前面提到的修改的副作用就没有? "开-?原则如果从另外一个角度讲q?是所谓的"对可变性封装原?(Principle of Encapsulation of Variation, EVP).讲的是找C个系l的可变因素,之装h.在我们考虑一个系l的时?我们不要把关注的焦点攑֜什么会D设计发生变化?而是考虑允许什么发生变化而不让这一变化D重新设计.也就是说,我们要积极的面对变化,U极的包容变?而不是逃避. [SHALL01]这一思想用一句话ȝ?"扑ֈ一个系l的可变因素,它装h",q将它命名ؓ"对可变性的装原则". "对可变性的装原则"意味者两? "对可变性的装原则"从工E的角度说明了如何实现OCP.如果按照q个原则来设?那么pȝ应当是遵守OCP? 但是现实往往是残L,我们不可?00%的遵守OCP,但是我们要向q个目标来靠q?设计者要对设计的模块对何U变化封闭做出选择.http://blog.csdn.net/kxy/archive/2005/06/27/405013.aspx
]]>
2005.06.28 来自Q?a title="http://mypm.net/" >http://mypm.net/ 作者:吴超
对于软g的需求调研活动,虽然曄写过三篇相关的需求管理文章,出发角度是从整体的需求管理过E考虑Q在引入CMMQ二Q需求管理KPAzd的基上,列D了如何进行需求调研前的需求管理计划活动;在失败的目中,扑և规范和管理Y仉求过E的兛_点及需求关联的模型架构Q这些可以参考以前写q的《CMM 需求管理实늻验记录谈》、《从CMM角度考虑需求管理计划》、《如何用CRC模型来确定需求》)。一直以来,感觉自己在经q几个项目试验的基础上对于Y件的需求管理应该是有一定的基础和经验了Q然而在最q参与的一个大型项目过E中Q在新加坡项目经理的引导与帮助下Q对于Y仉求调研又有了更深一层的体会和认识;ȝ出需求调研中?W+1H定律Q在此把自己的一些过E和l验描述出来Q希望能与各同仁一起分享与讨论?
目背景Q?br>一个中型的企业信息化项目,其中乙方的项目经理是一个拥有PMP证书的资深项目管理h员。甲方的目l理是一个有着丰富目实施和管理经验的新加坡项目管理h员。(在这里需要补充的Ӟ在调研生冲H过E中Q外ch员如何用自己的经验和技巧,让乙方完全可以接Ӟ
目成员Q?/strong> 工作内容Q?/strong> q程描述Q?br>目启动后,乙方的项目经理列了一份详l的需求调研时间表、调研阶D|果目录清单、界面成果等的计划内容,可以用一?“赞?字来形容Q从计划上看Q乙方的目l理计划真的是完无~;在与用户q行业务需求调研的zd中,乙方不仅记录下目前用L有的业务程Q包括目前流E的局限性,程的执行性等斚wQ还为用戯行了来pȝ程的规划,的确是一个不错的开始。可是在乙方提交光D늚需求分析文和界面Ӟ却发C者存在了U种的冲H和矛盾Q我们无法将需求分析文档与界面l合在一赗此Ӟ乙方的项目经理解释是因ؓ文档比界面细Q所以二者存在一些理解上的差异。而我们甲方却总觉得有些不太对Ԍ但因为同样存在着对用hE细节的不熟悉,所以我们也提不出具体的问题Q直到有一天,跟着乙方一起做用户的需求活动后Q从乙方目l理的提问方面,我们l于明白Z么他们会做出q样的文和界面? 首先Q乙斚w目经理对用户的提问是没有序列的,我们所谓的序列是目l理的逻辑是否清晰Q除了问及目前的程外,最重要的引入项目(x的Y件系l)的目的,所需辑ֈ的效果,可以对用戯助的东东Q而这些乙方的目l理一字未提与问,只记录用h说的q程、局限和要求。这P乙方目l理在分析与规划pȝ的需求时Q就没有一个明的目的性和方向性,q里p引入W一个W定律---WHY定律?strong>WHY是Z么用戯引入pȝQ引入新的信息系l对用户有什么帮助,在M工作效能上如何实C个最l的l果QWHY定律是要求在需求开始时Q项目经理就应该明确的,q个目是ؓ了改q用户工作效率;提高部门间的协作机制Q加快对客户反应的体pL务;提升企业的竞争力{等?/strong>有了q么一个WHY引入思想Q?strong>目l理可以理清用hl要的是可以提供l他们什么样的系l,在系l的定位和徏立上Q就有一个明地最l目标?/strong> 其次Q有了一个M的目标性,从各业务程的要求入手,引入W二个W定律---WHAT定律QWHAT则是q个pȝ要做什么?实现什么?是乙方目l理提出的各业务程问题、流E局限性问题、系l要解决的问题等Q在q个WHAT的基上,把系l划分成各功能模块,逐步弄清模块程需求、功能需求、结构需求。引入WHAT定律可以让我们了解到pȝ的初步需求? 再次Q引入第三、四、五个定?--WHO、WHEN、WHERE定律Q这个阶D其实就是需求细化阶D,在WHAT定律的基上,l分pȝ的用户需求:分析什么hQ在什么时_什么阶D可以或必须操作q个功能Q结合前面的WHAT定律Q理清系l的程阶段划分Q记录ƈ分析pȝ功能实现的细节,在这个阶D就可以产生pȝ需求的用例图(Use CaseQ,作ؓ下阶D设计的依据? 最后,是所谓的1H定律---HOW定律Q就是怎样实现pȝ了,在前面的WHY、WHAT、WHO、WHEN、WHERE基础上,我们已经搭徏了一个非常好的系l需求基框架Q如何在q些用户需求的基础上,分析pȝ的需求,如何q行需求规格的分析与下阶段的设计、实现工作,是HOW TO ACCOMPLISH THE SYSTEM了? 在需求阶D引入这5W+1H的定律,在一定程度上保证了系l需求的准确性,也得项目经理或需求分析h员可以非常有序的有条理的开展需求挖掘和调研zdQ这L安排用户在配合上也非常清晎ͼ知道如何与项目h员配合。其后,在我们的下,乙方改进了工作方式,理清了一些工作序列,不过在最l文的提交上,乙方的项目经理ؓ了迎合我们的需求,一直对需求文档的格式与内容进行修改,没有保持需求分析中应该有的从粗到细的阶层分析,也导致其需求分析中的不定性因素较多,后期的设计工作展开不顺Q这些算后话Q希望能在以后的外包理斚wQ就存在的这些问题进行其它的分析和讨论?/p>
甲方Q外包项目经理、外包项目管理h?br>乙方Q项目经理、系l分析员、界面制作h?
目需求阶D늚zdQ对于系l的需求,甲乙双方与最l用戯达成一_甲方作ؓ外包理者,主要是对乙方目l的目q度、项目阶D|果进行跟t与验收Q以保证目在预期的旉内完成预期的工作d?
Dirty Read | NonRepeatabe Read | Phantom Read | |
Read uncommitted | Possible | Possible | Possible |
Read committed | not possible | Possible | Possible |
Repeatabe read | not possible | not possible | Possible |
Seriaizabe | not possible | not possible | not possible |
ORACE的隔ȝ?/b>
ORACE提供了SQ92标准中的read committed和seriaizabeQ同时提供了非SQ92标准的read-ony?
read committedQ?/strong> seriaizabeQ(串行执行事务Qƈ发性最) 如果有在seriaizabe事务开始时未提交的事务在seriaizabe事务l束之前修改了seriaizabe事务要修改的行q进行了提交Q则seriaizabe事务不会dq些变更Q因此发生无法序列化讉K的错误。(换一U解释方法:只要在seriaizabe事务开始到l束之间有其他事务对seriaizabe事务要修改的东西q行了修改ƈ提交了修改,则发生无法序列化讉K的错?/strong>。) If a serializable transaction contains data manipulation language (DML) that attempts to update any resource that may have been updated in a transaction uncommitted at the start of the serializable transaction, Qƈ且修改在后来被提交而没有回滚)Qthen the DML statement fails. q回的错误是ORA-08177: Cannot serialize access for this transaction? ORACE在数据块中记录最q对数据行执行修Ҏ作的N个事务的信息Q目的是定本事务开始时Q是否存在未提交的事务修改了本事务将要修改的行。具体见英文Q? Oracle permits a serializable transaction to modify a data row only if it can determine that prior changes to the row were made by transactions that had committed when the serializable transaction began. To make this determination efficiently, Oracle uses control information stored in the data block that indicates which rows in the block contain committed and uncommitted changes. In a sense, the block contains a recent history of transactions that affected each row in the block. The amount of history that is retained is controlled by the INITRANS parameter of CREATE TABLE and ALTER TABLE. Under some circumstances, Oracle may have insufficient history information to determine whether a row has been updated by a "too recent" transaction. This can occur when many transactions concurrently modify the same data block, or do so in a very short period. You can avoid this situation by setting higher values of INITRANS for tables that will experience many transactions updating the same blocks. Doing so will enable Oracle to allocate sufficient storage in each block to record the history of recent transactions that accessed the block. The INITRANS ParameterQOracle stores control information in each data block to manage access by concurrent transactions. Therefore, if you set the transaction isolation level to serializable, you must use the ALTER TABLE command to set INITRANS to at least 3. This parameter will cause Oracle to allocate sufficient storage in each block to record the history of recent transactions that accessed the block. Higher values should be used for tables that will undergo many transactions updating the same blocks. read-onyQ?/strong> read committed和seriaizabe的区别和联系Q?/strong> 事务1先于事务2开始,q保持未提交状态。事?惌修改正被事务1修改的行。事?{待。如果事?回滚Q则事务2Q不论是read committedq是seriaizabe方式Q进行它惌做的修改。如果事?提交Q则当事?是read committed方式Ӟq行它想要做的修改;当事?是seriaizabe方式Ӟp|q报错“Cannot seriaize access”,因ؓ事务2看不见事?提交的修改,且事?惛_事务1修改的基上再做修攏V? 即seriaizabe不允许存在事务嵌? 具体见英文: Both read committed and serializable transactions use row-level locking, and both will wait if they try to change a row updated by an uncommitted concurrent transaction. The second transaction that tries to update a given row waits for the other transaction to commit or roll back and release its lock. If that other transaction rolls back, the waiting transaction (regardless of its isolation mode) can proceed to change the previously locked row, as if the other transaction had not existed. However, if the other (blocking) transaction commits and releases its locks, a read committed transaction proceeds with its intended update. A serializable transaction, however, fails with the error "Cannot serialize access", because the other transaction has committed a change that was made since the serializable transaction began. read committed和seriaizabe可以在ORACEq行服务器中使用? 关于SET TRANSACTION READ WRITEQread write和read committed 应该是一L。在L面,它们都避免了脏读Q但都无法实现重复读。虽然没有文说明read write在写斚w与read committed一_但显然它在写的时候会加排他锁以避免更C失。在加锁的过E中Q如果遇到待锁定资源无法锁定Q应该是{待而不是放弃。这与read committed一致? 语句U的M致? 事务U的M致? 讄隔离U别 讄一个事务的隔离U别 讄增个会话的隔ȝ? Application designers and developers should choose an isolation level based on application performance and consistency needs as well as application coding requirements. For environments with many concurrent users rapidly submitting transactions, designers must assess transaction performance requirements in terms of the expected transaction arrival rate and response time demands. Frequently, for high-performance environments, the choice of isolation levels involves a trade-off between consistency and concurrency. For many applications, read committed is the most appropriate isolation level. Read committed isolation can provide considerably more concurrency with a somewhat increased risk of inconsistent results due to phantoms and non-repeatable reads for some transactions. Many high-performance environments with high transaction arrival rates require more throughput and faster response times than can be achieved with serializable isolation. Other environments that supports users with a very low transaction arrival rate also face very low risk of incorrect results due to phantoms and nonrepeatable reads. Read committed isolation is suitable for both of these environments. 两种情况Q(1Q在事务量大、高性能的计环境,需要更高的吞吐量和响应旉Q(2Q事务数,q且发生qd和不可重复读的几率的比较? Oracle read committed isolation provides transaction set consistency for every query. That is, every query sees data in a consistent state. Therefore, read committed isolation will suffice for many applications that might require a higher degree of isolation if run on other database management systems that do not use multiversion concurrency control. Read committed isolation mode does not require application logic to trap the "Cannot serialize access" error and loop back to restart a transaction. In most applications, few transactions have a functional need to issue the same query twice, so for many applications protection against phantoms and non-repeatable reads is not important. Therefore many developers choose read committed to avoid the need to write such error checking and retry code in each transaction. Oracle's serializable isolation is suitable for environments where there is a relatively low chance that two concurrent transactions will modify the same rows and the long-running transactions are primarily read-only. It is most suitable for environments with large databases and short transactions that update only a few rows. Q?Q适合于很存在两个事务同时修改同一条记录的情况 Q?Q长事务以只Mؓ? Q?Q大型数据库q且每个短事务只修改很少的记? Serializable isolation mode provides somewhat more consistency by protecting against phantoms and nonrepeatable reads and can be important where a read/write transaction executes a query more than once. Unlike other implementations of serializable isolation, which lock blocks for read as well as write, Oracle provides nonblocking queries and the fine granularity of row-level locking, both of which reduce write/write contention. For applications that experience mostly read/write contention, Oracle serializable isolation can provide significantly more throughput than other systems. Therefore, some applications might be suitable for serializable isolation on Oracle but not on other systems. All queries in an Oracle serializable transaction see the database as of a single point in time, so this isolation level is suitable where multiple consistent queries must be issued in a read/write transaction. A report-writing application that generates summary data and stores it in the database might use serializable mode because it provides the consistency that a 作者联pL? E TaoPuyin
Choice of Isolation Level
Read Committed Isolation
Serializable Isolation
READ
ONLY
transaction provides, but also allows INSERT
, UPDATE
, and DELETE
.
G System Engineer Oracle DBA
G Fuji Xerox China Limited (Shanghai)
]]>
~存是介于应用程序和物理数据源之_其作用是Z降低应用E序对物理数据源讉K的频ơ,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复Ӟ应用E序在运行时从缓存读写数据,在特定的时刻或事件会同步~存和物理数据源的数据?
~存的介质一般是内存Q所以读写速度很快。但如果~存中存攄数据量非常大Ӟ也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质,q要考虑到管理缓存的q发讉K和缓存数据的生命周期?
Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分ؓ两类Q内|缓存和外置~存?
Session的缓存是内置的,不能被卸载,也被UCؓHibernate的第一U缓存?/strong> SessionFactory的内|缓存和Session的缓存在实现方式上比较相|前者是SessionFactory对象的一些集合属性包含的数据Q后者是指Session的一些集合属性包含的数据。SessionFactory的内|缓存中存放了映元数据和预定义SQL语句Q映元数据是映文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶D|据映元数据推导出来QSessionFactory的内|缓存是只读的,应用E序不能修改~存中的映射元数据和预定义SQL语句Q因此SessionFactory不需要进行内|缓存与映射文g的同步? SessionFactory的外|缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用q个插g。外|缓存的数据是数据库数据的拷贝,外置~存的介质可以是内存或者硬盘?strong>SessionFactory的外|缓存也被称为Hibernate的第二~存?/strong> Hibernate的这两~存都位于持久化层,存放的都是数据库数据的拷贝,那么它们之间的区别是什么呢Qؓ了理解二者的区别Q需要深入理解持久化层的~存的两个特性:~存的范围和~存的ƈ发访问策略?/strong> ~存的范围决定了~存的生命周期以及可以被谁访问。缓存的范围分ؓ三类? 1 事务范围Q缓存只能被当前事务讉K。缓存的生命周期依赖于事务的生命周期Q当事务l束Ӟ~存也就l束生命周期。在此范围下Q缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,~存内的数据通常采用怺兌的的对象形式? 2 q程范围Q缓存被q程内的所有事务共享。这些事务有可能是ƈ发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进E的生命周期Q进E结束时Q缓存也q束了生命周期。进E范围的~存可能会存攑֤量的数据Q所以存攄介质可以是内存或盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据Ş式。松散的对象数据形式有点cM于对象的序列化数据,但是对象分解为松散的法比对象序列化的算法要求更快? 3 集群范围Q在集群环境中,~存被一个机器或者多个机器的q程׃n。缓存中的数据被复制到集环境中的每个进E节点,q程间通过q程通信来保证缓存中的数据的一致性,~存中的数据通常采用对象的松散数据Ş式? 对大多数应用来说Q应该慎重地考虑是否需要用集范围的~存Q因问的速度不一定会比直接访问数据库数据的速度快多? 持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据,q可以到q程范围或集范围的~存内查询,如果q是没有查到Q那么只有到数据库中查询。事务范围的~存是持久化层的W一U缓存,通常它是必需的;q程范围或集范围的~存是持久化层的W二U缓存,通常是可选的? 当多个ƈ发的事务同时讉K持久化层的缓存的相同数据Ӟ会引起ƈ发问题,必须采用必要的事务隔L施? 在进E范围或集群范围的缓存,即第二~存Q会出现q发问题。因此可以设定以下四U类型的q发讉K{略Q每一U策略对应一U事务隔ȝ别? 事务型:仅仅在受理环境中适用。它提供了Repeatable Read事务隔离U别。对于经常被M很少修改的数据,可以采用q种隔离cdQ因为它可以防止脏读和不可重复读q类的ƈ发问题? d型:提供了Read Committed事务隔离U别。仅仅在非集的环境中适用。对于经常被M很少修改的数据,可以采用q种隔离cdQ因为它可以防止脏读q类的ƈ发问题? 非严D写型Q不保证~存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能,必须数据配置一个很短的数据q期旉Q从而尽量避免脏诅R对于极被修改Qƈ且允许偶脏ȝ数据Q可以采用这Uƈ发访问策略? 只读型:对于从来不会修改的数据,如参考数据,可以使用q种q发讉K{略? 事务型ƈ发访问策略是事务隔离U别最高,只读型的隔离U别最低。事务隔ȝ别越高,q发性能p低? 什么样的数据适合存放到第二~存中? 1 很少被修改的数据 2 不是很重要的数据Q允许出现偶ƈ发的数据 3 不会被ƈ发访问的数据 4 参考数? 不适合存放到第二~存的数据? 1 l常被修改的数据 2 财务数据Q绝对不允许出现q发 3 与其他应用共享的数据? 如前所qͼHibernate提供了两U缓存,W一U是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的~存是事务范围的~存。第一U缓存是必需的,不允许而且事实上也无法協R。在W一U缓存中Q持久化cȝ每个实例都具有唯一的OID? W二U缓存是一个可插拔的的~存插gQ它是由SessionFactory负责理。由于SessionFactory对象的生命周期和应用E序的整个过E对应,因此W二U缓存是q程范围或者集范围的~存。这个缓存中存放的对象的松散数据。第二对象有可能出现ƈ发问题,因此需要采用适当的ƈ发访问策略,该策略ؓ被缓存的数据提供了事务隔ȝ别。缓存适配器用于把具体的缓存实现Y件与Hibernate集成。第二~存是可选的Q可以在每个cL每个集合的粒度上配置W二U缓存? Hibernate的二U缓存策略的一般过E如下: 1) 条g查询的时候,L发出一条select * from table_name where ? Q选择所有字D)q样的SQL语句查询数据库,一ơ获得所有的数据对象? 2) 把获得的所有数据对象根据ID攑օ到第二~存中? 3) 当HibernateҎID讉K数据对象的时候,首先从Session一U缓存中查;查不刎ͼ如果配置了二U缓存,那么从二U缓存中查;查不刎ͼ再查询数据库Q把l果按照ID攑օ到缓存? 4) 删除、更新、增加数据的时候,同时更新~存? Hibernate的二U缓存策略,是针对于ID查询的缓存策略,对于条g查询则毫无作用。ؓ此,Hibernate提供了针Ҏ件查询的Query~存? Hibernate的Query~存{略的过E如下: 1) Hibernate首先Ҏq些信息l成一个Query KeyQQuery Key包括条g查询的请求一般信息:SQL, SQL需要的参数Q记录范_起始位置rowStartQ最大记录个数maxRows)Q等? 2) HibernateҎq个Query Key到Query~存中查扑֯应的l果列表。如果存在,那么q回q个l果列表Q如果不存在Q查询数据库Q获取结果列表,把整个结果列表根据Query Key攑օ到Query~存中? 3) Query Key中的SQL涉及C些表名,如果q些表的M数据发生修改、删除、增加等操作Q这些相关的Query Key都要从缓存中清空?持久化层的缓存的范围
持久化层的缓存的q发讉K{略
Hibernate的二U缓?/b>
很清楚,q有源码下蝲
http://www.xd-tech.com.cn/blog/article.asp?id=34
一般的情况下我们都是用IE或者Navigator览器来讉K一个WEB服务器,用来览面查看信息或者提交一些数据等{。所讉K的这些页面有的仅仅是一些普通的面Q有的需要用L录后方可使用Q或者需要认证以及是一些通过加密方式传输Q例如HTTPS。目前我们用的览器处理这些情况都不会构成问题。不q你可能在某些时候需要通过E序来访问这L一些页面,比如从别人的|页中“偷”一些数据;利用某些站点提供的页面来完成某种功能Q例如说我们想知道某个手机号码的归属地而我们自己又没有q样的数据,因此只好借助其他公司已有的网站来完成q个功能Q这个时候我们需要向|页提交手机Lq从q回的页面中解析出我们想要的数据来。如果对方仅仅是一个很单的面Q那我们的程序会很简单,本文也就没有必要大张旗鼓的在q里费口舌。但是考虑C些服务授权的问题Q很多公司提供的面往往q不是可以通过一个简单的URL可以访问的Q而必ȝq注册然后登录后方可使用提供服务的页面,q个时候就涉及?COOKIE问题的处理。我们知道目前流行的***|术例如ASP、JSP无不是通过COOKIE来处理会话信息的。ؓ了我们的程序能使用别h所提供的服务页面,p求程序首先登录后再访问服务页面,q过E就需要自行处理cookieQ想惛_你用java.net.HttpURLConnection 来完成这些功能时是多么恐怖的事情啊!况且q仅仅是我们所说的固的WEB服务器中的一个很常见的“顽固”!再有如通过HTTP来上传文件呢Q不需要头|q些问题有了“它”就很容易解决了Q?
我们不可能列举所有可能的固Q我们会针对几种最常见的问题进行处理。当然了Q正如前面说到的Q如果我们自׃?java.net.HttpURLConnection来搞定这些问题是很恐怖的事情Q因此在开始之前我们先要介l一下一个开放源码的目Q这个项目就?Apache开源组l中的httpclientQ它隶属于Jakarta的commons目Q目前的版本?.0RC2。commons下本来已l有一个net的子目Q但是又把httpclient单独提出来,可见http服务器的讉Kl非易事?
Commons-httpclient目是专门设计来简化HTTP客户端与服务器进行各U通讯~程。通过它可以让原来很头疼的事情现在L的解冻I例如你不再管是HTTP或者HTTPS的通讯方式Q告诉它你想使用HTTPS方式Q剩下的事情交给 httpclient替你完成。本文会针对我们在编写HTTP客户端程序时l常到的几个问题进行分别介l如何用httpclient来解军_们,Z让读者更快的熟悉q个目我们最开始先l出一个简单的例子来读取一个网늚内容Q然后@序渐q解x前进中的所形侍?/font>
1Q?d|页(HTTP/HTTPS)内容
下面是我们给出的一个简单的例子用来讉K某个面
/*
* Created on 2003-12-14 by Liudong
*/
package http.demo;
import java.io.IOException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
/**
* 最单的HTTP客户?用来演示通过GET或者POST方式讉K某个面
* @author Liudong
*/
public class SimpleClient {
public static void main(String[] args) throws IOException
{
HttpClient client = new HttpClient();
//讄代理服务器地址和端?nbsp;
//client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);
//使用GETҎQ如果服务器需要通过HTTPSq接Q那只需要将下面URL中的http换成https
HttpMethod method = new GetMethod(" //使用POSTҎ //HttpMethod method = new PostMethod(" client.executeMethod(method); //打印服务器返回的状? System.out.println(method.getStatusLine()); //打印q回的信? System.out.println(method.getResponseBodyAsString()); //释放q接 method.releaseConnection(); } 在这个例子中首先创徏一个HTTP客户?HttpClient)的实例,然后选择提交的方法是GET或?POSTQ最后在HttpClient实例上执行提交的ҎQ最后从所选择的提交方法中d服务器反馈回来的l果。这是使用HttpClient的基本流E。其实用一行代码也可以搞定整个请求的q程Q非常的单! 2Q?以GET或者POST方式向网|交参? 其实前面一个最单的CZ中我们已l介l了如何使用GET或者POST方式来请求一个页面,本小节与之不同的是多了提交时讑֮面所需的参敎ͼ我们知道如果是GET的请求方式,那么所有参数都直接攑ֈ面的URL后面用问号与面地址隔开Q每个参数用&隔开Q例如:http://java.sun.com?name=liudong&mobile=123456Q但是当使用POSTҎ时就会稍微有一点点ȝ。本节的例子演C向如何查询手机L所在的城市Q代码如下: /* * Created on 2003-12-7 by Liudong */ package http.demo; import java.io.IOException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.*; /** * 提交参数演示 * 该程序连接到一个用于查询手机号码所属地的页? * 以便查询LD?330227所在的省䆾以及城市 * @author Liudong */ public class SimpleHttpClient { public static void main(String[] args) throws IOException { HttpClient client = new HttpClient(); client.getHostConfiguration().setHost(" HttpMethod method = getPostMethod();//使用POST方式提交数据 client.executeMethod(method); //打印服务器返回的状? System.out.println(method.getStatusLine()); //打印l果面 String response = new String(method.getResponseBodyAsString().getBytes("8859_1")); //打印q回的信? System.out.println(response); method.releaseConnection(); } /** * 使用GET方式提交数据 * @return */ private static HttpMethod getGetMethod(){ return new GetMethod("/simcard.php?simcard=1330227"); } /** * 使用POST方式提交数据 * @return */ private static HttpMethod getPostMethod(){ PostMethod post = new PostMethod("/simcard.php"); NameValuePair simcard = new NameValuePair("simcard","1330227"); post.setRequestBody(new NameValuePair[] { simcard}); return post; } } 在上面的例子中页?a >http://www.imobile.com.cn/simcard.php 3Q?处理面重定? 在JSP/Servlet~程中response.sendRedirectҎ是使用HTTP协议中的重定向机制。它与JSP中的<jsp:forward ?gt;的区别在于后者是在服务器中实现页面的跌{Q也是说应用容器加载了所要蟩转的面的内容ƈq回l客LQ而前者是q回一个状态码Q这些状态码的可能D下表Q然后客Ld需要蟩转到的页面的URLq新加载新的页面。就是这样一个过E,所以我们编E的时候就要通过 HttpMethod.getStatusCode()Ҏ判断q回值是否ؓ下表中的某个值来判断是否需要蟩转。如果已l确认需要进行页面蟩转了Q那么可以通过dHTTP头中的location属性来获取新的地址? 状态码 下面的代码片D|C如何处理页面的重定? client.executeMethod(post); System.out.println(post.getStatusLine().toString()); post.releaseConnection(); //查是否重定向 int statuscode = post.getStatusCode(); if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY) || (statuscode == HttpStatus.SC_SEE_OTHER) || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) { //d新的URL地址 Header header = post.getResponseHeader("location"); if (header != null) { String newuri = header.getValue(); if ((newuri == null) || (newuri.equals(""))) newuri = "/"; GetMethod redirect = new GetMethod(newuri); client.executeMethod(redirect); System.out.println("Redirect:"+ redirect.getStatusLine().toString()); redirect.releaseConnection(); } else System.out.println("Invalid redirect"); } 我们可以自行~写两个JSP面Q其中一个页面用response.sendRedirectҎ重定向到另外一个页面用来测试上面的例子? 4Q?模拟输入用户名和口oq行d 本小节应该说是HTTP客户端编E中最常碰见的问题Q很多网站的内容都只是对注册用户可见的,q种情况下就必须要求使用正确的用户名和口令登录成功后Q方可浏览到惌的页面。因为HTTP协议是无状态的Q也是q接的有效期只限于当前请求,h内容l束后连接就关闭了。在q种情况下ؓ了保存用Ld信息必须使用到Cookie机制。以JSP/ServletZQ当览器请求一个JSP或者是Servlet的页面时Q应用服务器会返回一个参敎ͼ名ؓjsessionidQ因不同应用服务器而异Q,值是一个较长的唯一字符串的CookieQ这个字W串g是当前讉K该站点的会话标识。浏览器在每讉K该站点的其他面时候都要带上jsessionidq样的Cookie信息Q应用服务器Ҏdq个会话标识来获取对应的会话信息? 对于需要用L录的|站Q一般在用户d成功后会用戯料保存在服务器的会话中,q样当访问到其他的页面时候,应用服务器根据浏览器送上的Cookie中读取当前请求对应的会话标识以获得对应的会话信息Q然后就可以判断用户资料是否存在于会话信息中Q如果存在则允许讉K面Q否则蟩转到d面中要求用戯入帐号和口oq行d。这是一般用JSP开发网站在处理用户d的比较通用的方法? q样一来,对于HTTP的客L来讲Q如果要讉K一个受保护的页面时必L拟浏览器所做的工作Q首先就是请求登录页面,然后dCookie|再次hd面q加入登录页所需的每个参敎ͼ最后就是请求最l所需的页面。当然在除第一ơ请求外其他的请求都需要附带上 Cookie信息以便服务器能判断当前h是否已经通过验证。说了这么多Q可是如果你使用httpclient的话Q你甚至q一行代码都无需增加Q你只需要先传递登录信息执行登录过E,然后直接讉K惌的页面,跟访问一个普通的面没有M区别Q因为类HttpClient已经帮你做了所有该做的事情了,太棒了!下面的例子实Cq样一个访问的q程? /* * Created on 2003-12-7 by Liudong */ package http.demo; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.cookie.*; import org.apache.commons.httpclient.methods.*; /** * 用来演示d表单的示? * @author Liudong */ public class FormLoginDemo { static final String LOGON_SITE = "localhost"; static final int LOGON_PORT = 8080; public static void main(String[] args) throws Exception{ HttpClient client = new HttpClient(); client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT); //模拟d面login.jsp->main.jsp PostMethod post = new PostMethod("/main.jsp"); NameValuePair name = new NameValuePair("name", "ld"); NameValuePair pass = new NameValuePair("password", "ld"); post.setRequestBody(new NameValuePair[]{name,pass}); int status = client.executeMethod(post); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); //查看cookie信息 CookieSpec cookiespec = CookiePolicy.getDefaultSpec(); Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies()); if (cookies.length == 0) { System.out.println("None"); } else { for (int i = 0; i < cookies.length; i++) { System.out.println(cookies[i].toString()); } } //讉K所需的页面main2.jsp GetMethod get = new GetMethod("/main2.jsp"); client.executeMethod(get); System.out.println(get.getResponseBodyAsString()); get.releaseConnection(); } } 5Q?提交XML格式参数 提交XML格式的参数很单,仅仅是一个提交时候的ContentType问题Q下面的例子演示从文件文件中dXML信息q提交给服务器的q程Q该q程可以用来试Web服务? import java.io.File; import java.io.FileInputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.PostMethod; /** * 用来演示提交XML格式数据的例? */ public class PostXMLClient { public static void main(String[] args) throws Exception { File input = new File(“test.xml?; PostMethod post = new PostMethod(“http://localhost:8080/httpclient/xml.jsp?; // 讄h的内容直接从文g中读? post.setRequestBody(new FileInputStream(input)); if (input.length() < Integer.MAX_VALUE) post.setRequestContentLength(input.length()); else post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED); // 指定h内容的类? post.setRequestHeader("Content-type", "text/xml; charset=GBK"); HttpClient httpclient = new HttpClient(); int result = httpclient.executeMethod(post); System.out.println("Response status code: " + result); System.out.println("Response body: "); System.out.println(post.getResponseBodyAsString()); post.releaseConnection(); } } 6Q?通过HTTP上传文g httpclient使用了单独的一个HttpMethod子类来处理文件的上传Q这个类是MultipartPostMethodQ该cdl封装了文g上传的细节,我们要做的仅仅是告诉它我们要上传文g的全路径卛_Q下面的代码片段演示如何使用q个cR? MultipartPostMethod filePost = new MultipartPostMethod(targetURL); filePost.addParameter("fileName", targetFilePath); HttpClient client = new HttpClient(); //׃要上传的文g可能比较?因此在此讄最大的q接时旉 client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); int status = client.executeMethod(filePost); 上面代码中,targetFilePath即ؓ要上传的文g所在的路径? 7Q?讉K启用认证的页? 我们l常会碰到这L面Q当讉K它的时候会弹出一个浏览器的对话框要求输入用户名和密码后方可,q种用户认证的方式不同于我们在前面介l的Z表单的用戯n份验证。这是HTTP的认证策略,httpclient支持三种认证方式包括Q基本、摘要以及NTLM认证。其中基本认证最单、通用但也最不安全;摘要认证是在HTTP 1.1中加入的认证方式Q而NTLM则是微Y公司定义的而不是通用的规范,最新版本的NTLM是比摘要认证q要安全的一U方式? 下面例子是从httpclient的CVS服务器中下蝲的,它简单演C如何访问一个认证保护的面Q? import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.methods.GetMethod; public class BasicAuthenticationExample { public BasicAuthenticationExample() { } public static void main(String[] args) throws Exception { HttpClient client = new HttpClient(); client.getState().setCredentials( " "realm", new UsernamePasswordCredentials("username", "password") ); GetMethod get = new GetMethod(" get.setDoAuthentication( true ); int status = client.executeMethod( get ); System.out.println(status+""+ get.getResponseBodyAsString()); get.releaseConnection(); } } 8Q?多线E模式下使用httpclient 多线E同时访问httpclientQ例如同时从一个站点上下蝲多个文g。对于同一个HttpConnection 同一个时间只能有一个线E访问,Z保证多线E工作环境下不生冲H,httpclient使用了一个多U程q接理器的c: MultiThreadedHttpConnectionManagerQ要使用q个cd单,只需要在构造HttpClient实例的时候传入即可,代码如下Q?pre>MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
以后管讉Kclient实例卛_?
参考资料:
httpclient首页Q?nbsp; http://jakarta.apache.org/commons/httpclient/
}
对应HttpServletResponse的常?br> 详细描述
301 SC_MOVED_PERMANENTLY
面已经怹Ud另外一个新地址
302 SC_MOVED_TEMPORARILY
面暂时Ud到另外一个新的地址
303 SC_SEE_OTHER
客户端请求的地址必须通过另外的URL来访?br>307 SC_TEMPORARY_REDIRECT 同SC_MOVED_TEMPORARILY
关于NTLM是如何工作: http://davenport.sourceforge.net/ntlm.html
]]>
1Q?nbsp;您好Q请先向我们的网友简单做一下自我介l好吗?
我的|名?#8220;银狐999”Q目前就职于TIBCO中国研发中心Q负责tibco administrator server底层lg的维护?br> 我的工作l历即简单又复杂。简单是因ؓq五q来Q我几乎都在围绕着Workflow相关的技术在发展Q而复杂则是更换了好几家公司,从事q电子政务领域,数据集成领域、业务基软gq_、协同办公^台等多方面的工作?br> 我是个很Open的hQ这得益于早期javaunion论坛上那帮伙_他们的无U奉献让我明白了Q开攄技术交才能让我们学得更多Q懂得更多。所以这几年来,我一直坚持写技术心得,写工作流研究心得Qƈ他们无U的公开在我的主和Blog上?/p>
2Q现在谈C业流E管理,l常会出现EAI、WF、BPMq些关键词。您做ؓq方面的专家Q请解释一下它们之间的关系以及不同好吗Q?/strong> Workflow和BPM之间的区别是比较含糊的。所以在国外Q一般不用Workflow去表C工作流应用。Workflow只是用于表示“工作技术(Workflow TechnologyQ?#8221;及这个领域范_而用“Process”来表C流E?br> 我们所熟知的工作流理联盟l织QWfMCQ,目前几乎也只是提BPMQ其程描述语言XPDL也是一直采用Processq个元素的?/p>
上面的说法似乎是q于专业化了一炏V那让我们回ֈ上个世纪九十q代Q诞生了“Process
Reengineering”q个概念Q单那个时候只是一阵风Q因为技术跟不上Q所以大多都只停留在理层概c而在九十q代Qworkflow技术和?
用却蓬勃发展Q可谓是癑֮争鸣Q蒸蒸日上? 事实上,如何LqC务过E?#8220;Business Process”Q一直还是个争论不休的话题,也因此存在几U标准。主要是以WfMCZ表的XPDLQOASISZ表的BPELQOMGZ表的BPMN和BPDM?br> 虽然描述q程“Process”的标准ƈ不一P但是围绕q程定义、过E仿真、过E执行、过E监控、过E分析、过E优化这几个斚w为核心的BPM SolutionQ这一斚w各家几乎都是相同的,只是实现技术不同?/p>
3Q工作流理主要可以帮助企业解决什么样的问题呢Q?/strong> 5Q从个h角度Ԍ国内的工作流理的品他们各自的特点是什么? 国内厂商的优势在?#8220;业务”?#8220;客户化项目实?#8221;。如果从单纯程q个角度Q我惛_内品的优势则主要在于两斚wQ?br> W一Q?#8220;客户应用的本地化程特色”Q比如上面提到的“回退”“会签”“回退”“取回”“自由?#8221;“d辅办”{等特色Q?br> W二Q?#8220;本地化组l模型和权限”Q国内的l织模型是国外品很隄解和越的,q也是ؓ什么国内工作流应用市场Q几乎都q是主要被国内自q厂商占据的一个主要原因之一?br> 8Q企业部|一套工作流理pȝ遇到的最大的困难是来自技术方面吗Q你认ؓ最大的困难在哪里?如何克服Q?/strong> 国内企业实施工作最大的困难来自于两个方面:
EAI
我想是比较容易理解和区分的,全称是企业应用集成(Enterprise Application
IntegrationQ。目前EAI更多的是Z消息中间件服务(企业消息ȝInformation
BusQ,利用多种适配装置完成分散的、分布式的应用的整合。目前比较流行的ESB概念Q和EAI是有一定融合的Q但ESB更多的是站在业务程服务的角
度,而不单单是消息或应用?/p>
2000左右Q工作流技术应用已l非常成熟,数据集成Q应用集成也发展q速。随之也推动了业务过E管理、整合、统计、优化等斚w的应用需求。在q样一U市场需求下Q必焉要一个含义更q泛、更偏管理和应用性的概念来服务于客户Q这p生了“BPM”q个概念?br> 如果Workflow是早期h们ؓ了解?#8220;办公自动?#8221;“程自动?#8221;而诞生的应用技术和解决Ҏ的话Q那么BPM则是Z“对全局性的业务分析、整?#8221;Q以?#8220;能够Zq些分析提供对上层管理决{的支持”的一U应用技术和解决Ҏ?/p>
可以帮助企业更清晰、更灉|的管理业务流E?br>
4Q目前,国内企业工作管理应用环境的特点是什么?
目前国内的工作流应用q依然围l电子政务和协同办公的审批类程应用Z。当Ӟ也存在一定的商业化业务性流E,比如q两q比较火热的物流领域的仓储管理流E等?/p>
在国内,工作应用与l织理是密切不可分Q甚臛_很多时候,我们可以_是ؓl织理服务的。受到国内的理更多的偏向于?#8220;?#8221;为本的思想Q所以国内的程存在很严重的“Zؓ影响”Q比?#8220;回退”“会签”“回退”“取回”“自由?#8221;“d辅办”{等特色?br> 也正因ؓq样Q国内客户应用需求的差别非常大,单纯和固定的一Ƒַ作流产品Q很难满不同领域,不同客户的需求,所以国内的工作品更多的不得不依托于目来生存。也很难短时间发展v来一ƾ或几款非常庞大的品?/p>
你让我谈谈我对v步Y件的看法Q是有些不太好绝对公q的评论的。因为我曄在思维加速(h软g的前w)待过?br> h软g是典型的以技?
和品征服客L一家Y件品和应用服务提供商。前两年Q从早期的纯_业务技术Y件^C品提供商Q{变ؓ多业务品和服务提供商(当然Q目前主要以协同
领域ZQ,是非常成功的转型。而他们早在多q以前就定位?#8220;模型驱动”的品架构和思\更是h越性的Q这首先要得益于他们ȝ理马U先生的前?
光,也更得益于他们的dE师宋兴烈的执著和坚韧?br> 当然Q目前国内偏于应用开发^台的产品已经很多了,处理h的X3Q还有浪潮的loushangQ炎黄盈动的AWSQ普元的EOS{等?br>6Q许多国际Y件巨头比如BEAQIBMQTibco它们都有涉q个领域Q对于它们的产品Q我们国内的产品有哪些优势与不呢?
对于q些z巨头们Q我想用一句成语来形容—?#8220;高山仰止”。意思是Q在BPM、EAI、ESBq几个领域内Q我们国内厂商与他们的实力差距太大。当然国内还是有q样的品,比如东方通的消息产品Q西安协同的ESB产品{?br>
因ؓ我在TIBCOQ所以我拿TIBCO来说吧。TIBCO最初是以消息服务品发展v来的Q直到目前的以提供EAI、BPM及相关的Solution
产品的服务提供商。纳斯达克证怺易所QNasdaqQ的底层信息交易pȝ是TIBCO消息产品支撑的。仅在消息服务这一个领域,是国内产品短时间无
法逾越的?br> 我们再看看BPMq个领域吧,TIBCO的bpm产品是收购自StaffwareQ而Staffware早在85q的时候就一直在工作领域发展?br>
我不是过于夸大国外厂商的在这个领域内的实力。我的一个PSG部门的同事,每次在客L场POC之后QL感慨Q?#8220;每次在我用TIBCO产品竞标成功?
后,我不是喜悦,而是深深的感到国内品的落后Q以及这个领域的q乎I白”。但我只能说Q我们在基础技术和核心技术方面,落后的太多太多?br>
相比较这些国际巨头们Q国内厂商的劣质主要表现在:
Q?Q?nbsp;研发资金不?br>Q?Q?nbsp;理论U篏、技术积累和沉淀不。研发团队的E_性也是一个问题之一
Q?Q?nbsp;国内客户需求和工作应用还属于基本应用层次Q所以很难推动国内厂商投入h力物力来提供产品的定位和应用层次Q比如流E监控、分析等{?
7Q企业的需要是个性化的,那么通常国内的工作流理厂商如何满企业的个性需求?
国内工作品则主要依赖于提供灵zȝ建模工具Q表单工P对外E序接口QAPIQ,可外挂的扩展应用和接口实现等{来满企业的个性化需求?/p>
我一直有个观点:技术不是最主要的问题。国内应用开发商都是很厉害的Q基本上在项目实施过E中Q只要客戯够提出基本的需求,技术开发h员L可以扑ֈ解决办法的?/p>
Q?Q?nbsp;需求。客户对程应用的需求很难提的比较清晰和准确。一斚w是客户对工作技术基本理念不清,所以很隑և地阐述应用需求;另一斚wQ是应用开发商ҎE应用的整体性认识不全,pȝ性不够,所以很难正的引导客户来分析流E应用和需求?br>Q?Q?nbsp;合适的程产品。国内的产品外部怼性很多,但内部细力度的区别却又很多。但是这U细力度的区别是很难通过单的演示p够让应用开发商明白的?/p>
“?
没有听说qSEMAQ这可是衡量一个Y件开发组好坏的很深奥的系l。别动,{一下!别按那个链接Q给你六q你也搞不清q玩意儿。所以我自己随便攒了一套衡
量系l,信不信由你,q系l,三分钟就可掌握。你可以把省下的旉去读d院了Q译注:国的医学院可是要读Mh的!Q?/p>
Q注QSEMAQSoftware Engineering Measurement and AnalysisQ?br>
Joel 衡量法则Q?br>1. 你们用不用源文g理pȝQ?
2. 你们可以把整个系l从源码到CD映像文g一步徏成吗Q?
3. 你们每天白天都把从系l源码到CD映像做一遍吗Q?
4. 你们有Y件Bug理pȝ吗?
5. 你们在写新程序之前L把现有程序里已知的Y件Bug解决吗?
6. 你们的品开发日E安排是否反映最新的开发进展情况?
7. 你们有没有Y件开发的详细说明书?
8. 你们的程序员是否工作在安静的环境里?
9. 你们是否使用现有市场上能买到的最好的工具Q?
10. 你们有没有专职的软g试人员Q?
11. 你们招h面试时是否让写一D늨序?
12. 你们是否随便抓一些h来试用你们的软gQ?
“Joel 衡量法则”好就好在你只需照着逐条回答以上问题Q然后把所{ؓ”?#8221;的问题算成一分,再加h可以了Q而不需要去什么每天写的程序行数或E序虫的q_数等{。但׃话说在前面,可别?#8221;Joel 衡量法则”L你的核늫理E序是否可靠?
如果你们得了12分,那是最好,得了11分还q得去,但如果只得了10分或低于10分,你们可能有很严重的问题了。严L现实是:大多数的软g开发公司只能得??分。这些公司如果得不到急救可就玄了Q因为像微Yq样的公总来就没有低过12分?
?
Ӟ一个公司成功与否不仅仅只取决于以上标准。比如,让一个管理绝佳的软g公司d发一个没有h要的软gQ那开发出来的软g也只能是没有。或反过来,
一帮Y件痞子以上标准一条也达不刎ͼ没准照样也能搞出一个改变世界的伟大软g。但我告诉你Q如果不考虑别的因素Q你只要能达C?2条准则,你的团队?
是一个可以准时交zȝU律严明的好团队?#8221;
--------------------------------------------------------------------------------
1. 你们用不用源文g理pȝQ?br>我用q商业化的源文g理pȝQ我也用q免费的pȝQ比如CVSQ告诉你吧,CVS挺好用。但如果你根本就没有用源文g理pȝQ那你就是篏M也没法让你的E序员出z:他们没法知道别h在改动什么源文gQ写错了的源文g也没法恢复?
使用源文件管理系l还有一大好处是Q由于每一位程序员都把源文件从源文件管理系l里提出来放到自q盘里,几乎不会发生丢失源文件的事,最L我还没听说过?
2. 你们可以把整个系l从源码到CD映像文g一步徏成吗Q?br>q? 句话问的问题是:从你们最新的源码开始到建立赯够交出去的最后文Ӟ你们有多步骤要做?一个好的团队应该有一个批处理E序一步便可将所有的工作做完Q? 像把源文件提取出来,跟据不同的语a版本要求Q英文版Q中文版Q,和各U编译开养I#ifdefQ进行编译,联接成可执行文gQ标上版本号Q打包成CD? 像文件或直接送到|站上去Q等{等{?
如果q些步骤不是一步做完,有可能Zh为差错。而且当你很接q品开发尾声的时侯Q你可能很急于把最后几个虫解决Q然后尽快地交活。如果这时候你需要做20步才能把最l文件制出来Q你肯定会急得要命Q然后犯一些很不该犯的错误?br>
?
因ؓq个原因Q我工作的前一个公总用WISE改用InstallShieldQ我们必需要让我们的批处理E序完全自动化地Q在夜里Q被NT
scheduler起动把最l文件制成,WISE不能被NT
scheduler启动而InstallShield可以Q我们只能把WISE扔掉。(WISE的那帮家伙向我保证他们的下一代品一定支持在夜里自动q?
?
3. 你们每天白天都把从系l源码到CD映像做一遍吗Q?br>你们有没有遇到过q样的事情:一个程序员不小心把有毛病的源码放进 源文件管理系l,l果造成最l文件没法制成。比如,他徏立了一个新源文件但忘了把它放进源文件管理系l,然后他高高兴兴锁机回家了Q因为在他的机器上整? ~译得很好。可是别人却因ؓq没法工作下MQ也只好闷闷地回家了?
q种造成最l文件没法制成的情况很糟p,但却很常见。如果每天在? 天就把最l文件制一遍的话,可以让q种事不造成太大危害。在一个大的团队里Q要想保证有毛病的源码及时得到纠正,最好每天下午(比如午餐Ӟ制一下最l? 文g。午前Q每个h都尽可能地把改动的源文g攑ֈ源文件管理系l里Q午后Q大家回来,如果最l文件已l制成了Q好Q这时大家再从源文g理pȝ里取? 最新的源文件接着q活。如果最l文件制作出错,出错者马上修正,而别可接着用原有的没问题的源程序干zR?
在我以前曑ֹq的微Y Excel开发组里,我们有一条规定:谁造成最l文件制作出错,谁就得被|去负责监视以后的最l文件制作过E,直到下一位造成最l文件制作出错的人来接Q 他。这样做不仅可以督促大家造成最l文件制作出错,而且可以让每个h都有ZM解最l文件制作过E?
如果x多了解这个话题,可以L的另一文?Daily Builds are Your Friend.
4. 你们有Y件虫理pȝ吗?
?
Z有Q何借口Q只要你写程序,哪怕只是一个h的小l,如果你没有一个系l化的管理Y件虫的工P你写的程序的质量一定高不了。许多程序员觉得自己可以?
得自q软g虫。没门!我从来记不住过Q到Q个软g虫。而且W二天早上v床后忙着Mq买那,好不ҎC的Y件虫早忘掉了。你l对需要一个系l来住
你的那些虫?
软g虫管理系l功能有多有。但最要理以下几种信息Q?br>
如何重复软g虫的详细步骤
正常情况Q无虫)应是怎样
现在情况Q有虫)又是怎样
谁来负责杀?
问题有没有解?
如果你觉得用软g虫管理系l太ȝQ可以简化一下,建立一个有以上5列的表来用就行了?
如果x多了解这个话题,可以L的另一文章Painless Bug Tracking.
5. 你们在写新程序之前L把现有程序里已知的虫解决吗?
?
软Windows
Word的第一版的开发项目曾被认为是“M之旅”目。好象永q也做不完,永远时。所有h疯狂地工作,可怎么也完成不了Q务。整个项目一拖再拖,大家
都觉得压力大得受不了。最后终于做完了q个鬼项目,微Y把全l送到墨西哥的Cancund假,让大家坐下来好好x?
大家意识到由?
目l理q于强求E序员们按时交活Q结果大家只能匆匆地赶活Q写出的E序毛病癑և。由于项目经理的开发计划ƈ没有考虑杀虫的旉Q大家只能把杀虫的d往
后推Q结果虫积多。有一个程序员负责写计字体高度的E序Qؓ了图快,居然写一?#8221;return
12;”了事。他指望以后的质人员发现q段E序有毛病后报告他再Ҏ。项目经理的开发计划事实上已变成一个列写程序功能的清单Q而上面列的所谓程序功?
q早都会成ؓ软g虫。在目ȝ会上Q我们称q种工作Ҏ?#8220;l对劣质之\”?br>
Z避免再犯q个错误Q微软制定了“零缺L?#8221;。许多程序员嘲笑q个{略Q觉得经理们g在指望靠行政命o来提高品质量。而事实上“零缺L?#8221;的真正含义是Q在M时候,都要把解决现有程序里的问题作为首要问题来抓,然后再去写新E序?br>
Z么要q样做呢Q?
一 般说来,你越不及时地杀虫,杀虫的代hQ时间和金钱Q就会越高。比如,你写E序时打错了一个字Q编译器马上告诉你,你很Ҏ把它改正。你刚写好的E序? W一ơ运行时发现了一个问题,你也很快p解决它,因ؓ你对你刚写的E序q记忆犹新。如果你q行你的E序时发C一个问题,可这个程序是几天以前写的Q你 可能需要折腾一会儿Q还好,你还大致记得Q所以不会花太长旉。但如果你在你几个月以前写的E序里发C问题Q就比较难解决了Q因Z已经忘了许多l? 节。这时候,你还没准儿正忙着杀别hE序里的虫呐Q因家伙到加勒比阿鲁巴岛度假去了。这时候,解决q一堆问题的隑ֺ不亚于从事尖端科学研I。你一? 得小心翼地Q非常系l化C事,而且你很隄道多长时间你才能把问题解冟뀂还有更p糕的,你的E序已交到用h里了Q才发现问题Q那你就{着掏腰包吧?
ȝhQ就一条:早解决问题Q越Ҏ解决?
另外q有一个原因,刚写的程序里发现问题Q你能够比较ҎC解军_的时 间。D个例子,如果我问你写一D늨序去把一个列表排序需要花多长旉Q你可以l我一个比较确切的估计。如果你的程序,在Internet Explorer 5.5安装以后Q工作不正常。我问你要多长时间把q个问题解决Q你恐怕都估计不出来,因ؓ你根本就不知道是什么原因造成了这个问题。你可能要花三天旉? 能解冻I也有可能只花两分钟?
q个例子告诉我们Q如果你的开发过E中有许多虫没有及时解决Q那你的开发计划肯定不可靠。反q来Q如果你们已l把已知的虫全部解决了,要做的事只是写新的程序,那你的开发计划就会比较准?
?
已知的虫全部解决Q这样做q有一个好处:你可以对竞争Ҏ快速反凅R有些h把这叫着“让开发中的品随时处在可以交l用L状?#8221;。如果你的竞争对手推?
一个新的功能想把你的客h赎ͼ你可以马上在你的产品里加上这个功能,立刻新产品交付用户Q因Z没有一大堆U篏下来的问题要解决?
6. 你们的品开发日E安排是否反映最新的开发进展情况?
Z么我们需要开发日E安排?如果你的E序对公司的业务很重要,那公司就必须知道你的E序何时能写完。满世界的程序员都有一个通病Q那是他们都搞不清自己何时才能写完要写的程序。他们都只会对管理h员嚷P“{我做好了就做好了!”
不幸的是Q程序写完了Q事q远没完。作Z个公司,在发行品之前,q有许许多多的事情要做:何时做品演C?何时参加展览会?何时发广告?{等。所有的q一且都依赖于品的开发日E安排?
定下产品开发日E安排,q有一个很关键的好处:它逼着你只做叫你做的功能,甩掉那些可要可不要的功能Q否则这些可要可不要的东西有可能把你~住。请看featuritis ?
定下产品开发日E安排,按照它开发,qƈ不难做,L我的另一文?Painless Software Schedules Q这文章告诉你一U制订品开发日E的好方法?
7. 你们有没有Y件开发的详细说明书?
写Y件开发的详细说明书就像是l花Qh人皆知是好东西,可没谁愿意去做?
我不知道q是Z么,也许是因为多数程序员天生׃喜欢写文章。其l果是,一个开发组里的E序员们Q宁可用E序来沟通,也不愿写文章来表达自己。他们喜Ƣ上来就写程序,而不是写什么详l说明书?
在品的前期设计q程中,如果你发C一些问题,你可以轻易地在说明书里该几行字就行了。一旦进入了写程序的阶段Q解决问题的代hp高得多了Q不仅仅是时间上的代P而且也有感情上的代hQ因为没人愿意将自己做成的东西扔掉。所以这时候解决问题L一些阻力?
? 有品开发详l说明书开始写E序Q往往会导致程序写的ؕ七八p,而且左拖x不能交付使用。我觉得q就是Netscape遇到的问题。前四个版本的程? 写ؕQ以至管理h员作Z个愚蠢的军_Q把以前的程序统l扔掉,重新写。后来他们在开发Mozilla时又犯了同样的错误。品越做越乱,完全失控Q? ׃几年的时间才q入内部试阶段?
我最得意的理论是Q如果让E序员们接受一些写文章的训l,如an intensive course in writingQ他们就可能会改变一下不写说明书的坏习惯Q而以上所说的p糕的例子就有可能少发生?
另一个解决问题的办法是:雇一些能q的目MQQ专职写产品开发详l说明书?
不论采用以上哪种ҎQ道理只有一个:在没有品开发详l说明书之前Q决不可写程序?br>
如果x多了解这个话题,可以L的四文章?
8. 你们的程序员是否工作在安静的环境里?
当你让你的智囊们工作在安静,宽敞Q不受h打扰的环境里Q他们往往能更快地出活Q这已是不争的事实。有一本经典的讲Y件开发管理的书PeoplewareQhӞ 把这个问题阐q得很清楚?
问题在于Q我们都知道最好不要打断这些智囊们的思\Q让他们一直处于他们的最佳状态中Q这样他们就能全诏注,废寝忘食地工作,充分发挥他们的作用。作ӞE序员,U学Ӟ甚至球q动员都有他们的最佳状态?
问题q在于,q入q个最佳状态不Ҏ。我觉得q_hQ需?5分钟才能q入最佳状态,辑ֈ最高工作效率。有时侯Q当你疲劳了或已l高效率地干了许多工作了Q你很隑ֆq入q个状态,只好q点杂事打发旉Q或上网Q玩游戏{?
? 题更在于Q你很容易就被各U各L事打扎ͼ被拽Z的最佳状态:噪音啦,电话啦,吃午饭啦Q喝杯咖啡啦Q被同事打扰啦,{等。如果一个同事问你一个问题, 只花你一分钟Q可你却被拽Z的最佛_作状态,重新回到q个状态需要花半小时。你的工作效率因此而受到很大媄响。如果让你在一个嘈杂的大房间里工作Q那? 搞网站的家伙q就喜欢q样Q,边上的推销员在电话里大叫大P你就很难出活Q因Zq入不了你的最佛_作状态?
作ؓE序员,q入最佛_ 作状态更难。你先要把方斚w面的l节装在脑子里,M一U干扰都可能让你忘掉其中某些东西。你重新回来工作Ӟ发现好些东西Ch了(如你刚用的局部变 量名Q或你刚才的搜烦E序写到哪里了等Q,你只好看看刚写的E序Q回忆一下,慢慢地回C刚才的最佛_作状态?
我们来做一个简单的? 数。假设一个程序员被打C下,哪怕只有一分钟Q他却需要花15分钟才能回到最佛_作状态(l计资料昄如此Q。我们有两个E序员:杰夫和愚夫, 坐在一个大办公区里工作。愚夫想不v来用什么函数去q行Unicode 字符串复制。他可以?0U查一下,或者花15U问杰夫。由于他坐在杰夫的旁边,他就选择去问杰夫。杰夫被打扰了一下,耽误了他15分钟Q节省了愚夫15 U钟?
现在Q我们把他们俩用墙和门隔开Q让他们俩分坐在不同的办公室里,愚夫又想不v来什么函数名Q自己查一下要?0U;问杰夫,? ?5U,因ؓ他要站v来走q去问(对这帮程序员来说Q这可不是g单的事,看看他们的体质就知道Z么了Q。所以他选择自己L。愚夫损׃30U钟Q? 可是杰夫损׃ 15分钟。哈哈!
9. 你们是否使用现有市场上能买到的最好的工具Q?br>用可~译语言写程序恐怕是q世界上为数 不多的还不能随便抓一个破计算机就可以做的事。如果你用于~译的时间超q几U钟Q你应该换一台最新最快的计算Z。因为如果编译时间超q?5U,E序? 们就会不耐烦Q{而去上网看一些无关的东西比如 The OnionQ弄不好一看就是好几个时?
调试囑Ş界面软gӞ用只有一个显C器的计机不仅不方便,有时甚至是不可能。用有两个显C器的计机Q要方便许多?
E序员们l常不可避免地要ȝ一些图标或工具栏图。多数程序员没有一个好的图形编辑器可用。用微Y?#8220;ȝ”软gȝ图标直是W话Q可事实上大家还在q样做?
在我的前一个工作,pȝ理员成天给我发来自动警告,说我在服务器上用了过220兆的I间。我告诉他,按现在硬盘的价钱Q超点空间的价钱q低于我用的厕纸的h钱。让我花10分钟L理我的文件绝Ҏ我工作效率的莫大费?
一的开发组l不折腾它的E序员。工兯后会让h用v来觉得难受,一点点U篏hQ会让程序员们成天叫苦,而一个成天叫苦的E序员绝对不会是一个高消率的程序员?
再添一句,要想使你的程序员高兴Q最好的办法是l他们买一些最新最的工具软g。用q种Ҏ可以让他们乖乖地Z工作Q这可比用高薪吸引他们来得便宜得多?
10. 你们有没有专职的软g试人员Q?br>如果你的开发组里没有专职的试人员Q或没有_的测试h员(两到三个E序员就应该配一个测试员Q,那你的品就一定是毛病癑և。想在测试员w上省钱Q绝Ҏ打错了算盘。我真不明白Z么这么多人算不过来这W帐?
我有另一文章专门讲q个Q请看Top Five (Wrong) Reasons You Don't Have Testers?
11. 你们招h面试时是否让写一D늨序?
我问你,让你L一个魔术师Q你是否q看都不看一g的魔术玩得怎样p他?当然不会Q?br>
你D办婚_要请一个厨师,你是不是q嚐也不嚐他做的菜好吃不好吃p他?我想也不会?
? 怪的是,几乎每天都有q样的事发生Q在面试一个程序员Ӟ历写得漂亮,谈得热火朝天Q问几个单的问题Q如CreateDialog()? DialogBox()有什么区别?q种问题Q查一下帮助文件就知道了)Qh招q来了。你真正应该兛_的不是这不记得这些写E序的边边角角的东西Q? 而是他能否出产品Q更p糕的是Q许多问题是知道q道,不知道,x也不知道的问题?
不能q样下去了!在面试时Q请一定要让写一D늨序。在我的q篇文章里Guerrilla Guide to InterviewingQ我有许多好?
12. 你们是否随便抓一些h来试用你们的软gQ?br>q句话的意思是Q让你从走道里走q的ZQ随便抓几个人来Q让他们试用你的软g。如果你抓五个h来用你的软gQ那你就可能把你的程序中95%的不方便使用的地Ҏ出来?
要想让用户去C的YӞ你必要设计好你的用L面。这其实q不难。你可以L的free online book on UI design打打基础?br>
用户界面设计的关键是Q如果你让几个hȝ你的软gQ五六h可能够了)Q你可能很快找出最大的问题。想知道Z么吗Q请读Jakob Nielsen's article。只要你坚持随便抓一些h来试用你的YӞ你就能将你的用户界面设计得越来越好?br>
--------------------------------------------------------------------------------
The Joel Test 软g开发成?2法则的四个实用领域:
1. 用该法则来衡量你的Y件开发组Q告诉我你得的分敎ͼ让我来品头论?
2. 如果你是开发组的经理,用该法则来你的l提高效率。如果你们一上来p?2分,你就别再打扰你的E序员了Q专心致志别让公司的理人员来烦你的E序员吧?
3. 如果你在找一份程序员工作Q问问你未来的老板他能得几分,如果分数很低Q你一定要信你进d有够的权力来改变这一切,否则Q最好躲q点Q不Ӟ你在那儿会很隑֏的?
4. 如果你是投资者,正在军_是否向一个Y件公司投资,或者你的Y件公司正在决定是否兼q另一个Y件公司,该法则可以帮你做军_?/p>