티스토리 뷰
객체지향 프로그래밍의 기본 원칙은 캡슐화(encapsulation), 상속(inheritance), 다형성(polymorphism)이며, 이들은 소프트웨어를 보다 모듈화하고 유지보수하기 쉽게 한다.
- 캡슐화(Encapsulation):
- 캡슐화는 관련된 데이터와 메서드를 하나의 단위로 묶는 것
- 클래스는 데이터(속성)와 해당 데이터를 다루는 메서드(함수)를 함께 캡슐화하여 객체를 형성
- 캡슐화는 정보 은닉(Information Hiding)을 통해 객체의 내부 구현을 외부로부터 숨기고, 외부에서는 객체의 인터페이스를 통해 상호작용한다.
- 상속(Inheritance):
- 상속은 기존의 클래스에서 정의된 속성과 메서드를 새로운 클래스에서 재사용할 수 있도록 하는 개념
- 상속을 통해 코드 중복을 줄이고, 기존 클래스의 기능을 확장하거나 변경할 수 있다.
- 부모 클래스와 자식 클래스 간의 계층 구조를 형성하여 객체 간의 관계를 표현
- 다형성(Polymorphism):
- 다형성은 같은 이름의 메서드나 연산자가 다양한 상황에서 다르게 동작할 수 있는 능력을 의미합니다.
- 다형성은 오버로딩(Overloading)과 오버라이딩(Overriding)을 통해 구현
- 오버로딩은 같은 이름의 메서드가 매개변수의 타입이나 개수에 따라 다르게 동작하는 것을 말하며, 오버라이딩은 부모 클래스에서 정의된 메서드를 자식 클래스에서 재정의하여 사용하는 것을 말합니다.
그러나 막상 프로그래밍을 하면서 이 3요소를 제대로 지키지 못하는 경우가 많고, 고려하지 못하는 경우가 많다.
나도 그렇다. 그러다 이번 업무 중 소켓통신을 사용하는 일이 있었고, 회사 처음으로 코드리뷰 시간을 가졌다.
나에게 업무를 주신 수석님이 내 코드를 보면서 상속을 사용을 하면 좋을 것 같아요. 라는 말씀을 해주셨다.
넹..? 상속이요..? 머리가 벙쪘다.. 코드를 짜면서 전혀 고려를 해보지 못한 것이기 때문이다.
리뷰 시간에 엇..넵..넵..(이해안간다..🙄) 하고 리뷰가 끝난 다음 다시 살펴보았다.
상속화를 고려하지 못한 나의 코드는 아래와 같다.
다른 요청에서 사용할 수 있도록 메세지를 전달하고 응답을 받는 것을 함수화 했고, 어떤 요청이든 저 sendMessage와 recieveMessage를 호출하면 되서 코드의 재사용성을 높혔다고 생각했다! 가장 중요한게 뭔지도 모르고!
[상속을 고려하지 못한 코드]
public class SocketConnector {
public MessageResponse request(MessageRequest messageRequest) {
try(Socket socket = new Socket()) {
//소켓 타임아웃 설정
socket.connect(socketAddress, SOCKET_TIME_OUT);
//소켓 read timeout 설정
socket.setSoTimeout(SOCKET_TIME_OUT);
//메세지 전달
sendMessage(MessageType.Type.getValue(), MessageRequest);
//메세지 응답 및 리턴
return (MessageResponse) receiveMessage(MessageResponse.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 응답메세지 받기
* @param returnType
* @throws Exception
*/
private Object receiveMessage(Class<?> returnType) throws Exception {
//메세지 응답 코드
return returnType;
}
/**
* 요청 메세지 보내기
* @param messageType
* @param obj
* @throws Exception
*/
private void sendMessage(String messageType, Object obj) throws Exception {
//메세지 전달 코드
}
}
[상속을 고려한 코드]
socket 객체를 상속받아, 객체를 새롭게 생성하지 않고, 부모 클래스에 정의된 함수들을 그대로 사용 할 수 있었다.
public class SocketConnector extends Socket{
public MessageResponse request(MessageRequest messageRequest) {
try {
//소켓 타임아웃 설정
connect(socketAddress, SOCKET_TIME_OUT);
//소켓 read timeout
setSoTimeout(SOCKET_TIME_OUT);
//메세지 전달
sendMessage(MessageType.Type.getValue(), MessageRequest);
//메세지 응답 및 리턴
return (MessageResponse) receiveMessage(MessageResponse.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
사실 두 코드가 크게 차이가 없어보이지만, 상속 받지 않은 경우에는 request1, request2, request3 과 같이 새로운 요청들이 생긴 경우, 각각의 요청 안에서 매번 소켓 객체를 새로 만들어야한다. 그렇지만 상속을 사용하는 경우 이런 불필요한 과정이 없어진다! 완전 짱임.. 이렇게 개념적으로만 알고 있던 걸 실무에서 사용해볼 때 너무나 재밌는 것 같다😆
앞으로도 프로그래밍을 하면서 상속을 통해 코드를 재사용할 수 있는지 고려해보도록 해야겠다!
'백엔드 > java' 카테고리의 다른 글
[java] 소켓 통신 시 데이터가 제대로 오지 않는다?! / 엔디안 / 빅엔디안 / 리틀엔디안 / ByteBuffer (1) | 2024.09.18 |
---|---|
[java] null 대신 Optional 클래스 (0) | 2024.09.18 |
[java] 신뢰할 수 없는 인증서(사설인증서)를 사용 할 수 있도록 jvm 설정하기/PKIX path building failed (0) | 2024.06.10 |
[java/자바] try-with-resource 구문 / 자원 자동 반납 (0) | 2023.08.03 |
[java/자바] 익명내부 클래스를 람다식으로 변경하기 (0) | 2023.07.25 |
- Total
- Today
- Yesterday
- 전자정부프레임워크
- 현대코테
- 자바
- 도커
- 코테
- 자바코테
- java 코테
- Spring
- 코딩테스트
- Linux
- javascript
- centos
- 아파치카프카
- 오토에버코테
- react
- 스프링
- 현대
- 톰캣
- springboot
- Kubernetes
- tomcat
- 현대오토에버
- mysql
- softeer
- java
- softeer java
- 리액트
- Docker
- 자바스크립트
- 쿠버네티스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |