시스템 Concern (관심사) 시작 단계는 모든 앱이 풀어야하는 관심사(Concern) 이다. 관심사 분리는 오래된 가장 중요한 기법이다. 대다수의 앱은 시작 단계라는 관심사를 분리 하지 않고 준비 과정 코드를 주먹구구로 구현하고 심지어 런타임 로직하고도 섞인다. 다음은 대표적인 예다. class SomethingMain(object): ... def get_service() -> Service: if not self._service: self._service = MyService() return self._service def main(): ... service = self.get_service() ... ... 위는 초기화 지연 (Lazy Initialization) 혹은 계산 지연 (Laze Ev..
응집도 클래스는 인스턴스 변수 수가 적어야 한다. 각 메소드는 클래스 인스턴스 변수를 하나 이상 사용해야 한다. 일반적으로 메소드가 인스턴스 변수를 더 많이 사용 할수록 메소드와 클래스는 응집도가 높다. 모든 인스턴스 변수를 메소드마다 사용한다면 응집도가 가장 높은 경우이다. 응집도가 높은 클래스는 바람직 하지 않지만 많은 개발자들이 응집도가 높은 클래스를 작성한다. 응집도가 높다는 말은 변수와 메소드가 서로 논리적으로 묶여 있다는 의미이기 때문이다. 아래는 클래스의 응집도가 매우 높은 케이스다. class Stack(object): _top_of_stack = 0 _elements = [] def size(self) -> int: return self._top_of_stack def push(self,..
클래스 클래스 체계 클래스에서 static, public 변수는 위에 다음으로 private 변수 마지막으로 private object 가 나와야 한다. 클래스의 변수와 메소드는 가능한 공개하지 않는 편이 좋지만 때로는 접근을 허용해야 하는 경우가 있다. 따라서 그런 경우에는 protected 로 하거나 패키지내 공개 해야 한다. 하지만 가능한 그렇지 않게 작성 해야 한다. 클래스 이름 이름은 해당 클래스의 책임을 기술해야 한다.(명사로) 간결한 이름이 떠올리지 않는다면 책임이 많을 확률이 높다. 단일 책임 원칙(Single Responsibility Principle) 단일 책임 원칙은 모듈을 변경할 이유가 단 하나뿐이어야 한다는 원칙. 매우 지키기 쉽지만 많은 개발자들이 안지키는 원칙이다. 어떤 개발..
단위 테스트 깨끗한 테스트 1. 테스트틑 빨라야 한다. 테스트가 느리면 테스트를 자주 못하고 자주 돌리지 못하면 결국 문제가 발생해도 코드 정리가 힘들어져 코드 품질이 망가지기 시작한다. 2. 독립적 각 테스트는 서로 독립적이여야 한다. 한 테스트가 다음 테스트가 실행될 한경을 기다려서는 안 된다. 테스트가 서로 의존하면 하나가 실패하면 연달아 실패하므로 결함 찾기가 힘들다. 3. 반복 가능 테스트는 Test, QA, Production 모두 사용 가능 해야 한다. 4. 자가 검증 테스트는 Boolean 으로 결과를 내야 한다. 즉 성공 아니면 실패 로 해야 한다. 5. 적시에 단위 테스트는 실제 코드 작성 전 구현해야 한다. 실제 코드를 구현하고 테스트 코드 작성시에는 테스트 코드로 작성하기가 어려울 ..
단위 테스트 도메인 특화 테스트 앞서 9-1 에서 구현간 기법으로 주로 API 위에다 함수와 유틸리티를 구현한 후 테스트 코드를 작성함으로 코드작성과 높은 가독성을 가진다. 테스트 코드는 쉽고 간결하고 이해하기 쉽게 해야하지만 효율성의 측면에서는 효율적일 필요는 없다. 온드가 급격하게 떨어지면 경보, 온풍기, 송풍기가 모두 가동 되는지 확인하는 코드. func TestTurnOnLoTempAlramAtThreashold(t *testing.T) { hardware.SetTemp(WayTooCold) controller.Tic() tests.AssertEqual(t, hardware.HeaterState(), true) tests.AssertEqual(t, hardware.BlowerState(), tru..
단위 테스트 TDD, Test Driven Development 첫째, 실패하는 단위 테스트를 작성할 때까지 서비스 코드를 작성하지 마라. 둘째, 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성 하라. 셋째, 현재 실패하는 테스트를 통과할 정도의 서비스 코드를 작성 하라. 이렇게 일을 하면 테스트 수천개의 케이스가 생기는데 이를 전부 다 방치를 하면 서비스 코드와 맞먹을 정도의 규모가 되는데 이는 심각한 관리문제를 야기한다. 깨끗한 테스트 코드 테스트 코드는 가독성이 중요하다. 변경 전은 addPage와 assertSubString를 부르는라 중복되는 코드가 매우 많다. 자질구레한 사항은 없애고 테스트 코드 표현의 중점하자. public void testGetPageHieratch..
객체와 자료구조 디미터 법칙 모듈은 자신이 조작하는 객체의 속을 몰라야 한다는 법칙이다. 객체는 조회 함수로 내부 구조를 공개한다면 안 된다는 의미 (내부 구조를 노출하는 셈) C 클래스의 f 메소드는 다음과 같은 객체의 메소드만 호출 해야 한다. 클래스 C f가 생성한 객체 f로 넘어온 인수 클래스 C 인스턴스 변수 객체 디미터 법칙을 어긴 예시 같은 객체가 아닌 서로 다른 객체를 가지고 서로 연결해서 작성한 이런 코드를 기차 충돌 이라고 부른다. 일반적으로 조잡하니 지향하는 편이 좋다. outputDir := cTxt.GetOptions().GetScratchDir().GetAbsolutePath() 변경 예시 opts := cTxt.GetOptions(); scratchDir := opts.GetS..
객체와 자료구조 객체 지향적 과 절차 지향적의 차이 절차 지향적인 코드는 기존 자료구조를 변경하지 않으면서 새 함수를 추가하기 쉽다. 반면 객체 지향적인 코드는 변경점이 생기면 기존 함수를 변경해야 하는 부분이 생길 수 있다. 모든 것을 객체 지향적인것 보다는 때로는 단순한 것이 적합한 상황이 있을 수 있다. 절차 지향적 class Squre(object): x: float y: float side: float class Rectangle(object): x: float y: float width: float height: float class Circle(object): x: float y: float radius: float def get_arae(figure: object) -> float: if ..
형식 소스를 보았을 때 코드가 깔끔하고 일관적이며 꼼꼼하며 질서정연하다고 생각되면 좋겠다. 술 취한 사람이 짜놓은 듯한 코드로 보인다면 코드를 보는 사람은 다른 부분도 그렇다고 생각 할 것이다. 개인적으로 스파게티처럼 작성된 소스는 유지보수할때 나도 스파게티를 만든는 경향이 있는데 비교적 잘 짜여졌다고 생각되는 부분을 고칠때는 나도 조심하여 일관성 있게 코드를 작성 할려고 하는 것 같다.프로그래머라면 형식을 깔끔하게 맞춰 코드를 짜야 한다. 팀마다 형식을 맞추고 규칙을 정하며 규칙을 따라야 한다. 필요하다면 형식을 적용하는 도구를 활용해도 된다. jetbranin 제품을 사용한다면 코드 양식을 1명이 수정한 다음 config 파일 공유해도 괜찮지 않을까? 싶다.# 형식을 맞추는 목적 누군가 "돌아가기만 ..
주석 우리는 주석을 코드로 의도를 표현 하지 못하여 사용 한다. 그러나 과거의 주석이 미래에 실패를 불러 올 수 있다. 코드는 언제나 변화하고 진화하며 이곳 저곳 옮겨지기도 한다. 주석은 그 코드를 따라가지 못한다. 누군가는 주석을 엄격하게 관리해야 한다고 할 수도 있지만 애초에 주석이 필요하지 않도록 코드를 작성 하는데 에너지를 쏟자. 코드로 주석을 대체하라 변경 전 # 직원에게 복지 혜택을 받을 자격이 있는지 체크 if (employee.flags and HOURLY_FLAG) and employee.age > 65 : do_something() 변경 후 if employee.isEnoughForFullBenefits() : do_something() # 이상적인 주석 public static Sim..
함수 함수는 한 가지만! 문제의 코드다. session_initialize() 를 주목하자. 최초 개발시 로그인시에 암호 체크용으로 개발을 했는데 이후에 다른 곳에서도 암호를 체크가 필요한 경우가 생겼고 똑같이 가져다 썻을 경우 Session이 초기화 되어 문제가 생길수 있다. 문제를 해결하기 위해서는 함수명을 check_password_and_session_init() 등으로 함수기능 명시하는 방법 (그래도 함수가 2가지 역할을 담당하여 문제) 함수의 기능을 두개로 다시 작성을 진행하는 방법이 있다. def check_password(username: str, password: str) -> bool: try: user = User.object.get(username = username) encrypt..
함수 인수 함수의 이상적인 인수개수는 0개 이다. 다음은 1개(단항) 다음은 2개(이항) 3개(삼항)은 피하는게 좋다. 4개(다항) 이상은 작성하면 안된다. 이유는 개념을 이해하기 어렵게 만든다 Test case 에서도 검증하기 위해서 다양한 인수를 작성하는 것도 어렵다. 운영 개발할때 경우에 따라서 필요한 경우가 있는데 요즘은 IDE 잘 되어 있어서 상관 없지 않을까 싶다. 그래도 줄일수 있다면 줄이자.1개 (단항 함수) 대표적인 단항의 경우는 주로 두가지로 나누어진다. 질문을 던지는 경우 def is_file_exist(filepath:string) -> bool: ... Parameter를 변환하여 결과를 Return 하는 경우 def file_open(filepath:string) -> file:..
함수는 작게 만들어라 함수는 최대한 작게 만들어라. If문, While문 등 사용시 블록안에는 라인 1개로 처리하도록 하자. 이를 통해서 우리는 1단~2단 수준에 들여쓰기 수준을 유지할 수 있고 함수는 읽기 쉬워지고 이해하기 쉬워진다. def some_method(): ... if is_something: show_something() 함수는 한 역할만 해라 def request_something(): response = requests.post('url') return response def handle_response(response: Response): if response.status_code == 200: do_success() else: do_failure()
Class 이름 Class와 Object의 이름은 명사가 적합하다. [Good] Customer, WikiPage, Account, AddressParser [Bad] Manager, Processor, Data, Info Method 이름 Method와 Function의 이름은 동사가 적합하다. [Good] postPayment, deletePage, save javabean 표준에 따라서 Accessor(접근자), Mutator(변경자), Predictate(조건자)는 앞에 get, set, is 를 붙인다. 이름을 혼용하지마라 여러 Class에 add() 함수의 역할과 Paramerter와 Return 이 동일하다면 계속 사용해도 되지만 기존과 다른 성격을 지닌다면 insert() 나 append(..
5S 철학... 1. 정리 또는 조직화(정렬) : 적절한 명명법 방법 등을 통해 무엇이 어디에 있는지 알아야 한다. 2. 정돈 또는 체계화 : 코드는 누구나 예상하는 위치에 있어야 한다. 그렇지 않다면 위치 정돈을 하여라. 3. 청소 또는 정리 : 소스에 과거 이력이나 주석으로 처리한 코드 등은 제거하기 바란다. 4. 청결 또는 표준화 : 프로젝트 내 일관적인 구현 스타일과 기법을 가져라. 5. 규율 또는 생활화 : 관례를 따르고, 변경이 필요하다면 기꺼이 변경 하여라. 맞는 말도 있는 것 같고 아닌 말도 있는 것 같고...