OOP 的实际用途
我最近与一位不喜欢 OOP 的同事进行了一场辩论。引起我注意的是他所说的:
“在对象中进行编码有什么意义?如果是重用,那么我可以创建一个库并调用手头任何任务所需的任何函数。我需要这些多态性概念吗?” 、继承、接口、模式或者其他什么?”
我们是一家小公司,为电子商务网站和房地产开发小型项目。
如何在“日常、现实世界”设置中利用 OOP?或者 OOP 真的是为了解决复杂的问题而不是为了“日常”开发吗?
I recently had a debate with a colleague who is not a fan of OOP. What took my attention was what he said:
"What's the point of doing my coding in objects? If it's reuse then I can just create a library and call whatever functions I need for whatever task is at hand. Do I need these concepts of polymorphism, inheritance, interfaces, patterns or whatever?"
We are in a small company developing small projects for e-commerce sites and real estate.
How can I take advantage of OOP in an "everyday, real-world" setup? Or was OOP really meant to solve complex problems and not intended for "everyday" development?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
我个人的观点:上下文
当您使用面向对象编程时,您会对上下文有更深入的了解。它可以帮助您以更容易理解的方式组织代码,因为现实世界也是面向对象的。
My personally view: context
When you program in OOP you have a greater awareness of the context. It helps you to organize the code in such a way that it is easier to understand because the real world is also object oriented.
OOP 的优点在于将一组数据与一组行为联系起来。
因此,如果您需要对一组相关数据执行许多相关操作,您可以编写许多对结构进行操作的函数,也可以使用对象。
对象以继承的形式为您提供一些代码重用帮助。
IME,使用具有一组已知属性和方法的对象更容易,因为它保留一组复杂的结构和对其进行操作的函数。
有些人会继续讲继承和多态。这些都很有价值,但 OOP 的真正价值(在我看来)来自于它封装数据并将数据与行为关联起来的良好方式。
你应该在你的项目中使用 OOP 吗?这取决于您的语言对 OOP 的支持程度。这取决于您需要解决的问题类型。
但是,如果您正在做小型网站,那么您仍然在谈论足够的复杂性,以至于在开发语言的适当支持下我会使用 OOP 设计。
The good things about OOP come from tying a set of data to a set of behaviors.
So, if you need to do many related operations on a related set of data, you can write many functions that operate on a struct, or you can use an object.
Objects give you some code reuse help in the form of inheritance.
IME, it is easier to work with an object with a known set of attributes and methods that it is to keep a set of complex structs and the functions that operate on them.
Some people will go on about inheritance and polymorphism. These are valuable, but the real value in OOP (in my opinion) comes from the nice way it encapsulates and associates data with behaviors.
Should you use OOP on your projects? That depends on how well your language supports OOP. That depends on the types of problems you need to solve.
But, if you are doing small websites, you are still talking about enough complexity that I would use OOP design given proper support in the development language.
您朋友的观点是,设计良好的 OO 设计不仅仅是让某些东西正常工作,它更容易理解、遵循、扩展、扩展和实现。例如,委派绝对相似的工作或保存应该放在一起的数据(是的,甚至 C 结构体也是一个对象)要容易得多。
More than getting something to just work - your friend's point, a well designed OO design is easier to understand, to follow, to expand, to extend and to implement. It is so much easier for example to delegate work that categorically are similar or to hold data that should stay together (yes even a C struct is an object).
好吧,我相信很多人会给出更多学术上正确的答案,但这是我对一些最有价值的优点的看法:
Well, I'm sure a lot of people will give a lot more academically correctly answers, but here's my take on a few of the most valuable advantages:
看看设计模式的使用,您就会看到 OOP 的实用性。它不仅仅涉及封装和重用,还涉及可扩展性和可维护性。正是接口让事物变得强大。
几个例子:
在没有对象的情况下实现流(装饰器模式)很困难
向现有系统添加新操作,例如新的加密类型如果没有对象,(策略模式)可能会很困难。
看看PostgresQL是怎样的
实施与你的方式
数据库书说数据库应该
实施后你会看到一个很大的
不同之处。本书会建议
每个运算符的节点对象。
Postgres 使用无数的表和
宏来尝试模拟这些节点。
它不太漂亮,而且很多
因此更难扩展。
这样的例子还在继续。
Look at the use of Design Patterns and you'll see the utility of OOP. It's not just about encapsulation and reuse, but extensibility and maintainability. It's the interfaces that make things powerful.
A few examples:
Implementing a stream (decorator pattern) without objects is difficult
Adding a new operation to an existing system such as a new encryption type (strategy pattern) can be difficult without objects.
Look at the way PostgresQL is
implemented versus the way your
database book says a database should
be implemented and you'll see a big
difference. The book will suggest
node objects for each operator.
Postgres uses myriad tables and
macros to try to emulate these nodes.
It is much less pretty and much
harder to extend because of that.
The list goes on.
大多数编程语言的强大之处在于它们提供的抽象。面向对象编程提供了一个非常强大的抽象系统,它允许您管理相关想法或操作之间的关系。
考虑计算任意且不断扩展的形状集合的面积的任务。任何程序员都可以快速编写圆形、正方形、三角形等面积的函数。并将它们存储在库中。当尝试编写一个识别和计算任意形状面积的程序时,就会遇到困难。每次添加一种新的形状(例如五边形)时,您都需要更新和扩展诸如
IF
或CASE
结构之类的结构,以允许您的程序识别新的形状从“函数库”中塑造并调用正确的区域例程。一段时间后,与这种方法相关的维护成本开始增加。对于面向对象的编程,很多都是免费的——只需定义一个包含区域方法的 Shape 类即可。那么在运行时处理什么具体形状并不重要,只需使每个几何图形成为一个继承自 Shape 的对象并调用area方法即可。面向对象范例处理这样的细节:此时此刻,通过用户输入,我们是否需要计算圆形、三角形、正方形、五边形或半分钟前刚刚添加的椭圆选项的面积。
如果您决定更改区域函数调用方式背后的接口怎么办?使用面向对象编程,您只需更新 Shape 类,更改就会自动传播到从该类继承的所有实体。对于非面向对象的系统,您将面临艰难地浏览“函数库”并更新每个单独的界面的任务。
总之,面向对象编程提供了一种强大的抽象形式,可以消除代码中的重复并简化扩展和维护,从而节省您的时间和精力。
The power of most programming languages is in the abstractions that they make available. Object Oriented programming provides a very powerful system of abstractions in the way it allows you to manage relationships between related ideas or actions.
Consider the task of calculating areas for an arbitrary and expanding collection of shapes. Any programmer can quickly write functions for the area of a circle, square, triangle, ect. and store them in a library. The difficulty comes when trying to write a program that identifies and calculates the area of an arbitrary shape. Each time you add a new kind of shape, say a pentagon, you would need to update and extend something like an
IF
orCASE
structure to allow your program to identify the new shape and call the correct area routine from your "library of functions". After a while, the maintenance costs associated with this approach begin to pile up.With object-oriented programming, a lot of this comes free-- just define a Shape class that contains an area method. Then it doesn't really matter what specific shape you're dealing with at run time, just make each geometrical figure an object that inherits from Shape and call the area method. The Object Oriented paradigm handles the details of whether at this moment in time, with this user input, do we need to calculate the area of a circle, triangle, square, pentagon or the ellipse option that was just added half a minute ago.
What if you decided to change the interface behind the way the area function was called? With Object Oriented programming you would just update the Shape class and the changes automagically propagate to all entities that inherit from that class. With a non Object Oriented system you would be facing the task of slogging through your "library of functions" and updating each individual interface.
In summary, Object Oriented programming provides a powerful form of abstraction that can save you time and effort by eliminating repetition in your code and streamlining extensions and maintenance.
1994 年左右,我试图同时理解 OOP 和 C++,但发现自己很沮丧,尽管我原则上可以理解 OOP 的价值是什么。我已经习惯了能够用其他语言(主要是 Basic、Assembly 和 Pascal 家族语言)来搞乱应用程序任何部分的状态,以至于我似乎为了某些学术抽象而放弃了生产力。不幸的是,我最初几次接触像 MFC 这样的面向对象框架使得破解变得更容易,但不一定提供太多启发。
只有通过结合持久性、接触处理对象的替代(非 C++)方法以及对 OO 代码的仔细分析,才能够比我开始使用的等效过程代码更连贯、更直观地阅读 OO 代码真正得到它。 15 年后,我经常对(对我来说)新发现的聪明而又令人印象深刻的简单的面向对象解决方案感到惊讶,我无法想象用过程方法可以如此巧妙地实现这些解决方案。
在过去的几年里,我一直在经历同样的一系列努力,试图理解函数式编程范例。用保罗·格雷厄姆的话来说,当你俯视权力连续体时,你会看到缺失的一切。当你查找功率连续体时,你看不到功率,你只会看到奇怪的东西。
我认为,为了致力于以不同的方式做某事,你必须 1) 看到某人显然通过更强大的构造变得更有生产力,2) 当你发现自己碰壁时,暂停怀疑。拥有一位对新范式的理解至少更进一步的导师可能会有所帮助。
除非你有勇气停止怀疑,否则如果你想让某人快速领会 OO 模型的价值,我认为你可能做得比要求某人花一周时间阅读关于 Rails 的《实用程序员》一书还要糟糕。不幸的是,它确实遗漏了很多关于魔法如何运作的细节,但它很好地介绍了面向对象抽象系统的强大功能。如果读完这本书后,你的同事由于某种原因仍然没有看到面向对象的价值,那么他/她可能是一个绝望的例子。但是,如果他们愿意花一点时间使用一种方法,这种方法具有强烈的固执己见的 OO 设计,并且可以使他们从 0 到 60 比用过程语言做同样的事情快得多,那么可能就有希望。我认为即使您的工作不涉及网络开发也是如此。
我不太确定提出“现实世界”是否会成为编写优秀应用程序的工作框架一样的卖点,因为事实证明,尤其是在 C# 和 Java 等静态类型语言中,对现实世界进行建模通常需要曲折的抽象。通过观察成千上万的人努力对像“形状”的几何抽象(形状、椭圆、圆形)这样表面上简单的东西进行建模,您可以看到对现实世界进行建模的难度的具体示例。
Around 1994 I was trying to make sense of OOP and C++ at the same time, and found myself frustrated, even though I could understand in principle what the value of OOP was. I was so used to being able to mess with the state of any part of the application from other languages (mostly Basic, Assembly, and Pascal-family languages) that it seemed like I was giving up productivity in favor of some academic abstraction. Unfortunately, my first few encounters with OO frameworks like MFC made it easier to hack, but didn't necessarily provide much in the way of enlightenment.
It was only through a combination of persistence, exposure to alternate (non-C++) ways of dealing with objects, and careful analysis of OO code that both 1) worked and 2) read more coherently and intuitively than the equivalent procedural code that I started to really get it. And 15 years later, I'm regularly surprised at new (to me) discoveries of clever, yet impressively simple OO solutions that I can't imagine doing as neatly in a procedural approach.
I've been going through the same set of struggles trying to make sense of the functional programming paradigm over the last couple of years. To paraphrase Paul Graham, when you're looking down the power continuum, you see everything that's missing. When you're looking up the power continuum, you don't see the power, you just see weirdness.
I think, in order to commit to doing something a different way, you have to 1) see someone obviously being more productive with more powerful constructs and 2) suspend disbelief when you find yourself hitting a wall. It probably helps to have a mentor who is at least a tiny bit further along in their understanding of the new paradigm, too.
Barring the gumption required to suspend disbelief, if you want someone to quickly grok the value of an OO model, I think you could do a lot worse than to ask someone to spend a week with the Pragmatic Programmers book on Rails. It unfortunately does leave out a lot of the details of how the magic works, but it's a pretty good introduction to the power of a system of OO abstractions. If, after working through that book, your colleague still doesn't see the value of OO for some reason, he/she may be a hopeless case. But if they're willing to spend a little time working with an approach that has a strongly opinionated OO design that works, and gets them from 0-60 far faster than doing the same thing in a procedural language, there may just be hope. I think that's true even if your work doesn't involve web development.
I'm not so sure that bringing up the "real world" would be as much a selling point as a working framework for writing good apps, because it turns out that, especially in statically typed languages like C# and Java, modeling the real world often requires tortuous abstractions. You can see a concrete example of the difficulty of modeling the real world by looking at thousands of people struggling to model something as ostensibly simple as the geometric abstraction of "shape" (shape, ellipse, circle).
所有编程范例都有相同的目标:隐藏不需要的复杂性。
有些问题可以通过命令式范例轻松解决,就像您的朋友使用的那样。其他问题可以通过面向对象的范例轻松解决。还有许多其他范式。主要的编程(逻辑编程、函数式编程和命令式编程)都是彼此等价的;面向对象编程通常被认为是命令式编程的扩展。
当程序员对相似但不相同的项目进行建模时,最好使用面向对象编程。命令式范式会将不同类型的模型放入一个函数中。面向对象范例将不同类型的模型分离为相关对象上的不同方法。
你的同事似乎陷入了一种范式。祝你好运。
All programming paradigms have the same goal: hiding unneeded complexity.
Some problems are easily solved with an imperative paradigm, like your friend uses. Other problems are easily solved with an object-oriented paradigm. There are many other paradigms. The main ones (logic programming, functional programming, and imperative programming) are all equivalent to each other; object-oriented programming is usually thought as an extension to imperative programming.
Object-oriented programming is best used when the programmer is modeling items that are similar, but not the same. An imperative paradigm would put the different kinds of models into one function. An object-oriented paradigm separates the different kinds of models into different methods on related objects.
Your colleague seems to be stuck in one paradigm. Good luck.
对我来说,只有开始谈论继承和多态性,OOP 的力量才会显现出来。
如果一个人对 OOP 的争论基于封装和抽象的概念,那么这对我来说并不是一个非常令人信服的论点。我可以编写一个巨大的库,并且只记录我希望用户了解的接口,或者我可以依靠语言级构造(例如 Ada 中的包)将字段设为私有,并且只公开我想要的内容暴露。
然而,当我在通用层次结构中编写代码时,真正的优势就出现了,以便以后可以重用它,从而将相同的代码接口用于不同的功能以实现相同的结果。
为什么这个很方便?因为我可以站在巨人的肩膀上来完成我现在的任务。我的想法是,我可以将问题的各个部分归结为最基本的部分,即组成对象的对象,组成对象的对象……组成项目的对象。通过使用在一般情况下很好地定义行为的类,我可以使用相同的经过验证的代码来构建同一事物的更具体的版本,然后是同一事物的更具体的版本,然后是更具体的版本同一事物的版本。关键是这些实体中的每一个都具有已经编码和测试过的共性,以后不需要再次重新实现。如果我不为此使用继承,我最终会重新实现通用功能或将我的新代码与旧代码显式链接,这为我提供了引入控制流错误的场景。
当我需要从对象实现某些功能,但也需要从相似但独特的类型获得相同的功能时,多态性非常方便。例如,在 Qt 中,存在将项目插入到模型中的想法,以便可以显示数据并且您可以轻松维护该对象的元数据。如果没有多态性,我将需要比现在更多的细节来困扰自己(即我需要实现相同的代码接口,这些接口执行与最初打算在模型上进行的项目相同的业务逻辑)。由于数据绑定对象的基类与模型本机交互,因此我可以毫无问题地将元数据插入到该模型中。我从对象中得到我需要的东西,而不关心模型需要什么,并且模型得到它需要的东西,而不关心我添加到类中的东西。
To me, the power of OOP doesn't show itself until you start talking about inheritance and polymorphism.
If one's argument for OOP rests the concept of encapsulation and abstraction, well that isn't a very convincing argument for me. I can write a huge library and only document the interfaces to it that I want the user to be aware of, or I can rely on language-level constructs like packages in Ada to make fields private and only expose what it is that I want to expose.
However, the real advantage comes when I've written code in a generic hierarchy so that it can be reused later such that the same exact code interfaces are used for different functionality to achieve the same result.
Why is this handy? Because I can stand on the shoulders of giants to accomplish my current task. The idea is that I can boil the parts of a problem down to the most basic parts, the objects that compose the objects that compose... the objects that compose the project. By using a class that defines behavior very well in the general case, I can use that same proven code to build a more specific version of the same thing, and then a more specific version of the same thing, and then yet an even more specific version of the same thing. The key is that each of these entities has commonality that has already been coded and tested, and there is no need to reimpliment it again later. If I don't use inheritance for this, I end up reimplementing the common functionality or explicitly linking my new code against the old code, which provides a scenario for me to introduce control flow bugs.
Polymorphism is very handy in instances where I need to achieve a certain functionality from an object, but the same functionality is also needed from similar, but unique types. For instance, in Qt, there is the idea of inserting items onto a model so that the data can be displayed and you can easily maintain metadata for that object. Without polymorphism, I would need to bother myself with much more detail than I currently do (I.E. i would need to implement the same code interfaces that conduct the same business logic as the item that was originally intended to go on the model). Because the base class of my data-bound object interacts natively with the model, I can instead insert metadata onto this model with no trouble. I get what I need out of the object with no concern over what the model needs, and the model gets what it needs with no concern over what I have added to the class.
让你的朋友想象一下他的房间、房子或城市中的任何物体……他是否能告诉一个这样的物体,它本身就是一个系统,并且能够做一些有意义的工作。
像按钮这样的东西并不能单独做某事 - 它需要很多对象才能打电话。
同样,汽车发动机也是由曲轴、活塞、火花塞组成。 OOPS 概念是从我们对自然过程或生活中事物的感知演变而来的。
《Inside COM》一书通过童年时通过提问来识别动物的游戏进行类比,讲述了 COM 的用途。
Ask your friend to visualize any object in his very Room, House or City... and if he can tell a single such object which a system in itself and is capable of doing some meaningful work.
Things like a button isnt doing something alone - it takes lots of objects to make a phone call.
Similarly a car engine is made of the crank shaft, pistons, spark plugs. OOPS concepts have evolved from our perception in natural processes or things in our lives.
The "Inside COM" book tells the purpose of COM by taking analogy from a childhood game of identifying animals by asking questions.
设计胜过技术和方法。好的设计往往会结合复杂性管理的通用原则,例如德米特法则,这是面向对象语言功能努力编码的核心。
良好的设计并不依赖于 OO 特定语言功能的使用,尽管使用它们通常符合人们的最佳利益。
Design trumps technology and methodology. Good designs tend to incorporate universal principals of complexity management such as law of demeter which is at the heart of what OO language features strive to codify.
Good design is not dependant on use of OO specific language features although it is typically in ones best interests to use them.
它不仅使其
您可以查找有关它的更多信息:
- Java:休眠
- Dot Net:实体框架
甚至了解 LINQ (Visual Studio) 如何使您的编程生活变得更加轻松。
也许用一个小演示来演示甚至很有趣:
.PS。我尝试以伪方式编写它:)
OO 方式
您调用的代码:
io.file.save(objectsCollection.ourFunctionForSaving())
类 objectCollection
函数 ourFunctionForSaving() As String
String _Objects
return _Objects
end method
NON-OO Way
我不认为我会写下非 oo 代码。但想一想:)
现在让我们
以面向对象的方式说。上面的类是所有保存账本、员工、成员、账户等方法的父类。
如果我们想更改保存到文本文件的方式会发生什么?例如,使其与当前标准 (.CVS) 兼容。
假设我们想添加一个加载函数,您需要编写多少代码?
在面向对象的方式中,您只需要添加一个 New Sub 方法,该方法可以将所有数据拆分为参数(这会发生一次)。
让你的同事考虑一下:)
Not only does it make
You can find more info about it looking up:
- Java : Hibernate
- Dot Net : Entity Framework
See even how LINQ (Visual Studio) can make your programming life MUCH easier.
Perhaps it is even fun to demonstrate with a little demo:
.PS. I tried writing it in a PSEUDO way :)
the OO way
Code you call:
io.file.save(objectsCollection.ourFunctionForSaving())
class objectsCollection
function ourFunctionForSaving() As String
String _Objects
return _Objects
end method
NON-OO Way
I don't think i'll write down non-oo code. But think of it :)
NOW LET'S SAY
In the OO way. The above class is the parent class of all methods for saving the books, employees, members, accounts, ...
What happens if we want to change the way of saving to a textfile? For example, to make it compactible with a current standard (.CVS).
And let's say we would like to add a load function, how much code do you need to write?
In the OO- way you only need the add a New Sub method which can split all the data into parameters (This happens once).
Let your collegue think about that :)
在状态和行为不一致的领域中,面向对象降低了这些领域内的整体依赖密度(即复杂性),这使得最终的系统不那么脆弱。
这是因为面向对象的本质是基于这样一个事实:从组织上来说,它根本不区分状态和行为,而是将两者统一视为“特征”。对象只是聚集在一起以最小化总体依赖性的一组功能。
在其他领域,面向对象并不是最好的方法。针对不同的问题有不同的语言范式。经验丰富的开发人员知道这一点,并且愿意使用最接近该领域的任何语言。
In domains where state and behavior are poorly aligned, Object-Orientation reduces the overall dependency density (i.e. complexity) within these domains, which makes the resulting systems less brittle.
This is because the essence of Object-Orientation is based on the fact that, organizationally, it doesn't dustinguish between state and behavior at all, treating both uniformly as "features". Objects are just sets of features clumpled to minimize overall dependency.
In other domains, Object-Orientation is not the best approach. There are different language paradigms for different problems. Experienced developers know this, and are willing to use whatever language is closest to the domain.