[우아한테크코스] 2월 17일 TIL
오늘 배운 것
- git코톡 강의
- 로또 미션 진행
git코톡!
git 특별한 명령어
- 브랜치 이동: git checkout / switch step1 (switch는 checkout 대신 새로 생긴거)
- 브랜치 병합 merge: git merge 브랜치명
-> Step1 브랜치는 병합된 곳에, 브랜치명 브랜치는 병합 전에 - 브랜치 rebase: rebase는 merge와 달리 히스토리를 깔끔하게 보여준다. 기록이 없어진다.
HEAD는 현재 작업 중인 브랜치 작업트리의 최신 - 이전 커밋 위치로 이동: git switch HEAD^
- 붙인만큼 이전 커밋 위치로 이동: git switch HEAD^^^^
- 특정 커밋 위치로 이동: git branch -f step2 step1~2
- 완전히 기록 지우기: git reset HEAD~1
- 커밋 되돌리기: git revert HEAD
- 모든 로그 보기: git reflog
- 삭제된 커밋, 브랜치 복구: git reset –hard 해시값
가져와서 Git fetch upstream dusdn
땡기고 Git pull upstream dusdn
푸시 Git push origin dudsn - 체리픽: git cherry-pick 해시값
- 체리픽 범위 지지정: git cherry-pick 해시값^..해시값
실험해보기
브랜치 전략
브랜치 생성에 규칙을 만들어 협업을 원활하게 한다.
- Git-flow: 5개의 브랜치를 운영
- 메인 브랜치: 항상 유지
- Master: 완성본 (woowa/master)
- Develop: 다음 버전 개발 (dusdn1702/dusdn1702)
- 보조 브랜치: merge되면 삭제 - feature: 기능 개발 (dusdn1702/step1)
- release: 이번 출시 준비
- hotfix: 출시된 것에서 버그 잡기
- GitHub-flow: master와 pr을 이용한 전략
오로지 하나의 브랜치로 작업하고 머지하기를 반복한다. 원활한 관리를 위해 이름을 상세히 적는다.
CI/CD에 적용하기 쉬움
로또 미션 도중 배운 것
- stream으로 한번에 range 안에 숫자 만들기
private static final List<Integer> NUMBERS_IN_RANGE = IntStream.rangeClosed(1, 45)
.boxed()
.collect(Collectors.toList());
boxed(): int->Integer, long->Long, double->Double로 형변환
stream 정리
-
Collections.shuffle(List<>)
list 안에 있는 값 무작위로 섞기
Collections는 클래스로 정적 메서드로 구성되어 있다. reverse(), reverseOrder(), sort(), shuffle() 등 다양한 메서드가 존재한다.
Java Collections Framework
데이터, 자료구조인 Set, List, Queue, Map들의 컬렉션과 클래스를 정의하는 인터페이스를 제공한다.
-
공백을 제거하는 방법
Stream.of(numbers.split(","))
.map(s -> s.replaceAll(" ", ""))
.collect(Collectors.toList());
replace(“ “, ““)라는 메서드를 사용하면 공백을 제거할 수 있고, 위 코드를 사용하면 모든 요소들에 적용할 수 있다.
- Checked Exception, Unchecked Exception
- checked exception
반드시 처리해야 하는 예외로, try-catch를 해서 에러를 잡거나 예외를 던져야한다.
트랜잭션 rollback이 되지 않는다.
IOException, SQLException 과 같은 예외가 있다. - unchecked exception
처리하지 않아도 되는 예외로 흔히 예외처리하는 예외이다.
rollback을 진행한다.
NullPointerException, IllegalArgumentException 과 같은 예외가 있다.
- checked exception
- stream에서 예외 발생시키기
- 람다식으로 try-catch 하는 방법
Arrays.stream(~~) .map(s -> { try { return Integer.parseInt(s); } catch(NumberFormatException e) { throw new IllegalArgumentException(e); } }) .collect(toList());
와 같이 해결할 수 있지만, 내부 메서드를 분리하지 않는다면 코드가 지저분해져 stream을 사용하는 이유에 대해서 의문이 든다!
- Supplier로 예외 던져달라고 하기
public interface ExceptionSupplier<T> { T get() throws Exception; }
메서드 정의해서 method(()->Integer.parseInt(s))와 같이 넘겨줄 수 있다.
- 아예 메서드 추출하기
아예 Function을 뽑아서 메서드를 사용할 수도 있다.
- 람다식으로 try-catch 하는 방법
- Enum의 사용
리팩토링 시에 변경이 용이하고, 값의 관리가 쉽고 중복되는 코드 관리가 쉬운 enum을 애용합시다.
관련 있는 상수들을 모아 클래스로 만들어준다!
public enum Ranking {
FIRST(6, 2000),
SECOND(5, 200),
THIRD(4, 20);
private int count;
private int price;
Ranking(int count, int price){
this.count = count;
this.price = price;
}
}
와 같이 생성하고, 클래스와 유사하게 사용한다.
enum에 대해 잘 나와있는 글
- Optional의 사용
메서드가 반환할 결과 값이 없음을 알릴 때 사용하도록 만들어졌다고 한다.
예를 들어, .map() 혹은 .filter() 한 내용이 없을 경우 .orElseThrow(), orElse(), orElseGet()을 사용할 수 있다.
.isPresent()와 .get()을 사용하는 것보다 좋다고 한다.- .orElse(new ..) 보다는 .orElseGet(()->new ..)을 사용하는 것이 당연히 효율적일 것이다.
- Optional은 비싸므로 null을 얻는게 목적이나면 그냥 null을 비교해서 얻는게 낫다고 한다.
- .of(..)는 값이 무조건 null이 아닐 때, null일 수 있으면 .ofNullable(..) 사용
- Map의 사용
Map<Ranking, Integer> rankings = new HashMap<>();
rankings.put(Ranking.FIRST, 0);
rankings.computeIfAbsent(ranking, (Ranking k, Integer v) -> v++);
애초에 생각은 했지만 ranking[FIRST]++; 와 같이 간단하게 구현하면 될 줄 알았는데 아니었다.
없어도 무조건 계산하고 싶으면 putIfAbsent()을 사용하도록 한다.
compute()도 존재하는데 재매핑된 함수의 값을 바탕으로 map에 value를 추가하므로 비효율적이다.
값을 가져올때는 .get(k)을 사용하도록 한다.
- 소숫점 관리
String.format("%.2f", 0.3514)
라고 하면 될줄 알았지만 반올림이 되어 버림은 안됐다.
Math.floor(0.3523)이 버림이지만 특정 자리에서 버림하는 것을 찾지 못했다.
무조건 자연수를 원한다면,
Math.ceil(2.22)
: 올림
Math.floor(2.22)
: 버림
Math.round(2.22)
: 첫째자리 반올림
을 사용하면 된다.
최종적으로 특정 자리에서만 올림 내림 하는 것은 아래 방식을 사용하였다.double profit = Math.floor(0.35 * 100) / 100;
추가적인 궁금중
계속해서 생성자에 객체를 넘겨주고, 생성하면서 메서드를 이용해 원하는 값을 얻게 되는데 생성자의 매개변수로는 int, String, List와 같은 값이 좋은걸까, 객체가 좋은 걸까?
객체를 넣으면 프로덕션 코드는 간단해지는 것 같으면서도 테스트 코드는 많이 복잡해지고 이해가 어려워진다.
원시값을 넘겨주면 테스트가 쉽고 생성자가 간단해지며 보다 직관적이다.