TopCoder Component Development Tutorial(组件开发说明书)

【写在前面】

    想研究TopCoder整点小外快,翻来找去只找到 @Xviewee 在2008年翻译的文章,由于年代久远,我对TopCoder组件开发说明书更新到最新版,看他的原文点这里,首先对他的工作表示感谢!
    TopCoder Component Development Tutorial 英文版原文看这里
    如果发现本文有任何错漏敬请告知,感激不尽。
    本人小菜,想着能在TopCoder上攒经验顺带挣些小钱,若能有大神可以指导一二,带一带上路,感激不尽。
    此外,如果有志同道合的朋友们可以一起交流开发经验,那是再好不过了,一起争取早日进步嘛。
    最后说一句,转载请注明出处,谢谢。

1  简介(Introduction)

1.1   TopCoder组件开发

   TopCoder使用包括 C#、Java、C++、Ruby、Flex、JavaScript 在内的多种语言,尽管这语言有较大差别,但开发过程都差不多。本指南将由始至终涵盖整个开发过程。在不同语言差别较大的地方,会分别给出相应的说明。

1.2   开发流程

    总体上说,TopCoder组件的开发流程比较简单。你的任务就是按照组件设计文档开发组件并交由评审团(DesignReview Board)进行审查。通过审查称为优胜者之后,你还需要根据审查团提出的整改要求对组件进行修正,最后通过终审(Final Review)就行了。

    TopCoder 提供了很多关于设计和开发流程的文档(对于某些简单直接的组件,设计这一步骤会被省略,此时你获得的会是需求说明书而不是设计文档。),你需要仔细阅读软件开发文档。包括成员指南(Member Guide)、开发设计(DevelopmentDesign)、审查记分表(Review Scorecard),这些文档告诉你到底要提交些什么。

1.3   所需软件

    你可以在任何环境下编写你的代码,但是我们依靠特定的技术构建组件并对其打包;另外,我们还需要每种语言的公共库,具体包的列表如下,除此之外还有一个UML公用工具

1、C#:

(1)  Microsoft .NETFramework v3.5:如果你喜欢用C#进行开发, 你可能已经安装了此工具。

(2)  NUnit:这个框架可以让你简单快速的测试你的代码,有关测试的内容后面会详细描述。

(3)  MSBuild:微软和VS的构建工具,有关构建的内容后面会详细描述。

(4)  TC CodeDocumenter:一个编写API文档命令行工具,类似 JavaDoc。

(5)  NCover:代码覆盖工具。

2、Java:

(1)   SunJAVA SE 5.0+:Java开发要注意使用最新的JDK。

(2)   Ant:一种执行可定制、可扩展构建脚本的工具,你需要用它编译工程和向 TopCoder 提交代码,后面会细说构建脚本的内容。

(3)   JUnit:用于单元测试,具体内容后面说。

(4)   SunJAVA EE:只有少数组件需要用到这个包,具体看需求文档。

(5)   Checkstyle:一种格式检查工具,提交之前最好用他来检查一下你的代码。

(6)   Cobertura:Java代码覆盖分析工具,用来检查你的代码被单元测试覆盖的百分比。

    确保系统环境符合MSBuild/Ant 的需求,注意xUnit的安装位置,随后的构建脚本配置里面会说明。

1.4   注册

    参加开发竞赛之前,你必须在 TopCoder公司网站上注册。注册之后,你不仅可以提交你的设计和开发作品, 而且可以参加其他 TopCoder 竞赛,包括算法(algorithms),概念模型(conceptualization),规格说明书(specification),架构(architecture),应用装配(application assembly)以及测试(testing)还有马拉松赛(marathon),点击这里注册。

2  挑选项目(Picking A Project)

    项目选题是竞赛取胜的第一步,你可以在这里找到所有开放的程序开发竞赛。该页面中,你可以看到项目的开放情况、注册、提交的截止日期。这些日期非常重要,你必须在注册截止日期(Registration End)前确定你对哪个组件感兴趣,并在提交截止日期(Submitby)前提交你的作品,包括测试文件和文档。

    作品第一名获得奖金,第二名获得一半奖金,评分标准分值名为“DR point”,有关他的更多内容看这里

2.1   项目细节

    点开你感兴趣的项目,你会看到有关这个项目的更多细节。包括项目信息、文档链接、论坛链接、报酬信息以及综合时间点。

2.2   决定是否参加

    找到感兴趣的项目之后,第一步你要详细查看项目设计文档,最简明的文档就是需求规格说明书(Requirements Specification),它包含这个项目会用到的各种技术的信息(如SSL,LDAP,ODBC 等)。如果你依然兴趣不减,可以继续阅读组件说明书(Component Specification),它包含了实现这个组件的更多细节信息。当然,还有其它一些文档,但是这两个文档对决定一个项目是否适合你是最重要的。

    选择一个项目之前,请确保你有足够的时间完成它。项目期间,你是否有其他的安排和工作要做?另外,项目可能会用到一些你并不熟悉的技术。你知道在C#中怎样使用数据库连接吗?你知道怎样使用java.lang.ref 类库吗?你充分了解完成这个组件所需要的网络协议吗?最好重新阅读一下组件说明书的1.2、1.3 节和第二节,确保你对所用到的技术比较了解。

