블로그

겸손한 북극곰

[워밍업-백엔드3기] ReadableCode 2주차 회고

ReadableCode 를 완강했다.실습 과제로 마무리하며, 클린 코드는 많이 보고 연습하며 습득해야할 필요성을 느꼈다. 🔢 클린코드의 두번째 학습Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈2주차 새롭게 배운 내용일급 컬렉션 단 하나의 컬렉션 필드를 가지며, 책임을 새로 가질 수 있는 객체이다.Enum상태와 행위를 함께 관리할 수 있는 추상화된 객체이다.Early Return 과 부정문 관리부정문은 두번의 사고를 거쳐야 한다.else if 는 이전 과정을 모두 기억해야 하는 장기 사고적인 부분이다.예외 관리예외는 비싸다. 예외는 개발자를 위한 정보이다.문맥을 활용하여 의도를 전달하자메서드의 순서, 패키지 또한 의도이다.Optional 을 조심해서 사용하자. 클린 코드 사고를 기반으로 결정하는 코드 센스 능력을 기르자   🤔 2주차 회고리팩토링 실습을 진행하며, 머리로 이해한 개념을 직접 적용하는 것의 어려움을 느꼈다.마치 악기를 배우듯이 꾸준히 내용을 확인하고 적용하며 습득해야하는 습관 과제 같았다. 미션 제출과 중간 라이브를 통해 다른 사람들의 리팩토링을 보는 시간을 가질 수 있었다.동일한 바탕으로 다양한 접근 방식을 확인할 수 있었다.코드에 정답은 없다. 클린 코드를 만들 수 있는 센스를 몸에 익히고 큰 그림을 보며 코드를 짜는 능력을 길러야겠다.'완벽한 코드는 없다. 그 당시의 최선일 뿐!'클린 코드 학습을 고민하는 분이 있다면 박우빈님 강의를 추천한다!   

백엔드클린코드ReadableCode박우빈님강의워밍업클럽

[인프런 워밍업 클럽 3기 - 백엔드] 발자국 1주차

