본문 바로가기

프로그래밍&IT/기타

[클린 코드] 1. 깨끗한 코드 정의 / 2. 의미있는 이름

클린코드 읽다가 말았는데, 이번에 다시 보고 있다.

어디서부터 읽었는지 기억이 안나니 복습도 할겸 첨부터 보긴하는데,

시작을 했으면 제대로 한 번 봐야 시간도 아끼는 것 같다. (필요하면 다시 볼수는있지만)

 

차례

1. 깨끗한 코드

2. 의미있는 이름 짓기

1. 깨끗한 코드

코드란?  요구사항을 상세히 표현하는 수단.

- 의존성을 최대한 줄여야 유지보수쉬워진다. 깨끗한 코드는 한가지를 제대로 한다

- 단순하고 직접적. 잘쓴 문장처럼 읽힌다. 설계자의 의도를 숨기지 않는다. 명쾌한 추상화와 단순한 제어문
- 모든 테스트를 통과하며 , 중복이 없다, 시스템 내 모든 설계 아이디어를 표현

- 작성자가 아닌 사람도 읽기쉽고 고치기 쉽다. 의미있는 이름. 의존성을 최소화하며. 의존하게되면 의존성을 명확히 정의하도록 한다.
- 코드는 문학적으로 표현해야 마땅하다

- 깨끗한 코드는 언제나 누군가 주의깊게 짰다는 느낌을 준다

- 중복피하라. 함수는 한개의 기능만 수행하도록 한다.. 제대로 표현하라. 작게 추상화하라
- 짐작했던 기능을 각 루틴이 그대로 수행된다.. 코드가 그 문제를 풀기위한 언어처럼 보인다면 아름다운 코드라 불러도 되겠다

 

- 의존성을 줄인다?

소프트웨어 모듈 또는 클래스 간의 강한 결합을 완화하여 코드의 재사용성, 유지보수성, 확장성을 높이는 개발 기법을 의미.

이는 주로 의존성 주입(DI), 인터페이스 분리, 느슨한 결합(loose coupling) 등의 설계를 통해 달성된다.

 

1. 의존성높은 (강한 결합) 코드 예시

- 문제점

  • Notification 클래스는 EmailService에 강하게 결합되어 있어 다른 메시지 전송 서비스(SMS, Push 등)로 교체가 어렵습니다.
  • 테스트 시 EmailService의 실제 구현에 의존해야 하므로 단위 테스트가 어려워집니다
public class EmailService
{
    public void SendEmail(string message)
    {
        Console.WriteLine($"Sending Email: {message}");
    }
}

public class Notification
{
    private EmailService _emailService;

    public Notification()
    {
        // 직접 인스턴스를 생성하여 의존성이 높음
        _emailService = new EmailService();
    }

    public void Notify(string message)
    {
        _emailService.SendEmail(message);
    }
}

 

2. 의존성을 줄인 코드. 느슨한 결합

// 메시지 전송을 추상화하는 인터페이스
public interface IMessageService
{
    void Send(string message);
}

// EmailService는 IMessageService를 구현
public class EmailService : IMessageService
{
    public void Send(string message)
    {
        Console.WriteLine($"Sending Email: {message}");
    }
}

// Notification 클래스는 IMessageService에 의존
public class Notification
{
    private readonly IMessageService _messageService;

    // 생성자를 통해 의존성을 주입
    public Notification(IMessageService messageService)
    {
        _messageService = messageService;
    }

    public void Notify(string message)
    {
        _messageService.Send(message);
    }
}

//// 사용
class Program
{
    static void Main(string[] args)
    {
        // 필요한 구현체를 생성자에 전달
        IMessageService emailService = new EmailService();
        Notification notification = new Notification(emailService);

        notification.Notify("Hello, Dependency Injection!");
    }
}

장점:

  1. 느슨한 결합:
    • Notification은 IMessageService 인터페이스에만 의존하므로, 구체적인 구현체(EmailService, SmsService)에 독립적
    • 새로운 메시지 전송 서비스가 추가될 경우 Notification 코드를 변경할 필요가 없다.
  2. 유지보수성:
    • 코드를 확장하거나 변경할 때 수정 범위가 최소화
  3. 테스트 용이성:
    • 단위 테스트에서 IMessageService를 목(Mock) 객체로 대체하여 테스트가 가능하다.

 

2. 의미있는 이름을 짓는다.

  • 의도를 분명히 밝히기
  • 그릇된 정보/단서를 피하라
  • 흡사한 이름사용도 주의
  • 일관성떨어지는 표기법은 그릇된 정보
  • 의미있게 구분
  • 발음 쉬운 이름
  • 검색하기 쉬운 이름 사용
  • class명: 명사계 / 메서드: 동사계. 접근,변경,조건자는 get/set/is를 붙인다
  • 기발하거나 유머적인 이름은 피한다
  • 한 개념에 한 단어 사용 ex) 조회클래스마다, get, fetch, retrieve 등 사용은 혼란스럽다
  • 말장난하지 말라  - 1단어를 2가지목적으로 사용치 말라
  • 문제 영역에서 가져온 이름을 사용하라
  • 의미있는 맥락 추가. 정안되면 접두어붙인다. Addr 같은
  • 불필요한 맥락을 없애라. 의미가 분명하면 짧은 이름이 긴 이름보다 좋다