在编码之前设计OOP系统的简单过程是什么?


10

每当需要构建项目时,我总是设法进行构建,而不是事先设计计划或设计,而是在首先编写了需要的类之后,从下至上充实整个项目。现在,我知道这不是创建软件的正确方法,但是对我来说,将其包裹在所谓的面向对象的分析和设计上并不容易。我可以更容易地理解自上而下的程序设计,因为它只包含将任务分解为子任务,这些子任务在代码,功能上与之相对。但是我不容易理解面向对象的分析和设计,因为我不理解人们如何知道他们将需要哪些类以及它们将如何交互,除非他们知道如何对它们进行编码。

因为一旦在设计过程中引入了类和对象的概念,就不能再自上而下进行设计,因为我们不再将问题分解为可以作为过程实现的事物。相反,根据我对该主题的了解,我们必须确定需要哪些类,并在统一建模语言中创建各种工件,然后在实现软件时就可以使用这些工件。但是这种设计过程我不明白。除非他们已经构思了整个系统,否则如何知道他们将需要哪些类以及它们将如何交互?

这就是我的问题。尽管我确实了解面向对象编程的概念,但是我不了解如何设计面向对象的系统,并且可以在我知道的任何面向对象编程语言中使用这些概念。因此,我需要有人向我解释可以使用对我来说有意义的方式设计面向对象系统的简单过程。


8
“现在我知道这不是创建软件的正确方法” -谁告诉你的?您似乎以某种方式陷入了一个普遍的陷阱,即认为“设计是您在编码之前要做的事情,也许是通过绘制精美的UML图来实现的”。为了解决这种误解,我建议从Jack Reeves撰写的“ Code as Design”开始。
布朗


@DocBrown。您不认为编码时进行设计才是使我们的工作如此手工的原因吗?我无法想象其他工程也能如此。想象一下,一位建筑师在路上堆砌砖瓦和砂浆并设计建筑物/桥梁。
2015年

5
@Laiv:“编码”是其他工程师学科称为设计的一部分。在房屋建筑中,从设计到最终产品的步骤是使用起球的砖块和砂浆完成的。在编程中,此步骤由编译器将设计(=程序)转换为最终产品(=可执行二进制文件)时完成。那不是新的智慧。里夫斯杂文已有25岁。
布朗

@DocBrown,是开发人员。*不再策划吗?例如,订阅按钮已损坏。
–radarbob

Answers:


20

自上而下的瀑布样式OOAD不能确保您编写的代码完全是面向对象的。我见过严格的OOAD生产的代码证明了这一点。如果OO使您感到困惑,请不要在这里寻求帮助。您将找不到它。OO不需要您自上而下进行设计。

如果您喜欢学习编码,那就去吧。让我告诉你一个提示。拖延。

通过编写使用类的代码来设计类,即使它们尚不存在,也是如此容易。忘记程序了。忘记结构。只需使自己达到一个良好的一致抽象水平并坚持下去即可。不要屈服于诱惑,不要在其中混入更多细节。任何使您脱离当前抽象的事情都可以通过某种方法来完成,而该方法可能位于某个其他对象上,而该对象以某种方式知道需要知道的内容。不要构建任何您可以要求交给您的东西。

学会这样写,您会发现自己正在做面向对象,甚至都不会非常努力。这迫使您从对象的使用方式(它们的界面)以及哪些对象知道哪些其他对象的角度来查看对象。猜猜UML图表的主要两点是什么?

如果您可以采用这种思维方式,那么剩下的就是架构。我们都还在想办法。从MVC到干净的体系结构再到域驱动的设计。学习他们并玩耍。使用有效的方法。如果您发现100%可靠的产品,请回来告诉我。这样做已经有几十年了,我仍在寻找。


2
否则,您会发现自己没有在做OO,但无论如何“一切”都可以正常工作……
德里克·埃尔金斯

2
“通过编写即使在尚不存在的类时使用它们的代码来设计类也是如此容易”,我称这种自上而下的设计,但这似乎是错误的。什么是自上而下的设计,我怎么称呼它?它是对接口编程吗?
Piovezan

这不只是自上而下的。您还必须愿意不通过接受参数来构建您可以要求的东西。
candied_orange

@Piovezan即使接口尚不存在,您也可以执行此操作。只是稍微忽略一下编译器。稍后,您将使它存在。
candied_orange

@CandiedOrange “您还必须愿意不通过接受参数来构建您可以要求的东西。” -我不确定我是否理解,能否请您澄清/提供一个简短示例(或与此相关的反示例)?
Piovezan

