零雨其蒙's Blog

做优秀的程序员
随笔 - 59, 文章 - 13, 评论 - 58, 引用 - 0
数据加载中……

[翻译]Driven to … Discovering Your Design Values

 

Driven to … Discovering

Your Design Values

驱动……发现你的设计价值

Rebecca J. Wirfs-Brock

There will be variations of everything forever. … Ideas don’t disappear. They change form,

they merge with other ideas. —Bob Frankston, coinventor of VisiCalc

万物永远都是变化的……思想没有消失。它们改变了形式,它们并入了其他思想。——Bob FrankstonVisiCalc发明者

Today we have design or development approaches that are, for example, responsibility driven (RDD), test driven (TDD),behavior driven (BDD), domain driven(DDD), and model driven (MDD). Not all thought leaders in software development have been “driven”—Bertrand Meyer, for example, invented Design by Contract. But whether “driven” or not, these approaches all emphasize a core set of values and principles around which practices, techniques, and tools have emerged.

  今天我们拥有的设计或开发方法是,举个例子,责任驱动(RDD),测试驱动(TDD),行为驱动(BDD),领域驱动(DDD)和模型驱动(MDD)。并不是软件开发中的所有领导者都是“驱动”的——比如Bertrand Meyer发明的契约式设计。但是无论是不是“驱动”,这些方法都强调了一组围绕已经出现的实践、技术和工具的核心价值和准则。  

   A thoughtful designer should be able to pick and choose among practices without losing their essence. But not all practices are congruent. After stewing in this alphabet soup for years, I’m keen on exposing the common and complementary threads that are interwoven among various design practices.

   一个有思想的设计者应该能够在这些实践中挑选而不失去它们的本质。但是不是所有的实践都是适合的。在这个字母汤里煮了多年之后,我热衷于揭示交织在各种各样的设计实践中的共通之处和补充内部。

Responsibility-driven design

责任驱动设计

    So how can you integrate various practices without watering them down or muddling your thinking with too many considerations? It’s certainly easy if you have one belief system with one small set of coherent values and practices that guide your work. In 1989, Brian Wilkerson and I authored the paper “Object-Oriented Design:A Responsibility-Driven Approach.”1 For better or worse, we started the trend of tagging design approaches as “driven.” To make our point, we oversimplistically divided object design approaches into two camps: those that focus first on structure and those that focus first on action (or responsibilities or behaviors). We argued that designers who first focus only on an object’s structure fail to maximize encapsulation.

Thinking too early about structure makes it too easy for implementation details to bleed into class interfaces.

    所以你怎样将各种不同的实践整合起来而不会由于有太多需要考虑的事项将它们全都随水一起倒掉或搞乱你的思想?如果你有一个信任系统和一小套一致的价值和实践指导你工作,那么这确实很容易。在1989年,我和Brian Wilkerson写了名为“面向对象设计:一种责任驱动的方法”的论文。为了更好或更糟,我们开始倾向于给设计方法贴上“驱动”的标签。为了声明我们的观点,我们过分单纯的将对象设计方法分为两个阵营:一派首先关注结构,而另一派首先关注动作(或责任或行为)。我们认为首先只是关注一个对象的结构的设计者未能实现最佳的封装。过早的考虑结构会导致过早的将实现细节侵染到类接口。

We contrasted two approaches for designing a RasterImage class that represented a rectangular grid of pixels. (We wrote this paper when raster technology was new, and at the time we both worked at Tektronix, a leading provider of graphics workstations.) With a data-first approach,we started defining our RasterImage class by declaring the image data structure and then adding methods to retrieve and set the image and query its dimensions. Voila!—a class where form and function were inextricably intertwined.

