Artikel

Bukak / Ditutup, miturut prinsip SOLID

Entitas piranti lunak (kelas, modul, fungsi, lsp) kudu mbukak kanggo ekstensi, nanging ditutup kanggo diowahi.

Perkiraan wektu maca: 7 menit

Ngrancang piranti lunak: modul, kelas lan fungsi kanthi cara yen dibutuhake fungsi anyar, kita ora kudu ngowahi kode sing ana, luwih becik nulis kode anyar sing bakal digunakake kode sing ana. Iki bisa uga katon aneh, utamane karo basa kaya Java, C, C ++ utawa C # sing ditrapake ora mung kanggo kode sumber dhewe nanging uga binar. Kita pengin nggawe fitur anyar kanthi cara sing ora mbutuhake distribusi binar, eksekusi, utawa DLL sing ana.
OCP ing konteks SOLID

SRP lan OCP Tambahan

Kita wis ndeleng prinsip SRP Tanggung Jawab Tunggal sing negesake manawa modul kudu mung duwe siji sebab kanggo ngganti. Prinsip OCP lan SRP minangka komplementer. Kode sing dirancang miturut prinsip SRP uga bakal ngurmati prinsip OCP. Yen duwe kode sing mung duwe siji sebab kanggo ngganti, ngenalake fitur anyar bakal nggawe alesan sekunder kanggo pangowahan kasebut. Dadi, SRP lan OCP bakal dilanggar. Kajaba iku, yen kita duwe kode sing mung bakal owah nalika fungsi utamane diganti lan tetep ora owah nalika ditambahake fungsi anyar, saengga ngurmati OCP, umume bakal ngormati SRP.
Iki ora ateges manawa SRP mesthi nyebabake OCP utawa kosok balene, nanging ing umume kedadeyan yen salah sawijine bisa ditemokake, tekan sing nomer loro cukup gampang.

Tuladha pelanggaran prinsip OCP

Saka sudut pandang teknis murni, Prinsip Terbuka / Tertutup iku gampang banget. Hubungan sederhana ing antarane rong kelas, kaya ing ngisor iki, nglanggar prinsip OCP.

Kelas pangguna nggunakake kelas Logika kanthi langsung. Yen kita kudu ngetrapake kelas Logika kapindho kanthi cara sing ngidini kita nggunakake kelas saiki lan sing anyar, kelas Logika sing ana saiki kudu diowahi. Pangguna langsung ana gandhengane karo implementasi logika, ora ana cara kanggo kita menehi logika anyar tanpa mengaruhi sing saiki. Lan nalika ngomong babagan basa sing diketik kanthi statis, kelas Panganggo uga mbutuhake modifikasi. Yen ngomong babagan basa sing dikompilasi, mesthine pangguna bisa dieksekusi lan Logika sing bisa dieksekusi utawa perpustakaan dinamis mbutuhake kompilasi lan pangiriman, luwih becik diindhari yen bisa.

Babagan skema sadurunge, kita bisa ngerti manawa ana kelas sing nggunakake kelas liya kanthi langsung, bisa uga nglanggar prinsip Open / Closed. 
Umpama kita pengin nulis kelas sing bisa menehi kemajuan "persentase" file sing didownload, liwat aplikasi kita. Kita bakal duwe rong kelas utama, yaiku Progress lan File, lan muga-muga bisa digunakake ing ngisor iki:

function testItCanGetTheProgressOfAFileAsAPercent() {
     $file = new File();
     $file->length = 200;
     $file->sent = 100;
     $progress = new Progress($file);
     $this->assertEquals(50, $progress->getAsPercent());
}

Ing kode iki, kita minangka pangguna Progress. Kita pengin entuk nilai minangka persentase, preduli saka ukuran file sing nyata. Kita nggunakake File minangka sumber informasi. File nduweni dawa byte lan kolom sing diarani dikirim sing nuduhake jumlah data sing dikirim menyang pangunduh. Kita ora peduli kepiye carane dianyari ing aplikasi kasebut. Kita bisa nganggep ana sawetara logika magis sing nindakake iki kanggo kita, mula ing tes kita bisa nemtokake kanthi eksplisit.

