Depend upon abstractions, not concretions

 

1️⃣ 학습 목표

: 학습 목표는 "1)의존성 이해"와, "2)의존성 문제 파악"입니다. 이를 위한 단계별 학습 순서를 확인합니다.

더보기

✔️ 1. 학습 목표

  • Step 1. 
    • Dependency, 의존성이라는 용어와 개념 이해
    • 의존(의지, 종속, 객체 생성 책임)에 대한 개념 이미지를 머리속에 그리기
    • 간단한 상속 관계를 기반으로 "의존" 이라는 개념을 이해하기
  • Step 2.
    • 객체 지향 프로그래밍(OOP)의 의존된 구조에서
      "의존성" 개념을 코드로 이해하기
  • Step 3.
    • 의존된 구조의 문제 파악하기

 

 

✔️ 2. 의존 관계와 집합 이미지

 

 

✔️ 3. 의존 관계와 의존 역전 관계


 

2️⃣ 의존성 이해

더보기

✔️ 1. 용어

 

  • Dependency: 의존, 의지, 종속
  • 依 의지할 의, 存 있을 존
  • 다른 것에 의지(依支)하여 존재(存在)함.

 

 

✔️ 2. 상속 관계에서 의존 관계 의미 이해하기

 

  • 상속받은 자식 객체는, 부모 객체의 속성을 가지고 있습니다.
    부모 객체의 속성 없이 존재할 수 없습니다.
  • 이를 하위 객체인 Programmer, Dancer, Dog, Iguana 등의 객체가 "상위 객체에 의존한다"고 표현합니다. 
  • 화살표의 방향은 의존하고 있는 방향입니다.

 

✔️ 3. 예제 - 간단한 상속관계

 

📁 3.1 부모 클래스 - Person 

// Person 클래스: 부모 클래스 (상위 클래스)
// 공통 속성(Name)과 메서드(Hello)를 정의
public class Person
{
    public string Name { get; set; }

    public void Hello()
    {
        Console.WriteLine($"안녕하세요, 저는 {Name}입니다.");
    }
}

Person 클래스는, Name이라는 데이터를 다루는 필드와, Hello( )라는 로직을 맴버로 갖습니다. 

 

📁 3.2 자식 클래스 - Programmer, Dancer, singer 

// Programmer 클래스: Person 상속 (하위 클래스)
// → Name 속성과 Introduce 메서드를 상위 클래스(Person)로부터 상속받아 의존
public class Programmer : Person
{
    public void Code()
    {
        Console.WriteLine($"{Name}가 코딩을 합니다.");
    }
}

Programmer 클래스는, Code( )라는 로직만을 맴버로 갖습니다.

하지만 Person 클래스를 상속받았기 때문에, Name 필드와, Hello( ) 로직도 맴버로 갖습니다. 

public class Dancer : Person
{
    public void Dance()
    {
        Console.WriteLine($"{Name}가 춤을 춥니다.");
    }
}
public class Singer : Person
{
    public void Sing()
    {
        Console.WriteLine($"{Name}가 노래를 부릅니다.");
    }
}

 


✔️
4. 예제 - 간단한 상속 관계에서 알아보는 의존 개념

// 메인 실행 클래스
class Program
{
    static void Main()
    {
        Programmer programmer = new Programmer { Name = "홍길동" };
        Dancer dancer = new Dancer { Name = "김영희" };
        Singer singer = new Singer { Name = "박철수" };

        // 상위 클래스의 Introduce 메서드를 호출
        programmer.Introduce();
        programmer.Code();

        dancer.Introduce();
        dancer.Dance();

        singer.Introduce();
        singer.Sing();
    }
}
// 출력 예시
안녕하세요, 저는 홍길동입니다.
홍길동가 코딩을 합니다.

안녕하세요, 저는 김영희입니다.
김영희가 춤을 춥니다.

안녕하세요, 저는 박철수입니다.
박철수가 노래를 부릅니다.

(상위 클래스) Person 은 Name 속성과 Introduce 메서드를 (하위 클래스) Programmer, Dancer, Singer 에 제공합니다.

>> 하위 클래스는 상위 클래스의 기능을 "상속"받아 "확장"되었으므로, 상위 객체의 속성없지 존재 할 수 없음 → 종속(dependency) 관계

>> 상위 클래스 변경 시 하위 클래스에 영향 → 상속 관계의 의존성을 보여주는 기본 구조
>> 객체지향에서 "is-a" 관계를 표현 → Programmer is a Person, Dancer is a Person


 

3️⃣ 의존 관계

더보기

✔️ 1. 의존 관계 (Python 참고 영상 링크)

- Cat, Dog 객체

