Search
Duplicate

2021년 9월 1주차 회고록 - 비자아적 프로그래밍, 객체지향 패러다임

Facts

코드숨 스프링 3기 4주차 미션 진행및 피드백 정리
비자아적 프로그래밍
Test Double
매체 및 시니어에 대한 과도한 신뢰에 대한 경계
객체지향 패러다임 다시 한 번 공부
책 <오브젝트> 의 영화 예매 예제 리마인드
이펙티브 자바 아이템 18 리마인드

Feelings

코드숨 스프링 3기 미션 진행 및 피드백 정리

비자아적 프로그래밍

내 성격, 내 자아, 내 가치관이 코드에 다 드러날 꺼라고는 생각하지 못했다.
아니라고 하면서도 내 코드, 그리고 내 개발스타일에 내 자아가 들어가면서 이게 내 발전을 막고 있었다.
코드에 대한 지적을 나에 대한 지적으로 받아들이고, 그와중에 미움받고나 각을 세우고싶지는 않아서 돌리고 돌리면서 반박하거나 대답하는 식은 핑계를 대거나 아는척을 하는 것처럼 보일 수 있다.
잘 생각해보면 내 코드 스타일, 내 대화 스타일 자체가 몹시 방어적이였다. 예를들어 A를 리뷰했다고 가정했을때,
나는 A라는 내용이 전혀 이해가 되지 않으면, 일반적으로는 A 이해 안되요 다시 설명해주세요. 라고 하면 될 일을 나는 이렇게 생각한다.
그냥 물어보면 공부도안해보고 너무 쉽게 물어보는거 라고 생각하는게 아닐까?
이런 쉬운 내용도 이해 못하네. 머리가 나쁜가보다
저 나이 먹고 저것도 이해 못 해?
그러다보니 리뷰 혹은 대화를 할 때 하나의 응답에 대해서 바로 되묻기보다는 따로 조사를 다 해보고 수필 초안 작성하듯이 대본을 쓰고 이를 수정하고 수정한다음 상대방이 내가 모른다고 생각하지 않게 아는 지식을 최대한 나열하고 반박할만한 예상 질문을 최대한 미리 선대답하는식으로 대화를 한다.
그러다 보니 대화가 길어지는 단점도 있고, 너무 눈치를 본다는 것을 상대방도 알게 되면 별로 좋은 일은 아니다.
무의식적으론 알고 있지만 의식적으로는 몰랐던 내 성향이였다.
그리고 한편으로는 이게 왜 문제야? 라고 생각했던 것 같기도 하다.
하지만, 이렇게 감정적이고 방어적인 대응은 일상생활도 그렇지만 내 코드 품질을 높히는데는 전혀 도움이 안된다는 것이 사실이다.
코드는 코드고 나는 나다. 내 자존감과 자아를 코드에 섞어 내 코드.. 아니 그냥 코드 퀄리티를 높히기 위해서 코드에서 나라는 자아를 빼내보자.
더하여 미움받을 용기라는 책도 읽어보라는 말을 다른 사람에게 들었는데, 지금까진 그냥 필요할 때 보면 되지 했는데, 이제 좀 빨리 읽어봐야 할 것 같다.

Test Double

mocking을 이용해 given/when을 이용해서 테스트를 진행하다 리뷰를 통해 내 코드에서 given/when을 빼도 문제가 없다는 얘기를 듣고 이해가 잘 되지 않아 Test 도구에 대해 학습을 하면서 예전에 스치듯이 공부했던 Test Double이 떠올라 다시 검색하여 공부를 진행했다.
(근데 리뷰를 다시 잘 보면 Service 테스트에서 given으로 Service를 옵저빙하고있었다... 뭔 생각으로 코드를 짠 걸까..)
이 키워드를 알기 전에는 mocking같은 개념을 그냥 대신 대답해주는 허수아비 정도라고 추상적으로 생각을 했는데, 이전에 한 번 학습하며 대략적인 키워드를 인지하고, 이 번에 다시 한 번 학습을 통해 Test Double이라는 개념에 대해 학습했다.
비록 다시 학습하기까지의 과정은 정상적이진 않았지만, 이 결과가 내게 최근 가장 큰 인사이트와 새로운 지식을 얻게 해줬으니, 매우 성과가 높다.

공통 모듈화에 대한 경계

같은 로직이 중복되지 않게 해서는 안된다. 라는 말이 있다. 즉 코드의 중복이 많을수록 수정에 대처하기가 어려워지기에 하나로 합쳐 코드를 간결하고 수정에 취약하지 않도록 하라는 말이기도 하다.
하지만, 이런 내용에 매몰되어 '무조건' 합치려고 하는 건 좋지 않다. 때로는 하나하나 풀어놓는게 유지보수에도 쉽고 인수인계에도 편하다.

