Today I Learned

2024 스파르타 내일배움캠프 Sping 트랙 참여 // day17

shinelee26 2024. 10. 24. 22:25

오늘 진행한 학습 요약

1. Java 코드 컨벤션 특강

  • 컨벤션을 지켜야 하는 이유
  • Coding Convention
  • Clean Code
  • 코드 컨벤션 방법

2. 새싹반 4회차 (예외처리와 제네릭)

  • 예외와 오류
  • 예외처리
  • 제네릭

3. CH 2 숫자 야구 게임 과제

  • 숫자 야구 게임 검토
JAVA 숫자야구게임 Git-hub 링크 :https://github.com/chews26/WordleGame/tree/main

 

4. 객체지향, 생성자, 제너릭 개념 공부

  • 객체지향 언어 복습
  • 생성자 개념 및 활용
  • 제너릭 개념 및 활용
자바의 정석 - 객체지향 언어 : https://youtu.be/CXuA31XcBZ0?si=l5_R3RWlxog8n5Fz
노마드 코더 - 객체지향 프로그래밍? 문과도 이해쌉가능. 10분컷. : https://youtu.be/cg1xvFy1JQQ?si=ejL-roZFYzKialUK
자바의 정석 - 기초편 생성자, 기본생성자 : https://youtu.be/Pgutf0G3nE4?si=W0txOkSHpJLCgy6d

생활코딩 - 제너릭(1/5) : 제너릭의 사용 : https://youtu.be/YUinFIexEQ4?si=FoG4EwHW3c4IpTal

 

5. 알고리즘 코드카다  Day9 (작성 생략)

CodingTest Git-hub 링크 : https://github.com/chews26/CodingTest

학습 정리

1. Java 코드 컨벤션 특강

  • 컨벤션을 지켜야 하는 이유
    • 가독성 향상
    • 유지보수성 증가
    • 협업 효율성 향상
    • 일관된 코드 스타일
    • 버그 발생 가능성 감소
    • 코드 리뷰와 자동화 도구와의 연계
  • Coding Convention
    • 개발자가 따라야 할 일련의 규칙과 스타일 가이드
    • 주로 코드의 형식과구조를 표준화
    • 코드의 가독성과 유지보수성을 높임
  • Clean Code
    • 코딩컨벤션의 일부분을 포함하지만 그보다 더 넓은개념
    • 코드의 품질과 설계 철학에 관한 것 
    • 가독성, 유지보수성, 효율성, 명료성을 모두 고려한 좋은 코드
    • 코드 자체가 직관적이고 명확하게 작성되도록 하는 것이 목표
항목 Coding Convention Clean Code
초점 코드의 형식과 구조 (스타일, 명명 규칙) 코드의 품질과 설계 (가독성, 효율성)
목적 일관된 코딩 스타일을 유지 코드의 직관성, 유지보수성, 재사용성 향상
주로 다루는 부분 들여쓰기, 공백, 변수/함수 이름, 주석 등 함수 설계, 명확한 이름, 단순한 구조
검사 방법 Linter, 포매터 같은 자동화 도구 코드 리뷰, 소프트웨어 설계 원칙
팀 협업 코드 스타일을 통일하여 협업 효율성 향상 협업 시 코드를 쉽게 이해하고 유지보수 가능

 

  • 코드 컨벤션 방법
표기법 형식 예시
Camel Case 첫 단어는 소문자, 이후 단어는 대문자 myVariableName
Pascal Case 모든 단어의 첫 글자 대문자 MyClassName
Snake Case 단어 사이에 _, 소문자 my_variable_name
Upper Snake Case 단어 사이에 _, 대문자 MAX_VALUE
Kebab Case 단어 사이에 -, 소문자 my-variable-name
  • 네이밍
    • Full- Text 작성 지향
      • 패키지
        • 패키지 이름은 소문자를 사용
        • 언더스코어(_)나 대문자를 포함하지 않음
      • 클래스
        • PascalCase를 사용.
        • 명사로 표현
      • 변수 & 메소드
        • camelCase 형식을 사용
        • 소문자로 시작하고 명확하고 구체적인 이름을 사용
      • 상수
        • 상수는 대문자와 언더바를 사용해 작성
        • 모든 단어는 명확하게 분리
  • 선언
    • 전처리
      • import는 와일드카드(*) 없이 사용하는 클래스 단위까지 작성
    • 제한자 우선순위
      • 1 2 3 4 5
        public/protected/private abstract static final synchronized
    • Annotation 선언
      • 클래스, 인터페이스, 메서드, 생성자에 붙는 애너테이션은 선언 후 새줄을 사용
    • 라인당 선언 수
      • 한 줄에 여러 문장쓰지 않음
    • 배열 대괄호 선언
      • 한 줄에 여러 문장쓰지 않음
    • Long 접미사 선언
      • 대문자 사용
    • 들여쓰기
      • 일관되게 작성
      • 계층을 나눌 때에는 tab(4space)로 구분
      • 클래스, 메서드, 제어문 등의 코드 블럭()이 생길 때마다 1단계 더 추가
    • 중괄호
      • 줄의 마지막에 {
        로 쓰고 블럭을 닫았을 때 새줄로
        }
    • 줄바꿈
      • 명령어, 구문이 길어질 때 가독성을 위하여 사용
    • 빈줄
      • 메소드 사이의 에는 빈줄로 구분
    • 공백
      • 빈줄을 포함하여 모든 줄은 탭이나 공백을 포함하지 않음
      • [] 대괄호 작성 시 공백을 삽입
    • 주석
      • 코드 관리와 가독성면에서 꼭 필요한 기능
      • 불필요한 주석은 작성하지 않기
        • 의도 설명
        • 결과 경고
        • TODO 작성
    • 예외처리
      • 절대 빈 catch 블록으로 처리하거나 무시하지 않기
      • 복구할 수 있는 예외와 복구할 수 없는 예외를 구분
      • 호출자에게 문제를 알리기 위한 예외알리기
      • 구체적인 예외를 처리
      • null을 전달 및 반환하지 않기

 