4

您声称可以在代码中使用面向对象的技术,因此您确实已经知道如何设计一个面向对象的系统,我相信您的问题更多的是何时,而不是是否可以。您似乎以短期的迭代方式而不是长期的规划方式来适应面向对象的设计。

刚开始开发项目时,计划和设计可能非常困难,那就是敏捷开发胜于瀑布式开发,因为瀑布式计划的宏大范围通常无法捕获软件项目的所有复杂性。

您断言,没有“初始计划”的情况下即时开发是:

“ ...不是创建软件的正确方法...”

如果您的问题是您的初始计划不够详细,请花一些时间来解释您的第一个想法。您计划编写的程序第一部分是什么?它是什么将需要?也许甚至都不考虑要从什么对象开始,而是想起什么功能并从那里计划。

如果您的问题是您对自己的文档编制/设计/ UML技能不满意,请通过记录现有项目进行练习。

我个人建议不要担心您的设计完全是面向对象的,大多数系统都不是100%面向对象的。目标是创建对系统的更好的理解和可视化,而不是完美的抽象。面向对象不是万灵丹,它只是皮带上的另一种工具。


我也想提一下,尽管答案有点题外话……您的计划不必太大!有时,计划只是“我想运行它就可以做某事”的问题。这足够好了,如果这真的是它要做的全部。
Erdrik Ironrose '17

2

OOAD是乌托邦。我并不是说这是最好的方法,我的意思是我从来没有真正实现过这种方法。根据我的经验,某些事情总是在变化,无论是需求还是细节,甚至是依赖冲突都迫使您完全替换依赖。无论是因为我是通过这种方式学习的,还是因为这对我来说是最自然的事情,所以在编写代码时,我的设计思想就很容易实现。如果我要编写代码,但对如何构造代码不清楚,我将重点指出要花时间首先真正地理解问题,尽管通常情况下,我会发现上课的必要性,我去做。

我的建议是,您自己可以做的最好的事情就是使用Facades进行代码,为输入和输出提供简单的界面,并希望输入和输出不会经常更改。即使他们这样做,也要知道这不是设计问题,而只是规格问题(必要性/操作/功能的变化)。这将使您的程序在某种程度上可以抵抗程序内部与那些调用您的程序或代码段的人产生共鸣的问题,反之亦然。

对于设计面向对象的系统所涉及的问题,应该说一些尝试使一切都不应该是面向对象的。在C#和Java之类的OOP编程语言之间,这是一个普遍的错误,就是试图将所有内容都视为一个对象,这通常导致创建一个类的单个实例来执行原本不会改变状态的静态方法。就是说,您当然应该在适用的地方使用OOP设计,尽管在编写静态方法更自然时不会觉得您做错了。这并非总是错误的本能。

当您对以下任何一个问题的回答为“是”时,您应该考虑使用课程:

  • 我是否有一组与同一概念相关的信息(即名字,姓氏,地址)?
  • 我是否需要执行需要几条信息的操作(即calculatePrice(basePrice, quantity, tax))?
  • 如果大型代码块使用相同或相似的信息(即if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak()) 执行略有不同的操作,我是否还有其他方法?
  • 我是否有一个现有的班级执行多个特定任务,并且该班级变得太大了?

一段时间后,创建类将成为第二天性。如果您的代码属于上述情况之一,请不要害怕使用它们。希望对您有所帮助!


2

我认为布朗博士在评论中提出的观点比评论更值得关注,因为他是绝对正确的:

现在我知道这不是创建软件的正确方法 ”-谁告诉过您?您似乎以某种方式陷入了一个普遍的陷阱,即认为“设计是您在编码之前要做的事情,也许是通过绘制精美的UML图来实现的”。为了解决这种误解,我建议从Jack Reeves撰写的“ Code as Design”开始。– 布朗 博士6月21日下午5:27

@Laiv:“编码”是其他工程师学科中称为设计的一部分。在房屋建筑中,从设计到最终产品的步骤是使用起球的砖块和砂浆完成的。在编程中,此步骤由编译器将设计(=程序)转换为最终产品(=可执行二进制文件)时完成。那不是新的智慧。里夫斯杂文已有25岁。– 布朗 博士6月21日下午6:39

