Robinjoon’s Develop Blog
Search
독서록
독서록
Search
준비 실행 검증 패턴을 사용한 단위 테스트 구성법
3장 : 단위 테스트 구조
단위 테스트
2024/04/02
단위 테스트의 정의
1.
작은 코드 단위를 테스트,
2.
빠르게 수행하고,
3.
격리된 방식으로 처리하는 자동화된 테스트
격리가 무엇인지에 대한 의견 차이가 디트로이트 학파와 런던 학파를 나눈다.
격리에 대한 의견 차이는 테스트 단위에 대한 차이로 이어진다.
런던 학파
테스트 대상 시스템을 협력자에서 격리하는 것 ⇒ 테스트 대상 클래스의 모든 의존성을 테스트 대역(test double)로 대체해야 한다. ⇒ 장점 : 테스트가 실패하면 어디가 고장난건지 확실히 알 수 있다, 객체 그래프(객체 사이의 의존성을 그래프로 그린 것)을 중간에 끊어내고 테스트를 더 간단하게 할 수 있다.
단위 = 단일 클래스
테스트 대역 = 불변 의존성 제외한 모든 의존성
디트로이트 학파
단위 테스트를 격리하는 것 ⇒ 공유 의존성을 데스트 대역으로 대체하는 것
공유 의존성 : 테스트 간에 공유되고 서로의 결과에 영향을 미칠 수 있는 수단을 제공하는 의존성. 정적 가변 필드, 데이터베이스 등이 이에 해당된다. 비공개 의존성 : 공유하지 않는 의존성 프로세스 외부 의존성 : 애플리케이션 실행 프로세스 외부에서 실행되는 의존성. 보통은 공유 의존성이나, 꼭 공유 의존성인 것은 아니다. 예를 들어 데이터베이스는 프로세스 외부 의존성이지만, 테스트마다 컨테이너를 이용해 다른 데이터베이스를 실행시킨다면 공유 의존성은 아니다.
2장 단위 테스트란 무엇인가?
단위 테스트
2024/04/02
그룹화
Collectors.groupigBy
특정 기준에 따라 스트림의 요소를 그룹화 하여 Map으로 만들 수 있다.
만약, 위와 같이 분류된 각각의 리스트에 필터링을 걸고 싶다면, Collectors.filtering()을 사용할 수 있다.
예를 들어 가격이 1000 이상인 것만 남기고 싶다면 다음과 같이 하면 된다.
만약, 위와 같이 분류된 각각의 리스트에 map 을 적용하고 싶다면, Collectors.mapping을 사용할 수 있다.
위와 같이 코드를 작성하면 이름 리스트가 value인 map이 생성된다.
두번째 인자로 또 다른 groupBy를 넣으면, 여러 수준의 그룹화가 가능하다.
분할
Collectors.partitioningBy
6장 : 스트림으로 데이터 수집
IT / 언어
모던 자바 인 액션
정리 완료
2024/02/26
필터링
filter 메서드
Predicate 를 이용해 특정 조건에 맞는 요소만 남기는 필터링이 가능하다.
단, 별도의 연산을 추가하지 않는다면, filter 메서드는 모든 요소에 대해 검사하기 때문에 전체 순회가 발생한다.
distinct 메서드
equals 메서드와 hashCode 메서드로 결정되는 동일한 요소는 하나만 포함하도록 필터링한다.
equals 와 hashCode가 적절하게 정의되어있지 않으면 의도대로 동작하지 않을 수 있기 때문에 주의해야 한다.
스트림 슬라이싱
stream의 일부 영역을 잘라낸 stream을 얻는 메서드 들이다.
takeWhile & dropWhile
Predicate를 이용해 각각 조건에 맞지 않는 요소가 처음 나왔을 때까지 탐색한 요소를 포함하는 stream, 조건에 맞지 않는 요소가 처음 나왔을 때까지 탐색한 요소를 제외한 steream 을 생성한다.
만약, totalMenus가 이미 가격 순으로 오름차순 정렬되었다면 위 코드를 통해 가격이 3000 미만인 메뉴가 선택될 것이다.
5장 : 스트림 활용
IT / 백엔드
IT / 언어
모던 자바 인 액션
정리 완료
2023/09/18 → 2023/09/24
스트림 이란?
자바 8에서 새로 추가된 API 로, 선언형으로 컬렉션을 다룰 수 있게 해주고, 손쉽게 병렬처리를 할 수 있도록 해주는 API이다.
스트림의 우수성
다음 코드는 스트림 없이 작성한 저칼로리의 요리를 반환하는 코드다.
기존의 프로그래밍에 익숙한 사람은 금방 이해할 수 있지만, 임시 변수들도 여럿 사용되었고, 장황한 코드가 많다.
아래는 Stream을 이용한 코드다.
훨씬 알아보기 쉬운 코드가 작성되었다. 심지어
stream()
대신
parallelStream()
을 호출하면 알아서 멀티코어에서 실행된다.
스트림의 정의와 특징
스트림은 ‘데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소’로 정의할 수 있다.
•
연속된 요소 : 컬렉션처럼 스트림은 특정 형식의 요소의 집합에 대한 인터페이스이다. 컬렉션과 다른 점은 요소 저장이나 접근 연산이 아닌, 표현 계산식이 주를 이룬다. 즉,
컬렉션은 데이터 그 자체가 주제이고, 스트림은 계산이 주제이다.
•
소스 : 스트림은 컬렉션, 배열, I/O 자원 등의 데이터 소스로부터 데이터를 소비한다. 데이터 소스의 요소 순서를 유지한다.
•
데이터 처리 연산 : 함수형 프로그래밍에서 일반적으로 제공하는 연산과 데이터베이스와 비슷한 연산을 제공한다.
filter
,
map
,
reduce
,
find
,
sort
등의 연산을 통해 데이터를 조작할 수 있다. 이런 연산들은
순차적으로 혹은 병렬적
으로 실행할 수 있다.
4장 : 스트림 소개
IT / 백엔드
IT / 언어
모던 자바 인 액션
정리 완료
2023/09/11 → 2023/09/17
4
람다 표현식
람다 표현식 이란?
익명함수를 단순화 한 것. 람다 표현식을 사용하면 동작 파라미터를 이용하는 코드를 더 쉽고 간결하게 작성할 수 있다.
람다 표현식의 구조
•
매개변수 리스트
•
화살표
•
람다 바디
함수형 인터페이스
람다 표현식은 함수형 인터페이스를 표현하는 문맥에서만 사용할 수 있다.
함수형 인터페이스란 추상 메서드를 한개만 가지는 인터페이스이다. 디폴트 메서드나 정적 메서드와는 무관하다.
람다 표현식은 결과적으로 함수형 인터페이스를 구현한 클래스의 인스턴스로서 동작한다.
람다식 활용 : 실행 어라운드 패턴
초기화&준비 코드와 정리&마무리 코드가 실제 작업 코드 앞뒤에 등장하는 형태의 패턴을 실행 어라운드 패턴이라 한다.
3장 : 람다 표현식
IT / 백엔드
IT / 언어
모던 자바 인 액션
정리 완료
2023/09/09
7장부터 11장은 설계 원칙을 다룬다. SOLID 말이다. 이 원칙은 중간 수준의 소프트웨어 구조가 변경에 유연하고, 이해하기 쉽고, 많은 소프트웨어 시스템에 사용할 수 있는 컴포넌트의 기반이 된다. 중간수준이라는 것은 이 원칙을 모듈 수준에서 작업할 때 적용할 수 있다는 뜻이다. 코드 수준보다 조금 상위의 모듈과 컴포넌트 내부에서 사용되는 소프트웨어 구조를 정의하는데 도움을 준다.
SRP 원칙은 모듈이 단 하나의 일만 해야 한다는 의미가 아니다. 이런 원칙은 더 낮은 수준 즉, 코드 수준에서 사용된다.
SRP 원칙
SRP 원칙의 정의
단일 모듈은 변경의 이유가 하나, 오직 하나뿐이어야 한다.
소프트웨어 시스템은 사용자와 이해관계자를 만족시키기 위해 변경된다. 변경의 이유는 곧 시용자와 이해관계자를 가리킨다. 따라서 SRP는 다음과 같이 바꿔 말할 수 있다.
하나의 모듈은 하나의, 오직 하나의 사용자 또는 이해관계자에 대해서만 책임져야 한다.
시스템이 같은 방식으로 변경되기 원하는 사람이 여러명일 수 있기 때문에 이는 집단으로 표현해야 한다. 이를 액터(actor)라고 하자.
하나의 모듈은 하나의, 오직 하나의 액터에 대해서만 책임져야 한다.
모듈은 쉽게 소스파일이라 생각하면 된다. 만일 코드가 소스 파일에 저장되지 않는다면 모듈은 단순히 함수와 데이터 구조로 구성된 응집된 집합이다.
SRP를 위반하는 징후
우발적 중복
Employee 클래스에 calcutePay(), reportHours(), save()메서드가 있다. 이 클래스는 SRP 원칙을 위배한다.
•
calcutePay() : 회계팀에서 기능을 정의 ⇒ CFO에게 보고를 위해 사용
•
reportHours() : 인사팀에서 기능을 정의 ⇒ COO에게 보고를 위해 사용
7장 : SRP, 단일 책임 원칙
IT / 이론
클린아키텍처
2023/06/07
함수형 프로그래밍 개요
함수형 프로그래밍은 사례로 설명하는 것이 가장 좋다.
자바에서 0부터 9까지의 수의 제곱을 출력하려면 이렇게 한다.
함수형 언어인 클로저를 이용하면 이렇게 한다.
•
range 함수는 0 부터 시작해서 끝이 없는 정수 리스트를 반환한다.
•
map 함수는 range 함수가 반환한 리스트를 제곱을 반환하는 익명함수를 이용해 끝이 없는 정수 제곱 리스트를 생성한다.
•
제곱된 리스트는 take 함수로 전달되고, 10 개만 선택되어 println 함수에 전달된다.
눈여겨 봐야 할 것은 자바에서는 i 가 매번 변했지만, 클로저에서는 어떤 순간에도 변수의 값이 변경되지 않았다는 점이다. 즉, 함수형 언어에서 변수는 변경되지 않는다.
불변성과 아키텍처
변하지 않는다면 경합 조건, 교착상태 조건, 동시 업데이트 등이 발생할 수 없다. 당연한 말이지만, 어떤 변수도 갱신되지 않는다면 경합 조건이나 동시 업데이트가 발생할 수 없고, 락이 가변적이지 않으면 교착상태 역시 발생할 수 없다.
다수의 스레드와 프로세스로 인해 발생하는 문제는 가변 변수가 없으면 생기지 않는다.
물론, 현실적으로 가변 변수 없이 시스템을 만드는 것은 불가능하기 때문에 타협해야 한다.
가변 컴포넌트와 불변 컴포넌트의 분리
6장 : 함수형 프로그래밍
IT / 이론
클린아키텍처
정리 완료
2023/05/14
객체지향이 무엇인가?
객체지향을 “데이터와 함수의 조합” 이나 “실제 세계를 모델링 하는 새로운 방법” 으로 설명하는 것은 부족하고 모호한 설명이다.
객체지향을 캡슐화, 상속, 다형성을 통해 설명하는 경우도 있다. 이것이 객체지향의 본질인지 알기 위해선 이것들이 무엇인지를 알아야 한다.
캡슐화
캡슐화는 데이터와 함수를 응집하고, 구분선을 그어 외부에선 내부의 데이터는 은닉되고, 일부 함수들만이 공개되는 것이다.
캡슐화는 객체지향 프로그래밍에 국한된 개념이 아니다. 물론, 객체지향 언어에서 캡슐화를 쉽게 할 수 있는 도구들을 제공해주지만, 동시에 캡슐화를 불안전하게 만든다.
C언어에서도 .h 와 .c 를 분리해서 정보를 감추는 것이 가능하다. 오히려 자바에서의 private, public 을 이용한 캡슐화보다 더 강력하다.
point.h 에 struct 를 선언하고, struct 포인터를 만드는 함수를 선언하고, struct 를 사용하는 함수를 선언한 뒤, point.c 에서 이들을 정의하면, point.h를 include해서 사용하는 main.c 에서는 구조체의 내부에 접근할 수 없다. 심지어, point.c 를 변경하고 싶으면 변경한 뒤 point.c 만 컴파일하면 main.c 은 건들 필요가 없다.
결론
캡슐화는 객체지향의 본질이 아니다.
상속
상속은 결국 변수와 함수를 감싸 하나의 유효범위로 묶어서 재정의하는 것이다.
객체지향 언어는 상속을 편하게 그리고 안전하게 할 수 있도록 해준다. 하지만, 상속이 객체지향 프로그래밍에 국한된 개념은 아니다. C 언어에서도 구조체와 함수 포인터, 형변환을 사용해 상속을 구현 할(흉내 낼) 수 있다. 다만, 이런 방법은 프로그래머가 이를 의도적으로 따라야만 잘 작동한다는 단점이 있다. 객체지향 언어는 상속을 쉽게 할 수 있도록 해준다.
다형성
다형성은 다양한 것으로 하나의 것을 할 수 있는 것이다. STDIN, STDOUT 이 그 예시
5장 : 객체지향 프로그래밍
IT / 이론
클린아키텍처
정리 완료
2023/05/13
데이크스트라의 발견
모든 프로그램은 순차, 분기, 반복으로 표현할 수 있다.
기능적 분해
모듈을 기능적으로 나누는 것을 의미한다.
거대한 문제 기술서를 받아도, 문제를 고수준의 기능들로 분해할 수 있고, 이렇게 분해된 모듈은 제한된 제어구조(순차, 분기, 반복)를 이용해 표현할 수 있다. 이를 토대로 70~80년대에 구조적 분석, 구조적 설계같은 기법이 등장해서 인기를 끌었다.
구조적 프로그래밍은 프로그램을 증명 가능한 세부 기능 집합으로 분해하고, 이를 테스트를 통해 세부 기능들이 거짓(잘못된)임을 증명하려고 시도한다. 테스트를 모두 통과하면 목표에 부합할 만큼 충분히 참이라고 여긴다.
구조적 프로그래밍의 가치
구조적 프로그래밍의 가치는 프로그래밍에서 반증 가능한 단위를 만들어내는 것에 있다.
현대적 언어에서 아무 제약 없는 goto 문장을 지원하지 않는 이유이고, 아키텍처 관점에서 기능적 분해를 최고의 실천법 중 하나로 여기는 이유다.
소프트웨어 아키텍트는
모듈
,
컴포넌트
,
서비스
가 쉽게 반증 가능하도록 만들기 위해 분주히 노력해야 한다.
4장 : 구조적 프로그래밍
IT / 이론
클린아키텍처
정리 완료
2023/05/13
소프트웨어 아키텍처는 코드로부터 시작한다. 코드는 언어와 프로그래밍 패러다임이 발전하면서 변화했다. 따라서, 소프트웨어 아키텍처를 이야기 하기 위해서는 프로그래밍 패러다임을 이야기 해야 한다.
구조적 프로그래밍
구조적 프로그래밍은
무분별한 goto가 해롭다는 사실
에서 출발한다. if/then/else do/while/for 등의 구조를 이용해 goto 대체한다.
구조적 프로그래밍
은
제어흐름의 직접적인 전환에 대해 규칙을 부과한다.
객체지향 프로그래밍
함수 호출 스택 프레임을 힙 영역
으로 옮겨 함수에서 선언된 지역변수를 오래 유지시키는 아이디어에서 등장했다. 이 과정에서, 클래스, 생성자, 인스턴스 변수, 메서드 등의 개념이 생겼다.
객체지향 프로그래밍
은
제어흐름의 간접적인 전환에 대해 규칙을 부과한다.
함수형 프로그래밍
수학의 람다 계산법을 프로그래밍에 도입
한 것이다. 람다 계산법의 기초가 되는 개념은 기본적으로 심볼의 값이 변경되지 않는다는 불변성이다.
함수형 프로그래밍
은
할당문에 대해 규칙을 부과한다.
각 패러다임은 프로그래머로부터 뭔가를 뺏어갔다. 더이상 뺐을게 없기 때문에 새로운 패러다임은 등장하지 않을 것.
패러다임과 아키텍처
객체지향
의
다형성
을 이용해
아키텍처의 경계를 넘어간다.
함수형 프로그래밍
을 통해
데이터의 위치와 접근 방법에 대한 규칙을 부과한다.
3장 : 패러다임 개요
IT / 이론
클린아키텍처
2023/05/11
소프트웨어 시스템은 이해당사자에 행위와 아키텍처 라는 두가지 가치를 제공한다.
개발자는 두가지를 모두 챙겨야 하지만, 현실은 두가지중 덜 중요한 것을 챙기기 위해 중요한 것을 버리는 경우가 많다.
행위
프로그래머는 기능 명세서나 요구사항 문서를 구체화하고, 소프트웨어가 어떤 행위를 하도록 만든다. 소프트웨어가 이를 위반하면 고치는 것이 프로그래머가 해야 할 일이다.
그러나 이런 일이
프로그래머가 해야할 일의 전부가 아니다.
아키텍처
소프트웨어는 soft(부드러운)와 ware(제품)의 합성어다. 즉,
소프트웨어
는 ‘부드러움을 지니도록’ 만들어졌다. 부드러움을 지닌다는 것은
변경하기 쉬워야 한다
는 말이다.
변경사항 적용의 어려움은 변경의 범위에 비례해야 하고, 변경되는 형태와는 관련이 없어야 한다.
아키텍처는 형태에 독립적
이어야한다.
기능과 아키텍처 중 더 중요한 가치
업무 관리자(시스템 사용자)는 당장 원하는 기능이 동작하는 것을 더 중요하게 여길 것이다. 하지만, 개발자는 이 의견에 동조해서는 안된다. 변경이 가능하면 기능이 잘 동작하도록 수정할 수 있기 때문.
아이젠하워 매트릭스
긴급한 문제가 아주 중요한 경우와, 중요한 문제가 아주 긴급한 경우는 거의 없다. 행위는 긴급하지만 매번 높은 중요성을 가지지 않는다. 아키텍처는 중요하지만 즉각적인 긴급성은 가지지 않는다.
우선순위
1.
중요O 긴급O
2.
중요O 긴급X
2장 : 두가지 가치에 대한 이야기
IT / 이론
클린아키텍처
정리 완료
2023/05/10
4
소프트웨어가 동작하도록 하는 것은 쉽다. 소프트웨어를 올바르게 만드는 것은 매우 어렵다. 제대로 만든 시스템 설계와 아키텍처는 아주 적은 인력으로 새로운 기능을 추가하거나 유지보수 할 수 있도록 해준다.
설계와 아키텍처.
설계를 저수준으로, 아키텍처를 세부사항에서 분리된 고수준의 것으로 구분하는 것은 무의미하다. 저수준의 세부사항과 고수준의 구조 모두 소프트웨어 전체 설계의 구성요소이기 때문. 둘은 개별로 존재할 수 있는 것이 아니고, 둘을 구분짓는 경계도 뚜렷하지 않다.
좋은 소프트웨어 설계의 목표
필요한 시스템을 만들고 유지보수하는 데 투입되는 인력을 최소화 하는 데 있다.
설계 품질을 재는 척도는 고객의 요구를 만족시키는데 드는 비용을 재는 척도와 같다. 즉,
기능을 추가
할 때 마다
비용이 증가
한다면
나쁜 설계
다.
코드 정리를 나중으로 미루는 개발자는 결코 코드를 정리하지 않는다. 이것이 반복되고 쌓이면 생산성은 0을 향해 수렴한다.
지저분한 코드는 장기적인 시각에서는 물론 단기적인 시각에서도 항상 깔끔한 코드보다 생산성이 낮아진다.
빨리 가는 유일한 방법은 제대로 가는 것이다.
결론
소프트웨어 아키텍처의 품질을 진지하게 고민하는 것을 하루라도 빨리 하는 것이 좋다.
비용을 최소화하고, 생산성은 최대화 하려면
시스템 아키텍처의 속성을 알아야 한다.
1장 : 설계와 아키텍처란?
IT / 이론
클린아키텍처
정리 완료
2023/04/23
4