반응형

우아하게 예외 처리하기

 

목차

1. 예외 처리 방식

2. Unchecked Exception을 사용하라

3. Exception 잘 쓰기

4. 실무 예외 처리 패턴

5. 오픈소스 속 Exception 살펴보기


1. 예외 처리 방식

오류 코드를 리턴하지 말고, 예외를 던져라

 

2. Unchecked Exception을 사용하라

Exception을 상속하면 Checked Exception 명시적인 예외처리가 필요하다.

  - ex) IOException, SQLException

 

RuntimeException을 상속하면 Unchecked Exception 명시적인 예외처리가 필요하지 않다.

  - ex) NullPointerException, IllegalArgumentException 

 

<Effective Java> Exception에 관한 규약

  자바 언어 명세가 요구하는 것은 아니지만, 업계에 널리 퍼진 규약으로 Error 클래스를 상속해 하위 클래스를 만드는 일을 자제하자.

 

즉, 사용자가 직접 구현하는 unchecked throwable은 모두 RuntimeException의 하위 클래스여야 한다.

 

Exception, RuntimeException, Error를 상속하지 않는 throwable을 만들 수도 있지만, 이러한 throwable은 정상적인 사항보다 나을 게 하나도 없으면서 API 사용자를 헷갈리게 할 뿐이므로 절대로 사용하지 말자

 

c#, c++, python, 루비는 확인된 예외(Checked Exception)가 없음에도 불구하고 안정적인 소프트웨어를 구현하기에 무리가 없다.

 

3. Exception 잘 쓰기

  - 예외에 메시지 담자 :

        오류가 발생한 원인과 위치를 찾기 쉽도록, 예외를 던질 때는 전후 상황을 충분히 덧붙인다.

        실패한 연산 이름과 유형 등 정보를 담아 예외를 던진다.

  - exception wrapper

 

4. 실무 예외 처리 패턴

  - getOrElse :

      * 예외 대신 기본 값을 리턴한다.

         1. null이 아닌 기본 값 :

             복수형의 데이터를 가져올 때는 데이터의 없을 의미하는 컬랙션을 리턴하면 된다. null보다 size가 0인 컬렉션이 훨씬 안전한다.

         2. 도메인에 맞는 기본 값 :

             예외 처리를 데이터를 제공하는 쪽에서 처리해 호출부 코드가 심플해진다.

             코드를 읽어가며 논리적인 흐름이 끊기지 않는다.

             도메인에 맞는 기본값을 도메인 서비스에서 관리한다.

         3. 도메인에 맞는 기본값이 없다면? getOrElseThrow 이용

 

  - getOrElseThrow :

        * null 대신 예외를 던진다.(기본 값이 없다면)

           1. 데이터를 제공하는 쪽에서 null 체크를 하여, 데이터가 없는 경우엔 예외를 던진다.

           2. 호출부에서 매번 null 체크를 할 필요 없이 안전하게 데이터를 사용할 수 있다. 

           3. 호출부의 가독성이 올라간다.

 

   - 파라미터의 null을 점검하라 :

        1. null을 리턴하는 것도 나쁘지만 null을 메서드로 넘기는 것은 더 나쁘다.

        2. 메서드에서 null을 파라미터로 받지 못하게 한다.

 

   - 실무에서는 보통 자신의 예외를 정의한다 :

        1. 에러 로그에서 stacktrace 해봤을 때 우리가 발생시킨 예외라는 것을 바로 인지할 수 있다.

        2. 다른 라이브러리에서 발생한 에러와 섞이지 않는다. 기본 IllegalArgumentException을 던지는 것보다 우리 예외로 던지는게 어              느 부분에서 에러가 났는 지 파악하기 용이하다.

       3. 우리 시스템에서 발생한 에러의 종류를 나열할 수 있다.

   

5. 오픈소스 속 Exception 살펴보기

 apps-android-commons

 