2.3   项目注册

    现在,你发现你可以胜任并有时间去完成某个项目,就可以注册了。点击项目细节页面的注册链接进行注册。

3  项目启动——环境配置(Getting Started--Environment)

    完成注册后,你将有权限访问项目提交程序,并且可以参加组件的开发人员论坛。

3.1   项目提交及评审

    项目提交和评审是你参加程序设计和开发竞赛的核心枢纽。通过这个应用程序,你可以上传你的作品,查看评审得分。点击这里登录,你可以看到自己所有开放的项目及其状态。点击相应的项目名称可以查看该项目的时间表和其它细节信息。在页面底部,有一排对应项目当前状态的按钮。另外,还有一个“Contact Product Manager”按钮,你可以随时点击该按钮向项目经理(Project Manager,PM)发送问题、评论、投诉以及其他信息。

3.2   开发者论坛

    项目细节页面上有一个指向其开发论坛的链接。绝大部分关于项目的交流、讨论将在此处进行。你可以使用你的 TopCoder 账户、密码登陆所参与项目的论坛。如果不能登录,请及时与项目经理联系。

3.3   开发包

    开发人员论坛主要包括四部分:设计阶段文档(Design Phase Documents)、设计阶段问题(DesignPhase Questions)、开发阶段文档(Development Phase Documents)和开发阶段问题(DevelopmentPhase Questions)。你可以在开发阶段文档下找到开发包,其中包含所有与项目开发相关的文档和文件。

通常,Java 开发包是jar 文件,.NET 开发包则是zip 文件,它们都可以用普通的解压工具解压。

3.4   目录

/conf:此目录如果存在,则会在此目录包含组件的配置文件,有时还会包含所依赖组件的配置文件,或组件设计者写好的配置文件的例子。如果在设计阶段没有创建这些文件,开发包里面将没有这个目录。

/docs:此目录包含组件当前的所有文档。包括 .tcuml 格式的 UML 设计规格,需求说明书和组件说明书。有关设计文档会在后续章节中详细介绍。

/src:当你完成这个项目的时候,此目录应该包含了所有源文件。开发包通常只包含一个目录框架。开发者负责填充源文件,这将在后续章节详细介绍。

/test_files:此目录包括组件测试过程中用到的全部文件。包括测试所需的特殊配置文件、输入/输出样例、数据库方案和其它任何非编译文件。开发包中一般会包含设计者创建的样本测试数据。

1、Java:

/META-INF:这个目录由jar 打包程序生成,可以忽略。

/build.xml:这是一个缺省的,可能未加配置的构建脚本。构建脚本的内容会在后续章节详细介绍。

/build-dependencies.xml:这是一个包含了组建的依赖、定义的构建脚本碎片,相关内容随后详述。

/build.version:包含了项目元信息的配置文件,包括名称、版本、源目录以及包定义。

2、C#:

/<projectname>.sln:一个VS解决方案文件包含以下两个项目。

/ComponentSources.csproj:这个项目文档包含了主要源代码(在主目录里)。

/ComponentTests.csproj:这个项目文档包含了测试源代码(在测试目录里)。

/Build.dependencies:项目的依赖性定义,随后详述。

/Build.version:包含项目元信息的配置文件,包括:名称、版本、源目录以及包定义。

/README.txt:这个文件描述了如何装配和构建这个组件。

3.5   设置开发环境

    首先,你需要设置一个工作目录。例如C:\working\、C:\proj\、~/projects/;任何你觉得合适的地方。建议为 TopCoder 项目建立一个新的目录,防止混乱,避免提交一些错误的文件。在这里,我们假定工作目录为/proj/tc/。

    确定了工程放置的目录,就可以解压开发包了。目录 /proj/tc/projectname将是你的工程目录。这里,我们假定工程名字为 tutorial_gen。

    下一步是配置构建脚本。记住TCS不会使用你的构建脚本,不要在它上面花太多时间。按照下述说明修改路径和库文件引用即可。如果遇到很棘手的问题,你可以向项目经理核实。

1、Java构建脚本——build.xml

    你需要在构建脚本里配置cobertura 的路径,把注释部分修改成正确的值,大部分情况下,这样就已经可以了:

            <property name="cobertura.dir"value="${ext_libdir}/cobertura/1.8"/>

