2010-04-12 4 views
8

Manypeople은 기능 크기에 대해 논쟁했습니다. 그들은 일반적으로 기능이 매우 짧아야한다고 말한다. 의견은 15 줄에서 약 1 화면까지 다양합니다. 오늘은 약 40-80 줄입니다.
또한 함수는 항상 하나의 작업 만 수행해야합니다.긴 초기화 방법을 사용하는 것은 나쁜 습관입니까?

그러나 내 코드의 두 기준에서 자주 실패하는 기능 중 하나가 있습니다. 초기화 기능.

예를 들어 오디오 응용 프로그램에서 오디오 하드웨어/API를 설정하고 오디오 데이터를 적절한 형식으로 변환해야하며 개체 상태를 올바르게 초기화해야합니다. 이것은 분명히 세 가지 다른 작업이며 API에 따라 쉽게 50 줄 이상을 확장 할 수 있습니다.

init 함수는 일반적으로 한 번만 호출되므로 아무 구성 요소도 다시 사용할 필요가 없습니다. 큰 초기화 함수를 좋다고 생각한다면 몇 가지 작은 함수로 나누겠습니까?

답변

12

는 여전히 작업에 의해 기능을 파괴하고 내 공개 대면 초기화 함수 내에서 낮은 수준의 기능의 각 부를 것이다 읽을 수있는 것으로 유지합니다. 실패가 _convert_format()에있는 것을 안다면, 버그를 담당하는 ~ 40 줄을 상당히 빠르게 추적 할 수 있습니다. 하나의 기능 만 변경하는 변경 사항을 커밋하는 경우에도 동일한 작업이 적용됩니다.

마지막으로 나는 assert()을 자주 사용하므로 "자주 실패하고 일찍 실패"할 수 있으며 함수의 시작은 몇 가지 온 전성 검사 주장을위한 가장 좋은 장소입니다.기능을 짧게 유지하면 더 좁은 임무에 따라 기능을보다 철저하게 테스트 할 수 있습니다. 10 가지 다른 일을하는 400 회선 기능을 단위 테스트하는 것은 매우 어렵습니다.

+1

+1()'만. – ndim

+0

+1 : "구성 요소를 다시 사용할 필요가 없습니다." 재사용은 문제가 아닙니다. 다른 사람들이 이해하고 유지할 수있는 무언가를 쓰는 것이 훨씬 더 중요합니다. –

+0

밑줄로 시작하는 식별자를 C 컴파일러의 내부 용으로 남겨두고 프로그램에서이를 피하는 것에 관한 조언을 기억합니다. 또한 세 번의 일회성 초기화 함수를 '정적'으로 표시해야합니다. 한번은 현재 소스 파일 밖에서 사용되지 않을 것입니다. 그리고 추가적인 이점으로 스마트 컴파일러는 코드가 한 번만 호출되고 코드를 인라인합니다 (호출 오버 헤드가 걱정되는 경우). – ndim

5

더 작은 부분으로 나누면 코드가 더 잘 구조화되고 더 읽기 쉽게 만들어집니다. 기능이 무엇이든 관계 없습니다. 그것은 코드 품질에 관한 라인 수에 관한 것이 아닙니다.

2

이와 같은 상황에서 나는 개인적인 취향에 달려 있다고 생각합니다. 함수를 한 가지만 수행하도록하는 것이 더 좋기 때문에 초기화를 별도의 함수로 분할 할 수 있습니다. 단 한 번만 호출해도됩니다. 그러나 누군가가 단일 기능으로 모든 작업을 수행하기를 원한다면 (코드가 명확한 한) 너무 많이 걱정하지 않아도됩니다. (중괄호가 그들 자신의 분리 된 줄에 속하는지 여부와 같은) 논쟁 할 더 중요한 것들이 있습니다.

1

많은 구성 요소가있는 경우 서로 꽂아야 할 필요가 있습니다. 각 구성 요소의 작성이 가능한 경우 별도의 방법으로 리팩터링되는 경우에도 큰 방법을 사용하는 것이 당연합니다.

하나의 대안은 의존성 삽입 프레임 워크 (예 : Spring, Castle Windsor, Guice 등)를 사용하는 것입니다. 그건 확실한 장단점이 있습니다 ... 하나의 커다란 방법을 통해 작업하는 것은 꽤 고통 스러울 수 있습니다. 적어도 모든 것이 초기화되고, "마법"이 어떻게 진행 될지 걱정할 필요는 없습니다. . 그런 다음 다시 초기화 (예 : Spring 용 XML 파일과 같이)는 배치 후에 변경할 수 없습니다.

이 주입 될 수 있도록 코드 본문을 디자인하는 것이 좋습니다.하지만 해당 주입이 프레임 워크를 통해 수행되는지 또는 하드 코딩 된 (및 잠재적으로 긴) 초기화 호출 목록인지 여부가 결정됩니다. 다른 프로젝트에 따라 바뀔 수있는 선택. 두 경우 모두 응용 프로그램을 실행하는 것 외에는 결과를 테스트하기가 어렵습니다. 간결한 기능을 쓰는 것은 잘못과 변화를 분리에 대한 많은입니다