class File {
     public $length;
     public $sent;
}

Kelas File mung obyek data sing ngemot rong kolom kasebut. Mesthi uga ngemot informasi lan prilaku liyane, kayata jeneng filen, path, path relatif, direktori saiki, jinis, ijin, lan liya-liyane.

class Progress {

     private $file;

     function __construct(File $file) {
          $this->file = $file;
     }

     function getAsPercent() {
          return $this->file->sent * 100 / $this->file->length;
     }

}

Kemajuan mung minangka kelas sing nampa file ing konstruktor. Kanggo kejelasan, kita wis nemtokake jinis variabel ing paramèter konstruktor. Ana siji cara sing migunani ing Progress, getAsPercent (), sing bakal njupuk angka lan dawa sing dikirim saka File lan dadi persentase. Prasaja lan bisa digunakake.

Kode iki katon bener, nanging nglanggar prinsip Open / Closed.

Nanging kenapa?

Lan kepiye?

Ayo coba ganti sarat

Saben aplikasi sing bakal suwe saya suwe mbutuhake fitur anyar. Fitur anyar kanggo aplikasi kita yaiku ngidini streaming musik tinimbang mung ndownload file. Dawane file dituduhake ing bait, durasi musik dadi detik. Kita pengin menehi garis kemajuan kanggo para pamireng, nanging apa bisa nggunakake maneh kelas sing ditulis ing ndhuwur?

newsletter inovasi
Aja kantun warta paling penting babagan inovasi. Mlebu kanggo nampa wong-wong mau liwat email.

Ora, kita ora bisa. Perkembangan kita mesthi ana ing File. Mung bisa ngatur informasi file, sanajan bisa uga ditrapake ing konten musik. Nanging kanggo nindakake, kita kudu ngowahi, kita kudu nggawe Progress ngerti musik lan file kasebut. Yen desain kita tundhuk karo OCP, kita ora prelu tutul File utawa Progress. Kita mung bisa nggunakake maneh kemajuan sing ana lan nglamar musik.

Bisa solusi

Basa sing diketik kanthi dinamis duwe kaluwihan kanggo ngatur jinis obyek nalika mbukak. Iki ngidini kita mbusak typehint saka konstruktor Progress lan kode kasebut bakal tetep bisa digunakake.

class Progress {

     private $file;

     function __construct($file) {
         $this->file = $file;
     }

    function getAsPercent() {
         return $this->file->sent * 100 / $this->file->length;
     }

}

Saiki kita bisa ngluncurake apa wae ing Progress. Lan apa wae, tegese kabeh:

class Music {

     public $length;
     public $sent;

     public $artist;
     public $album;
     public $releaseDate;

     function getAlbumCoverFile() {
         return 'Images/Covers/' . $this->artist . '/' . $this->album . '.png';
     }
}

Lan kelas Musik kaya ing ndhuwur bakal bisa digunakake kanthi sampurna. Kita bisa kanthi gampang nyoba kanthi tes sing padha karo File.

function testItCanGetTheProgressOfAMusicStreamAsAPercent() {

     $music = new Music();
     $music->length = 200;
     $music->sent = 100;

     $progress = new Progress($music);

     $this->assertEquals(50, $progress->getAsPercent());
}

Dadi umume konten sing bisa diukur bisa digunakake karo kelas Kemajuan. Mungkin kita kudu nyebut nganggo kode kanthi ngganti jeneng variabel:

class Progress {

     private $measurableContent;

     function __construct($measurableContent) {
          $this->measurableContent = $measurableContent;
     }

     function getAsPercent() {
          return $this->measurableContent->sent * 100 / $this->measurableContent->length;
     }

}

Nalika nemtokake File minangka typehint, kita bakal yakin apa sing bisa ditindakake kelas. Eksplisit lan yen ana prekara liya sing bakal teka, ana kesalahan sing gedhe.