我们对比两种设计表现像素的一个矩形栅格的RasterImage类的方法。(我们写这篇论文时,光栅技术还是新的,那时我们一起在Tektronix工作,Tektronix是图形工作站的主要提供商。)用数据先行的方法,我们开始定义我们的RasterImage类,我们声明镜像数据结构,然后添加方法去重新得到和设置镜像,查询它的尺寸。瞧!——一个外形和功能避免不了的纠缠在一起的类。

The pixel grid data structure wasn’t considered a private implementation detail.Next, we demonstrated how a designer could think differently about the problem by asking,“What actions could this object be responsible for?” and “What information should it share with others?” This led us to first define operations for our RasterImage class to scale and rotate the image and access pixel values. The internal image  representation, which we didn’t specify until after we’d defined the interface,was considered a private detail.

这个像素栅格数据结构不是被考虑成一个私有的实现细节。下一步,我们证明一个设计者能够以不同的方式来思考问题,通过询问“这个对象对于什么动作负责任?”和“它和别人共享什么信息”。这引导我们首先定义我们的RasterImage类的操作来测量和旋转镜像和访问像素值。我们在定义接口之前没有指定的内部镜像表示被考虑成一个私有细节。

By consciously assigning most objects actionoriented responsibilities, you can design even seemingly  data-centric objects to perform some actions as well as encapsulate structural details.

DESIGN

1 0 IEEE SOFTWARE www.computer.org/software

Hiding that structure makes those de­tails easier to change. To us it seemed that the order in which a designer con­siders things profoundly affects the re­sulting design—even for a class as straightforward as RasterImage. To quote Samuel Alexander, the philoso­pher, “An object is not first imagined or thought about and then expected … but in being actively expected it is imagined as future and in being willed it is thought.”

通过自觉地分配给大多数对象面向动作的责任,你甚至能够设计看起来以数据为中心的对象来执行一些动作和封装结构的细节。隐藏结构使那些细节容易改变。对于我们而言,看起来一个设计者考虑事情的顺序深深的影响作为结果的设计——甚至对于一个像RasterImage一样简单易懂的类。引用哲学家Samuel Alexander的话,“一个对象不是先被想像或思考然后被期望……但是由于积极的被期望,它被想像成未来,由于有某种意志,它是思想。”

 Since those early days I’ve added the notion of role stereotypes, 2 acknowledg­ing that not all objects are active. Infor­mation holders—objects with responsi­bility for maintaining data—have a place in a design, too. But encapsulating their private details is important.

  自从那些早些的日子我添加了角色构造型的概念,知道不是所有的对象都是有效的。信息持有者——具有持有数据责任的对象——也在一个设计中有一席之地。但是封装它们的私有细节是重要的。

Test-driven design

测试驱动设计

  RDD evolved in the highly interactive world of Smalltalk development, where developers routinely designed a little, coded a little, and tested a little in short cycles. The delightful tension of cycling between imagining what an object might do, building it, and then refining your ideas and cycling through your design again can lead to deep insights. This has led agile-programming thought leaders to promote test-driven development practices. Test-driven design emphasizes deciding on an interface and then writ­ing code to test that interface, before im­plementing code to make the interface pass the test.

 RDD在高度互动的Smalltalk开发世界进化,在那儿开发者例行公事的设计一小块,编一小段代码,然后再很短的周期里做少许测试。在想象一个对象做什么,然后构建它,然后精化你的想法之间循环的令人愉快的压力而且循环通过你再一次设计能够使你有更深的理解。这引导敏捷开发思想的领导者提倡测试驱动开发实践。测试驱动设计强调动对一个接口作出决定,然后编写代码去测试那个接口,在实现代码之前使接口通过测试。

In Test-Driven Development by Example, Martin Fowler claims that TDD “gives you this sense of keeping just one ball in the air at once, so you can con­centrate on that ball properly and do a really good job with it.3 With a design­test-code-reflect-refactor rhythm, good code emerges alongside well-designed interfaces.

