redux 中是否有面向对象的地方? [英] Is there any place for OOP in redux?

查看:69
本文介绍了redux 中是否有面向对象的地方?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用面向对象的编程实践 25 年了,并在过去 5 年里尝试转向函数式编程,但是当我尝试做一些复杂的事情时,我的想法总是倾向于 OOP,尤其是现在ES6 支持体面的 OOP 语法,这是我构建东西的自然方式.

我现在正在学习 Redux 并且我明白(参见 如何将方法放在 Redux 状态的对象上?) 禁止将类实例放在你的减速器中;在普通减速器状态之上计算的推荐方法是使用选择器(例如,通过重新选择).而且,当然,React 推荐组合而不是继承(https://facebook.github.io/react/docs/composition-vs-inheritance.html, React redux oop 类).

但是在 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 技术.但看起来还是很奇怪.我无法保留我的对象,因为如果存储发生变化(例如,获取更多数据),我的对象可能会过时.如果我的对象是嵌套的但我的商店是规范化的,我会在我需要它们时(从选择器)实例化它们,并确保不要将它们留在周围......

解决方案

我将通过描述我最终做了什么来回答我自己的问题,尽管它并不完美.

首先,我开始使用 stampit,而不是常规的 ES6 类语法,比 ES6 类更丑,但更灵活.

不过,我的复杂对象主要以两种形式存在:

  • 用于商店的普通 JS 对象
  • 为了方便和使用实例方法的强大功能,对实例进行类(实际标记).

我习惯于在所有对普通对象的引用之前放置一个 _underscore.由于很多原因,我的解决方案"很笨拙而且很糟糕,但我认为尝试对所有事情都使用选择器会更糟.如果你很好奇,这里是我的代码中我将普通存储对象膨胀"到实例的地方:https://github.com/Sigfried/vocab-pop/blob/localstorage/src/ducks/conceptSet.js#L292

更新

将 redux state POJO 变成类实例(regular 或 stampit)是一个糟糕的主意,早就应该有人阻止我了.

我可能应该接受@markerikson 的回答,也许 Redux-ORM 的东西值得一看,但我只想明确地说,不要做我所做的.(我一直认为我很聪明地用聪明的黑客来填补我正在学习的技术的空白"——然后我花了几个月痛苦的时间来清理烂摊子,一旦我明白为什么该技术没有将我的黑客包括在第一名.)

另一个更新

来自作曲软件:简介:><块引用>

我们不会说函数式编程比面向对象的编程,或者你必须选择一个其他.OOP vs FP 是错误的二分法.每一个真正的 Javascript近年来我看到的应用广泛地混合了 FP 和 OOP.

看起来有很好的方法来考虑结合 FP 和 OOP,毫无疑问,它会使用一些不可变的类和组合,而不需要很多继承.这个关于作文的系列看起来像我需要学习的东西.

I've been using object-oriented programming practices for 25 years and trying to move toward functional programming for the last 5 years, but my mind always goes towards OOP when I'm trying to do something complex and, especially now that ES6 supports decent OOP syntax, that's the natural way for me to build stuff.

I'm now learning Redux and I understand (c.f. How to put methods onto the objects in Redux state?) that it's a no-no to put class instances in your reducers; and the recommended method for computing on top of plain reducer state is by using selectors (e.g., via reselect). And, of course, React recommends composition over inheritance (https://facebook.github.io/react/docs/composition-vs-inheritance.html, React redux oop classes).

But is there any place in the React/Redux ecosystem for class objects with methods and inheritance?

I guess, to sort of answer my own question, OOP classes encourage the addition of data properties and operations on the data in the same place, which is nice for readability, but doesn't fit well with pure functions and immutable data.

If I was going to use OOP, would I need to chuck the idea of having my instances persist and maintain state for any amount of time? Like, every time I want to use one, I would instantiate it from store data, use whatever methods I want, and throw it away? That might obviate a lot of the impetus to use OOP classes. But if I keep instances around, I'll have headaches keeping them synced with the store.

So, is the answer to always use selectors when I'm tempted to use methods and always use composition when I'm tempted to use inheritance? Specifically, I mean when storing and manipulating data held in a Redux store for use in React components. And, if so, where should it fit in? Connected to selectors? Immediately disposable like I suggested?


Adding my use case for clarity: My data is basically a huge graph: lots of objects with lots of properties and lots of relationships between objects. It's read only, but complex. My objects are called "concepts".

Before making the (probably foolish) decision to migrate to Redux, I used classes to structure and represent concepts, sets of concepts, and relationships between concepts. My classes included async api logic to fetch concept sets, information about each concept, and information about other concepts that each concept is related to. If the user chose to drill down, the classes would recursively fetch and instantiate new concept sets. The Redux documentation recommends flat, normalized structures for nested data (http://redux.js.org/docs/recipes/reducers/NormalizingStateShape.html) which is probably wise for storage, but my OOP model was good for traversing sections of the graph and stuff. I have a hard time wrapping my head around using selectors and immutable state that might involve nesting, potentially with cycles, or needing to make async calls for more data.

I'm successfully using https://redux-observable.js.org/ for the api stuff.

Maybe @Sulthan's answer is right: I should feel free to use OOP techniques in my Redux application. But it still seems weird. I can't keep my objects around because if the store changes (more data is fetched, for instance), my objects can get stale. If my objects are nested but my store is normalized, I'll instantiate them (from selectors) when I need them and make sure not to keep them around...

解决方案

I'll answer my own question by describing what I ended up doing, imperfect as it is.

First, instead of regular ES6 class syntax, I've started using stampit, which is uglier that ES6 classes, but much more flexible.

Mainly, though, my complex objects exist in two forms:

  • plain JS objects for the store
  • class (actually stamped) instances for convenience and power of using instance methods.

I use a convention of putting an _underscore in front of all references to the plain objects. My "solution" is kludgy and bad for lots of reasons, but I think trying to use selectors for everything would be worse. If you're curious, here's the place in my code where I "inflate" my plain store objects into instances: https://github.com/Sigfried/vocab-pop/blob/localstorage/src/ducks/conceptSet.js#L292

UPDATE

Turning redux state POJOs into class instances (regular or stampit) is a terrible idea and someone should have stopped me long ago.

I probably should have accepted @markerikson's answer, and maybe the Redux-ORM thing is worth looking at, but I just wanted to say definitively, DON'T DO WHAT I DID. (I always think I'm so smart filling in the "gaps" of technologies I'm learning with clever hacks -- and then I spend painful months cleaning up the mess once I understand why that technology didn't include my hack in the first place.)

Another update

From Composing Software: An Introduction:

What we won’t do is say that functional programming is better than object-oriented programming, or that you must choose one over the other. OOP vs FP is a false dichotomy. Every real Javascript application I’ve seen in recent years mixes FP and OOP extensively.

Looks like there are good ways to think about combining FP and OOP, and it will, no doubt, use some immutable classes and composition without a lot of inheritance. This series on composition looks like what I needed to learn.

这篇关于redux 中是否有面向对象的地方?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