블로그

Jason

파이썬 왈러스 연산자 소개(필요성, 사용 예시)

이번 글에서는 왈러스 연산자에 대해 알아보겠습니다.왈러스 연산자는 아무래도 새로운 기능을 위한 개념이라기 보다는 짧고 직관적인 코드 작성에 사용되는 개념이다보니 직접 예제를 보며 설명하겠습니다.왈러스 연산자는 비교적 최근인 3.8 버전에서 등장한 개념입니다.한 줄에서 변수에 값을 할당하면서 동시에 이 값을 표현식의 일부로 사용할 수 있습니다.바다코끼리 연산자를 통해 파이썬에서 할당 표현식을 가능하게 합니다.여러분이 오랜만에 소비를 좀 하려고 합니다. 우선 그래픽 카드도 좀 사고 싶고,,, 그 다음 순위로 책(2권 사야됨), 그 다음 순위로 키보드, 그 다음 순위로 만년필을 선호한다고 가정하겠습니다.이제 온라인 쇼핑몰 속을 돌아다니며 현재 예산에서 무엇을 살 수 있을 지 봅니다!예산 내에서 그래픽 카드를 살 수 있으면 사고, 아니면 책 2권 값을 낼 수 있는 지 확인합니다. 그래도 안 되면 순서대로 키보드, 만년필을 살 수 있는지 확인해야 합니다.능숙한 프로그래머인 여러분들은 이정도는 파이썬으로 자동화하실 수 있죠?my_budget = 1000000 gift_value = { # 그래픽 카드는 품절이랍니다 'gc': 1300000, 'book': 50000, 'keyboard': 55000, 'pen': 80000 } # 99999999 정도면 품절 상품도 구매할 수 있다고 칩시다. value = gift_value.get('gc', 99999999) if value <= my_budget: print('그래픽카드 구매') else: value = gift_value.get('book', 99999999) if value*2 <= my_budget: print('책 주문!') else: value = gift_value.get('keyboard', 99999999) if value <= my_budget: print('키보드 구매') else: value = gift_value.get('pen', 99999999) if value <= my_budget: print('만년필 구매') else: print('살 수 있는 게 없습니다.') print(f'{my_budget}에서 {value}만큼 사용하셨습니다.')의도대로 동작하지만;; 너무 복잡해보이는 코드입니다. 제가 코드를 잘못 짰다고요?elif 사용을 통해 직관적으로 보이게 만들 수 있지만, 그렇게 쉽게 줄여지지 않습니다. 항상 동일 환경 조건에서 비교를 하는 것이 아니며(book 같은 경우에는 *2 후 비교) 각 상품마다 나오는 메시지가 다르기 때문입니다.이제 왈러스 연산자가 나올 시간입니다. 이 코드에 왈러스 연산자를 적용해보겠습니다.my_budget = 1000000 gift_value = { # 그래픽 카드는 품절이랍니다 'gc': 1300000, 'book': 50000, 'keyboard': 55000, 'pen': 80000 } if (value := gift_value.get('gc', 99999999)) <= my_budget: print('그래픽카드 구매') elif (value := gift_value.get('book', 99999999) * 2) <= my_budget: print('책 주문!') elif (value := gift_value.get('keyboard', 99999999)) <= my_budget: print('키보드 구매') elif (value := gift_value.get('pen', 99999999)) <= my_budget: print('만년필 구매') else: print('살 수 있는 게 없습니다.') print(f'{my_budget}에서 {value}만큼 사용하셨습니다')위아래 코드의 차이가 잘 느껴지셨으면 좋겠습니다.지금 본 사례처럼 왈러스 연산자를 사용하면 코드를 더 직관적이게 만들 수 있습니다.조건문 내에서 값을 할당하고 바로 검사, 블록 안밖에서 사용까지 할 수 있으니 정말 편리하다고 느낍니다.다른 사용 예시를 보며 마무리하겠습니다.# 입력값을 받아서 검사하고 처리 if (n := int(input("Enter a number: "))) > 10: print("10보다 큰 수를 입력했군")# 튜플 언패킹을 사용한 예 a, b = (1, 2) print(a, b) # 출력: 1 2 # 튜플 타입에서 왈러스 연산자를 사용하려면 반드시 명시적으로 괄호를 해주거나 따로 언패킹, 패킹해야 됩니다. (a := 1, b := 2) print(a, b) # 출력: 1 2 원문: https://pinstella.com/writer/articles/7

프로그래밍 언어파이썬pythonwalruscleancode

김태영

[인프런 워밍업 클럽 3기 BE 클린코드 & 테스트 스터디 ] 발자국 3주차

3주차 [섹션 6]레이어드 아키텍처(Layered Architecture)와 테스트Presentation Layer, Business Layer, Persistence Layer로 분리관심사의 분리통합 테스트여러 모듈이 협력하는 기능을 통합적으로 검증하는 테스트일반적으로 작은 범위의 단위 테스트만으로는 기능 전체의 신뢰성을 보장할 수 없다.풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트Persistene Layer 테스트@SpringBootTestspring boot의 모든 빈들을 다 주입한다.@DataJpaTestJPA관련 빈들만 주입한다.속도가 @SpringBootTest보다 빠르다.Business Layer 테스트비즈니스 로직을 구현하는 부분Persistence Layer와의 상호작용을 통해 비즈니스 로직을 전개시킨다.트랜잭션을 보장해야 한다.@DataJpaTest는 @SpringBootTest와 다르게 @Transactional이 자동으로 걸려있다.데이터 롤백이 기본적으로 된다.@SpringBootTest에 @Tracnsactional을 걸었을 때 주의할 점서비스 클래스에서 @Transactional이 없어도 Test시에 걸어줬기 때문에 테스트가 통과될 수 있다.@AfterEach를 통해서 repository들을 초기화할 수 있다. @Transactional을사용하면 deleteAll 등 초기화 단계를 설정하지 않아도 된다. deleteAll과 deleteAllInBatch의 차이deleteAll은 내부적으로 한 건씩 개별 삭제한다. 연관 관계 테이블을 먼저 지우지 않아도, 개별 삭제할 때 같이 지운다.deleteAllInBatch는 개별 삭제가 아닌 bulk query를 사용하여 한 번에 삭제한다.단, 연관 관계 테이블을 먼저 삭제해야지, 외래키 제약 조건에 어긋나지 않는다.  Presentation Layer 테스트동시성 이슈생성 함수에서는 동시성을 고려해줘야 한다.함수 호출 빈도가 낮으면, id에 unique 제약 조건을 걸고, 실패 시 재시도하는 로직 추가함수 호출 빈도가 높으면, UUID 같은 것으로 대체서비스단에 readOnly = true를 base로 사용cud 작업일 때는 @Transactioal을 메서드 위에 선언해서, readOnly가 되지 않게끔 작동CQRS - command / read를 분리read 부분은 조회 전문 repository나 로직을 구현 가능command는 복잡한 로직을 담당할 수 있다.Day 11 미션  https://github.com/taeyeongKims/readable-code/tree/main/src/test/java/cleancode/studycafe/tobe/model출처 : https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard

cleancode

김태영

[인프런 워밍업 클럽 3기 BE 클린코드 & 테스트 스터디 ] 발자국 2주차

[2주차] [섹션 6]주석의 양면성후대에 전해야 할 "의사 결정 히스토리"를 코드로 표현할 수 없을 때, 주석으로 상세하게 설명한다.주석을 작성할 때, 자주 변하는 정보는 최대한 지양해서 작성한다.관련 정책이 변하거나, 코드가 번경되었다면 주석도 잊지 않고 업데이트주석이 없는 코드보다, 부정확한 주석이 달린 코드가 치명적이다.좋은 주석우리가 가진 모든 표현 방법을 동원해 코드에 의도를 녹여내고, 그럼에도 불구하고 전달해야 할 정보가 남았을 때 사용하는 주석변수와 메서드의 나열 순서변수는 사용하는 순서대로 나열한다.메서드의 나열 순서는 개인 취향객체는 협력을 위한 존재, 외부 세계에 내가 어떤 기능을 제공할 수 있는지 드러냄공개 메서드를 상단에 배치공개 메서드끼리도 기준을 가지고 배치하는 것이 좋다중요도 순, 종류별로 그룹화하여 배치하면 중복된 로직을 만드는 것을 피할 수 있다.상태 변경 >> 판별 >= 조회 메서드패키지 나누기패키지는 문맥으로써의 정보를 제공할 수 있다.Level 패키지 안의 Beginner, Middle 등에 Level을 붙이지 않아도 되는 이유는 문맥상 레벨 단위라고 생각할 수 있기 때문패키지를 쪼개지 않으면 관리가 어려워진다.패키지를 너무 잘게 쪼개면 그것대로 관리가 어려워진다.대규모 패키지 변경은 팀원과의 합의를 이룬 시점에 하자.다같이 사용하는 패키지를 변경하면, 충돌이 발생할 수 있다.처음부터 잘 고민해서 패키지를 나누자!기능 유지보수하기 (1) - 버그 잡기기능을 개발하다 보면 리팩토링 과정에서 달라진 부분에 따라 수정해야 하는 경우가 생긴다.리팩토링을 진행하며 판별 조건이 세분화될 경우 세분화된 경우에 따라 수정해야 한다.기능 유지보수하기 (2) - 알고리즘 교체하기사용하는 알고리즘에 따라 시간 복잡도를 감소시킬 수도 있고, 메모리 사용을 감소시킬 수도 있다.재귀 대신 스택을 사용할 수도 있고, 그리디 방법에서 다이나믹 프로그래밍을 사용하여 감소시킬 수도 있다.IDE의 도움 받기코드 포맷 정렬 Ctrl + Alt + L 코드 품질에 도움을 주는 플러그인포맷 규칙을 설정할 수 있는 파일[섹션 7]스터디 카페 코드 리팩토링 연습중점으로 리팩토링한 것SRP (단일 책임 원칙)OCP (개방 폐쇄 원칙)LSP (리스코프 치환 원칙)추상화 레벨 맞추기getter 사용 지양판별 메서드 사용중복 제거, 인터페이스 활용 내가 놓친 것DIP (의존성 역전 원칙)핸들러 통합의미있는 내용 상수화일급 컬렉션 활용 [섹션 8]능동적 읽기복잡하거나, 엉망인 코드를 읽고 이해하려 할 때, 리팩토링하면서 읽기리팩토링 후, 돌아갈 수 있는 git reset --hard가 있다.핵심 목표는 도메인 지식을 늘리고, 이전 작성자의 의도를 파악하는 것오버 엔지니어링필요한 적정 수준보다 더 높은 수준의 엔지니어링ex) 구현체가 하나인 인터페이스구현체가 하나라면 굳이 인터페이스로 만들 필요가 없다. 근시일 내로 추가된다면 좋다.ex) 너무 이른 추상화추상화로 인해 정보가 숨겨지기 떄문에 복잡도는 증가, 이해도는 감소후대 개발자들이 선대의 의도를 파악하기 힘들다.은탄환은 없다은탄환은 없다 : 만능 해결사는 없다.클린코드가 무조건 좋은가?유지보수성은 좋지만, 변경성이 없는 코드라면 동작면에서 달라지는 게 없다.실무 : 2가지 사이의 줄다리기지속 가능한 소프트웨어의 품질 VS 기술 부채를 안고 가는 빠른 결과물모든 기술과 방법론은 적정 기술의 범위 내에서 사용되어야 한다.ex) 급한 배포인데, style 관련 리뷰를 주고, 고치도록 하는 사람..?도구라는 것은, 일단 그것을 한계까지 사용할 줄 아는 사람이 그것을 사용하지 말아야 할 때도 아는 법이다.[섹션 9]강의 마무리추상 (抽象)전문가는 언제나 탑다운으로 깔끔하게 생각할 것이다.추상 -> 구체로 생각하자  테스트 강의 [섹션 1]어떻게 학습하면 좋을까?선택과 집중모든 것을 잘할 수는 없다.[섹션 2]테스트는 왜 필요할까?기능 개발 중 이전 개발 영역과 겹치는 부분이 생긴다. (중복되는 부분)기존 코드를 건드리게 된다면 여전히 정상 작동하는지 검증이 필요하다.사람이 검증을 한다면?커버할 수 없는 영역 발생경험과 감에 의존늦은 피드백유지보수 어려움소프트웨어 신뢰 저하 테스트를 통해서 얻을 수 있는 것빠른 피드백자동화안정테스트 코드를 작성하지 않는다면?변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려변화가 생기는 매순간마다 모든 팀원이 동일한 고민빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.테스트 코드가 병목이 된다면?프로덕션 코드의 안정성을 제공하기 힘들다.테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.잘못된 검증이 이루어질 가능성이 생긴다.[섹션 3] 수동 테스트 vs 자동화된 테스트수동 테스트 : 콘솔에 출력하며, 사람이 직접 확인한다.단점사람이 검증해야 한다.다른 사람이 봤을 때, 어떤 것을 검증해야 하는지 알기 어렵다. 자동 테스트 : 자동화 테스트 도구로 검증을 자동으로 한다.장점사람이 직접 검증하지 않는다.테스트 환경과 검증 목표를 뚜렷히 알 수 있다.JUnit5로 테스트하기단위 테스트 : 작은 코드 단위(클래스 or 메서드)를 독립적으로 검증하는 테스트검증 속도가 빠르고, 안정적이다.테스트 케이스 세분화하기해피 케이스, 예외 케이스 -> 경계값 테스트(범위, 구간, 날짜 등)정상 작동만 테스트하는 것이 아니라, 예외 상황도 검증을 해야 한다!테스트하기 어려운 영역을 분리하기현재 시간, 날짜 , 랜덤 값 등 고정적인 것이 아닌 유동적인 요소를 분리하자테스트하기 어려운 영역을 외부로 분리할수록 테스트 가능한 코드는 많아진다.테스트하기 어려운 영역?관측할 때마다 다른 값에 의존하는 코드현재 날짜/ 시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을주는 코드 표준 출력, 메시지 발송, 데이터베이스에 기록 순수 함수같은 입력에는 항상 같은 결과외부 세상과 단절된 형태테스트하기 쉬운 코드[섹션 4]TDD : Test Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법레드 - 그린 - 리팩토링레드 : 실패하는 테스트 작성 (구현부 없이 테스트 작성)그린 : 테스트 통과를 위한 최소한의 코딩 (최소한의 구현)리팩토링 : 구현 코드 개선 및 테스트 통과 유지선 기능 구현, 후 테스트 작성테스트 자체의 누락 가능성특정 테스트 케이스만 검증할 가능성 -> 해피 케이스잘못된 구현을 다소 늦게 발견할 가능성선 테스트 작성, 후 기능 구현복잡도가 낮은 테스트 가능한 코드로 구현할 수 있게 한다.쉽게 발견하기 어려운 엣지 케이스를 놓치지 않게 해준다.구현에 대한 빠른 피드백을 받을 수 있다.과감한 리팩토링이 가능해진다.TDD : 관점의 변화테스트는 구현부 검증을 위한 보조 수단 -> 테스트와 사옿 작용하며 발전하는 구현클라이언트 관점에서의 피드백을 주는 Test Driven(테스트 주도)[섹션 5]테스트는 []다테스트는 문서다.프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.DisplayName을 섬세하게테스트 코드는 팀 전체가 보는 것모두가 쉽고, 명확하게 알아볼 수 있게끔 적어야 한다.테스트 목적과 환경, 검증 요소를 명확하게테스트 행위에 대한 결과까지 기술하기도메인 용어를 사용하여 한층 추상화된 내용을 담기메서드 자체의 관점보다 도메인 정책 관점으로테스트의 현상을 중점으로 기술하지 말 것특정 시간 이전에 주문을 생성하면 실패한다 -> 영업 시작 시간 이전에는 주문을 생성할 수 없다. 명사의 나열보다 문장으로 작성A이면 B이다.A이면 B가 아니고, C다.BDD 스타일로 작성하기BDD, Behavior Driven DevelopmentTDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트케이스(TC) 자체에 집중하여 테스트한다.개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 추상화 수준(레벨)을 권장Given / When / ThenGiven : 시나리오 진행에 필요한 모든 준비 과정 (객체, 값, 상태 등)When : 시나리오 행동 진행Then : 시나리오 진행에 대한 결과 명시, 검증어떤 환경에서(Given) 어떤 행동을 진행했을 때(When) 어떤 상태 변화가 일어난다(Then)DisplayName에 명확하게 작성할 수 있다.[Day7 미션]https://github.com/taeyeongKims/readable-code/tree/day7[미션 회고]실제로 배웠던 것을 제대로 적용하지 못해서 아쉽다.추상에만 신경을 쓰느라, 일급 컬렉션, 상수화 등의 디테일을 신경쓰지 못했다.또한, 단일 책임 원칙에서도 시간권 패스에 라커 패스가 함께 묶여 있는 게 맞는 걸까?라는 생각도 들었다.리스코프 치환 원칙을 생각하느라 공통 인터페이스를 만들었지만 치환성에 중점을 둔 나머지, 다른 원칙을 어긋낸 건 아닐까라는 생각도 든다.또한, 의존성 역전 원칙을 어떻게 적용할지는 감도 안 잡혔었다.하지만, 섹션 7의 리팩토링 강의 영상으로 보니, 이런 식으로 연결짓는구나 라고 조금은 감이 잡히게 되었다.리팩토링에는 정답이 없다고는 하지만, 반복 연습하다보면 정답에 가까워지지 않을까,,? 라는 생각이 든다.앞으로도 계속 클린코드에 대해 생각해보며 코드를 작성해야 겠다.   [2주차 회고]리팩토링 강의가 끝나고, 테스트 강의로 넘어가는 주차였다.리팩토링 미션을 진행하며 아쉬움이 많은 주차였으며강의 1개를 완주하였다는 뿌듯함도 남은 주차였으며테스트 강의를 시작하는 기대감이 생긴 주차였다.지금까지 많은 강의를 보았지만, 깊게 생각해본 강의는 이번이 처음이었던 거 같다.앞으로 많은 코드를 만들고, 보겠지만 이번 주차 강의가 많이 생각날 듯하다. 