Test-Driven Development by Example中,Martin Fowler声称TDD“给你这种保持一次只有一个球在空中的感觉,所以你可以完全集中精力在那个球上和使用它真正地做好一件事。”带着一种“设计测试-编码-反馈-重构”的节奏,好的代码在一旁显示出设计良好的接口。

Linda Crispin explains that TDD isn’t really about testing.4 Instead, it’s a prac­tice that gets you thinking about as many aspects of a feature as you can be­fore you code it. With frameworks such as Fit and Fitnesse, TDD has extended beyond its initial focus on just develop­ers to enable nontechnical people to write concrete examples of inputs and expected results in tabular form. Programmers write test fixtures that use these behavioral specifications to test the code.

Lina Crispin说明TDD其实不是关于测试的。相反,它是一种使你在编码之前尽可能考虑一个特征的许多方面的实践。使用像FitFitness这些框架,TDD扩大了它最初的关注范围,那时它只关注开发者使非技术人员能够在表格中写出具体的输入样板和期望的结果。程序员编写测试装置来测试代码,测试装置使用这些行为的详细规格说明书。

 As TDD practices have grown, new variants of them, along with newer test­ing frameworks, have emerged. Users of jMock use mocks that mimic unimple­mented behaviors to drive out an appro­priate distribution of responsibilities among collaborators .5 They don’t think that it’s just about testing, either. Mock­ing lets you incrementally design and build software, hypothesizing and refin­ing your ideas as you go.

 作为一个TDD实践者已经成长,它们中的新的变体和更新的测试框架已经形成。jMock的使用者使用mocks来模仿未实现的行为来完成在协作者中一个适当责任的分配。他们不认为只是测试。Mock让你增量的设计和构建软件,当你前进时假定和精炼你的想法。

Behavior-driven design

行为驱动设计

 BDD is another subtle refinement of TDD. BDD proponents firmly believe that how you talk about what you’re do­ing influences how you work. The focus is on writing small behavior specifica­tions to drive out the appropriate design. As Dave Astels puts it, “A major differ­ence is vocabulary. Instead of subclass­ing TestCase [as you would do using an xUnit framework], you subclass Con­text. Instead of writing methods that start with test, you start them with should.”6 Testing, to BDD proponents, connotes verifying code after it’s built. Instead, they want to encourage incre­mental design by writing small specifica­tions, then implementing code that works according to spec.

BDDTDD另一种的细微的改进。BDD支持者坚定的相信你如何讨论你正在做的事情会影响你如何工作。焦点是编写小的行为规范来导出合适的设计。当Dave Astels提出它时,“一个主要的不同是词汇。代替子集化TestCase [当你使用一个xUnit框架时],你子集化上下文。代替书写使用测试开始的方法,你使用意愿开始。”测试,对于BDD的支持者,意味着在构建之后检验代码。相反,他们想要鼓励增量设计通过书写小的规格说明书,然后实现按照规格说明书工作的代码。

Does every method
warrant a contract?
Probably not. Methods
that don’t cause side
effects probably don’t
need contracts.

Design by Contract

契约式设计

In contrast, Design by Contract (DbC) has roots in formal specifica­tions. To specify how they expect sys­tem elements to interact, designers write contracts specifying what must be true before a module can begin (precon­ditions), what must be preserved during its execution (invariants), and what it guarantees to be true after it completes (postconditions). You could specify con­tracts for components, services, or even individual methods. However, in prac­tice, most contracts are written at the method level because existing program­ming languages and tools support work at that level. Writing contracts is easier if the languages and tools you use sup­port them and you have good examples to emulate. The Eiffel language inte­grates contract support into the lan­guage and runtime environment; most other object-oriented languages don’t.

