2장 정리

프로그래밍을 할때 대부분의 사람들은 어떤 클래스가 필요한지부터 고민한다.
그렇게 클래스를 결정한 후에 클래스에 어떤 속성, 메서드가 필요한지 고민한다.
하지만 이는 객체지향적인 설계와 거리가 멀다.
진정한 객체지향 패러다임으로의 전환은 클래스가 아닌 객체에 초점을 맞출 때에만 얻을 수 있다.

이를 위해서는 다음 두가지에 집중해야 한다.

1. 어떤 클래스가 필요한지를 고민하기 전에 어떤 객체들이 필요한지 고민하라.

  • 클래스는 공통적인 상태와 행동을 공유하는 객체들을 추상화한 것이다.
  • 따라서 클래스의 윤곽을 잡기 위해서는 어떤 객체들이 어떤 상태와 행동을 가지는지를 먼저 결정해야 한다.

2. 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 봐야 한다.

  • 객체지향적으로 생각하고 싶다면 객체를 고립된 존재로 바라보지 말고 협력에 참여하는 협력자로 바라봐야 한다.
  • 객체들의 모양과 윤곽이 잡히면 공통된 특성과 상태를 가진 객체들을 타입으로 분류하고, 이 타입을 기반으로 클래스를 구현하라.

시스템의 어떤 기능을 구현하기 위해 서로의 메서드를 호출하며 상호작용하는 것을 협력이라고 한다.
객체는 다른 객체의 인터페이스에 공개된 행동을 수행하도록 요청할 수 있다.
요청을 받은 객체는 자율적인 방법에 따라 요청을 처리한 후 응답한다.
객체가 다른 객체와 상호작용할 수 있는 유일한 방법은 메시지를 전송 하는것 뿐이다.
다른 객체에 요청이 도착할 때 해당 객체가 메시지를 수신했다고 한다.
메시지를 수신한 객체는 스스로의 결정에 따라 자율적으로 메시지를 처리할 방법을 결정하며, 이 방법을 메서드라고 한다.
메시지와 메서드의 구분에서 다형성의 개념이 출발한다.

 

다형성을 이용하면 컴파일 시점의 의존성과 실행 시점의 의존성이 서로 다를 수 있다.
이를 통해 같은 메시지로도 메시지를 수신한 객체의 타입에 따라 다른 메서드를 실행할 수 있다.
이렇게 코드를 작성한다면 더 유연하고, 쉽게 재사용 할 수 있다.
하지만 이러면 코드를 읽었을 때 이해하기 어려워진다.
이와 같은 의존성의 양면성은 설계가 트레이드오프의 산물이라는 사실을 보여준다.
따라서 객체지향적으로 설계하기 위해서는 이런 유연성과 가독성 사이에서 고민해야한다.

 

상속은 구현 상속 / 인터페이스 상속으로 분류할 수있다.
구현 상속 - 코드를 재사용하기 위한 목적
인터페이스 상속 - 다형적인 협력을 위해 부모 클래스와 자식 클래스가 인터페이스를 공유하기 위한 목적
상속은 구현 상속이 아니라 인터페이스 상속을 위해 사용해야 한다.
= 코드 재사용이 아닌, 같은 메시지를 수신할 수 있다는걸 뜻하는 의미에서 사용해야한다.

 

대부분의 사람들은 객체지향 프로그래밍 과정을 클래스 안에 속성과 메서드를 채워넣는 작업이나,
상속을 이용해 코드를 재사용하는 방법 정도로 생각한다.
하지만 이렇게 프로그래밍 관점에 너무 치우쳐서 객체지향을 바라볼 경우 객체 지향의 본질을 놓치기 쉽다.
객체지향이란 객체를 지향하는 것이다.
가장 중요한것은 애플리케이션의 기능을 구현하기 위해 협력에 참여하는 객체들 사이의 상호작용이다.
이런 객체들 사이의 역할, 책임, 협력이라는 본질이 가장 중요하다.

 


인상깊었던 점

