6대 설계 원칙의 5: 디미트의 법칙

7813 단어

정의


디미트 법칙(Law of Demeter, LoD)은 1987년 가을 랜홀랜드가 미국 동북대학교의 디미트라는 프로젝트 설계에서 제기한 것으로 한 대상이 다른 대상에 대해 최소한의 이해를 가져야 하기 때문에 디미트 법칙은 최소 지식 원칙(Least Knowledge Principle, LKP)이라고도 부른다.

보람


디미트 법칙의 의미는 클래스 간의 결합을 낮추는 데 있다.모든 대상이 다른 대상에 대한 이해를 최대한 줄이기 때문에 시스템의 기능 모듈 기능이 독립되고 상호 간에 의존 관계가 존재하지 않거나 거의 존재하지 않게 하기 쉽다.
특히 이 법칙은 컴퓨터 분야에만 국한된 것이 아니라 다른 분야에서도 똑같이 적용된다.예를 들어 미국인들은 우주 시스템의 설계에서 이 법칙을 채택한다.

실천하다


그렇다면 실천에서 어떻게 한 대상이 다른 대상에 대해 최소한의 이해를 가져야 하는가?만약에 우리가 한 대상을 한 사람으로 간주한다면'한 사람이 다른 사람에 대해 최소한의 이해를 가져야 한다'는 두 가지를 실현하면 충분하다.직접적인 친구와만 교류하기;2. 친구에 대한 이해를 줄인다.다음은 어떻게 이 두 가지를 할 수 있는지 상세하게 설명한다.

직접적인 친구와만 소통하다


디미트 법칙의 또 다른 영문 해석은 토크 온리 to your immediate friends(직접적인 친구와만 교류)이다.친구가 뭐예요?모든 대상은 반드시 다른 대상과 결합 관계를 가지게 되고 두 대상 간의 결합은 친구 관계가 된다.그럼 뭐가 또 직접적인 친구인가요?구성원의 변수, 방법의 입력과 출력 매개 변수에 나타나는 클래스는 바로 직접적인 친구이다.디미트의 법칙은 직접적인 친구와만 통신할 것을 요구한다.
주의: 방법체 내부에만 나타나는 클래스는 직접적인 친구가 아니다. 만약에 하나의 클래스가 직접적인 친구가 아닌 친구와 교류를 한다면 디미트의 법칙에 위반된다.
우리는 예를 들어 무엇이 친구이고 무엇이 직접적인 친구인지 설명한다.간단한 예: 선생님은 반장에게 반 전체 학우들의 수를 점검하라고 하셨다.이 예에는 모두 세 가지 종류가 있는데 그것이 바로 선생님Teacher, 반장GroupLeader과 학생Student이다.
선생님:
@interface Teacher : NSObject

// 
- (void)command:(GroupLeader *)groupLeader;

@end

@implementation Teacher

- (void)command:(GroupLeader *)groupLeader{

    // 
    NSMutableArray *students = [[NSMutableArray alloc] init];
    for (int i = 0; i < 20; i++) {
        Student *student = [[Student alloc] init];
        [students addObject:student];
    }

    // 
    [groupLeader count:students];
}

@end

반장류:
@interface GroupLeader : NSObject

// 
- (void)count:(NSArray *)students;

@end

@implementation GroupLeader

- (void)count:(NSArray *)students{
    // 
    NSLog(@" :%d",(int)students.count);
}

@end

학생:
@interface Student : NSObject

@end

@implementation Student

@end

장면을 사용하는 것도 매우 간단하다.
int main(int argc, const char * argv[]) {

    // 
    GroupLeader *groupLeader = [[GroupLeader alloc] init];

    // 
    Teacher *teacher = [[Teacher alloc] init];
    
    // 
    [teacher command:groupLeader];

    return 0;
}

