diff --git "a/\353\202\264 \354\275\224\353\223\234\352\260\200 \352\267\270\353\240\207\352\262\214 \354\235\264\354\203\201\355\225\234\352\260\200\354\232\224/03. \355\201\264\353\236\230\354\212\244 \354\204\244\352\263\204: \353\252\250\353\223\240 \352\262\203\352\263\274 \354\227\260\352\262\260\353\220\230\353\212\224 \354\204\244\352\263\204 \352\270\260\353\260\230.md" "b/\353\202\264 \354\275\224\353\223\234\352\260\200 \352\267\270\353\240\207\352\262\214 \354\235\264\354\203\201\355\225\234\352\260\200\354\232\224/03. \355\201\264\353\236\230\354\212\244 \354\204\244\352\263\204: \353\252\250\353\223\240 \352\262\203\352\263\274 \354\227\260\352\262\260\353\220\230\353\212\224 \354\204\244\352\263\204 \352\270\260\353\260\230.md" index ecd9171..861990e 100644 --- "a/\353\202\264 \354\275\224\353\223\234\352\260\200 \352\267\270\353\240\207\352\262\214 \354\235\264\354\203\201\355\225\234\352\260\200\354\232\224/03. \355\201\264\353\236\230\354\212\244 \354\204\244\352\263\204: \353\252\250\353\223\240 \352\262\203\352\263\274 \354\227\260\352\262\260\353\220\230\353\212\224 \354\204\244\352\263\204 \352\270\260\353\260\230.md" +++ "b/\353\202\264 \354\275\224\353\223\234\352\260\200 \352\267\270\353\240\207\352\262\214 \354\235\264\354\203\201\355\225\234\352\260\200\354\232\224/03. \355\201\264\353\236\230\354\212\244 \354\204\244\352\263\204: \353\252\250\353\223\240 \352\262\203\352\263\274 \354\227\260\352\262\260\353\220\230\353\212\224 \354\204\244\352\263\204 \352\270\260\353\260\230.md" @@ -1,2 +1,153 @@ # 03. 클래스 설계: 모든 것과 연결되는 설계 기반 +# 📌 Contents + +### 📌 클래스 단위로 잘 동작하도록 설계하기 + +가장 중요한 것은 '클래스 단위로도 잘 동작하게 설계해야 한다'는 접근 방법 + +- 클래스는 클래스 하나로도 잘 동작할 수 있게 설계해야 함 +- 복잡한 초기 설정을 하지 않아도 곧바로 사용할 수 있게 만들어야 함 +- 클래스를 마음대로 조작해서 클래스 전체가 고장나는 일이 없게, 최소한의 조작 방법만 외부에 제공해야 함 + +
+ +- 클래스의 구성 요소 + - 인스턴스 변수 + - 메서드 +- 잘 만들어진 클래스의 구성 요소 + - 인스턴스 변수 + - 인스턴스 변수에 잘못된 값이 할당되지 않게 막고, 정상적으로 조작하는 메서드 +- 이렇게 클래스가 인스턴스 변수와 메서드를 구성 요소로 가져야 하는 이유는 데이터 클래스에서 일어나는 폐해들을 생각해보면 알 수 있음 + +
+ +- 데이터 클래스는 일반적으로 인스턴스 변수를 조작하는 로직이 다른 클래스에 구현되어 있음 +- 따라서 연관성을 알아채기 어려워서 코드가 중복될 수 있고, 수정하다가 중복 코드 중 일부를 그대로 둘 수 있고, 가독성을 낮춤 +- 또한 인스턴스를 생성하더라도 인스턴스 변수들은 아직 유효하지 않은 상태이므로, 초기화를 따로 해줘야 하는데, 데이터 클래스는 초기화 작업을 하는 코드조차 다른 클래스에 구현되어 있음 +- 인스턴스 변수에 값을 잘못 넣을수도 있는데, 데이터 클래스를 잘못된 값으로부터 방어하기 위한 유효성 검사도 다른 클래스에 구현되어 있음 +- 즉, 데이터 클래스는 다른 클래스가 여러 가지를 준비해 줘야만 잘 작동하고, 혼자서는 아무것도 할 수 없는 미성숙한 클래스 + +> ####info::Note +> +> '따로 초기화하지 않거나 사전 준비를 하지 않으면 사용할 수 없는' 클래스와 메서드가 있다면, 누가 사용하고 싶을까요? +> 자신의 몸은 자신이 지켜야 합니다. 클래스 스스로 자기 방어 임무를 수행할 수 있어야 소프트웨어 품질을 높이는 데 도움이 됩니다. +> 소프트웨어 구성 부품이라 할 수 있는 클래스 하나하나의 품질이 뛰어나야, 소프트웨어 전체의 품질이 향상됩니다. +> 데이터 클래스는 모든 것을 다른 클래스에 맡겨야 했기 때문에 악마들을 불러들였습니다. 그럼 어떻게 해야 할까요? 굉장히 간단합니다. +> 데이터 클래스에 자기 방어 임무를 부여해서, 다른 클래스에 맡기던 일을 스스로 할 수 있게 설계하면 됩니다. + +### 📌 성숙한 클래스로 성장시키는 설계 기법 + +#### 생성자로 확실하게 정상적인 값 설정하기 + +- 데이터 클래스는 디폴트 생성자(매개변수 없는 생성자)를 사용해서 인스턴스를 생성한 뒤, 인스턴스 변수에 따로 값을 할당해서 초기화 +- 이는 '로우 데이터 객체'로서 '초기화 되지 않은 상태'를 유발하는 클래스 구조 +- 이를 방지하기 위해 적절한 초기화 로직을 생성자에 구현하기 (생성자에서 초기값을 매개변수로 받아 초기화) +- 또한 잘못된 값으로 초기화 되지 않도록 유효성 검사를 생성자 내부에 정의하기 + - 처리 범위를 벗어나는 조건을 메서드 가장 앞 부분에서 확인하는 코드를 '가드'라고 부름 + - 가드를 사용해 유효성 검사를 하면 불필요한 요소를 메서드 앞부분에서 제외할 수 있으므로 이어지는 로직이 간단해짐 + +#### 계산 로직도 데이터를 가진 쪽에 구현하기 + +- '데이터'와 '데이터를 조작하는 로직'이 분리되어 있는 구조를 '응집도가 낮은 구조'라고 함 +- 응집도가 낮은 구조에서는 여러 가지 문제가 발생하는데, 이를 막으려면 스스로 일을 하는 성숙한 클래스를 만들어야 함 + +#### 불변 변수로 만들어서 예상하지 못한 동작 막기 + +- 인스턴스 변수를 변경하는 코드는 이해하기 어려움. +- 변수의 값이 계속 바뀌면, 값이 언제 변경되었는지, 지금 값은 무엇인지 계속 신경써야 함 +- 코드를 수정하다 '예상치 못한 부수 효과'가 쉽게 발생함 +- 이를 막기 위해 인스턴스 변수를 값을 한 번 할당하면 다시는 바꿀 수 없는 불변 변수로 만들기 -> final 수식자 사용 (Java) + +#### 변경하고 싶다면 새로운 인스턴스 만들기 + +- 불변이면 아예 변경을 못한다고 생각할 수 있음 +- 변경을 할 때는 인스턴스 변수의 내용을 변경하는 것이 아닌, 변경된 값을 가진 새로운 인스턴스를 만들어서 사용하면 됨 + +#### 메서드 매개변수와 지역 변수도 불변으로 만들기 + +- 값이 중간에 바뀌면, 값의 변화를 추적하기 힘들기 때문에 버그를 발생시키기도 함 +- 기본적으로 매개변수는 변경하지 않는 것이 좋음 (메서드와 생성자의 매개변수도 마찬가지) +- 지역 변수도 중간에 값을 변경하면, 값의 의미가 바뀔 수 있음 +- 매개변수와 지역 변수 모두 final을 붙여 불변으로 만들수 있음 (Java) + +#### 엉뚱한 값을 전달하지 않도록 하기 + +- int, string처럼 프로그래밍 언어가 표준적으로 제공하는 자료형을 기본 자료형이라고 함 +- 기본 자료형 위주로 사용하면, 의미가 다른 값이 여러 개 있어도 모두 int 자료형이나 string 자료형으로 정의하기 쉬움 +- 독자적인 자료형을 사용하면, 의미가 다른 값을 전달할 경우 컴파일 오류가 발생할 수 있음 + +#### 의미 없는 메서드 추가하지 않기 + +- 나중에 필요할 줄 알고, 시스템 사양에 필요하지 않은 메서드를 '선의'로 추가했다면, +- 이후에 누군가 무심코 사용했을 때 버그가 될 수 있음 +- 시스템 사양에 필요한 메서드만 정의하자 + +### 📌 악마 퇴치 효과 검토하기 + +- 위에서 언급한 방법들처럼 인스턴스 변수를 중심으로, 인스턴스 변수가 잘못된 상태에 빠지지 않게 설계하면 악마를 퇴치할 수 있음 +- 클래스 설계란 인스턴스 변수가 잘못된 상태에 빠지지 않게 하기 위한 구조를 만드는 것 +- 같은 데이터라고 해도 메서드 매개변수, 지역 변수, static 변수로 설계했다면 악마의 공격을 방어할 수 없음 + - 인스턴스 변수이기 때문에 방어할 수 있는 것임 + +
+ +- 관련된 로직이 한 곳에 모여 있는 구조는 응집도가 높은 구조라고 함 +- '데이터'와 '그 데이터를 조작하는 로직'을 하나의 클래스로 묶고, 필요한 메서드만 외부에 공개하는 것을 `캡슐화`라고 함 + +### 📌 프로그램 구조의 문제 해결에 도움을 주는 디자인 패턴 + +- 응집도가 높은 구조로 만들거나, 잘못된 상태로부터 프로그램을 방어하는 등 프로그램의 구조를 개선하는 설계 방법을 `디자인 패턴`이라고 함 +- 위에서 언급한 방법들은 두 가지 디자인 패턴에 대한 내용임 + +#### 완전 생성자 패턴 + +- 완전 생성자는 잘못된 상태로부터 클래스를 보호하기 위한 디자인 패턴 +- 인스턴스 변수를 모두 초기화해야만 객체를 생성할 수 있게, 매개변수를 가진 생성자를 만들기 +- 생성자 내부에서는 가드를 사용해서 잘못된 값이 들어오지 않게 만들기 +- 인스턴스 변수를 불변 변수로 만들면, 생성 후에도 잘못된 상태로부터 방어할 수 있음 + +#### 값 객체 패턴 + +- 값을 클래스(자료형)로 나타내는 디자인 패턴 +- 애플리케이션에서 사용하는 금액, 날짜, 주문 수, 전화번호 등 다양한 값을 값 객체로 만들 수 있음 +- 이러한 값을 값 객체로 만들어서 사용하면, 각각의 값과 로직을 응집도가 높은 구조로 만들 수 있음 +- 값 객체를 사용하면 의도하지 않게 다른 값이 섞이는 상황을 원천적으로 차단할 수 있음 + +
+ +- 값 객체와 완전 생성자는 얻을 수 있는 효과가 거의 비슷하므로, 일반적으로 함께 사용함 +- '값 객체 + 완전 생성자'는 객체지향 설계에서 폭넓게 사용되는 기법임 +- '값 객체 + 완전 생성자'를 활용해서 설계하면, 제약과 의도를 자료형으로 표현할 수 있으며, 안전한 코드를 작성할 수 있음 +- 애플리케이션에서 다루는 값을 값 객체로 만들어 활용하면, 여러 악마를 퇴치할 수 있음 + +# ❓ Questions + +### ❓ 자바스크립트에서도 인스턴스 변수와 매개변수를 불변으로 만들 수 있을까? + +- 자바에서는 변수를 불변으로 만들기 위해 변수 앞에 final을 붙여준다고 한다. +- 자바스크립트는 애초에 변수를 선언할때 타입을 이용해 선언하는 것이 아니라 const, let을 이용하여 선언해 준다. +- 여기서 const로 선언한 변수는 불변이므로 final과 비슷하다고 볼 수 있다. +- 하지만 이 const는 클래스의 인스턴스 변수나 매개변수 앞에 붙이지 않는다. +- 자바스크립트에서 클래스의 인스턴스 변수를 선언할 때 `this.{변수명}`을 이용한다. +- 클래스의 필드에서는 const나 let을 이용할 수 가 없다. +- 생성자 내부에서는 이용가능하지만 const나 let을 이용하면 생성자에서만 사용이 가능한 지역변수가 되고, 다른 메서드들에서는 사용할 수가 없다. +- 그럼 자바스크립트에서는 인스턴스 변수를 불변으로 만들 수 없는 것일까? + - 어떻게 자바스크립트에서 클래스의 인스턴스 변수를 불변으로 만들까 찾아보았지만 별다른 방법이 없는 것 같다. + - 그래서 자바스크립트에서 클래스를 이용할 때는 인스턴스 값을 직접 변하지 않게 하기 위해 인스턴스 변수를 private으로 선언해 클래스 외부에서는 아예 접근을 못하게하는 것이 최선의 방법인 것 같다. + - 클래스 내부에서 변하게 하는 것은 막지 못하는것 같다. +- 매개변수 또한 앞에 const를 붙이지 않기 때문에 불변으로 만드는 방법은 딱히 없는 것 같다. + +
+ +- c++도 궁금해서 찾아보았는데, final과 비슷한 역할로 변수를 선언할 때 앞에 const를 붙여주면 불변 변수가 된다고 한다. +- 자바의 final에는 상속과 관련된 기능도 있기 때문에 완전히 같지는 않다고 하지만, 변수를 불변으로 만들어 준다는 점은 같다. + +### ❓ 자바스크립트에서 값 객체 패턴을 사용할 수 있을까? + +- 자바스크립트는 동적으로 타입이 정해지는 동적 언이이다. +- 따라서 변수를 선언할 때 타입을 정해주지 않는다. +- 자바스크립트에서는 값 객체 패턴을 사용할 수 없다고 생각한다. +- 하지만 타입스크립트를 사용한다면, 값 객체 패턴과 비슷하게 코드를 작성할 수 있다고 생각한다. +- 타입스크립트에서는 number, string 등의 기본 타입 말고도 커스텀 타입을 만들어 사용할 수 있다. +- 이를 활용하면 값 객체 패턴과 비슷하게 코드를 작성할 수 있을 것 같다.