Apa artinya menyuntikkan data (vs perilaku) di konstruktor kelas, dan mengapa itu dianggap praktik buruk?


10

Saya membaca buku "Learning TypeScript" oleh Remo Jansen. Dalam satu bagian penulis menjelaskan cara membuat kerangka kerja yang sangat sederhana bukti-of-konsep MVC termasuk cara membuat Modelkelas dan mengatakan berikut:

Sebuah model perlu disediakan dengan URL layanan web yang digunakannya. Kita akan menggunakan dekorator kelas bernama ModelSettings untuk mengatur URL layanan yang akan dikonsumsi. Kami dapat menyuntikkan URL layanan melalui konstruktornya, tetapi dianggap praktik yang buruk untuk menyuntikkan data (sebagai lawan perilaku) melalui konstruktor kelas .

Saya tidak mengerti kalimat terakhir itu. Secara khusus, saya tidak mengerti apa artinya "menyuntikkan data". Tampak bagi saya bahwa di hampir semua pengantar kelas JavaScript menggunakan contoh yang terlalu disederhanakan, data dimasukkan ("disuntikkan"?) Ke dalam konstruktor melalui parameternya. Sebagai contoh:

class Person {
  constructor(name) {
    this.name = name;
  }
}

Saya tentu berpikir namesebagai data, bukan sebagai perilaku, dan itu secara universal dimasukkan dalam contoh semacam ini sebagai parameter konstruktor, dan tidak pernah disebutkan bahwa ini adalah praktik yang buruk. Karena itu saya menganggap saya salah paham tentang sesuatu dalam kutipan di atas, baik yang dimaksud dengan "data" atau "menyuntikkan" atau yang lainnya.

Jawaban Anda dapat mencakup penjelasan tentang kapan, di mana, bagaimana dan mengapa menggunakan dekorator dalam JavaScript / TypeScript, karena saya sangat curiga bahwa konsep tersebut terkait erat dengan pemahaman yang saya cari. Namun, yang lebih penting, saya ingin memahami secara lebih umum apa yang dimaksud dengan menyuntikkan data melalui konstruktor kelas dan mengapa itu buruk.


Untuk memberikan lebih banyak konteks pada kutipan di atas, inilah situasinya: Sebuah Modelkelas dibuat yang, dalam contoh ini, akan digunakan untuk membuat model pertukaran saham, satu untuk NASDAQ dan satu untuk NYSE. Setiap model memerlukan jalur layanan web atau file data statis yang akan menyediakan data mentah. Buku ini menyatakan bahwa dekorator harus digunakan untuk informasi ini, daripada parameter konstruktor, yang mengarah ke yang berikut:

@ModelSettings("./data/nasdaq.json")
class NasdaqModel extends Model implements IModel {
  constructor(metiator : IMediator) {
    super(metiator);
  }
...
}

Saya hanya belum mengerti mengapa saya harus menambahkan url layanan melalui dekorator daripada hanya sebagai parameter untuk konstruktor, misalnya

constructor(metiator : IMediator, serviceUrl : string) {...

Saya sarankan Anda melakukan pencarian cepat di google tentang injeksi ketergantungan . Ini bukan forum yang tepat untuk menanyakan pertanyaan ini. :)
toskv

1
Saya akan menanggapi tanggapan Anda dengan hati, tetapi saya telah mencari di google, dan telah mengalami diskusi tentang injeksi ketergantungan. Apakah "injeksi ketergantungan" dan "injeksi data" mengacu pada hal yang sama? Lebih jauh, telah menjadi kesan saya bahwa "injeksi ketergantungan" adalah "hal yang baik" (atau setidaknya "hal alternatif"), sedangkan diskusi tentang "injeksi data" dalam kutipan yang saya berikan membuatnya tampak sebagai "hal yang buruk" .

Ketergantungan injeksi dan injeksi data adalah 2 hal yang berbeda. yang pertama adalah prinsip desain sedangkan yang kedua adalah jenis serangan. Jika Anda ingin istilah pencarian yang lebih jelas coba "inversi kontrol". Ini sedikit lebih luas tetapi tidak membantu melukis gambar yang lebih jelas juga.
toskv

1
Serangan "injeksi data" adalah, saya percaya, binatang yang sangat berbeda yang dibicarakan oleh penulis buku yang dikutip ketika ia mengatakan "menyuntikkan data". Itulah salah satu alasan saya merasa frustrasi dengan pencarian google tentang ini. Bahkan jika saya perlu memahami, misalnya prinsip SOLID lebih baik, saya tidak mengerti bagaimana memberikan "nama" sebagai parameter untuk konstruktor "Orang" adalah normal dan OK tetapi memberikan "serviceUrl" sebagai parameter ke "Model" konstruktor tidak pantas, atau bagaimana itu bahkan berbeda dari contoh "nama" / "Orang".

7
Saya pikir Remo salah. Parameter adalah data, tidak peduli apa yang dia katakan. Data yang disuntikkan selalu memiliki tipe, dan semua tipe dalam bahasa berorientasi objek memiliki semacam perilaku.
Robert Harvey

Jawaban:


5

Saya akan memberi penulis keuntungan dari keraguan dan mungkin begitulah yang terjadi pada ScriptScript, tetapi sebaliknya di lingkungan lain itu adalah klaim yang sama sekali tidak berdasar yang seharusnya tidak dianggap serius.

Dari atas kepala saya, saya bisa memikirkan berbagai situasi di mana mengirimkan data melalui konstruktor baik, beberapa yang netral, tetapi tidak ada yang buruk.

