+) 22. 07. 23. day37 🌕 에 추가 완료!
+) 22. 07. 22. 01:10 일단... 첫 pr 올림...^^ 내가 봐도 코드 더러움. 그래도 일단 기록한다...
Input Class
사용자에게 값을 입력 받는 클래스
public class Input {
private ArrayList<Integer> numbers = new ArrayList<>();
public ArrayList<Integer> input() {
clear();
System.out.println("\n" + "숫자 3개를 입력해 주세요. (예: 123)");
String[] number = inputData();
while (checkForDuplicates(number) == true || checkForLength(number) == true) {
System.out.println("\n" + "입력값은 중복이 없어야 하며 3자리여야 합니다. 재입력해 주세요.");
number = inputData();
}
for (int i = 0; i < 3; i++) {
numbers.add(Integer.parseInt(number[i]));
}
return numbers;
}
public void clear() {
numbers.clear();
}
public String[] inputData() {
return new Scanner(System.in).nextLine().split("");
}
private static boolean checkForLength(String[] nums) {
return nums.length > 3 || nums.length < 3;
}
private static boolean checkForDuplicates(String[] nums) {
Long count = Stream.of(nums).distinct().count();
return nums.length != count;
}
}
input()
입력 받은 문자열을 하나씩 분리해 배열 number에 넣는다.
값에 중복이 있는지, 3글자가 맞는지 검사한 후 이를 만족하지 못하면 재입력 받는다.
배열에 있는 값을 정수로 변환한 뒤 리스트에 넣고 반환한다.
clear()
리스트를 초기화한다.
inputData()
값을 입력 받고 한 글자씩 분리한다.
checkForLength(String[] nums)
문자열의 길이가 3인지 검사한다. 만약 3이 아닐 경우 true를 반환한다.
checkForDuplicates(String[] nums)
중복값이 있는지 검사한다. 만약 중복값이 있을 경우 true를 반환한다. (배열의 총 개수와 중복값을 걸러낸 개수 비교)
RandomNumber Class
랜덤한 정수를 생성하는 클래스
public class RandomNumber {
private static final Set<Integer> randomNumbersSet = new HashSet<>();
public ArrayList<Integer> createRandomNumber() {
while(randomNumbersSet.size() < 3) {
randomNumbersSet.add((int) (Math.random() * 9 + 1));
}
ArrayList<Integer> randomNumbers = new ArrayList<>(randomNumbersSet);
return randomNumbers;
}
}
Comparison Class
사용자가 입력한 값과 랜덤 생성한 값을 비교하는 클래스
public class Comparison {
int ball;
int strike;
public int compareNumber(ArrayList<Integer> input, ArrayList<Integer> randomNumber) {
ball = 0;
strike = 0;
for (int i = 0; i < 3; i++) {
if (input.contains(randomNumber.get(i))) {
ball++;
}
if (input.get(i).equals(randomNumber.get(i))) {
ball = 0;
strike++;
}
}
Output output = new Output();
output.output(strike, ball);
return strike;
}
}
Output Class
결과를 출력하는 클래스
public class Output {
public void output(int strike, int ball) {
if(strike == 3) {
System.out.println("BASEBALL WIN~!");
return;
}
System.out.println();
System.out.println(ball + "ball");
System.out.println(strike + "strike");
}
}
Main Class
실행하는 클래스
public class Main {
public static void main(String[] args) {
System.out.println("Play Baseball Game");
Input input = new Input();
RandomNumber randomNumber = new RandomNumber();
Comparison compareNumber = new Comparison();
while (compareNumber.compareNumber(input.input(), randomNumber.createRandomNumber()) != 3) {
}
}
}
결과는 잘 나오는데 while문이... 너무 더럽다.
main에 있는 텅 빈 while문이랑 input에 있는 유효성 검사;; 너무 보기 안 좋음.
그리고 Input 클래스에 뭐가 너무 많아... 원래 저렇게 많으면 안 되는데;; 어떻게 리팩토링 해야 할지 감이 안 잡힘. 총체적 난국이다.
+) 22. 07. 24. day37 🌕 에 추가 완료!
+) 22. 07. 24. 추가
스프링은 자바 언어 기반의 프레임워크이며, 객체 지향 언어가 가진 강력한 특징을 살려낸다. 즉, 스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크다.
의존성 주입(DI)과 제어 역전(IoC), 관점 지향 프로그래밍(AOP) 요소를 통해 느슨한 결합(Loose Coupling)을 달성할 수 있게 해준다. 이렇게 느슨한 결합으로 개발한 애플리케이션은 단위 테스트를 수행하기 용이하다는 장점이 있다.
의존성 주입(DI, Dependency Injection)
⬇️ DI를 사용하지 않은 코드의 경우
@RestController
public class NoDIController {
private MyService service = new MyServiceImpl();
@GetMapping("/hello")
public String getHello() {
return service.getHello();
}
}
Controller는 ‘MyService’ 객체에 의존하게 된다.
객체의 인스턴스를 얻게 되면 객체 간의 결합도가 올라가고, 이런 코드 작성은 단위 테스트를 위해 Mock 객체(가짜 객체)를 사용할 수 없게 된다.
⬇️ DI를 사용한 코드의 경우
@Service
public class MyServiceImpl implements MyService {
@Override
public String getHello() {
return "Hello";
}
}
@RestController
public class DIController {
MyService myService;
@Autowired
public DIController(MyService myService) {
this.myService = myService;
}
@GetMapping("/hello")
public String getHello() {
return myService.getHello();
}
}
@Service
, @Autowired
어노테이션을 통해 MyService의 인스턴스를 가진다.
위와 같이 코드를 작성하면 단위 테스트 상황에서 Service 객체를 Mock 객체로 대체하여 쉽게 테스트 할 수 있다.
관점 지향 프로그래밍(AOP, Aspect Oriented Programming)
스프링 프레임워크에서 제공하는 강력한 기능 중 하나이다.
AOP는 쉽게 말해 OOP(객체 지향 프로그래밍)를 보완하는 수단으로, 여러 곳에 쓰이는 공통 기능을 모듈화하여 필요한 곳에 연결함으로써 유지보수 또는 재사용에 용이하도록 하는 것을 의미한다.
AOP를 통해 기존 프로젝트에 로직 수정 없이 다양한 기능을 추가할 수 있으며, 이러한 개발 방식을 통해 결합도를 낮춘 개발이 가능해진다.
스프링이란 단어는 문맥에 따라 다르게 사용된다.
최근에는 스프링 부트를 통해 스프링 프레임워크의 기술들을 편리하게 사용할 수 있다.
스프링은 다양한 기능을 제공하고 있지만, 그 기능을 사용하기 위한 설정에 많은 시간이 걸린다. (예: Hibernate Datasource, Entity Manager 등)
그래서 스프링을 좀 더 빨리, 편하게 사용할 수 있도록 나온 것이 바로 스프링 부트이다.
스프링 부트는 스프링을 편리하게 사용할 수 있도록 지원하며, 최근에는 기본으로 사용한다.
스프링 부트가 제공하는 기능
스프링 부트는 자동 설정(Auto Configuration)을 이용한다.
스프링 부트 프로젝트의 의존성 관리
장점
참고 자료
함께 보면 좋은 자료
우아한Tech, “[10분 테코톡] 🦊닉의 Spring vs Spring Boot”, https://youtu.be/6h9qmKWK6Io
뉴렉처, “스프링 프레임워크 강의 1강 - Spring 소개와 학습 안내”, https://youtu.be/XtXHIDnzS9c
뉴렉처, “스프링 프레임워크 강의 2강 - 느슨한 결합력과 인터페이스”, https://youtu.be/KJ9Rus3QfUc