소프트웨어 디자인 패턴: 프로덕션 코드 작성을 통한 실용적인 학습

빠르게 변화하는 스타트업의 친환경적이지만 열정적인 개발자로서, 코드 베이스를 학습하고 프로덕션에 즉시 사용 가능한 유지 관리 가능한 코드를 작성하는 작업을 동시에 수행할 때 El Capitan을 똑바로 쳐다보는 것처럼 느껴질 수 있습니다. Rescale에서는 개발자에게 특정 기능을 구현하기 위한 소프트웨어 설계 선택에 대한 폭넓은 자유권이 부여됩니다. 최근에는 여러 작업을 수용할 수 있는 영구 클러스터를 생성하는 기능을 구현했습니다. 확장 가능하고 유지 관리가 가능하며 애플리케이션 아키텍처와 일치하는 최적의 디자인 패턴을 선택하려면 어느 정도의 사려 깊음이 필요합니다. 이 멋진 기능을 작업하면서 얻은 경험을 공유하겠습니다.
빠르게 요약하자면, Rescale 용어로 '작업'은 소프트웨어(예: 기계 학습을 위한 Tensorflow 또는 유전자 정렬 쿼리를 위한 BLAST+(Rescale이 제공하는 수많은 다른 소프트웨어 패키지 중에서))와 하드웨어 클러스터(예: AWS의 C4 인스턴스) 및 작업별 명령입니다. 영구 클러스터 기능 이전에는 일반적인 "기본" 사용 사례에서 작업이 실행된 후 클러스터가 종료되었습니다. 이제 영구 클러스터 기능을 사용하면 사용자는 정확한 요구 사항에 따라 클러스터를 구축하고, 하루 종일 여러 작업을 실행하고, 완료되면 해체할 수 있습니다.   
이 기능은 Python Django 프레임워크로 수행된 새로운 API 엔드포인트와 Angular 프레임워크로 수행된 여러 보기(UI) 변경으로 구성되었습니다. UI의 과제 중 하나는 Angular 지시문("clusterList 지시문"이라고 함)으로 캡슐화되고 아래에 표시된 클러스터 목록 보기("clusterList 보기"라고 함)를 재사용하는 방법이었습니다.
1-클러스터 재조정
이 지시어에 해당하는 컨트롤러와 템플릿이 캡슐화를 완료합니다. Angular 지시문은 HTML 템플릿, 뷰 로직 및 비즈니스 로직의 캡슐화를 통해 재사용성을 제공합니다. 이 지시문의 핵심 역할은 클러스터 목록을 렌더링하는 것이며 클러스터를 삭제하는 기능도 포함되어 있습니다. 이 보기의 컨트롤러에는 페이지 매김 기능과 자세한 정보를 위해 특정 클러스터로 이동하는 기능이 포함되어 있습니다.
다음은 하드웨어 설정 보기에서 재사용되는 ClusterList 지시문입니다(이 자체는 "hardwareSettings 지시문"이라고 함). 하드웨어 설정 보기에서 사용자는 영구 클러스터(사용자가 이전에 가동한)를 선택하거나 새 클러스터(이전 워크플로)를 생성할 수 있습니다.  

이 보기는 다음 지시문으로 구성되었습니다(간결성을 위해 속성이 제거됨).

소프트웨어 설계 결정은 ClusterList 지시문에서 영구 클러스터가 선택되었음을 hardwareSettings 보기를 담당하는 컨트롤러에 전달하는 방법에 중점을 두었습니다. hardwareSettings 컨트롤러에는 Job 개체의 하드웨어 설정을 지정하는 논리가 포함되어 있습니다. 영구 클러스터 기능이 추가되면 이러한 하드웨어 설정은 영구 클러스터 또는 새로 생성된 클러스터에서 제공됩니다.

게시-구독('pub-sub')과 종속성 주입
Angular를 사용하면 $rootscope의 $emit 및 $on 함수를 사용하여 애플리케이션 전체의 pub-sub 아키텍처를 만들 수 있습니다.

위 코드는 'clusterSelected' 주제가 포함된 메시지를 클러스터 개체와 함께 $rootscope 내의 이벤트 버스로 전송합니다. 애플리케이션의 다른 부분은 $rootscope에 삽입하고 $on으로 주제를 구독하여 이 이벤트 버스를 활용할 수 있습니다.

pub-sub 디자인 패턴은 경계(이 경우 지시문 경계)를 넘어 통신하는 우아한 방법이며, 네트워크 경계를 넘어 통신하는 데 자주 사용되는 아키텍처입니다. Angular의 구현 용이성과 타임라인에 따라 작업할 때 '그냥 이 일을 해라'라는 사고방식이 제게 적합한 디자인 패턴으로 거래를 성사시켰습니다.    
제가 선택한 또 다른 디자인 선택은 하드웨어 설정 보기에서 클러스터 목록 컨트롤러("clusterListCtrl")를 재사용하는 것이었습니다.

