同一erlang记录的不同视图

同一erlang记录的不同视图,erlang,Erlang,假设我有记录 -record(expense, {uuid, amount, tags}). 我想要一个可显示版本的记录。标记字段包含标记唯一ID。我想在表单上显示标签的名称,而不是唯一的ID。在Erlang你会怎么做?通常,在OOP语言中,您可以使用ViewModel来显示同一对象的不同版本 备选方案1 使用不同数据格式的相同记录,但我认为这会破坏接口合同;人们将无法知道自己拥有的记录的版本 选择2 创建另一个记录 -record(expense_view1, {uuid, amount,

假设我有记录

-record(expense, {uuid, amount, tags}).
我想要一个可显示版本的记录。标记字段包含标记唯一ID。我想在表单上显示标签的名称,而不是唯一的ID。在Erlang你会怎么做?通常,在OOP语言中,您可以使用ViewModel来显示同一对象的不同版本

备选方案1 使用不同数据格式的相同记录,但我认为这会破坏接口合同;人们将无法知道自己拥有的记录的版本

选择2 创建另一个记录

-record(expense_view1, {uuid, amount, tags}).
但它会创建大量重复记录

选择3 使用元组或映射。如果我向记录中添加更多字段,Tuple很难维护,而maps也不能保证字段名的安全

标记字段包含标记唯一ID。我想显示名称 表单上的标记数,而不是唯一ID

这个怎么样:

-module(a).
-compile(export_all).

-record(expense, {uuid, amount, tags}).

show_action(#expense{uuid=UUID, amount=Amount, tags={A, B, C} }) ->
    TagConversions= #{1 => "Joe", 2 => "Tammy", 3 => "Bob"},
    A_Conv = maps:get(A, TagConversions, "Nathan"),
    B_Conv = maps:get(B, TagConversions, "Nathan"),
    C_Conv = maps:get(C, TagConversions, "Nathan"),
    io:format("~w, ~w, {~s,~s,~s}~n", 
              [UUID, Amount, A_Conv, B_Conv, C_Conv]).


go() ->
    Expense1 = #expense{uuid=1, amount=10, tags={1,2,3} },
    show_action(Expense1).
在外壳中:

12> c(a).  
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

13> a:go().
1, 10, {Joe,Tammy,Bob}
ok
5> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

6> a:go().
1, 10, {Joe,Tammy,Bob}
{expense,1,10,{{tag,1,"Joe"},{tag,2,"Tammy"},{tag,3,"Bob"}}}
1> c(tuple).                                                  
{ok,tuple}
2> rr(tuple).                                                 
[expense]
3> T = #expense{uuid = 12345, amount = 20000, tags = [1,3,4]}.
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
4> tuple:start().                                             
true
5> tuple:get(T).                                              
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
6> tuple:get(T,value).
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
7> tuple:get(T,id).   
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
8> tuple:stop().
stop
我想要一个可显示版本的记录。 但它会创建大量重复记录

是的,但在面向对象编程中,视图对象不是越来越多,它们包含模型对象中的全部或一个子集数据吗

选项1使用相同的记录和不同的数据格式,但我认为 它将破坏接口合同;人们将无法知道 你有哪个版本的记录

您可以对记录进行结构化,为与标记ID相对应的标记名留下一个空白点,然后在您能够:

-module(a).
-compile(export_all).

-record(tag, {id, name=""}).
-record(expense, {uuid, amount, tags}).

show_action(Expense = #expense{uuid=UUID, amount=Amount, tags={A, B, C} }) ->
    TagConversions= #{1 => "Joe", 2 => "Tammy", 3 => "Bob"},
    A_Conv = maps:get(A#tag.id, TagConversions, "Nathan"),
    B_Conv = maps:get(B#tag.id, TagConversions, "Nathan"),
    C_Conv = maps:get(C#tag.id, TagConversions, "Nathan"),
    io:format("~w, ~w, {~s,~s,~s}~n", 
              [UUID, Amount, A_Conv, B_Conv, C_Conv]),

    Expense#expense{tags={
                      A#tag{name=A_Conv},
                      B#tag{name=B_Conv},
                      C#tag{name=C_Conv}
                     }}.
go() ->

    Expense1 = #expense{uuid=1, amount=10, 
                        tags={#tag{id=1},
                              #tag{id=2},
                              #tag{id=3} }
                       },

    show_action(Expense1).
在外壳中:

12> c(a).  
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

13> a:go().
1, 10, {Joe,Tammy,Bob}
ok
5> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

6> a:go().
1, 10, {Joe,Tammy,Bob}
{expense,1,10,{{tag,1,"Joe"},{tag,2,"Tammy"},{tag,3,"Bob"}}}
1> c(tuple).                                                  
{ok,tuple}
2> rr(tuple).                                                 
[expense]
3> T = #expense{uuid = 12345, amount = 20000, tags = [1,3,4]}.
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
4> tuple:start().                                             
true
5> tuple:get(T).                                              
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
6> tuple:get(T,value).
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
7> tuple:get(T,id).   
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
8> tuple:stop().
stop

您可以在访问功能中选择查看模式:

-module (tuple).

-export ([get/1,get/2,start/0,stop/0]).


-record(expense, {uuid, amount, tags}).

%%%%%%%%% Interfaces %%%%%%%%%

% start the server with a static map
start() ->
    Pid =spawn(fun() -> loop(#{1 => one, 2 => two, 3 => three}) end),
    register(server, Pid).

stop() ->
    server ! stop.

% By default for "external users" get the view with value
get(T) ->
    get(T,value).

% for "internal usage" it is possible to choose either the id view or the value view
get(T,value) ->
    Values = lists:map(fun get_value/1, T#expense.tags),
    T#expense{tags = Values};
get(T,id) ->
    T.

%%%%%%%%% server %%%%%%%%%%
% the server is in charge to store the id => value association
% it could be also stored in an ETS, a database ...
loop(Ids) ->
    receive
        stop ->
            done;
        {From, get_value, Id} ->
            % the choice is made to do not crash if the id does not exist
            From ! {ok,maps:get(Id, Ids, undefined)},
            loop(Ids)
    end.

%%%%%%%%% private %%%%%%%%%

get_value(Id) ->
    server ! {self(), get_value, Id},
    receive
        {ok,Value} ->
            Value
    end.
在外壳中给出:

12> c(a).  
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

13> a:go().
1, 10, {Joe,Tammy,Bob}
ok
5> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}

6> a:go().
1, 10, {Joe,Tammy,Bob}
{expense,1,10,{{tag,1,"Joe"},{tag,2,"Tammy"},{tag,3,"Bob"}}}
1> c(tuple).                                                  
{ok,tuple}
2> rr(tuple).                                                 
[expense]
3> T = #expense{uuid = 12345, amount = 20000, tags = [1,3,4]}.
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
4> tuple:start().                                             
true
5> tuple:get(T).                                              
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
6> tuple:get(T,value).
#expense{uuid = 12345,amount = 20000,
         tags = [one,three,undefined]}
7> tuple:get(T,id).   
#expense{uuid = 12345,amount = 20000,tags = [1,3,4]}
8> tuple:stop().
stop