2. 새싹반 4회차 (예외처리와 제네릭)

  • 예외와 오류
    • 예외(Exception)는 프로그램 실행 중 발생할 수 있는 예측 가능한 문제
    • 오류는 프로그램이 복구하기 어려운 문제
    • 예외처리의 필요성
      • 프로그램의 비정상 종료 방지
      • 오류 원인 파악 용이
      • 오류 원인 파악 용이
  • 예외처리
    • Checked Exception
      • 컴파일 시점에 예외 처리
      • 예외 처리를 하지 않으면 컴파일 오류가 발생
      • 외부 환경과의 입출력(IO) 작업에서 발생
      • 예외 처리를 강제하여 개발자가 이를 반드시 처리
    • Unchecked Exception
      • 런타임 시점에 발생
      • 예외 처리를 강제하지 않음
      • 프로그래머의 실수로 인해 발생하는 예외
    • 예외 전파
      • 메소드 선언부에 throws 키워드를 사용하여 예외를 선언
    • 예외를 우아하게 처리하는 방법
      • 적절한 예외 메시지
      • 프로그램의 안정성 유지
      • 자원 누수 방지
      • 로깅 활용
// 1. try-catch-finally 블록 사용
try {
    // 예외가 발생할 수 있는 코드
} catch (ExceptionType e) {
    // 예외 처리 코드
} finally {
    // 예외 발생 여부와 관계없이 항상 실행되는 코드
}

// 2. 사용자 정의 예외 클래스 작성
public class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

 

  • 제네릭
    • 제네릭(Generics)은 클래스나 메소드에서 사용할 데이터 타입을 외부에서 지정할 수 있게 하는 기법
    • 잘못된 타입을 캐스팅할 경우 ClassCastException이 발생하고 코드의 가독성이 떨어지는 문제로 제네릭이 제시됨
    • 타입 안전성 보장
    • 형 변환 불필요
  • 제네릭 클래스
    • 박스에는 어떤 종류의 물건이든 담을 수 있음
// 제네릭 클래스 Box 선언
public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}
  • 제네릭 메소드
    • 제네릭 메소드는 메소드 레벨에서 타입 파라미터를 정의
public class Util {
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}
  • 와일드 카드
    • 와일드카드는 제네릭 타입을 보다 유연하게 사용할 수 있음
public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}
  • 제한된 타입 파라미터
    • 상한 제한
      • extends
      • 명시한 클래스와 그 하위 클래스만 허용
    • 하한 제한
      • super
      • 명시한 클래스와 그 상위 클래스만 허용

3. CH 2 숫자 야구 게임 과제

  • 숫자 야구 게임 검토
  • 오늘 오전에 배운 코드컨벤션을 지키며 작성했는지 검토하였다. 코드컨벤션이 안지켜진 코드들을 수정하였다.
  • 일부 변수명이 중복되어 선언되어있는 문제를 해결하였다.
  • 메인 메서드에서 입력을 받는데 input값 처리에 대한 예외를 하지 않아 int형에 문자를 입력할 경우 게임이 종료되는 문제점이 있어 InputMismatchException 예외처리를 통해 해결하였다. 처음에 예외처리를 while문 밖에 작성하였다가 예외처리 후 게임이 종료되는 문제가 있어 while문 안에 try catch를 추가하였다.
  • Level1, 2, 3에 있는 코드들이 중복되는 경우가 많은데 이를 상속과 추상메소드를 통해 어떻게 해결할 수 있는지 고민이 되었다.
  • 제너릭을 적용하지 않았는데 추후에 코드 작성 시 제너릭을 사용하면 더 편리할 것 같다.

