文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

用代码来说明,为什么需要面向扩展的设计

2024-12-24 17:12

关注

在基本的面向对象编程中,你只能直接调用一个类的方法,而这些方法是由这个类的作者定义的,这对于面向用户设计的类来说是没有问题的。此外,在 20 - 30 年前,在大型标准库和开源库被大量复用之前,大部分代码通常是跟自己的代码中的类来一起工作的 —— 也就是你自己的团队或公司维护的代码。然而,在现代代码世界中,我们经常会使用其他人编写的类。

业务逻辑通常大量使用包括字符串和集合等标准库功能、以及第三方库中的一些类,我们受到这些类提供的操作的限制。例如,当我们需要用破折号替换字符串中的空格时,我们会这样编写代码:

  1. string.replace(' ''-'

但是当我们需要将左边的字符串对齐到指定的长度时,我们可能没有现成的方法可用,在这些旧的语言(如 Objective-C、C++、Java 或 JS)中,你需要强制写成这种形式:

  1. leftPad(string, ' ', length) 

这个 leftPad 可能来自一个单独的库¹,也可能来自第三方的工具函数集合(比如 Apache Commons),或者在你自己的项目中自行编写。总之,它的调用看起来和字符串类上的内置方法是非常不同的。

为什么会有这样的问题呢?我引用 Java 的作者之一 Guy Steele,他在 1998 年的《成长的语言》论文²中的一段话。

在大多数语言中,用户至少可以定义一些新语法来代表另外一段代码,然后可以很方便地调用这些代码,这种方式可以让新语法看起来像原生调用一样。通过这种方式,用户可以构建一个更大的语言来满足他的需求。

Guy Steele, Growing a Language

他是在批评 APL 缺乏这样的设施,但同样的批评也适用于现代环境下的旧的面向对象语言。你被困在一个类的操作词汇表上,而这个词汇表是原始库的设计者们所设想的,它不能由你来扩展。此外,它也没法被广泛使用的库的维护者随意地扩展,再次引用同一篇论文中的内容作为原因。

编程词汇的一部分适合所有程序员使用,但其他部分仅适合少数几个人。 程序员需要了解学习其所有词汇用法,这并不公平。

现代语言(如 C#、Scala、Rust、Kotlin 和 Swift)通过支持扩展方法解决了这个问题。你可以在不是你控制的类中添加特定领域的扩展方法,这样,你自己的函数可以用类似于内置方法来调用,而你的代码仍然可以像散文一样,流畅的按从左到右的顺序阅读。

  1. string.padLeft(' ', length) 

这个 padLeft 扩展可以在任何地方定义,它是一个很好的编程语言进化的故事。但是,它的意义还不止于此。

一旦一种编程语言支持扩展函数,它就改变了经典面向对象的 API 设计方法。这对于一个从 Java 这样的旧语言,切换到 Kotlin 这样的现代语言的程序员来说,是一个不小的启示,因为扩展函数通常只是作为方便的语法糖³呈现出来。我们还是先看一个带有一堆属性(或 getter 方法)的接口。

interface Obscure { val foo: Int val bar: Int val sum: Int val max: Int val min: Int}

它和你在一个典型的商业应用程序中找到的接口或类并无大的区别 —— 有一堆属性和方法。

你能快速掌握这个接口代表了一个什么样的实体吗?它的状态空间是由哪些属性构成的?如果没有额外的文档,要弄清楚这一点并不容易。但是,让我们把这个接口重构成一个核心实体和方便的扩展函数。

  1. interface NotObscure { 
  2.     val foo: Int 
  3.     val bar: Int 
  4.  
  5. val NotObscure.sumInt 
  6. val NotObscure.maxInt 
  7. val NotObscure.minInt 

现在,很明显,这个接口的核心功能是由两个整数属性 foo 和 bar 组成的,而其余的 sum、max 和 min 属性只是为了方便起见而提供的,并在这些核心属性的基础上进行计算。不需要再明确地写文档描述这种区别了 —— 从代码的结构中就可以直接看出。

这种面向扩展的设计在 Kotlin 标准库和第三方库中得到了广泛的应用。它是一种强大的设计技术,使用它会有非常好的效果。

这种设计方法有一个副作用。你可能会注意到,Kotlin 代码通常会使用通配符 import,比如 import com.examplease.*。这在 Kotlin 中很方便,因为在 Kotlin 中仅导入一个类是非常少见的。所有有用的、方便的、实用的函数通常都定义在同一个包中,但在类外作为扩展函数定义。

文中链接:

https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/ How one developer just broke Node, Babel and thousands of projects in 11 lines of JavaScript, Chris Williams, 2016

https://www.cs.virginia.edu/~evans/cs655/readings/steele.pdf Growing a Language, Guy Steele, 1998

https://kotlinlang.org/docs/reference/extensions.html Extensions in Kotlin Programming Language

英文原文:

https://medium.com/@elizarov/extension-oriented-design-13f4f27deaee

本文转载自微信公众号「 高可用架构」,可以通过以下二维码关注。转载本文请联系 高可用架构公众号。

 

 

来源:高可用架构内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