你如何设计面向对象的项目? [关闭]

问题描述 投票:222回答:23

我正在开发一个大型项目(对我来说),它有很多类,需要可扩展,但我不知道如何规划我的程序以及类需要如何交互。

我在几个学期后参加了OOD课程并从中学到了很多东西;比如编写UML,并将需求文档翻译成对象和类。我们也学习了序列图,但不知怎的,我错过了讲座或其他什么,他们并没有真正坚持我。

在以前的项目中,我尝试过使用从课程中学到的方法,但通常最终得到的代码一旦我能说“是的,看起来像我的想法”我不想挖掘泥土添加新功能。

我有一份史蒂夫麦康奈尔的代码完整副本,我不断听到这里和其他地方都很棒。我阅读了有关设计的章节,似乎没有提供我正在寻找的信息。我知道他说这不是一个削减和干燥的过程,它主要基于启发式,但我似乎无法将他的所有信息都应用到我的项目中。

那么你在高级设计阶段(开始编程之前)做了些什么来确定你需要什么类(特别是那些不基于任何“真实世界对象”的类)以及它们如何相互作用?

具体来说,我对您使用的方法感兴趣?您遵循的流程是什么,通常会形成一个良好,干净的设计,能够代表最终产品?

architecture oop class-design
23个回答
190
投票

我用于初始设计(获取类图)的步骤是:

  1. 需求收集。与客户交谈并分析用例以定义软件应具有的功能。
  2. 撰写个人用例的叙述。
  3. 通过叙述并突出显示名词(人,地点,事物),作为候选类和动词(动作),作为方法/行为。
  4. 丢弃重复的名词并分解常用功能。
  5. 创建一个类图。如果您是Java开发人员,Sun的NetBeans 6.7有一个UML模块,允许绘图和往返工程,它是免费的。 Eclipse(一个开源Java IDE)也有一个建模框架,但我没有使用它的经验。您可能还想尝试一种开源工具ArgoUML。
  6. 应用OOD原则来组织您的类(分解常见功能,构建层次结构等)

4
投票

首先 - 设计应该来自你的灵魂。你必须用你的每一根纤维来感受它。我经常走两三个月才开始做任何事情,只是走在街上(真的)。思考。你知道,散步是一种很好的冥想。所以它可以让你集中注意力。

其次 - 仅在存在自然对象层次结构的地方使用OOP和类。不要人为地“搞砸”它。如果不存在严格的层次结构(如在大多数业务应用程序中) - 请转到过程/功能,或者至少仅将对象用作具有隔离访问器的数据容器。

最后一点 - 尝试阅读:The Algorithm of Creative Thinking


4
投票

只是引用http://www.fysh.org/~katie/computing/methodologies.txt

而RUP的核心是一个小区域,你必须使用OO设计才能......如果你没有它们,那就像有一个运行100米的方法。

“第1步:写下跑步真的很快。第2步:去绘制赛道的计划。第3步:去买非常紧身的莱卡短裤。第4步:真的,真的,非常快地跑。第5步:交叉线第一“

这是第4步,这是艰难的。但是如果你把重点放在1,2,3和5上,那么没有人会注意到这一点,然后你可能会花很多钱卖掉这种方法,那就是运动员认为有一些“秘密”是100米跑过去


4
投票

你问了许多作者用来写书的问题。有很多方法,你应该选择一个看起来“最漂亮”的方法。 我可以推荐Eric Evans的书"Domain Driven Design"。另外,检查网站dddcommunity.org


4
投票

我建议您使用BlueJ和ActiveWriter来学习并开发对对象的良好理解。推荐的书也是一个不错的资源。

来自Wikipedia

BlueJ是Java编程语言的集成开发环境,主要用于教育目的,但也适用于小规模软件开发。

此外,它使用UML,对我来说,理解有关建模对象的几个方面是一个很好的资源。

alt text http://www.ryanknu.com/ryan/bluej.png