cleancode

김태영

[인프런 워밍업 클럽 BE 클린코드 & 테스트 스터디] 발자국 1주차

1주차 발자국 정리 [섹션 2]추상과 구체추상 : 중요한 정보는 가려서 남기고, 덜 중요한 정보는 생략추상으로부터 구체를 유추하지 못 하는 이유추상화 과정에서 중요 정보를 부각시키지 못함해석자가 동일하게 공유하는 문맥이 없음적절한 추상화는 도메인 문맥 안에서, 중요한 핵심 개념만 남기는 것이름 짓기단수와 복수 구분끝에 -(e)s를 붙여 데이터가 단수인지, 복수인지 구분이름 줄이지 않기자주 사용하는 줄임말이 이해될 수 있는 것은 문맥 때문은어/방언 사용하지 않기일부/현재 팀원만 아는 용어 금지도메인 용어 사전 정의좋은 코드 보고 습득비슷한 상황에서 자주 사용하는 단어, 개념 습득메서드와 추상화한 메서드의 주제는 반드시 하나다.생략할 정보와 의미를 부여하고 드러낼 정보를 구분메서드 선언메서드명추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름파라미터와 연결지어 더 풍부한 의미 전달 가능파라미터타입, 개수, 순서를 통해 의미를 전달외부 세계와 소통하는 창반환 타입메서드 시그니처에 납득이 가는, 적절한 타입의 반환값 돌려주기void 대신 충분히 반환할 만한 값이 있는지 고민추상화 레벨하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.추상화 레벨을 주변 코드와 동등하게 구성매직 넘버, 매직 스트링의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등상수 추출로 이름을 짓고, 의미를 부여함으로써 가독성 및 유지 보수성이 상승한다.  [섹션 3]뇌 메모리 작게 쓰기인지한다는 것 자체가 메모리를 사용하는 것추상화를 통해서 인지할 정보를 추려내기Early Returnelse문을 쓴다는 것은 이전 if문의 조건을 기억해야 하는 것메모리 작게 쓰기의 중요성을 생각하면 이전 조건 기억을 줄여야 한다.빠른 return문을 통해 이전 조건을 기억하지 않도록 하는 기법사고의 depth 줄이기중첩 분기문, 중첩 반복문메서드 분리로 1차원 반복문으로 구성할 수 있다.중첩 구조가 사고하는 데 도움이 된다면 메서드 분리할 필요가 없다.사용할 변수는 가깝게 선언하기공백 라인을 대하는 자세공백 라인도 의미를 가진다. 복잡한 로직의 의미 단위를 나눔으로써, 읽는 사람에게 추가 정보 제공 가능부정어를 대하는 자세부정 연산자 코드는 가독성이 떨어지고, 생각하는 것 자체가 비효율적이다. 메서드 네이밍에 부정의 의미를 담는 것이 생각하기 더 편하다.부정어구를 쓰지 않아도 되는 상황인지 체크부정의 의미를 담은 다른 단어가 존재하는지 고민 or 부정어구로 메서드명 구성해피 케이스와 예외 처리예외가 발생할 가능성 낮추기어떤 값의 검증이 필요한 부분은 주로 외부 세계와의 접점사용자 입력, 객체 생성자, 외부 서버의 요청 등의도한 예외와 예상하지 못한 예외를 구분하기사용자에게 보여줄 예외와 개발자가 보고, 처리해야 할 예외 구분Null을 대하는 자세 (Optional에 관하여)Optional은 비싼 객체이다. 꼭 필요한 상황에서 반환 타입을 사용한다.Optional을 파라미터로 받지 않도록 한다. (분기 3가지)Optional이 가진 데이터가 null인지 아닌지 + Optional 자체가 null인지Optional을 반환받았다면 최대한 빠르게 해소분기문을 만드는 isPresent() - get() 대신 다른 API 사용ex) orElseGet(), orElseThrow(), ifPresent(), ifPresentOrElse()orElse() : 항상 실행, 확정된 값일 때 사용, 호출할 필요가 없을 도 실행orElseGet() : null인 경우 실행, 값을 제공하는 동작 정의orElseThrow() : null인 경우 실행, 예외 동작 정의 [섹션 4]추상의 관점으로 바라보는 객체 지향관심사의 분리, 높은 응집도, 낮은 결합객체 설계하기 (1)절차 지향에서 잘 보이지 않았던 개념을 가시화관심사가 한 군데로 모이기 때문에 유지보수성을 상승시킨다.객체 내부에서 객체가 가진 데이터의 유효성 검증 책임을 가질 수 있다.여러 객체를 사용하는 입장에서는 구체적인 구현에 신경쓰지 않고, 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다.새로운 객체를 만들 때, 주의할 점1개의 관심사로 명확하게 책임이 정의되어 있는지 확인하기생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다.setter 사용 자제, 외부 세계 데이터로 변경해야 하는 경우, update~ 같이 의도를 드러내는 네이밍을 쓰자.필드의 수는 적을수록 좋다.SRP : Single Responsibility Principle (단일 책임 원칙)하나의 클래스는 단 한 가지의 변경 이유만을 가져야 한다.객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경 되는가?관심사의 분리높은 응집도, 낮은 결합도OCP : Open-Closed Principle (개방 폐쇄 원칙)확장에는 열려 있고, 수정에는 닫혀 있어야 한다.추상화와 다형성을 활용해서 OCP를 지킬 수 있다.LSP : Liskov Substitution Principle (리스코프 치환 원칙)상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다.자식 클래스는 부모 클래스의 책임을 준수하며, 부모 클래스의 행동을 변경하지 않아야 한다.LSP를 위반하면, 상속 클래스를 사용할 떄 오동작, 예상 밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입 체크가 동반될 수 있다.ISP : Interface Segregation Principle (인터페이스 분리 원칙)클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다.ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.DIP : Dependency Inversion Principle (의존성 역전 원칙)상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.의존성의 순방향 : 고수준 모듈이 저수준 모듈을 참조하는 것의존성의 역방향 : 고수준, 저수준 모듈이 모두 추상화에 의존하는 것 저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다.  [섹션 5]상속과 조합상속은 시멘트처럼 굳어지는 구조, 수정이 어렵다.조합과 인터페이스를 활용하는 것이 유연한 구조상속을 통한 코드의 중복 제거가 주는 이점보다, 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 크다.Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급하기 위해서, 불변셩, 동등성, 유효성 검증 등을 보장해야 한다.불변성 : final 필드 사용, setter 금지동등성 : 서로 다른 인스턴스여도 내부의 값이 같으면 같은 값 객체로 취급equals() & hashCode() 재정의 필요유효성 검증 : 객체가 생성되는 시점에 값에 대한 유효성을 보장하기Value Object vs EntityEntity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급한다.Value Object는 식별자 없이, 내부의 모든 값이 다 같아야 동등한 객체로 취급한다.일급 컬렉션컬렉션을 포장하면서, 컬렉션만을 유일하게 필드로 가지는 객체컬렉션을 추상화하며 의미를 담을 수 있고, 가공 로직의 보금자리가 생긴다.만약, getter로 컬렉션을 반환할 일이 생긴다면, 외부 조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환, new 사용Enum의 특성과 활용Enum은 상수의 집합이며, 상수와 관련된 로직을 담을 수 있는 공간이다.특정 도메인 개념에 대해 그 종류와 기능을 명시적으로 표현해줄 수 있다.만약, 변경이 정말 잦은 개념은 Enum 보다 DB로 관리하는 것이 나을 수 있다.다형성 활용하기인터페이스 구현을 통하여 여러 개의 구현 클래스들을 인터페이스로 관리숨겨져 있는 도메인 개념 도출하기도메인 지식은 만드는 것이 아니라 발견하는 것객체 지향은 현실을 100% 반영하는 도구가 아니라, 흉내내는 것이다.설계할 때는 근식적, 거시적 관점에서 최대한 미래를 예측하고, 시간이 지나 만약 틀렸다는 것을 인지하면 언제든 돌아올 수 있도록 코드를 만들어야 한다.[Day2 Mission]ㅇhttps://taey-coding.tistory.com/75 [Day4 Mission]https://taey-coding.tistory.com/77

