5

我正在阅读很多关于 OOP 设计中好的和坏的做法。很高兴知道您的设计是坏的还是好的。但是你如何从糟糕的设计变成优秀的设计呢?我已将接口 (xaml) 和代码隐藏从主要的业务逻辑类中分离出来。最后一堂课越来越大了。我试过把它分成更小的班级,但我现在卡住了。关于如何拆分大班的任何想法?主类有 1 个不同类型的数据列表。我正在对总数进行计算,但也在对个别类型进行计算。我有方法来执行这些计算,这些计算是从代码隐藏中处理的事件中调用的。有什么想法可以从这里开始吗?

附加信息:

我们已经进入这个项目大约 6 个月了。我多年来一直使用面向对象的语言(首先是 c++、java,现在是 c#),但从未参与过像这样的大型项目。我相信我们一开始就犯了一些错误,我认为我们需要纠正这些。目前我无法具体说明这个项目的任何细节。我要订一两本关于设计的书。如果我将所有课程分开,我如何将它们重新组合在一起?也许以这种方式继续到第一个版本并在此之后重建部分以进行第二个版本会更好?

4

12 回答 12

10

练习和阅读。重复 :)

一些推荐书籍:

  • 罗伯特 C 马丁的清洁代码
  • GoF 设计模式
  • Martin Fowler 重构

我个人也喜欢 Head First Design Patterns,但这种风格可能并不适合所有人。有一本类似的书称为 C# 3.0 Design Patterns(请参阅 ora.com)。它有很多相同的东西,但以更传统的方式。

于 2009-01-13T20:05:44.973 回答
4

我强烈建议选择Code Complete。这是一本很棒的书,为您提出的问题提供了大量的好建议。

为了让您快速回答有关如何拆分大型班级的问题,这里有一个很好的经验法则:让您的班级负责一件事,并且只负责一件事。当您开始这样思考时,您可以快速识别不属于的代码。如果某些东西不属于,请将其分解到一个新类中,并从您的原始类中使用它。

编辑:也将这种想法降低到“方法”级别——让你的方法对一件事负责,而且只对一件事负责。帮助将大型(>50 行)方法快速分解为可重用的代码块。

于 2009-01-13T20:06:36.967 回答
4

改变你对物体的看法。每个对象都应该有一个非常具体的职责。如果您有一个名为通用类的类,例如“MainBusinessLogic”,那么您可能做错了什么。

很好的起点:阅读 David West 的Object Thinking

于 2009-01-13T20:12:12.633 回答
3

主类有 1 个不同类型的数据列表。我正在对总数进行计算,但也在对个别类型进行计算。我有方法来执行这些计算,这些计算是从代码隐藏中处理的事件中调用的。有什么想法可以从这里开始吗?

如果有很多基于列表内容的计算,您是否考虑过将操作移动到自定义列表类中?对特定类型的操作也是如此,也许它们可以存在于类型中?

在对不同类型执行相似但不同的操作方面,请考虑使用状态模式(将其视为 switch 语句的替代),它使您能够以统一的方式处理实体。

许多 OOP 是关于抛弃“自上而下”/微观管理方法并考虑“自下而上”/自给自足的方法。值得记住的是,这两种方法都不是孤立的“正确”。创建可维护的代码是为了找到一个合理的平衡点,这需要大量的思考并且通常通过经验来发展。

于 2009-01-13T20:30:47.417 回答
3

这只是这里一些好书建议的附录。

我在 OO 上做得越好,我似乎就越能减小对象大小。这不像我要小对象大小或任何东西,但它似乎正在发生。

让它们保持小规模、单一职责、易于使用和理解——所有这些都至关重要。每个对象都应该尽可能地接近防弹,检查你的参数并且永远不要让你的对象进入无效状态。在文档中明确定义所有有效状态。

任何时候你创建一个类,为那个类创建一个测试。它不仅测试您的代码,而且迫使您使用自己的设计。始终从“外部视图”考虑您的班级。确保您没有对使用您的班级的人提出太多要求,并且您对他提出的任何要求都应记录在界面中。如果没有可用的测试框架,我通常只是将一个快速的 main 放入一个类中——它在同一个文件中放置了一个如何使用您的代码的示例。

在编码中,我几乎所有的时间都花在试图弄清楚别人做了什么上。如果我能够使用已知或有据可查的 API 发布代码,那么我的工作将变得微不足道,并且日程安排会大大缩短。

设计优先可能很难。将编码能力视为类似于运动能力。我们中的大多数人在我们的车道上比赛,少数人在当地的运动队比赛。在一个复杂的项目上做好前期设计是一个全国联赛球员的任务,他们是百万分之一。接受这一点并计划改变——迭代是你的朋友。(顺便说一句,我们大多数人认为我们很容易处于州一级。我们不是)。

于 2009-01-13T21:03:14.840 回答
3