일주일 간 학습내용 정리 섹션 2. 추상추상 & 구체적절한 추상화 = 해당 도메인의 문맥안에서, 중요한 핵심개념만 남겨서 표현하는 것이름 짓기 - 단순하면서 중요한 고도의 추상적 사고행위추상적 사고 표현하고자 하는 구체에서 중요한 핵심개념만을 추출하여 잘 드러내는 표현우리 도메인의 문맥안에서 이해되는 용어이름 짓기 단수와 복수 구분하기 - 끝에 '-(e)s' 붙이기과도하게 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기 - 자주 사용되는 단어,개념 습득하기  메서드와 추상화 - 잘 쓰여진 코드라면, 한 메서드의 주제는 하나이다추상화 레벨은 주변과 동등하게 섹션 3. 논리, 사고의 흐름Early return 으로 else,case 의 사용을 지양하자공백 라인을 대하는 자세사고의 depth 줄이기 '무조건 1 depth로 만들기' 가 아닌 추상화를 통한 사고 과정의 최소 depth로 줄이기사용할 변수는 가깝게 선언 Tip - 메소드를 리팩토링 한다면 메소드를 복사해 복사된 메소드2를 리팩토링 한 후에 메소드2를 사용되는 부분마다 적용시켜 에러를 점검하고 기존메서드 삭제후 메서드2의 이름을 변경해준다.(컴파일 에러 등 확인위해)공백라인은 복잡한 로직의 의미 단위를 나눠주어 읽는사람에게 추가적인 정보 전달 가능하다.부정어(!)를 대하는 자세 - 부정연산자의 가독성 때문 부정어구 쓰지 않아도 되는지 체크부정의 의미 담은 다른단어 존재하는지 고민해피케이스와 예외처리 예외가 발생할 가능성 낮추기어떤 값의 검증이 필요한 부분은 주로 외부 세계와의 접점의도한 예외와 예상하지 못한 예외를 구분하기해피케이스와 예외처리 - Null을 대하는 자세 항상 NullPointException을 방지하는 방향으로 경각심 가지기메서드 설계 시 return null을 자제한다Optional에 관하여Optional은 비싼 객체이다. 꼭 필요한 상황에서 반환타입에 사용함Optional을 파라미터로 받지 않도록 한다. 분기 케이스가 3개나 된다Optional을 반환받았다면 최대한 빠르게 해소한다Optional을 해소하는 방법분기문을 만드는 isPresent() - get() 대신 풍부한 API 사용orElse(),orElseGet(),orElseThrow()의 차이 숙지 섹션 4. 객체 지향 패러다임절차지향: "위에서 아래로 순차대로 실행하는 방식"객체지향: "객체 단위로 설계하는 방식"함수형: "함수를 1급 객체로 다루는 방식" 관심사의 분리(높은 응집도, 낮은 결합도)객체로 추상화 하기비공개 필드(데이터),비공개 로직(코드)공개 메서드 선언부를 통해 외부 세계와 소통 - 각 메서드의 기능은 객체의 책임을 드러내는 창구객체의 책임이 나뉨에 따라 객체 간 협력 발생 객체가 제공하는 것절차 지향에서 잘 보이지 않던 개념 가시화관심사가 한 군데로 모이기 때문에, 유지보수성 높아짐(객체 내부에서 데이터 유효성 검증 책임)여러 객체를 사용하는 입장에서, 구체적인 구현에 신경쓰지 않고 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다새로운 객체 만들 때 주의점 1개의 관심사로 명확하게 책임 정의가 되었는지 확인 메서드 추상화와 비슷 객체를 만듦으로써 외부 세계와 어떤 소통을 하려는지 생각생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다 도메인에 특화된 검증 로직이 들어갈 수 있다setter 사용 자제 데이터는 불변이 최고이다, 변하는 데이터이더라도 객체가 핸들링 할 수 있어야한다 객체 내부에서 외부 세계의 개입 없이 자체적인 변경/가공으로 처리 가능한지 확인 만약 외부에서 가지고 있는 데이터로 데이터 변경 요청을 해야하는 경우('set~'이라는 단순한 이름보다는 'update~'같이 의도를 드러내는 작명 고려)getter도 처음에는 사용 자제, 반드시 필요한 경우에 추가하기 외부에서 객체 내 데이터가 필요하다고 getter를 남발하는 것은 무례한 행동이다필드의 수는 적을수록 좋다 불필요한 데이터 많을수록 복잡도가 높아지고 대응할 변화가 많아진다 필드 A를 가지고 계산할 수 있는 A필드가 있다면 메서드 기능으로 제공(단, 미리 가공하는 것이 성능 상 이점이 있다면 필드로 가지고 있는 것이 좋을 수도 있다)SRP:Single Responsibility Principle하나의 클래스는 단 한가지 변경이유만을 가져야함('변경이유' = 책임)객체가 가진 공개 메서드,필드,상수 등은 해당 객체의 단일 책임에 의해서만 변경 되는가?관심사의 분리높은 응집도, 낮은 결합도OCP:Open-Closed Principle확장에는 열려있고, 수정에는 닫혀 있어야 한다(기존코드 변경없이, 시스템의 기능을 확장할 수 있어야 한다)추상화와 다형성을 활용해서 OCP를 지킬 수 있다.LSP:Liskov Substitution Principle상속 구조에서, 부모 클래스의 인스턴스를 자식클래스의 인스턴스로 치환할 수 있어야 한다(자식클래스는 부모클래스의 책임을 준수하며, 부모클래스의 행동을 변경하지 않아야 한다)LSP를 위반하면, 상속클래스를 사용할 때 오동작, 예상밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입체크가 동반될 수 있다ISP:Interface Segregation Principle클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다.(인터페이스를 잘게 쪼개라!)ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.DIP:Dependency Inversion Principle상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다. 의존성의 순방향: 고수준 모듈이 저수준 모듈을 참조하는 것 의존성의 역방향: 고수준,저수준 모듈이 모두 추상화에 의존하는 것 (저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다)DIP:Dependency Inversion Principle의존성 역전 원칙DI:Dependency Injection - "3"의존성 주입(제 3자 필요)IoC:Inversion of Control제어의 역전 섹션 5. 객체 지향 패러다임상속과 조합 : 상속은 결합도가 높기 때문에 조합을 활용하는 것이 더 좋은 설계이다.Value Object, EntityVO는 불변성, 동등성, 유효성을 보장해야하며 도메인의 개념을 추상화한 객체이다. (ex. Money 객체)Entity는 식별자가 존재한다. 식별자가 같으면 동등한 객체로 취급한다.일급 컬렉션 : 컬렉션을 Wrapping한 객체를 뜻한다. 컬렉션을 추상화하여 의미를 담을 수 있고, 가공 로직의 보금자리가 생긴다. (VO와 비슷하다.)Enum : 상수의 집합, 상수들에 대한 로직을 담을 수 있다.추상화와 다형성 활용하여 반복되는 if문 제거 -> OCP 지키기변하는 것 : 조건 & 행위 (구체)변하지 않는 것 : 조건을 만족하는가? / 행위를 수행한다. (추상) 변하는 것과 변하지 않은 것을 구분해서 보는 훈련이 필요하다.숨겨져 있는 도메인 개념 도출하기 : 변경이 많이 일어날 것 같은 미래를 예견하고 이런 것을 도입해보면 어떨까? 하고 숨겨진 도메인 개념을 도출도메인 지식은 만드는 것이 아니라 발견하는 것이다.객체지향은 흉내내는 것이다.미래를 예견하고 도메인 개념을 도출해보자. 강의 회고사람마다 같은 기능을 구현하더라도 코드 스타일이 저마다 다를 것이다. 하지만 클린 코딩을 실천하면 코드가 더욱 직관적이고 명확해져서 협업과 소통이 훨씬 원활해질 것이라고 생각했다. 이러한 이유로 이번 강의를 신청하게 되었다.이번 강의를 통해 클린 코딩의 장점뿐만 아니라 추상의 개념과 그 반대 개념인 구체에 대해서도 배울 수 있었다. 강의에서는 지뢰찾기 게임의 코드를 클린 코드로 개선하는 과정을 예제로 보여주며 개념을 설명해 주었고, 이를 통해 클린 코드가 실제 코드에서 어떻게 적용되는지 더 쉽게 이해할 수 있었다.다만, 아직 코딩 실력이 부족하다 보니 직접 따라 하거나 혼자서 구현해보는 것이 쉽지는 않았다. 하지만 수업을 들으며 내가 이전에 작성했던 코드들을 다시 살펴보니, 개선할 점들이 보이기 시작했다. 앞으로는 이런 점들을 하나씩 고쳐 나가며 실력을 키워야겠다고 다짐했다.처음에는 클린 코딩이 정해진 규칙이나 규율을 따라야 하는 것이라고 생각했지만, 강의를 들으며 그것이 단순한 형식적 규칙이 아니라 소속된 팀이나 협업하는 사람들 간의 원활한 소통을 위한 과정이라는 점을 깨닫게 되었다. 결국 클린 코딩은 단순히 코드 스타일을 개선하는 것이 아니라, 코드를 읽는 사람을 배려하고, 보다 쉽게 이해할 수 있도록 만드는 작업이라는 점이 가장 인상적이었다. 앞으로는 더 좋은 코드 작성법을 고민하며 클린 코딩을 실천해 나가야겠다. 미션 회고 [미션 Day 2 회고] "추상과 구체" 개념을 학습하며, 스마트폰 충전 과정을 예시로 들어 미션을 수행했다.처음에는 단순히 "스마트폰을 충전했다"라는 한 문장으로 표현할 수 있는 일이었지만, 이를 구체적인 단계로 풀어 쓰면서 우리가 일상적으로 당연하게 여기는 행동들이 얼마나 많은 세부 과정으로 이루어져 있는지 다시 한번 깨닫게 되었다.이 과정에서 추상이란 복잡한 개념을 간결하게 표현하는 것이며, 구체란 그 개념을 더 세부적으로 풀어 설명하는 것이라는 점을 실감했다. 예를 들어, "충전기를 꽂는다"라는 간단한 표현도 실제로는 케이블을 찾고, 포트를 확인하고, 어댑터에 연결한 뒤, 충전 여부를 확인하는 과정을 포함하고 있었다.이번 미션을 통해 추상화가 얼마나 중요한 개념인지, 그리고 개발에서도 이처럼 필요한 수준에서 적절한 추상화를 적용하는 것이 왜 중요한지 다시금 생각해보는 계기가 되었다. 앞으로 코드 작성 시에도 너무 구체적으로 표현하여 복잡도를 높이지 않으면서도, 필요한 핵심 개념이 잘 드러나도록 추상화하는 연습을 해야겠다고 다짐했다. [미션 Day 4 회고]이번 미션에서는 가독성이 좋은 코드 작성과 SOLID 원칙을 이해하는 것이 핵심이었다.1. 코드 리팩토링기존 코드에서 getter 최소화, 부정 연산자 제거, Early return 적용을 통해 코드의 가독성을 개선했다.특히, order.getItems().size() == 0 대신 order.isEmpty(), order.getTotalPrice() > 0 대신 order.hasInvalidTotalPrice() 등의 메서드를 추가하여 객체가 스스로 판단할 수 있도록 책임을 분리했다. 이를 통해, 코드의 의도가 명확해지고 유지보수가 쉬워지는 효과를 얻었다.리팩토링을 하면서 객체지향적인 사고방식이 얼마나 중요한지 다시 한번 실감했다. 기존의 validateOrder 메서드는 여러 개의 조건문이 중첩되어 있어 읽기 어려웠지만, 조금만 분리하고 정리해도 코드가 한눈에 들어오는 것을 경험할 수 있었다. 앞으로 코드 작성 시 "내가 짠 코드가 명확한가?"를 더 자주 고민해야겠다고 다짐했다.2. SOLID 원칙 정리SOLID 원칙을 정리하면서, 이론적인 내용만 외우는 것이 아니라 일상적인 예시를 들어 직접 설명해 보는 과정이 재미있었다.특히, 예시로 들면서 원칙이 왜 필요한지 더욱 쉽게 이해할 수 있었다.이처럼 코드뿐만 아니라 개념도 직접 예시를 들어 설명하면 더 깊이 이해할 수 있다는 점을 느꼈다.이번 미션을 통해 "읽기 좋은 코드가 좋은 코드다"라는 사실을 다시금 깨닫게 되었다. 앞으로 코드 작성 시 단순히 기능 구현에 집중하는 것이 아니라, 다른 사람이 봤을 때도 쉽게 이해할 수 있는 코드인지 고민하는 습관을 길러야겠다.

