Spring 1st Step

최보현·2022년 7월 6일
1

Spring

목록 보기
3/10
post-thumbnail

인프런 김영한 강사님의 스프링 핵심 원리 - 기본편 sec02
백문이 불열일타, 우선 따라해라

출처 : 스프링 핵심 원리 - 기본편

🌟윈도우 단축키(intelliJ)
생성자 자동 생성 -> alt + insert
변수 생성 -> ctrl + alt + v

🦾역할과 구현을 분리하자!

학교에서 배운 것들 중에 유일하게 이게 잘 써먹히는구나를 느낀 'UML'
계발에 들어가기 앞서서, 도메인을 설계함으로써 어떤 클래스와 인터페이스가 필요할지 정리를 할 수 있음!

🌟스프링에서는 특히 다형성이 가장 중요!

역할(인터페이스)를 정해놓고 구현(구현 클래스)을 세분화함으로써 변경이 편리!

예제만들기

회원 도메인 만들기

우선 member 패키지 생성!

Grade class 생성

public enum Grade {
    BASIC,
    VIP
}

Member class 생성

public class Member {
    private Long id;
    private String name;
    private Grade grade;

    public Member(Long id, String name, Grade grade) {
        this.id = id;
        this.name = name;
        this.grade = grade;
    }

    //getter와 setter 생성
}

MemberRepository interface 생성

public interface MemberRepository {
    void save(Member member);

    Member findById(Long memberId);
}

MemoryMemberRepository class 생성

import java.util.*;

public class MemoryMemberRepository implements MemberRepository{
    private static Map<Long, Member> store = new HashMap<>();
    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

MemberService interface 생성

public interface MemberService {
    void join(Member member);
    Member findMember(Long memberId);
}

MemberServiceImpl class 생성

public class MemberServiceImpl implements MemberService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

주문과 할인 도메인 만들기

order와 discount 패키지 생성!

order class 생성

public class Order {
    private Long memberId;
    private String itemName;
    private int itemPrice;
    private int discountPrice;

    public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
        this.memberId = memberId;
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.discountPrice = discountPrice;
    }

    public int calculatePrice() {
        return itemPrice - discountPrice;
    }

    //getter와 setter 생성

    @Override
    public String toString() {
        return "Order{" +
                "memberId=" + memberId +
                ", itemName='" + itemName + '\'' +
                ", itemPrice=" + itemPrice +
                ", discountPrice=" + discountPrice +
                '}';
    }
}

OrderService interface 생성

public interface OrderService {
    Order createOrder(Long memberId, String itemName, int itemPrice);

}

OrderServiceImpl class 생성

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;

public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

DiscountPolicy interface 생성

import hello.core.member.Member;

public interface DiscountPolicy {
    //return 할인 대상 금액
    int discount(Member member, int price);
}

FixDiscountPolicy class 생성

import hello.core.member.Grade;
import hello.core.member.Member;

public class FixDiscountPolicy implements DiscountPolicy{
    private int discountFixAmount = 1000;
    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP){
            return discountFixAmount;
        } else{
            return 0;
        }
    }
}

🌟개발에서 무엇보다 중요한 테스트!

테스트가 가장 헷갈렸던 것 같다...
main method를 만들어서 하기에는 시간이 너무 오래 걸리니깐 test를 활용하는데 손에 붙으면 main method보다 빨라질거라 믿는다,,,
+given, when, then도 내가 구분하는 날이 오기를,,,
Assertion을 사용할 때 core.api껄로 사용한다.

OrderServiceTest class

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class OrderServiceTest {
    MemberService memberService = new MemberServiceImpl();
    OrderService orderService = new OrderServiceImpl();

    @Test
    void createOrder(){
        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "itemA", 10000);
        Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
    }
}

MemberServiceTest class

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class MemberServiceTest {
    MemberService memberService = new MemberServiceImpl();
    @Test
    void join(){
        //given
        Member member = new Member(1L, "memberA", Grade.VIP);
        //when
        memberService.join(member);
        Member findMember = memberService.findMember(1L);
        //then
        Assertions.assertThat(member).isEqualTo(findMember);
    }
}
하찮은 나의 느낀 점

annotation의 활용이 진짜 많아진 느낌 그리고 다형성의 개념을 다시 한 번 잡아두는 게 좋을 것 같음!
즉, 이것이 자바다 다시 한 번 봐야할 듯🤣

profile
Novice Developer's Blog

0개의 댓글