매체 및 시니어에 대한 과도한 신뢰에 대한 경계

자존감? 자신감이 낮다보니 저명한 사람 혹은 인정받는 책에 대해서 신앙하다시피 믿는 경향이 있다.
일례로 예전 소트웍스 앤솔러지 책에서 나온 객체지향 생활체조 9가지 원칙에서는 2단계 이상의 들여쓰기를 금지하고 있다. 그러다보니 유효성 검증을 위한 메서드의 반환값이 있는경우 들여쓰기가 늘어나는 문제로 유효성 검사 메서드에서 바로 예외를 발생시켜버리는 마치 C의 goto문과 같은 메서드가 되버리는 문제가 발생한다.
여기에는 차라리 네이밍이라도 잘 해서 다른 사람이 볼 때 이 메서드가 유효성 검사 후 문제가 발생하면 예외를 발생하는구나! 라는걸 알게끔 하면 모를까 심지어 이름도 isValidationString 이런식이니 당연히 boolean 값을 반환할 꺼라고 예측을 했는데 예외가 발생하면 당황할 수밖에 없다...
그리고 JPA책에서 상속관계를 소개할 때 알려준 기능으로 @MappedSuperClass와 , @Inheritance 기능이 있다. 그리고 나는 이 책을 무작정 신뢰하기에 쓸 수있는 상황이 오는거 같다 싶으면 바로 써버렸다. 하지만, 이펙티브 자바 아이템 18에서는 상속보다는 컴포지션을 사용하라며 상속의 문제점을 제시한다. 또한 리뷰어분 역시 이런 상속은 객체지향의 적이라면서 객체지향에 대해 다시 공부하기를 권유했다.
하나하나 들어보면 이펙티브자바, JPA, 객체지향 패러다임, 오브젝트 모두 스터디까지 했었고 발표도 하고 개인적으로도 공부했던 부분이다. 하지만, 이를 엮어서 생각할 줄 알아야 하는데 이를 못하다보니 이런 문제가 생기는 것 같다.
@MappedSuperClass와 , @Inheritance 이런 기능이 있다고 무조건 써야하는건 아니다. 기능이 있어도 써야 할 때 써야한다. 다시 말해 쓸 수 있으니까 쓴다가 아니라 써야 하기에 써야한다.
즉, 이번 4주차 과정에서 Product > CatToy라고 상속을 만들기보다는 Product라는 엔티티를 사용하되 확장 및 공통 필드의 재사용이 필요하다면 @Embedded를 사용하도록 하여 컴포지션을 활용하는게 맞다.

객체지향 패러다임 다시 한 번 공부

객체지향이라는 말은 너무 자주 듣고 개발을 시작하는 시점에서 귀에 딱지가 듣게 듣는 내용이기도 하다. 하지만, 이를 항상 지키면서 개발을하는건 쉽지가 않은 것 같다. 이번 주 대화를 통해 이 점을 다시 한 번 깨닫고 오브젝트 책을 다시 한 번 읽어보도록 해야 겠다.

이펙티브 자바 아이템 18 리마인드

객체지향에서 상속은 적이라고 하는데 '어째서' 적인지에 대해서 학습할 필요가 있다. 그리고
이펙티브 자바라는 책에서 클래스와 인터페이스 챕터에서 이를 다룬다. 제한적으로 상속을 써도 괜찮은 경우와 그외에 대부분 상속이 어째서 문제서인지에 대해서 소개한다. 나는 이 내용을 알고있으면서도 우선순위를 높게두지 않아서 다른사람은 잘 모르는 기능이니까 사용해야지! 하면서 애노테이션을 통해 jpa 상속을 구현했다가, 코드의 가독성만 떨어진 것 같다.

Finding

코드숨 스프링 3기 미션 진행 및 피드백 정리

비자아적 프로그래밍

