我已经使用了面向对象的编程实践25年了,并试图在过去的5年里转向功能性编程,但是当我尝试做一些复杂的事情时,我的脑子总是朝向OOP。 ,特别是现在ES6支持合适的OOP语法,这是我构建内容的自然方式。
我现在正在学习Redux,而且我理解(c.f。How to put methods onto the objects in Redux state?)将减少类中的类实例放入禁令中是不行的。在普通减速器状态之上计算的推荐方法是使用选择器(例如,通过重选)。当然,React建议组合而不是继承(https://facebook.github.io/react/docs/composition-vs-inheritance.html,React redux oop classes)。
但React / Redux生态系统中是否存在具有方法和继承的类对象?
我想,为了回答我自己的问题,OOP类鼓励在同一个地方添加数据属性和数据操作,这对于可读性很好,但不适合纯函数和不可变数据。
如果我要使用OOP,我是否需要放弃让我的实例持续并保持状态任何时间的想法?就像,每次我想使用一个,我会从商店数据中实例化它,使用我想要的任何方法,然后扔掉它?这可能会消除使用OOP类的很多动力。但如果我保留实例,我会头疼,让他们与商店保持同步。
那么,当我试图使用方法并且在我试图使用继承时总是使用合成时,总是使用选择器的答案是什么?具体来说,我的意思是存储和操作Redux存储中保存的数据以用于React组件。如果是这样,它应该放在哪里?连接到选择器?像我建议的那样立即丢弃?
为了清晰起见,添加我的用例:我的数据基本上是一个巨大的图形:许多对象具有许多属性和对象之间的大量关系。它是只读的,但很复杂。我的对象被称为"概念"。
在做出(可能是愚蠢的)迁移到Redux的决定之前,我使用类来构造和表示概念,概念集和概念之间的关系。我的类包括用于获取概念集的异步api逻辑,有关每个概念的信息,以及与每个概念相关的其他概念的信息。如果用户选择向下钻取,则类将递归地获取并实例化新的概念集。 Redux文档推荐了嵌套数据(http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html)的平面,规范化结构,这对于存储来说可能是明智的,但我的OOP模型很适合遍历图形和部分的部分。我很难绕过使用选择器和不可变状态,可能涉及嵌套,可能包含循环,或者需要对更多数据进行异步调用。
我已成功使用https://redux-observable.js.org/作为api内容。
也许@Sulthan的答案是正确的:我应该随意在我的Redux应用程序中使用OOP技术。但它似乎仍然很奇怪。我无法保留我的对象,因为如果存储更改(例如,更多数据被提取),我的对象可能会变得陈旧。如果我的对象是嵌套的,但我的商店已经标准化,我会在需要时将它们(来自选择器)实例化,并确保不要将它们保留在...
答案 0 :(得分:10)
答案是它可能但严重劝阻和非惯用。
React确实依赖于React.Component
的类和单级继承来实现具有生命周期的有状态组件,但是正式不鼓励您在组件中进一步继承级别。
Redux是围绕功能编程原理构建的。出于各种原因,我们鼓励您将状态保持为普通的JS对象和数组,并使用普通函数访问/操作它。
我确实看到许多库试图在Redux之上添加OOP层(例如将其方法转换为动作创建者和缩减器的类)。那些工作,但肯定违背了Redux的整体精神。
我确实使用了一个名为Redux-ORM的库, 允许您定义模型类,它们充当商店中普通JS对象的外观。但是,与我见过的许多其他库不同,它与一起使用 Redux,而不是试图改变Redux的行为方式。我在我的博客文章Practical Redux, Part 1: Redux-ORM Basics和Practical Redux, Part 2: Redux-ORM Concepts and Techniques中讨论了Redux-ORM如何工作,我如何使用它,以及为什么它仍然是合理的惯用语。总的来说,它是帮助管理Redux商店中的关系和规范化数据的绝佳工具。
最后,我目前正在撰写一篇博客文章,讨论Redux需要的实际技术限制(及其原因),以及打算使用Redux的方式
答案 1 :(得分:8)
我将通过描述我最终做的事来回答我自己的问题,不完美。
首先,我开始使用stampit而不是常规的ES6类语法,这比ES6类更加灵活,但更加灵活。
但主要是,我的复杂对象有两种形式:
我使用了一个惯例,即在普通对象的所有引用之前放置一个_underscore。我的“解决方案”因为很多原因而变得很糟糕,但我认为尝试使用选择器会更糟糕。如果你很好奇,这里是我的代码中我将普通商店对象“膨胀”到实例中的地方:https://github.com/Sigfried/vocab-pop/blob/localstorage/src/ducks/conceptSet.js#L292
将redux状态POJO转换为类实例(常规或压力)是一个可怕的想法,很久以前有人应该阻止我。
我可能应该接受@ markerikson的答案,也许Redux-ORM的东西值得一看,但我只想明确地说,不要做我想做的事情。 (我一直认为我很聪明地填补了我正在用聪明的黑客学习的技术的“空白” - 然后我花了痛苦的几个月清理一塌糊涂,一旦我明白为什么这项技术不包括我的黑客第一名。)
来自Composing Software: An Introduction:
我们不会做的是说功能编程比 面向对象的编程,或者你必须选择一个 其他。 OOP与FP是一种错误的二分法。每个真正的Javascript 我近年来看到的应用程序广泛混合了FP和OOP。
看起来有很好的方法可以考虑组合FP和OOP,毫无疑问,它会使用一些不可变的类和组合而不需要很多继承。这个关于作文的系列看起来就像我需要学习的那样。
答案 2 :(得分:1)
这个问题有点基于意见,但让我们专注于核心问题。
功能编程和OOP之间没有矛盾。您只需要使用相同的编程模式。在函数式编程中使用类(带继承)没有问题,如果你保持它们是不可变的。
为了证明我的观点,许多人用来在redux中保持状态的流行库Immutable.js由 classes 组成。这些类具有继承性(例如OrderedSet extends Set
)。
另请注意,大多数React
组件都是类,它们也使用继承(... extends React.Component
)。