Apakah metode "mulai", "jalankan" atau "jalankan" adalah praktik yang baik?

30

Saat ini saya sedang mengerjakan basis kode yang memiliki banyak kelas yang menerapkan metode Mulai. Ini seperti konstruksi dua fase bagi saya, yang saya anggap sebagai praktik buruk. Saya tidak bisa membedakan antara ini dan konstruktor.

Kapan tepat menggunakan metode awal alih-alih konstruksi objek normal?

Kapan saya harus lebih suka menggunakan konstruktor?

Sunting: Saya tidak berpikir itu relevan tetapi bahasa pemrogramannya adalah C #, itu bisa juga berlaku untuk Java atau C ++

Dave Hillier
sumber
3
Bisakah Anda menambahkan lebih banyak konteks? Bahasa? Berulir vs utas tunggal? perbedaan antara startdan konstruktor? dll ...
@MichaelT Saya bisa melihat mengapa Anda bertanya, tapi saya tertarik pada prinsip umum di belakang ketika itu tepat. Saya khawatir jika saya memberikan contoh spesifik dari basis kode yang saya kerjakan, jawabannya akan terlalu terfokus pada detail dan bukan pada pertanyaan spesifik saya.
Dave Hillier
2
@DaveHillier Misalnya, dalam perl itu adalah praktik standar (dan yang bagus) untuk memiliki initmetode semacam di luar newfungsi - perldoc.perl.org/perlobj.html . Idiom dari satu bahasa dapat bekerja dengan baik di sana dan tidak dalam bahasa lain.
1
Contoh kelas dengan Startmetode dalam API umum termasuk utas dan stopwatch.
Luiscubal
1
Hitung saya di antara mereka yang membutuhkan sampel kode untuk memahami apa yang sebenarnya Anda tanyakan.
user16764

Jawaban:

44

Suatu Start()metode (suka Run(), Execute()atau yang serupa) sesuai ketika biaya membangun objek rendah, tetapi biaya menggunakannya tinggi. Sebagai contoh: Kelas yang merangkum algoritma optimasi jalur terbaik. Sepele untuk mengaturnya dengan seperangkat parameter ( Xkuadrat demi Ykuadrat, dengan metode evaluasi semacam itu), tetapi mungkin perlu beberapa saat untuk dieksekusi. Jika Anda ingin membuat 20 objek ini, Anda mungkin ingin menunda eksekusi sampai semuanya dibuat - ini memungkinkan Anda untuk memparalelkannya dengan lebih mudah, misalnya.

Atau, itu bisa berguna ketika Anda tidak tahu kapan objek akan diperlukan untuk memulai - mungkin karena itu didasarkan pada input pengguna, atau logika yang memilih dari daftar kemungkinan.

Ini mengasumsikan, tentu saja, itu Start()adalah metode yang berguna pada objek, dan bukan yang setara dengan Initialize()metode. Jika ini hanya cara tambahan untuk mengatur lebih banyak parameter, seharusnya tidak ada.

Bobson
sumber
1
Penggunaan lain untuk metode mulai adalah ketika tindakan yang dilakukan juga membuat utas pekerja baru atau timer. Konstruktor tidak boleh melakukan pengangkatan berat semacam ini atau menghasilkan efek samping yang signifikan (seperti membuat utas baru).
Ziv
50

Kode Lengkap (dan banyak sumber daya rekayasa perangkat lunak lainnya) menekankan pencocokan kelas Anda dengan objek dunia nyata. Saya percaya alasan mendasar untuk ini adalah karena hal itu membuatnya lebih mungkin bahwa Anda memiliki pemahaman yang benar tentang apa yang Anda implementasikan, daripada meretas ide yang tidak berwujud.

Jika Anda adalah pelanggan teori ini, saya tidak melihat ada yang salah dengan menambahkan Start()metode ke kelas mana pun yang seharusnya, apakah itu objek nyata, juga memiliki keadaan istirahat. Jika tidak masuk akal untuk objek Anda ada saat tidak berjalan (atau tidak masuk akal untuk objek Anda berjalan sama sekali), maka saya akan mengatakan itu adalah praktik yang buruk.

Dan Albert
sumber
16
Analogi yang bagus. Perlu dicatat bahwa Start()bisa berhubungan dengan saklar on / off (seperti lightswitch) yang kemudian harus memiliki Stop(), atau ke tombol-tekan (seperti tombol Print pada mesin fotokopi) di mana ia memulai dan kemudian berjalan sampai selesai.
Bobson
3
+1 disampaikan dengan baik dan selamat datang di P.SE, jawaban seperti ini merupakan awal yang baik.
Jimmy Hoffa
14

Anda dapat menggunakan inisialisasi malas.

Dalam pemrograman komputer, inisialisasi malas adalah taktik untuk menunda pembuatan objek, perhitungan nilai, atau beberapa proses mahal lainnya hingga pertama kali dibutuhkan.

Dengan begitu Anda menghindari penggabungan temporal, artinya konsumen kelas Anda harus memanggil metode tertentu dalam urutan tertentu. Harus menelepon start()dulu adalah cara untuk mengetahui bagaimana kelas bekerja secara internal, yang buruk karena Anda dapat mengubahnya di masa depan.

Tunda inisialisasi mahal sampai pertama kali diperlukan ..

Contoh:

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

    }
}
Tulains Córdova
sumber
5
Manfaat lain dari inisialisasi malas yang patut dicatat adalah bahwa dibutuhkan sedikit usaha untuk membentuknya menjadi proxy virtual . Bergantung pada situasinya, ini bisa sangat berguna untuk menampilkan sesuatu sambil menunggu sumber daya dimuat (terutama berguna untuk hal-hal seperti gambar jarak jauh). Berdasarkan pertanyaan awal, saya kira ini bukan tujuan OP, tapi saya pikir itu layak disebut.
Dan Albert
@DanAlbert Anda benar, bukan itu yang saya minta tetapi masih menarik
Dave Hillier