본문 바로가기

All

(42)
[개발생각] 어플리케이션 레이어에서 UseCase와 Service의 동일시 DDD, 클린아키텍쳐기반으로 설계를 하다보면, UseCase와 Service를 동일시 보고, 하나 개념으로 합치고 싶은 욕망이 들때가 있다. 책이나, 블로그등에 따르면 뭔가 잘못된 생각같고, 찜찜하고 아닌것같은 생각을 하고, 잠시 욕망을 접었던 기억이 많다. 대부분 책에서는 어플리케이션 레이어에서의 UseCase를 '행위의 정의'로 보고, Service는 이런 UseCase들을 이용한 '퍼사드 개념'으로 본다. 그런데, 이론은 그렇다고 해도, 일반적인 서비스에서 저렇게 UseCase와 퍼사드 Service로 나뉘는 경우가 많을까? 의구심이 든다. 그리고 Service를 UseCase의 정의대로 구현하면 (UserGetService, UserLoginService등), 행위의 정의와 퍼사드 개념을 펄쳐서 ..
[개발생각] Test코드 작성시, Fixture의 관리에 대해서 Mock용 객체를 기준값에서 파생되게 만들면, Mock객체의 통일성을 유지할수있고, 서로다른 테스트코드에서도 일관성을 유지하며 테스트코드를 작성할수있다. 테스크 코드를 작성할때, Mock용 User정보, Address정보, Device정보등, 테스트 실행시 필요한 정적인, 준비된 데이트들을Fixture라는 명아래, UserFixture, AddressFixture,DeviceFixture 등의 이름으로 모아두고, 활용하게 된다. 여기서 조금만 관리를 소홀히 하면, Fixture클래스는 온갖 데이터가 난무하는고, 중복 코드가 난무하는 클래스, 즉, 애물단지가 되버린다.여기서 Fixture를 더럽히는 가장 큰 요인하나가, 일관성없는 Mock용 데이터들 정의다. val user1 = User(id=1, na..
[개발생각] 익숙치않은 개발(론)에 팀원들을 적응시키는 방법에 대해서 개발자라면, 같은 회사에서 오랜기간 개발하게 되면, 그 회사만의 방식/방법에 익숙해지게 마련이고, 마치 관습과도 같이 코드를 작성하게 된다.이런게 '콘웨이 법칙'의 예가 아닐까? ㅎㅎ 만약 위와 같은 상황에 지속적으로 노출된다면, 개발자는 점점 관습으로 개발을 하게 되고,(관습이 나쁘다는 이야기는 아니다. 다만, 필연적으로, 개발에 고민하는 시간이 줄어든다는 이야기이다)어느 순간 개발자가 아닌 코더로 전락하게 된다.그런데 정말 무서운것은 코더가 된것을 자신은 모른다는것이다... 정말 무섭다.. 나도 코더였던 경험이 있다. (지금은 당연히 코더가 아니라고 자신있게 말할수있다 ㅎ)대학 졸업후에, 작은 SI개발회사에서 몇년 일하게 됬는데, 어느 순간, 내가 일명 CCCV (컨트롤 C + 컨트롤 V)의 고수가 ..
[개발생각] SOLID원칙에서 I의 경험에 대해서 여러 같은 행위를 하는 Service 빈을 만들어야 할때가 있다. 이경우, 각각의 공통된 행위/과정을 인터페이스 스펙으로 설계하고,그 인터페이스 스펙을 구현하는 AService, BService, CService를 만든다.첫단계에서는 이런 스펙들이 하나의 인터페이스 클래스에 같이 존재하게 되는데,이 스펙들이 많아지고, 성격이 틀리게 되면, 적절하게 그룹핑을 하고, 나눠야 하는 시점이 오게된다. ASpec, BSpec, CSpec등으로 인터페이스 클래스로 나누고, 해당 스펙을 구현하는 구현체를 만든다.구현체는 한개의 클래스에서 모두 구현하는게 아닌, 각각의 스펙별로 별개의 역할을 하는 구현체로 별도로 만드는게 훨씬 깔끔해진다.(일정부분, 단일책임원칙과도 맞는 부분이다) 이 스펙 클래스를 구현한 구현체들은 ..
[개발생각] toString()과 toInt()의 비교 순서에 대해서 작은 차이가 명품을 만든다.. 어느 광고 카피가 생각난다. Int형 userId변수가 있고, string형 userIdStr변수가 존재하는데,이 두개의 값 자체는 정수값으로 같고, 타입만 틀린상태라고 해보자.이 두 변수를 비교해서 처리하는 로직이 아래와 같이 코딩되었다고 가정하면, if (userId.toString() == userIdStr) { //비즈니스 로직} else { //비즈니스 로직}이 코드가 잘 짜여진 코드일까? 생각해보자.. 단연코, 나는 아니라고 생각한다. 엄청 심플한 코드 같지만, 정말 세밀한 차이로 코드의 퀄리티가 달라질수있다.위의 코드는 아쉽지만, 잘못 짜여진 코드라고 생각한다.userIdStr은 String형 타입, 문자열이기에, userIdStr안의 값이 정수값인지, ..
[개발생각] 도메인VO를 컨트롤러의 입력파라미터로 써도될까?에 대한 고민 개발자의 욕심은 끝이 없으니, 재사용, 재사용이라는 프레임에 갇히고, 또 의미를 잃어버리고... 도메인VO를 정의할때, 대부분 그냥 Value Class (코틀린)로 정의해서 사용한다.즉, 대부분은 단순 Wrap 클래스로만 VO를 정의하고 사용한다. 타입 안정성과 명시적 의미부여에 큰 의미를 둘 수 있기에, Wrap 클래스 정도만이여도 상당히 강력하다고 생각하기 때문이다.하지만, 좀더 서비스가 복잡해지고 방대해 진다면, (즉, 다뤄야하는 도메인이 많아진다면)VO가 다양해지고, 해당 VO의 값에 대한 벨리데이션 검증 로직을 VO로 빼는 경우도 많게 된다. 예를 들면Value Class Email(value:String) { init { //value 검증 로직. (Email포멧 검증..
[개발생각] 동일한 역할의 API 인터페이스를 도메인에서 분리해야할때 다른 방식으로 동작하는 동일한 역할을 하는 API는 깔끔하게 도메인 레이어에서 제거하는게 더 깔끔해진다. 도메인 주도 설계 개발을 하게 되면, 아래와 같은 상황이 올때가 있다. 예를 들면, ci를 넘기면, 그 ci의 주민등록상의 주소를 리턴해주는 API를 연동한다고 해보자.그런데, 해당 API는 불안해서, 또는 다른 이유로 같은 기능을 제공하는 몇개의 다른 API를 보조로 사용하려고 한다.(A api 죽으면, B api 사용,)그런데 각각의 A, B API는 응답을 주는 방식이 틀리고, 요청파라미터도 다르다.하나는 요청하면 바로 응답값을 주는 동기방식이고, 하나는 요청하면, 콜백URL을 통해 나중에 전달해주는 콜백 비동기 방식이다. 이런경우, 도메인 서비스에서 비즈니스 로직을 구현할때,해당 api호출을 ..
[개발생각] 회원구분코드(UserDvcdCode) 정의에 대해서 웹서비스에서 회원구분코드의 정의에 대한 깊은 생각을 했다. 좀더 전문적인 웹서비스를 만들때, 회원이라는 정의는 엄청나게 중요하다. 회원 정의를 엉성하게 설계하면, 결국 회원중심으로 돌아가는 모든 기능과 연결등이 엉성하고 어설프게 설계된다. 개발자는 유연과 엉성의 차이를 명확히 인지하고 있어야 한다.유연한 설계는 수정에 닫혀있고, 확장에 열려있는 구조가 되지만, 엉성하고 어설픈 설계는 수정에 활짝 열려있고(도둑들아 모두들어오세요~), 확장에 닫혀있는(불났는데 문이 안열려..) 답답한 시스템이 되버린다.. 이런 유연한 설계를 지향해야하고, 이런 설계를 위한 첫걸음은 회원에 대한 테이블 설계라고 할수있다.개인적으로는 경력이 있다보니,많은 프로젝트 설계/개발 경험이 있었고, 매번 해왔던 회원설계/회원구분에 대..
[개발생각] 시니어 개발자와 주니어 개발자에 대한 생각 시니어 개발자와 주니어 개발자의 가장 큰 차이는 '관심' 같다. 요즘은 수평문화등의 이유로 개발자들간의 시니어, 주니어 개발자의 역할과 책임의 경계가 모호해진것같다.수평문화는 참 좋은 문화이지만, 역할과 책임에서도 수평이 되는것은 나는 좋게 보지않는다.직장,학교,군대등 사람들이 모여 생활하는 집단에서는 역할과 그에 대한 책임의 경계가 명확해야하기 때문이다.이 부분을 수평문화라는 놈이 경계를 모호하게 만드는것 같긴하다. 그렇다면, 개발에서 역할과 책임이라는 범위로 봤을때,시니어 개발자는 어떤 사람이고, 어떤 역할을 해야하는걸까? 다수의 경험을 바탕으로, 모든것들을 척척 해나가는 슈퍼맨같은 사람이라고 볼수도있다.하지만, 나는 다르게 생각한다. 시니어 개발자의 가장 큰 덕목은 '관심'이다. 내가 사용하는 기술..
[개발생각] 코틀린에서 Exception과 Transactional관계에 대해서 코틀린에서는 Checked Exception 개념이 존재하지 않는다. 그로인해 모든 Exception은 RuntimeException과 같이 동작하고,그 가장 큰 수혜라고 하면, 함수간에 Exception을 주고받을 명세 throws Exception 같은 코드들이 없어지는 깔끔함일것이다. 처음에 이 개념을 알고, 좀 혼란스러웠던 경험이 있다. 바로 스프링에서 사용하는 @Transactional의 사용에서 였다. java에서@Transactional(rollbackOn = [Exception::class, Throwable::class])이런식으로 정의해서,Checked Exception인경우도 롤백이 되도록 설정을 하여, 많이 사용했다.하지만, 코틀린에서는 Checked Exception개념이 존재하지..