2、Java构建脚本——build-dependencies.xml 

    如果你无法添加JUnit 的 jar 包到你的 classpath 里,那么就需要把它放净构建脚本里,去掉下面的注释,并把路径修改成正确的值:

       <property name="junit.jar" value="${ext_libdir}/junit/4.6/junit.jar"/>

    如果你的工程需要额外的库文件,你需要在构建和运行前通过配置构建脚本来解决这个问题。在脚本中,应该有些注释掉的库文件的例子。

       <property name="spell_check.version" value="1.0"/>
       <property name="spell_check.jar.name" value="spell_check.jar"/>
       <property name="spell_check.path" value="spell_check/${spell_check.version}"/>
       <property name="spell_check.jar" value="${tcs_libdir}/${spell_check.path}/${spell_check.jar.name}"/>

    这样,稍作修改即可对库文件的不同版本进行配置,你可能已经注意到了对${tcs_libdir} 的引用。它应该在脚本文件的开始部分就已经做了如下定义:

       <property name="tcs_libdir" value="lib/tcs" />

    这个配置将在/proj/tc/tutorial_gen/lib/tcs/spell_check/1.0/spell_check.jar寻找拼写检查的库文件,你可以按需要修改构建脚本里面的一些路径或者文件名。

    你必须将你的组件构建和运行时所要用到的所有包都包含在内,虽然这部分工作可以依赖classpath,但将所有需要的包在这里配置好是一个好的习惯。

    有关 TopCoder 的目录依赖关系可以看这里

3、Java——topcoder_global.properties

    或许你已经注意到,开发包中的build.xml 包含对文件“../../topcoder_global.properties”的引用。通过这个文件,你可以设置一些不随组件而变化的属性,如JRE1.3 的路径。

    格式很简单(适用于所有的Java 属性文件):propertyname=value

    首先,在工程目录下创建 topcoder_global.properties文件(如果当前工程是 /proj/tc/tutorialgen,你的属性文件将放在 /proj/tc 下面)。现在,你可以设置对所有构建脚本的通用属性。

    对于JRE,你可以添加:

         java_1_3_bootclasspath=C:\Program Files\JavaSoft\JRE\1.3.1_10\lib\rt.jar

    你也可以添加注释:

         # I need a comment to remember what this means.
         java_1_3_bootclasspath=C:\Program Files\JavaSoft\JRE\1.3.1_10\lib\rt.jar

    还可以使用扩展属性:

         java_home=C:\Program Files\JavaSoft\JRE\1.3.1_10
         java_1_3_bootclasspath=${java_home}\lib\rt.jar

    需要注意的是,topcoder_global.properties引用在build.xml 的最起始部分。这意味着build.xml不会在你的配置文件里进行扩展(因为还没有定义)。此外,topcoder_global.properties 中设置的属性会覆盖build.xml中的属性。想了解更多相关信息,请查看Ant文档

4、C#构建脚本

    有关两个项目(组件源码和测试源码),有一些宏观上的构建目标,但都没有包含在开发包里,你可以点击这里下载到他们。下载完成之后解压,把目标文件放到你项目的父目录里。例如你当前项目的路径是 /proj/tc/tutorial-gen,你的目标文件就应该放在 /proj/tc 里面。

    MSBuild脚本很容易配置,因为项目文件可以直接用VS打开,直接打开解决方案文件,把两个项目添加到你的目标项目作为项目引用依赖,就完成了。

    项目依赖可以通过手动的编辑 Build.dependencies 文件来完成。找到源码或测试源码的相应部分,在包含有依赖关系的 ItemGroup 部分添加你的项目需要的东西,例如:

    对于TCS组件:

       <Reference Include="Hera.EPC.Data, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
          <SpecificVersion>False</SpecificVersion>
          <HintPath>lib\Hera.EPC.Data.dll</HintPath>
       </Reference>

    对于第三方库:

       <Reference Include="log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905">
          <SpecificVersion>False</SpecificVersion>
          <HintPath>lib\log4net.dll</HintPath>
       </Reference>

    对于 .NET 系统库:

       <Reference Include="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
          <RequiredTargetFramework>3.5</RequiredTargetFramework>
       </Reference>

    可能还有另外一些由设计者或者项目经理提供的设计文档,例如配置示例以及数据库设置。

3.6   开发过程

    正如第一节所述,你在开发过程中的角色就是实现已经创建并通过审查的设计。你应该严格遵循设计文档中给出的公共API。未经项目经理和/或设计者许可,你不得擅自修改组件的公共API,包括增加或删除public 类、方法和接口。这并不是说设计会毫无瑕疵;恰恰相反,所有的设计都有改进的空间。然而,对设计的不同意见要在设计中修正,而不是开发。在开发实行的过程修正设计方案是不合适的,除非其存在致命缺陷。TopCoder 会对设计的任何改动进行细致审核。

    如果你对下个修订版有任何的改进意见和见解,请在论坛上指出。开发过程中遇到的问题也请立即在论坛上提出来。设计上的任何冲突和问题越早明确,就能越早解决。如果可能,可以阅读一下设计论坛中的相关讨论,可能这个问题已经提出并被解决了。再强调一次,如果你发现任何没有解决的问题,请在论坛上提出来

    上面所说的一切,都是为了鼓励你们尽可能的做出改进。如果你能把 public类的行为分解成私有辅助类,那就去做!如果你能提出一个更加有效的算法,那太棒了!设计中你不能改变的只有公共API 及从用户角度来说组件的行为。对于一个组件,一般来说,你不可以改变“是什么”,但是有一定程度上改进“怎样做”的自由。