cleancode

성현규

인프런 워밍업 클럽 3기 백엔드 코드 스터디 1주차

정리. A. 추상1) 구체에서 중요한것만 남겨서 추상화 해야 한다. 2) 추상으로 부터 구체를 유추하지 못한 이유추상화 과정에서 중요한 정보를 부각 시키지 못했다.공유 문맥이 없다.중요한 정보의 기준이 다를 수 있다.도메인 영역별 추상화 기준이 다를 수 있다. 잘못된 추상화가 야기하는 side-effect가 크다.  3) 이름짓기줄임말. 자제하는 것이 좋으나 관용적인 경우도 있다. 문맥이 있는 경우에는 허용할 수 있다.(lat, lon)은어/ 방언 사용하지 않기.  좋은 코드를 보고 습득하기 4) 메서드와 추상화- 한 문단의 주제는 반드시 하나여야 한다.- 메서드는 하나의 일을 해야 한다. 5) 반환타입 메서드명 (파라미터) {}구성{} : 메서드 구현부반환타입 + 메서드명 + 파라미터 : 메서드 선언부메서드명 (파라미터) : 메서드 시그니처메서드명 추상화된 구체를 유추할 수 있는 적절한 의미가 담긴 이름파라미터와 연결지어 더 풍부한 의미를 전달할 수도 있다.파라미터파라미터의 타입, 개수, 순서를 통해 의미를 전달파라미터는 외부 세계와 소통하는 창반환타입메서드 시그니처에 납득 가는, 적절한 타입의 반환값 돌려주기Void대신 충분히 반환할 만한 값이 있는지 고민해보기. -> 반환값이 있다면 테스트도 용이.  * 한줄이라도 추상화를 하는지 -> 코드 크기보다 추상화로 부여하는 의미가 더 중요하다.6) 추상화 레벨외부세계 (추상화 레벨이 높다.)  내부세계( 추상화 레벨 낮다.)추상화 레벨을 맞춰주어서 읽다가 너무 구체적인 내용으로 나오지 않는지 체크. 7) 상수로 추출의미 가지고 있으나 상수로 추출 되지 않은 숫자, 문자열상수 추출로 이름을 짓고 의미를 부여함으로서 가독성과 유지보수성 높아진다.  B. 논리 사고의 흐름1) Early return을 해서 if문 복잡하게 만들지 말기2) 사고의 depth 줄이기:이해하기 복잡하다면 중첩문의 depth 줄이기변수 사용하는 곳 가까이 쓰기 3) 공백 라인: 의미를 어디서 나눌지에 대한 의미를 가진다.4) 부정어는 사용 지양.5) 예외처리해피케이스도 중요하지만 예외를 꼼꼼히 해야 소프트웨어가 견고해진다.예외 가능성을 낮추기 -> 의도와 다르게 동작하지 않도록 한다.외부와의 접점이 검증 필요사용자 입력, 외부 서버, 객체 생성자 등불신을 하면서 검증하며 신뢰를 쌓아간다.의도한 예외랑 의도치 않은 예외 검증 * Optional : orElse(항상 실행), orElseGet(null인 경우만 실행)  C. 객체 지향 패러다임1) 객체로 추상화비공개 필드, 비공개 로직공개 매서드의 선언을 통해 외부와 소통(퍼블릭 인터페이스)객체의 책임이 나뉨에 따라 객체간 협력 발생2) 객체가 제공하는 것절차 지향에서 잘 보이지 않았던 개념을 가시화관심사가 한군데로 모임.클라이언트는 구현에 신경 쓰지 않고 추상화 레벨에서 도메인 로직 사용 가능.3) 새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임 정의 되었는지 확임.객체를 만듦으로써 외부 세계와 어떤 소통을 하려고 하는지 생각.생성자, 정적 팩토리 메서드에서 유효성 검증이 가능도메인에 특화된 검증 로직이 들어갈 수 있다.Setter 사용 자제 -> 의도 드러내는 메서드로 사용getter도 처음에는 사용 자제하고 반드시 필요한 경우 추가.외부에서 객체 내 데이터가 필요하다고 getter 남발은 무례하다. (또한, 의도를 드러내자)객체에 메세지를 보내기필드의 수는 적을 수록 좋다.소나큐브에서는 7개를 권장한다.4) SOLIDSRP : 단일 책임 원칙 응집도를 높이고 결합도를 낮추기 위한 방법.클래스가 변경되는 이유는 하나여야 한다.테스트가 용이하도록 만들어야 한다. OCP : 개방 패쇄의 원칙 개방 폐쇄의 원칙은 확장에는 열려있고 수정에는 닫혀있다.중요한 것은 코드 변경없이 클래스의 추가만으로 확장 가능해야한다.  LSP : 리스코프 치환 원칙 자식은 부모의 인스턴스로 치환 가능해야 한다. 부모 객체가 쓰이는 곳을 자식으로 모두 바꾸어도 바뀌는 것 없이 작동해야 한다. ISP: 인터페이스 분리 원칙 SRP를 지킬 수 있도록 거대 인터페이스를 만들지 말고 기능별 분리한다.응집도를 높이며 결합도를 낮춘다. DIP: 의존성 역전 원칙 기존 고수준 모듈이 저수준 모듈을 의존하는 것을 모두 추상화에 의존하게 만든다.결과적으로 서로의 결합도를 낮추고 책임과 메시지만 남는다. 미션을 진행하며 배운점.: 혼자서 객체지향관련 책들을 읽고 프로젝트에 적용해보았지만 정리가 안된 느낌이 강했습니다. 그런데 강의를 들으면서 한번 더 복습하게 되고 멘토님은 어떤 방법이 유용하였고 중요한지 정리해 주셔서 좋다고 생각했습니다. 강의를 들을 수록 이전의 코드들을 되돌아 보게 되네요. 실습을 해보면서 복습도 되고 또 고민했던 부분들에 대해 인사이트를 얻게 되어서 좋습니다. 특히 이번 과제에서는 객체의 책임을 나눌때 "기능적으로 분리"를 해도 되는지 이전 개인 프로젝트에서도 고민이 많았는데 이번 과제를 하면서 어떻게 해야 될지 인사이트가 생겨서 그렇게 개인 프로젝트도 리팩토링 해 보았네요 ㅎㅎ

