伪代码编程过程与测试驱动开发

发布于 2024-07-06 20:36:25 字数 387 浏览 8 评论 0原文

对于那些还没有读过 Code Complete 2 的人来说,伪代码编程过程基本上是一种设计例程的方法,首先用简单的英语描述它,然后逐渐将其修改为更详细的伪代码,最后编写代码。 这样做的主要好处是通过自上而下而不是自下而上构建系统来帮助您保持正确的抽象级别,从而在不同的层中发展出干净的 API。 我发现 TDD 在这方面效率较低,因为它过于注重做最少的事情来通过测试,并且鼓励很少的预先设计。 我还发现,必须为不稳定的代码(不断重构的代码)维护一套单元测试是相当困难的,因为通常情况下,您对一个只需要一两次的例程进行十几个单元测试。 当您进行重构时(例如更改方法签名),您所做的大部分工作是更新测试而不是产品代码。 我更喜欢在组件代码稳定一点后添加单元测试。

我的问题是 - 在尝试过这两种方法的人中,您更喜欢哪一种?

For those who haven't read Code Complete 2, the Pseudocode Programming Process is basically a way to design a routine by describing it in plain English first, then gradually revise it to more detailed pseudocode, and finally to code. The main benefit of this is to help you stay at the right level of abstraction by building systems top-down rather than bottom-up, thereby evolving a clean API in distinct layers. I find that TDD is less effective at this, because it focuses too much on doing the bare minimum to get a test to pass and encourages little up-front design. I also find that having to maintain a suite of unit tests for unstable code (code that's constantly being refactored) is quite difficult, because it's typically the case that you have a dozen unit tests for a routine that's only needed once or twice. When you do refactor - change a method signature, for example - most of the work you do is in updating the tests rather than the prod code. I prefer adding unit tests after a component's code has stabilized a bit.

My question is - of those who've tried both approaches, which do you prefer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷血 2024-07-13 20:36:25

我的团队混合了这两种方法,这是一种很棒的开发方式(至少对我们来说)。 我们需要单元测试,因为我们有一个庞大而复杂的软件系统。 但伪代码编程过程无疑是我遇到过的最好的软件设计方法。 为了让他们一起工作:

  • 我们从编写我们的课程开始,
    并填写完整评论
    方法存根,带有输入和
    输出。
  • 我们使用结对编码和同行评审作为对话来完善和验证设计,仍然只使用方法存根。
  • 至此,我们已经设计了我们的系统并拥有了一些可测试的代码。 所以我们继续编写我们的单元测试。
  • 我们返回并开始用需要编写的逻辑的注释填充方法。
  • 我们编写代码; 测试通过。

它的美妙之处在于,当我们真正编写代码时,大部分实现工作已经完成,因为我们认为的实现实际上是代码设计。 此外,早期的过程取代了对 UML 的需求 - 类和方法存根具有描述性,而且实际上会被使用。 我们始终保持在适当的抽象级别。

显然,这个过程从来都不像我所描述的那样线性 - 实现的一些怪癖可能意味着我们需要重新审视高层设计。 但总的来说,当我们编写单元测试时,设计确实非常稳定(在方法级别),因此不需要大量的测试重写。

My team mixes both approaches and it's an awesome way to develop (at least for us). We need unit tests because we have a large and complex software system. But the Pseudocode Programming Process is hands-down the best approach to software design I've come across. To make them work together:

  • We start by writing our classes,
    and fill in with fully commented
    method stubs, with inputs and
    outputs.
  • We use pair coding and peer review as a dialogue to refine and validate the design, still only with the method stubs.
  • At this point we've now both designed our system and have some testable code. So we go ahead and write our unit tests.
  • We go back in and start filling in the methods with comments for the logic that needs to be written.
  • We write code; the tests pass.

The beauty of it is that by the time we actually write code, most of the work of implementation is already done, because so much of what we think of as implementation is actually code design. Also the early process replaces the need for UML - class and method stubs are just as descriptive, plus it'll actually be used. And we always stay at the appropriate level of abstraction.