在其他地方也有同样的看法。考虑格伦·范德堡(Glenn Vanderburg)关于“真正的软件工程” 的演讲,并在某种程度上考虑他的“工艺,工程和编程的本质”以及“工艺和软件工程”的演讲。还可以考虑C2 Wiki上的WhatIsSoftwareDesignTheSourceCodeIsTheDesign页面/讨论。

设计的代码概念并非特定于任何范例。它可以同等地应用于面向对象,功能,过程,逻辑或其他任何对象。基本思想是相同的-设计就是源代码本身。构造行为是由解释器或编译器将源代码(设计)转变为可用物的过程。

在复杂的系统中,可能会进行某种级别的体系结构设计-在开始编写代码之前,先确定子系统,组件,模块,服务并为其分配需求。您可以使用UML作为创建,记录和帮助围绕该体系结构设计进行讨论的一种方式。考虑一下马丁·福勒(Martin Fowler)讨论UML模式的概念,特别是UML作为草图UML作为注释。还要考虑敏捷建模中的一些想法- 初始体系结构建模迭代建模勉强足够好的模型

所有这些都意味着构建软件的正确方法是不要充实整个项目。这是花费足够的时间来了解最关键的(在当前时间点)需求,确定技术依赖性和需求之间的权衡,然后利用软件软性这一事实。还应认识到,进行设计和生产某些东西的成本非常低(特别是与许多其他工程学科中进行设计和生产某些东西相比)。因此,迭代您的设计(编码)活动,并利用逐步构建或修改您所做的工作是多么容易和便宜。


1

OOAD涉及识别实体并对现实生活中的对象或概念进行某种程度的抽象建模。如果您不打算先编写类而不是最初编写接口,那么您会认为它更容易,因为您实际上还不需要实现它们,但是代码可以编译。

OOAD并不排除系统中作为大模块进行思考的可能性。您仍然可以这样做。每个模块的存在都是为了满足一组用户案例(用例)。这样的用户故事需要协作来实现它们的类。

面向对象程序的方法之间的一个主要区别是,通常程序思维将需求映射到屏幕上,而OOD倾向于考虑在幕后发生的事情,而前端则由另一个人或以非OO方式进行。

极限编程中有一种称为CRC卡的技术。CRC代表“类责任协作者”。

基本上,您可以确定明显的类别,并为每个类别分配一张卡片。说,课程Invoice有自己的卡片。

对于每个持卡类,您都要写出该类的职责,例如“计算总计”

同样,对于每个持卡类,您都要写出该类要满足自己职责的其他类。在这里,您可能会发现Invoice需要协作的需求,InvoiceDetail甚至首先会发现需要此类。

您可能会发现您认为属于的某些责任Invoce确实属于其合作者之一。

练习后,每张卡片都变成一类,每一种责任都变成一种方法,每一种协作关系都可能变成一个组合,一个集合或一个电话。

这种锻炼可以(并且应该)在一个小组中完成,甚至连商人也可以参加。

您可以在以下链接中了解有关此技术的更多信息:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

CRC卡示例:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明


0

作为软件从业者社区,我们面临的主要挑战;更具体地讲,面向对象的设计从业人员是将我们所有的问题/任务具体化为编程核心。是它的任务 -表示为函数或为它的行动者的任务-表示为接口 / [驱动朝OOAD]。随着我们不断发展软件设计习惯,不断获得有关各种方法论/框架的知识。我们的观点越来越明确地划分对象以及哪个对象将执行哪个功能。

至于将存在对象周围的问题分解为子问题,您仍然可以方便地执行此操作,因为您可以完全控制要显示的所有对象。您还可以方便地为对象和界面赋予性质和目的。您要做的就是,可视化问题陈述并考虑可以将哪个目的/功能赋予哪个对象。

我将尝试通过一系列汽车的示例来进一步解释,并且我将重点介绍两种可视化同一对象模型的不同方法。

举一个汽车制造商的例子,它涵盖了各种汽车:商用车,消费车(轿车,掀背车,旅行车)等。

为了使制造商明确区分类别和目的,可以使用多种方法在其中创建类。

车辆制造商OOAD

  1. 基于车辆的类别(市场领域):重型车辆,消费车辆[轿车,掀背车,旅行车等]

  2. 根据发动机容量和驱动方式:800-1500 CC,> 1500 CC等。

按照制造商可以为属于这些分类中的每一个的对象分别赋予功能的最佳方式,他们可以选择适当的基础对象设计,并在此基础上构建模型。


您一开始就可以,但是最后一点似乎是OOD是关于事物分类而不是将相似行为分组的谬论。
Pete Kirkham
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.