백엔드ReadableCode클린코드

겸손한 북극곰

[워밍업-백엔드3기] ReadableCode 1주차 회고

클린 코드와 테스트 코드 작성 능력 향상을 위해 워밍업 클럽을 신청했다. 👋혼자하는 것보다는 빠르게 성장하지 않을까 하는 기대감을 가졌다.결과적으로 그냥 인프런을 수강할 때보다 두 배로 강의를 집중해서 빠르게 들을 수 있었다.개인적으로 TIL 을 메모하려 했고, 미션을 통해 복습을 하니 강의를 습득하는걸 체감할 수 있었다. 🔢 클린코드의 첫번째 학습Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈1주차 새롭게 배운 내용추상 개념 잡기 추상 계층에 따라 어떻게 관리해야하는 지 이해하고, 클래스를 분리 할 수 있다.void 는 피한다.반환값은 테스트 코드에 도움이 된다.Early Return 과 부정문 관리부정문은 두번의 사고를 거쳐야 한다.else if 는 이전 과정을 모두 기억해야 하는 장기 사고적인 부분이다. 점진적 리팩토링다른 곳에서 참조되는 클래스를 한번에 바꾸는 것은 위험하다.의도한 예외와 예상하지 못한 예외try-catch 시, CustomException을 활용하여 예외의 경우를 나뉘어 관리한다.NPE 를 조심하자!외부에서 오는 값은 항상 의심하고 검증해야한다.Setter 는 물론이고 Getter 도 참아보자메서드를 활용해서 객체간 소통할 수 있다. getter 를 먼저 작성하지 말고 방법을 고민해본다.  클린코드를 실습과 함께 동시 진행하며, 빠르게 내용을 이해하고 습득할 수 있었다.실무 관점에서 클린코드의 목적과 어떠한 방향으로 코드를 작성해야하는지 팁을 계속 알려주셨다.  💾 클린코드 실습 미션 과 SOLID[Readable Code] 클린 코드 리팩토링 연습과 SOLID 원칙 정리클린코드 미션 제출 코드배울 때는 너무 잘 정리해주셔서 정답이 있는 듯 보이지만, 예제 코드를 직접 수정하니 주관적이고 판단하기 어려웠다.강의를 들으며 정리한 메모를 한 줄씩 읽어보고, 예제 코드를 딱 보았을 때 맘에 들지 않는 부분을 정리했다.배운 내용을 규칙처럼 적용하려 했고, 평소와 다르게 작성하려 노력했다. 저 짧은 예제 코드 하나 수정하는데 꽤 많은 시간이 들었다. 🥵제출하고 나서도 '이게 최선일까?' 라는 생각이 많이 들었고, 좋은 코드를 찾아 보라는 말이 이해가 되었다. 나의 언어로 SOLID 정리하기OCP : 개방 폐쇄 원칙 게임에 새로운 레벨이 추가된다고, 게임 로고가 바뀌지는 않는다.게임에 새로운 스테이지가 추가 된다고, 튜토리얼이 바뀌지는 않는다. 기존 코드의 변경 없이 새로운 요구사항을 반영할 수 있어야 한다.   SOLID 를 이해하려면 앞으로도 몇개월이 걸릴 거라 생각했는데, 직접 정리하면서 개념을 다시 잡아보기도 하고 생각을 정리할 수 있었다. 배운 내용을 내 언어로 정리하니 기억도 잘되었다! 🧠  🤔 1주차 회고세션이나 도서 등을 참고한 적은 많지만 내용을 직접 적용해본 경험은 없는 것 같았다.클린 코드 학습은 막연하다고 생각했는데, 실시간 예제와 함께 강의를 들으니 너무 이해가 잘되었다.매일 배운 내용을 나의 언어로 메모를 남겨 내 것으로 만들기 위해 노력하고 있다.1주만 들었을 뿐인데, 코테를 연습하면서도 클린코드를 고민하게 된다.클린 코드 학습을 고민하는 분이 있다면 박우빈님 강의를 추천한다!   