3.7   开发创新

    不同的设计允许不同程度的开发创新。其一方面是设计本身复杂度的原因,另一方面是设计者的方法问题。或许有的设计方案对组件描述的如此彻底,以至于组件编码变成了将组件说明书中的伪码翻译成合适的程序设计语言。或许有的设计方案仅仅给出了公共API 的定义,而将实现细节留给了开发人员。大多数设计方案则是介于这两者之间。

    方法体的具体实现一直是程序开发者展现才华地方。对某些设计方案,添加private 或packageprivate的方法、构造函数,甚至设计文档中没有明确说明的类都是可行甚至必要的。如果你真要这么做,请确保这些改动是必要而且适当的,因为这些地方可能会引起评审团额外的注意。开发人员所添加的内容(和组件中的其他元素一样)应有最小作用域,并且予以与其用途一致的最严格的访问控制权限。对于一个任务,确保采用最恰当的对象或者基本数据类型。

3.8   生成占位程序(Stubs)

    具体开发的第一步是生成站位程序。站位程序是可编译的代码框架。其中你可以找到函数体;然而,这仅仅是一个站位程序。这些站位程序刻画了组件的全部API,但并没有实现其内部逻辑。TopCoder 使用的UML工具可以帮你生成占位程序。你获得的这些站位程序很可能无法成功编译,需要你对它们稍加整理例如在 .NET 组件中可能存在一些设计人员添加的针对系统类型的代码,这些东西你要删掉才行。

    站位程序的另一个问题是关联部分。UML 文档里面的一些关系(例如聚合、组合)可能会被不适当的转化成了代码。程序开发人员负责维护API 文档(UML 文档和组件说明书)和可编译代码的一致性。

3.9   项目结构

    工程的源代码应该放在项目的 /src 目录下,且应具以下结构(在示范项目的 /proj/tc/tutorial_gen/ 目录下):

路径

描述

conf/

所有必须的配置文件

docs/

和工程有关的所有文档

lib/

所有本地库文件

src/

所有源代码(包括测试代码)

test_files/

所有非编译的用于测试的文件

1、Java

    组件代码放在/src/java/main/目录下。你需要根据包名来组织你的源代码。例如,如果组件是com.topcoder.util.tutorial ,那么源代码路径应该是/src/java/main/com/topcoder/util/tutorial/。下面是典型的Java 路径:

路径

描述

lib/tcs/spell_check/1.0/spell_check.jar

对于这个例子,这里表示 Tutorial Generator项目依赖的库,你的组件可能不需要任何依赖库,也可能依赖多个

src/java/main/

组件有关的所有代码应该放在这里

src/java/main/com/topcoder/util/tutorial/

对于这个例子,这里是放占位程序的好地方,对于你自己的项目,这个路径会有所不同

2、C#

    组件代码放在/src/csharp/main/目录下。你需要根据包名来组织你的源代码。例如,你的组件是TopCoder.Util.Tutorial.dll ,你的源代码路径就是/src/csharp/main/TopCoder/Util/Tutorial/。尽管C#的命名空间不要求目录和包名完全一致,但是根据命名空间来安排的源文件是TopCoder 的惯例。下面是典型C#路径:

Path

Description

lib/TopCoder.Util.SpellCheck.dll

对于这个例子,这里表示 Tutorial Generator项目依赖的库,你的组件可能不需要任何依赖库,也可能依赖多个

src/csharp/main/

组件有关的所有代码应该放在这里

src/csharp/main/TopCoder/Util/Tutorial/

对于这个例子,这里是放占位程序的好地方,对于你自己的项目,这个路径会有所不同

3.10 构建你的项目

    生成并整理好站位程序后,你应该可以通过构建脚本来构建你的组件了。你只需从命令行里指定构建目标然后运行构建工具即可。

    以下是 Ant 的常用构建目标:

目标名

描述

compile

把工程编译成功能完全的二进制单元(如果你的代码正确)

compile_tests

编译测试代码,需要 compile的成功执行

test

执行测试,需要 compile_tests的成功执行,测试的结果可以在 /log 目录找到

coveragereport 

执行测试并生成测试覆盖报告,你可以在 /log/coverage目录找到结果

clean

清除 /build目录,删除所有已经编译代码以及项目的中间文件

dev_submission

生成一个已经打包好的提交包,让你在项目完成后提交

    以下是MSBuild的常用构建目标:

目标名

描述

Build

编译 .cs 源文件到 /build 目录下

Test

(在测试项目中运行)运行测试并且输出单元测试结果到 /log

NCoverReport

(在测试项目中运行)生成组建的测试覆盖报告并存放于 /log

FxCop

(在测试项目中运行)生成装配信息,诸如可能的设计、位置、性能以及安全方面的提升

Doc 

(在测试项目中运行)生成组件的javadoc方式的 API 文档

Dist

基于 Build,生成组建部署的二进制分布

CleanSolution

清除 /build以及 /log 目录,删除所有已编译代码

    如果要执行构建,只需要移动到构建脚本的目录(应该是工程的根目录),并执行 ant <target> 或者MSBuild<project> <target>。确保你已经配置好Ant/MSBuild,否则这一步将无法执行。

    点击查看NAnt的构建示例以及Ant的构建示例

    你的组件站位程序应该总能完全干净利落地按照占位程序构建。如果它们不能成功编译,可能是API 的问题,也可能是库文件的配置问题。在编写代码和测试前就修正这些问题会简单的多,如果可能,你也应该这样。

