본문 바로가기
프로그래밍 놀이터/iOS

[Effecitve Objective-C] #2 헤더에 헤더를 포함하는 것을 최소화하라

by 돼지왕 왕돼지 2017. 7. 17.
반응형

 [Effecitve Objective-C] #2 헤더에 헤더를 포함하는 것을 최소화하라


출처 :  Effective Objective-C

#import, #include, .h, .m, @end, @implementation, @interface, @property, C, C++, COPY, effective objective-c, forward class declaration, Foundation, foundation.h, header, import, Include, Interface, nonatomic, Objective-C, protocol conformance, [Effecitve Objective-C] #2 헤더에 헤더를 포함하는 것을 최소화하라, 구현 파일, 상호 종속, 상호 참조, 상호 헤더 참조, 유지 보수, 인스턴스 변수, 컴파일, 컴파일 시간, 컴파일 시간 줄이기, 컴파일러, 클래스 확장 카테고리, 포워드 선언, 포워드 클래스 선언, 프로토콜, 프로토콜 따르기, 프로퍼티, 헤더



-
Objective-C 는 C, C++ 처음 헤더 파일과 구현 파일을 사용한다.
Objective-C 로 클래스를 작성할 때 쓰는 표준적인 방법은 클래스 이름 뒤에 확장자가 .h 인 헤더 파일과 .m 인 구현 파일을 생성하는 것이다.


// header
#import <Foundation/Foundation.h>

@interface EOCPerson : NSObject

@property (nonatomic, copy) NSString *nane

@end


// implementation
#import “EocPerson.h"

@implementation EOCPerson

@end


-
Foundation.h 는 Objective-C 클래스의 기본적인 녀석이다.


-
EOCPerson 에 EOCEmployer 라는 녀석을 사용하려고 할 때, 가장 흔한 방법은 EOCEmployer.h 를 import 하는 것이다.

#import “EOCEmployer.h"

그러나 이 방법은 동작은 하지만 나쁜 해결 방법이다.

EOCPerson 을 사용하는 어떤 것을 컴파일 할 때 EOCEmployer 에 대해 자세히 알 필요가 없다.
알아야 할 것은 EOCEmployer 라는 클래스가 존재하고 있다는 사실 뿐이다.
이에 대해 컴파일러에 알려줄 방법이 있다.

@class EocEmployer;

이를 “포워드 클래스 선언” 이라고 부른다.

포워드 클래스 선언을 사용하면, EOCPerson 구현 파일은 EOCEmployer 의 헤더 파일을 include해야 한다.
EOCEmployer 를 사용하기 위해 클래스의 모든 인터페이스를 자세히 알아야 하기 때문이다.


-
include 가 필요한 곳에 include 를 미루면 클래스의 사용자가 include 해야 하는 것들의 범위를 줄일 수 있다.
include 사슬이 이어지면 예상보다 훨씬 많은 헤더를 포함해야 한다.
이 때문에 컴파일 시간도 늘어날 수 있다.


-
포워드 선언을 사용하는 것은 또한 서로를 참조하는 클래스 문제를 완화할 수 있다.
서로의 헤더를 포함하는 것은 닭이 먼저냐, 달걀이 먼저냐의 문제다.
먼저 파싱되는 헤더가 파싱될 때 상대 헤더를 include 한다.
#include 가 아닌 #import 를 사용하면 무한 루프에 빠지지 않는다.
그러나 클래스 중 하나는 제대로 컴파일되지 않을 것이다.
믿지 못하겠다면 직접 시도해 보라.


-
헤더에서 다른 헤더를 include 할 필요가 있을지라도 여러분이 상속하는 상위 클래스를 정의하는 헤더를 포함해야 한다.
비슷하게 프로토콜을 선언할 때는 포워드 선언이 아닌 모든 헤더가 정의되어야 한다.
컴파일러는, 프로토콜이 포워드 선언되어 프로토콜이 존재한다는 간단한 정보가 아니라 프로토콜이 선언한 모든 메서드를 볼 수 있어야 한다.


-
헤더 파일에서 include 를 사용할 때, 정말 필요한 것인지 스스로에게 항상 질문하라.
포워드 선언이 가능하다면 그것을 사용하라.
프로퍼티, 인스턴스 변수, 프로토콜 따르기를 위해 포함하는 것이라면 클래스 확장 카테고리로 바꿀 수 있으니, 그것을 사용하라.
그렇게 하면 컴파일 시간을 최소한으로 줄이고 유지 보수가 어려워지는 상호 종속을 줄일 수 있다.
또한 퍼블릭 API 로 공개하고 싶은 코드 부분만 노출할 수 있게 한다.


-
기억할 점

     항상 헤더를 include하는 것을 최대한 미루라.
     이는 보통 헤더에 클래스를 포워드 선언하고 구현 파일에 그것과 연관된 헤더를 include 하는 것을 의미한다.
     이렇게 하면 클래스끼리 연관되는 것을 최대한 피할 수 있게 된다.

     때때로 프로토콜을 따른다는 것(protocol-conformance)을 선언할 때와 같이 포워드 선언이 불가능할 때가 있다.
     이 경우 가능하다면 프로토콜을 따르는 것을 클래스 확장 카테고리로 바꿔보라.
     그렇지 않을 경우, 할 수 있으면 프로토콜만 정의하는 헤더를 포함하라.



반응형

댓글