与之对照的,契约式设计根植于正式的规格说明。为了指出他们期望系统要素如何相互作用,设计者撰写契约详细说明在一个模块开始之前什么是必须正确的(前置条件),在执行时什么是必须保持不变的(不变式),在它完成之后它保证什么是正确的。你应该详细说明组件、服务或者甚至是单独的方法的契约。然而,在实践中,更多的契约是在方法级上书写的,因为既有的编程语言和工具支持工作在那个层面上。如果你使用的语言和工具支持他们而且你有好的例子仿效那么撰写契约是更容易的。Eiffel语言将契约支持整合进语言和运行时环境;大多数其他的面相对象语言不具备这种支持。

Before looking at Contract4J, a DbC tool for Java, I thought that spec­ifying contracts for languages without built-in support would be clunky. However, using aspect technology, Contract4J automatically weaves as­pect-specific contract tests, which are specified in method comments, into your running code. Contracts specified this way leave method code unclut­tered with assertion statements and leave a nice documentation trail of how methods should be invoked.

在看到Contract4JJavaDbC工具)之前,我认为为一种语言指定契约而没有内置的支持将会非常郁闷。然而,使用方面技术。Contract4J自动将细节方面的契约测试织入你运行的代码,它在方法注释中被指出,被这种方式指出的契约使用断言声明使方法代码保持整洁,保留一份好的文档跟踪方法是如何被调用的。

If you choose to, you could apply TDD practices to understand your classes’ behaviors and then add contracts to methods whose behaviors you want verified at runtime. But I suspect these two communities differ considerably in their thinking. Some TDD proponents want to discourage after-the-fact verifica­tion, which to them seems antithetical to designing for quality. But adding con­tracts does tighten up how you use classes, theoretically making it easier to catch errors before they propagate.

如果你做出选择,你可以应用TDD实践理解你的类的行为然后将契约加入到你想要在运行时检验其行为的方法中。但是我怀疑这两个社区在他们的思想中相当不同。一些TDD支持者反对事后检验,这对他们而言看起来与为了质量设计是对立的。但是增加契约加强了你如何使用类,理论上使它更容易在他们传播之前捕捉到错误。

   When you change your design, sometimes contracts will naturally change, too. But once your design ideas settle down, you can finalize or add contractual details. But does every method warrant a contract? Probably not. Methods that don’t cause side ef

DESIGN

fects probably don’t need contracts. But I know I’d certainly find it easier to use class libraries if contract specifications were part of their documentation even if they weren’t validated at runtime.

    当你改变你的设计,有时契约也将自然的改变。但是一旦你的设计想法稳定下来,你能够最终定下来或者添加契约的细节。但是每一个方法都保证一份契约?或许不是这样的,不会导致副作用的方法或许不需要契约。但是我知道我的确发现如果契约详细规格书是它们的文档的一部分就更容易使用类库,即使他们不在运行时被验证。

Domain-driven design

  What about incorporating DDD ideas into your design practice? Accord­ing to Eric Evans, DDD isn’t a technol­ogy or methodology but “a way of thinking and a set of priorities, aimed at accelerating software projects that have to deal with complicated domains” (www.domainlanguage.com/ddd/ index.html). A central activity in DDD is searching for the language that experts use to talk about the problem and then literally reflecting that language in classes and services in a domain layer. Eric be­lieves that, “If developers don’t realize that changing code changes the model, then their refactoring will weaken the model rather than strengthen it.” Creat­ing a domain model is intricately tied to expressing it in working code. Domain­driven design is an active, ongoing process of expressing this domain lan­guage in code.

 怎样把DDD想法融入到设计实践中?按照Eric Evans的说法,DDD不是一项技术获方法论而是“一种思考方式和一组优先级,目的在于促进不得不解决复杂领域的软件项目”。在DDD中一项核心活动是寻找专家用来讨论问题的语言,然后逐字的将那种语言反映到位于领域层的类和服务中。Eric相信,“如果开发者不了解改变代码时改变模型,然后他们的重构将削弱而不是增强模型。”创建一个领域模型杂乱的在工作着的代码中被依靠表达它。领域驱动设计是一种积极的、正在进行的使用代码表示领域语言的过程。

