# 클래스

### **단일 책임 원칙(SRP) 지키기**

* 하나의 클래스는 하나의 책임만 갖도록 설계한다.
* 클래스도 작아야 가독성과 유지보수 측면에 이점이 있다.

```swift
// as-is
class Store {                 // Store 클래스가 많은 역할을 혼자 수행한다.
    func cummunicateUser() { }
    func manageProducts() { }
    func manageMoney() { }
}
```

```swift
// to-be
class CounterManager {
    func communicateUser() { }
}

class ProductManager {
    func manageProducts() { }
}

class Owner {
    func manageMoney() { }
}

class Store {
    let counterManager: CounterManager
    let productManager: ProductManater
    let owner: Owner

    func sellProduct() {
        counterManager.communicateUser()
        // code
    }
    // code...
}
```

### **응집도를 높이자.**

* 응집도는 클래스의 변수와 메서드가 얼마나 유기적으로 엮여있는지를 나타내는 지표이다.
  * 응집도가 높을수록 클래스의 메서드는 인스턴스 변수를 많이 사용한다.
  * 응집도가 낮을수록 클래스의 메서드는 인ㅅ턴스 변수를 적게 사용하거나 사용하지 않는다.

```swift
// as-is

class LowCohension {
    var a: Int
    var b: Int
    var c: Int

    func processA() {
        print(self.a)
    }

    func processB() {
        print(self.b)
    }

    func processC() {
        print(self.c)
    }
}
```

```swift
// to-be
class HighCohension {
    var abc: ABC

    func processA() {
        print(self.abc.processA())
    }

    func procesB() {
        print(self.abc.processB())

    func procesC() {
        print(self.abc.processC())
}
```

```swift
// 실제 코드, element인스턴스가 3개의 메서드에서 모두 사용되고 있다.
class Stack { 
    var elements = [Int]()

    func size() -> Int {
        return elements.count
    }

    func push(_ element: Int) {
        elements.append(element)
    }

    func pop() -> Int? {
        guard !elements.isEmpty else { return nil }
        return elements.removeLast()
    }
}
```

***

### **변경하기 쉽게 만들자 (open closed)**

* 다형성과 연결되는 부분이다.
* 새 기능을 수정하거나 기존 기능을 변경할 때, 코드의 변경으 최소화하는 것이 중요하다.
* 일반적으로 클래스(객체)는 구현과 추상으로 나뉜다.
  * 구현(Concrete) : 실제 동작하는 구체적 코드
  * 추상 (Abstract) : 구체적인 기능을 개념화한 코드
* 변경하기 쉽게 설계하기 위해서, 추상화를 통해 구체 클래스에 의존하지 않고, 추상 클래스에 의존하도록 코드를 작성하는 것이 중요하다.

  ```swift
  // as-is
  class Developer {
      func coding() {
          print("코딩을 합니다")
      }
  }

  class Designer {
      func design() {
          print("디자인을 합니다")
      }
  }

  class Analyst {
      func analyze() {
          print("분석을 합니다")
      }
  }

  class Company {
      var employees = [Employee]

      func makeWokr() {
          for employee in employess {
              switch employee {
              case .developer:
                  employee.coding()
              case .designer:
                  employee.disign()
              case .analyst:
                  employee.analyze()
              }
          }
      }
  }
  ```

  ```swift
  // to-be
  protocol Employee {
      func work()
  }

  class Company {
      var employees = [Employee]

      func makeWork() {
          for employee in employees {
              employee.work()
          }
      }
  }

  class Developer: Employee {
      func work() {
          print("coding")
      }
  }

  class Designer: Employee {
      func work() {
          print("design")
      }
  }
  ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sois-organization.gitbook.io/today-i-learned/clean-code/04..md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
