10

バイナリ プロトコルからメッセージをデコードするコードを書いています。各メッセージ タイプには 1 バイトのタイプ ID が割り当てられ、各メッセージにはこのタイプ ID が含まれます。メッセージはすべて、5 つのフィールドで構成される共通のヘッダーで始まります。私の API は単純です。

decoder:decode(Bin :: binary()) -> my_message_type() | {error, binary()}`

私の最初の本能は、メッセージ タイプごとに 1 つのデコード関数を記述してパターン マッチングに大きく依存し、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 の関数があります。この構造で完全なメッセージを複数回デコードしていますか? 慣用句ですか?関数ヘッダーのメッセージ タイプ フィールドをデコードしてから、メッセージ本文のメッセージ全体をデコードしたほうがよいでしょうか?

4

2 に答える 2

8

あなたのスタイルが非常に慣用的な Erlang であることに同意するだけです。コードがより明確になると思わない限り、デコードを別々の部分に分割しないでください。そのようなタイプのグループ化を行う方がより論理的である場合があります。

コンパイラはスマートで、メッセージを 2 回以上デコードしないようにパターン マッチングをコンパイルします。まず最初の 2 つのフィールド (バイト) をデコードし、次に 2 番目のフィールド (メッセージ タイプ) の値を使用して、残りのメッセージをどのように処理するかを決定します。これは、バイナリの共通部分の長さに関係なく機能します。

したがって、デコードを別々の部分に分割してコンパイラを「支援」する必要はありません。より効率的になることはありません。繰り返しますが、コードがより明確になる場合にのみ実行してください。

于 2011-04-28T21:48:18.493 に答える