일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- shader
- 112일선
- 전주비빔 라이스 버거
- 2023 게이밍
- 상계9동
- 224일선
- 공부
- GenAI
- JavaScript
- 언리얼5
- 언리얼 5
- 리팩터링 3장
- 스포일러 주의
- 2023 Gaming
- 이득우의 언리얼 프로그래밍 1
- URP
- 스즈메의 문단속
- 작계훈련
- 리팩터링 4장
- 리팩터링
- 1일차
- 이득우의 언리얼 프로그래밍1
- 주식
- 산토리 하이볼
- 448일선
- unity
- 주식단테
- 구글 컨퍼런스
- 2023 구글 클라우드
- 2023 게이밍 인 구글 클라우드
- Today
- Total
개발 이야기 안하는 개발자
Good Code, Bad Code (3) _ 다른 개발자와 코드 계약 본문
이번 3챕터는 다른 사람들이 나의 코드를 어떻게 바라보는지, 그래서 어떻게 해야하는지 생각해보는 챕터이다.
우리가 코딩을 할땐 해야하는 작업에 대해 생각하고,
어떻게 할지 구조를 짜고 설계를 한다.
즉, 내 일도 바쁜데 다른 사람 코드를 보기엔 피곤하다.
그래서 다음을 고려하며 코드를 작성해야 한다.
- 자신에게 명백하다고 해서 다른 사람에게도 명백한 것은 아니다.
작업을 진행하다보면 내가 작성한 코드 위에 동료의 코드가 위에 층층이 쌓이는 일이 빈번하다.
그렇게 하다보면 내가 작성한 코드의 명명이 다른사람들에겐 명백하지 않아 혼란을 줄 수 있다.
최대한 명백하게 해야하고, 만약 혼란을 줄 것을 고려한다면 주석을 다는 것도 좋은 방법이다.
- 다른 개발자는 무의식중에 여러분의 코드를 망가뜨릴 수 있다.
작업을 하면 당연히 내 코드에 추가로 필요한 로직을 추가할 수 있다.
이 과정에서 내가 원하지 않았던 과정이 추가되어 코드가 망가질 수 있다는 것을 고려하고 작업을 진행해야 한다.
- 시간이 지남에 따라 자신의 코드를 기억하지 못한다.
내가 지금 당장 코드를 작성하면서 왜 이렇게 했는지 정확하게 기억할 수 있다.
하지만 시간이 지나면 당연히 까먹게 된다.
내 코드를 처음 보는 사람처럼 똑같이 낯설게 느껴질 수 있다는 것을 고려해야 한다.
하지만 위 사항들을 고려하면서 코딩할때 주의사항으로는
세부 조항에 너무 의존하지 말아야 한다.
여기서 세부 조항이란, 해당 함수를 사용할때 어떠한 조건이 필요하다, 어떤게 필요하다 라는 조건으로 보면 된다.
즉, GetData() 를 한다고 한다면 LoadData() 를 먼저 시행했어야 한다라는 식을 세부 조항으로 본다.
(코드 계약이란 말은 해당 코드를 사용하기 위한 전제조건, 사후조건, 불변 등이 깔려 있음을 뜻한다)
#include <optional>
class TestClass
{
public :
TestClass() { };
//데이터 초기화
void InitData() {};
//데이터를 변경하기 위해선 Init이 먼저 호출되어야 한다.
//Init이 호출되었는지 확인 필요
void DataChange() {};
//데이터가 초기화 되었거나 데이터가 변경되었다면 데이터를 정상반환한다.
//그게 아니라면 null을 반환
std::optional<int> GetData() {
return std::nullopt; // 초기화되지 않은 경우 null 반환
}
};
우선 누군가가 TestClass를 사용한다고 가정한다.
그럼 필요할 것 같은 Init, Change, Get 을 public으로 두는데, 이 3 메소드에는 조건이 붙는다.
Change를 하려면 Init을 해야하고, Get을 하려면 둘 다 해야하고, Get은 Optional 이라서 딱히 초기화 되지 않아도 오류가 뜨지 않을 것이다.
즉, 정상적으로 원하는 데이터를 가져오려면 Init과 Change를 모두 진행했어야 한다.
...
포인트는 이 주석들을 다 읽으며 작업하기에는 너무 피곤하다는 것이다.
다른 누군가가 이 코드를 보고 작업하려면 피곤해 진다.
즉, 읽을 필요 없고, 고려하거나 고민할 거리를 없애주는게 제일 좋다.
세부 조항을 없애도록 고려하려면 이걸 모두 강제하면 된다.
#include <optional>
class TestClass
{
private:
TestClass() { };
public:
static std::optional<TestClass> CreateTestClass() {
TestClass instance;
instance.InitData();
instance.DataChange();
return instance; // std::optional로 래핑하여 반환
}
int GetData() {
return 0;
}
private:
void InitData() {};
void DataChange() {};
};
이렇게 하면 데이터를 생성할때 반드시 Init과 Change를 순차대로 진행하게 된다.
이렇게 하면 불필요한 주석들이 없어지고, 이 코드를 처음보는 사람으론 이해하는데에 짧은 시간이 걸리게 되어 더 좋은 코드가 된다.
* 여기서 TestClass를 값 타입으로 객체를 저장해서 사용했습니다.
어차피 RVO 때문에 불필요한 복사를 피하고 효율적으로 메모리를 관리하고 반환할때 Optional이기 때문에 여기에 복사되거나 이동되어서 사용될 것입니다
물론 코드가 합쳐지지 못하는 경우도 있을 수 있다.
그럴땐 Assert 나 Check 를 활용할 것을 권장한다.
'Book > Good Code, Bad Code' 카테고리의 다른 글
Good Code, Bad Code (5) _ 가독성 높은 코드를 작성하라 (0) | 2025.09.16 |
---|---|
Good Code, Bad Code (4) _ 오류 (0) | 2025.09.14 |
Good Code, Bad Code (2) _ 추상화 계층 (0) | 2025.09.04 |
Good Code, Bad Code (1) _ 코드 품질 (0) | 2025.09.02 |