4. 상속과 추상화 개념 공부

  • 객체지향 언어 복습
  • 스타크래프트로 비유..(?)하면 ...
    • 스타크래프트에서 각 유닛이나 건물은 객체
    • 마린 객체는 다음과 같은 속성(데이터)과 행동(메서드)을 가지고 있음
      • 속성: 체력, 공격력, 방어력, 이동 속도
      • 행동: 공격, 이동, 방어, 스팀팩 사용
    • 클래스는 객체를 생성하는 설계도 스타크래프트의 유닛이나 건물을 정의하는 설계도가 바로 클래스  
      • 마린이라는 클래스가 있다면, 이 클래스는 마린 객체를 만들 수 있는 청사진 역할
      • 테란에는 마린 외에도 벌처, 시즈탱크 등 여러 유닛이 있는데, 이 유닛들은 각각 다른 클래스로 정의될 수 있음
    • 유닛이라는 공통 클래스를 만들고, 이를 상속받아 마린, 벌처, 탱크 등 세부적인 유닛 클래스를 만들 수있음
      • 유닛 클래스: 모든 유닛들이 가지는 기본 속성(체력, 공격력, 이동 속도 등)과 행동(이동, 공격 등)을 정의
      • 마린 클래스: 유닛 클래스를 상속받아 추가 속성(스팀팩 사용)과 특화된 행동을 추가
      • 벌처 클래스: 유닛 클래스를 상속받아 특유의 속성(마인 설치 능력)과 행동을 정의
    • 모든 유닛에게 "이동" 명령을 내릴 수 있는데, 마린, 벌처, 탱크는 각각 이동 방식이 다른 것을 다형성
      • 마린: 일반적인 걸음으로 이동
      • 벌처: 빠르게 이동
      • 시즈탱크: 시즈 모드에서는 이동 불가, 일반 모드에서는 느리게 이동
    • 마린의 체력이나 공격력 같은 속성은 외부에서 직접 수정할 수 없고, 게임 엔진이 정해진 규칙에 따라 조정하여 객체의 중요한 데이터를 보호하는 것이 캡슐화
    • 플레이어는 마린이 총을 쏘면 적에게 피해를 주는 것만 알면 되며, 그 총알이 날아가는 궤적이나 적이 어떻게 피해를 입는지 내부 로직을 알 필요가 없음. 이런 식으로 복잡한 과정을 감추고 필요한 정보만 제공하는 것이 추상화
  • 생성자 개념 및 활용
    • 클래스가 객체를 생성할 때 자동으로 호출되는 특별한 메서드
    • 생성자를 선언하지 않으면 기본생성자를 자동으로 호출한다.
      • 하지만 만약에 생성자를 하나라도 작성했으면 작성한것만 생성자 작성이 됨.
    • 체가 생성될 때, 클래스에 정의된 속성(변수)을 초기화하는 데 사용. 예를 들어, 마린 객체가 생성될 때 체력, 공격력, 이동 속도 등을 설정해야 할 때 생성자가 그 역할
class Marine {
    int health;
    int attack;

    // 생성자
    Marine(int health, int attack) {
        this.health = health;  // 체력 초기화
        this.attack = attack;  // 공격력 초기화
    }

    void status() {
        System.out.println("마린의 체력: " + this.health + ", 공격력: " + this.attack);
    }
}

public class Main {
    public static void main(String[] args) {
        Marine marine1 = new Marine(40, 6);  // 객체 생성 시 생성자가 호출됨
        marine1.status();  // 출력: 마린의 체력: 40, 공격력: 6
    }
}
  • 제너릭 개념 및 활용
    • 스타크래프트의 조합 가능한 기술 업그레이드로 설명
    • 유닛들이 업그레이드된 기술을 사용함으로써 더 다양한 상황에 적응할 수 있게 되는 것을 제너릭으로 표현할 수 있음
    • 스타크래프트에서는 각 유닛이 특정 기술을 업그레이드하면, 특정 능력을 얻을 수 있음. 예를 들어, 마린은 스팀팩을 업그레이드할 수 있고, 벌처는 스파이더 마인을 사용할 수 있음 이때, 각 유닛이 기술을 업그레이드할 수 있는 시스템을 제너릭으로 비유하면, 제너릭이 코드에서 특정 데이터 타입에 맞게 유연하게 동작하는 것과 비슷한 원리를 설명
// 제너릭 업그레이드 연구소 클래스
class UpgradeLab<T> {
    private T unit;

    // 유닛에게 업그레이드 적용
    public void applyUpgrade(T unit) {
        this.unit = unit;
        System.out.println(unit.getClass().getSimpleName() + "에게 업그레이드가 적용되었습니다!");
    }

    public T getUnit() {
        return unit;
    }
}

// 마린 클래스
class Marine {
    public void useStimpack() {
        System.out.println("마린이 스팀팩을 사용했습니다!");
    }
}

// 벌처 클래스
class Vulture {
    public void laySpiderMine() {
        System.out.println("벌처가 스파이더 마인을 설치했습니다!");
    }
}

public class Main {
    public static void main(String[] args) {
        // 마린 업그레이드 연구소
        UpgradeLab<Marine> marineLab = new UpgradeLab<>();
        Marine marine = new Marine();
        marineLab.applyUpgrade(marine);  // 마린에게 업그레이드 적용
        marine.useStimpack();  // 업그레이드된 스팀팩 사용

        // 벌처 업그레이드 연구소
        UpgradeLab<Vulture> vultureLab = new UpgradeLab<>();
        Vulture vulture = new Vulture();
        vultureLab.applyUpgrade(vulture);  // 벌처에게 업그레이드 적용
        vulture.laySpiderMine();  // 업그레이드된 스파이더 마인 설치
    }
}