형식
형식 맞추기
-
코드 형식은 의사소통의 일환이다. 의사소통은 전문 개발자의 일차적인 의무다.
-
좋은 소프트웨어는 읽기 쉬운 문서로 이루어진다. 스타일은 일관적이고 매끄러워야 한다.
1. 적절한 행 길이 유지
- 일반적으로 큰 파일보다 작은 파일이 이해하기 쉬움
- 신문기사처럼 작성
- 표제: 최상단에서 기사를 몇마디로 요약
- 요약: 첫 문단에 전체 기사 내용 요약
- 세부 내용: 읽어 내려 갈 수록 세부 내용 표시
- 소스 파일
- 소스 파일 이름(표제): 간단하면서도 설명이 가능
- 첫 부분(요약): 고차원 개념과 알고리즘 설명
- 세무 내용: 아래로 내려갈수록 소스 파일 의도를 세세하게 묘사, 마지막에 가장 저차원 함수와 세부 내역이 나옴
- 빈 행
- 개념 분리: 빈 행은 새로운 개념을 시작한다는 시각적 단서로 사용
- 세로 밀집도(+ 수직거리)
- 연관성 분리: 서로 밀접한 코드 행은 세로로 가까이 놓여야 함
- 타당한 그건가 없다면 서로 밀접한 개념은 한 파일 속에 모음
- 세로 거리로 연관성을 표현
1) 변수 선언
- 변수는 사용하는 위치에 최대한 가까이 선언
2) 인스턴스 변수
- 모두가 알고 있는 위치에 인스턴스 변수를 모음
3) 종속 함수
- 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치
- 호출하는 함수를 호출되는 함수보다 먼저 배치
4) 개념적 유사성
- 친화도에 비례하여 코드 위치 지정
- 고차원 —-> 저차원 함수로 배치
- 친화도 높은 요인
- 직접적인 종속성
- 변수와 그 변수를 사용하는 함수
- 비슷한 동작을 수행하는 일군의 함수
2. 가로 형식 맞추기
- 프로그래머는 명백하게 짧은 행을 선호한다.
- 가로 공백: 개념의 밀집도를 표현
- 가로 정렬
- 들여쓰기: 들여쓰는 정도는 계층에서 코드가 자리잡은 수준과 비례
- 들여쓰기 무시하기 예제
const getURL = () => { if (!isValid) return ""; return attachments.reduce( (signedUrl, element) => (Number(attachment_id) === Number(element.attachment_id) ? element.url : signedUrl), "", ); };
if 문은 간단해서 들여쓰기를 무시하는 것이 가독성에 더 좋을지 모르겠다.
하지만 이런식으로return
을 생략하며 버릇처럼 들여쓰기를 무시하기도 하는 것 같다.
위 예시는 return 생략 + 삼항 연산자의 사용으로 가로 길이가 너무 길어져서 오히려 가독성을 해치는 것 같다.const attachmentId = Number(attachment_id) const getURL = () => { if (!isValid) return ""; return attachments.reduce( (signedUrl, element) => { const eleAttachmentId = Number(element.attachment_id); return(attachmentId === eleAttachmentId ? element.url : signedUrl)}, "", ); };
- 들여쓰기 무시하기 예제
- 가짜 범위
3. 팀 규칙
- 팀 내에서의 의사소통과 가독성을 위해서 규칙이 필요하다. 규칙이 있음으로 인해서 조금 더 매끄러운 의사소통을 할 수 있다.
- 예제(아래와 같은 규칙을 정리해서 한번에 볼 수 있도록 모아둔 페이지가 있다.)
4. 밥아저씨의 형식 규칙
- 코드 자체가 최고의 구현 표준 문서가 되도록 한다.
5. 예제
const { attachments, isValid } = useDownloadBySchedule(productId, Number(duration));
const getURL = () => {
if (!isValid) return "";
return attachments.reduce(
(signedUrl, element) => (Number(attachment_id) === Number(element.attachment_id) ? element.url : signedUrl),
"",
);
};
const getIsLink = () => {
if (!isValid) return false;
return attachments.reduce(
(isLink, element) => (Number(attachment_id) === Number(element.attachment_id) ? element.isLink : isLink),
false,
);
};
const onClick = () => {
if (duePassed) return;
useUpdateCount(productId, attachment_id).then((result) => {
if (getIsLink()) return window.open(getURL());
return result;
});
};
- 고차원 -> 저차원
- 빈 행
- 들여쓰기
- 이름 수정
const { attachments, isValid } = useDownloadBySchedule(productId, Number(duration)); const attachmentId = Number(attachment_id); const onAttachmentDownloadButtonClick = () => { if (duePassed) return; useUpdateCount(productId, attachment_id).then((result) => { if (getIsLink()) return window.open(getURL()); return result; }); }; const getIsLink = () => { if (!isValid) return false; return attachments.reduce((isLink, element) => { const eleAttachmentId = Number(element.attachment_id); return attachmentId === eleAttachmentId ? element.isLink : isLink; }, false); }; const getDownLoadURL = () => { if (!isValid) return ""; return attachments.reduce((signedUrl, element) => { const eleAttachmentId = Number(element.attachment_id); return attachmentId === eleAttachmentId ? element.url : signedUrl; }, ""); };