18

我最近阅读了一篇关于 OOP 相关问题的有趣评论,其中一位用户反对创建“Manager”类:

在谈论班级名称时,请从您的词汇表中删除单词管理器。类的名称应该描述其目的。经理只是垃圾场的另一个词。任何功能都适合那里。这个词一直是许多极其糟糕的设计的原因

这条评论体现了我成为一名优秀的面向对象开发人员的努力。我在一个只有程序编码员的组织里做程序代码已经很长时间了。似乎我们生成的相对较少的 OO 代码背后的主要策略是将问题分解为易于识别为离散单元的类,然后将剩余/通用位放入“管理器”类中。

我怎样才能打破我的程序习惯(比如 Manager 类)?大多数 OO 文章/书籍等使用的问题示例本质上很容易转换为对象组(例如,Vehicle -> Car),因此没有为分解更复杂的系统提供太多指导。

4

12 回答 12

15

首先,我不会再表现得像程序代码是错误的一样。它是某些工作的正确工具。OO 也是某些工作的正确工具。功能性也是如此。每个范式只是计算的不同观点,存在是因为它便于解决某些问题,而不是因为它是唯一正确的编程方式。原则上,这三种范式在数学上是等价的,因此请使用最能映射到问题域的一种。恕我直言,如果使用多范式语言,如果不同的子问题最好由不同的世界观建模,甚至可以在模块中混合范式。

其次,我会阅读设计模式。如果没有一些实际问题的例子,很难理解 OO,它有利于解决。Head First Design Patterns 是一本很好的读物,因为它回答了很多 OO 的“为什么”。

于 2009-02-18T04:39:46.450 回答
9

擅长 OO 需要多年的实践和学习良好的 OO 代码,最好有导师。请记住,OO 只是达到目的的一种手段。话虽如此,这里有一些对我有用的一般准则:

  • 优先组合而不是继承。阅读并重新阅读GoF 书的第一章。
  • 遵守得墨忒耳法则(“告诉,不要问”)
  • 尝试仅使用继承来实现多态性。当您从另一个类扩展一个类时,这样做的想法是您将通过对基类的引用来调用该类的行为。基类的所有公共方法都应该对子类有意义。
  • 不要沉迷于建模。构建一个工作原型来为您的设计提供信息。
  • 拥抱重构。阅读福勒著作的前几章。
于 2009-02-18T05:41:09.207 回答
8

单一职责原则帮助我将对象分解为有意义的可管理类 。

每个对象都应该做一件事,并且做得很好,而不会将其内部工作方式暴露给需要使用它的其他对象。

于 2009-02-18T04:04:02.090 回答
7

“经理”类通常会:

  1. 询问某物的状态
  2. 根据该状态做出决定

作为一种解毒剂或与之形成对比,面向对象的设计将鼓励您设计类 API,在其中您“告诉不要要求”类本身自己做事(并封装自己的状态):有关“告诉不要”的更多信息“不要问”参见例如此处此处(也许其他人对“告诉不要问”有更好的解释,但这是谷歌为我找到的前两篇文章)。

看起来我们生成的小 OO 代码的主要策略是将问题分解为易于识别为离散单元的类,然后将剩余/通用位放入“管理器”类中。

即使在最好的时候,这也可能是真的。Coplien 在他的Advanced C++: Programming Styles and Idioms一书的结尾谈到了这一点:他说在一个系统中,你往往会:

  • 自包含对象
  • 以及作用于其他对象的“事务”

举个例子,一架飞机(我很抱歉给你另一个车辆例子;我在解释他):

  • “对象”可能包括副翼、方向舵和推力
  • “经理”或自动驾驶仪将执行各种命令或事务

例如,“右转”交易包括:

  • 襟翼.right.up()
  • 襟翼.left.down()
  • rudder.right()
  • 推力.增加()

所以我认为你确实有交易,它跨越或使用各种相对被动的“对象”;例如,在应用程序中,“随便”的用户命令最终将由每一层(例如 UI、中间层和 DB 层)的各种对象实现(因此调用)。

所以我认为在一定程度上你会有“剩余部分”。不过,这是一个程度的问题:也许您应该希望尽可能多的代码是自包含的、封装的,以及一切……以及使用(或依赖于)其他一切的剩余部分,应该给予/使用尽可能多地隐藏并尽可能多地执行的API,因此尽可能多地从所谓的经理那里承担责任(实施细节)。

