2011-04-28 21 views
10

Estoy escribiendo código para decodificar mensajes desde un protocolo binario. A cada tipo de mensaje se le asigna un identificador de tipo de 1 byte y cada mensaje lleva este tipo de identificación. Todos los mensajes comienzan con un encabezado común que consta de 5 campos. Mi API es simple:Cadenas de bits que coinciden con el patrón de Erlang

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

Mi primer instinto es apoyarse en gran medida de coincidencia de patrones escribiendo función de uno de decodificación para cada tipo de mensaje y para descifrar que tipo de mensaje completo en el argumento divertido

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}. 

Nota que si bien los primeros 5 campos de los mensajes son estructuralmente idénticos, los campos posteriores varían según el tipo de mensaje.

Tengo aproximadamente 20 tipos de mensajes y por lo tanto 20 funciones similares a las de arriba. ¿Estoy decodificando el mensaje completo varias veces con esta estructura? ¿Es idiomático? ¿Sería mejor que simplemente decodificara el campo de tipo de mensaje en el encabezado de la función y luego decodificara el mensaje completo en el cuerpo del mensaje?

+0

Meta pregunta: obtengo un bonito coloreado del código erlang en la vista previa cuando edito esta publicación, pero no en la página representada después de publicar. ¿Ayuda? – mpm

+0

se dio cuenta de esto también cuando se publica el código de erlang, podría ser una pregunta para meta –

+1

Publicó una pregunta sobre meta con respecto a la coloración de sintaxis http://meta.stackexchange.com/questions/89117/why-do-i-get-nice-erlang -syntax-coloring-in-preiviev-but-not-in-the-rendered-page –

Respuesta

8

Solo para acordar que su estilo es muy idiomático Erlang. No divida la decodificación en partes separadas a menos que sienta que hace que su código sea más claro. A veces puede ser más lógico hacer ese tipo de agrupación.

El compilador es inteligente y compila la coincidencia de patrones de forma que no decodificará el mensaje más de una vez. Primero decodificará los primeros dos campos (bytes) y luego usará el valor del segundo campo, el tipo de mensaje, para determinar cómo manejará el resto del mensaje. Esto funciona independientemente de cuánto tiempo es la parte común del binario.

Así que no es necesario intentar "ayudar" al compilador dividiendo la decodificación en partes separadas, no lo hará más eficiente. De nuevo, solo hazlo si hace que tu código sea más claro.

+0

Justo lo que necesitaba escuchar en re: optimizaciones del compilador. El código es más claro ya que está estructurado actualmente. Gracias, Rob. – mpm

7

Su enfoque actual es idiomático Erlang, así que continúe en esta dirección. No se preocupe por el rendimiento, el compilador de Erlang hace un buen trabajo aquí. Si sus mensajes son realmente exactamente el mismo formato, puede escribir macro para él, pero debería generar el mismo código en el capó. De todos modos, el uso de macro generalmente conduce a una peor capacidad de mantenimiento. Solo por curiosidad ¿por qué está generando diferentes tipos de registros cuando todos tienen exactamente los mismos campos? El enfoque alternativo es simplemente traducir el tipo de mensaje de constante a átomo de Erlang y almacenarlo en un tipo de registro.

+1

En segundo lugar. Si no simplificó la estructura para la publicación y todos los registros tienen el mismo formato, utilice átomos para diferenciar entre los tipos de registros, una función y una definición de registro erlang. –

+1

Lo siento, me simplifiqué demasiado en mi código. Después de los primeros 5 campos, los mensajes son diferentes. He actualizado el código del ejemplo para indicar que los dos mensajes, TypeX y ​​TypeY, tienen un número diferente de campos y diferentes estructuras de campo. Perdón por la confusion. – mpm

+1

@mpm: Entonces, su código se adapta perfectamente a las expresiones idiomáticas de Elang. Para el lector de código, por lo general, es más difícil seguir el flujo de código "hacer coincidir esto y luego hacer coincidir esto y luego esto", que ver aquí es un tipo de mensaje y otro tipo de mensaje. Es incluso mejor para el mantenimiento a largo plazo. Después de una etapa muy temprana del proyecto, leerá más y más parches y las suposiciones iniciales pueden cambiar drásticamente. Lo que es común para el mensaje de hoy no podría ser en polillas o años y cada uno de esos cambios provocará un cambio de código más en cascada que su enfoque actual. –

Cuestiones relacionadas