도서 - 스프링 입문을 위한 자바 객체지향의 원리와 이해 1
by choising
스프링 입문을 위한 자바 객체지향의 원리와 이해 ( ~ 197p)
스프링 삼각형
- IoC/DI, AOP, PSA.
- 스프링을 지배하는 근원적인 요소.
- POJO(Plain Old Java Object)에 세 가지 유형의 진동을 줌으로써 거대한 프레임워크를 완성.
현실 세계 vs 자바 세계
- Write Once Run Anywhere.
현실 세계 | 자바 세계 |
---|---|
하드웨어(물리적 컴퓨터) | JVM(자바 가상 기계) - 가상의 컴퓨터. |
운영체제 | JRE(자바 실행 환경) - JVM용 OS |
소프트웨어 개발 도구 | JDK(자바 개발 도구) - JVM용 소프트웨어 개발 도구 |
- JDK에는 JRE가 포함되어 있고, JRE에는 JVM이 포함되어 있다.
-
편의를 위해, JDK만 배포 받으면 사용이 가능한 것이다.
- JDK에는 자바 소스 컴파일러 javac.exe가 포함되어 있다.
- .java -> .class
- JRE에는 자바프로그램 실행기 java.exe가 포함되어 있다.
- .class파일을 이용한 실행.
- .class파일을 이용한 실행.
main() 메서드와 Java run
- 간략히 추상화한 메모리 구조의 데이터 저장영역을 편의를 위해 T 메모리 모델 이라 부르겠다.
- JRE가 프로그램의 main() 메서드가 있는지 확인한다.
- main() 메서드의 존재가 확인되면, JRE는 프로그램을 실행하기 위한 사전 준비.
- 비유적으로, JVM 부팅.
- JVM은 object file 실행.
- 패키지 로딩
- java.lang 패키지 스테틱 영역에 위치시킨다.
- import 된 패키지를 스테틱 영역에 위치시킨다.
- 클래스 로딩
- 프로그램 상의 모든 클래스를 스테틱 영역에 위치시킨다.
- 스택 프레임 배치
- Class를 생성하는 중괄호를 제외하고, 여는 중괄호를 만날 때 마다 Stack영역에 메서드 스택 프레임을 할당한다.
- 변수 공간 배치
- 메서드에 인자가 있다면, 인자를 저장할 변수 공간을 해당 스택 프레임 최하단에 확보한다.
- 위 과정을 완료했다면, main() 메서드 안의 첫 명령문을 실행한다.
- 닫는 중괄호를 만나면 스택 프레임을 소멸한다.
- 패키지 로딩
- main() 메서드가 종료되면 JRE는 JVM을 종료시키고 JRE 자체도 OS의 메모리에서 사라진다.
변수와 메모리
- 로컬 변수는 Stack Area.
- 스택 프레임이 사라지면 함께 사라진다.
- 클래스 변수는 Static Area.
- JVM이 종료될 때 사라진다.
- 인스턴스 변수는 Heap Area.
- 가비지 컬렉터가 힙 메모리 회수 시 사라진다.
- 가비지 컬렉터가 힙 메모리 회수 시 사라진다.
멀티 스레드 / 멀티 프로세스
-
멀티 스레드는 스택 영역을 스레드 개수만큼 분할하여 사용한다.
-
멀티 프로세스는 다수의 데이터 저장 영역 즉 다수의 T 메모리 모델 을 갖는다.
- 멀티 프로세스는 각자 고유의 공간을 침범할 수 없다.
- 그에 반해 멀티 스레드는 스테틱 영역과 힙 영역은 공유한다. (멀티 프로세스보다 메모리를 적게 사용한다.)
클래스(Class) vs 객체(Instance)
- 클래스는 개념이고 객체는 실체다.
- 클래스는 분류에 대한 개념.
- 클래스와 객체를 구분하는 정의 중 가장 와닿는 정의였다.
- 또한 이 책의 작가는 객체와 클래스를 다음과 같이 정의하기도 하였다.
- 객체 : 세상에 존재하는 유일무이한 사물.
- 클래스 : 분류, 집합. 같은 속성을 가진 객체를 총칭하는 개념.
객체지향의 4대 특성
- 캡슐화(Encapsulation)
- 정보 은닉(information hiding)
- 상속(Inheritance)
- 재사용(re-use)
- 추상화(Abstraction)
- 모델링
- 다형성(Polymorphism)
- 사용 편의
- 사용 편의
상속
- 객체지향에서의 상속 정의.
- 상위 클래스의 특성을 하위 클래스에서 상속(재사용)하고,
- 거기에 필요한 특성을 추가 및 확장 가능하다.
extends
라는 단어에서 느껴지듯, 상속 보다 확장의 개념이 강하다.
- 부모 - 자식 보다는, 상위 분류 - 하위 분류 라고 이해하는 것이 더 좋다.
- 상위 클래스 쪽으로 갈수록 추상화, 일반화 되었다고 말하며
- 하위 클래스 쪽으로 갈수록 구체화, 특수화 되었다고 말한다.
Bird bird = new Bird()
- 위와 같은 선언을 줄이자.
Bird theBird = new Bird()
가 훨씬 명확하다.
- 상속은 is a 관계다?
- is a kind of 관계 가 더욱 명확하다.
- 하위 클래스 is a kind of 상위 클래스
- 하위 클래스 인스턴스가 생성될 때 상위 클래스의 인스턴스도 함께 생성된다.
- 당연히 Heap 영역.
- 당연히 Heap 영역.
인터페이스
- 구현 클래스 is able to 인터페이스
- 구현 클래스는 인터페이스 할 수 있다.
- 때문에 인터페이스는 be able to 라는 표현 형태로 만드는 것이 좋다.
- 예) Comparable, Runnable, Cloneable …
- 퍼블릭 추상 메서드와 퍼블릭 정적 상수만을 가질 수 있다.
- 메서드에는 따로 입력하지 않아도 public, abstract가 추가되어 컴파일 된다.
- 속성에는 public, static, final이 추가되어 컴파일 된다.
- 하지만, 키워드들을 적는 것이 보다 명확하다.
- 자바 8, 람다를 지원하면서 부터
- 디폴트 메서드를 지원하도록 스펙이 바뀌었다.
- 객체 구상 메서드, 정적 추상 메서드
- 디폴트 메서드를 지원하도록 스펙이 바뀌었다.
- 인터페이스는 구현을 강제하는 메소드가 적을수록 좋다.
- 상속은 반대로 많을수록 좋다고 할 수 있다.
- 상속은 반대로 많을수록 좋다고 할 수 있다.
추상
- 객체지향의 추상화는 곧 모델링이다.
- 추상의 사전적 의미 : 여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용.
- 조금 더 자세히
- 구체적인 것을 분해해서 관찰자가 관심 있는 특성만 가지고 재조합 하는 것
- 조금 더 IT 적으로
- 추상화란, 구체적인 것을 분해해서 관심 영역(애플리케이션 경계, Apllication Boundary)에 있는 특성만 갖고 재조합 하는 것
- = 모델링.
- 조금 더 자세히
다형성
- 다형성의 가장 기본은 오버라이딩과 오버로딩에 있다.
- 오버로딩이 다형성인지 아닌지에 대해서는 이견이 있다고 한다.
- 오버로딩이 다형성인지 아닌지에 대해서는 이견이 있다고 한다.
Abstract
- 추상 클래스
- 하나 이상의 메소드가 추상 메소드인 경우.
- 사실 추상 메소드가 없어도 추상 클래스로 선언은 가능하다.
- 하나 이상의 추상 메소드를 갖는 경우 반드시 추상 클래스로 선언하여야 한다.
- 추상 클래스는 인스턴스를 생성할 수 없다.
- 추상 클래스를 상속 받는 하위 클래스는 반드시 추상 메소드의 구현부를 구현해야 한다.
- 오버라이딩 강제.
- 오버라이딩 강제.
static block
public class A {
static {
System.out.println("hello");
}
}
-
static block에 놓인 코드블록은 클래스가 스테틱 영역에 배치될 때 단 한 번 실행된다.
-
클래스 정보는 해당 클래스가 코드에서 맨 처음 사용될 때 메모리의 스태틱 영역에 로드된다.
- 위와 유사하게 아무런 표시 없이
{}
block을 사용하게 되면, - 인스턴스가 생성될 때 마다 생성자보다 먼저
{}
block을 실행한다.
final
- final keyword가 붙을 수 있는 곳은 세가지. 클래스, 변수, 메소드.
- final Class
- 상속을 허용하지 않는다.
- final 변수
- 상수(변경을 허용하지 않는다.)
- final 메소드
- 오버라이딩을 허용하지 않는다.
- 오버라이딩을 허용하지 않는다.
SOLID
- 객체 지향 프로그래밍 설계의 다섯 가지 기본 원칙.
- for High Cohesion, Loose Coupling
- 응집도↑, 결합도↓
- 응집도↑, 결합도↓
SRP(Single Responsibility Principle)
“어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.” - 로버트 C.마틴
-
단일 책임 원칙.
- 설계(모델링) 시, 단일 책임 원칙을 고려하는 습관을 들이자.
- 애플리케이션 경계를 정하고
- 추상화를 통해 클래스, 속성, 메소드를 설계할 때.
- 단일 책임 원칙을 기억하자. 애플리케이션의 경계를 정하고 추상화를 통해 클래스들을 선별하고 속성과 메소드를 설계할 때.
- 또한, 리팩토링을 통해 코드를 개선할 때에도 단일 책임 원칙을 기억.
OCP(Open Closed Principle)
“소프트웨어 엔티티는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다.” - 로버트 C.마틴
-
개방 폐쇄 원칙.
- 확장성 있게 설계하고,
-
변화에 유연하게 대처할 수 있게 설계하라는 것 같다.
- 하나의 예로 JDBC 인터페이스를 들었다.
- DB가 변경(MySQL -> Oracle 등)되더라도, Connection을 설정하는 부분 외에는 아무것도 수정할 필요가 없다.
- 변경 시에 수정할 부분은 아주 미세하나, 확장 시 매우 편리한 것.
-
위 규칙을 준수할 경우 유연성, 재사용성, 유지보수성이 향상하는 효과를 얻을 수 있다.
- 하지만, 너무 어려워 보인다.
LSP(Liskov Substitution Principle)
“서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다. - 로버트 C.마틴
-
리스코프 치환 원칙.
-
즉, 하위 클래스의 인스턴스는 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다.
ISP(Interface Segregation Principle)
“클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.” - 로버트 C.마틴
-
인터페이스 분리 원칙.
- 인터페이스는 그 역할에 충실한 최소한의 기능만 공개.
- 인터페이스는 is able to 라는 기준으로 만드는 것이 정석.
DIP(Dependency Inversion Principle)
“고차원 모듈은 저차원 모듈에 의존하면 안된다.
이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.”
“추상화된 것은 구체적인 것에 의존하면 안된다.
구체적인 것이 추상화된 것에 의존해야 한다.”
“자주 변경되는 구체 클레스에 의존하지 마라” - 로버트 C.마틴
-
의존 역전 원칙.
-
자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것이 의존 역전 원칙이다.
Subscribe via RSS