必填项
我不能保证此处阐述的普遍接受的术语和原理的解释与上世纪下半叶加州教授在可靠的科学文章中提出的内容一致。 我不能保证我的解释完全被行业或学术界的大多数IT专业人员共享或共享。 我什至不能保证我的解释会在面试中对您有所帮助,尽管我认为它们会很有用。
但我保证,如果我的解释代替了对理解的缺乏,并开始应用它们,那么您编写的代码将更易于维护和修改。 我也非常了解,在评论中,我会写得很烂,这将使我能够纠正绝对明显的遗漏和不一致之处。
如此小的保证使人们对撰写本文的原因提出了疑问。 我认为,无论在哪里教授编程,都应该教这些东西,直到在学校深入学习它的计算机科学课程为止。 但是,对我来说,当我发现对话者是我的同事,并且已经工作了几年,但是关于封装“我在那儿听到了一些声音”时,这变成了令人恐惧的正常情况。 将所有这些收集在一处并在出现问题时提供链接的需求已经很长时间了。 然后我的“宠物项目”给了我很多思考的机会。
在这里,他们可能会反对我,现在在学校学习这些东西还为时过早,并且总的来说,OOP并没有把它们融合在一起。 首先,这取决于您的学习方式。 其次,本文中70%的材料不仅适用于OOP。 我将分别注意。

