왜 고체가 불로장생약에 너에게 유용한가

간단한 소개


소프트웨어 개발이 어렵다.소프트웨어 구축의 어려움을 극복하는 방법 중 하나는 이른바 구조 모델을 사용하는 것이다. 예를 들어 모두가 알고 있는 SOLID원칙이다.
그러나 불로장생의 약에 이런 원칙을 적용하려면 우리는 종종 망설인다.
  • 이러한 원칙이 적용됩니까?그것들은 고전적인 OOP 언어를 가리키지 않는데, Elixir는 함수식 언어입니까?
  • 이러한 원칙이 유용합니까?이런 것들은 허구의 직사각형과 정사각형의 차원 구조의'똑똑한'서적만이 아니라 프로그래밍 실천을 가리키는 것입니까?우리의 일상적인 업무가 주로 '프레임워크'가 제공하는 미리 정의된 위치에 코드를 넣는 것일 때, 이것은 더욱 불안하다. 보기, 컨트롤러, 모델 등이다.
    본고는 진정한 OSS Elixir 라이브러리(SMPPEX)의 진실한 문제로 이 문제들에 대한 적극적인 답을 설명하는 작은 시도이다.

    SMPPEX


    SMPPEXSMPP protocol을 통해 상호작용을 하는 불로장생의 약고이다.그것은 이동통신사의 인터페이스에서 매우 환영을 받는다.
    이 프로토콜의 구조는 그리 중요하지 않다. 이것은 TCP 기반의 비동기 2진 프로토콜이라고 할 수 있다.
    SMPPEX는 TCP 연결을 처리하는 ranch을 기반으로 합니다.

    비헤이비어


    우리는 행위에 관한 몇 마디의 말을 해야 한다.비헤이비어는 인터페이스를 지정하는 Erlang 방식입니다.각 Erlang 모듈마다 callbacks을 정의할 수 있습니다.
    defmodule Foo do
      @callback bar(a :: pos_integer(), b :: String.t()) :: String.t()
    end
    
    그런 다음 모든 모듈에서 이러한 동작을 수행할 수 있습니다.
    defmodule FooImpl do
      @behavior Foo
    
      @impl true
      def bar(a, b) do
        String.duplicate(b, a)
      end
    end
    
    이후 Foo beahaviour만 있으면 이 모듈을 안전하게 사용할 수 있다.
    def do_smth(foo_impl_module) do
      ...
      s = foo_impl_module.bar(5, "abc")
      ...
    end
    
    ...
    
    do_smth(FooImpl)
    

    SMPPEX의 동작


    처리 세션에는 두 개의 주요 모듈이 있다(그림 참조).
  • SMPPEX.TransportSession . 이는 직접 TCP 소켓과 함께 작동하여 바이너리 파일을 소켓에서 프로토콜 구조(PDU)로 변환하고, 반대로 PDU를 보내고 TCP 오류를 처리한다.SMPPEX.TransportSession 비헤이비어: 보다 지능적인 PDU 처리를 위한 콜백도 정의합니다.
  • SMPPEX.Session . 그것은 SMPPEX.TransportSession 행위를 실현했다.SMPPEX.Session의 직책은 ping 진행, 시간 초과 처리, 요청 PDU와 응답 PDU 연결 등이다.SMPPEX.Session은 또한 자신의 행위를 정의했다. 사용자 정의 논리에 대한 리셋을 배치하는 데 사용된다.
  • 따라서 SMPP'서버'또는'클라이언트'(MC와 ESME)를 실현할 때 SMPPEX.Session 행위를 실현해야 한다.

    첫 번째 문제의 답안.


    Elixir에서 인터페이스를 정의하고 프로그래밍 엔티티에 대한 멀티태스킹 액세스를 허용하는 것을 보았습니다.이것은 OOP의 주요 부분이다. (일부 정의에 따르면 전체 OOP이 아니라면.)우리는 또 실천에서 이런 메커니즘을 사용하는 진실한 예가 하나 있다.
    장생불로약 코드는 믿을 만한 원칙을 통해 분석할 수 있다는 결론을 얻을 수 있다.
    그런데 이게 실제로 쓸모가 있나?

    아주 작은 인출 요청의 역사 기록


    SMPPEX는 상당히 특정 분야에 사용되는 라이브러리인데, 이것이 바로 그것이 매우 유행하지 않지만 여전히 전 세계 사용자층을 가지고 있는 이유이다.사용자는 수시로 보고서와 개선 건의를 제출한다.
    한 번은 PR을 받았는데 그 중에서 합리적인 건의가 하나 있다. 그것이 바로 telemetry 통합을 추가하는 것이다.

    Telemetry는 시스템 이벤트를 추적하고 독립적으로 처리하는 Erlang 라이브러리입니다.
    이 기능은 매우 유용한 것 같지만, 제시된 해결 방안은 나로 하여금 생각해 보게 했다.한 차례의 고려를 거친 후, 나는 내가 다른 문제를 해결하는 방법을 보고 싶다는 것을 깨달았다.

    S와 O는 고체


    뭐가 그렇게 생각해요?나는 이것이 잠재의식적으로 이 준칙을 지지하는 데 직면할 수 있는 어려움에 대한 기대라고 생각하지만, 바로 이러한 튼튼한 원칙들이 내가 이러한 느낌에 대해 이성적으로 해석하는 데 도움을 주었다.

    S


    Si in SOLID는 단일 책임 원칙을 나타냅니다.

    There should never be more than one reason for a class to change.


    분명히 우리는 수업이 없지만, 모듈이 하나 있다.'이성'의 의미를 이해하는 데는 왕왕 약간의 어려움이 있다.이것이 바로 내가 이 원칙의 또 다른 공식을 자주 사용하는 이유이다.

    There should never be more than one party interested in modifying a unit of code.


    분명히 우리는 이 원칙을 위반할 것이다. 두 가지 뚜렷한 측면이 하나의 모듈(심지어 기능)을 공유하고자 한다. 나는 전체 라이브러리의 지지자이고 팀은 이 기능을 필요로 하며 PR을 제정했다.

    O


    O는 솔리드에서 개폐 원칙을 나타냅니다.

    Software entities ... should be open for extension, but closed for modification.


    다시 말하면, 만약 우리가 새로운 기능을 추가하고 싶다면, 우리의 체계 구조는 우리가 기존의 클래스와 함수에 넣지 않고 새로운 실체를 구성하여 그것들을 이용할 수 있도록 허락해야 한다.
    분명히 우리는 이 원칙을 위반할 것이다. 기존 함수에 새로운, 상관없는 기능을 추가할 것이다.

    실제 문제


    만약 일부 이론 구조가 파괴된다면, 우리는 너무 걱정하지 말아야 할 것이다.이것이 바로 우리가 이러한 원칙이 위반될 때 나타나는 현실적인 문제를 보여줘야 하는 이유다.

    코드 소유권


    S원칙을 어기고 단일 함수나 모듈에서 관심사를 혼합하면 코드에 관심이 있는 모든 사람들에게 불편을 줄 수 있다.
    분명히 라이브러리의 관리자로서 나는 핵심이 좋은 기록, 좋은 테스트 등을 얻기를 바란다.새 코드를 받은 후에 나는 코드를 테스트하고 수정하며 심지어 코드까지 이해하기가 더욱 어려울 것이다.
    다른 한편, 이 코드가 필요한 팀은 나의 여가 시간을 기다리는 것이 아니라 가능한 한 빨리 코드를 수정하기를 바란다.

    코드 계층


    설령 이 기능이 포함될 가치가 있다 하더라도, 우리는 코드에 대해 서로 다른 '차원' 지원을 원한다.우리의'핵심'코드는 좋은 테스트를 거쳐 좋은 문서 기록을 가지고 더욱 광범위한 호환성을 가져야 한다(SMPPEX의 경우 documentationcompatibility matrix 참조).
    또한 보충 코드는 좋은 문서 기록이 없거나 새 버전의 도구와만 호환될 수 있습니다.

    의존 관계


    제안된 PR brings a new dependency:telemetry을 확인할 수 있습니다.비록 그것은 유용한 라이브러리이지만, 부가적인 의존 관계는 통상적으로 문제와 충돌을 가져올 수 있다.SMPPEX와 같은 소형 라이브러리에서도 문제입니다(예를 들어 issue 참조). 이것이 바로 Ranch에만 의존하려는 이유입니다.
    우리는 라이브러리의 사용자가 부차적인 기능 (심지어, 갈라지거나 다시 실현) 중의 충돌을 해결하고 안정적인 핵심을 사용하도록 허용하기를 희망한다.
    또한 telemetry은 여전히 0.x버전으로 사람들이 0.x고에 의존하고 싶지 않을 수도 있다.

    솔루션


    그래서 제가 제시한 해결 방안은 다음과 같습니다.

    Hello!

    Thanks for the proposal.

    But as far as I can see, the proposed solution violates the Open-closed principle. We shouldn't add orthogonal functionality to existing modules and functions.

    One may do the following not to violate the Open-closed principle. Since SMPPEX.Session implements SMPPEX.TransportSession behavior, it is possible to create a "proxy" session which

    • Implements SMPPEX.TransportSession.
    • Contains only telemetry-sending logic.
    • Passes all the handling to the encapsulated SMPPEX.Session.

    Moreover, this can be probably implemented without changing original modules at all.


    SMPPEX.TelemetrySession은 상술한'대리'TransportSession이다.
    이것은 상술한 견고한 원칙에 부합된다.
  • 새 모듈에 새 기능을 추가하는 규칙을 위반하지 않습니다.
  • 우리는 O를 위반하지 않았다. 왜냐하면 우리는 변하지 않는 낡은 실체와 새로운 실체로 구성된 기능을 확장했기 때문이다.
  • 이윤.


    잠시 후, 나는 팀이 successfully implemented이라는 방법을 시도했다는 것을 발견하고 매우 기뻤다!
    튼튼한 원칙에 따라 많은 불편을 피할 수 있다. 관리자를 기다리지 말고, 단지 몇 줄의 코드를 추가하기 위해 프로젝트를 포기하지 마라.나는 심지어 일이 진행 중인 줄도 몰랐다!

    smppex 원격 측정


    나중에 솔루션을 "배터리"로 만들었습니다. savonarola/smppex_telemetry.
    이것은 독립된 라이브러리입니다. 비교적 작은 호환성 행렬을 가지고 있으며, 자술한 파일 하나만으로도 충분합니다.그것은 핵심 라이브러리에 없는 의존항이 하나 더 있다.

    결론


    나는 이것이 매우 작지만 좋은 예라고 생각한다. SOLID가 어떻게 소프트웨어 구축과 통신 간소화를 돕는지 설명한다.따라서 우리는 두 번째 질문에 솔직하게 대답할 수 있다. 그래, 튼튼한 원칙은 실천에 응용될 수 있고 소프트웨어를 더욱 잘 구축하는 데 도움이 된다.

    좋은 웹페이지 즐겨찾기