System Design/Method design
return (code, data) 함께 반환하기
return (code, data) 함께 반환하기
2023.10.07때때로 method 내에서 정상 로직 진행에 실패한 경우에도 data를 상위 메서드에 전달해야 하는 경우가 있다. (e.g., 추가인증필요, 기처리) 기본적으로 throw Exception을 return 처럼 data 반환 용도로 사용하는 것은 불가능 하기 때문에, return 기반으로 접근해야 한다. 직접 return 타입 정의해 사용하기 data class FooResult( val code: Code, val field1OnlyIfSuccess, val field2OnlyIfSuccess, val field3OnlyIfFailure } { enum Code { SUCCESS, FAILURE } } Result 타입 R 타입에 code 없고 성공+실패 data field만 존재하는 경우 유용. 보편적..
caller는 callee를 믿지 않는 것이 좋다 (어차피 catch 해야 한다)
caller는 callee를 믿지 않는 것이 좋다 (어차피 catch 해야 한다)
2023.10.07중요한 처리로직 인 경우, 어차피 caller는 callee를 믿어서는 안된다. 여기서 callee는 다른 class 혹은 다른 class의 메서드를 의미한다. 같은 class 내 private method를 호출하는 경우라면, 자기 자신이 직접 정의한 기능이므로 믿을 수 있으나, class 바깥의 다른 class와 메시지를 주고 받는 상황이라면 신뢰하지 않는 것을 기본 전제로 깔고가야 한다. 예시 ) 금액 소진 메서드를 제공하는 callee가 Exception을 반환하지 않겠다고 docstring에 명시해두었다면 믿을 것인가? 금액 소진 기능인데, callee의 docstring과 현재 구현된 메서드 내부만 믿고 caller는 catch 안할 것인가? 그럴리가 없다는 것이다. caller 입장에서 ca..
CQRS : Command and Query Responsibility Segregation
CQRS : Command and Query Responsibility Segregation
2021.04.21martinfowler.com/bliki/CQRS.html (번역) https://martinfowler.com/bliki/CommandQuerySeparation.html CRUD를 모두 하나의 도메인 모델을 사용해 처리했었다면, CQRS는 CUD를 Command용 모델로, R을 Query용 모델로 분리하여 설계하는 방법 하지만 문서 전체에서 CQRS는 잘 들어맞는 부분에만 일부 사용할 것을 권장하고 있다. 문서에서 발췌 CQRS는 시스템의 특정한 부분(DDD 표현으로는 Bounded Context)에서만 사용돼야 하고, 시스템 전체에서 사용해서는 안 된다. 이러한 사고방식은 각 Bounded Context는 개별적으로 모델링을 해야 한다는 의미다. (Bounded Context: https://www..
External Client class에서 Exception을 던지는게 좋을까?
External Client class에서 Exception을 던지는게 좋을까?
2020.08.21예시 API 응답으로 수신하는 code 및 그에 따른 반환값 when (response.code) { 1000 -> 성공 (데이터 반환) 1007 -> 기처리 (데이터 반환) 2000 -> 구분해야하는 실패1 2001 -> 구분해야하는 실패2 else -> 그 외 모든 응답 코드(실패) } 예시 상황에서, External Client class에서 Exception을 직접 던지는게 나을까? 아니면 return 기반으로 가는게 나을까? 둘 다 사용하는 hybrid로 가는게 나을까? External Client class에서 Exception을 직접 던지는 경우 예시) 후술하겠지만 이렇게 처리하는 것은 좋지 않다. AbcClient { fun post() { val response = webClient.po..
공통 비즈니스 로직 분리(제휴사 인터페이스 통합 및 클래스 설계)
공통 비즈니스 로직 분리(제휴사 인터페이스 통합 및 클래스 설계)
2019.08.21- 제휴사 API 서버 Npay 서버 연결 작업을 각자 진행한 후, 이를 하나로 통합하는 과정에서 비즈니스 로직 코드 중복이 발생함. - 코드 중복을 해결하면서 제휴사 마다 다른 구현 사항을 고려하여 처음 설계한 아키텍쳐는, PointChangeService라는 abstract class에 공통 로직을 작성하고, 각 제휴사 마다 다른 부분은 abstract 메서드로 만들어 상속을 이용해 구현을 강제하는 방법이었음. - 그러나 서비스가 점차 커지고 코드가 복잡해지면서 순환 의존 (Cycle Dependency) 문제가 발생함. - 더불어 PointChangeService의 책임이 너무 많다는 문제점도 있었음. 결국 XXPointChangeService는 제휴사 마다 다른 구현부와 공통 비즈니스 로직을 모두..
Exception 처리, 어떻게 하는게 좋을까?
Exception 처리, 어떻게 하는게 좋을까?
2019.05.29Error와 Exception의 차이 에러 : 애초에 예상이 불가능한 것. 예외 : 발생을 예상할 수 있는 것. 그리고 예상할 수 있기 때문에 그에 대한 대비로 try-catch가 있는 것. checked exception 컴파일 타임에 경고를 해주는 예외. 예외 처리가 안되어 있으면 컴파일이 안된다. 컴파일 타임에 발생하는 Exception이라고 말하기는 좀 그렇다. 정확히는 Exception은 Runtime에 발생하며 컴파일 타임에 경고를 해주는거지. 대표적인게 `` IOException, SQLException`` unchecked exception 컴파일 타임에 경고를 안해주는 예외. 예외 처리가 안되어 있어도 컴파일이 된다. 대표적인 것이 `` NPE, IndexOutOfBoundsExcepti..
상속 vs 컴포지션 구분 : delegation, decorator, wrapper
상속 vs 컴포지션 구분 : delegation, decorator, wrapper
2019.02.04Effective Java : 아이템 18. (기능 확장이 필요할 때)상속보다는 컴포지션을 사용하라 [Effective Java] 4장 클래스와 인터페이스 상속이란? extends를 말함. (implements는 아님. 이건 구현.) 컴포지션이란? Composition은 필요한 객체를 내부 private 변수로 두는 것 기존 클래스가 새로운 클래스의 구성요소로 쓰인다는 뜻 [Coding/CodingNote] - [코딩 노트] 객체 지향 패러다임 둘 다 어떤 클래스에 기능을 추가하거나, 책임을 더해서 확장하고 싶을 때 사용 할 수 있으나, 근본적인 의미가 다르다. 무조건 컴포지션을 써야 한다는 의미가 아니라, 의미에 맞게 사용해야 한다. (하단 '상속과 컴포지션을 구분하는 방법' 참고) 상속의 단점? 상속..
디자인 패턴 - Singleton
디자인 패턴 - Singleton
2018.06.22singleton VS static 어차피 하나만 생성되는 객체라면 ``java static`` 메서드만 가진 클래스로 만들어도 똑같은거 아닌가 싶을 수도 있겠지만, 다음과 같은 장점 이 있다. OOP 패러다임 : 싱글턴은 OOP 패러다임을 따르는 객체이지만, static은 객체가 아니므로 OOP 패러다임과는 거리가 멀다. 상속 : 싱글턴은 인터페이스를 구현하거나, 클래스를 상속받거나, 상속해줄 수 있음. (반면 static은...) 인스턴스화 : 싱글턴은 static class와 달리 인스턴스화가 가능하다. (static은 인스턴스화가 의미가 없다) 인스턴스화가 가능하다는 것은 필드, 매개변수로 전달, 리턴 가능하다는 것이다. 상속 & 인스턴스화 가능하다는 것은? == 다형성을 사용할 수 있다. 다형성..
Design Pattern, 디자인 패턴
Design Pattern, 디자인 패턴
2018.05.14이 글은 보호되어 있기 때문에 이것을 보려면 암호가 필요합니다.