백엔드cleancodesolidooprefactoring

masiljangajji

[인프런 워밍업 클럽 2기 1주차 회고] - 그래서 클린코드가 뭐냐

클린 코드는 무엇일까요? 보통 "읽기 좋은 코드"라는 말을 하곤 합니다.그런데 "읽기 좋다"는 무엇을 의미할까요? 주석을 아예 달지 않으면 읽기 좋은 코드일까요? 이건 좀 아닌 것 같고...변수의 이름을 잘 짓는 것? 이것만으로는 좀 부족한 것 같고... 이런 고민을 해결하고자 클린 코드 & 테스트 스터디에 참여해 활동한 지 1주 차가 됐습니다. 첫 주차는 객체 지향의 가장 기본이 되는 "추상화"에 대해서 말하는 시간이었습니다.물리적으로 나뉜 세션은 여러 가지였지만, 다룬 내용들이 대부분 "추상화"를 뒷받침하는 요소였기 때문에 1주 동안 추상화에 대해서 말했다 해도 괜찮을 것 같습니다. 그리고 이 부분은 매우 중요하다고 생각하는 것이, 기본이 곧 쉽다는 의미는 아니기 때문입니다.기본은 너무나 중요해서 기본이라 부르는 것이지, 쉬워서 기본이라 부르는 것은 아니니까요. 스터디의 진행은 기본적으로 인프런을 통해 온라인으로 학습하고 미션을 통해 학습도를 점검하는 방식으로 진행됩니다.1주차 미션 자체는 실질적으로 코드를 작성하여 검증하는 느낌은 아니었고, "나는 강의에서 이렇게 말했는데, 너는 어떻게 생각해?"라는 느낌이었습니다.그 생각을 묻는 질문에 대한 답변이 곧 미션이고, 저의 경우에는 블로그에 글을 기재하는 방식으로 수행했습니다.https://masiljangajji-coding.tistory.com/66https://masiljangajji-coding.tistory.com/68 이 글에서 가장 하고 싶은 말은 "클린 코드", "TDD", "DDD" 등은 그저 도구라는 것입니다.저 모든 것들은 단순히 "이렇게 하면 좋다더라~"를 한 단어로 묶어 개념화한 도구입니다.따라서 도입하는 것이 생산성을 높이면 도입하면 되는 것이고, 떨어지면? 도입하지 않아도 됩니다. 주석을 달았더니 팀이 코드를 더 쉽게 이해하고 생산성이 증가하는데? -> 그럼 주석을 다는 게 클린 코드입니다.주석을 다는 행위로 인해 코드의 가독성이 증가했기 때문입니다. 소프트웨어를 개발하는 사람들은 생각도 soft하게 할 필요가 있지 않나 생각합니다.어떻게 커스터마이징하느냐에 따라서 우리 팀만의 클린코드 컨벤션이 존재할 수 있다고 생각합니다. 한 줄로 정리하면, XX를 하면 클린 코드? XX를 안 하면 클린 코드? 이런 게 아니라,생산성을 증가시키면 그게 뭐가 됐든 클린 코드라 생각합니다. 강의 내용에 대해서 말하자면 평소에 생각하던 부분들과 일치하는 부분이 많아 그리 어렵지 않게 들을 수 있었습니다.그런데 가끔 "아, 이렇게도 생각할 수 있네?", "이런 게 기준이 될 수 있겠네?" 하는 부분들이 있어 생각했던 것보다 이미 많은 것을 얻어간 느낌입니다. 사실 강의 자체의 퀄리티가 좋습니다. ㅋㅋㅋ 이번 주는 강의를 듣고 미션을 수행하는 것이 조금 버거웠습니다.강의의 양 자체가 적지 않기도 했고, 더 우선적으로 수행해야 할 과제들이 있어 더욱 그러지 않았나 생각됩니다. 주말 동안 재충전의 시간을 갖고 돌아오는 월요일부터는 다시 달려보도록 하겠습니다.

백엔드백엔드클린코드cleancodecleancoderedable

채널톡 아이콘