"객체지향이란 단순히 클래스 안에 속성과 메서드를 채워넣는 작업이나 상속을 이용해 코드를 재사용하는게 아니다."
이번 장에선 이 문장이 가장 인상깊었다.
지금껏 객체 지향 프로그래밍에서 상속에 대해 설명할 땐 코드 재사용 측면을 위주로 설명했다.
하지만 이번 장을 읽고 상속은 단순히 코드를 재사용한다는게 중점이 아닌,

다형적인 협력을 위해 부모 클래스와 자식 클래스가 인터페이스를 공유하는 것이라는걸 배울 수 있었다.
앞으로 코드를 작성하기에 앞서, 객체 간의 협력 과정을 메시지 / 메서드로 나눠서 생각하는 습관을 들여봐야 겠다.

'공부방 > 북스터디' 카테고리의 다른 글

[오브젝트] 6장  (0) 2024.01.23
[오브젝트] 5장  (0) 2024.01.15
[오브젝트] 4장  (0) 2024.01.05
[오브젝트] 3장  (0) 2023.12.25
[오브젝트] 1장  (0) 2023.12.15

1장 정리

데이터 관점으로 코드를 작성하면 변경 이전 코드처럼 되기 쉽다.
모든 처리가 하나의 클래스 안에 위치하고, 나머지 클래스는 단지 데이터의 역할만 수행한다.
그래서 어떤 클래스가 어떤 정보를 갖고 있는지 너무 많은 정보를 알아야 한다.
이는 코드를 읽는 사람에게도 굉장한 부담을 준다.
또한 너무 많은 정보를 알고 있기 때문에 변경에도 쉽게 영향을 받고 취약하다.

 

캡슐화를 통해 객체의 내부 구현을 숨겨서 객체를 자율적인 존재로 만들면,
객체끼리 메시지를 전달함에 있어서 오로지 퍼블릭 인터페이스에만 의존한다.
즉, 메시지를 수행할 객체의 구현 세부사항을 전혀 몰라도 동작할 수 있다.
알아야할 정보가 줄면 결합도 또한 자연스럽게 줄어든다.
또한 인터페이스에만 의존 하므로 객체의 내부 구현이 변경되어도 영향을 받지 않는다.

 

객체지향 설계에서는 각각의 객체를 자율적인 존재로 만들어 각자의 책임을 수행하도록 한다.
이렇게 책임의 관점에서 설계를 하면 하나의 객체가 가진 과도한 책임을 분산할 수 있다.
하지만 동일한 기능을 한가지 이상의 방법으로 설계할 수 있으므로 결합도와 자율성 사이에서 적절한 트레이드 오프가 필요하다.

 

객체지향적인 프로그래밍이란 흔히들 실세계의 모방이라고 설명한다.
하지만 객체지향적인 설계를 설명하기에 이 실세계의 모방이라는 개념은 적절하지 않다.
객체 세계에선 현실에서 무생물이거나 수동적인 존재를 생물처럼 능동적이고 자율적인 존재로 의인화한다.
훌륭한 객체지향 설계란 소프트웨어를 구성하는 모든 객체들이 자율적으로 행동하는 설계를 가리킨다.
애플리케이션의 기능을 구현하기 위해 객체들이 협력하는 과정속에서 객체들은 다른 객체에 의존하게 된다.
이런 의존성을 적절하게 관리하는것이 훌륭한 객체지향 설계이다.

 

인상깊었던 점

"객체지향적인 설계를 설명하기에 이 실세계의 모방이라는 개념은 적절하지 않다"
1장에서 가장 크게 와닿은건 이 내용이었다.
이전까지 저는 실세계의 모방이라는게 머리에 박혀서 코드를 짤 때 실세계에서는 어떻게 동작할까?
라는 생각을 위주로 코드를 짰던것 같다.
그래서 실세계에서 무생물인건 수동적으로, 생물인건 능동적인 개념으로 코드를 짜는 경향이 있었던것 같다.
지금이라도 이 고정관념에서 벗어날 수 있어서 다행이다.

'공부방 > 북스터디' 카테고리의 다른 글

[오브젝트] 6장  (0) 2024.01.23
[오브젝트] 5장  (0) 2024.01.15
[오브젝트] 4장  (0) 2024.01.05
[오브젝트] 3장  (0) 2023.12.25
[오브젝트] 2장  (0) 2023.12.24

자라기

1. 야생형 개발자가 되라.

