Today I../Today I Read

[Clean Code] Chapter 02. 의미 있는 이름

HJChung 2022. 1. 29. 00:24
Clean Code 클린 코드 - 로버트 C. 마틴  를 읽고, 해설 강의를 통해 보충 이해한 내용을 정리한 글입니다. 

 

1. 의미가 분명한 이름

약 3개월 전, 나는 이런 코드가 포함된 '나쁜 코드'를 PR했고

INTERVAL1 = int(os.environ.get("INTERVAL1"))
INTERVAL2 = int(os.environ.get("INTERVAL2"))
...
...
...
if interval_flag == 1:
    logger.info("There is no messages to be processed yet or no instance to turn on")
    time.sleep(INTERVAL1)
else:
    logger.info("wait for creating and setting the new instance")
	time.sleep(INTERVAL2)

아래와 같은 코드리뷰를 받았다. 

 

" Interval1, Interval2보다는 각각이 가지고 있는 의미를 쓰면 좋을 것 같습니다.
변수명에서 '아 뭔가 interval이구나' 밖에 알 수가 없어서 개선의 여지가 있는 것 같아요 "

 

클린코드 2장. 의미 있는 이름 을 읽으면서 저 코드와 리뷰가 바로 생각이 나면서 정말 부끄러워졌다.

저 코드 리뷰를 받았다는게 부끄러웠다는게 아니라, 어떻게 저런 변수명을 사용한 코드를 피알할 수 있었는지 그 당당함이 부끄러워졌달까..

 

책에서 여러가지 권고사항이 언급되지만 그 중 '의도를 분명히 밝혀라', '그릇된 정보를 피하라', '의미 있게 구분하라', '자신의 기억력을 자랑하지 마라'에 해당하는 내용은 '올바른 의미가 분명한 이름'으로 정리할 수 있다고 생각한다. 

보통 의미가 분명하지 않은 이름을 사용하는 경우에 작성자에게 깔려있는 나쁜 마음은 '암암리에 코드 리딩하는 사람이 다음과 같은 정보 (사실은 코드 짠 사람만 알고 있음)을 알고 있다고 가정' 하는 것이다. 

하지만 위에서 언급한 내가 리뷰 받은 INTERVAL1, INTERVAL2 변수명처럼 이 변수가 뭘 의도했는지, 무슨 의미적인 차이가 있는지는 '나'만 알고 있는 것이다.

명확하게 밝혀놓지 않으면 명확하게 알 수 없다. 

2. 의미가 분명한 이름을 짓기 위한 마음가짐 & 질문

의미가 분명한 이름을 짓기 위해서는 이런 마음가짐을 가져보자 .

  • 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약는 시간이 훨씬 더 많다. 
  • 유사한 개념은 유사한 표기법을 사용한다. 이것도 정보이며 일관성이 떨어지는 표기법은 그릇된 정보이다. 
  • 읽는 사람이 차이를 알도록 이름을 짓자. 

 

그리고 이런 질문을 스스로 던져보자. 

  • 변수 (or 함수 or 클래스) 의 존재 이유는?
  • 수행 기능은?
  • 사용 방법은?

 

3. 예시

해당 예시들의 출처는 
https://github.com/ryanmcdermott/clean-code-javascript#variables,
https://github.com/labs42io/clean-code-typescript#variables,
https://github.com/zedr/clean-code-python#variables
입니다. 

1) Use meaningful variable names

  • Javascript
    • Bad: 
      const yyyymmdstr = moment().format("YYYY/MM/DD");​
    • Good: 
      const currentDate = moment().format("YYYY/MM/DD");
  • Python
    • Bad:
      import datetime
      
      ymdstr = datetime.date.today().strftime("%y-%m-%d")
    • Good:
      import datetime
      
      current_date: str = datetime.date.today().strftime("%y-%m-%d")

2) Use the same vocabulary for the same type of variable

  • Javascript
    • Bad:
      function getUserInfo()
      function getUserDetails()
      function getUserData()
    • Good:
      function getUser(): User;
  • Python 
    • Bad:
      def get_user_info(): pass
      def get_client_data(): pass
      def get_customer_record(): pass
       
    • Good:
      def get_user(): pass

3) Use explanatory variables

  • Javascript
    • Bad:
      const address = "One Infinite Loop, Cupertino 95014";
      const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
      saveCityZipCode(
        address.match(cityZipCodeRegex)[1],
        address.match(cityZipCodeRegex)[2]
      );​
       
    • Good:
      const address = "One Infinite Loop, Cupertino 95014";
      const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
      const [_, city, zipCode] = address.match(cityZipCodeRegex) || [];
      saveCityZipCode(city, zipCode);
  • Python
    • Bad:
      import re
      
      address = "One Infinite Loop, Cupertino 95014"
      city_zip_code_regex = r"^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$"
      
      matches = re.match(city_zip_code_regex, address)
      if matches:
          print(f"{matches[1]}: {matches[2]}")
    • Good:
      import re
      
      address = "One Infinite Loop, Cupertino 95014"
      city_zip_code_regex = r"^[^,\\]+[,\\\s]+(?P<city>.+?)\s*(?P<zip_code>\d{5})?$"
      
      matches = re.match(city_zip_code_regex, address)
      if matches:
          print(f"{matches['city']}, {matches['zip_code']}")

4) Avoid Mental Mapping

  • Javascript
    • Bad:
      const locations = ["Austin", "New York", "San Francisco"];
      locations.forEach(l => {
        // doStuff();
        // doSomeOtherStuff();
      
        // Wait, what is `l` for again?
        dispatch(l);
      });
       
    • Good:
      const locations = ["Austin", "New York", "San Francisco"];
      locations.forEach(location => {
        // doStuff();
        // doSomeOtherStuff();
        // ...
        dispatch(location);
      });
  • Python
    • Bad:
      seq = ("Austin", "New York", "San Francisco")
      
      for l in seq:
          #do_stuff()
          #do_some_other_stuff()
      
          # Wait, what's `l` again?
          print(l)
    • Good:
      locations = ("Austin", "New York", "San Francisco")
      
      for location in locations:
          #do_stuff()
          #do_some_other_stuff()
          # ...
          print(location)

 

4. 실습 코드

Clean code 해설강의에서는 함수, 주석, 단위테스트, 오류 처리 등 각 챕터별로 실제로 어떻게 적용하면 되는지 실습하는 시간이 있다. 

이를 따라서 해보고는 있는데, Java 언어로 진행되기 때문에 완벽한 이해에는 조금 무리가 있긴 하다. 

하지만 개발이 목적이 아닌 clean code 연습이 목적이기 때문에 이에 초점을 맞춰서 진행하고 있다. 

https://github.com/Gracechung-sw/clean-code-practice

 

GitHub - Gracechung-sw/clean-code-practice

Contribute to Gracechung-sw/clean-code-practice development by creating an account on GitHub.

github.com