2021 04 21 학습로그정리
조엘의 학습로그¶
[OOP] 일급 컬렉션 - 3¶
내용¶
- 비즈니스에 종속적인 자료구조 생성
- 불변성을 보장함으로써 부작용 최소화
- 상태와 행위를 한 곳에 관리하도록 함
- 이름이 있는 컬렉션으로, 의미 부여 가능
링크¶
[OOP] 정적 팩토리 메서드 - 3¶
내용¶
- 객체 생성의 역할을 하는 클래스 메서드
- 이름이 있어, 가독성이 좋아짐
- 호출할 때마다 새로운 객체 생성하지 않아도 됨
- 객체 생성을 캡슐화 할 수 있음
링크¶
- https://johngrib.github.io/wiki/static-factory-method-pattern/
- https://velog.io/@ljinsk3/%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C%EB%8A%94-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C
[OOP] DTO - 2¶
내용¶
- 계층 간 통신 용도로 오가는, 데이터 교환을 위한 객체
- 로직이 없는 순수한 데이터 객체로, getter와 setter만을 가짐
링크¶
[JDK] BigDecimal - 2¶
내용¶
- 부동 소수점 연산을 정확하게 수행하도록 지원
- 돈을 다룬다면 필수로 써야함
링크¶
- http://javamoods.blogspot.com/2009/03/how-big-is-bigdecimal.html
- https://www.geeksforgeeks.org/bigdecimal-class-java/
- https://jsonobject.tistory.com/466
[JDK] Stream API - 3¶
내용¶
- Stream API를 활용한 데이터 처리
링크¶
[Design Pattern] 전략 패턴 - 2¶
내용¶
- 랜덤한 값을 테스트하기 위해 인터페이스로 분리, 테스트 가능한 구조로 변경
- 구조 - Context: 갖고 있는 전략 콘크리트에 따라 행동이 달라짐 - Strategy: 제공하는 알고리즘에 대한 공통의 연산들을 interface로 정의 - Strategy Concrete Class: 실제 알고리즘
- 장점 - 상속을 사용하지 않음 - if문의 제거를 가능하게 한다 - 구현의 선택이 가능해진다
- 단점 - 객체 수 증가 - 서로 다른 전략을 이해해야 함
링크¶
- https://velog.io/@lxxjn0/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EB%B6%84%EB%A6%AC%ED%95%98%EC%97%AC-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%98%EA%B8%B0-%EC%A2%8B%EC%9D%80-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0
- https://www.youtube.com/watch?v=zGJzEBOELoU
[OOP] 응집도와 결합도 - 2¶
내용¶
- 응집도: 모듈 내부의 기능적인 집중 정도
- 결합도: 모듈과 모듈간의 상호 의존 정도
- 독립적인 모듈이 되기 위해서는 응집도는 강하고, 결합도는 약해야 한다
링크¶
- https://raisonde.tistory.com/entry/%EA%B2%B0%ED%95%A9%EB%8F%84Coupling%EA%B3%BC-%EC%9D%91%EC%A7%91%EB%8F%84Cohension
- https://medium.com/@shaul1991/%EC%B4%88%EB%B3%B4%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9D%BC%EC%A7%80-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EB%AA%A8%EB%93%88%EA%B3%BC-%EB%AA%A8%EB%93%88%ED%99%94-%EA%B2%B0%ED%95%A9%EB%8F%84-%EC%9D%91%EC%A7%91%EB%8F%84%EC%9D%98-%EC%9D%B4%ED%95%B4-44af52e03a91
[JDK] Stream.forEach vs Collection.forEach - 2¶
내용¶
- Stream.forEach - Stream 객체를 생성한 후에 forEach 메서드 호출 - 따라서 중간 연산에 해당하는 로직과 함께 써야 유의미하게 Stream을 사용한 것 - 반복 도중에 다른 쓰레드에 의해 수정될 수 있다 - parallelStream을 통해 여러 쓰레드에서 스트림을 실행할 수 있다 - 무조건 요소의 끝까지 반복을 돌게 된다.
- Collection.forEach - 따로 객체를 생성하지 않고 forEach 메서드 호출 - forEach 메서드는 Iterable 인터페이스의 default 메서드 - Collection 인터페이스에서 Iterable 인터페이스를 상속하기에 바로 사용한다. - 인터페이스는 인터페이스를 상속 받을 수 있다 (다중 상속도 가능하다!) - 멀티쓰레드 환경에서 락이 걸려있기에 더 안전하게 사용할 수 있다
링크¶
- https://woowacourse.github.io/javable/post/2020-09-30-collection-stream-for-each/
- https://woowacourse.github.io/javable/post/2020-05-14-foreach-vs-forloop/
[OOP] Enum 활용 - 1¶
내용¶
- 정의 - 관련한 상수 Singleton 객체의 모음집 - 컴파일 당시, 가능한 모든 값을 안다면 Enum 활용을 고려할 것
- 장점 - Java의 Enum은 상태와 행위를 동시에 관리할 수 있다 - 컴파일 시에 정의한 타입 이외의 타입에 대해 오류를 발생시킨다
링크¶
- https://limkydev.tistory.com/50
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-02-19.md#%EC%9E%90%EB%B0%94-enum
- https://www.youtube.com/watch?v=AVVWaRg6Q3A&t=327s
[JDK] new ArrayList<>() vs Arrays.asList() - 2¶
내용¶
- new ArrayList<>() - java.util.ArrayList 소속 - List에 대한 모든 operation을 쓸 수 있음 - new로 생성해주기에, 넘겨받은 원본 리스트에 대한 참조는 끊는다 - 여기서 참조를 끊는다는 것은, 새로운 주소에 List를 만들고, 넘겨받은 List들의 원소를 하나하나 복사해주어 만들어 반환한다는 것 - 넘겨준 원본 List에 add, remove등의 연산을 해도 새롭게 만든 ArrayList에는 영향이 가지 않는다 - 하지만 List안에 들어있는 객체들은 그대로 얕은 복사가 되기 때문에 넘겨준 원본 List에서 원소로 가지고 있는 객체의 필드값을 조작하면, 새롭게 만든 ArrayList 내의 원소로 포함된 객체에도 영향을 미친다.
- Arrays.asList() - java.util.Arrays.ArrayList 소속 - 읽기만 가능한 List - add(), remove() 메서드를 통해 해당 list에 원소를 추가/삭제하려고 하면... - "UnsupportedOperationException"을 반환 - 원본 배열의 참조도 끊지 않는다. 즉 얕은 복사로 주소를 공유한다. - List 형태로 배열을 포장한 것이라고 보면 됨
링크¶
- https://unluckyjung.github.io/java/2021/03/07/Java-Arrays.asList-VS-newArrayList/
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-09.md#arraysaslist-vs-new-arraylist
[JDK] HashMap vs LinkedHashMap - 3¶
내용¶
- HashMap - 중복된 원소를 허용하지 않으며, 순서도 고려되지 않음 - HashMap은 key와 value를 저장하는 두개의 배열로 구성되어 있음 - Key값이 어디에 저장될지는 다음과 같이 정의됨 - Key값으로 저장할 Object의 hashCode()를 구한다 - 정수로 반환된 hashCode() 값을 버킷의 수로 나눈 나머지를 구한다 (초기 버킷 수는 16개) - 그렇게 구한 값이 배열의 index가 된다 - 해당 index에 Object를 저장한다
- LinkedHashMap - HashMap과 동일하게 데이터를 저장 - 하지만 Doubly-Linked-List를 통해 데이터 저장 순서를 동시에 기록함 - 따라서, 데이터가 저장된 순서대로 접근할 수 있음
링크¶
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-09.md#hashset-vs-treeset-vs-linkedhashset
- https://d2.naver.com/helloworld/831311
[JDK] 함수형 인터페이스 - 3¶
내용¶
- 람다식 - 메서드를 하나의 "식"으로 표현한 것 - 따라서 메서드의 역할을 람다식으로 대체할 수 있음 - 이는 일급객체로, 변수처럼 다루게 되었음
- 함수형 인터페이스 - Java의 모든 메서드는 클래스/인터페이스 내에 포함되어 있어야 호출할 수 있다 - 람다식의 소속 클래스는 익명 클래스이다 - 익명 클래스: 클래스의 선언과 객체 생성을 동시하는, 한 번만 사용될 수 있고 오직 하나의 객체만을 생성할 수 있는 일회용 클래스 - 하나의 메서드가 선언된 인터페이스를 정의하여, 람다식을 다루게 된다 - @FunctionalInterface 어노테이션 추가하여 정의 - 하나 이상의 메서드를 인터페이스에 추가하려는 경우, 컴파일 에러 발생 - 결국 해당 인터페이스를 매개변수로 넘겨주고, 인터페이스 내부에 있는 하나의 메서드를 실행하는 방식으로 사용
- java.uti.function 패키지
- 자주 쓰이는 형식의 메서드를 함수형 인터페이스로 정의해놓음
- 재사용성/유지보수를 위해 가능한 이 패키지의 함수형 인터페이스를 활용하자
- https://github.com/woowacourse/java-blackjack/pull/193/commits/d472685930c7ccd0a9f7ec03a918de237e6549b1
- 해당 커밋에서 사용한 BiFunction
함수형 인터페이스는... - 두 개의 Integer 형식의 매개변수를 받아, Boolean 타입의 결과를 반환하는 함수 - 나머지 사용법은 아래 링크 참조
링크¶
[OOP] VO - 3¶
내용¶
- 정의 - 도메인에서 한 개 혹은 그 이상의 속성들을 묶어서 "특정 값"을 나태내는 객체 - ex) 좌표, 금액, 날짜 등
- 특징 - equals, hashCode 메서드를 재정의 할 것 - 값 자체를 나타내는 객체이기에, 내부의 속성과 타입이 같다면 같은 VO로 보는 것이 타당하다 - 불변객체로 만들 것 - VO는 속성값 자체가 해당 객체의 고유한 식별값으로, 내부 속성값을 바꿀 수 있게 하면 안 된다
링크¶
[Design Pattern] 상태패턴 - 3¶
내용¶
- 정의 - 기능이 "상태"에 따라 다르게 동작해야 할 때 사용하는 패턴으로, 가능한 "상태"들을 Class로 정의해 놓은 것! - "상태" 객체가 필요한 "기능"을 제공하게 된다.
- 구현 - 상태 사용자(context): 클라이언트로 부터 기능 실행 요청을 받으면, 상태 객체에게 해당 기능 처리를 위임한다 - 상태(state): 구체화된 여러 상태들의 기능들을 추상화함으로써, 변화하는 부분을 담당한다 - 상태 콘크리트(Concrete state): 실제 상태의 기능들을 구현
- 장점 - 상태에 따른 if - else 분기를 안 만들어도 된다. - 유지보수가 쉬워지고, 단일 책임 원칙을 준수하기도 수월해진다. - 상태별로 동작 수정이 쉬워짐 - 상태에 관련된 코드가 한 곳에 모여있어 안전하고 빠른 구현이 가능하다
링크¶
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-15.md#%EC%83%81%ED%83%9C-%ED%8C%A8%ED%84%B4
[JDK] hashCode & equals 의 동치성 - 3¶
내용¶
- HashSet/HashMap 같은 경우, hashCode와 equals 가 같다면, 같은 Key값으로 인지
- 2개의 "같아야 하는"객체를 HashMap에 넣었는데, hashCode/equals가 다르게 정의되어 있다면, - 즉, hashCode는 같고 equals는 다르다면 - 2개의 객체는 각각 다른 Key값으로 HashMap/HashSet에 저장된다.
- 해당 방식은 결국 고유한 Key값을 통한 Value의 접근을 방해하는 Side Effect를 발생시킨다.
- 따라서 객체의 고유함을 보장할 수 있도록, hashCode와 equals가 같이 동작하도록 정의해야 한다.
링크¶
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-24.md#hashcode%EC%99%80-equals%EC%9D%98-%EB%8F%99%EC%B9%98%EC%84%B1-%EB%B3%B4%EC%9E%A5
- https://papimon.tistory.com/74
[OOP] 객체 생성의 캡슐화 - 2¶
내용¶
- 체스에 필요한 팀 객체를 인스턴스화 하기 위해, Team 클래스의 생성자를 통해 각 팀을 생성해주었다.
- 하지만 생각해보니까, 체스에는 블랙팀, 화이트팀만 있으면 된다.
- 그러면 굳이 생성자를 열어두지 말고(물론 열어줘도 됨), BlackTeam을 만드는 정적 팩토리 메서드와 WhiteTeam을 만드는 정적 팩토리 메서드를 만들어 보는 것은 어떨까?
- 해당 방식으로 코드를 리팩토링 했더니, Team 생성에 필요한 정보를 생성자를 통해 외부로 공개하지 않고, 체스에 필요한 팀을 만드는 역할을 충분히 하게 되었다.
링크¶
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-24.md#hashcode%EC%99%80-equals%EC%9D%98-%EB%8F%99%EC%B9%98%EC%84%B1-%EB%B3%B4%EC%9E%A5
- https://velog.io/@ljinsk3/%EC%A0%95%EC%A0%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C%EB%8A%94-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C
[OOP] SOLID 원칙 중 LSP - 2¶
내용¶
- 리스코프 치환 원칙 정의 - 상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야한다 - OCP를 뒷받침 하는 "다형성"에 관한 원칙
- LSP 위반 신호 - isInstanceOf는 전형적인 LSP 위반 신호 - 상위 타입을 그대로 쓰지 못하고, 하위 타입 인스턴스 인지 검사하는 것 자체가, 상위 타입으로 프로그램을 정상 작동 못시킨다는 것! - 이를 해결하려면, 더 "추상화" 시켜볼 것 - "구체적 구현에 따라 변화하는 기능"으로 만들어 일을 처리해보자...!
링크¶
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-03-22.md#%EC%84%A4%EA%B3%84%EC%9B%90%EC%B9%99-solid
- 개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 (최범균)
[Architecture] Service Layer¶
내용¶
- Layer가 필요한 이유 - Layer를 통해 역할을 추상화 할 수 있음 - 다른 계층 끼리 부품을 갈아끼우듯 변환 가능 - 컴포넌트들의 의존 계층 관계 유지 가능
- Service Layer - 어플리케이션의 비즈니스 로직을 캡슐화하고, transaction을 조절하는 역할
링크¶
[JS] fetch API¶
내용¶
- Ajax - 비동기 방식으로 데이터를 주고받는 JS 기술 - 페이지 새로 고침 없이 서버에 요청하고, 응답을 받을 수 있음
- fetch - Ajax 기술의 복잡도를 낮춰 사용할 수 있도록 fetch 보급 - Promise를 반환함 - 따라서, then() 메서드에 응답 처리하는 콜백함수 추가할 것
링크¶
[JDBC] 자원 반환¶
내용¶
- Connection, Statement/PreparedStatement, ResultSet 들을 모두 close() 해줘야 한다
- 그렇지 않다면... - Statement가 제대로 안 닫히면, 생성된 Statement의 갯수가 증가하여, 더 이상 Statement를 생성할 수 없게 됨 - close() 하지 않으므로, 불필요한 자원을 낭비하게 됨 (네트워크/메모리) - 커넥션 풀을 사용하지 않는 상황에서 Connection 안 닫아주면 DBMS에 새로운 Connection을 만들 수 없음
- 해결 방법으로 커넥션을 관리하는 class를 생성하거나, try-with-resource를 사용할 수 있다
링크¶
- https://javacan.tistory.com/entry/78
- https://github.com/PapimonLikelion/woowacourse-TIL/blob/master/Level1/2021-04-05.md
[Java] 멀티 스레드 환경에서 고려할 것¶
내용¶
- 만약 인스턴스 변수가 있는 클래스에서 멀티 스레드 환경을 지원한다면, 해당 인스턴스 변수에 대해 쓰레드 동기화를 확보해야함 - synchronized 예약어로 필요한 영역을 임계 영역으로 지정할 수 있음 - 이렇게 된다면, 하나의 쓰레드만 접근/처리 가능하여 성능이 떨어질 것임
- 만일 클래스를 stateless하게 만든다면, race-condition이 일어날 인스턴스 변수가 없다 - 멀티 스레드 환경을 쉽게 지원할 수 있음