공부법에는 학자형 공부법과 야생형 공부법이 있다.

둘 중 뭐가 우위다 하는건 아니고 두 학습법 모두 적합한 상황에 적용해야 한다.

  • 학자형 학습법은 차근차근 순차적으로 기초를 쌓아올라가는 방법이다.
  • 불확실성과 변동이 적은 분야는 학자형 공부법이 어울린다.
  • 야생형은 비순차적으로 필요에 따라 지식을 습득한다.
  • 불확실성이 높고 변동이 많은 분야일수록 야생형 공부법이 필요하다.

사람들은 불확실성이 높은 분야에서도 학교에서 공부하던 방법대로 공부하려는 경향이 있다.

졸업한 시점에서는 결국 학자형으로만 공부해서는 안된다.

아무 생각없이 고수가 시키는대로, 고수가 해왔던대로 하다보면 고수가 된다는 판타지를 버려야한다.

2. 의도적 수련을 하라.

생각없이 오랜 시간을 투자해봤자 일정 수준 이상 실력이 오르지 않고 효율도 나쁘다.

중요한건 의도적 수련이다. 짧은 주기로 피드백을 반복하면서 공부의 목적과 어디에 쓸 수 있을지 의식해야 한다.

또한 나를 되돌아보는 시간을 자주 가져서 변화한 실력에 맞는 적절한 난이도를 수시로 조정해야 한다.

3. 자신이 이미 갖고 있는 것부터 잘 활용하라.

올해 책 몇권을 읽었다고 자랑하지 말고, 배운것을 얼마나 활용했는지 생각해야한다.

이미 갖고 있는 지식을 촘촘히 연결하고 새로 배운 지식을 기존 지식과 충돌시키며 자신의 것으로 만들어야한다.

4. 실행 프레임을 만들지 말라.

무언가를 하면 어떤걸 얻을 수 있다는 보상심리로 공부하는건 좋지 않다.

또한 어떠한 이유 때문에 무언가를 할 수 없다는 생각도 좋지않다.

"부트 캠프를 수료하면 취업할 수 있겠지", "내 환경이 이래서 할 수 없었다" 같은 생각을 버려야 한다.

어차피 과거를 되돌릴 수는 없는 일이므로 동일한 환경 속에서도 성장의 기회를 찾아야 한다.

5. 능률을 올려주는 도구와 환경을 점진적으로 만들어라.

처음부터 완벽한 환경을 구성하고 시작할 생각을 하지 말고 점진적으로 개선할 생각을 해야한다.

결국 완벽한 환경이라는건 성립할 수 없고 결국 아쉬운 부분이 생긴다. 그러므로 당장 실행하고 점진적으로 개선하자.

6.튜토리얼을 읽어도 뭘 만들지 생각하며 읽어라.

그냥 배우는 데서 끝내면 결국 쉽게 잊어버리고 학습 속도도 느리다.

배운걸로 간단한거라도 만들어보는게 가장 빨리 배우는 길이다.

7. 새로운 언어를 배울 때는 표준 라이브러리 소스 코드를  읽어라.

새로운 언어를 배울 때는 당장은 잘 와닿지 않는다. 결국 사용을 해봐야 그 언어에 대한 스타일을 습득할 수 있는데

이럴 때 표준 라이브러리 소스코드를 보면 해당 언어의 숙어와 패턴, 스타일을 배우기 좋다.

8. "전문가에게 전문성을 효과적으로 뽑아내는" 전문가가 되라.

전문가에게 배움을 구할 때 그 비결 자체를 물어보는 화법은 원하는걸 많이 얻지 못할 수 있다.

전문가 본인도 잘 설명하고 싶어도 대본까지 완벽하게 준비해온게 아닌 이상 모든걸 말 할 수는 없다.

따라서 구체적인 사건에 대해 말하도록 유도하는 화법을 사용해야 원하는걸 많이 얻을 수 있다.

또한 모르는 문제에 대해 질문할 때도 어떻게 생각하면서 문제에 접근 했는지 과정을 설명하는 습관을 들이면

듣는 사람의 입장에서도 메타 인지에 도움이 되고 더 많은걸 알려줄 수 있다.

 


함께