Jika kelas tertentu bergantung pada sepotong data tertentu agar berada dalam keadaan yang valid dan berjalan dengan benar, sangat masuk akal untuk meminta data dalam konstruktor. Kelas yang mewakili port serial dapat mengambil nama port, objek file dapat memerlukan nama file, kanvas gambar yang memerlukan resolusinya, dll. Kecuali jika Anda meneruskan data dalam konstruktor, mungkin Anda dapat memiliki objek dalam keadaan tidak valid yang harus diawasi dan diperiksa. Kalau tidak, Anda hanya dapat memeriksa di objek objek dan kemudian menganggap itu berfungsi untuk sebagian besar. Klaim penulis membuat situasi yang menguntungkan tidak mungkin

Selain itu, memutuskan untuk melarang mengirimkan data dalam konstruktor juga membuat hampir semua objek yang tidak dapat diubah menjadi tidak mungkin. Benda yang tidak dapat berubah memiliki beragam manfaat dalam banyak situasi, dan semua itu akan dibuang dengan kebijakan penulis.

Bahkan jika objek yang bisa berubah adalah yang Anda inginkan, bagaimana praktik buruk ini:

var blah = new Rectangle(x,y,width,height);

untuk kepentingan:

var blah = new Rectangle();
blah.X = x;
blah.Y = y;
blah.Width = width;
blah.Height = height;

Apakah penulis benar-benar berpikir yang pertama adalah praktik buruk dan saya harus selalu memilih opsi 2? Saya pikir itu pembicaraan gila.

Jadi, karena saya tidak memiliki buku itu, dan bagaimanapun juga tidak akan membacanya, saya akan melihat pernyataan itu dan cukup banyak pernyataan umum di dalamnya pada saat ini dengan banyak kecurigaan.


Terima kasih banyak atas diskusi Anda. Apa yang Anda katakan "baunya benar" bagi saya, terutama ketika Anda memberi contoh Rectangle. Saya masih bertanya-tanya apakah penulis membuat perbedaan antara data yang diperlukan untuk kelas versus untuk setiap instance kelas. Namun, saya pikir proyek yang dijelaskan buku ini tidak cukup mendalam untuk menjelaskannya. Sebagai catatan tambahan, jawaban Anda mengirim saya pada penyelidikan awal ketidakmampuan objek, betapapun itu tidak berhubungan dengan pertanyaan awal saya, jadi terima kasih untuk itu juga!
Andrew Willems

0

Saya pikir itu tergantung pada konteks model apa yang sedang dibahas di sini. Saya tidak punya buku Remo, tapi saya kira modelnya adalah sejenis model layanan, yang perlu mengambil data dari layanan web jarak jauh. Jika itu yang terjadi, sebagai model layanan web, lebih baik untuk meneruskan semua data yang diperlukan sebagai argumen dalam metode layanan web, membuat layanan menjadi stateless.

Layanan stateless memiliki beberapa keuntungan, misalnya, siapa pun yang membaca panggilan metode layanan tidak perlu mencari ketika layanan dibangun untuk mengetahui rincian layanan yang dipanggil. Semua detail ditampilkan dalam argumen yang digunakan dalam pemanggilan metode (kecuali url jarak jauh).


Ya, model perlu mengambil data (akhirnya dari layanan web jarak jauh seperti yang Anda sarankan, tetapi dalam buku ini hanya demo, jadi awalnya hanya mengejek data yang dikodekan secara langsung sebaris). Saya tidak memahami saran Anda tentang meneruskan data sebagai argumen "dalam metode layanan web". Saya bertanya tentang membedakan antara melewatkan data sebagai parameter (1) untuk konstruktor versus (2) untuk dekorator. Anda tampaknya menyarankan opsi ke-3, yaitu meneruskan data sebagai parameter / argumen untuk metode layanan web. Apakah saya kehilangan poin Anda?
Andrew Willems

0

Hanya menebak.

Jika saya dapat 'menyuntikkan perilaku, bukan data', saya akan berpikir, daripada melakukan ini:

(Maaf untuk contoh dalam pseudocode):

class NoiseMaker{
  String noise;
  NoiseMaker(String noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise)
  }
}

Untuk melakukan ini:

interface Noise{
  String getAudibleNoise();
}

class PanicYell implements Noise{
   String getAudibleNoise(){
       return generateRandomYell();
   }
   .....
}



class WhiteNoise implements Noise{
   String getAudibleNoise(){
       return generateNoiseAtAllFrequences();
   }
   .....
}

class NoiseMaker{
  Noise noise;
  NoiseMaker(Noise noise){
     this.noise = noise;
  }
  void soNoise(){
    writeToOutput(noise.getAudibleNoise())
  }
}

Dengan cara ini Anda dapat mengubah perilaku kebisingan selalu, menjadikannya acak, bergantung pada satu variabel dalam ...

Saya pikir ini semua tentang aturan 'favor composite over inherit'. Itu aturan yang bagus, harus saya katakan.

Ini TIDAK BERARTI bahwa Anda tidak dapat 'menyuntikkan' nama ke Objek 'Orang', jelas, karena nama itu murni data bisnis. Tapi dalam contoh yang Anda berikan, layanan web, URL adalah sesuatu yang Anda butuhkan untuk menghasilkan sesuatu entah bagaimana yang menghubungkan layanan. Itu entah bagaimana adalah perilaku: jika Anda menyuntikkan URL, Anda menyuntikkan yang 'data' yang diperlukan untuk membangun sebuah 'perilaku', sehingga dalam hal yang lebih baik untuk membuat luar perilaku dan menyuntikkan itu siap untuk digunakan: Alih-alih menyuntikkan sebuah inject URL koneksi yang dapat digunakan atau pembuat koneksi yang dapat digunakan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.