简而言之OOP
对我来说,这可能是最困难的部分。 但是,您仍然需要建立基础并简要描述OOP的本质,以了解封装,多态性,继承和SOLID原理为何增强了OOP。 我将通过谈论您如何想到这样的事情来做到这一点。
首先是Dijkstra,他证明了可以用三种方式表示任何算法来选择以下命令:线性执行(按顺序),按条件分支,在满足条件时循环执行。 使用这三个连接,您可以构造任何算法。 此外,建议编写程序,将程序限制在一个接一个的线性排列中,即分支和循环。 这被称为“ 过程结构编程”(感谢sshikov的澄清)。
同样在这里,我们注意到命令序列必须组合成子程序,并且每个子程序可以使用一个命令执行。
除了动作的顺序,对我们来说重要的是要执行的动作。 它们对已习惯存储在变量中的数据执行。 变量存储数据。 它们根据其类型进行解释。 显然是要打磨牙齿,但请耐心一点。
从一开始,就形成了或多或少的通用原始数据类型集。 整数,实数,布尔变量,数组,字符串。 正如尼克劳斯·沃思遗赠的算法+数据结构=程序。
同样,从一开始就以不同的形式出现了诸如子程序之类的数据类型。 或一段代码(如果需要)。 有人可能会说使用子程序作为变量是功能编程的特权。 即使这样,在汇编器中也可以编写一段可变代码。 让这种可能性降低为“好吧,这是此子例程所在的RAM中的字节数,然后将调用堆栈插入牙齿并尽可能旋转以执行CALL命令。”
当然,很少有几种类型的数据,人们开始考虑为各种PL添加创建自己的类型的功能。 此功能的一种变体是所谓的录音。 以下是使用不存在的编程语言(以下称为NEPL-不存在的编程语言)进行录制的两个示例:
type Name: record consisting of FirstName: String, MiddleName: String, LastName: String. type Point: record consisting of X: Double, Y: Double.
也就是说,您无需将它们拖到两个或三个相关的变量中,而是将它们分组为一个具有命名字段的结构。 然后,声明一个类型为Name的变量,并引用FirstName字段。
对于我们的主题,在此“增强型”变量中有什么价值? 从这里到OOP仅一步之遥。 我不仅突出显示了一个粗体段落,它还指示代码段也可以放在变量中。 查看变量如何变成对象:
type Name: class consisting of FirstName: String, MiddleName: String, LastName: String, GetFullName: subprogram with no parameters returns String. type Point: class consisting of X: Double, Y: Double, ScalarMultiply: subprogram with (Double) parameters returns Point.
NB NEPL正在积极开发中,并且已经用class代替了record关键字。
也就是说,我们可以访问“ GetFullName”字段并调用它 。 变量不仅包含描述其状态的数据,而且还包含行为。 因此,变量变成具有一定技能和状态的对象。 而且我们已经不仅在处理变量,而且还在与可以接受命令的小型系统一起工作。
在我年轻的时候,这个想法让我着迷。 试想, 您可以创建任何类型的数据 。 您不是在处理一些数字,而是在与您所创造的世界的对象一起工作。 不会因无聊的数组或复杂的数字集而受折磨。 我们直接与“玩家”,“敌人”,“子弹”,“老板”类型的对象合作! 是的,在我年轻的时候就想做电子游戏。
实际上,事实并非如此简单。 没有一些“强化”的想法,OOP将使程序员的生活陷入困境。 但是在继续之前,让我们再说几句:
- 因其在OOP中的行为而得到“加强”的数据类型称为类 。
- 这些类型的变量称为对象 。
- 定义对象行为的例程称为方法 。 通常,每个类都有自己的一组方法,而不是每个对象。 这样一来,某个类的每个对象的行为就类似于同一类的其他对象。 我将很高兴从有关语言的注释中得知不同之处。
三位一体
从历史上看,他们在面试中询问这些事情。 它们是在任何OOP语言教科书中写的。 怎么了 因为如果您在不考虑封装和多态性的情况下设计OOP程序,那么您将获得“棺材,棺材,墓地,无人陪伴”。 继承不是绝对必要的,但是此概念使您可以更好地理解OOP,并且它是使用OOP设计的主要工具之一。
封装形式
好吧,让我们从Wikipedia的定义开始:“将数据和功能打包到单个组件中”。 该定义似乎很明确,但同时也过于笼统。 因此,让我们讨论一下为什么这是完全必要的,它将为我们带来什么,以及如何将数据和函数打包到单个组件中。
我已经写了一篇有关封装的文章。 我受到了这样的事实的责备:我将封装简化为隐藏信息,而这是有些不同的事情。 特别是, EngineerSpock产生了一种优雅的表述,如不变保护 。 我承认自己的错误,然后我将解释为什么会犯错。
同时,我的是封装原理的初步定义,或者,如果需要的话,它也描述了封装的过程,它不仅描述了封装原理,而且还描述了它应该达到的目的:
处于非平凡状态的任何软件实体都应变成封闭的系统,该系统只能从一种正确的状态转移到另一种正确的状态。
关于“具有非平凡状态的任何软件实体”的部分,让我们稍等一下。 现在,我们将只讨论对象。 关于我定义的第二部分。 我们为什么需要这个?
这里的一切都很简单:只能从一种正确状态转移到另一种正确状态的状态不能被破坏。 也就是说,我们需要确保没有任何物体可以损坏。 听起来,有些雄心勃勃。 如何实现呢?
假设零,与对象相关的所有事物都必须位于同一架构边界内的一个位置。 如果结果非常深刻,我将重复Wikipedia的定义:“将数据和功能打包到单个组件中”。
首先,要明确区分接口及其实现。 我认为我的所有同事都熟悉缩写API 。 因此,每个对象都应该有自己的API或PI(如果我们要谨慎的话)。 他们为之创建的东西,以及其他人将使用的东西,它们将导致什么。 应该是什么样? 因此,甚至没有人会想到进入一个对象并不合适地使用它。 但仅此而已。
,在一本书中,我不记得是哪本书,这是用微波炉的例子来解释的。 上面有按钮。 钢笔 它们可以让您加热食物。 您无需解开微波炉,在这里焊接一些东西即可加热昨天的汤。 你有一个界面,按钮。 放盘子,按几个按钮,等待一分钟,然后开心。
只需考虑对象的用户需要按下哪些按钮,然后将其与内部小物件分离即可。 而且在任何情况下都不要添加额外的按钮! 那是第一个。
其次, 尊重接口和实现之间的界限,并让其他人尊重它。 原则上,这种想法是直觉的,并以多种形式徘徊在民间智慧中。 至少要说“如果您利用了一些没有记录的东西,然后又有东西对您造成了破坏,您应该对此负责。” 我认为,“只有在微波以您需要的方式工作之前,才旋转微波炉”,一切都显而易见。 现在介绍如何使他人尊重臭名昭著的边界。
这正是信息的隐秘之处。 是的,您总是可以同意,询问,设置代码约定,并指出代码审查是不可能的。 但是,超越这一边界的可能性仍然存在。 这是救援的隐瞒信息。
如果我们的代码无法了解其存在及其背后的原因,我们就无法越过臭名昭著的边界。 即使他发现了,编译器也会假装没有这样的字段或方法,即使有,也没有必要去碰它,我拒绝编译,通常来说你是谁,我们没有打电话给你,而是使用了接口部分。