1. 커뮤니케이션과 협력의 중요성

짝 프로그래밍은 대화를 통해 서로의 생각을 공유하면서 추상화와 구체화 과정을 반복한다.

그 결과 혼자서는 생각하지 못했던 영역까지 사고를 확장시킨다.

뛰어난 프로그래머 일수록 커뮤니케이션을 통해 구성원들의 협력을 잘 이끌어내고 이는 곧 생산성과 이어진다.

직관이라는 것은 생각보다 틀릴 때가 많다. 함께함으로써 이 직관의 허점을 줄일 수 있다.

함께라면 확률이 AND 에서 OR 로 바뀐다. 만약 팀원이 n명이고 개개인의 버그 발생 확률이 10% 라면

팀원끼리 단절된 독립적인 팀의 버그 발생하지 않을 확률은 0.9^n  이다. (모두 버그 발생하지 않은 경우)

하지만 함께 소통하는 팀의 버그가 발생하지 않을 확률은 1 - 0.1^n 이다. (1 - 모두가 버그가 발생할 확률)

2. 팀장이면 새로운 아이디어 전파가 쉬울거란 생각은 환상이다.

새로운 아이디어를 전파하기 위해서는 구성원들을 설득하는 과정이 필요하다.

구성원 각각의 이해의 수준과 성향이 판이하므로 그 사람에 맞는 대화법을 통한 설득이 필요하다.

3. 커뮤니케이션을 할 수록 신뢰가 깨지는 사람이 되지 말자.

신뢰는 사회적 자본이고 신뢰가 깨진 상태에서는 좋은 의도로 한 말이나 행동도 악의적으로 보인다.

결국 새로운 기술을 도입하고 제대로 정착시키기 위해서는 구성원들의 협력이 필요하다.

아무리 논리적이고 타당한 제안일지라도 구성원들간의 신뢰가 깨진 상태에서 구성원들을 설득하는것은 쉽지 않다.

상대방을 설득할 때는 논리성과 객관성에 대한 환상을 버려야 한다. 인간은 그리 합리적인 동물이 아니다.

4. 실수는 예방하는게 아니라 관리하는 것이다.

상대방을 압박하는 말투는 그 사람을 위축시키고 할 수 있는 일도 못하게 만드는 수가 있다.

결국 그 사람은 실수를 숨기고 질문을 안하는 경향을 띠게 될것이고 이는 조직에 큰 피해를 주는 결과로 이어질 수 있다.

상대방을 비난하는 대화 보다는 그 사람의 사고 과정과 전략을 이해하고 조언을 하는 사람이 되라.

더 나아가 행동을 유도하는 대화를 하라.

실수를 어떻게 막을지 생각하기 보단 실수를 빠르게 처리하는 방법을 생각하라.

 


애자일

1. 앞에서 말한 "함께"와 "자라기" 가 애자일의 핵심

애자일은 불확실성이 높은 프로젝트를 위해 생겨난 개념이다.

"자라기" 에서의 짧은 주기의 피드백을 통해 방향성을 수시로 재조정하고 필요한것을 학습하며 점진적으로 발전시킨다.

"함께" 에서의 협력과 커뮤니케이션을 통해 안좋은 일이 일어날 확률을 줄이고 좋은 일이 일어날 확률을 올린다.

2. 고객에게 가치를 전하라.

여기서 고객이란 돈주고 프로젝트를 맡긴 사람 뿐 아닌 프로젝트와 관련된 모든 이해 관계자를 말한다.

고객에게 가치를 전하면 신뢰가 쌓이면서 고객의 협력을 얻기 쉬워진다.

이로써 고객의 의사소통이 명확하고 구체화 되고 고객이 원하는 결과물에 더 가까워질 수 있다.

3. 두려워도 중요하다면 미루지 말고 시도해라.

결국 사람과의 소통이 가장 어렵기 때문에 고객의 협력을 얻는 것을 주저할 수 있다.

코드 공유 또한 개발자를 설득해야 하므로 이 또한 꺼려질 수 있다.

하지만 소통의 중요성을 알고 있다면 두려워도 미루지 말고 시도해야한다.

4. 누구나 애자일 코치가 될 수 있다.