백엔드클린코드ReadableCode박우빈님강의워밍업클럽

하얀종이개발자

워밍업 클럽 3기 클린코드 스터디 - 1주차 발자국

클린코드 스터디 - 발자국을 통해서 1주동안의 강의와 미션을 통해 무엇을 배웠고, 어떻게 느꼈는지 작성합니다. 섹션1~5 배운 내용섹션 2. 데이터를 추상화추상과 구체이름짓기, 메서드와 추상화, 메서드 선언부, 추상화 레벨, 매직넘버와 스트링 섹션 3. 코드를 추상화인지적 경제성메서드를 리팩토링 하는 방법Early return공백 라인, 부정어예외처리stream API와 Optional() 섹션 4. 객체지향 페러다임객체지향의 특성SOLID 원칙 섹션5. 객체 지향 적용하기상속과 조합Value Object 일급 컬렉션Enum의 특성과 활용 다형성 활용숨겨져 있는 도메인 개념 도출하기  발자국 1주차 회고 💡 배운 점기존에 어설프게 객체지향 코드를 작성했던 부분을 왜 이렇게 작성해야 하는지어떻게하면 더 잘 읽힐 수 있는지를 많이 배운 것 같아요.특히, 인지적 경제성: 최소한의 인지만 가져가서 최대한의 효율을 내보자!! 라는 말을 많이 깨닫게 된 것 같습니다. 🤷‍♂ 잘한 점읽기 좋은 코드를 이해한 상태로 내가 바꿔보고 강의를 보면서 나와 다른점이 뭔지 보면서 많이 느꼈어요.굉장히 재밌어서 그런지, 매일 꾸준히 공부한 부분도 좋았습니다.이제는 코드를 칠 때 한번 더 생각하게 되는거 같아요. 어떻게 작성하면 다른사람이 편하게 읽을 수 있을까를요.₩⚠ 아쉬운 점영어가 약해서 메서드명 짓기가 너무 서투르다는 것을 느꼈어요.다른 사람들이 메서드명을 어떻게 짓는지 많이 보면서 더 읽기 좋은 메서드명을 찾아봐야 할 것 같아요. 🎯 다음 주 목표따로 정리한 내용 한번씩 읽어보기코드를 따라 치는게 아니라 내가 바꿔보고, 강의를 통해서 바뀐 부분 비교하기단순히 원칙만 지키는게 아니라, 더 읽기 좋은 코드를 작성하기 위해 깊게 고민하기   한마디아직 많이 부족하구나 라는 것도 느꼈지만, 더 좋은 코드를 작성할 수 있게 될 거라는 생각에 너무 즐거워요. 🙃다들 다음주도 화이팅입니다.  

