“可变”的最佳策略Erlang 中的记录
我开发的系统假设会有很多用户。每个用户都有一个在应用程序内以记录形式表示的个人资料。为了存储用户的配置文件,我执行以下操作 base64:encode_to_string(term_to_binary(Profile))
,因此配置文件基本上以序列化方式存储。
到目前为止一切都很好。现在的问题是:
我有时确实计划通过添加和删除其中的某些字段来扩展配置文件功能。我的问题是处理代码中这些更改的最佳策略是什么?
我目前看到的方法是做这样的事情:
Profile = get_profile(UserName),
case is_record(Profile, #profile1) of
true ->
% do stuff with Profile#profile1
ok;
_ ->
next
end,
case is_record(Profile, #profile2) of
true ->
% do stuff with Profile#profile2
ok;
_ ->
next
end,
我想知道我的任务是否有更好的解决方案?
其他信息:我使用的是简单的 KV 存储。它无法存储 Erlang 类型,这就是我使用 State#state.player#player.chips#chips.br 的原因
I develop the system where I assume will be many users. Each user has a profile represented inside the application as a record. To store user's profile I do the following base64:encode_to_string(term_to_binary(Profile))
, so basically profiles stored in serialized maner.
So far everything is just fine. Now comes the question:
From time to time I do plan to extend profile functionality by adding and removing certain fields in it. My question is what is a best strategy to handle these changes in the code?
The approach I see at the moment is to do something like this:
Profile = get_profile(UserName),
case is_record(Profile, #profile1) of
true ->
% do stuff with Profile#profile1
ok;
_ ->
next
end,
case is_record(Profile, #profile2) of
true ->
% do stuff with Profile#profile2
ok;
_ ->
next
end,
I want to know if there are any better solutions for my task?
Additional info: I use is simple KV storage. It cannot store Erlang types this is why I use State#state.player#player.chips#chips.br
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
也许,你可以使用 proplists。
假设您已经存储了一些用户配置文件。
然后,几年后,您决定根据用户的年龄扩展用户配置文件。
现在您需要从数据库获取用户配置文件。
如果您获取“版本 2”的用户配置文件,您将获得实际年龄(在本例中为 23)。
如果您获得“版本 1”(“旧”版本)的用户配置文件,您将获得“未定义”的年龄, - 然后您可以更新配置文件并将其存储为新值,因此它将是“新”版本'实体。
所以,不存在版本冲突。
也许,这不是最好的方法,但在某些情况下它可能是一个解决方案。
Perhaps, you could use proplists.
Assume, you have stored some user profile.
Then, after a couple of years you decided to extend user profile with user's age.
Now you need to get a user profile from DB
If you get a user profile of 'version 2', you will get an actual age (23 in this particular case).
If you get a user profile of 'version 1' ('old' one), you will get 'undefined' as an age, - and then you can update the profile and store it with the new value, so it will be 'new version' entity.
So, no version conflict.
Probably, this is not the best way to do, but it might be a solution in some case.
它很大程度上取决于记录数量的比例、更改频率和可接受的中断。由于可维护性,我更喜欢首先将配置文件升级到最新版本。您还可以制作像 mnesia 一样即时升级的系统。最后,有可能保留所有版本的代码,这是我绝对不喜欢的。这是维护的噩梦。
无论如何,当守卫中允许
is_record/2
时,我更愿意注意,没有 catch all 子句,因为您将如何处理未知的记录类型?这是错误,所以很快就会失败!
您还有许多其他选择,例如 hack like:
或类似的东西
以及许多其他可能性。
It strongly depend of proportion of number of records, frequency of changes and acceptable outage. I would prefer upgrade of profiles to newest version first due maintainability. You also can make system which will upgrade on-fly as mnesia does. And finally there is possibility keep code for all versions which I would definitely not prefer. It is maintenance nightmare.
Anyway when
is_record/2
is allowed in guards I would preferNotice there is not catch all clause because what you would do with unknown record type? It is error so fail fast!
You have many other options e.g. hack like:
or something like
and many other possibilities.
最好的方法是拥有序列化(配置文件)的副本以及相同但以记录形式存在的副本。然后,每次对记录形式配置文件进行更改时,也会自动对同一用户的序列化配置文件进行更改(在同一事务中!)。修改用户记录配置文件的代码应该始终重新计算新的序列化形式,对您来说,这是用户记录的外部表示
So whatever the serialize function is doing, that's that. But this always leaves an overhead free profile change. We thereby keep the serialized profile as always the correct representation of the record profile at all times. When changes occur to the record profile, the serialized form must also be recomputed (transactional) so as to have integrity.
The best approach is to have the copy of the serialized (profile) and also a copy of the same but in record form. Then , each time changes are made to the record-form profile, changes are also made to the serialized profile of the same user ATOMICALLY (within the same transaction!). The code that modifies the users record profile, should always recompute the new serialized form which, to you, is the external representation of the users record
So whatever the serialize function is doing, that's that. But this always leaves an overhead free profile change. We thereby keep the serialized profile as always the correct representation of the record profile at all times. When changes occur to the record profile, the serialized form must also be recomputed (transactional) so as to have integrity.
您可以使用一些可扩展数据序列化格式,例如 JSON 或 Google Protocol Buffers。
这两种格式都支持添加新字段,而不会破坏向后兼容性。通过使用它们,您不需要向序列化数据结构引入显式版本控制。
在两种格式之间进行选择取决于您的用例。例如,使用 Protocol Buffers 更可靠,而 JSON 更容易上手。
You could use some extensible data serialization format such as JSON or Google Protocol Buffers.
Both of these formats support adding new fields without breaking backwards compatibility. By using them you won't need to introduce explicit versioning to your serialized data structures.
Choosing between the two formats depends on your use case. For instance, using Protocol Buffers is more reliable, whereas JSON is easier to get started with.