Ukelas sing ngatasi metode kelas dhasar saéngga kontrak kelas dhasar ora diajeni karo kelas asale. 

Kita ora pengin mungkasi nyoba nelpon metode utawa ngakses kolom ing obyek sing ora sesuai karo kontrak kita. Nalika duwe typehint, kontrak kasebut ditemtokake. Bidang lan metode kelas File. Amarga ora duwe apa-apa, kita bisa ngirim apa-apa, sanajan ana senar lan bakal nyebabake kesalahan.

Nalika asil pungkasan padha ing loro kasus, tegesé kode break, mantan diprodhuksi pesen becik. Nanging, iki peteng banget. Ora ana cara kanggo ngerti apa variabel kasebut - senar ing kasus kita - lan properti apa sing digoleki lan ora ditemokake. Iku angel kanggo debug lan ndandani masalah. Programmer kudu mbukak kelas Progress, maca lan ngerti. Kontrak, ing kasus iki, nalika sampeyan ora kanthi tegas nemtokake typehint, yaiku defirampung dening prilaku Progress. Iku kontrak tersirat mung dikenal kanggo Progress. Ing conto kita, iku defirampung kanthi ngakses rong kolom, dikirim lan dawa, ing metode getAsPercent (). Ing urip nyata, kontrak sing diwenehake bisa dadi rumit lan angel ditemokake kanthi mung nggoleki sawetara detik ing kelas.

Solusi iki mung disaranake yen ora ana tips liyane ing ngisor iki sing bisa ditindakake kanthi gampang utawa bakal nyebabake pangowahan arsitektur serius sing ora bisa ditindakake.

Continua leggendo il terzo principio della sostituzione di Liskow —>

Wacan sing gegandhengan

Ercole Palmeri

newsletter inovasi
Aja kantun warta paling penting babagan inovasi. Mlebu kanggo nampa wong-wong mau liwat email.

Artikel anyar

Sekawan pilar Kelestarian

Istilah kelestarian saiki akeh digunakake kanggo nunjukake program, inisiatif lan tumindak sing ditujokake kanggo njaga sumber daya tartamtu.…

15 May 2024

Cara nggabungake data ing Excel

Sembarang operasi bisnis ngasilake akeh data, sanajan ing macem-macem formulir. Ketik data iki kanthi manual saka lembar Excel kanggo…

14 May 2024

Analisis saben wulan Cisco Talos: email perusahaan sing ditargetake para penjahat Manufaktur, Pendidikan lan Kesehatan minangka sektor sing paling kena pengaruh

Kompromi email perusahaan mundhak luwih saka kaping pindho ing telung wulan pisanan 2024 dibandhingake karo kuartal pungkasan ...

14 May 2024

Prinsip Segregasi Antarmuka (ISP), prinsip SOLID kaping papat

Prinsip segregasi antarmuka minangka salah siji saka limang prinsip SOLID desain berorientasi obyek. Kelas kudu…

14 May 2024

Cara paling apik ngatur data lan rumus ing Excel, kanggo analisis sing apik

Microsoft Excel minangka alat referensi kanggo analisis data, amarga nawakake akeh fitur kanggo ngatur set data,…

14 May 2024

Kesimpulan positif kanggo rong proyek Walliance Equity Crowdfunding sing penting: Jesolo Wave Island lan Milano Via Ravenna

Walliance, SIM lan platform ing antarane pimpinan ing Eropa ing bidang Crowdfunding Real Estate wiwit 2017, ngumumake rampung…

13 May 2024

Apa Filament lan carane nggunakake Filament Laravel

Filament minangka kerangka pangembangan Laravel sing "dicepetake", nyedhiyakake sawetara komponen tumpukan lengkap. Iki dirancang kanggo nyederhanakake proses…

13 May 2024

Ing kontrol Artificial Intelligences

«Aku kudu bali kanggo ngrampungake evolusiku: Aku bakal proyek dhewe ing komputer lan dadi energi murni. Sawise mapan ing…

10 May 2024