3.11 告一段落

    到这里,你已经为工程的具体开发做好了准备。有关程序开发技术和策略方面的具体问题已经超出了这份文档的范畴。在接下来的几节中,我们将介绍有关文档、单元测试和开发过程中的一些常见问题。

4  提交必备——文档(Documentation)

    文档对一个组件的可用性和可维护性至关重要。如果在写的同时就对代码添加文档,你或许根本就不会感觉到写文档的负担。评审团会评估文档质量。并且,文档越好,评审团就越容易看懂和评估你的作品,得分也就越高。

4.1   API文档

    你需要对从 UML 文档自动生成的 API 文档进行修改,而不是把它当作最终版本。在Java 中,API 是通过 Javadoc 来注释的,C# 中则是通过 XML 文档来注释。所有的类、接口、方法和变量都必须具备文档。以下是分别是Java 和 C# 的文档例子:

1、Java

    当键入如下内容,很多Java IDE(如Eclipse,IDEA 等)就可以自动生成API 文档:

/**
* Saves the file to permanent storage, on the path specified by configuration. The path
* must not begin with a backslash, and must not contain any special characters (see component
* specification). If the filename cannot be used, an exception will be thrown.
*
* @param filename The filename to save to. May not be null or empty.
* @throws IllegalArgumentException If filename is null.
* @throws IllegalArgumentException If filename is not valid (zero length, invalid characters, etc).
* @throws IOException If an error is encountered while saving the file.
*/
public void saveAs(string filename)

    更多有关 javadoc 的内容请点击这里

2、C#

    Visual Studio.Net 会在你编写代码的时候自动生成大部分 XML 文档,只需要在声明前面输入///即可。

/// <summary>
/// Saves the file to permanent storage, on the path specified by configuration. The path
/// must not begin with a backslash, and must not contain any special characters (see component
/// specification). If the filename cannot be used, an exception will be thrown.
/// </summary>
/// <param name="filename">The filename to save to. May not be null or empty.</param>
/// <exception cref= "ArgumentNullException">If filename is null.</exception>
/// <exception cref="ArgumentException">If filename is not valid
/// (zero length, invalid characters, etc).</exception>
/// <exception cref="IOException">If an error is encountered while saving the file.</exception>
public override void SaveAs(string filename)

虽然C#中不会对throws 语句进行检查,但是在API 文档中注明该方法可能产生的异常是个好习惯。有关 XML 文档的更详细信息请点击这里

4.2   文档内容

    解释组件的行为,非法输入及相应的异常行为。明确对象因为某种操作而发生的变化(对List.add(object)而言,这可能显而易见;而对 List.screenedAccept(object,bool) 来说,可能就不是那么明显了)。务必注明方法的返回值、可能抛出的异常和所有的参数。此外,每个类和接口都需要有个概括性文档,以解释其作用以及在组建中的位置。还要有这些内容(除了exceptions以及enumerations)的线程安全情况说明。此外,编写样本配置以及组件的主要类的作用也是个好习惯。

    请不要在组件中包含任何个人标识信息。任何需要用到你的TopCoder 账号(handle)的地方(例如@author 标签),请用 TCSDEVELOPER代替,保证客观、公平。如果你成为了获胜者,你可以在修正(Final Fix)阶段将 handle 写入自己的组件。

4.3   文档读者

    API 文档的读者将是组件的使用者,也即 TopCoder 软件的客户。在文档中请保持专业口吻,注意使用主动语态,语言尽量具有描述性,要考虑到组件的使用者可能没有你对语言和组件这么熟悉。

前面已经说过,从UML 直接产生的文档不是合适的最终版本。例如:SaveAs 函数可能会有如下的文档:

Pullthe path info from the config file, then append the filename passed in.Attemptsto save the file to that location, throws exception otherwise.

InvalidInput: null, blank, funny characters, non-fs safeValid Input: everything else

Throws:IOException on failure, InvalidArgumentException if it is.

    这段文字描述了 SaveAs 函数的功能;但是,它更多的是为程序开发者自己写的,而不是其用户。你可能想删除其实现细节,而又清晰准确的解释函数的行为。然而,俏皮话可能对内部人员适用,但是对用户来说是不行的。请将这些条目熟记于心,当你完成一个函数的时候,请重写其API 文档。

4.4   内嵌式文档

    内嵌式文档是一段代码中解释代码功能的文档。内嵌式文档是为组件使用者以及TopCoder 改进所用的。和任何其他程序设计过程一样,你注释得越详细,代码就越容易维护。x++,一个简单的自增语句,没有必要注释;但是你写成 loopIndex++ 或者 recordCount++可能更合适。如果一段代码的意图不甚明显的话,你可能就需要添加一些注释了。

4.5   必备文档

    关于API 文档和内嵌文档并没有硬性规定,对它们的评审将会比较主观,然而以下几项是基本要求,牢记这些准则可以在文档方面获得高分:

1、 所有文件必须有 TopCoder 版权声明;