백엔드워밍업클럽클린코드박우빈ReadableCode

sdsd988

[워밍업 클럽 스터디 2기 백엔드(클린코드, 테스트코드)] 1주차 발자국

1주차 강의섹션 1. 추상과 구체섹션 2. 논리, 사고의 흐름 | 객체 지향 패러다임섹션 3. 객체 지향 패러다임 (SOLID)요약 : 좋은 코드(클린코드)를 작성하기 위한 도구와 사용 방법을 학습 강의 내용추상과 구체 (클린코드의 목적과 도구)논리, 사고의 흐름  우리는 코드를 읽는 시간이 더 많다.따라서, 코드는 쉽게 읽히고 이해되어야 한다.이를 위해, 우리는 추상, 구체 를 이해하고 분리해야 한다.메서드 작성, 파라미터 선언, 반환값 고민, 매직 스트링 등 좋은 코드 작성을 위한 고민과 도구를 학습조기 리턴, 공백 라인, 부정어 등 이해하기 쉬운 코드 작성을 위해 조심해야 하는 부분 학습 한번쯤 들어보거나, 읽어본 이야기다. 그렇지만, 현업에서 개발하면서 시간을 핑계로, 선배들이 좋게 보지 않는다는 이유로 실무 개발과 공부한 내용을 분리해서 개발해왔다. 그렇기에, 실제 코드를 바탕으로 고민하고 코드를 작성해보는 경험이 좋았다. 개발자는 고민하고, 코드를 직접 작성해봐야 뭐가 된다는 것을 새삼 느낄 수 있었다. 객체 지향 패러다임단일 책임 원칙객체의 변경 기준은 책임이다.책임이 단일하지 않다면, 변경의 기준도 단일하지 않다.이로 인해 객체의 코드 변경의 원칙이 무너진다. 코드를 읽고, 객체를 사용해야 하는 입장에서 어려움을 겪게 된다.개방 / 폐쇄 원칙책임이 과중히 부과되어서는 안된다.즉 객체는 자신의 책임에 대해서는 기능을 확장할 수 있지만, 자신이 아닌 책임에 대해서는 영향을 받으면 안된다.현재의 책임이 구체인지 추상인지 고민하고, 구체라면 추상화와 다형성을 활용해서 원칙을 지킬 수 있다.리스코프 치환 원칙 사용하는 입장에서 부모 클래스와 자식 클래스의 차이를 알지 못해야 한다.즉 슈퍼 클래스는 불필요한 기능을 상속해서는 안된다. 객체의 상속 사용시 주의해야 할 것 같다.인터페이스 분리 원칙책임을 명확하게 갖는 것은, 인터페이스도 예외가 아니다.인터페이스는 추상화, 다형성의 중요한 도구인 동시에 책임을 갖는다.의존성 역전 원칙기능은 변하고, 요구사항은 추가된다.그렇기에 고수준 모듈은 구체(저수준 모둘)를 참조하는 것이 아니라 추상에 의존해야 한다.새로운 요구 사항이 추가되고, 기능이 변경된다고 하더라도 추상에 의존한다면 코드의 변경 범위를 최소화 할 수 있다  미션 : 배운 내용을 바탕으로 고민해보기미션1. 추상과 구체 사례 예시 제출미션2. 과제 코드 리팩토링 제출미션은 강의를 학습한 내용을 적용해보는 방향으로 접근했다.특히, 고민 해보는 것을 중요하게 생각했다.과거에도 강의를 보고 학습하면서, 직접 고민해보는 시간이 부족했다고 생각했다. public class Delivery { private Order order; public boolean validateOrder(Order order) { if (validateItemSize(order)) { log.info("주문 항목이 없습니다."); return false; } if (validateTotalPrice(order)) { log.info("올바르지 않은 총 가격입니다."); return false; } if (DoesNotHaveCustomerInfo(order)) { log.info("사용자 정보가 없습니다."); return false; } return true; } private boolean validateTotalPrice(Order order) { return order.getTotalPrice() <= 0; } private boolean validateItemSize(Order order) { return order.doesNotHaveItems(); } private boolean DoesNotHaveCustomerInfo(Order order) { return order.doesNotHaveCustomInfo(); } } 1주차 회고 계획한 것 보다 강의와 미션에 시간을 할애하지 못했다.과제를 제출하고, 다른 참여생분들이 작성한 미션을 보면서 반성하고 자극되었다.특히 아쉬운 점은, 과제를 pdf, github 등을 통해 더 깔끔하게 제출할 수 있었는데 하지 못한점이 아쉽다.좋았던 점은, 워밍업 클럽이라는 곳에 소속감이 생겨서 주어진 기간내에 강의를 완강했다는 것. 혼자 수강했다면 이 정도 진로를 나갈 수 없었을 것이라고 생각한다.가장 좋았던 것은 미션이었다. 강의에서도 가장 좋은 점이 직접 리팩토링을 하는 시간이 많다는 것.워밍업 클럽에서도 미션이 가장 좋았다. 직접 무언가를 하는 경험이 지금의 내게 가장 맞다고 생각되었다.