Obviously the process is never really quite as linear as I've described - some quirk of implementation may mean that we need to revisit the high-level design. But in general, by the time we write unit tests the design is really quite stable (at the method level), so no need for lots of test rewriting.

没有心的人 2024-07-13 20:36:25

使用测试驱动开发,您仍然应该在一开始就做一些计划。 首先应该从高层次审视您想要做什么。 不要提出所有细节,而是用简单的英语了解如何解决问题。

然后开始测试问题。 一旦你完成了测试,就开始让它通过。 如果这不容易做到,您可能需要修改最初的计划。 如果有问题就修改一下。 测试并不是为了定义解决方案,而是为了让您能够进行更改,以便在确保稳定性的同时获得更好的解决方案。

我想说最好的选择是使用 TDD。 关键是要认识到 TDD 并不意味着“跳过规划”。 TDD 意味着做一些计划才能很好地开始,并根据需要进行调整。 你甚至可能不需要调整。

With Test Driven Development you should still be doing some planning in the beginning. It should at first be a high level look at what you're trying to do. Don't come up with all the details, but get an idea in plain English of how to solve the problem.

Then start testing the problem. Once you've got the test in place, start to make it pass. If it isn't easy to do, you may need to revise your initial plan. If there are problems just revise. The test is not there to define the solution it is there to allow you to make changes so you can have a better solution while ensuring the stability.

I would say the best bet is to use TDD. The key is to realize that TDD doesn't mean "skip the planning". TDD means do a little bit of planning to get started well, and adjust as needed. You may not even need to adjust.

入怼 2024-07-13 20:36:25

一般来说,我发现只有当解决问题所需的代码比测试解决方案所需的代码复杂得多时,伪代码才真正变得相关。 如果情况并非如此,我就不会遇到您所描述的困难,因为对于值得在问题上花费的时间来说,可能可行的最简单的事情通常是可接受的解决方案。

另一方面,如果问题复杂,我需要在编写最初的简单解决方案之前考虑如何解决它 - 我仍然需要在编码之前进行计划; 因此,我结合使用了两种方法:对我最初要编写的内容进行英文描述,然后是测试工具,然后是简单的解决方案代码,然后是细化。

In general, I find pseudocode only really becomes relevant when the code required to solve the problem is much more complicated that the code required to test the solution. If this is not the case, I do not run into the difficulties you describe as the simplest thing that could possibly work is usually an acceptable solution for the amount of time worth spending on the problem.

If, on the other hand, the problem is complicated, I need to think through how to approach it before I can write even an initial naive solution - I still need to plan before I code; therefore, I use a combination of both approaches: an English description of what I will initially write, then a test harness, then naive solution code, then refinement.

罪歌 2024-07-13 20:36:25

我已经将这两种方法与大型前期开发一起使用,这三种方法都有自己的位置,具体取决于语言、团队动态和程序大小/复杂性等问题。

在动态语言(尤其是 ruby​​)中,我强烈推荐 TDD,它将帮助您捕获其他语言在编译时会捕获的错误。

在一个大型、复杂的系统中,您预先做的设计越多,您的情况就会越好。 似乎当我为一个大型项目设计时,我挥手并说“这应该非常简单”的每个区域都是项目后期的绊脚石。

如果您正在用静态类型语言单独处理一些小事情,那么列表方法是合理的,并且会比 TDD 节省大量时间(测试维护不是免费的,尽管首先编写测试也不是免费的)坏)——当您正在处理的系统中没有任何测试时,添加测试并不总是受到赞赏,甚至可能会引起一些不必要的注意。

I've used both along with Big Upfront Development, all three have their places depending on issues such as language, team dynamics and program size/complexity.

In dynamic languages (particularly ruby), I highly recommend TDD, it will help you catch errors that other languages would have caught at compile time.

In a large, complex system, the more design you do upfront the better off you will be. It seems like when I designed for a large project, every area that I hand-waved and said "this should be pretty straight forward" was a stumbling point later in the project.