这是您喜欢的语言在各种不同的公共,私有和其他访问修饰符中起作用的地方。 非常“信息隐藏”是使封装的好处不断减少的最可靠方法。 无论如何,如果代码使用了所需的内容和所需的位置,则将与一个类相关的所有内容组合在一个地方是没有意义的。 但是,由于隐瞒了信息,原则上不应再出现这种情况。 而且这种方法是如此可靠,以至于成千上万的程序员(包括我在内,已经在我心中)头脑中封装和隐藏信息之间的差异得以某种程度的消除。
如果您最喜欢的YP不允许您隐藏信息怎么办? 关于这个主题,您可以很有趣地谈论评论。 我看到了下一个出路。 升序:
- 仅记录接口部分,并考虑未记录为实现的所有内容。
- 通过代码约定将实现与接口分开(示例-在python中,有__all__变量指示当您要求导入所有内容时将从模块中导入什么)。
- 使这些非常严格的代码约定足够严格,以便可以对其进行自动检查,然后,对它们的任何违反都将等同于编译错误和版本下降。
再过一次:
- 与一类相关的所有内容都打包到一个模块中。
- 在类之间,绘制了严格的体系结构边界。
- 在任何类中,接口部分都与该接口部分本身的实现分开。
- 班级之间的界限必须得到尊重,并必须尊重他人!
我将以NEPL的示例结尾,该示例仍在非常积极地开发中,经过十段,已经获得了访问修饰符:
type Microwave: class consisting of private fancyInnerChips: List of Chip, private foodWarmingThing: FoodWarmerController, private buttonsPanel: ButtonsPanel, public GetAccessToControlPanel: subprogram with no parameters returns ButtonsPanel, public OpenDoor: subprogram with no parameters returns nothing, public Put: subprogram with (Food) parameters return nothing, public CloseDoor: subprogram with no parameters returns nothing. type ButtonsPanel: class consisting of private buttons: List of ButtonState, public PressOn: subprogram with no parameters returns nothing, public PressOff: subprogram with no parameters returns nothing, public PressIncreaseTime: subprogram with no parameters returns nothing, public PressDecreaseTime: subprogram with no parameters returns nothing, public PressStart: subprogram with no parameters returns nothing, public PressStop: subprogram with no parameters returns nothing.
我希望代码能清楚说明示例的全部内容。 我只澄清一点:GetAccessToControlPanel检查我们是否可以触摸微波炉。 如果她坏了怎么办? 然后,您将无法单击任何内容。 您只会收到一条错误消息。
好吧,ButtonsPanel已经成为一个单独的类这一事实使我们平稳地面临一个重要问题:维基百科上封装定义的“单个组件”是什么? 类之间的界限在哪里,应该在哪里? 我们一定会在稍后再讨论这个问题。
在OOP之外使用
如此多的程序员已经从Java / C ++ / C#教程中学到了关于封装的知识,也可以用您的第一种OOP语言来代替。 因此,封装在意识中与OOP有某种联系。 但是,让我们回到封装的两个定义。
将数据和功能打包到单个组件中。
必须将具有非平凡状态的任何软件实体转换为封闭系统,该封闭系统只能从一种正确的状态转移到另一种正确的状态。
你注意到了吗? 类和对象一无所有!
举个例子。 您是DBA 。 您的工作是关注某种关系数据库。 例如,在MySQL上。 您的宝贵数据库使用了几个程序。 您无法控制其中一些。 怎么办
创建一组存储过程。 我们将它们组合成一个电路,我们将其称为接口。 我们为程序创建了一个用户,没有任何权利。 这是CREATE USER命令。 然后,使用GRANT命令,仅授予用户从接口架构执行这些存储过程的权限。
仅此而已。 我们有一个数据库,它是具有非平凡状态的软件实体,很容易被破坏。 为了避免破坏它,我们从存储过程创建了一个接口。 而且,在使用MySQL本身的方法之后,我们进行了制作,以便第三方实体只能使用此接口。
请注意,臭名昭著的封装以及它的描述方式已被充分利用。 但是数据和对象的关系表示之间存在如此大的差距,必须使用庞大的ORM框架来弥补它。
这就是为什么类和对象没有出现在封装的定义中的原因。 这个想法比OOP广泛得多。 仅在有关OOP语言的教科书中讲它会带来太多好处。
多态性
多态有许多形式和定义。 当我打开Wikipedia时,Kondratius足以满足我。 在这里,我将讨论Straustrup提出的多态性: 一个接口-许多实现 。
通过这种形式,多态性的想法可以极大地加强作家的封装意识。 毕竟,如果我们从实现中分离出接口,那么使用该接口的人就不必知道实现中发生了某些变化。 那些使用接口(理想情况下)的人甚至不需要知道实现已经发生了改变! 这为扩展和修改开辟了无限的可能性。 您的前任是否确定最好用军用雷达加热食物? 如果这个疯狂的天才将接口从实现中分离出来并明确地形式化,那么军用雷达可以适应其他需求,并且可以使用微波炉来实现其加热食物的接口。
NEPL正在迅速发展,并且在C#的影响下,获取(小心谨慎,不要措辞生疏)接口的数据类型。
type FoodWarmer: interface consisting of GetAccessToControlPanel: no parameters returns FoodWarmerControlPanel, OpenDoor: no parameters returns nothing, Put: have (Food) parameters returns nothing, CloseDoor: no parameters returns nothing. type FoodWarmerControlPanel: interface consisting of PressOn: no parameters returns nothing, PressOff: no parameters returns nothing, PressIncreaseTime: no parameters returns nothing, PressDecreaseTime: no parameters returns nothing, PressStart: no parameters returns nothing, PressStop: no parameters returns nothing. type EnemyFinder: interface consisting of FindEnemies: no parameters returns List of Enemy. type Radar: class implementing FoodWarmer, EnemyFinder and consisting of private secretMilitaryChips: List of Chip, private giantMicrowavesGenerator: FoodWarmerController, private strangeControlPanel: AlarmClock, public GetAccessToControlPanel: subprogram with no parameters returns FoodWarmerControlPanel, public OpenDoor: subprogram with no parameters returns nothing, public Put: subprogram with (Food) parameters return nothing, public CloseDoor: subprogram with no parameters returns nothing, public FindEnemies: subprogram with no parameters returns List of Enemy. type AlarmClock: class implementing FoodWarmerControlPanel and consisting of private mechanics: List of MechanicPart, public PressOn: subprogram with no parameters returns nothing, public PressOff: subprogram with no parameters returns nothing, public PressIncreaseTime: subprogram with no parameters returns nothing, public PressDecreaseTime: subprogram with no parameters returns nothing, public PressStart: subprogram with no parameters returns nothing, public PressStop: subprogram with no parameters returns nothing. type Microwave: class implementing FoodWarmer and consisting of private fancyInnerChips: List of Chip, private foodWarmingThing: FoodWarmerController, private buttonsPanel: ButtonsPanel, public GetAccessToControlPanel: subprogram with no parameters returns FoodWarmerControlPanel, public OpenDoor: subprogram with no parameters returns nothing, public Put: subprogram with (Food) parameters return nothing, public CloseDoor: subprogram with no parameters returns nothing. type ButtonsPanel: class implementing FoodWarmerControlPanel and consisting of private buttons: List of ButtonState, public PressOn: subprogram with no parameters returns nothing, public PressOff: subprogram with no parameters returns nothing, public PressIncreaseTime: subprogram with no parameters returns nothing, public PressDecreaseTime: subprogram with no parameters returns nothing, public PressStart: subprogram with no parameters returns nothing, public PressStop: subprogram with no parameters returns nothing.
因此,如果将一个类声明为实现接口,则它必须实现该接口的所有方法。 否则,编译器会告诉我们“ fi”。 我们有两个接口:FoodWarmer和FoodWarmerControlPanel。 仔细查看它们,然后让我们分析实现。
作为苏联困难时期的遗产,我们收到了两用雷达,可以用来加热食物并找到敌人。 由于已超出计划,因此需要使用警报来代替控制面板,并且需要将警报放置在某个地方。 但是,幸运的是,他们推崇的化学,肥料和毒药研究所的未命名MNS实现了雷达的FoodWarmer接口和闹钟的FoodWarmerControlPanel接口。
一代人之后,有人想到最好用微波炉加热食物,最好用按钮控制微波炉。 现在创建了Microwave和ButtonsPanel类。 它们实现相同的接口。 FoodWarmer和FoodWarmerControl。 这给了我们什么?
如果在代码中到处都使用了诸如FoodWarmer之类的变量来加热食物,那么我们可以简单地将实现替换为更现代的实现,而没人会注意到。 也就是说,使用该接口的代码并不关心实现细节。 或事实已经完全改变了。 我们甚至可以使FoodWarmerFactory类根据您的应用程序的配置来生成不同的FoodWarmer实现。
还要查看“微波”和“雷达”类中的封闭字段。 那里我们有一个闹钟和一个带按钮的面板。 但是在外面,我们给出了FoodWarmerControlPanel类型的变量。
在Picabu的某个地方,有一个故事讲述某个候选人如何解释多态性的原理,如下所示:
我在这里有一支笔。 我可以给她写我的名字,但可以留在你的眼里。 这就是多态性的原理。
画面很有趣,情况很糟,对多态性原理的解释毫无用处。
多态性的原理不是让有些恐惧的笔类同时实现文具和冷钢的界面。 多态性的原理是,所有可能被刺破的事物都可能卡在眼中。 因为它会被刺破。 结果将有所不同,但理想情况下应放弃视觉剥夺。 多态方法可以使您在为自己的世界构建的模型中反映这一事实。
在OOP之外使用
这些词在所有意义上都有一种如此有趣的语言,例如Erlang。 它具有行为特征。 注意你的手:
那里的代码分为模块。 您可以将模块名称用作变量。 也就是说,您可以像这样从模块编写函数调用:
为了确保模块具有某些功能,该语言具有行为功能。 在使用其他模块的模块中,您可以使用behaviour_info声明定义变量模块的要求。 然后,通过行为声明,设置了behaviour_info的父亲模块将使用的模块告诉编译器:“我们承诺实现此行为,以便父亲模块可以使用我们。”
例如,gen_server模块允许您创建一个服务器,该服务器在一个单独的进程中同步或异步(Erlang中没有线程,只有数千个小型并行进程),可以执行其他进程的请求。 并且在gen_server中,收集了与其他进程的请求相关的所有逻辑。 但是,这些请求的直接处理是由实现gen_server行为的人员完成的。 尽管其他模块可以正确实现它(即使有空存根),但gen_server甚至都不关心如何处理这些请求。 此外,处理模块可以随时更换。
一个界面-许多实现。 正如斯特拉斯特鲁普遗赠给我们一样。 如关于OOP的智能书中所述。 现在从维基百科到录音室的报价:
Erlang — , .
« — » , , .
. .NET. . CLR . CLR Microsoft , , , ( ECMA-335).
.NET , Windows, Windows Phone, XBox ( XNA, , ), . Microsoft. , , . , Mono Project. .NET. .
, . Microsoft , .NET . . , , .NET Core. , .NET Core .NET Framework, , , . , .
, « — » - . , .
, . , , , . , .
, , . , , NEPL. . Name? , . EtiquetteInfo - .
import class EtiquetteInfo from Diplomacy. type PoliteName: class consisting of private FirstName: String, private MiddleName: String, private LastName: String, for descendants GetPoliteFirstName: subprogram with (EtiquetteInfo) parameters returns String, for descendants GetPoliteMiddleName: subprogram with (EtiquetteInfo) parameters returns String, for descendants GetPoliteLastName: subprogram with (EtiquetteInfo) parameters returns String, public GetFullName: subprogram with (EtiquetteInfo) parameters returns String. subprogram GetPoliteFirstName.PoliteName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as return _EtiquetteInfo.PoliteFirstName(FirstName). subprogram GetPoliteMiddleName.PoliteName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as return _EtiquetteInfo.PoliteMiddleName(MiddleName). subprogram GetPoliteLastName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as return _EtiquetteInfo.PoliteLastName(LastName). subprogram GetFullName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as return GetPoliteFirstName(_EtiquetteInfo) + GetPoliteMiddleName(_EtiquetteInfo) + GetPoliteLastName(_EtiquetteInfo).
, GetFullName - , ( , , ?). , , - . , , . , , , , . , . PoliteName . ExoticPoliteName — . , , .
- . ExoticPoliteName, PoliteName, . PoliteExoticName. , PoliteName.
import class EtiquetteInfo from Diplomacy. type PoliteExoticName: class extending PoliteName and consisting of private MoreMiddleNames: List of String, for descendants overridden GetPoliteMiddleName: subprogram with (EtiquetteInfo) parameters returns String, public overriden GetFullName: subprogram with (EtiquetteInfo) parameters returns String. subprogram GetPoliteMiddleName.PoliteExoticName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as String AggregatedMiddleName = String.Join(" ", MoreMiddleNames), return base.GetPoliteMiddleName(_EtiquetteInfo + AggregatedMiddleName). subprogram GetFullName with (EtiquetteInfo _EtiquetteInfo) parameters returning String implemented as String Prefix = "", String FirstName = GetFirstName(_EtiquetteInfo), if _EtiquetteInfo.ComplimentIsAppropriate(FirstName) then Prefix = "Oh, joy of my heart, dear ", return Prefix + base.GetFullName(_EtiquetteInfo).
: PoliteName . PoliteExoticName -.
, , . , GetPoliteFirstName GetPoliteLastName. . GetFullName, , .
, , PoliteName, PoliteExoticName, GetFullName. , PoliteName, , . , , base.GetFullName(etiquetteInfo). , , .
, " ". , . : , . . .
, . . , Boolean, , . , Object. . , , , , Object, .
, NEPL . PoliteName Object, PoliteExoticName PoliteName Object . , NEPL :
subprogram Foo.Bar with no parameters returning nothing implemented as PoliteExoticName _PoliteExoticName = GetSomePoliteExoticName(), PoliteName _PoliteName = _PoliteExoticName, Object _Object = _PoliteExoticName.
, , _Object.GetFullName, , . PoliteName PoliteExoticName - Object, - _Object, .
? , . . , ( Object) , - -.
, , , , . ? , . - , . . - , .
? , . . . , «» , . ?
. , NEPL for descendants.
type PoliteName: class consisting of private FirstName: String, private MiddleName: String, private LastName: String, for descendants GetPoliteFirstName: subprogram with (EtiquetteInfo) parameters returns String, for descendants GetPoliteMiddleName: subprogram with (EtiquetteInfo) parameters returns String, for descendants GetPoliteLastName: subprogram with (EtiquetteInfo) parameters returns String, public GetFullName: subprogram with (EtiquetteInfo) parameters returns String.
PoliteExoticName FirstName, «, , , , ». GetPoliteFirstName FirstName.