이 예에서 우리Teacher에는 친구가 몇 명 있습니까?두 개, 하나는 GroupLeader이다. 왜냐하면 Teachercommand: 방법의 입력 매개 변수이기 때문이다.또 하나는 Student인데 Teachercommand: 방법체에서Student를 사용했기 때문이다.
그럼 우리 Teacher 몇 명은 직접적인 친구예요?직접적인 친구의 정의에 따르면'구성원 변수, 방법의 입력과 출력 매개 변수에 나타나는 클래스는 바로 직접적인 친구이다'는 것은 GroupLeaderTeacher의 직접적인 친구다.Teacher 방법에서 command의 수조를 만들어 비직접적인 친구Student와 교류했기 때문에 상술한 예는 디미트의 법칙을 위반했다.방법은 유형의 한 행위이다. 류는 자신의 행위가 다른 류와 의존 관계를 맺었다는 것을 모르고 이것은 허용되지 않는다. 이것은 디미트의 법칙을 심각하게 위반했다!
상술한 예가 디미트의 법칙에 부합하도록 하기 위해서 우리는 다음과 같은 수정을 할 수 있다.
수정된 GroupLeader:
@interface GroupLeader : NSObject

// , 
- (instancetype)initWithStudents:(NSArray *)students;

// 
- (void)count;

@end

@implementation GroupLeader
{
    NSArray *_students;
}

- (instancetype)initWithStudents:(NSArray *)students{

    self = [super init];
    if (self) {
        _students = students;
    }
    return self;
}

- (void)count{
    NSLog(@" :%d",(int)_students.count);
}

@end

수정된 선생님 클래스:
@interface Teacher : NSObject

// 
- (void)command:(GroupLeader *)groupLeader;

@end

@implementation Teacher

- (void)command:(GroupLeader *)groupLeader{

    [groupLeader count];
}

@end

수정된 사용 장면:
int main(int argc, const char * argv[]) {

    // 
    NSMutableArray *students = [[NSMutableArray alloc] init];
    for (int i = 0; i < 20; i++) {
        Student *student = [[Student alloc] init];
        [students addObject:student];
    }
    
    // 
    GroupLeader *groupLeader = [[GroupLeader alloc] initWithStudents:students];

    // 
    Teacher *teacher = [[Teacher alloc] init];
    
    // 
    [teacher command:groupLeader];

    return 0;
}

이렇게 수정한 후 모든 종류는 직접적인 친구와만 교류하여 클래스 간의 결합을 효과적으로 감소시켰다.

친구에 대한 이해를 줄이다


어떻게 친구에 대한 이해를 줄입니까?만약 네 친구가 수다쟁이라면, 네가 주동적으로 그에게 물어보지 않아도, 그는 네 앞에서 중얼거리며, 그의 모든 경험을 너에게 들려줄 것이다.그러니 친구에 대한 이해를 줄이려면 내성적인 친구로 바꿔주세요~ 한 종류로 바꾸면 대외 노출을 최소화하는 방법입니다.
간단한 예를 들어 노출 방법이 너무 많은 상황을 설명하다.이 예는 한 사람이 커피 머신으로 커피를 끓이는 과정을 묘사하는데 예에서 두 가지 종류만 있는데 하나는 사람이고 하나는 커피 머신이다.
먼저 커피 머신류Student, 커피 머신으로 커피를 만드는 데는 세 가지 방법이 필요하다.커피 원두 넣기;2. 물을 넣는다.3. 커피 만들기:
@interface CoffeeMachine : NSObject

// 
- (void)addCoffeeBean;

// 
- (void)addWater;

// 
- (void)makeCoffee;

@end

@implementation CoffeeMachine

- (void)addCoffeeBean{
// ...
}

- (void)addWater{
// ...
}

- (void)makeCoffee{
// ...
}

@end

그 다음에 인간CoffeeMachine, 이런 방법은 하나Man밖에 없다. 이 방법에서 커피 머신을 이용하여 커피를 만든다.
@interface Man : NSObject

// 
- (instancetype)initWithCoffeeMachine:(CoffeeMachine *)coffeeMachine;

