jun96 2025. 4. 29. 23:46

내용 정리

전역 변수와 전역 메서드의 남용

모든 상수를 Constant 클래스로 통합할 경우 생기는 문제점

  1. 코드의 유지 보수성에 영향을 미친다. 상수를 추가할수록 점점 코드의 몸집은 불어나고, 수정을 하며 충돌을 일으킬 것이다.
  2. 코드 컴파일의 시간을 증가 시킨다. Constant 클래스를 수정할 때마다 Constant 클래스에 종속된 다른 클래스가 매번 다시 컴파일되어 불필요한 컴파일 시간을 낭비한다. 대규모 프로젝트는 컴파일 하는데 몇 분 또는 수십 분이 소요될 수도 있고, 개발 과정에서 단위 테스트가 실행 될 때마다 컴파일이 실행되기 때문에 긴 컴파일 시간은 개발 효율성에도 큰 영향을 미친다.
  3. 코드의 재사용 가능성에도 영향을 미친다. 이 프로젝트에서 개발한 클래스를 다른 프로젝트에서 재사용 하려고 할 때, 이 클래스가 Constant 클래스에 종속되어 있다면 어떻게 될까? 이 클래스가 Constant 클래스의 일부 상수만 사용하더라도 Constant 클래스 전체를 도입해야 한다. 실제로는 아무 관련도 없는 많은 상수들이 모듈에 포함되는 것이다.

Utils 클래스를 정의하기 전에

  1. Utils 클래스를 별도로 정의해야 하는가?
  2. Utils 클래스의 일부 메서드를 다른 클래스로 정의할 수가 있는가?

이 질문에도 여전히 Utils 클래스를 정의할 필요가 있다고 생각한다면 과감하게 정의한다

추상 클래스와 인터페이스의 정의와 차이점

추상 클래스의 특성

  1. 추상 클래스는 인스턴스화할 수 없으며 상속만 가능하다.
  2. 추상 클래스는 속성과 메서드를 포함할 수 있다.이때 클래스에 메서드에 코드 구현을 포함할 수 있고, 메서드에 코드 구현을 포함하지 않을 수도 있다. 이때 코드 구현을 포함하지 않는 메서드를 추상 메서드라고 한다.
  3. 하위 클래스는 추상 클래스를 상속할 때 추상 클래스의 모든 추상 메서드를 실제로 구현해야 한다.

인터페이스의 특성

  1. 인터페이스는 속성을 포함할 수 없다.
  2. 인터페이스는 메서드를 선언할 수는 있으나, 실제 코드 구현을 포함할 수 없다.
  3. 클래스가 인터페이스를 구현할 때는 인터페이스에 선언된 모든 메서드를 구현해야 한다.

합성이 상속에 비해 나은 점

상속 문제는 합성, 인터페이스, 위임이라는 세 가지 기술적 방법을 통해 해결할 수 있다.

public interface Flyable {
	void fly();
}

public class FlyAbility implements Flyable {
	@Override
	public void fly() { ... }
}

// .. 나머지 코드 생략 ..
// - Tweetable interface
// - TweetAbility 클래스

public class Duck implements Tweetable, Flyable {
	private FlyAbility flyAbility = new FlyAbility(); // 합성
	private TweetAbility tweetAbility = new TweetAbility(); // 합성
	// .. 일부 생략 ..

	@Override
	public void tweet() {
		tweetAbility.tweet(); // 위임
	}

	@Override
	public void fly() {
		flyAbility.fly(); // 위임
	}
}

is-a 관계는 합성과 인터페이스의 has-a 관계로 대체될 수 있고, 다형성은 인터페이스를 사용하여 달성될 수 있으며, 코드 재사용은 합성과 위임으로 목적을 달성할 수 있다. 이론적으로 합성, 인터페이스, 위임의 세 가지 기술 수단은 상속을 완전히 대체할 수 있다.

