Я пишу код для декодирования сообщений из двоичного протокола. Каждому типу сообщения присваивается 1-байтовый идентификатор типа, и каждое сообщение содержит этот тип идентификатора. Все сообщения начинаются с общего заголовка, состоящего из 5 полей. Мой API прост:
decoder:decode(Bin :: binary()) -> my_message_type() | {error, binary()}`
Мой первый инстинкт - сильно полагаться на сопоставление с образцом, написав одну функцию декодирования для каждого типа сообщения и полностью декодировать этот тип сообщения в забавном аргументе
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 функций, аналогичных описанным выше. Я декодирую полное сообщение несколько раз с этой структурой? Это идиоматично? Не лучше ли мне просто декодировать поле типа сообщения в заголовке функции, а затем декодировать полное сообщение в теле сообщения?