[노개북 1기] TIL (2022.02.11)

yourjin·2022년 2월 26일
0

read.log

목록 보기
23/37
post-thumbnail

TIL (2022.02.11)

DAY 20

🔖 Mission5 : 더러운 코드를 깨끗한 코드로 리펙터링 해보세요!


노개북 클린코드 🔥 Final Mission

본인이 잘 이해했는지 확인하는 가장 정확한 방법은 가르쳐 보는 것!

가장 잘하는 언어로(JS, Python 등) 더러운 코드를 깨끗한 코드로 리팩토링 해보세요. (클린코드 읽을 때 분명 참고하라고 적어준 예시인데 자바로 되어있어서 공감이 잘 안됐죠?)

클린코드 읽으며 뼈맞았던 내용 중 3가지 진리 를 고르고,

진리를 따르는 예시 총 3가지를 만들어보세요.


(Python 예시) 진리 1. 함수는 한 가지를 해야 한다. (p.44)

무엇을 고쳤나요?

  • 함수가 2가지 일을 하고 있다.
    1. score를 통해 grade를 계산하는 작업
    2. subjectgrade 를 출력하는 작업
  • 함수 인수가 여러 개이고 유추하기 힘들다.
    • subject 변수는 함수명만 보고는 필요한 지 유추하기 힘들다
  • 출력 인수가 있다.

    일반적으로 우리는 함수 인수를 함수 입력으로 해석한다. 함수에서 상태를 변경해야 한다면 함수가 속한 객체 상태를 변경하는 방식을 택한다.

😢 Before

def printGradeByScore(subject, score):
	grade = 'A'
	
	if score >= 81:
		grade = 'A'
	elif score >= 61:
		grade = 'B'
	elif score >= 41:
		grade = 'C'
	elif score>= 21:
		grade = 'D'
	else:
		grade = 'E'

	print(f"{subject} Grade is {grade}")

printGradeByScore("Math", 92)

어떻게 고쳤나요?

  • 함수가 2가지 일을 하고 있다.
    • scoregrade를 구하는 작업과, 이를 출력하는 작업을 별개의 함수로 분리했다.
  • 함수 인수가 여러 개이고 유추하기 힘들다.
    • 과목의 등급을 출력하기 위해서는 과목 이름, 성적, 등급이 계속 함께 다닐 수 밖에 없다. 이런 경우 함수 인수를 줄이기가 힘들다.
    • 그래서 Subject 이라는 클래스를 만들어 필요한 항목들을 묶어두었다. 이제 클라이언트는 Subject 객체를 하나만을 가지고 모든 조작을 할 수 있다.
  • 출력 인수가 있다.
    • 이 예제는 과목의 점수를 출력을 하는 예제로 만들었기 때문에 출력을 피할 수는 없다. 하지만 Subject 객체에서 출력하는 방식으로 수정해, 클라이언트가 인수를 보내야 하는 부담을 줄였다.

😍 After

class Subject:
    grade = ""

    def __init__(self, name, score):
        self.name = name
        self.score = score
        self.setGradeByScore(score)

    def setGradeByScore(self, score):
        if score >= 81:
            self.grade = 'A'
        elif score >= 61:
            self.grade = 'B'
        elif score >= 41:
            self.grade = 'C'
        elif score>= 21:
            self.grade = 'D'
        else:
            self.grade = 'E'
    
    def printGrade(self):
        print(f"{self.name} Grade is {self.grade}")

subject = Subject("Math", 92)
subject.printGrade()

(Java 예시) 진리 2. 오류 코드보다 예외를 사용하라. (p.130)

무엇을 고쳤나요?

  • 오류 처리를 예외가 아닌 조건문으로 처리하고 있다.
    • 이 경우 새로운 문제가 생겼을 때, 조건문이 점점 증가하면서 가독성이 떨어진다.
  • getCoupon에서 null을 반환한다.
    • null을 반환하는 것은 NullPointerException을 발생시킬 확률이 높다.

😢 Before

public class Coupon{
    private String code;
    private int amount;
    
    public Coupon(String code, int amount){
        this.code = code;
        this.amount = amount;
    }

    void use(){
        // 쿠폰 사용하는 코드
    }
}

...

public static void main(String[] args) {
    useCoupon("C20220211")
}

public void useCoupon(String couponCode){
		Coupon coupon = getCoupon(couponCode);
    if(coupon != null){
        coupon.use();
    }else{
        log.error("존재하지 않는 쿠폰입니다.");
    }
}

어떻게 고쳤나요?

  • 오류 처리를 예외가 아닌 조건문으로 처리하고 있다.
    • useCoupon 에서 조건문이 아닌 발생한 예외를 통해 처리하도록 수정했다.
  • getCoupon에서 null을 반환한다.
    • Coupon 클래스에서 쿠폰 사용을 할 때 쿠폰 코드가 없다면, null을 반환하지 않고 예외를 발생하게 수정했다. 예외에 발생 여부에 따른 처리는 useCoupon 함수에서 진행한다.

