如何决定何时抽象共同属性?

时间:2017-05-13 21:30:20

标签: oop design-patterns database-design database-schema software-design

想象一下,我们有两种类型的请求,一种是InvoiceRequest和一种QuoteRequest。您更喜欢对象模型(类)和数据库模型?以下哪两项更有意义?

InvoiceRequest: 
 - id
 - amount
 - discount
 - date
 - invoiceSpecificFieldHere

QuoteRequest:
 - id
 - amount
 - discount
 - date
 - quoteSpecificFieldHere. 

或者这个更有意义吗?

RequestData:
 - amount
 - discount
 - date

InvoiceRequest: 
 - id
 - requestData: <RequestData>
 - invoiceSpecificProperty

QuoteRequest:
 - id
 - requestData: <RequestData>
 - quoteSpecificProperty. 

我没有代表使用继承的第三个选项。

这个问题背后的问题如下:如果我们选择设计2,我们会减少冗余,但是有一些东西感觉不对。我认为折扣应与quoteSpecificProperty处于同一级别。将它放在requestData对象中并不能正确建模。

4 个答案:

答案 0 :(得分:2)

我的印象是,您正在混合面向对象建模和关系数据建模的概念。这是因为从关系数据建模的角度来看,您的第二个解决方案不是正确。

由于我不了解您在模型实施方面的确切需求,我将尝试针对不同情况提出解决方案。

如果你想使用面向对象语言实现的纯面向对象模型,你应该明确定义一个超类Request,它有两个子类InvoiceRequest和QuoteRequest,它们都具有特定的属性。

如果要在纯关系模型中使用关系数据库实现您的情况,您应该定义三个表:

Requests:
 - id (Primary Key)
 - amount
 - discount
 - date

InvoiceRequests: 
 - id (Primary Key) (Foreign Key for Requests)
 - invoiceSpecificProperty

QuoteRequests:
 - id (Primary Key) (Foreign Key for Requests)
 - quoteSpecificProperty. 

最后,如果你想使用对象关系映射,你应该设计一个超类Request,带有两个子类InvoiceRequest和QuoteRequest,它们都具有特定的属性,然后你可以将它映射到关系数据库中像前一个模型一样。

当然,在关系建模中还有另一种可能性,即具有单个表请求,具有所有属性,包括特定报价和发票特定,以及用于区分哪种请求是当前请求的属性。

答案 1 :(得分:0)

第二个更有意义,因为当您设计对象及其所拥有的字段时,您正在制作 抽象 真实的单词,以及它如何看待以及它中的行为。您在这里处理的是名为 normalization

的内容

数据库规范化或简单规范化是组织关系数据库的列(属性)和表(关系)以减少数据冗余和提高数据完整性的过程。  这种关系并不总是与世界上的现实完全匹配,但你必须从真实的词语中抽象出来,并将数据视为彼此相关。

答案 2 :(得分:0)

我将与您分享本周收集的一些信息。

也许SOLID原则可以帮助您做出决定。

SOLID =(Single responsibility principle,Open/closed principle,
Liskov substitution principle,Interface segregation principle,
Dependency inversion principle or Dependency injection principle.

好吧,这不仅仅是属性抽象。让我们看一些例子:

<强>取值

根据维基百科,单一责任原则意味着

  • 一个班级只有一个理由可以改变它 实施;
  • 类对其他类的依赖性很小;
  • 类应该从它们运行的​​特定层抽象出来。

<强> 0

定义课程或单元时,请记住:

They shall be open for extension;
But closed for modification.

关于修改,认为在bug情况下,你有义务做到这一点,第二个模型的修改对于常见的领域来说最容易。

第一个模型

InvoiceRequest: 
 - id
 - amount
 - discount
 - date
 - invoiceSpecificFieldHere
QuoteRequest:
 - id
 - amount
 - discount
 - date
 - quoteSpecificFieldHere.

第二个模型 - 公共字段

 QuoteRequest:
     - id
     - requestData: <RequestData>
     - quoteSpecificProperty.  

<强>→

根据&#34; Barbara Liskovs的替代原则&#34; ,如果TChildTParent的子类型,则TParent类型的对象可以替换为TChild类型的对象,而不会更改该程序的任何所需属性(正确性) ,任务执行等)。 我的意思是objects的{​​{1}},TParent的实例,而不是TParent类的实例。

当您想使用Interface实现此示例时,这是一个有趣的话题。也可以按照:

<强> I

界面隔离原则

<强> d

依赖倒置原则 另一种形式的解耦是反转软件设计的高级和低级之间的依赖关系:   - 高级模块不应依赖于低级模块。都    应该取决于抽象;   - 抽象不应取决于细节。细节应该取决于    抽象。

要了解有关SOLID原则的更多信息,请阅读http://blog.synopse.info/post/2011/11/27/SOLID-design-principles

在简历中,观察对象模型的三个特征:

  • 刚性 - 很难改变一些因为每一个变化都会影响 该系统的许多其他部分;
  • 脆弱性 - 当您进行更改时,系统的意外部分 打破;
  • 不动性 - 难以在其他应用程序中重复使用,因为它不能 从当前的申请中解脱出来。

特别感谢A.Bouchez,来源http://blog.synopse.info/post/2011/11/27/SOLID-design-principles

答案 3 :(得分:0)

发票和报价是两个完全不同的东西,即使它们看起来很相似。最好将它们分开,因为对其中一项进行更改可能会对另一项产生有害的副作用。