public boolean findBookmark(Bookmark bookmark) {
        if (bookmark == null) {//Avoiding NPE's
            return false;
        } // null이면 예외를 던지지않고 false를 리턴한다.
          // Bookmark 존재여부에 대한 메서드의 목적에 부합하다.

        Cursor cursor = null;
        ContentProviderClient db = clientProvider.get();
        try {
            cursor = db.query(
                    BookmarkPicturesContentProvider.BASE_URI,
                    Table.ALL_FIELDS,
                    Table.COLUMN_MEDIA_NAME + "=?",
                    new String[]{bookmark.getMediaName()},
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                return true;
            }
        } catch (RemoteException e) {
            // This feels lazy, but to hell with checked exceptions. :)
            // ReomoteException을 RuntimeException으로 바꿔서 던졌다.
            throw new RuntimeException(e); 
        } finally {
            // finally 블록에서 리소스를 close 처리한다.
            // 리소스를 사용했다면 반드시 finally 블록에서 닫아줘야 한다.
            if (cursor != null) {
                cursor.close();
            }
            db.release();
        }
        return false;
    }

Code - https://github.com/commons-app/apps-android-commons/blob/f8a8f9207028a6fb5a35483c040821f22daf755e/app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesDao.java

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 09  (0) 2022.03.21
[Clean Code] Chapter 08  (0) 2022.03.20
[Clean Code] Chapter 06  (0) 2022.03.13
[Clean Code] Chapter 05  (0) 2022.03.12
[Clean Code] Chapter 04  (0) 2022.03.12
반응형

어댑터 패턴(Adapter Pattern)

  - 어댑터 패턴은 구조패턴(Structural Pattern) 중 하나이다.
  - 구조 패턴은 클래스를 상속과 합성을 이용해서 더 큰 클래스를 생성하는 방법을 제공하는 패턴이다.

  - 구조 패턴을 사용하면 서로 독립적으로 개발한 클래스를 하나인 양 사용할 수 있다.

  - 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴

 

장점

  - 어댑터 패턴은 연결할 수 없는 두 개의 호환되지 않는 인터페이스 사이의 커넥터 역할을 수행한다.

  - 클래스의 인터페이스를 사용자가 기대하는 인터페이스 형태로 변환시킨다.

  - 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 재사용할 수 있다.

  - 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다.

단점

  - 새 클래스가 생겨 복잡도가 증가할 수 있다. 경우에 따라서는 기존 코드가 해당 인터페이스를 구현하도록 수정하는 것이 좋은 선택이 될 수도 있다.

 

코드

  • 최종 변경해 줘야 하는 객체 타켓 (Target)
  • 변환의 대상이 되는 객체 어댑티 (Adaptee)
  • 변경을 도와주는 객체 어댑터 (Adapter)

 * 예시) BugattiVeyron의 속도를 시속 마일(MPH) 단위에서 킬로미터(km/h) 단위로 반환해야 하는 예제

 

BugattiVeyron.java

 

public class BugattiVeyron implements Movable{

    @Override
    public double getSpeed() {
        return 268;
    }
}

 

Movable.java

 

public interface Movable {

    double getSpeed();
}

 

MovableAdapter.java

  - Adapter interface

 

public interface MovableAdapter {

    double getSpeed();
}

 

MovableAdapterImpl.java

  - Adapter 실제 구현체 convertMPHtoKMPH 마일단위를 킬로미터로 변환한다.

 

public class MovableAdapterImpl implements MovableAdapter{

    private Movable luxuryCars;

    // standard constructors
    MovableAdapterImpl(Movable luxuryCars) {
        this.luxuryCars = luxuryCars;
    }

    @Override
    public double getSpeed() {
        return convertMPHtoKMPH(luxuryCars.getSpeed());
    }

    private double convertMPHtoKMPH(double mph) {
        return mph * 1.60934;
    }
}

 

AdapterPatternTest.java

 

@SpringBootTest
class AdapterPatternTest {

    @Test
    void 어댑터_테스트() {
        Movable bugattiVeyron = new BugattiVeyron();
        MovableAdapter bugattiVeyronAdapter = new MovableAdapterImpl(bugattiVeyron);

        assertEquals(bugattiVeyronAdapter.getSpeed(), 431.30312, 0.00001);

    }


}

 

정리

 - 어댑터 패턴은 호환되지 않는 두 개의 객체를 호환되게 하기 위해서 하나의 Adapter라는 인터페이스를 추가해서 변환하는 로직을 추가한다.

기존 클래스의 소스코드를 수정해서 인터페이스에 맞추는 작업보다 기존 클래스의 소스코드의 수정을 하지 않고 타겟 인터페이스에 맞춰서 동작을 가능하게 한다.

 

실무 사용 사례

- java에서 collections(Arrays.asList, Collections.enumeration(), Collections.list())

- java에서 IO code

