Я пишу код для декодирования сообщений из двоичного протокола. Каждому типу сообщения присваивается идентификатор 1 байтового типа, и каждое сообщение содержит этот идентификатор типа. Все сообщения начинаются с общего заголовка, состоящего из 5 полей. Мой API прост:
decoder:decode(Bin :: binary()) -> my_message_type() | {error, binary()}`
Мой первый инстинкт состоит в том, чтобы сильно наклониться на соответствие шаблонов, написав одну функцию декодирования для каждого типа сообщения и полностью декодировать этот тип сообщения в аргументе fun
decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_X:8, Hdr3:8, Hdr4:8, Hdr5:32,
TypeXField1:32, TypeXFld2:32, TypeXFld3:32>>) ->
#message_x{hdr1=Hdr1, hdr3=Hdr3 ... fld4=TypeXFld3};
decode(<<Hdr1:8, ?MESSAGE_TYPE_ID_Y:8, Hdr3:8, Hdr4:8, Hdr5:32,
TypeYField1:32, TypeYFld2:16, TypeYFld3:4, TypeYFld4:32
TypeYFld5:64>>) ->
#message_y{hdr1=Hdr1, hdr3=Hdr3 ... fld5=TypeYFld5}.
Обратите внимание, что хотя первые 5 полей сообщений структурно идентичны, поля после этого изменяются для каждого типа сообщения.
У меня примерно 20 типов сообщений и, следовательно, 20 функций, подобных описанным выше. Я несколько раз расшифровываю полное сообщение с этой структурой? Это идиоматично? Не лучше ли мне просто декодировать поле типа сообщения в заголовке функции, а затем декодировать полное сообщение в теле сообщения?