Loosely coupled objects

Garam·2023년 11월 16일
0

The Odin Project

목록 보기
13/14

Translated from: https://web.archive.org/web/20200810210808/https://medium.com/@alexcastrounis/how-to-write-highly-scalable-and-maintainable-javascript-coupling-c860787dbdd4


Coupling

Coupling은 한 모듈과 다른 모듈이 직접적으로 연결됨으로써 일어난다.

이 챕터는 음식 배달 앱을 만든다는 전제하에 진행된다. 사용자가 주문을 하면, 앱은 주문을 만들어낸 후 사용자에게 예상 배달 시간을 전달한다. 사용자는 배달 상태를 확인하거나 주문을 취소할 수 있다.

이 앱을 모듈을 활용해 만들어본다면, 주문을 하는 모듈과 배달을 관리하는 모듈로 나눌 수 있다. 주문 관리 모듈은 주문을 생성하고, 읽어내고, 갱신하고, 삭제하는 기능을 가질 것이고 배달 관리 모듈은 배달 시간을 추정하고, 배달을 시작하고, 완성하는 등의 기능을 가질 것이다.

Example: Create Order

// Order module definition
var orderModule = (function() {
    var module = {},
        deliveries = myApp.deliveryModule;

    module.createOrder = function(orderData) {
        var orderResult;

        orderResult = // Code to actually create the order
        orderResult.estimatedDeliveryTime = 
        deliveries.getDeliveryTime(orderData);

        return orderResult;
    };

    return module;
})();

위에서 주문 모듈과 배달 모듈은 서로 긴밀하게 Coupling 되어있다. 주문 모듈이 예상 배달 시간을 가져오기 위해서는 배달 모듈과 연결이 되어있어야 하며, 모듈의 적절한 API를 불러와야 한다.

유지/보수가 쉽고 유연한 코드를 작성하기 위해서는 긴밀한 커플링을 피해야 한다. 각 모듈은 언제든 삭제가 가능해야 하며, 코드 재사용도 용이해야 한다.

만약 위 코드에서 예상 배달 시간을 가져오는 기능이 잘못되었다면, 이는 주문 프로세스를 완성하는 기능을 손상시키거나, 최악의 상황에서는 앱 전체를 망가뜨릴 수도 있다. 그러나 바람직한 방향은 한 기능에 오류가 있더라도 나머지 기능들과 앱은 그대로 작동하게끔 하는 것이다.



Patterns to Reduce Coupling

커플링의 긴밀함을 낮추기 위해서는 관찰자 패턴이라 불리우는 것의 여러 변형을 사용할 수 있다.그 변형 중 하나는 Pub/Sub 혹은 Publish/Subscribe 패턴이다.

어떤 경우에서는 관찰자가 자기 자신을 Event emitter에 직접적으로 register하는데 이는 어떠한 이벤트가 일어날때 마다 알림을 받기 위해서다. 이 접근법의 단점은 관찰자가 이벤트 에미터 객체와 이벤트에 대해 "알아야" 한다는 것이다. (= 연결이 되어있어야 한다)

그러나 이보다 나은 방법이 존재한다. 중재자 객체(Mediator object)를 보유한 다양한Pub/Sub 패턴을 통해 모듈간의 커플링을 줄일 수 있다. 중재자 객체는 publisher를 subscriber로 부터 고립시키는 역할을 한다.

Addy Osmani는 중재자를 관제탑에 비유함으로써 중재자에 대해 훌륭한 분석을 해냈다. 항공기는 절대 자기들끼리 교신하지 않는다. 그 대신 관제탑으로부터 모든 정보를 수신/제공하며, 따라서 관제탑 없이는 서로의 정보를 알 수 없다.

Pub/Sub 패턴을 적용한 라이브러리는 다양한데, 우리는 그 중에서 Morgan Roderick이 만든 PubSubJS를 사용할 것이다. 이 라이브러리는 모듈이 publish하거나 subscribe할 수 있는 topic에 기초한 것으로, 모듈은 필요할 때 토픽으로부터 unsubscribe할 수 있다.



Example: Estimated delivery time using Pub/Sub pattern

document.addEventListener("DOMContentLoaded", function(event) {
    var orderModule = (function() {
        var orders = {},
            EST_DELIVERY = 'current estimated delivery time',
            estimatedDeliveryTime;

        PubSub.subscribe(EST_DELIVERY, function(msg, data) {
            console.log(msg);
            estimatedDeliveryTime = data;
        });

        return orders;
    })();

    var deliveryModule = (function() {
        var deliveries = {},
            EST_DELIVERY = 'current estimated delivery time';

        deliveries.getEstimatedDeliveryTime = function() {
            var estimatedDeliveryTime = 1; 
          // Hard-coded to 1 hour, but likely an API call.

            PubSub.publish(EST_DELIVERY, estimatedDeliveryTime);
        };

        return deliveries;
    })();

    deliveryModule.getEstimatedDeliveryTime();
});

위의 코드에서는EST_DELIVERY라는 상수를 통해 'current estimated delivery time'이라 불리우는 토픽을 정의했다. 모듈들은 서로 연결되지 않은 상태로 이 토픽에 대해 publish 혹은 subscribe할 수 있다. 해당 코드에서는 delivery 모듈의 getEstimatedDeliveryTime이라는 메소드를 직접 호출하고 있다.

이 메소드를 호출함으로써 delivery 모듈은 현재 예상 배달시간을 가져온 후 EST_DELIVERY라는 토픽에 publish할 수 있다. 따라서 이 토픽을 구독하고 있는 구독자들은 배달시간이 업데이트된 후 알림을 받을 수 있게 된다.

order 모듈은 이 토픽에 대해 구독하고 있고, 따라서 주문이 들어올 때 마다 언제나 배달 예상시간에 관한 최신 업데이트를 받게될 것이다. delivery 모듈과 연결되지 않은 채로 말이다.



0개의 댓글