我是一名c ++程序员,我期待学习和掌握OO设计.我已经做了很多搜索,而且我们都知道有很多关于如何实现良好的OO设计的材料,书籍,教程等.当然,我确实理解一个好的设计只能带来大量的经验,个人才能,才华横溢,或者事实上甚至只是运气(夸张!).
但是肯定这一切都始于一个坚实的开端和建立一些强大的基础.可以通过指出正确的材料来帮助我,如何从识别对象,类等到舞台的阶段开始学习设计的任务使用设计模式.说我是程序员,但我没有设计经验.可以请你帮我从程序员到设计师的过渡中帮助我吗?任何提示,建议和建议都会有所帮助.
[编辑]感谢链接和答案,我需要自己介绍:)正如我之前提到的,我是一名C++程序员,我确实理解OO基本概念,如继承,抽象,多态和写C++中的代码也理解了一些设计模式.我不理解的是基本的思维过程,人们应该接近一个要求.关于如何评估和决定应该制作什么类的细节,以及如何定义或总结他们应该拥有的关系.知道概念(在某种程度上)但不知道如何应用它们是我似乎的问题有:(有任何建议吗?
(非常)简单但不简单的设计(如果你愿意,设计简单):亲吻.
首选平面层次结构,避免深层次结构.
关注点分离至关重要.
当它看起来不够简单或优雅时,考虑其他"范例"而不是OO.
更一般地说:DRY和YAGNI帮助您实现1.
没有秘密.这是汗水,而不是魔法.
这不是关于做正确的事情.它正在平衡许多不容错过的事情.有时,它们同步工作,有时候,它们彼此相互作用.设计只是这些方面中的一组.如果项目失败(例如因为它从未发货),最好的设计无济于事.
我提出的第一条规则是:
1.没有绝对的 直接来自"很多东西要平衡.干,YAGNI等是指导方针,严格遵循它们不能保证良好的设计,如果后面跟着它们可能会使你的项目失败.
示例: DRY最基本的原则之一,但研究表明,由于前/后条件检查,错误处理以及对多个相关案例的推广,小代码片段的复杂性在它们被隔离时会增加3倍或更多.所以原则需要被削弱为"干(至少,不要太多)" - 何时何时不是困难的部分.
第二条规则不是很常见的规则:
2.接口必须比实现简单
听起来很容易上口.然而,有很多话要说:
面向对象的前提是管理无法通过结构化编程管理的程序大小.主要机制是封装复杂性:我们可以隐藏更简单的接口背后的复杂性,然后忘记这种复杂性.
接口复杂性涉及文档,错误处理规范,性能保证(或缺少)等.这意味着例如通过引入特殊情况来减少接口声明并不是降低复杂性 - 只是一种洗牌.
3-N这里我提到了大部分其他提及的内容,已经很好地解释了.
关注点分离,KISS,SOLID原则,DRY,大致按此顺序排列.
如何根据这些指南构建软件?
以上指南有助于评估一段代码.不幸的是,没有配方如何到达那里."经验丰富"意味着您对如何构建软件有良好的感觉,而某些决策只是感觉不好.也许所有的原则都只是事后的合理化.
一般的道路是将系统分解为责任,直到各个部分都可以管理.
有正式的过程,但这些只是围绕这样一个事实,即一个好的,孤立的组成部分是一个主观的决定.但最终,这就是我们得到的报酬.
如果你对整个系统有一个粗略的想法,那么从这些作为种子之一开始并将它们培养成"核心"并没有错.自上而下和自下而上不是对映.
实践,实践,实践.构建一个小程序,使其运行,更改需求,让它再次运行."不断变化的要求"部分你不需要培训很多,我们有客户.
项目后评论 - 即使是为了个人项目,也要习惯他们.密封完成后,评估什么是好的,什么是坏的.考虑一下源代码被丢弃 - 即不要将sessison看作"应该修复什么?"
康威定律说"一个系统反映了构建它的组织结构." 这适用于我见过的大多数复杂软件,正式研究似乎证实了这一点.我们可以从中得到一些信息:
如果结构很重要,那么与你合作的人也是如此.
或许结构并不那么重要.没有一个正确的结构(只有许多错误的结构要避免)
我要引用Marcus Baker在论坛帖子中讨论如何实现优秀的OO设计:http://www.sitepoint.com/forums/showpost.php? p = 4671598&posttcount = 24
1)拿一个用例的一个线程.
2)实现任何旧的方法.
3)拿另一个线程.
4)实现任何旧的方法.
5)寻找共性.
6)对代码进行因式分析,以便将共性收集到函数中.旨在清晰的代码.没有全局,传递一切.
7)任何不清楚的代码块,也分成一个函数.
8)实现另一个线程任何旧的如何,但如果它们是即时插入,请使用现有的功能.
9)一旦工作,再次考虑去除重复.到目前为止,您可能会发现从功能到功能都会传递类似的东西.要删除重复,请将它们移动到对象中.
10)一旦你的代码完美,就实现另一个线程.
11)重复以避免重复,直到无聊.
现在OO位......
12)到目前为止,应该出现一些候选人更高的角色.按类分组这些函数.
13)为了清晰起见,再次重构.没有比几页代码大的类,没有超过5行的方法.除非变体只是几行代码,否则没有继承.
从这一点开始,你可以循环一下......
14)实现任何旧的用例线程如何.
15)重构如上.重构包括重命名对象和类,因为它们的含义在不断变化.
16)重复直到无聊.
现在模式的东西!
一旦你有几十个类和相当多的功能启动和运行,你可能会注意到一些类具有非常相似的代码,但没有明显的分裂(不,不使用继承).此时,请参阅模式书籍以了解有关删除重复的选项.提示:你可能想要"战略".
以下重复......
17)实现用例的另一个线程任何旧的如何.
18)重构方法低至五行或更少,类别低至2页或更少(最好少很多),寻找模式,以删除更高级别的重复,如果它真的使代码更清洁.
19)重复直到你的顶级构造函数要么有很多参数,要么你发现自己经常使用"new"在其他对象中创建对象(这很糟糕).
现在我们需要清理依赖项.任何有效的类都不应该使用"new"来创建内部的东西.从外面传递这些子对象.不进行机械工作的类允许使用"new"运算符.他们只是组装东西 - 我们称之为工厂.工厂本身就是一个角色.一个类应该只有一个角色,因此工厂应该是单独的类.
20)将工厂排除在外.
现在我们再说一次......
21)实现任何旧的用例的另一个线程.
22)将方法重构为五行或更少,类别低至2页或更少(最好少一些),寻找模式以删除更高级别的重复,如果它真的使代码更清洁,请确保为工厂使用单独的类.
23)重复直到你的顶级课程有过多的参数(例如8+).
你现在可能已经完成了.如果没有,请查找依赖注入模式......
24)使用依赖注入器创建(仅)顶级类.
然后你可以再重复一次......
25)实现用例的另一个线程任何旧的如何.
26)将方法重构为五行或更少,类别减少到2页或更少(最好少一些),寻找模式以删除更高级别的重复,如果它真的使代码更清洁,确保你为工厂使用单独的类,通过DI传递顶级依赖项(包括工厂).
27)重复.
在这个启发式的任何阶段,您可能希望看一下测试驱动的开发.至少它会在你重构时停止回归.
显然,这是一个非常简单的过程,其中包含的信息不应该适用于所有情况,但我觉得Marcus是正确的,特别是关于应该用来设计OO代码的过程.过了一会儿,你会自然地开始做它,它将成为第二天性.但是在学习的同时,这是一系列很好的步骤.
正如你所说,没有经验.你可以阅读这个星球上现有的所有书籍,你仍然不如练习那么好.
理解这个理论是好的,但在我的拙见中,没有什么比经验更好的了.我认为完全学习和理解事物的最好方法是在一些项目中应用它们.
在那里你会遇到困难,你会学会解决它们,有时也许会有一个糟糕的解决方案:但你仍然会学习.如果在任何时候有什么事情困扰你,你无法找到如何很好地解决它,我们将在这里帮助你!:)