"시작", "실행"또는 "실행"방법이 모범 사례입니까?


30

현재 Start 메서드를 구현하는 많은 클래스가있는 코드베이스에서 작업하고 있습니다. 이것은 나에게 2 단계 구조처럼 보이지만, 항상 나쁜 습관으로 간주했습니다. 이것과 생성자의 차이점을 알 수 없습니다.

일반적인 객체 구성 대신 시작 방법을 사용하는 것이 언제 적절한가요?

언제 생성자를 사용해야합니까?

편집 : 관련성이 없다고 생각하지만 프로그래밍 언어는 C #이며 Java 또는 C ++에도 동일하게 적용될 수 있습니다.


3
좀 더 컨텍스트를 추가 할 수 있습니까? 언어? 스레드 대 단일 스레드? start생성자와의 차이점은 무엇입니까? etc ...

@MichaelT 나는 왜 당신이 묻는 지 알 수 있지만, 그것이 적절할 때 뒤에있는 일반적인 원칙에 관심이 있습니다. 내가 작업중 인 코드베이스에서 특정 예제를 제공하면 답변이 세부적인 질문에 집중되지 않고 세부적인 질문에 초점을 맞출 것입니다.
Dave Hillier

2
@DaveHillier 예를 들어, perl에서는 perldoc.perl.org/perlobj.html 함수 init이외의 방법 을 사용하는 것이 표준 연습 (및 좋은 방법)입니다 . 한 언어의 관용구가 다른 언어에서는 잘 작동하지 않을 수 있습니다. new

1
Start공통 API에 메소드가있는 클래스의 예로 는 스레드 및 스톱워치가 있습니다.
luiscubal

1
실제로 요청하는 것을 이해하기 위해 코드 샘플이 필요한 사람들 중 나를 계산하십시오.
user16764

답변:


44

Start()방법 (같은 Run(), Execute()객체를 구성하는 비용이 낮지 만 비용 할 때 비슷하거나 아무것도) 적절한 사용 이 높다. 예를 들면 : 최상의 경로 최적화 알고리즘을 캡슐화하는 클래스입니다. 매개 변수 세트 ( X정사각형 Y등의 평가 방법으로) 를 설정하는 것은 쉽지 않지만 실행하는 데 시간이 걸릴 수 있습니다. 이러한 객체 중 20 개를 생성하려면 모든 객체가 생성 될 때까지 실행을 지연시킬 수 있습니다. 예를 들어 객체를 쉽게 병렬화 할 수 있습니다.

또는 객체를 언제 시작해야하는지 알지 못하는 경우 유용 할 수 있습니다. 사용자 입력 또는 가능성 목록에서 선택하는 논리를 기반으로하기 때문일 수 있습니다.

물론 이것은 Start()객체에 대한 유용한 방법이며 Initialize()방법 과 동등한 것이 아니라고 가정합니다 . 더 많은 매개 변수를 설정하는 추가 방법이라면 존재하지 않아야합니다.


1
start 메소드의 또 다른 용도는 조치가 새 작업자 스레드 또는 타이머를 작성하는 경우입니다. 생성자는 이런 종류의 무거운 작업을 수행하거나 새로운 스레드 생성과 같은 심각한 부작용을 일으키지 않아야합니다.
Ziv

50

Code Complete (및 기타 여러 소프트웨어 엔지니어링 리소스)는 클래스를 실제 객체와 일치시키는 것을 강조합니다. 나는 이것이 근본적인 이유는 그것이 무형의 아이디어를 해킹하기보다는 구현하고있는 것이 무엇인지에 대한 진실 된 이해를 가질 가능성이 있기 때문이라고 믿는다.

이 이론의 구독자 Start()라면 클래스에 메소드를 추가하는 데 아무런 문제 가 없습니다. 실제 객체이어야하고 휴식 상태 여야합니다. 실행 중이 아닌 동안 오브젝트가 존재하는 것이 의미가 없거나 (또는 ​​오브젝트가 전혀 실행되지 않는 경우) 나쁜 습관이라고 생각합니다.


16
좋은 비유입니다. 그 지적이의 가치는 Start()해당 수에 중 온 / 오프 스위치 다음을해야하는 (A lightswitch 같은) Stop(), 또는이 개막 후 완료 될 때까지 실행 (복사기에서 인쇄 버튼과 같은) 푸시 버튼.
Bobson

3
+1 잘 말하고 P.SE에 오신 것을 환영합니다. 이러한 답변은 훌륭한 시작입니다.
지미 호파

14

지연 초기화를 사용할 수 있습니다 .

컴퓨터 프로그래밍에서 게으른 초기화는 객체 생성, 값 계산 또는 기타 필요한 고가의 프로세스를 처음 필요할 때까지 지연시키는 전술입니다.

이렇게하면 시간 결합을 피할 수 있습니다. 즉, 클래스 소비자는 특정 순서로 특정 메소드를 호출해야합니다. start()먼저 전화를 거는 것은 수업이 내부적으로 어떻게 작동하는지 알아야하는 방법입니다. 이는 나중에 변경할 수 있기 때문에 나쁩니다.

비싼 초기화는 처음 필요할 때까지 연기하십시오.

예:

public class FooClass{

    private ExpensiveResource resource;
    private CheapResource cheap;

    public  FooClass(String someParameter){
        // constructor: initialize CheapResource cheap 
            // but NOT ExpensiveResource resource
    }

    public ExpensiveResource getExpensiveResource(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource
    }

    public String getExpensiveResourceName(){
        if (resource == null) {
            this.initializeExpensiveResource();     
        }
        return this.resource.getName();
    }   

    public CheapResource getCheapResource(){
        return this.cheap;
    }

    private initializeExpensiveResource(){
        // do expensive initialization of field "resource"
    }

}

public class Test{
    public static void main (String args[]){

        FooClass foo = new FooClass("some string");
        CheapResource cr = foo.getCheapResource();
        String s = foo.getExpensiveResourceName(); 
          // just now is the expensive resource initialized

    }
}

5
주목할만한 게으른 초기화의 또 다른 이점은 가상 프록시 로 구성하는 데 거의 노력이 없다는 것 입니다. 상황에 따라 리소스로드를 기다리는 동안 무언가 를 표시하는 데 매우 유용 할 수 있습니다 (특히 원격 이미지와 같은 경우에 유용). 원래의 질문에 따르면, 이것이 실제로 OP가 번창 한 것이라고 생각하지는 않지만 언급 할 가치가 있다고 생각했습니다.
Dan Albert

@ DanAlbert 당신이 맞아요 그것은 내가 요구했던 것이 아니라 여전히 흥미 롭습니다
Dave Hillier
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.