是否有针对来自不同、冲突、优先来源的属性的设计模式?
我有一个对象的一堆属性,这些值大多是布尔值,但它们来自不同的来源,不同的来源相互覆盖。
例如,要确定功能 X 是否可供用户使用,我有以下信息源:
- 功能的默认值,例如“功能 X 默认可用”
- 用户帐户类型,例如“功能 X 可供具有以下功能的用户使用”帐户类型“企业””
- 国家/地区,例如“功能 X 在您的国家/地区不可用”
- 每用户覆盖,例如“功能 X 可供该用户使用,因为他很酷”
对于不同的功能、来源列表及其顺序它们对违约的影响不同,例如,单个用户无法覆盖功能 Y,国家/地区源具有优先权。
也许我太受当前实现的束缚,如下所示:
- 每个功能都由类功能中的常量标识。
- 有一个具有默认值的数组(功能 X -> 默认情况下不可用)。
- 每种帐户类型都有数组(企业帐户:功能 X -> 可用,功能 Y -> ...)
- 所有其他来源都有一个很长的函数,其中有很多
if
-嵌套 - 最后有(或可能有)无条件的每用户覆盖
(从 user_feature 中选择可用,其中 user_id=1 且 feature_id=X
)。
问题是,我该如何正确地做到这一点,是否有一个设计模式? 或者也许我太笼统了,而 YAGNI 就是答案?
我想象的可能是这样的:
- 一个 DSL 来描述来源对财产的影响,表达诸如“适用于此帐户类型”和“在该国家/地区不可用”之类的内容
- 每个定义的财产的来源的有序列表
- 默认可能只是另一个来源
编辑
也许我的问题是不同属性和源的数量。也许我需要一个高效的数据结构来保存有关属性、数据源、优先级/源顺序/覆盖的信息来计算每个属性。
I have a bunch of properties of an object, which values are mostly boolean, but they come from different sources, different sources overriding each other.
For example, to decide if feature X is available to a user, I have following information sources:
- Default value for the feature, like, "Feature X is available per default"
- User account type, like, "Feature X is available for users with account type 'Business'"
- Country, like, "Feature X is not available in your country"
- Per-user override, like, "Feature X is available for this user because he's cool"
For different features, the list of sources, their order and their effect on default differ, for example, feature Y cannot be overridden for an individual user, country source has priority.
Maybe I'm too bound to the current implementation, which is following:
- Each feature is identified by a constant in the class Feature.
- There is an array with defaults (feature X -> not available per default).
- There are arrays for each account type (business account:feature X -> available, feature Y -> ...)
- There is a long, long function for all the other sources, with lots of
if
-nesting - There is (or there can be) an unconditional per-user override at the end
(select available from user_feature where user_id=1 and feature_id=X
).
The question is, how do I do it right, and is there a design pattern for this?
Or maybe I'm trying to be too generic and YAGNI is the answer?
What I imagine could work out:
- A DSL to describe the effect of a source on a property, to express things like "available for this account type" and "not available in this country"
- An ordered list of sources for each defined property
- Default could be just another source
EDIT
Maybe my problem is the number of different properties and sources. Maybe I need an efficient data structure to hold information about properties, data sources, priorities/source order/overriding to compute every property.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“先重要,后允许”
首先,为每个来源分配一个重要性。默认值是最不重要的,因为它总是应该被覆盖。
现在,当尝试确定权限时,请从最重要的来源开始,看看它有什么内容。继续下去,直到找到告诉您是否允许该操作的来源并使用它。
您可能希望某些来源具有同等重要性。在这种情况下,请使用最严格的设置。如果两个同等重要的来源不同,一个说你可以,另一个说你不能,那么你就可以。 (显然,这是假设没有更重要的消息来源表明您可以或不可以,否则您就会停在那里。)
我不知道这是否是一种模式,而不是一种算法。
"Importance, then permissive"
First, assign each source an importance. Default is the LEAST important, since it should always be overwritten.
Now, when trying to determine a permission, start with the most important source and see what it has to say. Continue until you find a source that tells you whether or not the action is allowed and use that.
You may want to have some sources be of equal importance. In this case, use the most premissive setting. If two sources of equal importance differ, where one says you can and another says you can't, then you can. (Obviously this assumes no more important sources have said you can or can't, or you would have stopped there.)
I don't know if this is a pattern so much as an algorithm.
您可能需要查看规范模式,以获取处理复杂规则系统的简洁方法。
您为规则定义 DSL 的想法也可能是一个不错的想法,由 DSL 构建的结构是模式中描述的复合规范。
You might want to look at the Specification Pattern for a clean way of handling a complex system of rules.
Your idea of defining a DSL for the rules may also be a good one, with the structure built by the DSL being a composite specification as described in the pattern.