😍 After

public class Coupon{
    private String code;
    private int amount;
    
    public Coupon(String code, int amount){
        this.code = code;
        this.amount = amount;
    }

    void use() throws NoSuchCouponException{
        if(String.isNullOrEmpty(this.code)){
            throw new NoSuchCouponException("존재하지 않는 쿠폰입니다.");
        }else{
             // 쿠폰 사용하는 코드
        }
    }
}

...

public static void main(String[] args) {
    useCoupon("C20220211")
}

public void useCoupon(String couponCode){
    try{
        Coupon coupon = getCoupon(couponCode);
        coupon.use();
    }catch(NoSuchCouponException e){
        e.getMessage();
        e.printStackTrace();
    }
}

(Java 예시) 진리 3. 클래스는 작아야 한다! (p.172)

무엇을 고쳤나요?

  • 단일 책임 원칙이 지켜지지 않고 있다.

    단일 책임 원칙(Single Responsibility Principle, SRP)이란 클래스나 모듈을 변경할 이유가 하나, 단 하나 뿐이어야 한다는 원칙이다.

    • Book 클래스에 책에 대한 정보 뿐만 아니라, 저자, 출판사에 대한 정보에 대한 책임까지 지고 있다. 즉, 저자의 메일 주소나 출판사의 주소가 바뀌는 경우에도 Book 클래스를 변경해야 한다.

😢 Before

public class Book{
    private String title;
    private String isbn;
    private int price;
    private int amount;
    private String authorName;
    private String authorMail;
    private String publisherName;
    private String publisherLocation;
    private String publisherMail;
    
    public Book(String title, String isbn, int price, int amount, String authorName, String authorMail, String publisherName, String publisherLocation, String publisherMail){
				this.title = title;
        this.isbn = isbn;
        this.price = price;
        this.amount = amount;
        this.authorName = authorName;
        this.authorMail = authorMail;
        this.publisherName = publisherName;
        this.publisherLocation = publisherLocation;
        this.publisherMail = publisherMail;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public String getAuthorName() {
        return authorName;
    }

    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }

    public String getAuthorMail() {
        return authorMail;
    }

    public void setAuthorMail(String authorMail) {
        this.authorMail = authorMail;
    }

    public String getPublisherName() {
        return publisherName;
    }

    public void setPublisherName(String publisherName) {
        this.publisherName = publisherName;
    }

    public String getPublisherLocation() {
        return publisherLocation;
    }

    public void setPublisherLocation(String publisherLocation) {
        this.publisherLocation = publisherLocation;
    }

    public String getPublisherMail() {
        return publisherMail;
    }

    public void setPublisherMail(String publisherMail) {
        this.publisherMail = publisherMail;
    }
}

어떻게 고쳤나요?

  • 단일 책임 원칙이 지켜지지 않고 있다.
    • 기존의 Book 클래스를 책임에 따라 Book, Author, Publisher 클래스로 나누었다.
    • 분할함으로써 기존의 큰 클래스 하나가 작은 여러개의 클래스로 분할되었다.

😍 After

public class Book{
    private String title;
    private String isbn;
    private int price;
    private int amount;
    
    public Book(String title, String isbn, int price, int amount){
        this.title = title;
        this.isbn = isbn;
        this.price = price;
        this.amount = amount;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }    
}

public class Author{
    private String authorName;
    private String authorMail;

    public Author(String authorName, String authorMail){
        this.authorName = authorName;
        this.authorMail = authorMail;
    }

    public String getAuthorName() {
        return authorName;
    }

    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }

    public String getAuthorMail() {
        return authorMail;
    }

    public void setAuthorMail(String authorMail) {
        this.authorMail = authorMail;
    }
}

public class Publisher{
    private String publisherName;
    private String publisherLocation;
    private String publisherMail;

    public Publisher(String publisherName, String publisherLocation, String publisherMail){
        this.publisherName = publisherName;
        this.publisherLocation = publisherLocation;
        this.publisherMail = publisherMail;
    }

    public String getPublisherName() {
        return publisherName;
    }

    public void setPublisherName(String publisherName) {
        this.publisherName = publisherName;
    }

    public String getPublisherLocation() {
        return publisherLocation;
    }

    public void setPublisherLocation(String publisherLocation) {
        this.publisherLocation = publisherLocation;
    }

    public String getPublisherMail() {
        return publisherMail;
    }

    public void setPublisherMail(String publisherMail) {
        this.publisherMail = publisherMail;
    }
}

소감 3줄 요약

  • (Python 예시) 진리 1. 함수는 한 가지를 해야 한다. (p.44)
  • (Java 예시) 진리 2. 오류 코드보다 예외를 사용하라. (p.130)
  • (Java 예시) 진리 3. 클래스는 작아야 한다! (p.172)
profile
make it mine, make it yours

0개의 댓글