2011-04-28 5 views
10

바이너리 프로토콜의 메시지를 디코딩하는 코드를 작성 중입니다. 각 메시지 유형에는 1 바이트 유형 식별자가 할당되며 각 메시지는이 유형 ID를 전달합니다. 메시지는 모두 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 개의 메시지 유형이 있습니다. 이 구조로 여러 번 전체 메시지를 디코딩합니까? 그것은 관용적입니까? 함수 헤더에서 메시지 유형 필드를 디코딩 한 다음 메시지 본문에서 전체 메시지를 디코딩하는 것이 더 낫지 않습니까?

+0

메타 질문 : 내가 게시 한 후에이 게시물을 편집 할 때 미리보기에 멋진 erlang 코드 색상 표시가 표시되지만 렌더링 된 페이지에는 표시되지 않습니다. 도움? – mpm

+0

도 오류 코드 게시시이 사실을 알았 으면 메타에 대한 질문 일 수도 있습니다 –

+1

http://meta.stackexchange.com/questions/89117/why-do-i-get-nice-erlang 구문 색상과 관련하여 메타에 질문을 게시 함 -syntax-in-preiviev-but-not-rendered-page –

답변

8

귀하의 스타일이 매우 평범한 얼랭 (Erlang)이라는 점에 동의하십시오. 코드를 명확하게 만들지 않는 한 디코딩을 별도의 부분으로 분할하지 마십시오. 이러한 유형의 그룹화를 수행하는 것이 더 논리적 일 수 있습니다.

컴파일러는 스마트하고 여러 번 메시지를 디코딩하지 않는 방식으로 패턴 일치를 컴파일합니다. 먼저 처음 두 필드 (바이트)를 디코딩 한 다음 두 번째 필드 값인 메시지 유형을 사용하여 나머지 메시지를 처리하는 방법을 결정합니다. 이것은 바이너리의 공통 부분이 얼마나 오랫동안 있는지에 관계없이 작동합니다.

따라서 개발자는 디코딩을 별도의 부분으로 분할하여 컴파일러를 "도움"할 필요가 없으므로 더 효율적으로 만들 수 없습니다. 다시 말하지만, 코드가 명확 해지면 다시하십시오.

+0

필자는 다시 듣고 싶었던 부분 : 컴파일러 최적화. 이 코드는 현재 구조화되어 있기 때문에 실제로 더 명확합니다. 고마워, 롭. – mpm

7

현재 접근 방식은 관용적 인 얼랭입니다. 따라서이 방향으로 계속하십시오. 성능에 대해 걱정하지 마십시오. Erlang 컴파일러는 여기서 잘 작동합니다. 메시지가 실제로 정확히 동일한 형식이면 매크로를 작성할 수 있지만 후드 아래에서 동일한 코드가 생성되어야합니다. 어쨌든 매크로를 사용하면 일반적으로 유지 관리가 더욱 어려워집니다. 호기심 때문에 왜 모두 똑같은 필드가있을 때 다른 레코드 유형을 생성합니까? 다른 방법은 메시지 유형을 상수에서 얼랑 (Erlang) 원자로 변환 한 다음 하나의 레코드 유형으로 저장하는 것입니다.

+1

그 두 번째. 게시물의 구조를 단순화하지 않았고 레코드의 형식이 모두 같으면 원자를 사용하여 레코드 유형 (하나의 함수와 한 개의 레코드 정의)을 구별합니다. –

+1

죄송합니다 - 코드가 지나치게 단순화되었습니다. 처음 5 개 필드 이후에는 메시지가 서로 다릅니다. TypeX와 TypeY라는 두 개의 메시지가 다른 개수의 필드와 다른 필드 구조를 가지고 있음을 나타 내기 위해 코드 예제를 업데이트했습니다. 혼란을 드려 죄송합니다. – mpm

+1

@mpm : 그러면 코드가 엘랑 관용구와 완벽하게 일치합니다. 코드의 독자는 일반적으로 코드 흐름을 따라가는 것이 더 어렵습니다. 다음은이 메시지와 다른 유형의 메시지입니다. 장기간 유지 보수가 더 좋습니다. 프로젝트 초기 단계에서 점점 더 많은 패치와 초기 가정이 크게 바뀔 수 있습니다. 오늘날 메시지에 공통적 인 것은 나방이나 몇 년 안에있을 수 없으며 이러한 각 변경은 현재 접근 방식보다 캐스케이드 일치에 더 많은 코드 변경을 유발합니다. –