이 선택을 통해 하드웨어 설정 보기에 필요한 동작을 달성하기 위한 추가 기능으로 ClusterListCtrl을 확장하고 컨트롤러에 불필요한 팽창을 추가하고 컨트롤러를 지시문에 추가로 결합했습니다. 나는 이 기능의 공동 개발자이자 소프트웨어 개발 지혜를 전달하는 데 관심이 있는 노련한 개발자인 Alex Kudlick에게 내가 선택한 디자인을 제시했습니다. 우리는 pub-sub와 의존성 주입의 장점을 논의했습니다.

의존성 주입
제어 역전과 밀접한 관련이 있는 종속성 주입은 종속성 흐름이 역전되는 패턴입니다. 대조적으로, pub-sub 예제에서는 'clusterSelected' 주제를 청취하는 모든 구독자에 의해 종속성이 생성됩니다. 이는 클릭이 감지될 때 ClusterList 지시문에 의해 게시됩니다. 종속성 흐름은 소스에서 바깥쪽으로 흐르는 것입니다.
종속성 주입을 사용하면 클릭 핸들러 'on-cluster-click'이 아래와 같이 ClusterList 지시문에 속성으로 주입되거나 전달됩니다.

이 속성은 이제 ClusterList 지시문의 격리 범위에 대한 속성입니다. hardwareSettings 보기의 컨트롤러에는 $scope에 영구 클러스터가 선택될 때 처리할 논리가 포함된 $scope 함수가 포함되어 있습니다. ClusterList 지시문에 의해 클릭이 감지되면 ToggleClusterSelected 함수가 호출됩니다.
이제 의존성 주입이 포함된 ClusterList 지시문의 재사용성이 ClusterList 보기에서 ClusterList 지시문이 클릭을 처리하는 방법을 통해 설명됩니다.

ClusterList 뷰의 컨트롤러에는 클릭 핸들러가 이 뷰에서 실행될 때 호출되는 goToCluster 함수가 포함되어 있습니다. 위는 종속성 주입의 사용을 보여주며, 다양한 표현식(toggleClusterSelected 및 goToCluster 메소드)을 클릭 핸들러에 바인딩함으로써 ClusterList 지시문은 사용되는 컨텍스트에 따라 다른 동작을 가질 수 있습니다.  

학습
이벤트를 전송하는 기능을 갖춘 pub-sub 아키텍처를 통해 경계를 넘어 통신하기 위한 애플리케이션 전반은 Angular에서 우아하고 간단하게 달성할 수 있으며, 이는 또한 느슨한 결합의 이상을 충족합니다. $rootScope.$emit를 사용할 때 메시지는 Angular 애플리케이션의 상위 범위인 $rootScope를 통해 전송되었습니다. 이로 인해 애플리케이션의 서로 다른 부분(hardwareSettings 컨트롤러와 ClusterList 컨트롤러에 'clusterSelected'에 대한 구독자가 있음)의 리스너가 서로 간섭한다는 점에서 문제가 발생했습니다. 예를 들어, hardwareSettings View에서 클러스터 목록을 클릭하면 goToCluster(원하지 않음) 및 ToggleClusterSelected(원하는 동작)가 트리거됩니다. 그러나 goToCluster가 승리하여 올바른 동작이 달성되지 않았습니다. 이 문제에 대한 해결 방법은 $scope.$emit 및 $scope.$on을 사용하여 메시징을 애플리케이션 전체 $rootScope가 아닌 관련 범위로만 제한하는 것이었습니다. 그러나 여러 가입자가 동일한 메시지에 대해 작업을 수행하는 경우 부작용 및 간섭 가능성이 여전히 존재합니다.  
또 다른 단점은 'clusterSelected' 메시지를 구독하는 구성 요소인 hardwareSettings 컨트롤러 및 ClusterList 컨트롤러가 ClusterList 지시문에 대한 암시적 종속성을 형성한다는 것입니다. 미래의 개발자는 'clusterSelected' 메시지에 대한 종속성이 있는지 확인하기 위해 컨트롤러 본문을 검사해야 합니다. 구독자가 XNUMX명인 경우에는 큰 문제가 아닐 수 있지만 구독자가 추가되면 이 접근 방식은 유지 관리가 부담스러워지고 코드가 불안정해질 수 있습니다.
종속성 주입을 사용하면 종속성이 명시적이므로 개발자는 지시문 마크업의 특성을 검색하거나 지시문의 격리 범위를 검색하여 전체 종속성 목록을 얻을 수 있습니다.    

또한 지시문은 적절한 종속성과 표현식 바인딩을 지정하여 다양한 컨텍스트에서 재사용할 수 있습니다. 나는 소프트웨어 엔지니어로서 주어진 설계 선택의 결과를 생각하는 데 시간을 할당해야 하며 유지 관리성과 확장성을 고려하여 궁극적으로 명시적인 것이 암시적인 것보다 낫다는 것을 배웠습니다.

저자

  • 애덤 매켄지

    CTO로서 Adam은 HPC 및 고객 성공 팀을 관리하는 책임을 맡고 있습니다. Adam은 Boeing에서 경력을 시작하여 787년 동안 XNUMX을 작업하면서 구조 및 소프트웨어 엔지니어링 프로젝트를 관리하고 날개를 설계, 분석 및 최적화했습니다. Adam은 오레곤 주립대학교에서 우등으로 기계공학 학사학위를 취득했습니다.

비슷한 게시물