in

SDT Community Server

SDT Forums, Blogs, Photos server.

Floating Heart

No description is bad.

May 2007 - Posts

  • 什么是Extreme Programming


    http://blog.csdn.net/laojievip/archive/2004/10/17/140179.aspx

    Extreme Programming(极限编程,简称XP)是由Kent Beck在1996年提出的。Kent Beck在九十年代初
    期与Ward Cunningham共事时,就一直共同探索着新的软件开发方法,希望能使软件开发更加简单而有
    效。Kent仔细地观察和分析了各种简化软件开发的前提条件、可能行以及面临的困难。1996年三月,
    Kent终于在为DaimlerChrysler所做的一个项目中引入了新的软件开发观念——XP。

    XP是一个轻量级的、灵巧的软件开发方法;同时它也是一个非常严谨和周密的方法。它的基础和价值观
    是交流、朴素、反馈和勇气;即,任何一个软件项目都可以从四个方面入手进行改善:加强交流;从简
    单做起;寻求反馈;勇于实事求是。XP是一种近螺旋式的开发方法,它将复杂的开发过程分解为一个个
    相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚
    开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。


    什么是软件开发

    软件开发的内容是:需求、设计、编程和测试!
    需求:不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是为了解
    决什么问题;测试案例中应该输入什么数据……为了清楚地知道这些需求,你经常要和客户、项目经理
    等交流。
    设计:编码前,肯定有个计划告诉你要做什么,结构是怎样等等。你一定要按照这个来做,否则可能会
    一团糟。
    编程:如果在项目截止日,你的程序不能跑起来或达不到客户的要求,你就拿不到钱。
    测试:目的是让你知道,什么时候算是完成了。如果你聪明,你就应该先写测试,这样可以及时知道你
    是否真地完成了。否则,你经常会不知道,到底有哪些功能是真正完成了,离预期目标还差多远。

    软件开发中,客户和开发人员都有自己的基本权利和义务。
    客户:
     • 定义每个用户需求的商业优先级;
     • 制订总体计划,包括用多少投资、经过多长时间、达到什么目的;
     • 在项目开发过程中的每个工作周,都能让投资获得最大的收益;
     • 通过重复运行你所指定的功能测试,准确地掌握项目进展情况;
     • 能随时改变需求、功能或优先级,同时避免昂贵的再投资;能够根据各种变化及时调整项目计划;
     • 能够随时取消项目;项目取消时,以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的,
    正在进行或未完成的的工作则应该是不难接手的。
    开发人员:
     • 知道要做什么,以及要优先做什么;
     • 工作有效率;
     • 有问题或困难时,能得到客户、同事、上级的回答或帮助;
     • 对工作做评估,并根据周围情况的变化及时重新评估;
     • 积极承担工作,而不是消极接受分配;
     • 一周40小时工作制,不加班。

    这就是软件开发,除此之外再还有其它要关心的问题!



    灵巧的轻量级软件开发方法

    一套软件开发方法是由一系列与开发相关的规则、规范和惯例。重量级的开发方法严格定义了许多的规
    则、流程和相关的文档工作。灵巧的轻量级开发方法,其规则和文档相对较少,流程更加灵活,实施起
    来相对较容易。

    在软件工程概念出现以前,程序员们按照自己喜欢的方式开发软件。程序的质量很难控制,调试程序很
    繁琐,程序员之间也很难读懂对方写的代码。1968年,Edsger Dijkstra给CACM写了一封题为GOTO 
    Statement Considered Harmful 的信,软件工程的概念由此诞生。程序员们开始摒弃以前的做法,转
    而使用更系统、更严格的开发方法。为了使控制软件开发和控制其它产品生产一样严格,人们陆续制定
    了很多规则和做法,发明了很多软件工程方法,软件质量开始得到大幅度提高。随着遇到的问题更多,
    规则和流程也越来越精细和复杂。

    到了今天,在实际开发过程中,很多规则已经难于遵循,很多流程复杂而难于理解,很多项目中文档的
    制作过程正在失去控制。人们试图提出更全面更好的一揽子方案,或者寄希望于更复杂的、功能更强大
    的辅助开发工具(Case Tools),但总是不能成功,而且开发规范和流程变得越来越复杂和难以实施。
    为了赶进度,程序员们经常跳过一些指定的流程,很少人能全面遵循那些重量级开发方法。

    失败的原因很简单,这个世界没有万能药。因此,一些人提出,将重量级开发方法中的规则和流程进行
    删减、重整和优化,这样就产生了很多适应不同需要的轻量级流程。在这些流程中,合乎实际需要的规
    则被保留下来,不必要的复杂化开发的规被抛弃。而且,和传统的开发方法相比,轻量级流程不再象流
    水生产线,而是更加灵活。

    Extreme Programming(XP)就是这样一种灵巧的轻量级软件开发方法。


    为什么称为“Extreme”(极限) 

    “Extreme”(极限) 是指,对比传统的项目开发方式,XP强调把它列出的每个方法和思想做到极限、
    做到最好;其它XP所不提倡的,则一概忽略(如开发前期的整体设计等)。一个严格实施XP的项目,其
    开发过程应该是平稳的、高效的和快速的,能够做到一周40小时工作制而不拖延项目进度。 


    XP的软件开发是什么样

    1 极限的工作环境

    为了在软件开发过程中最大程度地实现和满足客户和开发人员的基本权利和义务,XP要求把工作环境也
    做得最好。每个参加项目开发的人都将担任一个角色(项目经理、项目监督人等等)并履行相应的权利
    和义务。所有的人都在同一个开放的开发环境中工作,最好是所有人在同一个大房子中工作,还有茶点
    供应;每周40小时,不提倡加班;每天早晨,所有人一起站着开个短会;墙上有一些大白板,所有的
    Story卡、CRC卡等都贴在上面,讨论问题的时候可以在上面写写画画;下班后大家可以一起玩电脑游
    戏……。

    2 极限的需求

    客户应该是项目开发队伍中的一员,而不是和开发人员分开的;因为从项目的计划到最后验收,客户一
    直起着很重要的作用。开发人员和客户一起,把各种需求变成一个个小的需求模块(User Story),例
    如“计算年级的总人数,就是把该年级所有班的人数累加。”;这些模块又会根据实际情况被组合在一
    起或者被分解成更小的模块;它们都被记录在一些小卡片(Story Card)上,之后分别被程序员们在各
    个小的周期开发中(Iteration,通常不超过3个星期)实现;客户根据每个模块的商业价值来指定它们
    的优先级;开发人员要做的是确定每个需求模块的开发风险,风险高的(通常是因为缺乏类似的经验)
    需求模块将被优先研究、探索和开发;经过开发人员和客户分别从不同的角度评估每个模块后,它们被
    安排在不同的开发周期里,客户将得到一个尽可能准确的开发计划;客户为每个需求模块指定验收测试
    (功能测试)。

    每发布一次开发的软件(经过一个开发周期),用户都能得到一个可以开始使用的系统,这个系统全面
    实现了相应的计划中的所有需求。而在一些传统的开发模式中,无论什么功能,用户都要等到所有开发
    完成后才能开始使用。 

    3 极限的设计 

    从具体开发的角度来看,XP内层的过程是一个个基于测试驱动的开发(Test Driven Development)周
    期,诸如计划和设计等外层的过程都是围绕这些展开的。每个开发周期都有很多相应的单元测试
    (Unit Test)。刚开始,因为什么都没有实现,所以所有的单元测试都是失败的;随着一个个小的需
    求模块的完成,通过的单元测试也越来越多。通过这种方式,客户和开发人员都很容易检验,是否履行
    了对客户的承诺。XP提倡对于简单的设计(Simple Design),就是用最简单的方式,使得为每个简单
    的需求写出来的程序可以通过所有相关的单元测试。XP强调抛弃那种一揽子详细设计方式(Big 
    Design Up Front),因为这种设计中有很多内容是你现在或最近都根本不需要的。XP还大力提倡设计
    复核(Review)、代码复核以及重整和优化(Refectory),所有的这些过程其实也是优化设计的过
    程;在这些过程中不断运行单元测试和功能测试,可以保证经过重整和优化后的系统仍然符合所有需
    求。 

    4 极限的编程 

    既然编程很重要,XP就提倡两个人一起写同一段程序(Pair Programming),而且代码所有权是归于整
    个开发队伍(Collective Code Ownership)。程序员在写程序和重整优化程序的时候,都要严格遵守
    编程规范。任何人都可以修改其他人写的程序,修改后要确定新程序能通过单元测试。 

    5 极限的测试 

    既然测试很重要,XP就提倡在开始写程序之前先写单元测试。开发人员应该经常把开发好的模块整合到
    一起(Continuous Integration),每次整合后都要运行单元测试;做任何的代码复核和修改,都要运
    行单元测试;发现了BUG,就要增加相应的测试(因此XP方法不需要BUG数据库)。除了单元测试之外,
    还有整合测试,功能测试、负荷测试和系统测试等。所有这些测试,是XP开发过程中最重要的文档之
    一,也是最终交付给用户的内容之一。 


    XP中的重要惯例和规则

    1 项目开发小组(Team)

    在XP中,每个对项目做贡献的人都应该是项目开发小组中的一员。而且,这个小组中必须至少有一个人
    对用户需求非常清晰,能够提出需求、决定各个需求的商业价值(优先级)、根据需求等的变化调整项
    目计划等。这个人扮演的是“客户”这个角色,当然最好就是实际的最终用户,因为整个项目就是围绕
    最终用户的需求而展开的。程序员是项目开发小组中必不可少的成员。小组中可以有测试员,他们帮助
    客户制订验收测试;有分析员,帮助客户确定需求;通常还有个Coach(教练),负责跟踪开发进度、
    解决开发中遇到的一些问题、推动项目进行;还可以又一个项目经理,负责调配资源、协助项目内外的
    交流沟通等等。项目小组中有这么多角色,但并不是说,每个人做的工作是别人不能插手或干预的,XP
    鼓励每个人尽可能地为项目多做贡献。平等相处,取长补短;这就是最好的XP开发小组。

    2 计划项目(Planning Game)、验收测试、小规模发布(Small Releases)

    XP开发小组使用简单的方式进行项目计划和开发跟踪,并以次预测项目进展情况和决定未来的步骤。根
    据需求的商业价值,开发小组针对一组组的需求进行一系列的开发和整合,每次开发都会产生一个通过
    测试的、可以使用的系统。

    •  计划项目

    XP的计划过程主要针对软件开发中的两个问题:预测在交付日期前可以完成多少工作;现在和下一步该
    做些什么。不断的回答这两个问题,就是直接服务于如何实施及调整开发过程;与此相比,希望一开始
    就精确定义整个开发过程要做什么事情以及每件事情要花多少时间,则事倍功半。针对这两个问题,XP
    中又两个主要的相应过程:

    软件发布计划(Release Planning)。客户阐述需求,开发人员估算开发成本和风险。客户根据开发成
    本、风险和每个需求的重要性,制订一个大致的项目计划。最初的项目计划没有必要(也没有可能)非
    常准确,因为每个需求的开发成本、风险及其重要性都不是一成不变的。而且,这个计划会在实施过程
    中被不断地调整以趋精确。

    周期开发计划(Iteration Planning)。开发过程中,应该有很多阶段计划(比如每三个星期一个计
    划)。开发人员可能在某个周期对系统进行内部的重整和优化(代码和设计),而在某个周期增加了新
    功能,或者会在一个周期内同时做两方面的工作。但是,经过每个开发周期,用户都应该能得到一个已
    经实现了一些功能的系统。而且,每经过一个周期,客户就会再提出确定下一个周期要完成的需求。在
    每个开发周期中,开发人员会把需求分解成一个个很小的任务,然后估计每个任务的开发成本和风险。
    这些估算是基于实际开发经验的,项目做得多了,估算自然更加准确和精确;在同一个项目中,每经过
    一个开发周期,下一次的估算都会有更过的经验、参照和依据,从而更加准确。
    这些简单的步骤对客户提供了丰富的、足够的信息,使之能灵活有效地调控开发进程。每过两三个星
    期,客户总能够实实在在地看到开发人员已经完成的需求。在XP里,没有什么“快要完成了”、“完成
    了90%”的模糊说法,要不是完成了,要不就是没完成。这种做法看起来好象有利有弊:好处是客户可以
    马上知道完成了哪些、做出来的东西是否合用、下面还要做些什么或改进什么等等;坏处是客户看到做
    出来的东西,可能会很不满意甚至中止合同。实际上,XP的这种做法是为了及早发现问题、解决问题,
    而不是等到过了几个月,用户终于看到开发完的系统了,然后才告诉你这个不行、那个变了、还要增加
    哪个内容等等。

    •  验收测试

    客户对每个需求都定义了一些验收测试。通过运行验收测试,开发人员和客户可以知道开发出来的软件
    是否符合要求。XP开发人员把这些验收测试看得和单元测试一样重要。为了不浪费宝贵的时间,最好能
    将这些测试过程自动化。

    •  频繁地小规模发布软件(Small Releases)

    每个周期(Iteration)开发的需求都是用户最需要的东西。在XP中,对于每个周期完成时发布的系
    统,用户都应该可以很容易地进行评估,或者已经能够投入实际使用。这样,软件开发对于客户来说,
    不再是看不见摸不着的东西,而是实实在在的。XP要求频繁地发布软件,如果有可能,应该每天都发布
    一个新版本;而且在完成任何一个改动、整合或者新需求后,就应该立即发布一个新版本。这些版本的
    一致性和可靠性,是靠验收测试和测试驱动的开发来保证的。

    3 简单设计,Pair Programming,测试驱动开发,重整和优化

    XP程序员不但做为一个开发小组共同工作,还以两个人为一个小开发单元编写同一个程序。开发人员们
    进行简单的设计,编写单元测试后再编写符合测试要求的代码,并在满足需求的前提下不断地优化设
    计。

    •  简单设计

    XP中让初学者感到最困惑的就是这点。XP要求用最简单的办法实现每个小需求,前提是按照这些简单设
    计开发出来的软件必须通过测试。这些设计只要能满足系统和客户在当下的需求就可以了,不需要任何
    画蛇添足的设计,而且所有这些设计都将在后续的开发过程中就被不断地重整和优化。

    在XP中,没有那种传统开发模式中一次性的、针对所有需求的总体设计。在XP中,设计过程几乎一直贯
    穿着整个项目开发:从制订项目的计划,到制订每个开发周期(Iteration)的计划,到针对每个需求
    模块的简捷设计,到设计的复核,以及一直不间断的设计重整和优化。整个设计过程是个螺旋式的、不
    断前进和发展的过程。从这个角度看,XP是把设计做到了极致。

    •  Pair Programming

    XP中,所有的代码都是由两个程序员在同一台机器上一起写的——这是XP中让人争议最多、也是最难实
    施的一点。这保证了所有的代码、设计和单元测试至少被另一个人复核过,代码、设计和测试的质量因
    此得到提高。看起来这样象是在浪费人力资源,但是各种研究表明事实恰恰相反。—— 这种工作方式
    极大地提高了工作强度和工作效率。

    很多程序员一开始是被迫尝试这点的(XP也需要行政命令的支持)。开始时总是不习惯的,而且两个人
    的效率不会比一个人的效率高。这种做法的效果往往要坚持几个星期或一两个月后才能很显著。据统
    计,在所有刚开始Pair Programming的程序员中,90%的人在两个月以后都很认为这种工作方式更加高
    效。

    项目开发中,每个人会不断地更换合作编程的伙伴。因此,Pair Programming不但提高了软件质量,还
    增强了相互之间的知识交流和更新,增强了相互之间的沟通和理解。这不但有利于个人,也有利于整个
    项目、开发队伍和公司。从这点看,Pair Programming不仅仅适用于XP,也适用于所有其它的软件开发
    方法。

    •  测试驱动开发

    反馈是XP的四个基本的价值观之一——在软件开发中,只有通过充分的测试才能获得充分的反馈。XP中
    提出的测试,在其它软件开发方法中都可以见到,比如功能测试、单元测试、系统测试和负荷测试等;
    与众不同的是,XP将测试结合到它独特的螺旋式增量型开发过程中,测试随着项目的进展而不断积累。
    另外,由于强调整个开发小组拥有代码,测试也是由大家共同维护的。即,任何人在往代码库中放程序
    (Check In)前,都应该运行一遍所有的测试;任何人如果发现了一个BUG,都应该立即为这个BUG增加
    一个测试,而不是等待写那个程序的人来完成;任何人接手其他人的任务,或者修改其他人的代码和设
    计,改动完以后如果能通过所有测试,就证明他的工作没有破坏愿系统。这样,测试才能真正起到帮助
    获得反馈的作用;而且,通过不断地优先编写和累积,测试应该可以基本覆盖全部的客户和开发需求,
    因此开发人员和客户可以得到尽可能充足的反馈。

    •  重整和优化 (Refactoring)

    XP强调简单的设计,但简单的设计并不是没有设计的流水帐式的程序,也不是没有结构、缺乏重用性的
    程序设计。开发人员虽然对每个USER STORY都进行简单设计,但同时也在不断地对设计进行改进,这个
    过程叫设计的重整和优化(Refactoring)。这个名字最早出现在Martin Fowler写的《Refactoring: 
    Improving the Design of Existing Code》这本书中。

    Refactoring主要是努力减少程序和设计中重复出现的部分,增强程序和设计的可重用性。Refactoring
    的概念并不是XP首创的,它已经被提出了近30年了,而且一直被认为是高质量的代码的特点之一。但XP
    强调,把Refactoring做到极致,应该随时随地、尽可能地进行Refactoring,只要有可能,程序员都不
    应该心疼以前写的程序,而要毫不留情地改进程序。当然,每次改动后,程序员都应该运行测试程序,
    保证新系统仍然符合预定的要求。

    4 频繁地整合,集体拥有代码(Collective Code Ownership),编程规范

    XP开发小组经常整合不同的模块。为了提高软件质量,除了测试驱动开发和Pair Programming以外,XP
    要求每个人的代码都要遵守编程规范,任何人都可以修改其他人写的代码,而且所有人都应该主动检查
    其他人写的代码。

    •  频繁地整合 (Integration )

    在很多项目中,开发人员往往很迟才把各个模块整合在一起。在这些项目中,开发人员经常在整合过程
    中发现很多问题,但不能肯定到底是谁的程序出了问题;而且,只有整合完成后,开发人员才开始稍稍
    使用整个系统,然后就马上交付给客户验收。对于客户来说,即使这些系统能够通过终验收测试,因为
    使用时间短,客户门心里并没有多少把握。

    为了解决这些问题,XP提出,整个项目过程中,应该频繁地,尽可能地整合已经开发完的USER STORY
    (每次整合一个新的USER STORY)。每次整合,都要运行相应的单元测试和验收测试,保证符合客户和
    开发的要求。整合后,就发布一个新的应用系统。这样,整个项目开发过程中,几乎每隔一两天,都会
    发布一个新系统,有时甚至会一天发布好几个版本。通过这个过程,客户能非常清楚地掌握已经完成的
    功能和开发进度,并基于这些情况和开发人员进行有效地、及时地交流,以确保项目顺利完成。

    •  集体拥有代码(Collective Code Ownership)

    在很多项目开发过程中,开发人员只维护自己的代码,而且很多人不喜欢其他人随意修改自己的代码。
    因此,即使可能有相应的比较详细的开发文档,但一个程序员却很少、也不太愿意去读其他程序员的代
    码;而且,因为不清楚其他人的程序到底实现了什么功能,一个程序员一般也不敢随便改动其他人的代
    码。同时,因为是自己维护自己的代码,可能因为时间紧张或技术水平的局限性,某些问题一直不能被
    发现或得到比较好的解决。针对这点,XP提倡大家共同拥有代码,每个人都有权利和义务阅读其他代
    码,发现和纠正错误,重整和优化代码。这样,这些代码就不仅仅是一两个人写的,而是由整个项目开
    发队伍共同完成的,错误会减少很多,重用性会尽可能地得到提高,代码质量是非常好。

    为了防止修改其他人的代码而引起系统崩溃,每个人在修改后都应该运行测试程序。(从这点,我们可
    以再次看到,XP的各个惯例和规则是怎样有机地结合在一起的。)

    •  编程规范

    XP开发小组中的所有人都遵循一个统一的编程标准,因此,所有的代码看起来好像是一个人写的。因为
    有了统一的编程规范,每个程序员更加容易读懂其他人写的代码,这是是实现Collective Code 
    Ownership的重要前提之一。

    5 Metaphor(系统比喻),不加班

    XP过程通过使用一些形象的比喻让所有人对系统有个共同的、简洁的认识。XP认为加班是不正常的,因
    为这说明关于项目进度的估计和安排有问题。 

    •  Metaphor(系统比喻)

    为了帮助每个人一致清楚地理解要完成的客户需求、要开发的系统功能,XP开发小组用很多形象的比喻
    来描述系统或功能模块是怎样工作的。比如,对于一个搜索引擎,它的Metaphor可能就是“一大群蜘
    蛛,在网上四处寻找要捕捉的东西,然后把东西带回巢穴。”

    •  不加班

    大量的加班意味着原来的计划是不准确的,或者是程序远不清楚自己到底什么时候能完成什么工作。而
    且,开发管理人员和客户也因此无法准确掌握开发速度;开发人员也因此非常疲劳。XP认为,如果出现
    大量的加班现象,开发管理人员(比如Coach)应该和客户一起确定加班的原因,并及时调整项目计
    划、进度和资源。


    XP中一些基本概念的简介

    User Story:开发人员要求客户把所有的需求写成一个个独立的小故事,每个只需要几天时间就可以完
    成。开发过程中,客户可以随时提出新的User Story,或者更改以前的User Story。

    Story Estimates和开发速度:开发小组对每个User Story进行估算,并根据每个开发周期
    (Iteration)中的实际情况反复计算开发速度。这样,开发人员和客户能知道每个星期到底能开发多
    少User Story。

    Release Plan和Release Scope:整个开发过程中,开发人员将不断地发布新版本。开发人员和客户一
    起确定每个发布所包含的User Story。

    Iteration(开发周期)和Iteration Plan:在一个Release过程中,开发人员要求客户选择最有价值的
    User Story作为未来一两个星期的开发内容。

    The Seed:第一个开发周期(Iteration)完成后,提交给客户的系统。虽然这不是最终的产品,但它
    已经实现了几个客户认为是最重要的Story,开发人员将逐步在其基础上增加新的模块。

    Continuous Integration(整合):把开发完的User Story的模块一个个拼装起来,一步步接近乃至最
    终完成最终产品。

    验收测试(功能测试):对于每个User Story,客户将定义一些测试案例,开发人员将使运行这些测试
    案例的过程自动化。

    Unit Test(单元测试):在开始写程序前,程序员针对大部分类的方法,先写出相应的测试程序。

    Refactoring (重整和优化) :去掉代码中的冗余部分,增加代码的可重用性和伸缩性。 


    小结

    XP的一个成功因素是重视客户的反馈——开发的目的就是为了满足客户的需要。XP方法使开发人员始终
    都能自信地面对客户需求的变化。XP强调团队合作,经理、客户和开发人员都是开发团队中的一员。团
    队通过相互之间的充分交流和合作,使用XP这种简单但有效的方式,努力开发出高质量的软件。XP的设
    计简单而高效;程序员们通过测试获得客户反馈,并根据变化修改代码和设计,他们总是争取尽可能早
    地将软件交付给客户。XP程序员能够勇于面对需求和技术上的变化。

    XP很象一个由很多小块拼起来的智力拼图,单独看每一小块都没有什么意义,但拼装好后,一幅美丽的
    图画就会呈现在你面前。 

    Posted May 31 2007, 09:46 PM by wicky with 1 comment(s)
    Filed under:
  • 17th Annual Jolt Product Excellence Awards

    http://www.joltawards.com/2007/jolt_finalists.html

     

    Books (Practical/General Developer Interest)

    Agile Software Development: The Cooperative Game (Addison-Wesley) by Alistair Cockburn
    Catastrophe Disentanglement (Addison-Wesley) by E. M. Bennatan
    Eric Sink on the Business of Software (Apress) by Eric Sink
    Practices of an Agile Developer (Pragmatic Bookshelf) by Venkat Subramaniam and Andy Hunt
    Software Creativity 2.0 (DeveloperDotStar) by Robert L. Glass
    Software Estimation: Demystifying the Black Art (Microsoft Press) by Steve McConnell
    Weinberg on Writing: The Fieldstone Method (Dorset House) by Gerald M. Weinberg

     

    Books (Technical)

    Code Quality (Addison-Wesley) by Diomidis Spinellis
    How to Break Web Software (Addison-Wesley) by M. Andrews, J. Whittaker
    Java Concurrency in Practice (Addison-Wesley) by Brian Goetz et al
    Rails Recipes (Pragmatic Bookshelf) by Chad Fowler
    Refactoring Databases (Addison-Wesley) by Scott W. Ambler and P. J. Sadalage
    Head First Object-Oriented Analysis and Design (O'Reilly) by B. McLaughlin, G. Pollice and D. West
    Ruby Cookbook (O'Reilly) by Lucas Carlson and Leonard Richardson
    CSS: The Missing Manual (O'Reilly) by David Sawyer McFarland

     

    Change and Configuration Management

    AccuRev 4.5 with AccuWorkflow (Accurev)
    AnthillPro3 (Urbancode)
    Automated Build Studio (AutomatedQA)
    FLEXnet Connect (Macrovision)
    Perforce SCM (Perforce)
    Team Foundation Server (Microsoft Corporation)
    CA Wily Introscope ChangeDetector (CA / Wily Technology)

     

    Collaboration Tools

    Adobe Acrobat Connect Professional (Adobe Systems)
    Code Collaborator (Smart Bear Software)
    Confluence (Atlassian Software Systems)
    NetBeans IDE (Sun Microsystems)
    Sugar Professional (SugarCRM)
    TeamCity (JetBrains)

     

    Database Engines and Data Tools

    Coral8 Engine (Coral8)
    dbdeploy (ThoughtWorks)
    MarkLogic Server (Mark Logic)
    SQL Anywhere (Sybase iAnywhere)
    SQL Refactor (Red Gate Software)
    Visual Studio 2005 Team Edition for Database Professionals (Microsoft)

     

    Design and Modeling

    Compuware OptimalJ (Compuware)
    Corticon Business Rules Modeling Studio (Corticon Technologies)
    MagicDraw UML (No Magic)
    RAVEN (Ravenflow)
    stpBA Storyboarding for Microsoft Visual Studio 2005 Team System (stpsoft ltd.)
    Stylus Studio 2007 XML Enterprise Suite (DataDirect Technologies)

     

    Development Environments

    EiffelStudio Open Source Edition (Eiffel Software)
    IntelliJ IDEA (JetBrains)
    IronPython (Microsoft)
    Microsoft XNA Game Studio Express, XNA Framework (Microsoft)
    NetBeans IDE (Sun Microsystems)
    Wolfram Workbench (Wolfram Research)

     

    Enterprise Tools

    Cape Clear ESB Platform (Cape Clear Software)
    Liferay Portal (Liferay)
    Mule (MuleSource)
    Appistry EAF (Appistry)
    Pentaho Open BI Suite (Pentaho)
    TeamCity (JetBrains)

     

    Libraries, Frameworks and Components

    JViews (ILOG)
    NetAdvantage for .NET (Infragistics)
    telerik r.a.d.controls for WinForms (Telerik)
    .NET Framework 3.0 (Microsoft)
    Intel Threading Building Blocks (Intel)
    Microsoft XNA Game Studio Express, XNA Framework (Microsoft)
    The Mono Project (Novell)

     

    Mobile Development

    AccuSPEECH (Vangard Voice Systems)
    Carbide .c++ Professional Edition (Nokia)
    Crossfire (AppForge)
    Qtopia Greenphone (Trolltech)
    NetBeans Mobility Pack 5.5 and Sun Java Wireless Tookit 2.2 (Sun Microsystems)
    Qtopia (Trolltech)

     

    Project Mangement Tools

    6th Sense Analytics (6th Sense Analytics)
    DevPlan (TechExcel)
    Rally Enterprise (Rally Software)
    TargetProcess (TargetProcess)
    Teamwork (Open Lab)
    V1: Agile Enterprise (VersionOne)

     

    Security

    AppScan (Watchfire)
    beSTORM (Beyond Security)
    DevInspect (S.P.I. Dynamics)
    Fortify Defender (Fortify Software)
    Fortify Source Code Analysis (SCA) (Fortify Software)
    Metasploit Framework (Metasploit)

     

    Automated Testing Tools

    AgitarOne (Agitar Software)
    CodePro AnalytiX (Instantiations)
    Mindreef SOAPscope (Mindreef)
    Parasoft Jtest (Parasoft)
    Parasoft SOAtest (Parasoft)
    TestComplete (AutomatedQA)

     

    Bug and Defect Tracking Tools

    JIRA (Atlassian Software Systems)
    OnTime 2007 Hosted (Axosoft)
    Software Planner Professional (Pragmatic Software Co.)
    TestTrack Studio (Seapine Software)

     

    Utilities

    Adobe Captivate 2 (Adobe Systems)
    AutoPatch (Tacit Knowledge)
    ElectricCommander (Electric Cloud)
    TEKchecker and StyleWriter (ClearSpecs Enterprises)
    TextMate (MacroMates)
    VMware Lab Manager (VMware)

     

    Web Development

    Adobe Flex 2 (Adobe Systems)
    IntelliJ IDEA (JetBrains)
    Kapow Mashup Server (Kapow Technologies)
    LignUp Communications Application Server (LignUp)
    Mindreef SOAPscope Server (Mindreef)
    NetBeans Visual Web Pack (Sun Microsystems)

     

    Web Sites/Developer Networks

    CM Crossroads (CMC Media)
    IBM developerWorks (IBM)
    Sun Developer Network (Sun Microsystems)
    Koders.com (Koders)
    Krugle (Krugle)
    Makezine.com (O'Reilly)
    The Code Project (The Code Project)

    Posted May 31 2007, 05:51 PM by wicky with 1 comment(s)
    Filed under:
  • Windows 2003 SP2 + QQ莫名死机


    问题现象和说明: 安装了Windows 2003 Sp2 后计算机经常莫名其妙死机!

    都是“QQ键盘安全组件”惹的祸!

    解决方法一

    手动删掉QQ的键盘安全组件,关闭QQ,删除QQ目录下npkcrypt.sys和npkcusb.sys,用sreng删除npkcrypt服务, 如果不删掉这个服务,光删文件,可能会引起启动时提示有服务或者程序无法启动,接下来重启电脑就可以运行QQ了。不过输密码的时候会需要用软键盘输前三位密码,有点麻烦,但是总比死机好吧

    解决方法二(强烈推荐)

    卸载QQ,然后去http://im.qq.com下载新版的QQ 2007 beta1 kb1这个版本,在安装时可以选择是否安装键盘安全组件,去掉前面的钩就是不安装,这样就可以解决死机问题了.而且免去用软件键盘输前三位密码的烦恼.

    QQ2007 Beta1 KB1更新说明:

    1.可以选择是否安装键盘加密控件,避免部分USB键盘不兼容引起的问题。
    2.修正了在Windows Vista下QQ游戏大厅和访问QQ空间的不兼容问题。

    Posted May 29 2007, 08:01 PM by wicky with 5 comment(s)
    Filed under:
  • Team Foundation Server安装指南

    http://www.cnblogs.com/yanrongpi/archive/2007/03/27/644684.html

    1.说明

    Team Foundation Server(以下简称VSTF)的安装并不是一件轻松的事情,在安装的过程中相信很多人都或多或少碰到一些问题而安装不成功,虽然手头有微软提供的所谓安装手册,也曾听过WebCast上所谓专家的讲座,但是由于细节问题却并没有描述的十分清楚,笔者按照其指引,在安装过程中也是历经艰难,最后才得以安装成功。

    VSTF的部署模式分为两种,一是单服务器部署,一是双服务器部署,本文主要就单服务器模式的安装进行说明而不涉及双服务器部署的细节和其他领域。并且仅作为微软提供资料的补充,而不涉及过分多的细节。

    最新版本的安装手册您可以从下面的网址下载:

    http://go.microsoft.com/fwlink/?LinkId=40042

    2.安装前的准备

    1) 硬件要求:参见微软手册中的硬件要求。这里回答的一个问题是512MB RAM是否可以安装?在运行安装程序的时候安装程序会做一系列的检查,如果您的服务器的内存不足1GB(手册要求的最低),检查程序也仅仅是作为一个警告列出,而不影响安装,但是从性能的角度,如果您的团队大于10人,那么建议最好是在1GB或者以上。

    2) 操作系统要求:必须是Windows Server 2003 SP1 Enterprise Edition或者Windows Server 2003 SP1 Standard Edition,这是没有任何商量的余地的。

    3) 为安装VSTF创建其必须的用户。这些用户分别为安装用户,服务用户和报表用户,您可以使用微软推荐的名称,如TFSSetupTFSServiceTFSReports。一般而言TFSSetup必须添加到Administrators组中,至于TFSServiceTFSReports是否必须添加到Administrators组,微软手册不建议这样做,因为存在可能的安全风险。但如果您的小组不是很大,这样做也未尝不可以。

    4) 必须安装.Net Framework 2.0

    5) 必须安装IIS 6.0

    6) 必须安装SQL SERVER 2005SP1,值得注意的是VSTF不支持在SQL SERVER 2005 Express EditionVSTF要求安装Reporting ServiceAnalysis Service,至于Integration Service,则不是必须的。在安装前注意将SQL Server 2005相关的服务设置为自动启动,而且都必须是在已启动状态,否则会导致后续的安装失败,让您不得不又从头再来。

    7) 总结一下安装顺序,而且必须遵照的顺序是:windows2003 -> windows2003sp1 -> IIS6.0 -> .Net framework2.0 ->SQL Server 2005 -> SQL SERVER 2005 SP1

    3.Windows SharePoint Service2.0安装

    1) WSS2.0必须安装带有SP2,下载带有 Service Pack 2 Microsoft Windows SharePoint Services 2.0 的地址为http://go.microsoft.com/fwlink/?linkid=55087下载后的文件名为stsv2.exe

    2) 在微软手册中,WSS的安装提示为使用安装VSTF的用户来安装WSS,为了偷懒,您还是可以使用administrator来安装,实际上并没有多大的区别。

    3) 注意的问题是,在安装提示中,必须选择“服务器场”而不是“典型安装”。WSS安装完毕以后在IIS中应该可以看到“SharePoint管理中心”站点,如果没有看到,那么证明您的安装出现了问题。微软给出的测试输入http://servername,如果页面上出现“建设中”也表示安装成功,实际上这并不能代表什么,在笔者的安装中也出现过,但在IIS中没有看到“SharePoint管理中心”站点,后续的安装出现了错误。

    4) 安装到此,好了,您可以开始安装Team Foundation Server了。

     

    4.VSTF安装过程中出现的问题及其对策

    启动VSTF安装,经过漫长的检测过程以后,也许您以为可以一帆风顺,然而问题总是在您不经意的时候出现。

    错误一:The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 26403.

    安装程序遇到一个非预期的错误在此安装包中。这可能是包中文件被破坏了。错误号是26403

    原因分析:由于安装程序需要将名为TFSIdentity的用户添加到IIS_WPG工作组中,但是由于操作系统中没有这个用户,从而导致的错误。

    对策:创建TFSIdentity用户,将其添加到IIS_WPG工作组中。保险起见,您可以重新启动一次计算机。

     

    错误二:The Commandline '"c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\Bin\Stsadm.exe" ...' returned non-zero value: -2130242250

    命令行"c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\Bin\Stsadm.exe" ...返回非零值:-2130242250

    原因分析:这是典型的因为WSS2.0安装存在问题造成的。

    对策:卸载WSS2.0,重新启动计算机,重新安装带SP2WSS2.0

     

    错误三:没有足够的权限访问ReportServer

    对策:在IIS管理器中修改SQL SERVER 2005Report Server虚拟目录的访问权限,不要使用匿名登录,您可以设置为使用TFSService帐号或者TFSReports帐号来访问。

    5. 结论

    VSTF的安装不是一件容易的事情,因为牵涉到软件或者系统太多,在安装前需要仔细规划,希望本指南对您能有所帮助。如有遗漏欢迎指正。

    Posted May 29 2007, 01:25 PM by wicky with no comments
    Filed under:
  • ActiveReports: Using Custom Paper Sizes

    http://www.datadynamics.com/forums/696/ShowPost.aspx

    The manner in which an ActiveReport is rendered is dictated by the print driver. If the printer you've explicitly assigned for the report (or the default printer for the machine it's being run on if none was assigned) does not support the paper size you've chosen, ActiveReports will render the report on the printer's default paper size.

    If you need your report to show on a custom paper size not supported by the printer, you can use the ActiveReports virtual print driver. The following code in the ReportStart event, or just before .Run is called, will allow you to do so, and to use any paper size:

    .Document.Printer.PrinterName = ""

    The PaperHeight and PaperWidth properties, which take a float value defined in inches, will have no effect unless you set the PaperKind property to Custom. Here is some sample code which can be placed in the ReportStart event, or just before .Run:

    Me.PageSettings.PaperKind = Drawing.Printing.PaperKind.Custom
    Me.PageSettings.PaperHeight = 2
    'sets the height to two inches
    Me.PageSettings.PaperWidth = 4
    'sets the width to four inches

    Posted May 29 2007, 10:30 AM by wicky with 1 comment(s)
    Filed under: ,
  • MD5 Hash SQL Server Extended Stored Procedure

    http://www.codeproject.com/database/xp_md5.asp

    Introduction

    This is an extended stored procedure for Microsoft SQL Server 2000 that implements an optimized MD5 hash algorithm. It is intended to work much like the MySQL MD5() function. The algorithm was taken from here. I only added the md5_string() function. The DLL should work for older versions of SQL Server too, although I have not tested that. The source was compiled and tested on Microsoft Visual C++ 6.0 and .NET 2003.

    Installation

    1. Extract or build the DLL file xp_md5.dll and place it in C:\Program Files\Microsoft SQL Server\MSSQL\Binn (or wherever appropriate). A precompiled DLL is in the Release directory of the source distribution.
    2. Create an Extended Stored Procedure called xp_md5 in the "master" database. Right-click "Extended Stored Procedures" under the master database in the Server Manager and click "New Extended Stored Procedure...". Enter xp_md5 for the "Name" and for the "Path", enter the full path to xp_md5.dll.

      Note: If you want to add it manually:

      USE master;
      EXEC sp_addextendedproc 'xp_md5', 'xp_md5.dll'
    3. Create a user-defined function for each database in which you plan to use the MD5 procedure. Right-click "User Defined Functions" under the appropriate database(s) and click "New User Defined Function...". Enter the following:
      CREATE FUNCTION [dbo].[fn_md5] (@data TEXT) 
      RETURNS CHAR(32) AS
      BEGIN
        DECLARE @hash CHAR(32)
        EXEC master.dbo.xp_md5 @data, -1, @hash OUTPUT
        RETURN @hash
      END
    4. (Optional) Create other user-defined functions to let you specify the data length (for substrings, BINARY and other fixed-width types). In this particular function, we take an IMAGE for input and an optional LENGTH. A negative LENGTH value causes the DLL to try to compute the length of the input automatically (this is the default):
      CREATE FUNCTION [dbo].[fn_md5x] (@data IMAGE, @len INT = -1) 
      RETURNS CHAR(32) AS
      BEGIN
        DECLARE @hash CHAR(32)
        EXEC master.dbo.xp_md5 @data, @len, @hash OUTPUT
        RETURN @hash
      END

    Usage:

    FN_MD5

    The User-Defined Functions can be used as follows:

    -- Sample SQL statement:
    -- fn_md5() tries to automatically calculate the length of the input string
    SELECT dbo.fn_md5('Hello world!');
    
    -- fn_md5x() takes an optional length arg for substrings, fixed-width types, etc.
    SELECT dbo.fn_md5x('Hello world!', 12);

    Output for both statements:

    86fb269d190d2c85f6e0468ceca42a20

    XP_MD5: EXEC xp_md5 <@data> [@length = -1] [@hash OUTPUT]

    To use the Extended Stored Procedure directly:

    -- Sample command:
    EXEC master.dbo.xp_md5 'Hello world!'

    Output:

    86fb269d190d2c85f6e0468ceca42a20

    Or if you want the result saved to a variable instead:

    DECLARE @hash CHAR(32)
    EXEC master.dbo.xp_md5 'Hello world!', -1, @hash OUTPUT
    PRINT @hash

    Output:

    86fb269d190d2c85f6e0468ceca42a20

    Examples

    Collapse
    -- These are just examples for use with the given functions above.
    -- Feel free to create your own functions that take the input type you want.
    -- Use CAST() with caution, as it may truncate and have other unintended consequences.
    
    -- For TEXT, NTEXT, VARCHAR:
    SELECT dbo.fn_md5(data) FROM table;
    
    -- For VARBINARY:
    SELECT dbo.fn_md5(CAST(data AS VARCHAR(8000))) FROM table;
    
    -- For IMAGE:
    SELECT dbo.fn_md5x(data, DEFAULT) FROM table;
    
    -- For CHAR: (we can use LEN() on this fixed-width type to trim the padding)
    SELECT dbo.fn_md5x(data, LEN(data)) FROM table;
    
    -- For NCHAR: (we can use LEN() on this fixed-width type to trim the padding)
    SELECT dbo.fn_md5x(CAST(data AS CHAR(4000)), LEN(data)) FROM table;
    
    -- For BINARY:
    SELECT dbo.fn_md5x(data, 12) FROM table;
    
    -- FOR SQL_VARIANT:
    SELECT dbo.fn_md5x(CAST(data AS VARCHAR(8000)), DATALENGTH(data)) FROM table;

    Miscellaneous

    For purposes of speed, I did not include any real input data verification (e.g., type checking, data length checking, etc.). I opted to exclude that in order to maximize speed, as I originally wrote this for use in an application that inserts millions of rows at a time. I also know that I'm always calling the procedure properly. If you want to make it more robust - like if you do not know what kind of data will be passed to the function - then I highly recommend you add those safeguards.

    One last thing, I added the linker option /OPT:NOWIN98 to minimize the binary size. This may cause a performance hit on non-NT systems (e.g., Win95, Win98, etc.). If you're using the DLL on such a system, I would recompile it without that linker option.

    Cheers.

  • "Recent Additions" (photos) sidebar Item is not Updating in CS 2007

    http://communityserver.org/forums/p/487323/578989.aspx#578989

    What you are looking for is in the \Themes\default\galleries\galleries.Master line 40....

     By default the list is sorted by "PictureDate" which comes from the datestamp of the attachment, and not the datestamp that the post was made to your site.

    <CSGallery:GalleryPostList runat="server">

    <QueryOverrides SortBy="PictureDate" SortOrder="Descending" PageSize="5" />

    you can replace the sortby with "ThreadDate" (which is really the PostDate, its not updated when new comments are added) to change this behavior

    <QueryOverrides SortBy="ThreadDate" SortOrder="Descending" PageSize="5" />

    You may also want to change this on grouplist.aspx line 37, this is where the binding for the "thumbnail boxes" under each gallery name on the photos\default.aspx comes from...  right now it too sorts by the "PictureDate" and not the "ThreadDate"

  • UnicodeEncoding behavior in .Net 1.x and 2.0

    In .Net 1.x, we used to call UnicodeEncoding.GetString(byte[]) to convert byte array to string, and then call UnicodeEncoding.GetBytes(string) to convert it back to byte array.  In .Net 2.0, this approach doesn't work anymore, it's because .Net 2.0 adds some checking to prevent invalid bytes from being converted to string. So after the roundtrip, you may lose something and cannot get the original bytes back.
     
    Here is a good post which discussed this issue and gave a suggestion: Don't Roundtrip Ciphertext Via a String Encoding.
    And here is another one which discussed the changes: UTF8 Security and Whidbey Changes.

    However, if you still want to keep this working, you can try below simple "rip" from System.Text.UnicodeEncoding of .Net 1.x:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    
    using System;
    using System.Collections.Generic;
    using System.Text;</div>
    
    
    namespace MyText
    {
        //wicky.start
        public class UnicodeEncoding
        {
            private bool _bigEndian;
    
    
            public UnicodeEncoding()
            {
                _bigEndian = false;
            }
    
    
            public UnicodeEncoding(bool bigEndian)
            {
                _bigEndian = bigEndian;
            }
    
    
            #region GetBytes
            public byte[] GetBytes(string s)
            {
                if (s == null)
                {
                    throw new ArgumentNullException("s", ("ArgumentNull_String"));
                }
                char[] chars = s.ToCharArray();
                return this.GetBytes(chars, 0, chars.Length);
            }
    
    
            public byte[] GetBytes(char[] chars, int index, int count)
            {
                byte[] bytes = new byte[this.GetByteCount(chars, index, count)];
                this.GetBytes(chars, index, count, bytes, 0);
                return bytes;
            }
    
    
            public int GetByteCount(char[] chars, int index, int count)
            {
                if (chars == null)
                {
                    throw new ArgumentNullException("chars", ("ArgumentNull_Array"));
                }
                if ((index < 0) || (count < 0))
                {
                    throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count", ("ArgumentOutOfRange_NeedNonNegNum"));
                }
                if ((chars.Length - index) < count)
                {
                    throw new ArgumentOutOfRangeException("chars", ("ArgumentOutOfRange_IndexCountBuffer"));
                }
                int num = count * 2;
                if (num < 0)
                {
                    throw new ArgumentOutOfRangeException("count", ("ArgumentOutOfRange_GetByteCountOverflow"));
                }
                return num;
            }
    
    
            public int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
            {
                int count = charCount * 2;
                if ((chars == null) || (bytes == null))
                {
                    throw new ArgumentNullException((chars == null) ? "chars" : "bytes", ("ArgumentNull_Array"));
                }
                if ((charIndex < 0) || (charCount < 0))
                {
                    throw new ArgumentOutOfRangeException((charIndex < 0) ? "charIndex" : "charCount", ("ArgumentOutOfRange_NeedNonNegNum"));
                }
                if ((chars.Length - charIndex) < charCount)
                {
                    throw new ArgumentOutOfRangeException("chars", ("ArgumentOutOfRange_IndexCountBuffer"));
                }
                if ((byteIndex < 0) || (byteIndex > bytes.Length))
                {
                    throw new ArgumentOutOfRangeException("byteIndex", ("ArgumentOutOfRange_Index"));
                }
                if ((bytes.Length - byteIndex) < count)
                {
                    throw new ArgumentException(("Argument_ConversionOverflow"));
                }
                if (this._bigEndian)
                {
                    int num2 = charIndex + charCount;
                    while (charIndex < num2)
                    {
                        char ch = chars[charIndex++];
                        bytes[byteIndex++] = (byte)(ch >> 8);
                        bytes[byteIndex++] = (byte)ch;
                    }
                    return count;
                }
                Buffer.BlockCopy(chars, charIndex * 2, bytes, byteIndex, count);
                return count;
            }
            #endregion GetBytes
    
    
            #region GetString
            public string GetString(byte[] bytes, int index, int count)
            {
                return new string(this.GetChars(bytes, index, count));
            }
    
    
            public char[] GetChars(byte[] bytes, int index, int count)
            {
                char[] chars = new char[this.GetCharCount(bytes, index, count)];
                this.GetChars(bytes, index, count, chars, 0);
                return chars;
            }
    
    
            public int GetCharCount(byte[] bytes, int index, int count)
            {
                if (bytes == null)
                {
                    throw new ArgumentNullException("bytes", ("ArgumentNull_Array"));
                }
                if ((index < 0) || (count < 0))
                {
                    throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count", ("ArgumentOutOfRange_NeedNonNegNum"));
                }
                if ((bytes.Length - index) < count)
                {
                    throw new ArgumentOutOfRangeException("bytes", ("ArgumentOutOfRange_IndexCountBuffer"));
                }
                return (count / 2);
            }
    
    
            public int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
            {
                int num = byteCount / 2;
                if ((bytes == null) || (chars == null))
                {
                    throw new ArgumentNullException((bytes == null) ? "bytes" : "chars", ("ArgumentNull_Array"));
                }
                if ((byteIndex < 0) || (byteCount < 0))
                {
                    throw new ArgumentOutOfRangeException((byteIndex < 0) ? "byteIndex" : "byteCount", ("ArgumentOutOfRange_NeedNonNegNum"));
                }
                if ((bytes.Length - byteIndex) < byteCount)
                {
                    throw new ArgumentOutOfRangeException("bytes", ("ArgumentOutOfRange_IndexCountBuffer"));
                }
                if ((charIndex < 0) || (charIndex > chars.Length))
                {
                    throw new ArgumentOutOfRangeException("charIndex", ("ArgumentOutOfRange_Index"));
                }
                if ((chars.Length - charIndex) < num)
                {
                    throw new ArgumentException(("Argument_ConversionOverflow"));
                }
                byteCount = num * 2;
                if (this._bigEndian)
                {
                    int num2 = byteIndex + byteCount;
                    while (byteIndex < num2)
                    {
                        int num3 = bytes[byteIndex++];
                        int num4 = bytes[byteIndex++];
                        chars[charIndex++] = (char)((num3 << 8) | num4);
                    }
                    return num;
                }
                Buffer.BlockCopy(bytes, byteIndex, chars, charIndex * 2, byteCount);
                return num;
            }
            #endregion GetBytes
        }//end of class
    
    
        //wicky.end
    }