ActiveWriter是一个模拟实体和关系的工具,它还生成代码并且很容易进行更改。它将为您节省时间,并且敏捷开发非常适合。

alt text (来源:altinoren.com


3
投票

我认为这里的答案应该是非常不同的,这取决于这个家伙的实际经验。

如果您只有一到两年的工作经验,那么您必须达到以下目的:您如何确定您真正了解您的数据并准确理解您要做的事情?

是的,如果您已经在现实世界中工作了5年以上,那么您可以在许多软件开发过程模型或技术中进行选择。

但是你没有通过阅读书籍获得经验。你应该通过在良好的领导下在一个优秀的团队中工作来学习。

如果那不可能那么你应该自己做。开始迭代编写一个可能非常讨厌的代码片段,学习你的错误,倾倒所有代码,编写更好的代码等等。

您将学到很多关于代码库的知识。这些工具是工具,它们不会教你什么。


3
投票

如果您在项目中拥有领域专业知识,那么您将继续工作,例如银行业务。您可以轻松构建对象,并了解这些增强功能每隔一天如何进行。

如果您没有专业知识,那么具有该专业知识的人员就会将这些想法转化为技术细节。

如果您对如何构建项目设计感到困惑。盲目跟随“实用程序员”一书。我之前处于同样的境地,试着阅读那本书中的一章。你会看到它的不同之处,它将改变你作为软件开发者的思维方式。


2
投票
  1. 学习和掌握设计模式。
  2. 接下来,了解域驱动设计
  3. 之后,学习需求收集

我在几个学期后参加了OOD课程并从中学到了很多东西;比如编写UML,并将需求文档翻译成对象和类。我们也学习了序列图,但不知怎的,我错过了讲座或其他什么,他们并没有真正坚持我。

  1. 你知道第3步。你需要掌握它。我的意思是,通过大量的练习使它成为你的第二天性。那是因为你学到的方法完全违背了我们以前的方式。所以你需要真正掌握它。否则,你总会发现自己回到原来的做事方式。这有点像Test Driven Process,很多java开发人员经过几次尝试就放弃了。除非他们完全掌握它,否则它只是他们的负担
  2. 编写用例,尤其是替代课程。替代课程占我们开发时间的50%以上。通常,当您的PM为您分配任务时,例如,创建一个登录系统,他会认为它是直接的,您可以花1天时间完成它。但是他从不考虑你需要考虑的问题,1。如果用户输入错误的密码怎么办,2。如果用户输入错误密码3次,3,如果用户没有输入用户名等等怎么办?您需要将它们列出来,并将其显示给您的PM,要求他重新安排截止日期。

2
投票

我担心这不是人们喜欢听到的答案。无论如何,让我说出我的意见。

OOP应该被视为范式之一,而不是优越的范例。 OOP有助于解决某些问题,比如开发GUI库。它也适用于大型软件公司通常遵循的软件开发风格 - 设计师或架构师的精英团队在UML图或其他类似媒介中规划软件设计,而不那么开明的开发团队将该设计转化为源代码。如果您单独工作或与一群才华横溢的程序员合作,OOP几乎没有任何好处。然后,最好使用支持多种范例的语言,并帮助您快速提出原型。 Python,Ruby,Lisp / Scheme等都是不错的选择。原型是你的设计。然后你改进了。使用最能解决手头问题的范例。如果需要,使用C或其他系统语言编写的扩展名来优化热点。通过使用这些语言之一,您还可以免费获得可扩展性,不仅在程序员级别,而且在用户级别。像Lisp这样的语言可以动态生成和执行代码,这意味着您的用户可以通过编写小代码片段来扩展应用程序,使用软件本身编码的语言!或者,如果您选择使用C或C ++编写程序,请考虑为Lua这样的小语言嵌入解释器。将功能公开为使用该语言编写的插件。

我认为,大多数时候OOP和OOD创建的软件都是过度设计的受害者。

总而言之,我首选的编写软件的方法是:

  1. 使用动态语言。
  2. 用该语言本身编写设计(原型)。
  3. 如有必要,使用C / C ++优化某些区域。
  4. 通过实现语言本身的解释器提供可扩展性。

最后一项功能使软件能够轻松适应特定用户(包括我自己!)的要求。


2
投票

我使用测试驱动设计(TDD)。首先编写测试实际上有助于引导您进行干净和正确的设计。见http://en.wikipedia.org/wiki/Test-driven_development


2
投票

学习设计模式。过去两年来,这是我个人对OOP的革命。拿一本书。我会推荐你​​这个:

Head First Design Patterns

它在Java中,但它可以扩展到任何语言。


65
投票

我还没有足够的声誉发表评论(今天加入)或者我只是评论Scott Davies的回答。加上他不得不说的话:

  1. 在开始之前,请务必确定您的程序是什么。你的课程是什么?它不会做什么?它试图解决什么问题?
  2. 您的第一组用例不应该是程序最终将要执行的所有操作的清单。从您可以提出的最小的一组用例开始,这些用例仍然可以捕获您的程序的精髓。例如,对于此网站,核心用例可能是登录,提出问题,回答问题以及查看问题和答案。没有关于声誉,投票或社区维基的信息,只是你所拍摄的原始本质。
  3. 当你提出潜在的课程时,不要只考虑它们所代表的名词,而应考虑它们有什么责任。我发现这是在程序执行期间弄清楚类如何相互关联的最大帮助。很容易想出“狗是动物”或“小狗有一个母亲”之类的关系。通常很难找出描述对象之间运行时交互的关系。你的程序算法至少和你的对象一样重要,如果你已经详细说明了每个班级的工作,它们就更容易设计。
  4. 一旦获得了最小的用例和对象集,就开始编码。获得实际上尽快运行的东西,即使它没有做太多而且可能看起来像垃圾。这是一个起点,并将迫使您回答可能在纸上掩盖的问题。
  5. 现在回过头来选择更多用例,记下它们的工作方式,修改类模型,编写更多代码。就像你的第一次剪裁一样,尽可能少地拍摄,同时还要添加一些有意义的东西。冲洗并重复。

只是我的两分钱。希望它有用。


1
投票

老实说,一个很好的步骤将回过头来看流程图和序列图。有很多好的网站向您展示如何做到这一点。在查看我想如何将程序分解为类时,我发现它非常有用,因为我确切地知道程序需要输入,计算和输出的内容,并且每个步骤都可以分解为程序的一部分。



1
投票

一种有用的技术是将您独特的问题描述与您在现实世界中可以找到的内容联系起来。例如,您正在建立一个复杂的医疗保健系统,这个系统将风靡世界。你有什么例子可以随时打电话来模拟这个吗?

确实。观察药房的运作方式或医生的房间。

将您的域名问题降低到可以理解的范围;你可以联系到的东西。

然后,一旦域内的“玩家”开始变得明显,并且您开始为您的代码建模,请选择“提供者 - 消费者”建模方法,即您的代码是模型的“提供者”,并且您就是“消费者” ”。

关于域并在高层次上理解它是任何设计的关键部分。


1
投票

在我设计类结构的冒险中,我注意到从编写一些伪代码开始是非常有帮助的。这意味着:我开始在最高级别“编写”应用程序代码的一些通用片段,使用它,并发现出现的元素 - 事实上,我作为程序员想要使用的元素。这是设计模块的一般结构及其相互作用的一个非常好的起点。经过几次迭代后,整个结构看起来更像是一个完整的类系统。这是设计代码部分的一种非常灵活的方式。您可以将其称为面向程序员的设计。


19
投票

当我有机会时,我通常会使用我称之为“三次迭代规则”的东西。

在第一次迭代(或启动)中,我根据模型对象,算法和预期(真正预期的,未预期的)未来方向来设计应用程序的总体布局。我不编写设计文档,但如果我必须协调多个人,那么当然需要粗略描述该过程,同时分析依赖性和所需时间的猜测。如果像我一样,你更喜欢更敏捷的方法,尽量将这个阶段保持在最低限度。在某些情况下,需要一个强大的设计阶段,特别是当所有事情都已知并且对程序的逻辑真实,并且您计划在代码中的功能之间进行大量交互时。在这种情况下,提供的用例或用户故事是一个很好的高级想法,特别是对于GUI应用程序。对于命令行应用程序,特别是库,请尝试编写“程序故事”,在其中对您必须开发的库进行编码并检查其外观。完成后,这些程序将成为您库的功能测试。

在第一次迭代之后,您将更好地了解事物如何相互作用,了解细节和粗糙点,用一个打耳塞的胶带贴片解决问题。您已准备好利用这些经验来改进,清理,抛光,划分过大的内容,合并过于分散的内容,定义和使用设计模式,分析性能瓶颈和非常重要的安全问题。通常,所有这些更改都会对您编写的单元测试产生巨大影响,但不会对功能测试产生影响。

完成第二次迭代后,您将拥有一颗小宝石,经过良好测试,记录良好且设计精良。现在你有经验和代码来做第三次迭代,扩展。您将添加新功能和用例以改进您的应用程序。你会发现粗糙的斑点,你最终会进入第四次迭代,类似于第二次迭代。冲洗并重复。

这是我对软件设计的一般方法。它类似于螺旋设计,短期,三个月的迭代,以及敏捷开发的元素,使您可以了解问题并了解您的软件及其应用领域。当然,这是一个可扩展性的问题,所以如果应用程序如此庞大以至于涉及数百名开发人员,那么事情要比这复杂得多,但最后我想这个想法总是一样的,除了et impera。

所以总结:

  1. 在迭代一中,你会体验它并学习
  2. 在第二次迭代中,您将清理产品并为将来做好准备
  3. 在迭代三中,您可以添加新功能并了解更多信息
  4. 每两个

16
投票

关于这一点我知道的最有趣的来源是Bertrand Meyer的Object Oriented Software Construction, 2nd Edition的D部分。

D部分:面向对象的方法:很好地应用该方法

19:关于方法论,20:设计模式:多面板交互系统,21:继承案例研究:交互式系统中的“撤销”,22:如何找到类,23:类设计原则,24:使用继承,25:有用的技巧,26:风格感,27:面向对象的分析,28:软件构建过程,29:教学方法

有趣的是,章节22. How to find the classes可在线获取。


12
投票

它重复但完全正确 - 了解您的数据。

对于OOP,您的课程应该描述重要的信息以及它们如何相互作用。

如果您的心智模型能够很好地描述数据的行为和生命周期,那么您可以轻松地安排课程。

这只是一个扩展:确切地知道你要做什么。


10
投票

尝试使用行为驱动的开发。打破旧习惯很难,但我发现在现实世界中开发BDD确实是最好的选择。

http://behaviour-driven.org/


8
投票

大型项目的问题在于您无法监督组件之间的所有交互。因此,降低项目的复杂性非常重要。类和序列图对于此设计阶段来说过于详细。

首先尝试从更高的抽象级别进行思考。考虑主要组件及其职责(它们与其他组件的接口),看一些架构模式的灵感(不,不是设计模式,这些都是太低级别!MVC和Multi-Tier是架构模式示例)。对于相当大的项目,这样的视图应该有大约3-5个组件。

只有这样你才能放大某个组件并尝试设计它。现在我们处于设计模式和类图的层面。尝试关注项目的这一部分,如果您发现需要将责任添加到其他组件之一,只需将其添加到文档/待办事项列表中即可。不要浪费时间考虑其影响,在这一点上,他们的变化太快,在设计更加稳固时进行审核。

此时您不需要完全设计每个组件,尽管使用一段代码实现未实现的组件接口并生成简单但有用的响应可能是明智之举。这样,您可以一次开始开发(和设计)一个组件并对其进行合理的测试。

当然,当新组件完成后,您应该在继续之前测试它们如何(以及是否)相互集成。

非常简短:采用面向对象和信息隐藏原则,将其提升到另一个层次!


PS:在设计时做了很多素描,就像真正的建筑一样!

PPS:尝试从不同角度处理问题,在盒子外面思考(尽管盒子可能是要走的路),与同伴讨论对此非常有用......你可以在午餐时谈谈。


7
投票

我在真实项目中使用的技术取得了一定的成功,是责任驱动设计,灵感来自Wirfs-Brock的书。

从顶级用户故事开始,与同事一起在白板上绘制他们所暗示的高级别互动。这让您首先了解大模块是什么;和一两次高级CRC卡一样,您应该已经稳定了一系列主要组件,他们做了什么以及他们如何互动。

然后,如果任何职责很大或很复杂,那么通过在模块内部为更高级别交互所识别的每个主要操作播放内部的交互,将这些模块向下细化,直到您拥有足够小且足够简单的对象为止。 。

知道何时停止是一个判断问题(只有经验才有)。


7
投票

设计模式

创作设计模式

单例 - 确保仅创建一个类的一个实例并为该对象提供全局访问点。

Factory(Factory方法的简化版) - 创建对象而不将实例化逻辑暴露给客户端,并通过公共接口引用新创建的对象。

工厂方法 - 定义用于创建对象的接口,但让子类决定实例化哪个类,并通过公共接口引用新创建的对象。

抽象工厂 - 提供用于创建相关对象族的界面,而无需明确指定其类。

构建器 - 定义用于创建对象的实例,但允许子类决定实例化哪个类,并允许更好地控制构造过程。

原型 - 使用原型实例指定要创建的对象类型,并通过复制此原型来创建新对象。

行为设计模式

责任链 - 它避免将请求的发送者附加到其接收者,这使得其他对象也可以处理请求。 - 对象成为链的一部分,请求从一个对象发送到另一个对象,直到其中一个对象将处理它。

命令 - 在对象中封装请求,允许对具有不同请求的客户端进行参数化,并允许将请求保存在队列中。

解释器 - 给定一种语言,定义其语法的表示以及使用该表示来解释语言中的句子/将域映射到语言,将语言映射到语法,将语法映射到分层面向对象设计的解释器。

迭代器 - 提供一种顺序访问聚合对象元素的方法,而不暴露其底层表示。

介体 - 定义一个封装一组对象如何交互的对象。 Mediator通过使对象明确地相互引用来促进松散耦合,并且它允许您独立地改变它们的交互。

Observer - 定义对象之间的一对多依赖关系,以便当一个对象更改状态时,将自动通知和更新其所有依赖关系。

策略 - 定义一系列算法,封装每个算法,并使它们可互换。策略允许算法独立于使用它的客户端。

模板方法 - 在操作中定义算法的骨架,将一些步骤推迟到子类/模板方法让子类重新定义算法的某些步骤,而不让它们更改算法的结构。

访问者 - 表示要对对象结构的元素执行的操作/访问者允许您定义新操作而不更改其操作的元素的类。

空对象 - 提供一个对象作为缺少给定类型对象的代理。 / Null对象模式提供智能无任何行为,隐藏其协作者的详细信息。

结构设计模式

适配器 - 将类的接口转换为客户期望的另一个接口。 / Adapter允许类一起工作,否则由于不兼容的接口而无法工作。

Bridge - 将对象组合成树结构以表示部分整体层次结构。 / Composite允许客户端统一处理单个对象和对象组合。

Composite - 将对象组合成树结构以表示部分整体层次结构。 / Composite允许客户端统一处理单个对象和对象组合。

装饰器 - 动态地向对象添加其他职责。

Flyweight - 使用共享来支持大量具有部分内部状态的对象,其中状态的其他部分可以变化。

Memento - 捕获对象的内部状态而不违反封装,从而提供在需要时将对象恢复到初始状态的方法。

代理 - 为对象提供“占位符”以控制对它的引用。

© www.soinside.com 2019 - 2024. All rights reserved.