除了 Brian 对Robert C Martin 的 Clean Code的推荐之外,您可能还想阅读“Uncle Bob 的”面向对象设计的 SOLID 原则

你可以听到他在Hanselminutes Podcast 145上谈论 SOLID 原则,在.NET Rocks上谈论干净的代码!显示 #388他在.NET Rocks上还有更多内容!显示 #410,但他所说的与你的问题并没有真正的关系,我只是把它包括在内,以防你喜欢前两个。

在三个播客中,我更喜欢 Hanselminutes。

于 2009-01-13T21:57:59.957 回答
2

Martin Fowler 的《重构》是一本关于如何在不破坏软件设计的情况下更改软件设计的优秀书籍。

设计模式的工作原理与算法类似,但会告诉您如何组合对象以执行各种有用的任务。

最后, Martin Fowler为应用程序提供了多种有用的设计模式。例如被动视图

于 2009-01-13T20:11:21.513 回答
1

Michael Feathers 的“Working Effectively with Legacy Code”应该很好,但我承认我自己没有读过。

重构为模式”也是如此。

于 2009-01-13T20:11:49.297 回答
1

我发现在没有帮助的情况下完成一项复杂的“任务”,然后看看其他人是如何完成的,这对我来说是一次重要的学习经历。

一项特别的任务是创建一个类似于银行的程序,我们必须在其中跟踪交易并能够计算所赚取的利息等。这确实是我的第一个 OOP 程序,而且由于它的复杂性而非常棒。(对于初学者来说)以线性方式执行它而不会出错,这太令人困惑了。

于 2009-01-13T20:11:57.127 回答
0

我只能说什么对我有用,我还没有真正找到任何人以同样的方式工作,所以我不确定它是否会对你有很大帮助。

基本上,我的方法是尽可能少的类,但不会更少。

首先,您需要保存信息的唯一时间是,如果您在时间 A 收到它并在稍后的时间 B 需要它。如果您同时获得并处理它,则可能不需要存储它.

其次,你用它做什么?如果您打算以某些简化的方式迭代它,您可以将其视为指令集,并将在其上运行的程序视为指令集的解释器。在这种情况下,您可能希望实际设计一个带有解释器的字节码指令集,并将您的信息编码到该指令集中。

第三,信息多久变化一次?如果某些信息很少更改,您也许可以使用部分评估(即代码生成)。也就是说,您获取不经常更改的信息并使用它来生成一个临时程序,该程序执行您的整个程序将使用该信息执行的操作,但速度要快得多。代码生成器很容易编写,因为它只处理输入信息的一部分,变化缓慢的部分。

我现在看到的大部分数据结构都是为了支持 UI。这显然不是持有用户关心的对象,理想情况下你也不应该关心。所以我为 UI 构建了一个 DSL,它隐藏了所有这些 hoo-haw。

如果可能,请远离事件和通知,因为它们发生在时间点上,因此代表状态的增量变化。您将不得不非常担心它们可能会被丢弃、复制或排序错误。通常它们被用于简单的轮询方式会“效率较低”的理论,而实际上相反的情况经常发生。

所以当我看到人们全神贯注于类等技术时,通常是因为他们做了太多的数据结构。

只是我的downvote诱饵...

于 2009-01-13T22:48:04.147 回答
0

我推荐 Feather 的Working Effectively with Legacy Code ,在Safari上可用且可搜索,而不是Refactoring。它充满了有用和善解人意的章节,比如我没有太多时间,我必须改变它我的应用程序没有结构。

需要考虑的观点:

  1. 自动化设计质量测试——寻找提供设计质量指标的工具,作为对设计决策的交叉检查。
  2. 代码可测试性——你的重构是否有助于或阻碍测试驱动的开发、编写单元测试或编写功能测试?集成后测试大型架构的难度有多大?
  3. 理由 - 你如何捍卫这些决定,从愤世嫉俗的 CYA 到管理层,更重要的是,让你的团队相信重新设计。您能否轻松且始终如一地解释为什么要进行更改,并且在 6 个月内是否容易找到该解释?

设计中的个人偏好,尤其是重构:

  1. 概念的类——当有疑问时,如果有一个明确的概念,它应该被包装在一个类中,而不是作为一个或多个方法中的一种行为。
  2. 许多与责任沟通的小事更容易思考和审核。如果对设计如何映射到现实世界有疑问,请回到旧的责任驱动设计方法,即写下每个类的职责。如果你觉得这很难,那么你对每个班级所做的事情的概念可能会很混乱,或者他们做得太多。
  3. 如果它们是常规的,不要被大的东西吓到。有时,例如:GUI 上的许多事件处理程序,您将合法地拥有比指标推荐的方法或属性多得多的类。
于 2009-01-14T00:10:56.023 回答
0

尝试编写更多可测试的代码,仅此一项就迫使我研究和实施改进的 OOP 实践/设计概念。

于 2009-01-14T00:16:04.890 回答