애자일 코치는 팀장, 사장, 팀원 중 그 누구도 될 수 있다. 중요한건 애자일 코치가 되자고 결심하는 것이다.

"함께" 와 "자라기" 를 하고자 하는 사람이라면 누구든 애자일 코치가 될 수 있다.

5. 애자일을 애자일스럽게

애자일은 불확실성이 높은 프로젝트를 진행하기 위해 생겨난 개념이지 정해진 형식이 아니다.

변화에 대응하는 방식은 프로젝트마다 모두 다르다.

성공한 애자일 사례들로 나온 애자일 실천 방법들도 변화에 대응하는 한 때의 스냅샷이다.

 


느낀점

이 책을 보고 공부의 방향성과 커뮤니케이션 측면에서 깨달은 점이 많다.

나는 불확실성이 높은 프로그래밍이에서 학교에서 공부하던 방법대로 공부했던것 같다.

개발을 잘 하는 사람이 했던 순서대로 따라하다 보면 고수가 될거라고 생각했다.

아직도 옛날에 공부하던 습관을 버리지 못했나보다. 학자형 공부법을 쓰기에는 프로그래밍의 분야는 너무 넓다.

백년 천년 공부만 할게 아니라면 결국 개발을 진행하면서 생긴, 필요에 따른 공부가 필요하다.

 

또한 "함께" 파트를 읽으면서 저번에 했던 팀 프로젝트에 대해서도 생각해볼게 많다. 

최대한 신경쓴다고 했던 부분이지만 결국 커뮤니케이션과 협력 부분에서 미흡했던 부분이 많이 떠오른다.

커뮤니케이션과 협력의 가치를 생각하면서 함께 자랄 수 있는 방법 을 생각해야지.

더 나아가 나부터 애자일 코치가 되도록 스스로를 변화해나가야겠다.

코드 리뷰 훔쳐보기

최근 다른 사람이 받은 코드리뷰를 훔쳐볼때마다 하나씩 배워간다.

공부하기 싫을때는 이렇게 다른식으로 배움을 얻는것도 되게 좋은것 같다.

오늘 배운건 검증부는 하드코딩한다 라는 주제이다.

 

검증부는 하드코딩한다.

요즘 테스트코드를 적용해보는건 좋지만 너무 생각없이 작성하고 있었음을 느낀다.

예를 들자면 아래같은 코드다.

문제의 테스트코드

@DisplayName("로그인 요청 시 DB 정보와 일치하면 accessToken 을 발급한다.")
@Test
void signin() throws JsonProcessingException {
    // given
    Signup signup = Signup.builder()
        .email("hyukkind@naver.com")
        .name("midcon")
        .password("1234")
        .build();
    authService.signup(signup);

    LoginRequest request = LoginRequest.builder()
        .email("hyukkind@naver.com")
        .password("1234")
        .build();

    // when
    String name = authService.signin(request);
    User user = userRepository.findByEmail("hyukkind@naver.com")
        .orElseThrow(() -> new InvalidSigninInformationException());

    // then 이 검증부가 문제 !
    assertEquals(user.getName(), name);
}

생각없이 검증부를 아래처럼 작성하고 있었다.

assertEquals(user.getName(), name);

 


문제점

1. 무의미한 검증

이런 검증부는 별로 의미없는 테스트라고 생각이 된다.

이처럼 도메인 로직을 사용한 소프트 코딩은 사실상 프로덕션 코드를 복사 & 붙여넣기 한것이다.

굳이 userRepository.findByEmail 일 이유도 없고 signup.getName 이어도 상관없을 것이다.

 

2. 구현코드와 강결합

이처럼 도메인 로직을 사용한 테스트는 도메인 로직과 강결합을 한다는 문제점 또한 가진다.

만약 리팩토링을 하여 user.getName 로직이 바뀐다면 테스트 또한 모두 바꿔야한다.

검증하고자 하는 로직을 변경한다면 테스트를 바꿔야하는건 당연하지만

다른 도메인 로직을 바꿨을 때도 상관없는 다른 테스트 코드를 변경해야하는건 문제가 있다.

 

따라서 검증부는 아래처럼 하드코딩하여 테스트 목적에 맞는 값을 작성하는게 옳다.

수정한 검증부

