`

代码测试比率、测试驱动开发及行为驱动开发

阅读更多
曾经在项目中接触了TDD和BDD,但是对它们的理解不够深,偶然间在INFOQ看到专家的解答,觉得很多说得有道理,所以分享出来,原文如下

InfoQ:对项目而言,你认为哪些标准会影响你做决定,是采用TDD还是BDD或是什么都不用呢?

    JB:对这个话题做概述,我觉得有点不合适,莫不如让我来说明下,我在什么时候会用到TDD和BDD,以及这么做的理由吧。

    我第一次接触TDD是因为我试图寻找一种方法来减少代码中的错误(也叫代码缺陷或Bug)。曾经,我在程序中引入的错误数量让我一度认为自己永远都无法完成编码——不管我怎么努力,都看不到任何希望。我猜测,如果那个时候,能自己测一下代码,就能找到许多简单、愚蠢的代码并自己修复掉。TDD对我来说,并不只是为了不让别人觉得你写的代码有多糟糕,而是避免你错误地认为自己已经完成了编码,却留下一大堆Bug。然而,TDD帮我解决了这个问题,多年之后,我还意识到TDD不仅帮我避免了程序逻辑的错误,更帮我减少了程序设计中的问题。在我运用BDD之后,我发现BDD帮我减少了许多在选择特征与完成特征时的错误。日复一日,我逐渐明白代码的错误不仅让我费时费力,也让我无法按时完成编码工作。这个时候,我开始在项目中贯彻实施TDD与BDD的方法。

    让我们再回到问题本身,我鼓励大家去思考为什么你们需要做TDD,想想你的理由。不要限于典型的实施TDD与BDD的理由,例如:更好的设计、更少的程序缺陷、更有商业价值的产品特征以及更少的无用功。我鼓励人们多思考一下驱动你这样做的原因,这才是重中之重。我相信你会发现,一旦你采用了这两种方法,必然能按时完成分配的任务,因为这会让你更有条不紊,而不是到后来手忙脚乱。当然,我认为这些理由是因人而异的。

    Dan:首先允许我给出一些定义。TDD是一种编程技术,它引导程序员思考自己的代码是如何被其他代码所使用,从而避免由代码实现引起的“意外设计”(emergent design)。你首先要写一个测试来描述如何使用下一块代码,然后实现这块代码,并保证它通过测试。这项技术是需要编程技巧的,并且需要考虑何时进行合适的运用(我稍后会展开)。这样做有很多优点,编写测试帮助你理解行业知识并帮助你更好地去命名。一个测试可以发现理解上的差异(“你认为在这个用例中应该怎么做?”),当然,一整套自动测试可以帮助我们发现回归测试中的缺陷。

    我并不认为我们必须决定是否在这个项目中采用TDD,你几乎可以在任何一个项目中使用TDD。然而,我建议程序员在采用TDD前思考一下,这样做是否有价值。不可否认的是,除了TDD,我们还有其他很多方法可以用来做设计、对某个行业探索和建模以及减少回归测试的风险。有些项目,最有效的方法是逐一采用这些方法,而有些项目不是。不夸张地说,我认为TDD是每个程序员都应该了解,并知道如何去做的、很有用的方法。对于重构,我也持有相同的意见——你必须去了解这个方法,但你需要时间的磨练,去区分何时何地采用这种方法,或转投他法。

    BDD是一种开发方法,形式类似于极限编程(XP),但不能把它单单看成是TDD的一种实现方式。BDD的作用是把利益关系人、交付团队等不同方面的项目相关人员集中到一起,形成共同的理解,共同的价值观以及共同的期望值。如果你没有碰到过这样的难题,那就可能是哪里出问题了。当然,我也是最近才渐渐地运用起这种方法,之前我都是与较小的团队一起工作,通常也能有比较迅速和通畅的利益关系人反馈。因此,由理解不同而造成影响的情况比较少见。通常,利益关系人会说:“这里你能帮我改一下吗?”或者“这不是我想要的,我来举个例给你。”

    BDD会从业务目标着手,将这些目标与产品特征和故事衔接起来。BDD提供了如何确定你的验收标准的建议,以及你如何将这些标准落实到决定代码行为的自动测试上。如果你的项目决定采用BDD方法,那就必须从整个项目的层面上来考虑问题(尽管你可以在子项目中运用BDD),而且必须拉上整个团队一起做。

    我赞成以下说法:只要能够提交合格的代码,那么每个程序员或配对编程的人员就都有权利以他们所偏好的方式交付软件。如果他们打算使用TDD,我们就应该支持他们这样做。如果他们打算做些其他的,只要团队成员没有问题,我们也可以允许。

    Gojko:这取决于你如何定义TDD和BDD。看起来,在过去几年间,TDD的定义被局限在仅仅作为设计的单元测试。而BDD则变成以实例和业务导向的测试来驱动功能的、涵盖所有开发阶段的方法。根据Brian Marick在《Agile Testing by Lisa Crispin and Janet Gregory》中的敏捷测试象限的定义,TDD应该在第一象限,而BDD在第二象限。我并不完全同意这点,但既然你的问题是什么是影响你采用TDD还是BDD的标准,我假设你对TDD的定义是排除在BDD与其他方法之外的。基于这点,我们分析以下三个方面:

        这是个一次性项目吗?是否为了将技术的不确定性降到最低,从技术层面,帮助团队了解他们最终想要什么?在这种情况下,维护很多自动测试用例集合都是一种浪费,而且极有可能团队真正需要的只是一小部分相关联的简单用户用例。因为我们不清楚技术壁垒,所以编写技术测试可能会是个问题。我可能会选择写一些指导性的测试,而非教条式地为每个设计写一段单元测试。这符合Steve Freeman和Nat Pryce所著的有关《成长性面向对象软件》的大型系统测试。
        项目的复杂度是否由技术所决定?我们是否认同我们所要完成的是技术上的,而非业务逻辑上的风险和不确定性?是否所有项目相关人员都是技术出身,能够读懂代码?例如:搭建Web框架的项目、数据库平台的项目、查询系统的项目、或是云部署平台的项目。众多开源项目都可以归为这几类。如果是这样,那么偏技术的TDD就比较适用了——我会用单元测试工具来驱动业务场景和技术设计。我可能还会在白板上写些例子以求得到普遍认同(BDD的核心概念),但我不会浪费时间把这些例子录入到可执行用例或非技术自动工具(Cucumber)中了。
        项目是否也有复杂的业务逻辑需要讨论,或者存在不清晰的业务需求,需要在不懂编程语言的成员之间沟通的情况?如果是,我将各个击破。先使用实例来探讨业务需求,确保大家对业务有共同认识。然后为这些实例建立规格说明书,并将这些实例录入到诸如Cucumber、FitNesse或类似的自动工具中去。最后,用单元级别的测试来驱动代码的设计。

    Ron:我多希望在过去的半个世纪的开发生涯中,我能够在每个项目中都运用这两种方法。我并没有发明这两种方法,我只是最早接触的那几个人之一。TDD和BDD让我确信,没有更好的方法了,这两种方法也让我的代码缺陷数量大大降低。并且,当我更好地了解到系统或产品该设计成什么样子时,我的设计就更得心应手了。

    TDD和BDD太难被超越了。

    Steve:你需要为你的系统写测试吗?如果需要,为何不在代码实现前就写完呢?这样一来,你就能知道怎么把测试变得更简单。你也并不可能把所有的测试用例一下子都写完,何不边写代码边完成测试用例呢?

InfoQ:现在似乎有种普遍的认识,认为TDD等同于单元测试,而BDD则等同于验收测试(无论使用的是哪种工具)。你们认为这种说法是否正确?其他类型的测试例如构件测试与系统集成测试 又是如何与TDD/BDD关联的呢?

    JB:我想从两个方面谈这个问题:TDD对我的设计提供了反馈,而BDD则是对我们开发的产品理解提供了反馈。起初,我以TDD作为一种测试技术开始实施,慢慢地我把TDD作为设计手段,再后来把TDD作为一种深入了解产品设计原理的方式。而对于BDD,我则一开始把它作为提醒我从真正终端客户和利益受益者的角度看待产品的一种方法,最终变成改进业务与技术人员之间沟通的一种技巧。你可以看到,虽然测试在其中扮演着配角,却举足轻重。

    我并不把TDD和BDD当作测试技术,我认为测试策略与TDD/BDD是无关的。无论项目使用TDD,还是BDD,还是什么都不用,我都期望从微测试(microtesting)、系统测试和可用性测试的角度来考虑这个问题。

    Dan:这真的是不幸的历史产物。事实上,TDD和BDD都涵盖这两种测试,甚至更多。Kent Beck在极限编程(此后在他的TDD书中)中说到——TDD在不同等级粒度中均能适用,这也契合Nat Pryce和Steve Freeman在《成长性面向对象软件》所描述的。你撰写用户级别的功能测试与低级别的单元测试的目的是相同的,都是为了阐述你希望代码如何表现。TDD的激励作用多过于实际意义:如果你只为了得到更多的自动测试覆盖率而撰写自动测试用例,那不是TDD。类似地,你可以测试诸如并发、延迟、failover或吞吐量等非功能性需求。

    BDD之中用户级别测试与代码级别测试的区别更加明显。用户级别的测试是基于自我澄清和自动化的场景。并且这些构建的步骤可以在其他场景中重用。代码级别的测试也叫做实例(或者规格Spec,虽然我不倾向于这么叫),与TDD相比更接近人的思考方式。时过境迁,有不少不同类别的工具出现。比较有名的有:用户级别的跨语言工具Cucumber,以及代码级别的工具RSpec、NSpec等。我的经验是,我倾向于使用团队喜欢的工具。比如,大部分的BDD源码,我用过时的JUnit与JMock的Hamcrest matcher library编写。最近,我用Python的py.test和nodeunit来写node.js,这与JUnit风格类似,“BDD风格”的框架在两者中均有体现。因此我的建议是,这只是代码,如何实现它由你决定。

    Gojko:同样,这取决于你对TDD,BDD以及其他概念的定义。我对Kent Beck著作的理解是用户测试与单元测试属于TDD范畴。而我对Nat Pryce和Steve Freeman的《成长性面向对象软件》中的理解是TDD包括系统测试,构件测试以及单元测试。我对规格说明书的解释是好的文档会将业务概念拆分,并自动化,以求风险得到控制——如果大部分的风险来自于一个实例,我们则需要验证实例的Java方法;如果风险来自系统,我们则需要对系统进行30次的Web服务运行和100次数据库运行。

    Ron:BDD起源于TDD的另一种描述。而现在,在Chris Matts和Liz Keogh手中,BDD演化成实现产品特征描述与验收测试的方法,这也是我所理解的BDD描述。

    而其他形式的测试,当然也很重要。我特别指出,我们需要把用户体验测试加入到你的测试列表中。关于构件测试和系统集成测试,敏捷项目的最佳方式是使用持续集成(Continuous Integration)。这样,所有分散的构件就能关联起来,集成的系统所能承受的测试也随之增加。通常,这些分类很模糊。我们针对不同事件,在不同的间隔运行不同的测试集,比如:新的类库或构件,或新构建的版本。这样的测试集包含了用以描述单元测试、验收测试等所有的测试用例。 测试的精髓在于,分清什么需要测试,尽量在创建或有变化的时候就进行测试。这就是我们防止代码缺陷和及时发现代码缺陷的秘诀。

    Steve:我可不会做这样的类比,很明显,这是基于对TDD的错误理解。TDD中最基本的问题是“我怎么知道这样是可行的?”——所有的业务和组织都可以这样去考虑问题。

    我并不认为将测试细分成筒仓(silo)会有多大帮助,相反顺畅的测试给团队带来自信,相信系统能够正常运行。

InfoQ:一直以来,TDD被公认为是一种(代码)设计准则、测试准则或沟通工具。然而,在TDD方法中,作为这些准则和工具的目标会如何影响设计?在测试方面,TDD现在与未来的价值又是怎样的?

    JB:我认为这很大程度上取决于方法的实践者。当我实践TDD的时候,发现最有价值的部分是测试规范这块,这可能是因为我期望在这个方面有所提高。而只有当我的错误数大幅度地减少时,我才注意到TDD是如何帮助和指导自己改进设计。在你实践TDD的时候,所有这些都指向对测试的当前价值的个人感受:你可能期望从其他测试中获益。

    我觉得测试的当前价值远比未来价值要高得多。虽然从未这样试过,但我曾经打算在几个月后把测试都扔掉,仅当我需要改进某些东西的时候才去重写测试。

    我从未在不是我编写的测试上获益,我也不认为这会对我所工作的项目有什么样的帮助,或是对TDD实践者的基本规范有什么样的贡献。对此我有所顾虑,就好象合同工走进要装修的房间,然后对之前的装修出言不逊。

    我曾经宣称, TDD风格的测试会起到变更探测器的作用(引用Cem Kaner的术语),用来减少代码变更的代价。我也听到过有人像我这么宣称。尽管没有仔细地度量过,但的确见识过TDD所带来的益处。我甚至听说有人宣称,这些测试可以为从未了解系统和API的人,讲述清楚其中的内容。对我而言,这些益处仍旧是理想化和理论上的。

    Dan:TDD是一种设计规范,每样东西都有两面性。在 “测试驱动”这个词组中,“测试”这个词很不幸。 你所写的用来描述行为的实例并不是测试,你所写的代码也只是简单的实例。这些实例只有当与类似持续集成等实践联系在一起时,才成为一套的回归测试。但这些无法代替测试的需求,特别是代替类似Brian Marick和James Marcus Bach所倡导的有技巧的、直接的探索性测试。TDD测试的另一个特性就是它的决定性。在回归测试中,这是一个优势,但在发现阴暗角落方面(译注:指不易发现或重现的Bug/Defect)做得却不怎样。随机化的测试技巧能够帮复杂的系统找出许多细微之处,然后你就可以利用TDD逐个解决。Haskell和Scala的QuickCheck工具就是个很好的例子。

    关于沟通,这是TDD的主要目的之一。特别是在你需要向其他程序员讲述你的代码意向的时候。在文章《Introducing BDD》中,我描述了有含义的命名方式对测试起到了多么大的帮助。否则,你就无法得知你的测试用例失败时所揭示的真相。你必须能够像读故事一样地去理解TDD测试用例,而出色的测试命名则决定了功能文档的易用程度。

    Gojko:我认为答案总是位于这些因素的平衡点上。为了将TDD作为一种规范,我们必须找到一种方法来完成所有事情。好的单元测试,能够指引设计。但也必须能够帮助我们缓解关键技术难题带来的风险,并且告诉人们设计的代码应该怎样表现。

    Ron:TDD会用到测试,但不仅仅是测试而已。它是我们开发系统的方式,是所有测试和程序的骨架。TDD以及其他相关实践让我们逐步地、一个特征接一个特征地开发系统。从始至终,它保证了代码的活性,以及可塑性。这让我们更清楚地了解我们究竟完成了什么,也让产品负责人或管理者清楚下一步要做什么,不论是通过揭露代码满是缺陷,或者设计是错误的,或者我们不能太快地改进。这也极大地减少了在项目最后阶段才了解到坏消息的可能性。

    我不认为这些目标是“独立的”。好的软件开发,需要整合很多想法,也需要我们平衡很多目标。我们并不想放弃这些,相反,我们希望能够找到一种方法服务于所有的目标。而这一切,让开发产品变得更快捷。

    Steve:当发觉沟通决定着其他方面的结果时,我必须强调所有级别测试中的沟通因素。例如:如果我致力于把一个测试用例写得可读性很高,这真的也能帮我发现对象引用的不恰当。 我见过很多团队陷入过维护性很差的测试用例的泥塘,而从拖累了整个进程。特别是在新的理解或概念出现的时候,你必须像对待生产代码一样(甚至超过)谨慎地对待测试代码。

InfoQ:关于单元测试、集成测试以及验收测试比率的自动化以及相应的维护成本,有哪些准则可以告诉大家?

    JB:在团队实践TDD一到两年的时候,我不停地接到团队的消息,向我倾诉测试成本与收益的不平衡。每次这种情况发生,往往是因为团队尝试用较大的测试集(集成测试,系统测试以及端到端测试)去检验较小的事情(独立对象的具体行为)。这往往会导致更大的测试套件,更频繁地运行测试套件(一个失败意味着23个测试失败),也会降低程序员维护测试用例的信心和兴趣。这样的测试,反而会给项目带来负面影响。

    在这种情况下,我建议为微行为编写微测试,然后合并微测试。契约式测试是通过连接相邻层(adjoining layer)的接口,来检查这个层,不会再深入。这就意味着从集成测试及系统测试转移到检查我所指的“基本对错”上——例如:在无限的时间与空间的条件下,这个对象是否能得到正确的计算结果?我所说的“集成测试是骗局”就是这个意思。

    尽管对于不同的项目,不同的团队,要具体事件具体分析,但我还是强烈地建议程序员们从集成测试和系统测试转向微测试。

    Dan:我不认为对于比率的建议会行之有效,对我而言,这甚至会有风险。如果某个错误出现的可能性较高,或某个错误的影响较大,我会花更多的时间去解决。举例说明,我曾希望以测试驱动的方式编写转换数据的代码,因为我知道把转换数据搞糟是多么容易,而发现错误又是多么的困难。类似地,如果我在为系统的外围交互模块写代码,我会非常非常小心需要传送和接受的数据。一旦发现Bug,我就会编写一段测试用例来隔开这个Bug,并且用测试驱动的方式去修复它。其他时候,我会用REPL(一种命令行接口的语言)来实践,并找出Bug。

    Gojko:我想这个问题过于宽泛,没有一个具体的项目,我没法给你答案。

    Ron:比起“把这些事情做起来”,我并没有更好的答案。运用TDD及相关的实践方法进行编码,花费的成本会更少,结果也会更好。有些人或团队认为,如果他们运用TDD,搭上的时间会更多,这也是解释得通。也许会存在一些真实的开发情况,但我并没有找到。通常来说,这些人比较简单,也并不喜欢TDD。这样做的后果是,他们认为自己会很快速,但得到的只是不停增长的缺陷数。这些缺陷必须消除,却使设计变成恶梦,反过来又增加了缺陷,使缺陷不易被发现和修复,从而拖慢整个进程,让进程变得异常困难,造成恶性循环。往往在项目最后的几周,他们最后只能收到坏消息。

    这就是“死亡行军”(译注:越做错越多,越无法收拾)。当然,有些人或产品也能侥幸“活”下来。但遗憾的是,花如此大的时间和精力“活”下来,会让团队以为,所有项目都必须这样完成。(译注:感触颇深,同时有过3个项目,我带2个,另一个PM带一个,我的项目成员几乎不用在UAT前加班,氛围也非常好;另个项目天天加班,士气低落,民不聊生)。这才是大错特错!在有更好、更简单的选择的时候,他们几乎将自己逼进绝路。

    Steve:我没法给出答案,除非你已经为相同的团队搭建了可辨识的系统。敏捷方法的基本要领就是对应已发生的情况。同样重要的一点是这些比例会随着项目进程而改变。

InfoQ:除了至关重要的系统,现在似乎比较统一的说法是100%的测试覆盖不能作为一个目标,也是不实际的。你是否认为代码/测试比率能提升测试的注意力和效率吗?

    JB:正相反,如果组织重点关注在这些目标,那么就无形中创造出灾难的、会受到炮轰的“成熟模式”。你懂的:级别1表示“我们写测试”;级别2表示“我们为所有新代码写测试”;级别3表示“我们对系统做50%的覆盖”;我假设级别5表示“我测试故我在”。我认为这是没有意义的事情,我可以做这些,但结果还是交付了垃圾的产品。我觉得这是对我所教和我所崇尚的实践的一种嘲讽。

    当我有我自己的“网络瞬间(Network moment)”时,我开始关心起这些事情了——你知道的,“我像个疯子,我再不会接受这些!”我尝试让人们学会有自己的“网络瞬间”,然后给他们建议如何去解决问题。我相信比起目标式的测试覆盖率,这更有效。

    Dan:我认为教条式的代码测试比率恰巧有着相反的作用。这意味着所有的代码都是同等重要,具有相同的风险,这样的想法是错误的。相反,我提倡对不同的代码,采用不同关注程度及审查力度的测试。任何企图达到代码统一的测试覆盖率的机会成本都是疯狂的,特别在用户接口测试方面。把时间和精力放到改进需要重点关注的代码的质量上,会更加行之有效,立竿见影。

    Gojko:只关注代码覆盖率很可笑。关注在10%的风险最高的代码比关注99%可忽略风险的代码,收益要多得多。我认为风险覆盖比起测试覆盖要重要得多。我偏好使用属性构架能力矩阵(Attribute Component Capability Matrix),然后决定什么需要覆盖及怎样去覆盖。(详见James Whittaker的《How Google Tests Software》一书——译注:好书一本!)

    Ron:测试覆盖率永远都不该成为我们的目标。如果我们的测试很棒,那么我们势必能找到缺陷,这是显而易见的。那缺陷还会在哪里呢?在我们没有测的地方。因此覆盖率并不需要做得美好,只要“够用”就足够好了。我们需要做两件事情:

    首先,我们需要不停地提升我们的测试技巧,那样我们测不到的地方就会越来越少。如果我们仅仅做TDD的教条是没有意义的——“为得到失败而写测试(译注:为了找到错误而拼命地写更多的测试)”。我们会自然而然地得到完整的代码覆盖,以及很好的路径覆盖。

    第二,我强烈建议团队分析测试覆盖和这类信息,这样才能更好地决定什么需要改进。人无完人,但我们必须警觉,如果发现了缺陷,那么我们就需要回顾所发生的情况,补充漏掉的测试用例,保证将来不再发生。

    Steve:我还是认为,在数据和划分不清楚之前,这是评价会有失精准。代码覆盖率有用,但作为外部的、过分强调的目标,也会影响团队应有的关注程度。

InfoQ:TDD、BDD、验收测试驱动开发(ATDD),测试优先等等这些,对不同的人都意味着不同的东西,也容易让人搞浑。我们是否需要一种通用的语言,用以描述我们的软件开发方法并培养一种可达成共识的内容驱动的好实践呢?

    JB:不,我不这样认为。我想对每个实践,我们都有足够多的术语来描述。我发现,当我停止担心如何去定义它们、去分享我是如何理解、并鼓励人们分享他们的理解的时候,反而会有意想不到的收获。我还记得,我最有影响力的一次关于TDD和BDD的定义、意义和目的的讨论,发生在临晨4点半的一家旅馆的房间里。那次讨论,我言辞激励地与人争论Dan North和Chris Matts。如果我们只是推动大家在社区网站上发布某些定义集,而抵制形式上更生动的、有点疯狂的、激烈的辩论,这将是非常遗憾的事情。

    Dan:这只是我们对这块领域发展的理解的一个征兆。我起初建议把BDD用作辅助传授TDD的目的。我喜欢Gojko Adzic的名言“将规格说明书实例化”,只因它很清晰,没有歧义。很长一段时间中,我在“测试”、“实例”和“规格说明书”这些专用词汇中挣扎,我无法做出我的选择。有个短语“通用语言”本身就是有误导。“通用”指的是在边界之内的世界。换句话说,我们依据内容对同样的事物做出不同的描述。某人的测试是另一个实例,也是另一个规格说明书。这关乎你是否能将你的意图很好地传达到你的内容中。

    Gojko:我尝试用实例来定义规格说明书,将其变得更清晰、有内容边界并把范围缩小,就是为了避免TDD、BDD、ATDD或其他概念的混乱。我认为这个命名对实践的探索很有意义;对我们从业务角度确定要开发的系统并运用实例和搭建在线文档作为支持,也很有意义。某些建议和实践对此是有用的,有别于当我们用技术测试来驱动设计时所用的那些实践与建议,他们有自身的价值。

    我不喜欢ATDD或验收TDD这个命名,因为这给人们一种错误的印象,让大家觉得是因为关注在错误的事情上所以才造成失败。我希望人们不要这样思考,但不幸的是近期出版的书籍已经使用了这个名称。

    我理解的BDD是,包括了很多不仅仅是规格的实例,并以单元测试驱动技术设计。例如,我考虑特征注入(Feature Injection)、拉动需求、外围设计、定义商业价值的模式以及诸如此类的BDD事件。这些才是Liz Keogh所做的激动人心的事情。当然,除了这些实例化的规格说明书或单元测试,还是有很多其他事情可以做。例如,效果映射(Effect Mapping)是又一项令人激动的、全新的计划与路演的技术。这与整个BDD的系统价值完美地符合,将测试驱动拔高到业务对象的层面,并对任何形式的自动化都没有关联,也无需去做。

    Ron:好吧,我认为这是人类沟通的方式。这个世界上并不存在一种每个人听到都能理解的、清晰的语言。在我们边学边成长的商业世界,差异是不可避免的。在我眼中,最重要的差异是人们花很少或不花力气去理解这是些什么东西。相反,他们要么没有理解就开始诋毁这些建议;要么就是没有真正地去运用这些建议或没有理解地去运用这些建议,只是宣称他们在做这些。

    这样做有两个严重的后果:第一,许多项目和个人不去做他们可以做的。这将导致人员对工作的不满、失败的项目以及糟糕的结果。第二,误解通常会减缓大家对这些好建议的运用。

    Steve:当我们拥有完美的准则时,就能把它归纳成术语 我认为现在讨论什么技术该运用在什么地方还为时过早。我还认为不同的“领域“该有更宽泛的范围,用来获知他们的不同,但不至于弄个底朝天。

InfoQ:关于这些主题有什么最后寄语?

    JB:没什么特别的。多多地实践那些技术吧,因为你希望它们能指导你改进工作。去做吧,因为这能给你“个人成功”。去做吧,只因它能帮助你更好地享受你的工作。总之,无论什么原因,去做吧!

    Dan:我在这里讲的每个主题,今后我将分享更多我的感受。

    Ron:尽管我会在项目中运用其他方法,但在半个世纪里,我所用的所有方法中,这些是我见过最好的方法,虽然我不会强迫每个人都去使用。

    然而,我将做的是,我会建议关心这方面专业的每个人都能学习如何去运用这些技术……到一个“很好的程度”,然后拥有能够决定何时、何处使用它们的能力。在能够对某种技术进行客观的评测前,你不该去回避这种技术。

    因此我将要做的是,展示给大家我所要做的软件开发,让大家放心、大胆地去尝试这些技术。并且能够让人们对此类技术有较好的口碑,愿意花足够长的时间去做出一个好的决定。

    对我而言,好的决定是指能够在正确的时间正确地使用这些实践。我希望大家能发现这些技术的价值,并从中获益。

    Steve:较常见的是,我所看到的关于TDD的主要问题,都不是测试难题,而是基本设计技巧的缺憾;人们之所以对测试比较纠结,是因为代码有着错误的结构。类似地,我看到过代码不能表现清楚。我越来越觉得,程序员的面试应该包括一个测试预选者编写一段可读性强的段落的测验。

分享到:
评论

相关推荐

    原生js图片圆形排列按钮控制3D旋转切换插件.zip

    原生js图片圆形排列按钮控制3D旋转切换插件.zip

    类似c++数组的python包

    内含二维数组与三维数组,分别为list2nd,list3rd

    原生js颜色随机生成9x9乘法表代码.zip

    原生js颜色随机生成9x9乘法表代码.zip

    原生js实现图片叠加滚动切换代码.zip

    原生js实现图片叠加滚动切换代码.zip

    【Academic tailor】学术小裁缝必备知识点:全局注意力机制(GAM)TensorFlow

    【Academic tailor】学术小裁缝必备知识点:全局注意力机制(GAM) 注意力机制是深度学习中的重要技术,尤其在序列到序列(sequence-to-sequence)任务中广泛应用,例如机器翻译、文本摘要和问答系统等。这一机制由 Bahdanau 等人在其论文《Neural Machine Translation by Jointly Learning to Align and Translate》中首次提出。以下将详细介绍这一机制的背景、核心原理及相关公式。 全局注意力机制(Global Attention Mechanism, GAM)由 《Global Attention Mechanism: Retain Information to Enhance Channel-Spatial Interactions》提出,是一篇针对计算机视觉任务提出的方法。这篇文章聚焦于增强深度神经网络中通道和空间维度之间的交互,以提高分类任务的性能。与最早由 Bahdanau 等人提出的用于序列到序列任务的注意力机制 不同,这篇文章的重点是针对图像分类任务,并未专注于序

    基于SpringBoot的“篮球论坛系统”的设计与实现(源码+数据库+文档+PPT).zip

    本项目在开发和设计过程中涉及到原理和技术有: B/S、java技术和MySQL数据库等;此文将按以下章节进行开发设计; 第一章绪论;剖析项目背景,说明研究的内容。 第二章开发技术;系统主要使用了java技术, b/s模式和myspl数据库,并对此做了介绍。 第三章系统分析;包罗了系统总体结构、对系统的性能、功能、流程图进行了分析。 第四章系统设计;对软件功能模块和数据库进行详细设计。 第五章系统总体设计;对系统管理员和用户的功能进行描述, 第六章对系统进行测试, 第七章总结心得;在论文最后结束章节总结了开发这个系统和撰写论文时候自己的总结、感想,包括致谢。

    毕业设计&课设_iOS 商城项目,含购物与商家管理功能,用 Sqlite,有账号示例,适合 iOS 开发练习.zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。

    镗夹具总工艺图.dwg

    镗夹具总工艺图

    原生js树叶数字时钟代码.rar

    原生js树叶数字时钟代码.rar

    近代非线性回归分析-韦博成1989

    近代非线性回归分析-韦博成1989

    Rust语言中冒泡排序算法的高效实现与优化

    内容概要:本文详细介绍了用 Rust 语言实现冒泡排序算法的具体步骤,以及通过设置标志位来优化算法性能的方法。示例代码包括了函数定义、内外层循环逻辑、标志位的应用,并在主函数中展示了如何调用 bubble_sort 函数并显示排序前后的数组。 适合人群:具有基本 Rust 编程基础的学习者和开发者。 使用场景及目标:适用于想要深入了解 Rust 中冒泡排序实现方式及其优化技巧的技术人员。通过本篇文章,能够掌握 Rust 基本语法以及算法优化的基本思想。 阅读建议:除了仔细阅读和理解每一部分的内容外,还可以尝试修改代码,改变数据集大小,进一步探索冒泡排序的时间复杂度和优化效果。此外,在实际应用时也可以考虑引入并发或其他高级特性以提升性能。

    培训课件 -安全隐患分类与排查治理.pptx

    培训课件 -安全隐患分类与排查治理.pptx

    1-中国各地级市的海拔标准差-社科数据.zip

    中国各地级市的海拔标准差数据集提供了298个地级市的海拔变异性信息。海拔标准差是衡量某地区海拔高度分布离散程度的统计指标,它通过计算各测量点海拔与平均海拔之间的差异来得出。这一数据对于评估地形起伏对网络基础设施建设的影响尤为重要,因为地形的起伏度不仅会增加建设成本,还会影响信号质量。此外,由于地形起伏度是自然地理变量,它与经济社会因素关联性较小,因此被用作“宽带中国”试点政策的工具变量,以研究网络基础设施建设对经济的影响。数据集中包含了行政区划代码、地区、所属省份、所属地域、长江经济带、经度、纬度以及海拔标准差等关键指标。这些数据来源于地理空间数据云,并以Excel和dta格式提供,方便研究者进行进一步的分析和研究。

    YOLO算法的原理与实现.pdf

    YOLO算法的原理与实现

    机器学习用于视网膜病变预测:使用 XGBoost 揭示年龄和HbA1c 的重要性 -论文

    视网膜病变是糖尿病和高血压的主要微血管并发症。如果不及时治疗,可能会导致失明。据估计,印度三分之一的成年人患有糖尿病或高血压,他们未来患视网膜病变的风险很高。我们研究的目的是检查糖化血红蛋白 (HbA1c)、血压 (BP) 读数和脂质水平与视网膜病变的相关性。我们的主要假设是,血糖控制不佳(表现为高 HbA1c 水平、高血压和异常脂质水平)会导致视网膜病变风险增加。我们使用眼底照相机筛查了 119 名印度患者的视网膜病变,并获取了他们最近的血压、HbA1c 和血脂谱值。然后,我们应用 XGBoost 机器学习算法根据他们的实验室值预测是否存在视网膜病变。我们能够根据这些关键生物标志物高精度地预测视网膜病变。此外,使用 Shapely Additive Explanations (SHAP),我们确定了对模型最重要的两个特征,即年龄和 HbA1c。这表明血糖控制不佳的老年患者更有可能出现视网膜病变。因此,这些高风险人群可以成为早期筛查和干预计划的目标,以防止视网膜病变发展为失明。

    RL Base强化学习:信赖域策略优化(TRPO)算法TensorFlow实现

    在强化学习(RL)领域,如何稳定地优化策略是一个核心挑战。2015 年,由 John Schulman 等人提出的信赖域策略优化(Trust Region Policy Optimization, TRPO)算法为这一问题提供了优雅的解决方案。TRPO 通过限制策略更新的幅度,避免了策略更新过大导致的不稳定问题,是强化学习中经典的策略优化方法之一。

    Spring 应用编译为原生可执行文件.zip

    1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。

    1-中国各地区普通小学毕业生数(1999-2020年)-社科数据.zip

    这组数据涵盖了1999至2020年间中国各地区普通小学毕业生的数量。它为我们提供了一个深入了解中国教育领域中普通小学阶段教育水平和教育资源分配情况的窗口。通过分析这些数据,可以为制定科学合理的教育政策提供依据,同时,通过比较不同城市的普通小学毕业生数,也能为城市规划和劳动力市场调查提供参考。数据来源于中国区域统计年鉴和中国各省市统计年鉴,包含了8472个样本,以面板数据的形式呈现。这些数据对于掌握中国教育态势具有重要的参考价值。

    原生js制作拖拽排列排序代码.zip

    原生js制作拖拽排列排序代码.zip

    PixPin截图工具,非常好用的一款截图工具

    PixPin截图工具,非常好用的一款截图工具

Global site tag (gtag.js) - Google Analytics