🔖 Mission5 : 더러운 코드를 깨끗한 코드로 리펙터링 해보세요!
본인이 잘 이해했는지 확인하는 가장 정확한 방법은 가르쳐 보는 것!
가장 잘하는 언어로(JS, Python 등) 더러운 코드를 깨끗한 코드로 리팩토링 해보세요. (클린코드 읽을 때 분명 참고하라고 적어준 예시인데 자바로 되어있어서 공감이 잘 안됐죠?)
클린코드 읽으며 뼈맞았던 내용 중 3가지 진리
를 고르고,
진리를 따르는 예시 총 3가지를 만들어보세요.
score
를 통해 grade
를 계산하는 작업subject
와 grade
를 출력하는 작업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)
score
로 grade
를 구하는 작업과, 이를 출력하는 작업을 별개의 함수로 분리했다.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()
getCoupon
에서 null을 반환한다.😢 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();
}
}
단일 책임 원칙(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;
}
}