, , Square Shape, Shape Square . , . Shape , , . Square, Shape. 怎么了 , Shape, .
. , ? -, . -, , , , . , , .
, . , . « »? , . . , .
. , . , , . . , . , , .
, , . . ( , ), , . , , . , , . .
, ) , ) , , , 999 1000 . , , .
()
, . - , . , , . - , .
SOLID
— , , . - . SOLID — , , … ? ? , , .
S — The Single Responsibility Principle
. .
.
. . .
, « » - . . « ?». , , ? .
, SRP :
.
, ? — , . ? . « ». , . ? .
, ? . , .txt-. , , , .txt-. - , . , , … .txt-. 怎么了 . , , .txt-.
NB ( , ) «», « , ».

. , , , .txt-. . , . , . 但是! -, , , . -, , , .

, , . , ) , ) .html-. , , .txt/.html.
, , , . , , .txt-. 可能出什么问题了?
- . , . , , . , , , , , , . .
- , . 900 USD 900.00$? 20190826T130000 2019 ? , ?
- .txt-? .csv? , .txt. ? ? - ? - ? , ?
? — . , -.
, , , . , .
DRY — Don't Repeat Yourself
:
, . .
, , , - , . , , .
SRP . , , . , « ». , , , — .
. HTML . , «» . , HTML 90- . , . - , . , HTML- . CSS .
? -, CSS , «» . , . -, CSS- html- , - text-color . — . .
O — The Open/Closed Principle
, , , - . , «» «». / , , . « » . :
.
. , . , . , — .
, . . ? . , .
- , . , . , / .
- , . , . / /, . NB /. , : .
- , . , .
- , - , , . (), () «» .
- . , , ? , . , . , .
, . .
type SpellChecker: class consisting of public DoSpellCheck: subprogram with (String) parameters returns String. type CorporativeStyleChecker: class consisting of public DoCorporativeStyleCheck: subprogram with (String) parameters returns String. type TextProcessor: class consisting of private Text: String, private SpellChecker: SpellChecker, private CorporativeStyleChecker: CorporativeStyleChecker, public Process: subprogram with no parameters returns String. subprogram TextProcessor.Process with no parameters returning String implemented as String ProcessedText = Text, ProcessedText = SpellChecker.DoSpellCheck(ProcessedText), ProcessedText = CorporativeStyleChecker.DoCorporativeStyleCheck(ProcessedText), return ProcessedText.
,
type TextChecker: interface consisting of Check: have (String) parameters returns String. type SpellChecker: class implementing TextChecker and consisting of public Check: subprogram with (String) parameters returns String. type CorporativeStyleChecker: class implementing TextChecker and consisting of public Check: subprogram with (String) parameters returns String. type TextProcessor: class consisting of private Text: String, private SpellChecker: SpellChecker, private CorporativeStyleChecker: CorporativeStyleChecker, public Process: subprogram with no parameters returns String. subprogram TextProcessor.Process with no parameters returning String implemented as String ProcessedText = Text, List of SpellChecker Checkers = (SpellChecker, CorporativeStyleChecker), for each SpellChecker SpellChecker in Checkers do ProcessedText = SpellChecker.Check(ProcessedText) and nothing else, return ProcessedText.
O/CP . TextCheckersSupplier, .
type TextChecker: interface consisting of Check: have (String) parameters returns String. type SpellChecker: class implementing TextChecker and consisting of public Check: subprogram with (String) parameters returns String. type CorporativeStyleChecker: class implementing TextChecker and consisting of public Check: subprogram with (String) parameters returns String. type TextCheckersSupplier: class consisting of public GetCheckers: subprogram with no parameters returns List of TextChecker. type TextProcessor: class consisting of private Text: String, private CheckersSupplier: TextCheckersSupplier, public Process: subprogram with no parameters returns String. subprogram TextProcessor.Process with no parameters returning String implemented as String ProcessedText = Text, List of SpellChecker Checkers = CheckersSupplier.GetCheckers(), for each SpellChecker SpellChecker in Checkers do ProcessedText = SpellChecker.Check(ProcessedText) and nothing else, return ProcessedText.
? , , , . , TextProcessor. , TextCheckerSupplier , , . TextChecker' . , , , . , .
, , , , . .
L — The Liskov Substitute Principle
, :
, , , .
, , . ?
- NEPL:
type PoliteExoticName: class extending PoliteName and consisting of... subprogram Foo.Bar with no parameters returning nothing implemented as PoliteExoticName _PoliteExoticName = GetSomePoliteExoticName(), PoliteName _PoliteName = _PoliteExoticName, Object _Object = _PoliteExoticName.
, _PoliteName - . , , . , . PoliteName, . , , , PoliteName . , , , . .
, -, allex ( , ). , , :
-, .
, «Agile Principles, Patterns and Practices in C#». NEPL, .
Object _Object = GetObjectSomewhere(), PoliteExoticName IHopeItsActuallyName = _Object as PoliteExoticName,
, , . . , . - , . , . . ( , alias , ):
from UnboundedCollections import UnboundedSet as ThirdPartyUnboundedSet. from BoundedCollections import BoundedSet as ThirdPartBoundedSet. type Set: interface consisting of Add: have (Object) parameters returns nothing, Delete: have (Object) parameters returns nothing, IsMember: have (Object) parameters returns Boolean. type UnboundedSet: class implementing Set and consisting of private ThirdPartySet: ThirdPartyUnboundedSet, public Add: subprogram with (Object) parameters returning nothing, public Delete: subprogram with (Object) parameters returning nothing, public IsMember: subprogram with (Object) parameters returning Boolean. type BoundedSet: class implementing Set and consisting of private ThirdPartySet: ThirdPartyBoundedSet, public Add: subprogram with (Object) parameters returning nothing, public Delete: subprogram with (Object) parameters returning nothing, public IsMember: subprogram with (Object) parameters returning Boolean. subprogram BoundedSet.Add with (Object O) parameters returning nothing implemented as ThirdPartSet.Add(O).