Model-driven design

模型驱动设计

In contrast, adherents of MDD (some call it model-driven engineering to avoid the Object Management Group trademarked term) first develop a plat­form-independent model of their system (usually in UML or a domain-specific language) before translation tools trans­form the model into platform-specific code. MDD practitioners strive to clearly represent system concepts and behaviors with the goal of producing an abstract model, not working code (the translation tools do that for them). This view of model building followed by transformation probably causes the great divide between MDD practition­ers and other design schools—even though they share many common de­sign values. After recently listening to and talking with several well-known MDD proponents who were discussing what constitutes well-designed classes, methods, and components, I found my­self nodding in agreement with many of their design guidelines.

与之对照的,MDD的拥护者在使用转换工具将模型转换成具体平台代码之前,先开发一个他们系统的平台无关模型(通常使用UML货一种领域规范语言)。MDD开创者们带着生产一个抽象模型而非工作的代码(转换工具替他们来做生产代码的事情)的目的,努力清晰的表现系统概念和行为。模型遵循转换构建的观点或许导致了MDD开开创者与其他设计学派的巨大分隔——即使他们共享许多通用设计价值。在最近听到和与许多不同的众所周知的MDD支持者(他们正在讨论什么构成了良好设计的类、方法和组件)讨论之后,我发现自己非常赞同他们的设计指导思想中的很多内容。

H

ow you design should be based on your principles and values. Al­though a big division exists between those who believe the act of coding is what validates the design and those who don’t, you can learn many things about good design from each. My mantra has always been, “Be open to new ideas and techniques that make me a better de­signer.” I side with Canadian politician Dan Miller, who proclaims, “You know, we have our differences, everybody does, honest, real differences, but I do believe strongly that we as neighbors are drawn together far more than we’re dri­ven apart.”

     如何设计,你应该基于你的原则和价值。尽管有巨大的区别存在于那些确信代码的行为是检查设计的标尺的人们和他们的反对者中,但是你从他们中能够学会许多优秀设计的东西。我的箴言一直是,“善于接受新观点和技术,使我成为更优秀的设计师”。我和加拿大政治家站在一起,他宣称,“你知道,我们有不同,每个人都一样,诚实的,真实的不同,但是我深信作为邻国我们的共通之处远远多于我们的区别。”

References

 1. R. Wirfs-Brock and B. Wilkerson, “Object-Oriented Design: A Responsibility-Driven Ap­proach,” Proc. 1989 ACM SIGPLAN Conf.

Object-Oriented Programming, Systems, Lan‑

guages, and Applications (OOPSLA 89), ACM Press, 1989, pp. 71–75.

2.    R. Wirfs-Brock, “Characterizing Classes,” IEEE Software, Mar./Apr. 2006, pp. 9–11.

3.    M. Fowler, Test-Driven Development by Ex­ample, Addison-Wesley, 2003.

4.    L. Crispin, “Driving Software Quality: How Test-Driven Development Impacts Software Quality,” IEEE Software, Nov./Dec. 2006, pp. 70–71.

5. S. Freeman et al., “Mock Roles Not Objects,” Companion to 19th Ann. ACM SIGPLAN

Conf. Object-Oriented Programming, Sys‑

tems, Languages, and Applications (OOPSLA 04), ACM Press, 2004, pp. 236–246; www. jmock. org/oopsla2004.pdf.

6.    D. Astels, “A New Look at Test-Driven Devel­opment,” http://blog.daveastels.com/files/BDD _Intro.pdf.

Rebecca J. Wirfs-Brock is president of Wirfs-Brock Associates and an adjunct professor at Oregon Health & Science University. Contact her at rebecca@wirfs-brock.com.

 

posted on 2007-05-21 10:17 零雨其蒙 阅读(541) 评论(0)  编辑  收藏 所属分类: 面向对象理论与实践


只有注册用户登录后才能发表评论。


网站导航: