본문 바로가기

내 코드가 그렇게 이상한가요?17

8장 강한 결합: 복잡하게 얽혀서 풀 수 없는 구조 결합도란 ‘클래스 사이의 의존도를 나타내는 지표’라고 할 수 있다. 어떤 클래스가 다른 클래스에 많이 의존하고 있는 구조를 강한 결합이라고 부르고, 강한 결합 코드는 이해하기도 힘들고, 변경하기도 굉장히 힘들다. 느슨한 결합 구조로 개선하면 코드 변경이 쉬워진다. 어떻게 느슨한 결합 구조를 만들 수 있는지 알아보자. 8.1 결합도와 책무 책무를 생각하지 않으면 어떤 문제가 발생할까? 예를 들어 온라인 쇼핑몰에 할인 기능을 추가한다고 가정해보자. 일반 할인의 사양을 아래와 같이 구현 상품 하나당 3,000원 할인 최대 200,000원까지 상품 추가 가능 class DiscountManager { List discountProducts; int totalPrice; boolean add(Product pro.. 2024. 4. 2.
7장 컬렉션: 중첩을 제거하는 구조화 테크닉 7.1 이미 존재하는 기능을 다시 구현하지 말기 아래코드는 for 반복문 내부에 if 조건문이 중첩되어 있어서 가독성이 좋지 않다. boolean hasPrisonKey = false; // items는 List 자료형 for (Item each : items) { if (each.name.equals("감옥 열쇠")) { hasPrisonKey = true; break; } } 위 기능을 아래처럼 구현할 수 있다. boolean hasPrisonKey = items.stream().anyMatch( item -> item.name.equals("감옥 열쇠") ); anyMatch 메서드는 자바 표준 라이브러리에 있는 컬렉션 전용 메서드이다. 조건을 만족하는 요소가 컬렉션 내부에 하나라도 포함되어 있으면.. 2024. 3. 31.
6장 조건 분기: 미궁처럼 복잡한 분기 처리를 무너뜨리는 방법 6.1 조건 분기가 중첩되어 낮아지는 가독성 조건 분기 중첩 예시 : RPG 게임에서 마법 발동 RPG의 전투 상황에서 플레이어가 각 멤버에게 마법을 발동하려면 여러가지 조건을 모두 통과해야한다. //살아 있는가 if (0 < member.hitPoint) { //움직일 수 있는가 if (member.canAct()) { //매직 포인트가 남아 있는가 if (magic.costMagicPoint 2024. 3. 30.
5장 응집도: 흩어져 있는 것들 5.1 static 메서드 오용 // 주문을 관리하는 클래스 class OrderManager { static int add(int moneyAmount1, int moneyAmount2) { return moneyAmount1 + moneyAmount2; } } 금액을 더하는 add 메서드는 static 메서드로 정의되어 있기 때문에 클래스의 인스턴스를 생성하지 않고도 add 메서드를 호출할 수 있다. // moneyData1, moneyData2는 데이터 클래스 moneyData1.amount = OrderManager.add(moneyData1.amount, moneyData2.amount); 이렇게 static 메서드는 데이터 클래스와 함께 사용하는 경우가 많다. 이러한 구조의 문제는 데이터는 M.. 2024. 3. 28.
4장 불변 활용하기: 안정적으로 동작하게 만들기 불변 활용하기: 안정적으로 동작하게 만들기 가변: 상태를 변경할 수 있는 것 (변수의 값을 변경하는 등) 불변: 상태를 변경할 수 없는 것 ⇒ 가변과 불변을 적절하게 설계하지 못하면 동작을 예측하기 어렵다. 가능한 한 상태가 변경되지 않도록 설계해야 한다. 이때 불변의 개념이 사용된다. 요즘 프로그래밍 트렌드는 불변!!!! 4.1 재할당 : 변수의 값을 다시 할당하는 것 (=파괴적 할당) 변수의 의미를 추측하기 어렵고 언제 어떻게 변경됐는지 추적하기가 힘들다. int damage(){ //멤버의 힘과 무기 성능을 **기본 공격력**으로 활용합니다. int **tmp** = member.power() + member.weaponAttack(); //멤버의 **속도로 공격력을 보정**합니다. **tmp** .. 2024. 3. 28.
3장 클래스 설계: 모든 것과 연결되는 설계 기반 3.1 클래스 단위로 잘 동작하도록 설계하기 클래스는 클래스 하나로도 잘 동작할 수 있도록 설계해야 한다. 또한 복잡한 초기 설정을 하지 않아도 곧바로 사용할 수 있게 만들어야 한다. 그리고 클래스를 마음대로 조작해서 클래스 전체가 고장 나는 일(버그 발생)이 없게, 최소한의 조작 방법(메서드)만 외부에 제공해야 한다. 3.1.1. 클래스의 구성요소 인스턴스 변수 메서드 잘 만들어진 클래스: 인스턴스 변수에 잘못된 값이 할당되지 않게 막고, 정상적으로 조작하는 메서드 두 가지 요소를 모두 갖춰야한다. 둘 중 하나라도 빠지면 안된다. 왜일까? 데이터 클래스는 일반적으로 인스턴스 변수를 조작하는 로직이 다른 클래스에 구현되어 있다. 심지어 초기화도, 잘못된 값으로부터 방어하기 위한 유효성 검사도 다른 클래스.. 2024. 3. 21.
2장 설계 첫걸음 (변수명) 2.1 의도를 분명히 전달할 수 있는 이름 설계하기 int d = 0; d = p1 + p2; d = d - ((d1 + d2) / 2); if (d < 0) { d = 0; } 무언가를 계산하고 있지만, 무엇을 하고 있는지 전혀 이해할 수 없다. 변수 의미 이름을 짧게 줄이면 다른 사람이 읽거나 시간이 지난 후 다시 볼 때는 이해하기 매우 어렵다. 따라서 입력할 때 아낀 시간보다 몇 배 이상의 시간이 필요할 수가 있다. 그렇기 때문에 의도를 알 수 있는 이름을 사용해야한다. int damageAmount = 0; damageAmount = playerArmPower + playerWeaponPower; // 1 damageAmount = damageAmount - ((enemyBodyDefence + .. 2024. 3. 12.
1장 잘못된 구조의 문제 깨닫기 1장 잘못된 구조의 문제 깨닫기 나쁜 구조의 폐해란 코드를 읽고 이해하는 데 시간이 오래 걸림 버그가 계속해서 발생함 나쁜 구조로 인해서 더 나쁜 구조가 만들어짐 1.1 의미를 알 수 없는 이름 좋지 않은 이름이 일으키는 악영향을 소개한다. 기술 중심 명명 : 기술 기반으로 이름을 붙이는 것 class MemoryStateManager { void changeIntValue01(int changeValue) { ... } } 일련번호 명명 : 클래스와 메서드에 번호를 붙여서 이름 짓는 것 class Class001 { void method001(); void method002(); void method003(); } 위와 같이 이름을 지으면 코드에서 어떠한 의도도 읽어 낼 수 없다. 읽고 이해하는 데 시.. 2024. 3. 11.