不幸的是,我只在一本书(Advanced C++)中读过这个概念,并且无法将您链接到在线内容以获得比我的这个释义更清晰的解释。

于 2009-02-18T04:23:53.947 回答
6

阅读然后练习 OO 原则对我有用。Head First Object-Oriented Analysis & Design通过示例帮助您制定面向对象的解决方案,然后通过方法使解决方案变得更好。

于 2009-02-18T04:21:15.700 回答
5

您可以通过学习设计模式来学习良好的面向对象设计原则。 Code Complete 2是一本关于该主题的好书。自然,将良好的编程原则牢牢记住的最佳方法是通过将它们应用到自己的编码项目中来不断地练习它们。

于 2009-02-18T04:11:45.160 回答
4

我怎样才能打破我的程序习惯(比如 Manager 类)?

为经理管理的内容创建一个类(例如,如果您有一个 ConnectionManager 类,则为一个 Connection 创建一个类)。将所有内容移入该类。

“管理器”在 OOP 中这个名字不好的原因是 OOP 的核心思想之一是对象应该管理自己

不要害怕做小班。来自程序背景,您可能认为创建一个类是不值得的,除非它是一千行代码并且是您领域中的一些核心概念。想想更小。十行课程是完全有效的。在你认为有意义的地方创建小类(一个日期、一个邮件地址),然后通过编写这些类来逐步提升。

当您开始将代码库的一小部分划分为类时,剩余的过程代码汤将缩小。在那个不断缩小的池中,您将开始看到其他可以是类的东西。继续直到池为空。

于 2009-02-18T21:52:01.523 回答
3

换一个灯泡需要多少个 OOP 程序员?

没有,灯泡会自行改变。

;)

于 2009-02-18T05:01:29.050 回答
3

您可以使用像 Smalltalk 这样的过程支持非常差的 OO 语言。消息发送范式将迫使您进入 OO 思维。

于 2009-02-18T05:35:27.347 回答
1

我认为你应该从一个好的计划开始。使用类图进行规划将是一个好的开始。

您应该确定应用程序中需要的实体,然后定义每个实体的属性和方法。如果有重复的,您现在可以以可以完成继承的方式重新定义您的实体,以避免冗余。:D。

于 2009-02-18T05:19:34.903 回答
1

当我阅读 Eric Evans 的书“领域驱动设计:解决软件核心中的复杂性”时,我对理解面向对象设计的灵感产生了灵感。或者,如果您便宜或不耐烦,请阅读“快速领域驱动设计”迷你书(以免费 PDF 格式在线提供)。:)

任何时候你有一个“Manager”类或任何静态单例实例,你可能正在构建一个程序设计。

于 2009-02-18T06:24:34.077 回答
1

我有一个三步过程,这是我自己成功完成的过程。后来我遇到了一位前教师转为程序员(现在非常有经验),他向我解释了为什么这种方法如此有效,这涉及到一些心理学,但它基本上都是关于在你学习时保持控制和信心。这里是:

  1. 了解什么是测试驱动开发 (TDD)。您可以使用过程代码轻松地做到这一点,因此如果您不想这样做,则不需要开始使用对象。第二步取决于此。

  2. 拿起 Martin Fowler 的《重构:改进现有代码的设计》的副本。它本质上是您可以对现有代码进行的微小更改的目录。但是,如果没有测试,您将无法正确重构。这使您可以做的是弄乱代码,而不必担心一切都会中断。测试和重构消除了你不知道会发生什么的偏执和感觉,这是令人难以置信的解放。你离开基本上是在玩。随着您对此越来越有信心,开始探索用于测试对象之间交互的模拟。

  3. 现在到了大多数人错误地开始的大事件,它是好东西,但它真的应该排在第三位。在这一点上,您应该阅读有关设计模式、代码异味(这对 Google 来说很好)和面向对象设计原则的内容。还要了解用户故事或用例,因为它们在编写新应用程序时为您提供了良好的初始候选类,这是“我从哪里开始?”的一个很好的解决方案。编写应用程序时出现问题。

就是这样!证明善良!让我知道事情的后续。

于 2009-05-27T10:05:27.163 回答