- Spring에서 Spring Security에 UserDetails

- Spring에 HandlerAdapter

728x90
반응형
반응형

싱글톤 패턴(Singleton Pattern)

  - 싱글톤 패턴은 생성패턴(Creational Pattern) 중 하나이다.
  - 싱글톤 패턴은 인스턴스를 만드는 절차를 추상화하는 패턴이다.
  - 싱글톤 패턴에 속하는 패턴들은 객체를 생성, 합성하는 방법이나 객체의 표현방법을 시스템과 분리해준다.

  - 하나의 객체만을 생성해 이후에 호출된 곳에서는 생성된 객체를 반환하여 프로그램 전반에서 하나의 인스턴스만을 사용하게 하는 패턴이다.

 

장점

  - 한번의 객체 생성으로 재사용이 가능하여 메모리 낭비를 방지한다.

  - 시스템 런타임, 환경 세팅에 대한 정보 등, 인스턴스가 여러개 일 때 생기는 문제를 미연에 방지할 수 있다.

 

문제점

  - 멀티 스레드 환경에서 안전하지 않다. (대처가 가능하다.)

  - 객체간의 결함도가 높아지고 변경에 유연하게 대처할 수 없다. 싱글톤 객체가 변경되면 이를 참조하고 있는 모든 값들이 변경되어야 한다.

  - 객체 상태를 유지하면 큰 문제가 발생한다.(stateful)

코드

  * 여러가지 싱글턴 구현 방법이있다.

  1. 기본 Singleton
  2. 이른 초기화(Eager Initialization)
  3. synchronized 사용
  4. static inner SIngleton(권장하는 방법)
  5. enum SIngleton(권장하는 방법)

 

1. 기본 Singleton

 - 단점이 Thread Safe 하지 못하다.

 

public class SingletonStatic {

    private static SingletonStatic instance;

    private SingletonStatic() {}

    public static SingletonStatic getInstance() {
        if(instance == null) {
            instance = new SingletonStatic();
        }
        
        return instance;
    }

}

 

 

2. Eager Initialization

 - Thread Safe

 - 단점이 인스턴스를 미리 만들어 놓는다는 단점이 있다.

 

public class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }

}

 

3. Thread Safe Singleton(synchronized 사용)

  - synchronized를 통해서 여러 쓰레드에서 동시에 접근하는 것을 막을 수 있다.(Thread Safe)

  - 동기화 처리하는 작업 때문에 성능에 불이익이 생길 수 있다.

 

public class ThreadSafeSingleton {

    private static ThreadSafeSingleton instance;
    
    private ThreadSafeSingleton() {}

    public static synchronized ThreadSafeSingleton getInstance() {
        if (instance == null) { instance = new ThreadSafeSingleton();}
        return instance;
    }
    
}

 

4. static inner SIngleton(권장하는 방법)

  - SingletonHelper 클래스는 SIngleton 클래스가 Load 될 때에도 Load 되지 않다가 getInstance()를 호출할 때 jvm 메모리에 로드되어 인스턴스를 생성한다. synchronized를 사용하지 않기 때문에 synchronized 키워드 자체에 대한 성능 저하 문제를 해결할 수 있다.

  - 단점으로 자바 리플렉션을 이용하면 싱글톤 패턴이 깨진다.

 

public class BillPughSIngleton {

    private BillPughSIngleton(){}

    private static class SingletonHelper{
        private static final BillPughSIngleton INSTANCE = new BillPughSIngleton();
    }

    public static BillPughSIngleton getInstance(){
        return SingletonHelper.INSTANCE;
    }
    
}

 

객체 상태를 유지했을 경우 주의 (stateful)

BillPughSIngleton.java

 

public class BillPughSIngleton {

    private String apartment;

    private BillPughSIngleton(){}

    private static class SingletonHelper{
        private static final BillPughSIngleton INSTANCE = new BillPughSIngleton();
    }

    public static BillPughSIngleton getInstance(){
        return SingletonHelper.INSTANCE;
    }

    public String getApartment() {
        return apartment;
    }

    public void setApartment(String apartment) {
        this.apartment = apartment;
    }

}

 

