“기본적으로 전역 클래스를 사용하고 적절한 경우에만 로컬 클래스를 사용하라”는 조언은 주로 클래스의 가시성과 유지보수성에 관한 것이다.
1. 전역 클래스 (Top-Level Class)란?
전역 클래스는 패키지 레벨에서 정의되는 클래스입니다. 자바에서는 하나의 .java 파일 안에 여러 개의 클래스가 있을 수 있지만, 이 중 하나의 전역 클래스만이 public으로 선언될 수 있습니다. 대부분의 클래스는 전역 클래스로 정의됩니다.
장점
- 가시성: 전역 클래스는 다른 클래스나 패키지에서 쉽게 접근 가능하며, 코드의 구조와 가독성이 높습니다.
- 유지보수성: 코드가 전역 클래스에 존재하면, 파일이나 패키지 구조를 따라 쉽게 찾아볼 수 있습니다. 이는 코드 관리와 유지보수에 유리합니다.
- 재사용성: 전역 클래스는 다른 클래스나 패키지에서 재사용하기에 용이합니다.
2. 로컬 클래스 (Local Class)란?
로컬 클래스는 메서드 내부에 정의된 클래스입니다. 이는 메서드 내에서만 사용되는 클래스입니다.
장점
- 캡슐화: 로컬 클래스는 해당 메서드 내에서만 접근 가능하므로, 외부로부터 보호됩니다. 이는 클래스가 특정 메서드의 논리에만 국한된 경우에 적합합니다.
- 명확한 목적: 로컬 클래스는 메서드의 내부 구현을 보조하는 데 주로 사용되므로, 그 역할이 명확합니다.
사용 시기: 로컬 클래스는 아래와 같은 경우에 적합합니다.
- 로컬 클래스는 주로 간단한 작업을 위해 메서드 내에서 사용되기 때문에, 수십 개의 클래스와 수천 줄의 코드가 얽혀 있다면 로컬 클래스를 사용하는 것이 적합하지 않을 수 있습니다. 이는 복잡성을 증가시키고 코드 가독성을 떨어뜨릴 수 있습니다. 이 경우 로컬 클래스 대신 전역 클래스로 코드를 구조화하여 관리하는 것이 더 바람직할 수 있습니다.
- 글로벌 클래스는 전역 클래스를 의미하는데, 이를 패키지처럼 생각한다는 것은 전역 클래스를 너무 복잡하게 설계하여 많은 하위 클래스나 로직을 포함시키는 경우를 말합니다. 전역 클래스는 역할이 명확해야 하며, 지나치게 많은 기능을 담고 있으면 관리가 어려워집니다. 이를 피하기 위해 역할에 맞게 클래스를 분리하고 패키지를 잘 구조화해야 합니다.
- 전역 클래스를 선언해 놓고 사용하지 않으면 코드베이스에 불필요한 클래스가 쌓이게 됩니다. 이는 혼란을 초래하고 유지보수를 어렵게 만들 수 있습니다. 불필요한 클래스를 제거하고 실제로 필요한 클래스만 유지하는 것이 중요합니다.
- 로컬 클래스나 메서드 내부에서 중복되는 코드가 여러 군데에서 발견된다면, 로컬 클래스를 사용하기보다 공통된 로직을 전역 클래스로 추출하여 재사용할 수 있도록 하는 것이 더 효율적입니다. 중복 코드는 코드 유지보수와 확장성을 저해하므로 이를 피해야 합니다.
- 로컬 클래스나 지나치게 복잡한 로직이 서로 얽혀 있다면, 팀원들이 동시에 작업하는 데 어려움을 겪을 수 있습니다. 한 명의 개발자가 로컬 클래스에 대한 작업을 진행하면 다른 개발자들이 해당 부분에 대한 작업을 진행할 수 없게 되는 상황이 발생할 수 있습니다. 이러한 문제를 방지하기 위해 클래스를 명확하게 분리하고, 병렬 작업이 가능하도록 구조화하는 것이 중요합니다.
- 로컬 클래스나 하위 구조가 지나치게 복잡해지면 팀원들이 서로의 코드를 이해하기 어려워질 수 있습니다. 이로 인해 작업의 난이도가 증가하고, 백로그 추정치(할 일 목록에 대한 작업 추정 시간)가 매우 높아질 수 있습니다. 이 경우에는 코드 구조를 단순화하고, 전역 클래스로 역할을 분명히 하여 팀원들이 쉽게 이해하고 협력할 수 있도록 만드는 것이 필요합니다.
이 조언들은 로컬 클래스를 지나치게 사용함으로써 발생할 수 있는 문제점들을 지적하고 있습니다. 로컬 클래스는 간단하고 특정 메서드 내에서만 사용될 때 적합하지만, 복잡성이 증가하거나 중복 코드가 발생하면 전역 클래스를 사용하여 코드의 가독성과 유지보수성을 높이는 것이 좋습니다. 팀 협업과 코드의 확장성을 고려해, 적절한 경우에만 로컬 클래스를 사용하고, 그렇지 않은 경우 전역 클래스를 사용하는 것이 바람직합니다.
“상속을 고려하지 않았다면 final을 사용하라”는 조언은 객체지향 프로그래밍에서 안전성과 불변성을 강조하는 권고 사항입니다.
final 키워드의 의미
- 클래스에서 final: 클래스에 final을 붙이면, 해당 클래스를 더 이상 상속할 수 없습니다. 즉, 이 클래스는 확장될 수 없는 “종단 클래스”가 됩니다.
- 메서드에서 final: 메서드에 final을 붙이면, 자식 클래스에서 해당 메서드를 오버라이드할 수 없습니다.
- 변수에서 final: 변수에 final을 붙이면, 그 변수는 한 번 초기화된 이후로 변경할 수 없습니다. 이는 상수와 동일하게 작동합니다.
왜 상속을 고려하지 않는다면 final을 사용하는가?
- 안정성: 클래스나 메서드가 상속되거나 재정의될 수 있으면, 원래 의도한 대로 동작하지 않을 가능성이 있습니다. 이러한 경우 코드의 안정성이 떨어질 수 있기 때문에, 상속을 의도하지 않은 경우 FINAL을 사용하여 불필요한 변경을 방지할 수 있습니다.
- 명확성: FINAL 키워드는 클래스나 메서드가 확장될 수 없음을 명시적으로 나타내어, 다른 개발자들이 이 부분을 확장하거나 변경하려고 시도하지 않도록 유도합니다.
- 유지보수성: 만약 다른 개발자가 클래스나 메서드를 상속해서 변경하면, 원래 코드의 동작이 달라질 수 있어 유지보수가 어려워질 수 있습니다. FINAL을 사용하면 코드의 의도와 동작을 보존할 수 있어, 유지보수가 더 쉬워집니다.
ABAP에서 FINAL을 사용하는 것은 코드의 안정성과 명확성을 높이는 좋은 방법입니다. 특히 상속을 의도하지 않은 경우, 클래스나 메서드에 FINAL을 적용하여 불필요한 확장을 방지하고, 원래 설계된 대로 코드가 동작하도록 유지할 수 있습니다.
“기본적으로 Private를 사용하고 필요한 경우에만 Protected를 사용하라”는 조언은 정보 은닉과 클래스 설계의 원칙을 지키기 위한 중요한 규칙 중 하나입니다. 이 원칙은 ABAP을 포함한 객체지향 언어에서 중요한 개념입니다.
Private와 Protected 접근 제어자
Private란?
Private로 선언된 클래스의 속성이나 메서드는 해당 클래스 내부에서만 접근할 수 있습니다. 외부 클래스나 하위 클래스에서 접근할 수 없습니다.
클래스 내부의 구현 세부 사항을 완전히 숨기고, 외부나 하위 클래스에서 접근하지 못하게 하여 객체의 캡슐화를 강화합니다.
Protected란?
Protected로 선언된 속성이나 메서드는 해당 클래스와 이를 상속받은 하위 클래스에서 접근할 수 있습니다. 외부 클래스에서는 접근할 수 없습니다.
클래스 내부의 중요한 정보를 하위 클래스에서는 사용할 수 있게 허용하면서도, 외부에서 접근하는 것을 방지합니다.
왜 기본적으로 Private를 사용해야 하는가?
- 정보 은닉 (Encapsulation): 객체지향 프로그래밍의 중요한 원칙 중 하나는 정보 은닉입니다. 클래스의 내부 구현 세부 사항을 외부로부터 숨기고, 외부에서는 클래스가 제공하는 공용 인터페이스(메서드)를 통해서만 상호작용할 수 있게 하는 것입니다. Private 접근 제어자는 이 원칙을 가장 강력하게 지원합니다.
- 안정성: 속성이나 메서드를 Private로 선언하면 외부에서 이들을 변경하거나 사용할 수 없으므로, 클래스의 내부 상태가 의도치 않게 변경되는 것을 방지할 수 있습니다. 이는 코드의 안정성을 높여줍니다.
- 유지보수성: Private 멤버는 클래스 외부에서 접근할 수 없기 때문에, 클래스 내부 구현이 변경되더라도 외부 코드에 영향을 미치지 않습니다. 따라서 내부 구현을 자유롭게 수정할 수 있어 유지보수가 쉬워집니다.
언제 Protected를 사용하는가?
- 상속이 필요한 경우: 상속을 고려하여 설계할 때, 하위 클래스에서 부모 클래스의 특정 속성이나 메서드에 접근해야 할 경우 Protected를 사용할 수 있습니다. 이를 통해 하위 클래스에서 부모 클래스의 로직을 확장하거나 재사용할 수 있게 됩니다.
- 공유할 필요가 있는 내부 구현: 특정 로직이나 데이터가 하위 클래스들에서 공통적으로 필요하다면, Protected로 선언하여 하위 클래스가 이를 활용할 수 있도록 할 수 있습니다.
왜 Protected를 남용하면 안 되는가?
- 캡슐화 약화: Protected는 Private보다는 더 많은 접근을 허용합니다. 하위 클래스에서도 접근할 수 있기 때문에, 클래스 내부의 구현이 예상치 않게 하위 클래스에서 변경되거나 사용될 수 있습니다. 이는 캡슐화를 약화시키고, 클래스 설계의 의도와 다르게 하위 클래스가 동작할 수 있는 위험을 가져옵니다.
- 유지보수의 어려움: Protected 멤버는 하위 클래스에서 접근할 수 있기 때문에, 부모 클래스의 구현을 변경할 때 하위 클래스들이 어떻게 영향을 받을지 항상 신경 써야 합니다. 이는 코드의 유지보수를 어렵게 만들 수 있습니다.
- 의도치 않은 결합: Protected 멤버가 많아질수록 하위 클래스와 부모 클래스 간의 결합도가 높아질 수 있습니다. 이는 코드의 재사용성을 떨어뜨리고, 수정 시 여러 클래스에 영향을 미치는 문제를 일으킬 수 있습니다.
“기본적으로 Private를 사용하고 필요한 경우에만 Protected를 사용하라”는 조언은 클래스의 캡슐화를 유지하면서 코드의 안정성과 유지보수성을 높이는 데 중점을 둔 권고 사항입니다. ABAP이나 다른 객체지향 언어에서 이 원칙을 지키면 코드가 더 명확해지고 유지보수가 쉬워집니다. Protected는 상속 관계에서만 신중하게 사용하고, 가능한 한 Private을 기본으로 하여 클래스 내부 구현을 철저히 보호하는 것이 좋습니다.
ABAP에서 Getter 메서드 대신 PUBLIC과 READ-ONLY를 사용하라는 조언은 클래스를 설계할 때 불필요한 메서드를 줄이고, 더 간결하고 직관적인 코드를 작성하라는 의미입니다. 이 조언을 자세히 설명하면 다음과 같습니다.
Getter 메서드와 그 한계
- Getter 메서드: 전통적으로 객체지향 프로그래밍에서는 클래스의 속성(필드)을 PRIVATE 또는 PROTECTED로 선언하고, 해당 속성에 접근하기 위해 별도의 GET 메서드를 사용하는 방식이 일반적입니다.
* Getter
CLASS lcl_person DEFINITION.
PRIVATE SECTION.
DATA: name TYPE string.
PUBLIC SECTION.
METHODS: get_name RETURNING VALUE(name) TYPE string.
ENDCLASS.
CLASS lcl_person IMPLEMENTATION.
METHOD get_name.
name = me->name.
ENDMETHOD.
ENDCLASS.
PUBLIC과 READ-ONLY 속성
- ABAP에서는 속성 필드를 직접 PUBLIC으로 선언하고, 읽기 전용으로 사용할 수 있는 READ-ONLY 옵션을 제공합니다. 이를 통해 Getter 메서드를 만들지 않고도 클래스의 속성을 외부에서 안전하게 읽을 수 있게 할 수 있습니다.
- PUBLIC 이 접근 제어자는 속성을 외부에서 직접 접근할 수 있도록 허용합니다.
- READ-ONLY 이 옵션은 속성을 외부에서 읽을 수만 있게 하고, 수정은 불가능하게 만듭니다. 즉, 외부에서 값을 변경하지 못하도록 안전하게 보호하면서도, 값을 쉽게 읽을 수 있습니다.
* READ-ONLY
CLASS lcl_person DEFINITION.
PUBLIC SECTION.
DATA: name TYPE string READ-ONLY.
ENDCLASS.
언제 PUBLIC과 READ-ONLY를 사용하는가?
- Getter 메서드가 단순한 경우: Getter 메서드가 단순히 필드 값을 반환하는 것이라면, 대신 해당 필드를 PUBLIC과 READ-ONLY로 선언하여 불필요한 메서드를 피할 수 있습니다.
- 읽기 전용 필드가 필요한 경우: 클래스의 속성을 외부에서 수정하지 못하도록 보호하면서도 읽기 전용으로 제공하고 싶을 때, 이 접근 방식을 사용할 수 있습니다.
Getter 메서드 대신 PUBLIC과 READ-ONLY를 사용하라는 조언은 간단한 읽기 전용 속성을 제공할 때 코드를 간소화하고 직관적으로 만드는 방법입니다. Getter 메서드를 통해 불필요한 복잡성을 추가하지 않고도, 클래스의 속성을 외부에 안전하게 노출할 수 있습니다.
“READ-ONLY를 남용하지 마라”는 조언은 READ-ONLY 속성을 과도하게 사용하는 것에 대한 주의를 주는 것입니다. READ-ONLY는 코드의 간결함과 접근성 측면에서 유용할 수 있지만, 이를 남용하면 코드의 설계와 유지보수에 여러 가지 문제를 일으킬 수 있습니다.
READ-ONLY의 역할
- READ-ONLY는 클래스의 속성을 외부에서 읽을 수 있게 하지만, 수정할 수는 없도록 보호해줍니다. 주로 클래스 내부에서 생성되거나 변경된 값을 외부에 노출하면서도, 외부에서 해당 값을 수정하지 못하도록 할 때 사용됩니다.
- 클래스 내부 상태를 유지하면서도 필요한 데이터를 외부에 안전하게 노출할 수 있는 방법으로, 간단한 상황에서는 매우 유용할 수 있습니다.
READ-ONLY의 남용이 문제가 되는 이유
- 캡슐화 원칙 위반 가능성: 객체지향 프로그래밍의 핵심 원칙 중 하나는 캡슐화(Encapsulation)입니다. 캡슐화는 객체의 내부 구현을 외부에서 숨기고, 필요한 경우에만 공용 메서드를 통해 접근할 수 있도록 하는 것을 의미합니다. READ-ONLY 속성을 남용하면 클래스의 내부 상태를 외부에 노출하는 경우가 많아지므로, 캡슐화가 약해질 수 있습니다.
- 의도치 않은 의존성 증가: 클래스의 속성을 READ-ONLY로 외부에 노출할 경우, 외부 코드가 해당 속성에 의존하게 될 수 있습니다. 나중에 클래스의 내부 구현을 변경할 때, 이러한 의존성 때문에 외부 코드도 수정해야 할 가능성이 커집니다. 이는 코드의 유지보수성을 저해할 수 있습니다.
- 확장성 제한: READ-ONLY 속성은 현재 상태에서 외부에서 읽기만 가능하게 설정되지만, 나중에 해당 속성에 로직을 추가하거나 조건을 붙여야 하는 상황이 발생할 수 있습니다. 이때 READ-ONLY를 사용한 접근 방식은 유연성이 떨어져 수정이 어려워질 수 있습니다. 이러한 경우에는 Getter 메서드를 사용해 로직을 관리하는 것이 더 적절할 수 있습니다.
- 기능이 단순한 경우에만 적합: READ-ONLY 속성은 단순히 값을 반환하는 경우에만 적합합니다. 만약 반환할 때 추가적인 계산이나 검증이 필요하다면, 별도의 메서드를 사용하는 것이 더 바람직합니다. 단순히 속성을 읽는 것 외에도 로직이 필요할 때는 READ-ONLY 대신 메서드를 고려해야 합니다.
언제 READ-ONLY를 사용해야 하는가?
- 단순한 데이터 반환의 경우: 속성이 단순히 클래스의 상태를 나타내며, 외부에서 이 값을 읽기만 하면 되는 경우 READ-ONLY를 사용하는 것이 적합합니다.
- 데이터의 불변성이 필요한 경우: 속성이 클래스 생성 후 변경되지 않고, 외부에서 수정할 필요가 없는 경우에도 READ-ONLY를 사용할 수 있습니다. 예를 들어, 생성자에서 초기화된 이후로 변경되지 않는 ID 값 같은 경우가 이에 해당됩니다.
언제 READ-ONLY를 피해야 하는가?
- 미래에 로직 추가 가능성이 있는 경우: 속성에 대한 읽기 연산이 단순하지 않고, 나중에 조건을 추가하거나 비즈니스 로직을 포함해야 할 가능성이 있는 경우에는 READ-ONLY 대신 Getter 메서드를 사용하는 것이 더 좋습니다.
- 캡슐화가 중요한 경우: 클래스의 내부 구현을 외부에 철저히 숨기고, 외부에서 내부 데이터에 직접 접근하지 못하게 해야 하는 상황에서는 READ-ONLY 사용을 피하고, 필요한 데이터만 메서드를 통해 노출하는 것이 좋습니다.
- 의존성을 줄이고 싶은 경우: 외부 코드가 클래스의 특정 속성에 의존하지 않도록 하려면, 속성을 직접 노출하지 않고, 필요한 기능을 제공하는 메서드로 대체하는 것이 바람직합니다.
EAD-ONLY는 단순한 경우나 데이터가 외부에서 수정될 필요가 없는 경우에만 사용하고, 더 복잡한 상황에서는 Getter 메서드를 통해 데이터를 제공하는 것이 좋습니다. 이를 통해 코드의 안정성을 유지하고, 확장성과 유지보수성을 고려한 설계를 할 수 있습니다.
'ABAP Clean Code' 카테고리의 다른 글
ABAP 클린 코드 - METHOD 메서드 (호출) [10-1] (0) | 2024.08.24 |
---|---|
ABAP 클린 코드 - Class 클래스 (생성자) [9-3] (0) | 2024.08.23 |
ABAP 클린 코드 - Class 클래스 (객체 지향 클래스) [9-1] (0) | 2024.08.21 |
ABAP 클린 코드 - 정규식 [8] (0) | 2024.08.20 |
ABAP 클린 코드 - IF 조건문 [7] (0) | 2024.08.19 |