백엔드백엔드클린코드ReadableCode읽기좋은코드를작성하는사고법

[워밍업 클럽 2기] Day4 - 논리, 사고의 흐름 & SOLID

워밍업 클럽 2기 [Clean Code & Test Code](https://www.inflearn.com/roadmaps/5699) 로드맵의 Day4 미션입니다. 1. 코드 리팩토링As-Ispublic boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; } To-Bepublic boolean validateOrder(Order order) { if (order.itemsIsEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.customerInfoIsEmpty()) { log.info("사용자 정보가 없습니다."); return false; } if (order.totalPriceIsNegative()) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; }고려한 내용!를 쓰지 않고 부정어구를 사용해서 처리일찍 return할 수 있는 부분은 return을 해서 이전 내용을 신경 쓰지 않아도 된다else 지양분기문 중첩 depth 줄이기 2. SOLID(객체 지향의 5대 원칙)SRP(단일 책임)SRP는 하나의 클래스 또는 모듈은 하나의 책임을 가져야 한다는 원칙이다. Q. 그럼 책임이라는 것은 무엇일까? 여기서 책임은 "변경의 이유"라고 표현할 수 있다. 만약 하나의 클래스가 여러 가지 이유로 변경되어야 한다면, 그 클래스는 여러 가지 책임을 가지고 있다는 뜻이다. 이렇게 여러가지 책임이 하나의 클래스에 존재한다면, 추후에 유지보수하기 어려워질 가능성이 높다. Q. 그러면 책임의 범위를 어떻게 정하는 것이 좋을까?책임의 범위라는 것은 문맥과 상황에 따라 다를 수 있다. 이런 책임의 범위를 잘 정하는 것은 경험적인 영역이 많이 포함된다. (한마디로 책임을 보는 눈을 기르기 위해서는 경험을 많이 쌓자!)확실한 것은 어떤 변경이 있을 때 파급 효과가 적다면 SRP를 잘 따른 것으로 볼 수 있다. 정리하자면 SRP는 변경의 이유를 하나로 만들어서 코드의 응집성을 높이고, 결합도를 낮추면서 유지보수성을 개선하는 것 이다. 이때 책임(변경의 이유)의 범위를 잘 정할수 있는 능력을 기르는 것이 중요하다. OCP(개방 폐쇄)OCP는 소프트웨어가 확장에는 열려있고, 변경에는 닫혀 있어야 한다는 원칙이다. 쉽게 말해서, 새로운 기능이나 요소를 추가할 때 기존의 코드 변경 없이 추가가 가능해야 한다. Q. OCP는 어떻게 구현할까?인터페이스를 구현한 새로운 클래스를 만들어서 새로운 기능을 구현하거나 추가하는 다형성을 활용해서 구현한다. 조금더 자세히 설명하자면, 구현체가 아닌 인터페이스를 의존하도록 하고, 단순히 구현체를 변경하는 방식으로 기능의 변경이 가능하도록 설계하는 것이다. LSP(리스코프 치환)LSP는 프로그램의 객체는 프로그램을 깨트리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다. 쉽게 말해서 상속 관계에서 자식 클래스의 객체가 부모 클래스의 객체를 완전히 대체해도 정상적으로 동작해야 한다는 의미다. ISP(인터페이스 분리)ISP는 클라이언트는 자신이 사용하지 않는 인터페이스(메서드)에 의존하면 안된다는 원칙이다. 쉽게 말해서, 인터페이스를 명확한 기준을 가지고 더 작은 인터페이스로 분리하자는 원칙이다. Q. 사용하지 않는 인터페이스에 의존하지 말자는 것이 무슨 의미인가?인터페이스가 너무 광범위하면 인터페이스를 구현하는 클래스들이 사용하지도 않을 메서드를 오버라이딩 해야하는 상황이 발생한다. 이를 방지하기 위해서, 명확한 기준을 가지고 인터페이스를 더 작게 분리하자는 것이 ISP 원칙이다. 불필요한 메서드 오버라이딩 외에도, 변경으로 인한 파급 효과를 줄이기 위해서 ISP를 적용할 수 있다.쉽게 말해서, 특정 클라이언트를 위한 인터페이스(좁은 범위의 책임을 가지는 인터페이스) 여러개가 범용적인 인터페이스 하나보다 낫다는 것이다. DIP(의존 관계 역전)DIP는 구체화에 의존하면 안되고, 추상화에 의존해야 한다는 원칙이다. 더 자세히 말하자면 고수준 모듈과 저수준 모듈 모두 추상화에 의존해야 한다는 뜻이다. 쉽게 말해서, 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 뜻이다. Q. 구체적인 요소의 의존을 피하는 이유는?구체적이라는 것은 변동 가능성이 높다는 것이다. 저수준 모듈의 변경 사항이 있을 때 마다 해당 모듈을 사용하는 모듈도 변경이 필요할 가능성이 높아진다. 반면에, 추상화에 의존하게 되면 저수준 모듈이 변경되어도, 고수준의 모듈에는 영향이 가지 않는다(의존 관계의 역전). DIP는 DI(의존성 주입)과 IoC(제어의 역전)이라는 개념과 자주 다루어진다. IoC(제어의 역전)IoC는 프로그래머가 작성한 코드가 프레임워크의 제어를 받게 되는 패턴을 이야기 한다. 전통적인 프로그램에서의 흐름은 프로그래머가 작성한 프로그램이 라이브러리의 코드를 호출해 이용한다. 하지만 제어의 역전이 적용된 구조에서는 프레임워크의 코드가 프로그래머가 작성한 코드를 호출한다.DI(의존성 주입)DI는 클라이언트의 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는 것이다. 쉽게 말해서, 필요한 의존성을 외부로 주입을 받는 것이라고 생각하면 된다. 의존성이라는 것은 동작하기 위해 필요한 클래스 또는 객체이다. Q. 그러면 주입(의존 관계 연결)은 누가 해주는 것인가?주입 받는 쪽이나 주입하는 의존성이 아닌 제 3자가 해준다. 이를 보통 IoC 컨테이너, DI 컨테이너, 등의 표현을 사용한다.스프링을 예시로 들자면, ApplicationContext가 이를 해준다.  

백엔드ReadableCode워밍업클럽2기Day4

Seul Ki Lee

워밍업 클럽 2기 BE 클린코드&테스트 day4 과제

Readable Code: 읽기 좋은 코드를 작성하는 사고법(링크)아래 내용은 위의 인프런 강의를 들으면서 과제 및 내용을 정리해봤습니다. 아래 코드 리팩토링 하기public boolean validateOrder(Order order){ if(order.getItems().size() == 0){ log.info("주문 항목이 없습니다"); }else{ if(order.getTotalPrice() > 0){ if(!order.hasCustomerInfo()){ log.info("사용자 정보가 없습니다"); return false; }else{ return true; } }else if(!(order.getTotalPrice() > 0)){ log.info("올바르지 않은 총 가격입니다"); return false; } } return true; }본 코드의 문제는 아래와 같다if, else if, else 그리고 중접 if 등으로 인하여 주문의 유효성 조건이 한 눈에 들어오지 않는다=> early return을 사용해보자 무분별한 getter의 사용(if(order.getItems().size() == 0))=> 주문에 담긴 상품이 있는지 확인하는 내용인데 굳이 getter를 써야할까?=> 오히려 order에 item 항목이 있다고 세부 내용을 노출해버리고 있다=> 의미있는 이름의 메소드를 order에서 그 역할을 책임하도록 해보자 부정어의 사용 if(order.hasCustomerInfo()) / !(order.getTotalPrice() > 0)=> 부정어를 사용하면 코드의 가독성을 해친다 => 1순위 긍정어를 사용하여 메소드 만들 수 있는지 확인=> 2순위 긍정어를 사용할 수 없다면 메소드명으로 부정을 나타내서 만들어보자 위의 내용을 고려한 최종 코드는 아래와 같다public boolean validateOrder(Order order){ if(order.isEmptyOrderItem()){ log.info("주문 항목이 없습니다"); return false; } if(order.isLessThanOrEqualToZero()){ log.info("올바르지 않은 총 가격입니다"); return false; } if(order.isEmptyCustomerInfo()){ log.info("사용자 정보가 없습니다"); return false; } return true; }public class Order{ private List<Item> items; public boolean isEmptyOrderItem(){ return order.getItems().size() == 0; } public boolean isLessThanOrEqualToZero(){ return order.getTotalPrice() <= 0 }; public boolean isEmptyCustomerInfo(){ return !hasCustomerInfo(); } public double getTotalPrice(){...} public boolean hasCustomerInfo(){...} }SOLID에 대하여 자기만의 언어로 정리SRP클래스가 변경될 이유는 단 하나다!!클래스 설계 시, 하나의 관심사로 응집하여 구현하도록 하자OCP기존 코드의 변경 없이, 기능 추가하도록 설계가 되어야 한다 다형성을 이용하여 클라이언트 코드의 변경 없이 구현체를 쉽게 변경이 가능하다LSP부모 클래스에서 정의한 스펙을 자식 클래스에서도 지켜야 한다instance of로 타입 체크하여 특정 타입에 대해서만 처리가 필요하다는 건 LSP를 위반한 사례이다!!ISPSRP와 비슷하게 인터페이스 또한 한 가지 책임을 가지도록 분리를 잘해야 한다DIP클래스 참조 시, 추상화 레벨이 높은 인터페이스, 추상클래스, 상위 클래스를 참조하도록 하자코드에 구현체가 드러나게 되면 기능 변경시, 클라이언트 코드의 변경이 생기므로추상화 레벨이 높은 인터페이스 등을 메소드 파라메터, 필드, 리턴타입으로 활용하도록 하자

백엔드ReadableCode워밍업클럽2기

채널톡 아이콘