SIngletonTest.java

 

    @Test
    void singleTonStatefulTest() {

        BillPughSIngleton instance1 = BillPughSIngleton.getInstance();
        BillPughSIngleton instance2 = BillPughSIngleton.getInstance();

        instance1.setApartment("아크로빌 아파트");
        instance2.setApartment("한남더힐 아파트");

        System.out.println(instance1.getApartment());
        System.out.println(instance2.getApartment());


    }

  - stateful하게 코드를 작성하게 되면 위와 같이 객체의 상태가 바뀌는 문제가 발생하게 된다.

무결성하게(stateless) 코드를 작성하여야 한다.

 

BillPughSIngleton.java

  - setApartment 값을 바로 return 한다.

 

public class BillPughSIngleton {

    private String apartment;

    private BillPughSIngleton(){}

    private static class SingletonHelper{
        private static final BillPughSIngleton INSTANCE = new BillPughSIngleton();
    }

    public static BillPughSIngleton getInstance(){
        return SingletonHelper.INSTANCE;
    }

    public String getApartment() {
        return apartment;
    }

    public String setApartment(String apartment) {
        this.apartment = apartment;
        return apartment;
    }

}

 

SIngletonTest.java

 

   @Test
    void singleTonStatefulTest() {

        BillPughSIngleton instance1 = BillPughSIngleton.getInstance();
        BillPughSIngleton instance2 = BillPughSIngleton.getInstance();

        String apartment1 = instance1.setApartment("아크로빌 아파트");
        String apartment2 = instance2.setApartment("한남더힐 아파트");

        System.out.println(apartment1);
        System.out.println(apartment2);
        
    }

 

5. enum Singleton(권장하는 방법)

 - 4번(static inner Singleton)과 같이 권장하는 방법으로 enum 클래스로 사용하는 방법이다.

 - 자바 리플랙션을 이용해도 enum 클래스는 newInstance를 이용해서 새로운 인스턴스를 생성할 수 없어서 더 안전하다.

 - 단점으로는 상속을 사용하지 못하고, 사용하지 않아도 미리 만들어 놓는다는 단점이 있다.  

 

public enum ThreadSafeV5 {

    INSTANCE;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

실무 사용 사례

1. 자바 java.lang.Runtime 클래스가 싱글톤 패턴으로 구현되어 있다.

2. java Application 개발에서 많이 사용되는 스프링 프레임워크는 스프링 빈 컨테이너의 도움을 받아 싱글톤 스코프로 관리된다.

스프링 프레임워크를 사용하면 싱글톤 패턴의 문제점들을 보완하면서 장점을 누릴수 있다.  

3. 다른 디자인 패턴(빌더, 퍼사드, 추상 팩토리 등) 구현체의 일부로 쓰이기도 한다.

 

728x90
반응형
반응형

빌더패턴(Builder Pattern)

  - 빌더 패턴은 생성패턴(Creational Pattern) 중 하나이다.
  - 생성 패턴은 인스턴스를 만드는 절차를 추상화하는 패턴이다.
  - 생성 패턴에 속하는 패턴들은 객체를 생성, 합성하는 방법이나 객체의 표현방법을 시스템과 분리해준다.

  - 별도의 Builder 클래스를 생성해서 필수 값에 대해서는 생성자를 통해, 선택적인 값들에 대해서는 메소드를 통해 값을 입력받은 후에 build() 메서드를 통해 최종적으로 하나의 인스턴스를 리턴하는 방식이다.

 

장점

  - 필요한 데이터만 설정할 수 있다.

  - 유연성을 확보할 수 있다.

  - 가독성을 높일 수 있다.

  - 변경 가능성을 최소화할 수 있다.

 

코드

House.java

 

public class House {

    private Long houseId;
    private String address;
    private String type;
    private Long price;
    private String phone;

    public Long getHouseId() {
        return houseId;
    }
    public String getAddress() {
        return address;
    }
    public String getType() {
        return type;
    }
    public Long getPrice() {
        return price;
    }
    public String getPhone() {
        return phone;
    }

    private House(HouseBuilder builder) {
        this.houseId = builder.houseId;
        this.address = builder.address;
        this.type = builder.type;
        this.price = builder.price;
        this.phone = builder.phone;
    }

    public static class HouseBuilder{

        private Long houseId;
        private String address;
        private String type;
        private Long price;
        private String phone;

	// 필수값 생성자
        public HouseBuilder(Long houseId, String address, String type) {
            this.houseId = houseId;
            this.address = address;
            this.type = type;
        }

        public HouseBuilder price(Long price) {
            this.price = price;
            return this;
        }