합성을 사용할지 상속을 사용할지 결정하기

클래스 간의 상속 구조가 안정적이어서 쉽게 변경되지 않고 상속 단계가 2단계 이하로 비교적 얕아 상속 관계가 복잡하지 않다면 과감하게 상속을 사용할 수 있다. 반대로 시스템이 불안정하고 상속 계층이 깊고 상속 관계가 복잡하면 상속 대신 합성을 사용해야 한다.

public class FeignClient { // Feign Client 프레임 코드
	// .. 일부 코드 생략 ..
	public void encode(String url) { ... }
}

public class CustomizedFeignClient extends FeginClient {
	@Override
	public void encode(String url) {
		// .. 중복되는 encode() 구현 생략  ..
	}
}

public void demofunction(FeignClient feignClient) {
	// .. 일부 코드 생략 ..
	feignClient.encode(url);
	// .. 일부 코드 생략 ..
}

// 사용하기
FeignClient client = new CustomizedFeignClient();
demofunction(client);

나눌 내용

왜 리눅스 os는 C언어로 작성 됐을까?

https://www.quora.com/What-are-the-reasons-why-Linux-OS-is-written-in-C-language

  1. 리누스 토발즈는 C++와 같은 객체 지향 언어에서 일반적으로 나오는 코드 스타일을 좋아하지 않았다.
  2. 이미 C로 작성된 기존의 언어들의 예외들에 대한 정의가 잘 되어있어 안정적이었다.
  3. 당시에 시장을 지배하고 있던 언어가 C이기 때문이다.

GPT 답변

  • 직접적인 메모리 접근 가능 (포인터)
  • 어셈블리 언어와 가깝지만 이식성이 뛰어남
  • 효율적인 실행 속도 (최소한의 오버헤드)

절차지향이 OS 개발에 적합

운영 체제는 많은 프로세스, 메모리 관리, 디바이스 드라이버 등의 기능을 다루어야 합니다. 객체지향(OOP)이 OS 개발에 반드시 유리한 것은 아닙니다.

운영 체제 개발에 절차지향이 유리한 이유

  • 빠르고 직관적인 코드 실행 → OS는 성능이 중요하므로, 불필요한 추상화가 적은 절차지향 방식이 유리함 → 책에서 나온 코드 컴파일의 시간을 증가 시킨다. 라는 내용과 일맥상통 하는 듯
  • 직접적인 하드웨어 제어 → 객체지향 언어는 가비지 컬렉션(GC) 같은 기능이 추가될 수 있어, 시스템 성능 저하 가능성 있음
  • OS의 기능 자체가 계층적 설계 → 커널, 파일 시스템, 네트워크 스택 등은 절차적으로 동작하는 것이 효율적

그렇다고 객체지향이 운영 체제에서 전혀 쓰이지 않는 것은 아닙니다. 일부 운영 체제(예: Windows)는 일부 C++을 사용하고, 리눅스에서도 특정 서브 시스템에서 객체지향적 설계를 활용합니다.

도메인 모델 순수성 vs 도메인 모델 완전성

https://enterprisecraftsmanship.com/posts/domain-model-purity-completeness/

빈약한 도메인 모델 리팩토링?

빈약한 도메인 모델을 풍성한 도메인 모델로 전환하는 경우가 있는지..??

https://martinfowler.com/bliki/AnemicDomainModel.html

BO, Entity, VO 를 세세하게 나누는가?

회사에서는 개발 소요 시간이 짧아야 하고, 알아도 안 하시는 경우가 많기 때문에 (일관성을 유지한다는 명목으로) 직접적인 DB와 통신할 객체는 나누는 것은 많이 봤어도 BO, VO 등 세분화해 나누는 경우는 거의 없어, 실제로도 세분화하는 경우가 많은지? 혹은 단순한 로직에서는 나누지 않는 것인지?

따로 엔티티를 나누지 않으면 오히려 불편할 수도 있다…