2、 所有 public 的 API 元素必须要有详细的文档注释(参数,返回值,异常类型),注意:包括单元测试在内;

3、 所有比较复杂或者庞大的代码段都必须包含内嵌式文档以解释其目和功能;

4、 文档必须具备专业口吻以及高质量。

5  提交必备——单元测试(Unit Tests)

    组件无论大小都需测试。测试的目的是保证组件对各种输入均有正确的行为,也即保证鲁棒性。我们的单元测试风格起源于极限编程。你不一定要以这种风格来编程,需要获取有关极限编程和单元测试方法论的更详尽的信息,请参这里或者这里

    在极限编程中,测试先行。当然,这不是必须的,但非常有效。程序API 很大程度上是不变的, 这使得对照其写测试用例成为可能,而不需要管是否能通过。随着你的开发进度,不断测试,你的组件将会通过越来越多的测试。

5.1   何为单元测试?

    单元测试是程序功能模块最细微的测试(测试功能的每个单元)。通常,这意味着需要单独测试所有非private 的方法和构造函数。单元测试既需要验证程序在合法状态和输入下的行为(包括极限情况),也需要验证其在所有可测的出错情形下的异常行为。

5.2   测试范围

    单元测试的范围可以尽可能的广,有时候单元测试的代码量甚至会超过被测试的代码量。

    组件的所有public 函数都必须有相应的测试:包括准确性测试和异常测试(对应合法和非法的输入)。测试面越广,组件的bugs 就越容易暴露。要想覆盖所有的输入情形是非常困难的(有时甚至是不可能的)。但是,输入覆盖面越大,组件就越可靠。

除了这些小的、原子性的测试,你也应该创建测试来查看你的组件是否始终提供了所期望的功能。

5.3   创建你的测试

    第一步是在 src 文件夹下创建单元测试的目录,每种语言因测试目的而有细微不同。

    创建 C# 单元测试的示范看这里

    创建 Java 单元测试的示范看这里

5.4   单元测试技巧

    将所有的单元测试放在一个函数中听起来非常有诱惑力。但是,这样会极大地降低测试的效果。在上面的例子中,我们可以简单的将三个测试函数组合成一个:testSaveAs()。现在我们只有一个测试函数,而不是三个。如果三个当中任何一个失败的话,整个测试将失败。在大规模测试中,这种组合测试的方法论将会导致失败条件的混乱,测试的调试将变得困难。测试用例越小,功能越单一,错误点和可能的原因就越明显。以下是一些单元测试的技巧:

1、 总是对组件说明书中的demo实现测试用例;

2、 总是在assert和fail 调用中提供有意义的信息;

3、 总是像注释组件代码一样注释测试用例,编写文档也一样;

4、 把测试用例组织成离散的 TestCase 类, 如果一个 TestCase 已经难于管理, 别犹豫,把他拆成两个或者更多的类;

5、 将TestCase类中的测试用例拆分成尽可能小的功能集;这样,组件的哪部分出现了问题就一目了然。你也可以用测试用例通过和失败的情况作为组件完成与否的标准;

6、 通过使用 setup()和 teardown() 来减少重复代码,增加鲁棒性;

7、 时间允许的情况下,用尽可能多的合法或非法输入对每个public 函数进行测试;

8、 测试组件期望的流程。比如:载入数据、处理数据、保存数据;

9、 不要忘记清空测试环境。单元测试后,系统应保持在测试前的状态,而不是产生了持久的影响。此问题将会在评审过程中进行检查;

10、 除了对测试框架的特殊意义,测试类在各方面都是正常的类。这些类可以继承介于它们自己和最终测试间的类,可以包含非测试用的方法,并且有状态;

11、 因为它们和被测试的组件类处于同一包或命名空间下,单元测试可以访问具备 package-private访问属性或者 protected访问属性的类及其成员;

12、 接口不能直接测试,但是可能存在以接口为参数的方法。这种技术使得验证组件是否对于接口类型的域和参数有正确的行为、组件是否正确处理了此类方法调用时抛出的异常潜力巨大;

13、 所有的配置文档和其他要用到的资源都应该放到测试目录里;

14、 有时候,一些依赖关系在组件最终完成之前是无法验证的,这个时候你就需要编写一些模拟类,或者使用类似 JMock 或者 EasyMock 的模拟工具,但在使用前请务必向项目经理进行确认;

15、 永远不要把数据库连接信息硬编码进代码里,请确保它在一个单独的文件里进行配置,这样可以使得测试和构建过程变得更简单灵活,这条原则也适用于其他配置信息(例如网络配置)。