. . . PersistentSet, - . , PersistentObject. - . Delete IsMember . Add...
from PersistentCollections import PersistentSet as ThirdPartyPersistentSet, PersistentObject. type PersistentSet: class implementing Set and consisting of private ThirdPartySet: ThirdPartyPersistentSet, public Add: subprogram with (Object) parameters returning nothing, public Delete: subprogram with (Object) parameters returning nothing, public IsMember: subprogram with (Object) parameters returning Boolean. subprogram PersistentSet.Add with (Object O) parameters returning nothing implemented as PersistentObject Po = O as PersistentObject, ThirdPartySet.Add(Po).

. PersistentSet Object, . , , Set , . ( ):
type MemberContainer: interface consisting of Delete: have (Object) parameters returns nothing, IsMember: have (Object) parameters returns Boolean. type Set: interface extending MemberContainer and consisting of Add: have (Object) parameters returns nothing. type PersistentSet: interface extending MemberContainer and consisting of Add: have (PersistingObject) parameters returns nothing.

C#.
, NEPLNEPL. List of String. , .
type List: class generalized with (T) parameters consisting of
Set PersistentSet.
from UnboundedCollections import UnboundedSet as ThirdPartyUnboundedSet. from BoundedCollections import BoundedSet as ThirdPartBoundedSet. from PersistentCollections import PersistentSet as ThirdPartyPersistentSet, PersistentObject. type Set: interface generalized with (T) parameters consisting of Add: have (T) parameters returns nothing, Delete: have (T) parameters returns nothing, IsMember: have (T) parameters returns Boolean. type UnboundedSet: class implementing Set of Object and consisting of private ThirdPartySet: ThirdPartyUnboundedSet, public Add: subprogram with (Object) parameters returning nothing, public Delete: subprogram with (Object) parameters returning nothing, public IsMember: subprogram with (Object) parameters returning Boolean. type BoundedSet: class implementing Set of Object and consisting of private ThirdPartySet: ThirdPartyBoundedSet, public Add: subprogram with (Object) parameters returning nothing, public Delete: subprogram with (Object) parameters returning nothing, public IsMember: subprogram with (Object) parameters returning Boolean. type PersistentSet: class implementing Set of PersistentObject and consisting of private ThirdPartySet: ThirdPartyPersistentSet, public Add: subprogram with (PersistentObject) parameters returning nothing, public Delete: subprogram with (PersistentObject) parameters returning nothing, public IsMember: subprogram with (PersistentObject) parameters returning Boolean.
()
. , , «» . , « — » . , . .
I — The Interface Segregation Principle
, . . .
, ? , - . , , SQL? , . , API . API , «interface», , . . 可能出什么问题了?
, , - , DBA . , 100500 , . . , .
, , , «» . , « interface, ». DBA . GDPR, HIPAA , .
- . , . 依此类推。
? , . :
, ( ).
? interface «interface_billing», «interface_customer_data» . .
, , . pet-project. IActor. , . , IActor : ICollidable, IDisplayble, IUpdatable. ?