If you are working alone on something small in a staticly-typed language, the list approach is reasonable and will save you a good deal of time over TDD (Test maintenance is NOT free, although writing the tests in the first place isn't too bad)--When there aren't any tests in the system you're working on, adding in tests isn't always admired and you might even draw some unwanted attention.

緦唸λ蓇 2024-07-13 20:36:25

测试通过并不意味着您就完成了。

TDD 的最佳特征是红-绿-重构

进行测试可提供一条(两条)目标线。 这只是第一个、最低限度的要求。 真正的目标与“伪代码编程过程”或任何设计学科的目标相同。

此外,TDD 是通过测试驱动的,但这并不意味着盲目地通过测试驱动。 您可以像迭代代码一样迭代测试。 这里没有教条主义地遵守愚蠢计划的地方。 这是一种敏捷技术——这意味着要根据您的团队和环境进行调整。

设计足够的代码以获得可测试的界面。 设计足够的测试以确保界面能够正常工作。 设计更多的测试和更多的实现,直到您发现需要重构。

真正的目标是优秀软件。 TDD 不能排除“善良”。

技术不是限制性命令。 技术应该被视为帮助您编写良好代码的拐杖。 如果我更聪明、更富有、更漂亮,我就不需要 TDD。 但由于我和我一样愚蠢,所以我需要一个拐杖来帮助我重构。

Just because the test passes, doesn't mean you're done.

TDD is best characterized by Red - Green - Refactor.

Having a test provides one (of two) goal lines. It's just the first, minimal set of requirements. The real goal is the same goal as "Pseudocode Programming Process" or any design discipline.

Also, the TDD is driven by testing, but that doesn't mean driven blindly by testing. You can iterate your testing the same way you iterate your code. There's no place for dogmatic adherence to a dumb plan here. This an an Agile technique -- that means adapt it to your team and your circumstances.

Design enough code to have a testable interface. Design enough tests to be sure the interface will work. Design some more tests and some more implementation until you see the need to refactor.

The real goal is Good Software. TDD can't exclude "goodness".

A technique is not a restrictive mandate. A techniques should be looked as a crutch to help you product good code. If I were smarter, richer and better-looking, I wouldn't need TDD. But since I'm as dumb as I am, I need a crutch to help me refactor.

躲猫猫 2024-07-13 20:36:25

对我来说,TDD 拥有无法与之竞争的王牌伪编码 - 两者都可以帮助您抽象和规划开发,但是一旦您完成了 TDD 领域的开发,您仍然需要进行单元测试

尽管 CC2 描述的伪编码方法非常有用,但它无法与之相比。 TDD 只涉及设计的一半,它还提供了一个严格的框架,您可以从中发展项目。 然而,我认为没有理由不能用伪代码来解决 TDD 所设置的问题。

我不能有机地发展。
伪代码是精神杀手。
正是小死亡带来了项目记忆的遗忘。
我将面对90年代的方法论。
我将允许它越过我并穿过我。
当它过去时,我会转动内在的眼睛来看到它的路径。
伪代码消失的地方就会出现 TDD。
仅保留单元测试。

(请不要为此责怪我,我只是半认真的:P)

For me TDD has an ace pseudocoding just can't compete with - both help you abstract and plan the development, but once you're finished development in TDD land you still have the unit tests.

AS useful an approach as CC2 described pseudocoding is, it just can't match that. TDD is only half about designing, it's also providing a rigorous scaffold you can evolve the project forward from. However I see no reason why you can't pseudocode to solve the problems TDD sets.

I must not develop organically.
Pseudocode is the mind-killer.
It is the little-death that brings project memory oblivion.
I will face my 90's methodology.
I will permit it to pass over me and through me.
And when it has gone past I will turn the inner eye to see its path.
Where the pseudocode has gone there will be TDD.
Only unit-tests will remain.

(please don't flame me for that, I'm only half serious :P )

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文