오늘 진행한 학습 요약
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 형식을 사용
- 소문자로 시작하고 명확하고 구체적인 이름을 사용
- 상수
- 상수는 대문자와 언더바를 사용해 작성
- 모든 단어는 명확하게 분리
- 패키지
- Full- Text 작성 지향
- 선언
- 전처리
- 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 키워드를 사용하여 예외를 선언
- 예외를 우아하게 처리하는 방법
- 적절한 예외 메시지
- 프로그램의 안정성 유지
- 자원 누수 방지
- 로깅 활용
- Checked Exception
// 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(); // 업그레이드된 스파이더 마인 설치
}
}