// then
assertEquals("midcon", name);

 

이와 관련한 더 자세한 내용을 원한다면 아래 참고자료에 첨부한 향로님 블로그 글을 읽어봐도 도움이 될것이다.

 


참고자료

 

검증부 (assert / expect)는 하드코딩한다

최근 코드리뷰를 하다가 자주 지적하던 내용이 있어, 정리하게 되었다. 요즘 팀 분들이 가장 많이 하는 실수가 바로 검증부에 도메인 로직이 추가되는 것이다. 이를테면 다음과 같은 구현 클래

jojoldu.tistory.com

 

코드 리뷰

코드 리뷰란 주어진 코드에 대해 코드를 작성한 개발자와 이외의 개발자들끼리 피드백을 주고 받는것이다.

이 과정을 통해 코드를 작성한 개발자는 본인이 생각하지 못했던 버그나 사이드 이펙트를 발견할 수 있고,

코드를 리뷰한 개발자는 자신과 다른 관점의 코드를 보며 인사이트를 얻을 수도 있고 지식을 말로 가공하는 과정에서

지식을 재정리 하며 효과적으로 전달하는 방법을 생각해볼 수 있다.

 

코드 리뷰 하는법

그럼 이제 Github 에서 Pull request(PR)를 이용해 코드 리뷰를 하는 법을 알아보자.

org 를 만들어서 코드 리뷰 할 사람끼리 PR 올리는 과정까지은 알거라 생각하고 설명하지 않겠다.

우선 원격 리포지토리에 가서 Pull request 탭을 들어가면 아래처럼 나올 것이다.

 

 

1. 리뷰어로 참여하고자 하는 PR 에 들어가서 Files changed 를 누른다.

 

 

2. 아래 사진의 과정을 진행

Files changed 에 들어가면 해당 PR 에 커밋한 모든 파일들이 보일것이다.

리뷰를 남기고 싶은 코드가 있다면 아래 사진의 1, 2 의 과정으로 리뷰를 남긴다.

1, 2 를 반복하여 모든 리뷰를 마치고 나면 3번을 누른다.

 

 

3. Submit review 를 누른다.

Comment, Approve, Request changes 기능이 있으니 잘 활용하자.

전체적인 코멘트를 남기고 싶은게 있다면 맨 위 코멘트를 작성할 수 있다.

해당 PR 의 내용을 브랜치에 merge 하는걸 승인한다면 아래의 Approve 를 체크해주면 된다.

 

 

끝!

코드 리뷰는 처음이라

굉장히 유익한 시간이었다.

현업자들의 정돈된 코드와 취준생들의 정돈이 덜 된 코드를 번갈아 보면서 어떡해야 가독성 높고 변경에 용이한 코드를 작성할 수 있는지 생각해볼 수 있었다.

또한 현업자들의 커밋 단위와 커밋 메시지의 좋은 예를 볼 수 있었고 ReadMe 작성, 테스트 작성도 배울 수 있었다.

또한 코드 리뷰를 하며 동일한 주제에 대해 내가 생각했던 접근 방법과 다른 사람들의 다양한 관점의 접근을 비교해보고

좋은 인사이트를 얻을 수 있었다.

첫 코드 리뷰 모임을 굉장히 좋은 사람들과 진행하게 되어 기쁘다.

 

더 생각해 볼 점

코드 리뷰 또한 개발자간의 오고가는 커뮤니케이션이므로 리뷰를 받는 사람의 마음을 고려하는게 제일 순위인것 같다.

내가 생각하는 방법만이 정답이 아니고 코드 리뷰는 서로 최적의 방법을 찾아가는 과정임을 명심해야한다.

따라서 누가 봐도 완전히 안티패턴인 경우를 제외하면 내가 전달하고자 하는 메시지를 명확하게 전달하면서

상대방의 마음을 상하지 않게 하는법을 더 생각해봐야겠다.

또한 방법을 알려주기보단 방향을 알려주는 방식으로 리뷰하는 습관을 들여야겠다는 생각이 들었다.

현업자 분들의 코드 리뷰 방식을 보면서 이런 상대방을 생각하는 스탠스가 눈에 잘 보여서 배울게 정말 많았다.

+ Recent posts