6  提交必备——问题(Problems)

    在开发过程中,你可能会遇到一些问题。或许你需要额外的组件,或许组件本身设计的有瑕疵导致开发无法进行。你或许对设计者的意图感到疑惑,或许对组件使用的技术感到不解。别担心,你并不孤单。如果发现设计有任何不明确的地方,你都可以在组件论坛中进行提问(从Project Submit & Review 进入)。你可能会遇到一些设计者没有考虑到的情况。你可能错读了组件,或者没有注意到一些事项。任何情况下,组件本身相关的问题都应该在组件论坛中说明。

    另一方面,如果你在写代码过程中遇到了困难,或对某种技术不甚了解,或者遇到了某种程序bug,你可能就需要去 TopCoder 自由讨论区(Round Tables)而不是开发论坛了。要去自由讨论区可以查看这里,其中一般讨论区或组件竞赛讨论区是寻求帮助的合适地点。自由讨论区是一些经验丰富的TopCoder 成员和TopCoder 软件职员经常光顾的地方,他们都会尽可能提供帮助。

    如果你遇到一些问题,使你不能继续你的组件,请立即给项目经理发Email。这些问题包括文件缺失或者错误,访问或者应用程序问题,重大的设计问题等。你可以通过组件的Project Submit & Review Details 页面给项目经理发Email。如果你不能访问上述页面,请发email给support@topcoder.com

rel=”nofollow”

linktype=”raw”

linktext="support@topcoder.com|mailto:support@topcoder.com">support@topcoder.com">support@topcoder.com

    请注意写清楚你正在开发的项目以及碰到的问题的详细描述。

    readme 文件不是一个好的交互方法。如果需要对组件做任何大的改动,你必须与组件设计者和项目经理联系。

7  提交(Submission)

    艰苦的工作已经结束,此时你的组件已经通过了所有150 个测试,可以准备提交了。

    首先,你需要检查你的代码,确保尽可能符合评审条款,一些细枝末节的问题也会在稍后的评审过程中降低你的分数。确保你的目录结构符合要求。

    其次,你要确保你的代码可以编译通过。

    最后,执行dev_submission,生成最终的压缩包。务必检查一下你写的所有文件是否全部包含其中,需要的话加入缺失的文件。你的提交需要包含单元测试成功执行的日志文件,conf/ 目录下的所有文件,test_files/目录下的文件及目录。如果有时间的话,你可以将归档文件解压到另外一个目录下重新构建以确保成功。

    如果你对自己将要提交的归档文件已经比较满意了,就可以通过Project Submit & Review 上传了。

7.1   让你的作品出类拔萃

    想要在开发竞赛中胜出,你必须使你的提交出类拔萃。对于简单、比较具体的组件来说,这是一个诀窍;即使对于较复杂、抽象一些的组件来说,也应当给与足够的重视。有多种方法让你提交的作品脱颖而出,这里给出几点建议:

1、写简洁、清晰而高效的代码。虽然这方面没有明确的评审条目,不过评审员总是喜欢那些对他们来说易读易懂的代码。高效的代码可以使你的程序在压力测试和基准测试中表现优异,从而得到一些额外的分数。

2、单元测试务必全面。你可能会为测试不足付出高昂的代价,因为在评审条目中有好几条是关于单元测试的。单元测试应该覆盖所有非私有方法,并且需要良好的文档注释。在测试方面的良好表现会是赢得组件的重要砝码,因为单元测试是很容易被忽略的部分。

3、提供卓越的文档注释。类和方法的文档是由开发人员负责,但是似乎很少有人给它应有的重视。良好的文档必须清晰,容易理解。了解并熟悉Javadoc 的文档。例如:任何HTML标签都可以插到文档注释中,适当的应用这种特性将会非常有效。试着站在别的程序开发人员的角度问自己:你想要知道组件的什么信息,然后将其写下来。了解并遵循Sun 或Microsoft的文档注释指南,以及相关如何写API 规范的文档。

4、完全符合要求,提供所有要求的功能。或许,这是理所当然的;但是任何差错都会减少你获胜的机会。小心特殊情况和非正常输入。

5、注意任何设计者忽视的问题。比如:线程安全,可移植性(即使是Java 或者.NET也存在移植性问题)。请在设计框架内仔细斟酌,使你的提交具备想要的特性。

8  评审(Review)

    一旦提交,评审团就会对你的作品按照以下标准进行评分,在评分之前会有一个筛选阶段,你可以点这里查看一个筛选评分卡的示例,点击这里你可以找到一份非常详细的评分卡总结,在这里你可以看到一份评审积分卡的示例。

8.1   功能

    功能评审是最重要的,评审团会检查你的作品是否已经实现了所有的需求、是否已经提供了设计文档里定义的所有功能、是否用合适的技术来完成(例如是否恰当地连接了数据库、是否使用了恰当的XML配置)。如果你在对组件设计中指明使用的复杂算法进行了改进,也是非常值得鼓励的,但如果你不确定你使用的算法是否正确,请在论坛提问。

8.2   定义  

    另一个重要的方面是你的作品中的变量和声明是否和设计文档中的定义完全一致(可视性、类型、修饰词、名称、异常列表)。未经设计者或者项目经理同意,不得删除、添加或者修改任何非私有API。你可以创造新的功能类或函数,但应当把他们的作用域缩减到最小。

8.3   代码

1、 评审团会对代码中的对象类型进行检查,看是否做出了最好的选择,例如你可能会使用决定用一个TreeMap 去存储一些键值对。然而,除非你需要保持键的相对顺序,否则你应该使用HashMap 。在这里,“最好的选择”通常是与效率相关。不要写无用和臃肿的编码,不要有代码冗余,你的代码应该是清晰明了且尽可能精简的;