class Cat:
    def speak(self):
        print("Meow")
class Dog:
    def speak(self):
        print("bark")

 

- Zoo 객체

class Zoo:
    def __init__(self):
        self.cat = Cat()
        self.dog = Dog()
  • Zoo 클래스가 Cat 클래스 생성 책임을 가짐
  • Cat 클래스 코드 변경 시 Zoo도 영향을 받음
  • 다른 동물 추가 시 Zoo 내부 코드 수정 필요
  • 강한 결합 (Tight Coupling)

 

 

- 실행

zoo = Zoo()
zoo.cat.speak()
zoo.dog.speak()

 

- Zoo 객체는, Cat, Dog 객체에 의존된 관계다.

- Zoo 객체는, Cat, Dog 객체 없이 존재할 수 없으며, 

Zoo 객체는, Cat, Dog 객체가 수정되거나 Sheep 객체가 확장 될 때, 같이 수정할 필요가 있다.

 

 

✔️ 2.  예시 - 의존된 관계에 기능 확장하는 경우

 


✔️
3.  예시 - 의존된 관계에 기능 확장하는 경우, 소스코드

class Cat:
    def speak(self):
        print("Meow")

class Dog:
    def speak(self):
        print("bark")
# 추가된다고 가정합니다.
class Sheep:
    def speak(self):
        print("Baaa")

class Cow:
    def speak(self):
        print("Moo")
# 가장 먼저, 
# 의존된 관계에서는 Zoo 객체가 직접 수정되어야 한다.
class Zoo:
    def __init__(self):
        self.cat = Cat()
        self.dog = Dog()
        self.sheep = Sheep()
        self.cow = Cow()    

zoo = Zoo()
zoo.cat.speak()
zoo.dog.speak()
zoo.sheep.speak()
zoo.cow.speak()

- 프로그래밍 관점에서, 객체가 의존된 관계에서  어떤 문제가 발생하는지 확인해 봅시다.


 

4️⃣ 의존 관계 - 문제 파악하기

: 프로그래밍은, 개발자 입장에서 프로그램을 구현하는 관점에서 생각해보아야 한다.

더보기

✔️ 1. 가정

 

위 종속된 객체 구조 예시에서, 개발자 2명이 각각 구현했다고 가정합니다.

개발자A는 Sheep 객체를, 개발자B는 Cow 객체를 각각 구현한다면, 어떤 문제가 발생하는지 확인해봅시다.

 

 

✔️ 2. 개발자A, " Sheep 객체" 구현 후, 기존 코드 적용 작업

 

✔️  3. 개발자B, "Cow 객체" 구현 후, 기존 코드 적용 작업

 

✔️ 4. 개발자A, 개발자B 작업 결과 서로 다른 코드로 구현되어 통합 작업 필요

 

 

✔️ 5. 팀원  3명으로 의존 관계의 소스코드 구조 구현후 통합해보시면, 실감하실 수 있습니다.

 

- 전사, 마법사, 궁수 클래스를 각각 구현하고, 통합 테스트를 진행해보세요

 

 

✔️ 6. 여러명의 팀단위 구현이 아니더라도, 내 코드가 위 구조와 같다면, 동일 업무 로드가 발생합니다. 

 

 

✔️ 7. 문제를 파악했으니, 문제를 해결하기 위한 기술을 배울 차례입니다.



5️⃣ 의존 관계 - 문제 파악하기 (C# 소스코드 버전)

: 의존이란, 객체 생성 책임 구현 구조 문제다.

더보기

Cat, Dog 객체

class Cat
{
    public void Speak()
    {
        Console.WriteLine("Meow");
    }
}
class Dog
{
    public void Speak()
    {
        Console.WriteLine("Bark");
    }
}

 

(확장) Sheep 객체

class Sheep
{
    public void Speak()
    {
        Console.WriteLine("Baaa");
    }
}

 

Zoo 객체

// Zoo 클래스가 구체 클래스에 직접 의존함
class Zoo
{
    private List<object> animals = new List<object>();

    public void AddCat()
    {
        animals.Add(new Cat());
    }

    public void AddDog()
    {
        animals.Add(new Dog());
    }

    public void AddSheep()
    {
        animals.Add(new Sheep());
    }

    public void Run()
    {
        foreach (var animal in animals)
        {
            if (animal is Cat cat)
                cat.Speak();
            else if (animal is Dog dog)
                dog.Speak();
            else if (animal is Sheep sheep)
                sheep.Speak();
        }
    }
}

 

실행

class Program
{
    static void Main()
    {
        Zoo zoo = new Zoo();
        zoo.AddCat();
        zoo.AddDog();
        zoo.AddSheep();

        zoo.Run();
    }
}