        public HouseBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public House build() {
            return new House(this);
        }

    }


}

HouseTest.java

@SpringBootTest
class HouseTest {

    @Test
    void HouseBuilderTest() {

        String houseAddress = "서울특별시 관악구";
        String houseType = "매매";
        Long housePrice = 10000000L;

        House house =  new House.HouseBuilder(1L, houseAddress, houseType)
                                .price(housePrice)
                                .build();

        assertThat(house.getAddress(), is(houseAddress));
        assertThat(house.getType(), is(houseType));
        assertThat(house.getPrice(), is(housePrice));

    }


}

 

실무 사용 사례

- java에 StringBuilder

- java에 Stream API

- Spring Lombok

- Spring UriComponents

 

정리

 - 인스턴스를 생성할 때 생성자만을 통해서 생성하면 칼럼이 변경될 때마다 많은 소스코드에 영향이 가는 고통스러운 상황이 발생할 것이다. 빌더 패턴을 이용해서 유연성을 확보할 수 있다.

 

참조

 - https://readystory.tistory.com/121

 

 

728x90
반응형
반응형

객체와 자료구조로 데이터 표현하기

 

목차

1. 자료구조 vs 객체

2. 객체 - 디미터 법칙

3. DTO

4. Active Record


1.  자료구조 vs 객체

자료구조(Data Structure) 객체(Object)
데이터 그 자체 비즈니스 로직과 관련
자료를 공개한다. 자료를 숨기고, 추상화한다.
자료를 다루는 함수만 공개한다.
변수 사이에 조회 함수와 설정 함수로 변수를 다룬다고 객체가 되지 않는다.(getter, setter) 추상 인터페이스를 제공해 사용자가 구현을 모른 채 자료의 핵심을 조잘할 수 있다.

절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 함수를 고쳐야 한다.

 

객체지향 코드는 새로운 클래스를 추가하기 쉽다. 하지만 함수를 추가해야 한다.

 

상황에 맞는 선택을 한다.

  - 자료구조를 사용하는 절차적인 코드는 기본 자료 구조를 변경하지 않으면서 새 함수를 추가하기 쉽다.

  - 절차적인 코드는 새로운 자료 구조를 추가하기 어렵다. 그러려면 모든 함수를 고쳐야 한다.

 

  - 객체지향 코드는 기존 함수를 변경하지 않으면서 새 클래스를 추가하기 쉽다.

  - 객체지향 코드는 새로운 함수를 추가하기 어렵다. 그러려면 모든 클래스를 고쳐야 한다.  

 

2.  객체 - 디미터 법칙

내 친구만 호출하지 내 친구의 친구까지 호출하면 안된다. 연쇄작용이 이어지기 때문에

휴리스틱 : 경험에 기반하여 문제를 해결하기 위해 발견한 방법 의사결정을 단순화하기 위한 법칙들

    - 경험적으로 만들어낸 법칙 ex) Clean Code

기차 충돌 : 디미터의 법칙에 어긋나는 상황

 

3.  DTO(Data Transfer Object) 

 * 자료구조

다른 계층 간 데이터를 교환할 때 사용

 

4. Active Record

 * 자료구조

Database row를 객체에 맵핑하는 패턴

  - 비즈니스 로직 메서드를 추가해 객체로 취급하는 건 바람직하지않다.

  - 비즈니스 로직을 담으면서 내부 자료를 숨기는 객체는 따로 생성한다.

  - 객체가 많아지면 복잡하고, 가까운 곳에 관련 로직이 있는 것이 좋으므로 현업에서는 Entity에 간단한 메서드를 추가해서 사용한다.

 

 

 

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 08  (0) 2022.03.20
[Clean Code] Chapter 07  (0) 2022.03.17
[Clean Code] Chapter 05  (0) 2022.03.12
[Clean Code] Chapter 04  (0) 2022.03.12
[Clean Code] Chapter 03  (0) 2022.03.09
반응형

팩토리 메소드 패턴(Factory Method Pattern)

  - 팩토리 메소드 패턴은 생성패턴(Creational Pattern) 중 하나이다.
  - 생성 패턴은 인스턴스를 만드는 절차를 추상화하는 패턴이다.
  - 생성 패턴에 속하는 패턴들은 객체를 생성, 합성하는 방법이나 객체의 표현방법을 시스템과 분리해준다.

 