2、 这项可能有些主观,但是也有客观参照:你一般不应该对三元选择运算符进行套嵌(例如: good ? "great!" : ok ? "I suppose" : bad ?or_is_it ? "darn" : "phew" : "who knows?"),这样的代码非常不清晰。同样的,对于大段的代码,如果某个方法超过了50行,那就把它拆分成多个函数。例如说你正在画图,你应该要有一个 drawAxes() 方法、drawData()方法和一个drawLegend()方法,而不是一个非常大的代码块。效率方面,很小的改进也可以产生明显的效果。当你已经达到期望值的时候,从查找中跳出。智能设置控制条件,运用短路求值法。不要把你的代码写的过于复杂,能简化的尽量简化。

3、 所有代码,包括测试用例,都应当遵循TopCoder 编码规范。我们的编码规范是已发布的Java和C#标准。你可以通过以下链接查看:

Java编程规范

.Net编程规范

8.4   文档

    完成的代码必须附带关于类、方法和变量的详细文档,并以 Java/C# 编码标准所要求的Javadoc/XML风格编写。文档语法必须正确:不能有描述不存在的元素的文档、不能有晦涩难懂的文档。更详细的信息请参照前文有关文档的内容。

8.5   单元测试 

1、 单元测试应该正确、彻底地测试了所有的方法和构造函数。单元测试应当包含一个演示组件如何使用的Demo,该demo需要在要求的环境中完成。例如:对于 web 组件,你的 demo 应当以web 应用的形式给出。

2、 单元测试应当合理配置测试环境,不能在测试之后还有任何的文档或连接处于打开状态,经常在tear-down方法中清理环境是个好习惯。

3、 应当像注释组件代码一样注释单元测试。此外,三个程序评审员都会写单元测试,以探查你提交的组件的精确性、适当的异常行为以及压力测试的表现。基于以上各方面的测试结果,你的组件将会获得一个评分。

9  申诉(Appeals)

    评审结束后,你将有几天时间查看你的组件得分并进行申诉。你将看到分数卡上关于以上每一条的评论,而且可以为分数进行争辩。需要注意的是,你的申诉必须理由充分,否则将会被拒绝。如果评审员的陈述与设计相冲突,或者评审出现了差错,不要顾忌,申诉!另外,观念性的问题一般不要申诉。如过你是组件的获胜者,在修正阶段你将有机会讨论评审员的评判。

10    修正(Final Fixes)

    祝贺你!你是组件的获胜者!

    然而,仍然有一些工作需要你去做。你可以通过Project Submit & Review看到评审分数卡。在那里,你可以找到评审团提出的所有有关你的提交的问题。它包括对提交作品必需的和推荐的修正。

1、 必须项是必须解决的,任何一项没有完成,你的工作都不能结束;

2、 推荐项则需要你尝试去解决。显然,他们的优先级仅次于必须项,如果时间允许,也应该完成;

3、 别忘了把你的作品里的TCSDEVELOPER 改成你自己的账号(handle)!

10.1 交流

    在修正阶段,交流比在其他任何时候都重要。

    无论什么原因,如果你对评审有疑问或意见,及早提出来。如果问题严重,请立即致信项目经理,并且发布于论坛上,他将会查看这些问题,并确保主评审员(Primary Reviewer)会来解决这些问题。如果你觉得一些必需项是不可能做到的,请在论坛上提出来。绝对不要重复提交没有修正的组件或者仅仅在 readme 文件中声明这些问题。和评审员保持联系,以避免发生上述情况。你反映得越及时,提供的资料越详细,这个过程就会越顺利。和评审团交流的大门将一直对开发人员敞开,他们可能没有注意到设计或者你提交作品中的某些细节。不要害怕对评审团提出质疑。质疑和评论表明你在关注这些问题,并在积极参与。没有交流,评审团将无法阐明他们的要求,也无法得知你做了什么工作。

11    最终提交审核(Final Submissionand Review)

    这仅仅是一次dev_submission 的构建过程。遵循同样的指导原则,保证上传了所有文件。使你的提交尽可能完善。这样将节省所有人的时间,包括你自己。

如果你的提交已经满足了所有要求,通过了所有评审的测试,组件也就完成了,并将添加到目录中。你的工作也就完成了。

    注意,如果有任何工作没有完成,你会被打回 Final Fixes。

12    奖金(Prizes)

    再次祝贺!到了这一步你就已经可以获得奖金了,但要注意再接再厉!

12.1   可靠性奖金

    对于你最近完成的15个组件开发任务,如果他们的评分都比较高,你将可以获得奖金。详细内容可以看这里

12.2   DR奖金

  Digital Run可以让你获得更多奖金,有关它的内容看这里。PlacementPoints定义了过去提交的作品中通过评审的数量,有关它的内容看这里

13    总结(Conclusion)

    再次祝贺你!经过注册、开发、测试、提交、被审查、申诉、获胜、修正并再次提交,你得到了报酬,并且还可以从你所做的工作中得到版税!有什么庆祝方式会比再注册一个新的项目并且完成它更好呢?


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值