void _init_hardware() { } 
void _convert_format() { } 
void _setup_state() { } 

void initialize_audio() { 
    _init_hardware(); 
    _convert_format(); 
    _setup_state(); 
} 

:

3

나는 여전히 논리 단위로 기능을 해체하려고합니다. 그들은 길거나 짧아야 합당합니다. 예 :

SetupAudioHardware(); 
ConvertAudioData(); 
SetupState(); 

명확한 이름을 지정하면 모든 것이 더 직관적이며 읽기 쉽습니다. 또한이를 분리하면 향후 변경 사항 및/또는 다른 프로그램에서 쉽게 다시 사용할 수 있습니다.

1

먼저 초기화 기능 대신 공장을 사용해야합니다. 즉, initialize_audio()이 아니라 new AudioObjectFactory입니다 (더 좋은 이름을 생각해보십시오). 이것은 관심사의 분리를 유지합니다.

그러나 너무 일찍 추상화하지 않도록주의하십시오. 분명히 당신은 이미 두 가지 우려 사항이 있습니다 : 1) 오디오 초기화와 2) 그 오디오 사용. 예를 들어 초기화 할 오디오 장치 나 초기화 중에 주어진 장치를 구성 할 수있는 방법을 추상화 할 때까지 팩토리 메서드 (audioObjectFactory.Create() 또는 기타)를 실제로 하나의 큰 메서드로 유지해야합니다. 초기 추상화는 디자인을 난독 화하는 역할 만합니다.

audioObjectFactory.Create()은 단위 테스트 할 수있는 것이 아닙니다. 테스트는 통합 테스트이며, 추출 할 수있는 부분이있을 때까지 통합 테스트가 진행됩니다. 나중에 다른 구성에 대해 여러 개의 다른 공장이 있다는 것을 알 수 있습니다. 이 시점에서 하드웨어 호출을 인터페이스로 추상화하는 것이 유익 할 수 있으므로 다양한 공장에서 하드웨어를 적절한 방식으로 구성하도록 단위 테스트를 만들 수 있습니다.

+0

사실, 그게 내가하는 일입니다. 클래스 자체는 CoreAudio 인 엉망 처리를 추상화하는 오디오 플레이어 객체로 가정됩니다. 실제로, 오디오 데이터 준비와 오디오 하드웨어 초기화는 서로 다른 오디오 데이터가 다른 구성을 요구하기 때문에 매우 밀접하게 연결됩니다. – bastibe

1

줄 수를 세어보고 그에 따라 기능을 결정하는 것은 잘못된 접근이라고 생각합니다. 초기화 코드와 같은 경우에는 종종 별도의 함수가 있지만 대부분은 Load 또는 Init 또는 New 함수가 혼란스럽지 않고 혼란스럽지 않습니다. 다른 사람들이 제안한 것과 같은 몇 가지 작업으로 분리 할 수 ​​있다면 유용한 이름을 지정하고 정리하는 데 도움을 줄 수 있습니다. 한 번만 호출해도 악의적 인 습관은 아니며 종종 물건을 다시 시작하고 해당 기능을 다시 사용할 수있는 다른 시간이 있음을 알게됩니다.

1

아직 언급하지 않았기 때문에이 부분을 버릴 것이라고 생각했습니다. Facade Pattern은 종종 복잡한 하위 시스템의 인터페이스로 인용됩니다. 나는 그만큼 많이하지 않았지만, 은유는 보통 컴퓨터를 켜거나 (몇 단계가 필요함) 홈 시어터 시스템을 켜는 것과 같다. (TV 켜기, 수신기 켜기, 조명 끄기 등.)

코드 구조에 따라, 큰 초기화 기능을 추상화하려는 가치가있을 수 있습니다. 나는 그걸로 _init_X(), _init_Y(), 등으로 기능을 분해하는 것은 좋은 방법입니다 그래도 meagar의 요점에 동의합니다. 이 코드에서 주석을 재사용하지 않더라도, 다음 프로젝트에서, "어떻게 X 컴포넌트를 초기화 했습니까?"라고 스스로 말할 때, 돌아가서 선택하는 것이 훨씬 쉬울 것입니다 보다 작은 함수 _init_X()의 함수보다 큰 함수에서 선택하는 것보다 더 중요합니다. 특히 X 초기화가 그 안에 흩어져있는 경우 특히 그렇습니다.

1

기능 길이는 태그를 추가 할 때 매우 주관적인 내용입니다. 그러나 표준 최상의 방법은 자주 반복되거나 자체 엔티티로 작동 할 수있는 코드를 분리하는 것입니다. 예를 들어 초기화 함수가 특정 라이브러리에서 사용할 라이브러리 파일이나 객체를로드하는 경우 해당 코드 블록을 모듈화해야합니다.

이렇게 말하면 반복되는 많은 코드 나 추상화 될 수있는 다른 조각 때문에 오래 걸리지 않는 한 초기화 방법을 사용하는 것이 나쁘지 않습니다. 도움이

희망, 어설`에 대한
카를로스 모야

관련 문제