장점

  - 확장에 열려있고 변경에 닫혀있는 객체 지향 원칙을 적용해서 기존에 인스턴스를 만드는 과정의 로직을 건드리지 않고, 새로운 인스턴스를 다은 방법으로 확장이 가능하다.

  - 팩토리 메소드 패턴은 클라이언트 코드로부터 서브 클래스의 인스턴스화를 제거하여 서로 간의 종속성을 낮추고, 결합도를 느슨하게 하며(Loosely Coupled), 확장을 쉽게 한다.

  - 팩토리 메소드 패턴은 클라이언트와 구현 객체들 사이에 추상화를 제공한다.

 

단점

  - 각자의 역할을 나누어서 생성하다 보니 클래스 개수가 늘어난다.

코드

  * 부동산 중개 수수료 계산 프로그램 가정(매매/임대차)

 

  - 중개 정책 interface 생성 :

     interface를 구현하는 하위 클래스에서 수수료 계산 로직을 구현한다.

     java8 이후로 default 메소드를 사용하면 interface 내부에서 로직 작성이 가능하다. (default 명시)

     java9 이후로는 interface에 priave 메소드도 사용이 가능하다.

public interface BrokeragePolicy {

    BrokerageRule createBrokerageRule(Long price);

     default Long calculate(Long price) {
        BrokerageRule rule = createBrokerageRule(price);
        return rule.calcMaxBrokerage(price);
    }
}

 

  - 매매 중개 수수료 class :

    java7 이후부터 _는 숫자 리너털 어디에도 사용할 수 있다. 가독성 향상

 

public class PurchaseBrokeragePolicy implements BrokeragePolicy{

    public BrokerageRule createBrokerageRule(Long price) {
        BrokerageRule rule;
        if(price < 50_000_000) {
            rule = new BrokerageRule(0.6, 250_000L);
        } else if(price < 200_000_000) {
            rule = new BrokerageRule(0.5, 800_000L);
        }else if(price < 600_000_000) {
            rule = new BrokerageRule(0.4, null);
        }else if(price < 900_000_000) {
            rule = new BrokerageRule(0.5, null);
        }else{
            rule = new BrokerageRule(0.9, null);
        }
        return rule;
    }


}

 

  - 임대차 중개 수수료 class

 

public class RentBrokeragePolicy implements BrokeragePolicy{

    public BrokerageRule createBrokerageRule(Long price) {
        BrokerageRule rule;
        if(price < 50_000_000) {
            rule = new BrokerageRule(0.5, 200_000L);
        } else if(price < 100_000_000) {
            rule = new BrokerageRule(0.4, 300_000L);
        }else if(price < 300_000_000) {
            rule = new BrokerageRule(0.3, null);
        }else if(price < 600_000_000) {
            rule = new BrokerageRule(0.4, null);
        }else{
            rule = new BrokerageRule(0.8, null);
        }
        return rule;
    }


}

 

  - Factory Class (핵심 클래스)

 

public class BrokeragePolicyFactory {

    public static BrokeragePolicy of(ActionType actionType) {
        switch (actionType) {
            case RENT:
                return new RentBrokeragePolicy();
            case PURCHASE:
                return new PurchaseBrokeragePolicy();
            default:
                throw new IllegalArgumentException("해당 actionType에 대한 정책이 존재하지 않습니다.");
        }
    }

}

 

- 중개 수수료 계산 api

 

public Long calcBrokerage(@RequestParam ActionType actionType,
                          @RequestParam Long price) {
        // 타입 정의 - 매매 / 임대차
        BrokeragePolicy policy = BrokeragePolicyFactory.of(actionType);
        return policy.calculate(price);
}

 

실무 사용 사례

- Spring에서 BeanFactory

- Java Calendar 

728x90
반응형

'JAVA > Design Pettern' 카테고리의 다른 글

[Design Pattern] 프록시 패턴  (0) 2022.03.22
[Design Pattern] 추상 팩토리 패턴  (0) 2022.03.19
[Design Pattern] 어댑터 패턴  (0) 2022.03.16
[Design Pattern] 싱글톤 패턴  (0) 2022.03.15
[Design Pattern] 빌더 패턴  (0) 2022.03.14
반응형

코드의 가독성에 필수적은 포맷팅

 

목차

1. 포맷팅이 중요한 이유

2. 크린코드 포맷팅

3. Java Class Declarations

4. Team Coding Covention


