面向数据编程 Data-Oriented Programming [10]

1.7 当代码锁定在类中时,类层次结构很复杂

  避免在OO中两次编写相同代码的一种方法涉及类继承。实际上,当预先知道系统的每个需求时,您可以这样设计类层次结构,即具有共同行为的类从基类派生。
  此模式的一个示例如图1.15所示,重点放在我们的类图中处理Member和Librarian的部分。Member和Librarian都需要登录能力,他们从User类继承了这一能力。

到目前一切尚好。

图1.15类图中处理成员和图书馆员的部分

 
  但是,当在系统实现之后添加对系统的需求时,情况就完全不同了。
  现在是星期一上午11点,离截止日期还有两天(周三午夜),南希给你打了一个紧急电话。
  你不确定这是梦境还是现实。你捏一下自己,就会感觉到震动。这绝对是现实!

南希:“项目进行得怎么样了?”

你:“很好,南希。我们如期赶上了最后期限。运行我们上一轮的回归测试。”

南希:“太棒了!这意味着我们有时间在系统中添加一个小功能。对吗?”

你:“那要看你说的“小”是什么意思了。”

南希:“我们需要把VIP会员加入系统。”

你:“你说的VIP会员是什么意思?”

南希:“VIP会员是指允许自己向图书馆添加图书的会员。”

你:“嗯…”

南希:“什么?”

你:“这可不是个小变化!”

南希:“为什么?”

  我也在问你南希曾经问过的问题:为什么把VIP会员加入你的系统不是一件小事?

  毕竟,您已经编写了允许图书管理员向图书馆添加图书项目的代码:它位于Librarian::addBookItem()中。

  是什么阻止您对VIP会员重复使用此代码?

  原因是在面向对象中,代码作为方法锁定在类中。

TIP 在面向对象中,代码被锁定在类中。.

  让我们看看您会如何处理客户在最后一刻提出的这一请求。

  VIP会员是允许自己向图书馆添加图书项目的会员。

  让我们将客户需求分解为两部分:

  1. VIP会员是会员
  2. 允许VIP会员自行向图书馆添加图书

当然,您需要一个新的类VIPMember。

  对于需求#1,让VIPMember派生自Member听起来很合理

  然而,处理要求#2更为复杂。我们不能使VIPMember派生自Librarian,因为VIPMember和Librarian之间的关系不是线性的:

  1. 一方面,VIP会员就像图书管理员,他们被允许添加图书项目
  2. 另一方面,VIP会员不像图书馆管理员,因为他们不被允许阻止会员或列出会员的图书借阅情况

  问题是添加图书项目的代码锁定在Librarian类中。VIPMember类无法使用此代码

  一种可能的解决方案是使Librarian::addBookItem()的代码对Librarian和VIPMember都可用,如图1.16所示。以下是对前一个类关系图的更改:

  1. 扩展User的UserWithBookItemRight基类
  2. 将addBookItem()从Librarian移到UserWithBookItemRight
  3. VIPMember和Library均使用BookItemRight扩展UserWithBookItemRight
图1.16具有VIP成员的系统的类图

 
  这很艰难,但你能够按时处理(这要归功于你笔记本电脑前的一个白色夜晚)。您甚至可以在系统中包含新的测试,并再次运行回归测试。

  您太兴奋了,以至于没有注意到类关系图中引入的菱形VIPMember(VIPMember用BookItemRight扩展了Member和UserWithBookItemRight,它们都扩展了User)

  我们是周三上午10点,离截止日期还有14个小时,你打电话给南希,告诉她这个好消息:

你:“南希,我们可以按时把贵宾会员加入系统。”

南希:“太棒了!我告诉过你这只是个很小的特写”

你:“嗯…”

南希:“听着,反正我也要给你打电话的。我刚刚和我的商业伙伴开完会,我们意识到在发布之前我们还需要一个小功能。你能在截止日期前处理好吗?”

你:“再一次,这取决于你所说的“小”是什么意思。”

南希:“我们需要在系统中加入超级会员。”

你:“你说的超级会员是什么意思?”

南希:超级会员是指允许屏蔽和解锁会员的会员

你:“嗯…”

南希:“什么?”

你:“这可不是个小变化!”

南希:“为什么?”

  与VIP会员一样,向系统添加超级成员需要更改类层次结构。图1.17显示了一种可能的解决方案。

图1.17包含超级会员和VIP会员的系统的类图

 
  超级会员的加入使系统变得过于复杂。你突然发现你的职业图中有3颗钻石:不是宝石,而是3颗致命的死亡钻石!
  您试图通过将User类转换为接口并使用组合重于继承设计模式来避免菱形。

  但是,随着最后期限的到来,你无法使用你大脑中的所有细胞。

  事实上,这种复杂性使您无法在最后期限之前交付系统。您告诉自己应该使用组合而不是类继承。但现在已经太晚了。

TIP 在面向对象中,更喜欢组合而不是类继承。

  你打电话给南希,让她在晚上10点,也就是截止日期前两个小时向她解释情况:

你:“听着,南希,我们真的已经尽力了,但是我们不能在截止日期前把超级会员加入系统”

南希:“别担心,我和我的生意伙伴决定推迟发布会。”

你:呼!

南希:“你觉得如果我们以后再增加其他小功能,你能按时处理吗?”

你:“是的。”

南希:“怎么可能呢?”

你:“我们将把系统从面向对象重构为面向数据”

南希:“什么是面向数据的?”

你:"它是一种神奇的调料,允许开发人员编写代码以更快地更改需求! "

TIP DO是一种神奇的调料,它允许开发人员编写代码以更快地更改需求!

  读完这本书后,你将属于快乐的开发者社区,他们知道DO魔法酱的食谱。

1.8 总结

  在本章中,我们探讨了OO增加系统复杂性的趋势,即OO系统往往难以理解。复杂性增加的根本原因与将代码和数据混合到对象中有关。

  我们说明了OO的一些基本方面是如何增加OO系统的复杂性的。

  面向对象编程的各个方面及其对增加系统复杂性的影响

方面对复杂性增加的影响
代码和数据混在一起类往往涉及许多关系。
对象是可变的阅读代码时的额外思考
对象是可变的多线程环境中的显式同步
数据锁定在对象中数据序列化是不容易的
代码锁定在类中类层次结构很复杂

  可以使用智能设计模式和该语言的高级功能来处理这种复杂性。这本书建议通过坚持面向数据的编程来处理这种复杂性,这是一种可以在OO和FP中实现的范例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值