// 
- (void)makeCoffee;

@end

@implementation Man
{
    CoffeeMachine *_coffeeMachine;
}

- (instancetype)initWithCoffeeMachine:(CoffeeMachine *)coffeeMachine{

    self = [super init];
    if (self) {
        _coffeeMachine = coffeeMachine;
    }
    return self;
}

- (void)makeCoffee{
    // 
    [_coffeeMachine addCoffeeBean];
    [_coffeeMachine addWater];
    [_coffeeMachine makeCoffee];
}

@end

장면 사용도 간단합니다.
int main(int argc, const char * argv[]) {

    // 
    CoffeeMachine *coffeeMachine = [[CoffeeMachine alloc] init];

    // 
    Man *man = [[Man alloc] initWithCoffeeMachine:coffeeMachine];

    // 
    [man makeCoffee];

    return 0;
}

이 예에서 makeCoffeeCoffeeMachine의 직접적인 친구였지만 문제ManMan에 대해 너무 많이 알고 있었다. 사실 사람들은 커피 머신이 구체적으로 커피를 만드는 과정에 대해 전혀 관심이 없었다.그래서 우리는 다음과 같은 최적화를 할 수 있다.
최적화된 커피 기계류는 하나CoffeeMachine방법만 노출하고 커피를 만드는 세 가지 구체적인 방법work,addCoffeeBean,addWater을 사유로 설정한다.
@interface CoffeeMachine : NSObject

// 
- (void)work;

@end

@implementation CoffeeMachine

- (void)work{
        // work 
    [self addCoffeeBean];
    [self addWater];
    [self makeCoffee];
}

- (void)addCoffeeBean{
// ...
}

- (void)addWater{
// ...
}

- (void)makeCoffee{
// ...
}

@end

현재makeCoffeeMan에 대한 이해는 하나CoffeeMachine방법밖에 없기 때문에work류는 다음과 같이 수정해야 한다.
@interface Man : NSObject

// 
- (instancetype)initWithCoffeeMachine:(CoffeeMachine *)coffeeMachine;

// 
- (void)makeCoffee;

@end

@implementation Man
{
    CoffeeMachine *_coffeeMachine;
}

- (instancetype)initWithCoffeeMachine:(CoffeeMachine *)coffeeMachine{

    self = [super init];
    if (self) {
        _coffeeMachine = coffeeMachine;
    }
    return self;
}

- (void)makeCoffee{
    // 
    [_coffeeMachine work];
}

@end

이렇게 수정한 후 대외 노출을 줄이는 방법Man을 통해 CoffeeMachine에 대한 이해를 줄여 이들의 결합을 낮추었다.
실천에서 직접적인 친구와만 교류하고 친구에 대한 이해를 줄이면 디미트의 법칙을 만족시킬 수 있다.그래서 우리는 디미트 법칙의 목적이 우리의 종류를 하나의'비료집'으로 바꾸는 것이라고 상상하기 어렵지 않다.'비료'는 대외적으로 노출되는 방법이 적을 수 있지만 내부의 실현은 매우 복잡할 수 있다(이 해석은 약간 억지스럽다~).집은 단지 직접적인 친구와 교류하는 데 있다.현실에서'비옥한 집'은 나쁜 뜻의 단어로 일본에서는'비옥한 집'이 이미 사회문제가 되었다.그러나 프로그램에서'비옥한 집'의 종류는 우수류의 본보기이다.

주의


디미트 법칙의 핵심 관념은 바로 유간 결합, 약한 결합이다.약한 결합이 있어야 클래스의 복용이 높아지고 클래스 변경의 위험이 낮아진다.그러나 결합은 컴퓨터의 최소 단원인 2진법의 0과 1이 아니면 모두 결합이 존재한다.따라서 실제 프로젝트에서 이 원칙을 적당히 참고하여 과유불급을 피해야 한다.

좋은 웹페이지 즐겨찾기