1. 포맷팅이 중요한 이유

  * 가독성이 필수적이다.

  - 코드를 수월하게 읽어나갈 수 있다.

  - 아마추어처럼 보이지 않는다.

  - 코드를 잘못 해석해서 버그를 발생하는 위험을 줄일 수 있다.

 

 

2. 클린코드 포맷팅

  - 적절한 길이 유지 :

        200라인 정도, 200라인 넘어간다면 클래스가 여러개의 일을 하고 있을 가능성이 높다.

  - 밀접한 개념은 서로 가까이에 둔다 :

        행 묶음은 완결된 생각 하나를 표현하기 때문에 개념은 빈 행으로 분리한다.

        변수는 사용되는 위치에서 최대한 가까이 선언한다.

 

 

3. Java Class Declarations

  Class 내부 코드 순서

   1. static 변수 :

       public -> protected -> package -> private 순서

   2. instance 변수 :

       public -> protected -> package -> private 순서

   3. 생성자

   4. 메서드 :

       public 메서드에서 호출되는 private 메서드는 그 아래에 둔다. 가독성 위주로 그룹핑

 

 

4. Team Coding Convention

  개발 언어의 컨벤션이 우선이지만, 애매한 부분은 팀 컨벤션을 따른다. 없다면 같이 만들어가자!

 

참고 컨벤션

  - https://naver.github.io/hackday-conventions-java/ 

 

캠퍼스 핵데이 Java 코딩 컨벤션

중괄호({,}) 는 클래스, 메서드, 제어문의 블럭을 구분한다. 5.1. K&R 스타일로 중괄호 선언 클래스 선언, 메서드 선언, 조건/반복문 등의 코드 블럭을 감싸는 중괄호에 적용되는 규칙이다. 중괄호

naver.github.io

  - https://google.github.io/styleguide/javaguide.html 

 

Google Java Style Guide

1 Introduction This document serves as the complete definition of Google's coding standards for source code in the Java™ Programming Language. A Java source file is described as being in Google Style if and only if it adheres to the rules herein. Like ot

google.github.io

 

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 07  (0) 2022.03.17
[Clean Code] Chapter 06  (0) 2022.03.13
[Clean Code] Chapter 04  (0) 2022.03.12
[Clean Code] Chapter 03  (0) 2022.03.09
[Clean Code] Chapter 01 ~ 02  (0) 2022.03.06
반응형

목차

1. 주석을 최대한 쓰지 말자

2. 좋은 주석

3. 주석보다 annotation

4. JavaDoc


1.  주석을 최대한 쓰지 말자

 * 주석은 나쁜 코드를 보완하지 못한다.

  - 코드에 주석을 추가하는 일반적인 이유는 코드 품질이 나쁘기 때문이다. 자신이 저지른 난장판을 주석으로 설명하지 말고 개선하는데 시간을 보내야 한다.

  - 코드로도 의도를 표현할 수 있다.

  - 주석은 방치되는 경우가 많다.(코드는 컴파일 되기때문에 계속적으로 관리되지만 주석은 텍스트 그자체이기 때문에 방치될 수 있다.)\

 

2.  좋은 주석

 - 구현에 대한 정보를 제공한다.

 - 의도와 중요성을 설명한다.

 - TODO : 앞으로 할 일, 지금은 해결하지 않지만 나중에 해야할 일을 미리 적어둘 때

 - FIXME : 문제가 있지만, 당장 수정할 필요는 없을 때, 가능하면 빨리 수정하는게 좋다

 

3.  주석보다 annotation

 - 코드에 대한 메타 데이터

 - @Deprecated : 컴파일러가 warning을 발생시킴, IDE에서 사용시 표시됨

 - @NotThreadSafe : Thread Safe하지 않음을 나타냄

 

4. JavaDoc

   /**

     *

     */    <- 이런식으로 사용

 - JavaDoc build 명령어로 JavaDoc이 만들어진다. 문서화된 내용을 따로 볼수가 있다.

728x90
반응형

'Book > Clean Code' 카테고리의 다른 글

[Clean Code] Chapter 07  (0) 2022.03.17
[Clean Code] Chapter 06  (0) 2022.03.13
[Clean Code] Chapter 05  (0) 2022.03.12
[Clean Code] Chapter 03  (0) 2022.03.09
[Clean Code] Chapter 01 ~ 02  (0) 2022.03.06

+ Recent posts