자신의 프로그램이 자아의 외연이라고 진심으로 믿는 프로그래머는 프로그램에 있는 모든 오류를 찾아내려고 하지는 않을 것이다. 오히려 그 프로그램의 정확성을 증명하려고 노력할 것이다. - 프로그래밍 심리학
1971년 컴퓨터 프로그래밍 심리학이라는 책에서 처음 언급된 비자아적 프로그래밍이라는 단어는 개발자가 자신이 만든 프로그램에 자아를 투영해서는 안된다는 이야기를 한다.
프로그램을 자신의 작품 혹은 자신의 자아라고 생각하면 다른 사람의 의견 혹은 지적에 대해 방어적인 스탠스를 취하게 되고 이는 발전보다는 정체를 야기할 수 있다.
개발 뿐 아니라 내용의 대한 지적을 화자에 대한 지적으로 받아들여서 싸움이 이상하게 번져나가는 경우는 많다.
그리고 이런 싸움 혹은 감정적인 대처의 결과는 결국 떨어지는 퀄리티로 돌아올 수 밖에 없다.
그래서 우리는 비자아적 프로그래밍을 해야하고 이를 위해 다음과 같은 10가지 지침을 LamontAdams 라는 사람이 TechRepulbic이라는 사이트에서 주장했다고 한다.
1.
당신은 실수할 수 있다는 것을 받아들이고 이해하라.
: 실수는 일찍 발견할수록 좋은 것이다. 일찍 발견할수록 비용은 적어진다.
2.
당신의 코드는 당신의 작품이 아니다. :코드 리뷰의 목적은 문제를 발견해 치료하는 것이다. 감정적으로 받아들이지 말아라.
3.
장기도 훈수 두는 사람이 더 잘 안다. :장기에 몰입 해 있는 사람보다 멀리서 훈수 두는 사람이 더 멀리 볼 수도 있다. 가르침에 겸손해라.
4.
조언 없이 코드를 다시 쓰려 하지 마라. :혼자서 독단적으로 판단해 코드를 작성하지 말고 코드 리뷰를 통해 코드를 다시 작성해라.
5.
잘 알지도 못하는 사람을 존경하고 복종하고, 참아라. 비개발자는 개발자를 오페라의 프리마돈나처럼 생각하지만, 안 좋을 때는 울보로 간주한다. 여기에 휘둘리지 말아라.
6.
세상에 변하지 않는 진리는 변한다는 것이다. :변화에 대해 열린 마음으로 받아들여라. 요구사항의 변화, 플랫폼의 변화, 기술의 변화 모두에 대해 받아들여라.
7.
진정한 권위는 직위가 아닌 지식으로부터 나온다. :즉, 존경받고 싶다면 직위가 아닌 지식을 쌓아라.
8.
당신이 알고 있는 지식을 고수하며 싸워라. 하지만, 패배는 겸허히 받아들여라. :내 코드 내 개발 방법이 채택되지 않는다고 실망하지 말고 나중에 내 주장이 맞더라도 "내가 말한게 맞죠" 라며 복수하지 말자.
9.
독방의 개발자가 되지 말아라.(콜라 살 때만 나타나는 은둔형 개발자는 되지 말자.)
10.
사람이 아닌 코드를 비판하고, 코드가 아닌 사람에게 친절해라.
: 더하여 코멘트는 긍정적이며 개선하는 방향으로 해야 하며 기존 코드에 대한 비판적인 방향은 좋지 않다.

Test Double

테스트 목적으로 실제 객체 대신 사용되는 모든 종류의 척도 객체에 대한 일반적인 용어
가짜 버전은 실제와 같이 보이며 동일한 메소드 호출에 대해 단위 테스트 시작시 스스로 미리 준비된 답변으로 답변한다.
Test Double의 종류는 여럿 잇지만 대체 한다는 의미에선 모두 동일하다.
이러한 Test Double에서 미리 준비된 대답으로 답변하는 과정을 Stubbing이라 하는데, 미리 프로그램된 것 외의 것에 대해서는 응답하지 않는다.
stubbing 과정
그럼 Test Double은 언제 사용하고 언제 Stub 해야할까?
내가 테스트하려는 테스트 대상이 외부요인으로부터 철저히 격리되야 할 때 사용한다. 하지만, 테스트가 협력 객체의 상세 구현을 알아야 한다. 반면, 실제 객체를 이용하면 내가 협력 객체의 상세 구현에 대해 자세히 알 필요가 없다. 하지만, 협력 객체의 정상 작동 여부에 영향을 받을 수 있다.
실제 객체를 사용하는 것(좌측)과 고립테스트를 하는 경우(우측)
즉, TDD를 연습할 때는 가급적 실제 객체를 활용하는것을 우선으로 하되 테스트 작성이 어렵거나 흐름이 잘 이어지지 않는 경우 Test Double을 활용하는 방법으로 진행하면 좋을 것 같다.

공통 모듈화에 대한 경계

위 코드는 Product라는 엔티티에서 name, maker 등 String Field의 유효성 검증을 위해 만든 메서드이다.
리뷰 내용처럼 얼핏 보면 하나의 메서드에서 Rest Parameter를 받아서 이를 반복문으로 순회하며 유효성 검증을 해주는데, 간결해보인다. 하지만, 이 메서드는 모든 String 타입의 필드와 연관이 생길수도 있고, 몇몇 특정 String 필드가 기획의 변경으로 다른 유효성을 검증하게 될 때 이런 특정 필드를 찾아서 변경해주는 과정에서 문제가 생길 수 있다.
그리고 무엇보다 이런 함축적인 메서드와 공통적인 메서드명은 개발 당사자인 나도 시간이 지나며 헷갈릴 수 있고 인수인계라도 했다치면 문제가 발생할 확률이 높다.
객체지향 생활체조 9가지 원칙에서도 그렇고 흔히 리팩터링을 고려하다보면 중복되는 로직에 대해서는 모듈화를 하여 통합하는 과정을 생각하게 된다. 하지만, 상황에 따라서는 중복될지라도 각각의 로직을 별도로 놔둬야 한다는 것을 이번 일로 알게 되었다. 이 역시 마냥 하나의 주장 혹은 조언을 맹신하지 않아야 겠다는 생각을 하게 해주는 경험이였다.

