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


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.