POSIX API 和 SOLID 设计原则
POSIX API and SOLID design principles
虽然SOLID设计原则主要应用于面向对象系统,但也有一些SOLID概念可以应用于过程式编程,例如SRP或DIP。但是当我研究POSIXAPI中的一些功能时,我注意到有些原则没有得到尊重,即使它可能是这样。
我以SRP为例,系统调用sigaction:
- SRP 指出,在我们的例子中,一个函数必须具有单一职责,这意味着我们系统规范的单个部分的变化是一件事可以更改功能的规格。
- sigaction 是一个系统调用,用于改变进程在收到信号时采取的操作。
sigaction 可用于安装以下形式的基本处理程序:
void (*sa_handler)(int)
这意味着处理程序只接收到执行其操作的信号编号。系统调用也可用于安装以下形式的处理程序:
void (*sa_sigaction)(int, siginfo_t*, void*)
这让我们获得了有关已处理信号的更多信息。由于调用者放置的标志,两种形式都使用相同的系统调用安装。
在我看来,sigaction违反了SRP原则,因为它有责任实现两种类型的处理程序安装。
所以我的问题是:POSIXAPI是否违反了 SOLID 原则,如果是,为什么?
除了这些原则是意见问题之外,POSIX 比 SOLID 早几十年。它还主要记录现有实践并将其形式化,而不是从头开始重新发明事物。由委员会设计往往是一个比违反像 SRP 这样的迂腐更严重的问题,所以这几乎肯定是一件好事。
请注意,POSIX 实际设计的某些界面确实严格遵循 OOP 设计原则,通常采用引入缺陷的方式。例如,posix_spawn
无法成为 fork
和 execve
的 AS 安全替代品,因为它依赖于属性对象的创建。 POSIX 线程接口也大量借鉴了 OOP 的方法,这些方法通常不会破坏任何东西,但使用起来却无缘无故地痛苦。
我们真的不知道您调用的 sa_sigaction 的特定实现的目的,即单一责任。
不过,如果我不得不猜测的话,我希望 sa_sigaction 实现是一个接口模块的一部分,该接口模块在较低的顶部实现 POSIX API -level OS 特定功能,sa_sigaction 函数的职责之一是实现 POSIX 规范的特定部分。
换句话说,它是一个适配器模式对象,并且具有单一职责。
也许您的意思是说 POSIX API 规范违反了 SRP...也许 但这并不重要。 SRP 用于使您的系统能够适应不断变化的需求。作为一个古老的 API 标准,POSIX 没有满足很多新要求。它本质上记录了过去的事情,历史事实不会改变。
does POSIX API violates SOLID principles?
是。 POSIX 已有数十年历史,由 许多 软件工程师在 IEEE 的支持下编写。 SOLID 相对较新(相比之下),是由一个名叫 Bob 的人编写的。
POSIX 更成熟,它背后的人意识到有简洁的小首字母缩略词(即 S.O.L.I.D。)不能解释软件工程中的所有小异常。
如果你问我,SOLID 就是违反了 POSIX。
恕我直言,我认为您的示例如履薄冰(它也忽略了 SOLID 中的 D)。
POSIX 可能违反了 SOLID 原则(也可能不违反)......但另一方面,POSIX 对什么可以分开,什么属于一起有成熟的理解(来自实际使用的理解)。
换句话说,问题是关于"what is a single responsibility?"的范围,POSIX有几十年的经验帮助它划清界限。
在您的示例中,您声明 sigaction
必须实现这两种类型的东西,但这是一个谬论。
sigaction
有一个单一的职责——它需要注册一个回调。回调类型实际上是无关紧要的,因为责任在 "registering".
如果数组 push
函数是类型不可知的,它会违反 SRP 原则吗?不,它只处理一个职责——推送到数组。这里也一样。
如果我按照你的逻辑,为每个回调类型实现不同的函数,我会发现自己一遍又一遍地编写相同的代码,但有细微的变化——这违反了 DRY 原则,这是一个明显的迹象这些功能职责相同,应该统一。
虽然SOLID设计原则主要应用于面向对象系统,但也有一些SOLID概念可以应用于过程式编程,例如SRP或DIP。但是当我研究POSIXAPI中的一些功能时,我注意到有些原则没有得到尊重,即使它可能是这样。
我以SRP为例,系统调用sigaction:
- SRP 指出,在我们的例子中,一个函数必须具有单一职责,这意味着我们系统规范的单个部分的变化是一件事可以更改功能的规格。
- sigaction 是一个系统调用,用于改变进程在收到信号时采取的操作。
sigaction 可用于安装以下形式的基本处理程序:
void (*sa_handler)(int)
这意味着处理程序只接收到执行其操作的信号编号。系统调用也可用于安装以下形式的处理程序:
void (*sa_sigaction)(int, siginfo_t*, void*)
这让我们获得了有关已处理信号的更多信息。由于调用者放置的标志,两种形式都使用相同的系统调用安装。
在我看来,sigaction违反了SRP原则,因为它有责任实现两种类型的处理程序安装。
所以我的问题是:POSIXAPI是否违反了 SOLID 原则,如果是,为什么?
除了这些原则是意见问题之外,POSIX 比 SOLID 早几十年。它还主要记录现有实践并将其形式化,而不是从头开始重新发明事物。由委员会设计往往是一个比违反像 SRP 这样的迂腐更严重的问题,所以这几乎肯定是一件好事。
请注意,POSIX 实际设计的某些界面确实严格遵循 OOP 设计原则,通常采用引入缺陷的方式。例如,posix_spawn
无法成为 fork
和 execve
的 AS 安全替代品,因为它依赖于属性对象的创建。 POSIX 线程接口也大量借鉴了 OOP 的方法,这些方法通常不会破坏任何东西,但使用起来却无缘无故地痛苦。
我们真的不知道您调用的 sa_sigaction 的特定实现的目的,即单一责任。
不过,如果我不得不猜测的话,我希望 sa_sigaction 实现是一个接口模块的一部分,该接口模块在较低的顶部实现 POSIX API -level OS 特定功能,sa_sigaction 函数的职责之一是实现 POSIX 规范的特定部分。
换句话说,它是一个适配器模式对象,并且具有单一职责。
也许您的意思是说 POSIX API 规范违反了 SRP...也许 但这并不重要。 SRP 用于使您的系统能够适应不断变化的需求。作为一个古老的 API 标准,POSIX 没有满足很多新要求。它本质上记录了过去的事情,历史事实不会改变。
does POSIX API violates SOLID principles?
是。 POSIX 已有数十年历史,由 许多 软件工程师在 IEEE 的支持下编写。 SOLID 相对较新(相比之下),是由一个名叫 Bob 的人编写的。
POSIX 更成熟,它背后的人意识到有简洁的小首字母缩略词(即 S.O.L.I.D。)不能解释软件工程中的所有小异常。
如果你问我,SOLID 就是违反了 POSIX。
恕我直言,我认为您的示例如履薄冰(它也忽略了 SOLID 中的 D)。
POSIX 可能违反了 SOLID 原则(也可能不违反)......但另一方面,POSIX 对什么可以分开,什么属于一起有成熟的理解(来自实际使用的理解)。
换句话说,问题是关于"what is a single responsibility?"的范围,POSIX有几十年的经验帮助它划清界限。
在您的示例中,您声明 sigaction
必须实现这两种类型的东西,但这是一个谬论。
sigaction
有一个单一的职责——它需要注册一个回调。回调类型实际上是无关紧要的,因为责任在 "registering".
如果数组 push
函数是类型不可知的,它会违反 SRP 原则吗?不,它只处理一个职责——推送到数组。这里也一样。
如果我按照你的逻辑,为每个回调类型实现不同的函数,我会发现自己一遍又一遍地编写相同的代码,但有细微的变化——这违反了 DRY 原则,这是一个明显的迹象这些功能职责相同,应该统一。