객체지향 패러다임 다시 한 번 공부

S/W개발을 기능이 아닌 객체 단위로 분리하는 것. 객체를 중심으로 시스템을 바라보고 이를 시스템 개발에 적용하는 것
기존 프로시저 기반 구조적 프로그래밍에서는 프로그램 내에서 일어나는 모든 변화와 동작, 사건 등을 프로그래머가 직접 기술하는 형태로 프로그램을 기술했지만, 객체지향 프로그래밍에서는 각각의 객체가 메세지를 전달하는 형태로 프로그램을 기술한다.
조영호님의 책 <오브젝트> 의 챕터 3을 잠깐 보면 객체지향은 클래스, 상속이 핵심이 아니라 역할, 책임, 협력을 중요점으로 말 하고 이 세 요소의 조화와 균형을 맞추는 설계가 중요하다고 얘기한다.

이펙티브 자바 아이템 18 리마인드 - 상속보다는 컴포지션

상속 자체의 기능은 몹시 강력하다. 재사용성과 확장성 두 가지 모두 만족하며 얼핏보면 두 마리 토끼를 모두 잡은 것 같다. 하지만, 상속은 상위 클래스의 장점만 가져오는게 아니라 단점도 모두 가져온다.
대부분의 경우에서 상속은 캡슐화를 깨트리고 단점을 내리받으며 equals and hashCode 재정의의 어려움 등 문제가 많다. 또한, 상위 클래스의 변경에 이를 상속하는 모든 하위 클래스가 영향을 받는다는 문제도 있다.
또한 상위 클래스에서 접근을 허용하지 않는 private 필드나 메서드는 접근조차 할 수 없어서 중복 정의를 할 수도 있는데, 이는 만약 새로운 릴리즈에서 추가된 메서드가 동일한 시그니처에 반환타입만 다른 경우 또 문제가 발생할 수 있다.
또한 애초에 private 키워드가 붙었다는 말은 외부에서 접근을 못하게 하기 위함인데, 억지로 접근을 하는것도 문제이고, 우리는 이에 대처하기위해 컴포지션(Composition)이라는 개념을 가져온다.
이는 기존 클래스가 새로운 클래스의 상위 클래스가 아닌 구성 요소로써 사용된다는 의미인데, 기존의 자식 클래스였던 신규 클래스는 상위 클래스를 상속하는게아니라 위임을 통해 전달을 해 서로 협력관계가 되면 private 필드 접근문제나 캡슐화파괴같은 문제로부터 자유로워진다.
여기에 추가적으로 자바 디자인 패턴의 이해 라는 책에서도 브릿지 패턴(Bridge Pattern)을 소개할 때 견고한 상속과 느슨한 위임에 대해 언급한다. 클래스의 가장 편한 확장방법으로 상속이 있는데, 이러한 상속 관계는 소스를 고치지 않는한 견고한 연결이 되는데, 이는 유연함을 떨어트릴 수 있다. 그래서 브릿지 패턴에서는 Implementor(구현자)를 인자값으로 위임받아 사용한다.

Affirmation

내 방어적인 성격, 남을 의식하는 성격이 내 개발 인생에 관여하지 않도록 노력해야 한다.
모른다는건 부끄러울 수 있지만 부끄러움 뒤에는 앞으로 부끄럽지 않을 지식을 얻게 되니 질문은 많이 하자.
시간은 금이다. 눈치본다고 질문하나하나에 너무 시간을 들이다보면 서로 시간낭비이다. 용건만 간략히 하도록 하자. (이해안되면 그냥 이해 안된다고 바로 말하자.)
좋은 품질의 코드를 작성하려 하는거지 지식자랑하려고 개발하는거 아니다. 그러니 코드에 내가 새로 배우거나 남들이 아직 모르는 기술 넣는다고 설레발치지 말자.
리뷰를 받기 전/ 후로 분명 여유시간 더 있는데, 핑계대면서 다른 공부 안하고 있는데, 하도록 하자.
인프런 스프링 MVC2편
디자인패턴 남은 아이템
네트워크 포스팅
9월 말 시작하는 Java 알고리즘 스터디 준비