( , Camera), . , - . , . , , IDisplayble SpecEffect.
CollisionsController , - ICollidable. , , , SOLID . TileWall -, . CollisionsController . , , IActor , .

: , , .
D — The Dependency Inversion
-. , . , , . , , . , , , , - . , , - . , , - .
“这! .» — - ImportantClass. , , . , ImportantClass VeryImportantClass, , , EvenMoreImportantClass, , . , , , . , . , .

ImportantClass VeryImportantClass EvenMoreImportantClass. ImportantClass . , , . , IVeryImportantClass IEvenMoreImportantClass, ImportantClass.
ImportantClass VeryImportantClass . ImportantClass « », IVeryImportantClass .

. , , .
. .
. .
, «» «» - . , , . . , , . , . , -.
. , .
- , . ( MegaSender), . , , SOAP API.
-. SenderAccess. , MegaSender SenderAccess . SenderAccess MegaSender, , MegaSender, MegaSender , Apple i.
MegaSender. LightSender. , SenderAccess c LightSender. , , . , .
SenderAccess, , MegaSender . , SenderAccess MegaSender. MegaSender « ». , MegaSender, , , . . , LightSender , , LightSender, MegaSender.
, SenderAccess , SenderAccess LightSender . .
, IActor ICollidable, IUpdatable, IDisplayble. , IActor . Actor Player, Enemy, Door, Wall . , .
Blueprint. . , , , , , et cetera. , , , .
, , C#, . , - List<String>. , List<T> List<String>. Actor Actor<TBlueprint>.
, , - . Actor<EnemyBlueprint> Actor<DoorBlueprint> , . , .
- . , , . , . , . , IActor, , ActorsFactory .
. : .
, , . - , . () :
. . . TCP/HTTP/SMPP/SOAP, . ? , TCP/HTTP/SMPP/SOAP- TCP/HTTP/SMPP/SOAP- , . , - . ? 想一想。 , « » « 1000 ».
. ? - SOLID'? , . , - , .
- , .
- , .
. , -, , . . - , , , , -. , .
. - , :
KISS — . . . , , . , , .
, , Actor . , — , - . , .
YAGNI — . - , , « », , - . , . « » - . , , . , , .
, OC/P . 50 . , , -. 50 , . , - .
? , , « », . « » , .
, SOLID . , .
, . , -, , . , .
- «Code Complete» . , « » - .
- «Clean Code» . «Clean Architecture».
- «Agile Principles, Patterns and Practices in C#» . SOLID . , language-agnostic.
聚苯乙烯
, . , , . : ! , , language-agnostic .
, language-agnostic. NEPL, : , , , . , , .
, . , , . :
, , , . , , . , . : , .