Ini adalah bagian kedua dan terakhir dari lembar contekan singkatan saya yang harus diketahui oleh pengembang C ++. C ++ disebutkan di sini hanya karena saya membuat lembar cheat terutama untuk diri saya sendiri, dan saya hanya pengembang C ++ yang sama.
Bahkan, bagian ini berisi konsep-konsep yang ruang lingkupnya tidak terbatas pada C ++. Jadi seleksi mungkin menarik bagi khalayak yang lebih luas.

Seperti pada bagian
pertama , singkatan dikelompokkan, jika itu masuk akal. Jika tidak masuk akal, mereka terdaftar berdasarkan abjad.
Konkurensi dan operasi atom:•
CAS•
ABA•
FAA•
RCUPenyimpanan data:•
ASAM•
CAP•
PACELC•
DASARPrinsip Pengembangan Perangkat Lunak:•
KERING•
KISS•
YAGNI•
NIH•
FTSE•
GRASP•
SOLIDLainnya:•
ABI•
SAPI•
FBC, FBCP•
LRUOperasi Konkurensi dan Atom
Cas
Bandingkan dan Tukar. Perbandingan dengan pertukaran. Ini adalah instruksi atom dengan tiga argumen: variabel atom atau alamat memori, nilai yang diharapkan, nilai baru. Jika dan hanya jika nilai variabel cocok dengan nilai yang diharapkan, variabel menerima nilai baru dan instruksi berhasil diselesaikan.
CAS hanya mengembalikan nilai Boolean (dan kemudian dapat disebut Bandingkan dan Set), atau jika gagal,
CAS juga mengembalikan nilai saat ini dari argumen pertama.
Kode palsubool cas(int* addr, int& expected, int new_value) { if (*addr != expected) { expected = *addr; return false; } *addr = new_value; return true; }
Dalam C ++,
CAS diwakili oleh
std::atomic<T>::compare_exchange_weak
metode
std::atomic<T>::compare_exchange_weak
,
std::atomic<T>::compare_exchange_strong
dan fungsi bebas
std::atomic_compare_exchange_weak
,
std::atomic_compare_exchange_strong
. Perbedaan antara
* lemah dan
* kuat adalah bahwa yang pertama dapat menghasilkan hasil negatif palsu. Yaitu jika nilainya diharapkan, mereka akan mengembalikan
false
dan tidak akan menggantinya dengan yang baru. Alasan keberadaan
* operasi
lemah adalah bahwa pada beberapa arsitektur
* kuat relatif mahal. Dalam kebanyakan kasus, instruksi
CAS berputar dalam satu loop (disebut loop CAS), jadi menggunakan
* lemah sebagai ganti
* kuat tidak akan mengubah logika, tetapi itu dapat meningkatkan kinerja.
Instruksi
CAS digunakan untuk mengimplementasikan primitif sinkronisasi (seperti mutex dan semaphores) dan algoritma bebas kunci. Seringkali menyebabkan masalah
ABA .
Baca lebih lanjut:
sekali (Rusia) ,
dua (Inggris)ABA
Masalah ABA. Masalah ABA. Masalah ini muncul dalam algoritma paralel berdasarkan perbandingan dengan pertukaran (lihat
CAS ), misalnya, dalam algoritma bebas kunci. Intinya adalah bahwa thread membaca nilai variabel atom, melakukan sesuatu yang lain dan memperbarui variabel ini melalui perbandingan dengan pertukaran. Yaitu logika aliran adalah sebagai berikut: jika variabel masih berisi nilai sebelumnya, maka tidak ada yang berubah, semuanya dalam urutan. Tapi ini mungkin tidak benar. Deskripsi masalah yang lebih formal:
- thread 1 membaca nilai variabel, sama dengan A
- utas 1 sedang dipaksa keluar, utas 2 sedang dimulai
- thread 2 mengubah nilai variabel dari A ke B, membuat banyak perubahan (mengubah beberapa nilai yang terkait dengan variabel atau hanya membebaskan memori), dan sekali lagi mengubah nilai - dari B ke A
- utas 1 melanjutkan operasi, membandingkan nilai yang diperoleh sebelumnya dengan yang sekarang dan menyimpulkan bahwa tidak ada yang berubah
Kemungkinan solusi untuk masalah ini:
- Yang paling sederhana dan paling jelas adalah menggunakan kunci. Ini akan menghasilkan algoritma thread-safe yang biasa dengan bagian kritis. Tapi itu akan berhenti menjadi bebas dari kunci. Tetapi jika datang ke CAS dan ABA , maka ini kemungkinan besar bukan pilihan.
- Tambahkan label khusus ke nilai yang dibandingkan. Misalnya, penghitung jumlah perubahan. Di satu sisi, penghitung ini mungkin meluap, tetapi di sisi lain, prosesor x86_64 modern mendukung operasi CAS 128-bit. Yaitu ketika membandingkan pointer ke penghitung, Anda dapat memberikan hingga 64 bit, dan seseorang memperkirakan bahwa ini cukup untuk operasi algoritma yang berkelanjutan selama 10 tahun.
- Beberapa arsitektur (ARM, misalnya) menyediakan instruksi LL / SC (load linked, store conditional) yang tidak hanya memungkinkan Anda untuk mendapatkan nilai alamat saat ini dalam memori, tetapi juga untuk memahami apakah nilai ini telah berubah sejak pembacaan terakhir.
Untuk menggunakan struktur data seperti tumpukan, daftar, atau antrian, yang bebas dari penguncian, secara umum, di mana ada risiko tetap dengan pointer menggantung ke node jarak jauh, ada seluruh keluarga solusi untuk masalah
ABA berdasarkan pada penghapusan node yang ditangguhkan. Ini termasuk pengumpul sampah, penunjuk bahaya dan mekanisme baca-modifikasi-tulis (lihat
RCU ).
Baca lebih lanjut:
satu (Rusia) ,
dua (Inggris) ,
tiga (Inggris)FAA
Ambil dan Tambah. Ahem ... dapatkan dan tambahkan (sepertinya konsep ini tidak pernah diterjemahkan ke dalam bahasa Rusia). Operasi atom dengan dua argumen: variabel atom atau alamat di memori, dan nilai yang harus diubah oleh variabel ini. Jika arsitektur memungkinkan, operasi mengembalikan nilai sebelumnya dari variabel yang diubah (x86 memungkinkan sejak i486). Tidak seperti
CAS ,
FAA selalu berhasil.
Kode palsu int faa(int* addr, int diff) { int value = *addr; *addr = value + diff; return value; }
Dalam C ++, ini diimplementasikan sebagai keluarga metode
std::atomic<T>::fetch_add
,
fetch_sub
,
fetch_and
,
fetch_or
,
fetch_xor
dan fungsi bebas yang sesuai
std::atomic_fetch_add
, dll.
Sesuai instruksi atom,
FAA digunakan dalam implementasi primitif sinkronisasi dan algoritma kunci-bebas dan struktur data.
Baca lebih lanjut:
sekali (Rusia) ,
dua (Inggris)RCU
Baca-Salin-Perbarui. Baca-modifikasi-tulis. Ini adalah mekanisme non-pemblokiran untuk menyinkronkan akses ke struktur data (tentu saja bebas-penguncian). Ini digunakan dalam kasus di mana kecepatan membaca sangat penting. Ini adalah contoh dari tradeoff waktu dan memori (space-time tradeoff).
Gagasan
RCU adalah bahwa aliran penulis tidak mengubah data di tempat, tetapi membuat salinan, membuat perubahan yang diperlukan di dalamnya dan secara atomis menukar data saat ini dan salinan yang diubah. Pada saat yang sama, utas pembaca terus-menerus memiliki akses ke data - lama atau baru, siapa pun yang punya waktu. Ketika tidak ada pembaca yang tersisa bekerja dengan versi yang sudah ketinggalan zaman, penulis menghapus data yang tidak lagi diperlukan, membebaskan memori.
RCU yang sangat disederhanakan berfungsi seperti ini:
- Banyak pembaca, satu penulis.
- Membaca dan mengubah terjadi secara bersamaan.
- Pembaca menggunakan sinkronisasi yang sangat ringan. Bahkan, pembaca hanya perlu memberi tahu penulis pada saat memasuki bagian kritis dan pada saat meninggalkannya. Bekerja dengan data yang disinkronkan hanya terjadi di bagian kritis.
- Penulis, segera setelah secara atomik mengganti data dengan salinan, mengumumkan permulaan dari apa yang disebut periode rahmat (grace period). Masa tenggang berakhir ketika semua pembaca yang berada di bagian kritis pada awal periode ini meninggalkan bagian kritis mereka. Sekarang penulis dapat dengan aman menghapus data yang sudah usang. Tersirat bahwa semua bagian kritis terbatas, yang menjamin terbatasnya masa tenggang.
RCU sangat bagus untuk data yang sering dibaca dan jarang diperbarui. Mekanisme ini secara aktif digunakan dalam kernel Linux, di mana cukup mudah untuk menentukan kapan masa tenggang berakhir.
Kekurangan:
- Buruk untuk menyinkronkan akses ke data yang sering diubah.
- Sulit diimplementasikan di ruang pengguna.
- Tergantung pada kemampuan untuk mengubah pointer secara atom ke alamat dalam memori, tetapi tidak semua arsitektur menyediakan kemampuan ini.
Baca lebih lanjut:
sekali (Rusia) ,
dua (Inggris)Penyimpanan data
ASAM
Atomicity, Konsistensi, Isolasi, Daya Tahan. Atomicity, konsistensi, isolasi, daya tahan. Ini adalah seperangkat persyaratan transaksi dalam DBMS.
ACID menyediakan operasi DBMS yang andal dan dapat diprediksi bahkan jika terjadi kesalahan.
- Atomicity memastikan bahwa transaksi selesai atau tidak melakukan apa-apa. Keadaan perantara tidak mungkin, tidak akan seperti satu operasi transaksi berhasil, dan yang lainnya tidak. Semua atau tidak sama sekali.
- Konsistensi memastikan bahwa semua data dalam database memenuhi semua aturan dan batasan yang ditentukan baik sebelum dimulainya transaksi dan setelah penyelesaiannya. Selama pelaksanaan transaksi, konsistensi dapat dilanggar.
- Isolasi memastikan transaksi bersamaan tidak saling mempengaruhi. Tidak ada transaksi yang memiliki akses ke data tidak konsisten yang diproses oleh transaksi lain.
- Daya tahan berarti bahwa hasil transaksi yang berhasil disimpan dalam database dan tidak dapat hilang, tidak peduli apa yang terjadi pada database segera setelah transaksi selesai.
Semua DBMS relasional utama sepenuhnya mendukung
ACID . Di dunia NoSQL, dukungan penuh seperti itu kemungkinan besar merupakan pengecualian.
Baca lebih lanjut: satu
kali (bahasa Inggris) ,
dua (bahasa Inggris)Cap
Teorema CAP. Teorema CAP. Teorema menyatakan bahwa setiap sistem terdistribusi dapat memiliki tidak lebih dari dua properti dari daftar: konsistensi data (
Konsistensi ), ketersediaan (
Ketersediaan ), ketahanan terhadap pemisahan (
Toleransi partisi ).
- Konsistensi dalam hal ini berarti konsistensi konsisten (disederhanakan). Yaitu segera setelah operasi pembaruan data pada satu node selesai dengan sukses, semua node lain sudah memiliki data yang diperbarui ini. Dengan demikian, semua node dalam keadaan konsisten. Ini bukan konsistensi yang disyaratkan oleh ACID .
- Ketersediaan berarti bahwa setiap simpul yang gagal mengembalikan jawaban yang benar untuk setiap permintaan (baik untuk membaca dan menulis) dalam jumlah waktu yang wajar. Tidak ada jaminan bahwa tanggapan dari node yang berbeda cocok.
- Perlawanan terhadap pemisahan berarti bahwa sistem akan terus bekerja dengan benar jika terjadi kehilangan jumlah pesan yang sewenang-wenang di antara simpul-simpulnya.
Karena ketiga sifat tidak dapat dicapai, dari sudut pandang teorema
CAP , semua sistem terdistribusi jatuh ke dalam tiga kelas:
CA ,
CP, dan
AP . Sistem
CA jelas tidak memiliki resistensi pemisahan. Karena dalam sebagian besar kasus, distribusi menyiratkan distribusi melalui jaringan nyata, dan dalam jaringan nyata selalu ada probabilitas nol untuk kehilangan suatu paket, maka sistem
CA kurang menarik.
Pilihannya adalah antara
CP dan
AP , yaitu antara konsistensi dan ketersediaan. DBMS relasional tradisional yang mengikuti prinsip
ACID lebih memilih konsistensi. Sementara banyak solusi NoSQL memilih aksesibilitas dan
BASE .
Dalam kasus operasi normal jaringan, yaitu, ketika tidak ada pemisahan jaringan, teorema
CAP tidak memaksakan pembatasan pada konsistensi dan ketersediaan. Yaitu menyumbangkan sesuatu tidak perlu.
Baca lebih lanjut:
satu (Rusia) ,
dua (Inggris) ,
tiga (Inggris)Pacelc
Teorema PACELC. Teorema PACELC. Ini adalah perpanjangan dari teorema
CAP , yang menyatakan bahwa sistem terdistribusi dalam kasus
Pemisahan terpaksa memilih antara
Ketersediaan dan
Konsistensi , dan dalam kasus operasi jaringan normal (
Lain ), Anda harus memilih antara
Latensi dan
Konsistensi )
Dengan demikian, jika teorema
CAP membedakan 2 kelas sistem yang stabil dengan pemisahan jaringan, maka
PACELC memiliki 4 di antaranya:
PA / EL ,
PA / EC ,
PC / EL dan
PC / EC . Beberapa database NoSQL dapat mengubah kelas mereka tergantung pada pengaturan.
Baca lebih lanjut:
sekali (Rusia) ,
dua (Inggris)DASAR
Pada dasarnya Tersedia, Status lunak, Konsistensi akhirnya. Ketersediaan dasar, kondisi rapuh, konsistensi dalam jangka panjang. Menurut teorema
CAP dalam sistem terdistribusi, sesuatu harus ditinggalkan. Koherensi yang ketat biasanya ditinggalkan demi koherensi dalam jangka panjang. Yang berarti bahwa dengan tidak adanya perubahan data, suatu hari sistem akan pada akhirnya mencapai kondisi yang konsisten.
Untuk menunjukkan kompromi seperti itu,
BASE singkatan mulai digunakan agak
erat , dan permainan istilah kimia ternyata (
ACID - keasaman,
BASE - kebasaan).
- Pada dasarnya Tersedia berarti bahwa sistem menjamin ketersediaan data, itu menanggapi setiap permintaan. Tetapi jawabannya mungkin data yang lama atau tidak konsisten (atau tidak ada)
- Status lunak berarti keadaan sistem dapat berubah seiring waktu meskipun tidak ada permintaan untuk perubahan data. Karena pada titik waktu mana pun, data dapat dibawa ke keadaan konsisten.
- Konsistensi akhirnya berarti bahwa jika data berhenti berubah, mereka tentu saja akan berakhir dalam keadaan yang konsisten. Yaitu permintaan yang sama untuk node yang berbeda akan menghasilkan jawaban yang sama.
Baca lebih lanjut: satu
kali (bahasa Inggris) ,
dua (bahasa Inggris)Prinsip Pengembangan Perangkat Lunak
KERING
Jangan Ulangi Diri Anda Sendiri. Jangan diulang. Ini adalah prinsip pengembangan perangkat lunak, ide utamanya adalah untuk mengurangi jumlah informasi yang digandakan dalam sistem, dan tujuannya adalah untuk mengurangi kompleksitas sistem dan meningkatkan pengelolaannya.
Dalam buku aslinya (
The Pragmatic Programmer book, oleh
Andrew Hunt dan
David Thomas ), prinsip ini dirumuskan sebagai berikut: "Setiap pengetahuan harus memiliki representasi tunggal, konsisten, dan otoritatif dalam sistem." Dalam hal ini, pengetahuan dipahami sebagai bagian dari area subjek atau algoritma: kode, skema database, protokol interaksi tertentu, dll. Dengan demikian, untuk membuat satu perubahan pada sistem, hanya satu "pengetahuan" yang perlu diperbarui di satu tempat.
Contoh bodoh: klien dan server mengirimkan data terstruktur satu sama lain. Karena ini adalah aplikasi yang berbeda yang berjalan pada mesin yang berbeda, maka mereka berdua harus memiliki implementasi sendiri dari struktur ini. Jika sesuatu berubah, perubahan harus dilakukan di dua tempat. Langkah yang jelas untuk menghindari pengulangan ini adalah mengalokasikan kode umum ke pustaka yang terpisah. Langkah selanjutnya adalah membuatnya sesuai dengan deskripsi struktur (Google Protokol Buffer, misalnya), agar tidak menulis jenis kode yang sama untuk mengakses bidang struktur.
Duplikasi kode hanyalah kasus khusus pelanggaran
KERING . Dan itu tidak selalu terjadi. Jika dua potong kode terlihat sama, tetapi masing-masing menerapkan logika bisnis mereka sendiri,
KERING tidak rusak.
Seperti prinsip lainnya,
KERING adalah alat, bukan dogma. Semakin besar sistem, semakin mudah melanggar prinsip ini. Pertama, cita-cita itu tidak mungkin tercapai. Dan kedua, jika secara membabi buta mengikuti
KERING mengarah ke kode yang lebih rumit dan membuatnya lebih sulit untuk dipahami, maka lebih baik untuk meninggalkannya.
Baca lebih lanjut:
satu (Rusia) ,
dua (Rusia)CIUMAN
Tetap Sederhana, Bodoh. Buat lebih mudah (bodoh dalam hal ini bukan panggilan). Ini adalah prinsip desain yang sebagian besar sistem bekerja lebih baik jika tetap sederhana. Prinsipnya berasal dari industri pesawat terbang dan banyak diterapkan di mana, termasuk dalam pengembangan perangkat lunak.
Dalam kasus terakhir,
KISS berguna baik dalam mendesain dan menulis kode secara langsung. Arsitektur dan kode sederhana tidak hanya lebih mudah dipahami, tetapi juga lebih mudah digunakan, dipelihara, dan dikembangkan. MapReduce tidak boleh dibodohi jika pasangan produsen-konsumen sudah cukup. Keajaiban metaprogramming sangat rumit jika Anda dapat melakukannya dengan beberapa fungsi biasa dan mencapai tingkat kinerja yang diperlukan.
Dengan semua ini, orang tidak boleh lupa bahwa kesederhanaan bukanlah tujuan, tetapi hanya persyaratan non-fungsional. Hal utama adalah untuk mencapai tujuan desain / implementasi, dan disarankan untuk melakukan ini dengan cara sesederhana mungkin.
Baca lebih lanjut:
satu (Rusia) ,
dua (Rusia) ,
tiga (Inggris)YAGNI
Anda Tidak Akan Membutuhkannya. Anda tidak membutuhkannya. Ini adalah prinsip pengembangan perangkat lunak, gagasan utamanya adalah penolakan fungsi yang berlebihan, dan tujuannya adalah untuk menghemat sumber daya yang dihabiskan untuk pengembangan.
YAGNI mengatakan bahwa Anda tidak perlu merancang atau mengimplementasikan fungsi yang tidak dibutuhkan saat ini. Bahkan jika Anda yakin mereka akan dibutuhkan di masa depan. Tidak perlu menambahkan abstraksi yang tidak perlu, manfaatnya akan muncul beberapa saat kemudian.
Masalahnya adalah orang tidak memprediksi masa depan dengan baik. Oleh karena itu, kemungkinan besar semua yang dilakukan "cadangan" tidak akan berguna. Dan ternyata waktu dan uang yang dihabiskan untuk pengembangan, pengujian, dan dokumentasi seperti itu terbuang sia-sia. Plus, perangkat lunak menjadi lebih rumit, sumber daya tambahan harus dihabiskan untuk mendukungnya lagi. Lebih buruk lagi, ketika ternyata perlu dilakukan secara berbeda. Uang dan waktu akan dihabiskan juga untuk koreksi.
Prinsip
YAGNI agak lebih radikal daripada
KERING dan
CIUMAN . Jika mereka memecah sistem menjadi bagian-bagian yang dapat dipahami dan membuat keputusan sederhana, maka
YAGNI hanya memotong bagian dan solusi yang tidak perlu.
Baca lebih lanjut:
satu (Rusia) ,
dua (Inggris) ,
tiga (Inggris)Nih
Tidak Diciptakan Di Sini. Tidak ditemukan di sini. Ini adalah sindrom penolakan terhadap perkembangan orang lain, suatu posisi yang secara praktis berbatasan dengan penemuan sepeda. Seringkali, sindrom disertai dengan keyakinan bahwa menciptakan teknologi di dalam perusahaan akan lebih cepat dan lebih murah, dan teknologi itu sendiri akan lebih memenuhi kebutuhan perusahaan. Namun, dalam kebanyakan kasus ini bukan itu masalahnya, dan
NIH adalah anti-pola.
Berikut adalah beberapa kasus yang membenarkan
NIH :
- Kualitas solusi pihak ketiga tidak cukup tinggi, atau harganya tidak cukup rendah.
- Solusi pihak ketiga memiliki batasan lisensi.
- Menggunakan solusi pihak ketiga menciptakan ketergantungan pada pemasoknya dan dengan demikian mengancam bisnis.
Baca lebih lanjut:
satu (Rusia) ,
dua (Inggris) ,
tiga (Inggris)Ftse
Teorema Dasar Rekayasa Perangkat Lunak. Teorema dasar pengembangan perangkat lunak. Sebenarnya, ini bukan teorema, tidak punya bukti. Ini adalah perkataan terkenal oleh Andrew Koenig:
Masalah apa pun dapat diselesaikan dengan menambahkan lapisan abstraksi lainnya.
Terkadang mereka menambah frasa ini "... kecuali untuk masalah terlalu banyak lapisan abstraksi." Secara umum, "teorema" bukanlah hal yang serius, tetapi perlu diketahui tentang hal itu.
Baca lebih lanjut: satu
kali (bahasa Inggris) ,
dua (bahasa Inggris)GRASP
Pola Perangkat Lunak Penugasan Tanggung Jawab Umum. Template alokasi tanggung jawab umum. Sembilan pola ini dirumuskan dalam
Menerapkan UML dan Pola oleh
Craig Larman . Setiap template adalah solusi khas untuk satu (tetapi lebih umum) masalah desain perangkat lunak.
- Ahli Informasi . Masalah: apa prinsip umum pembagian tanggung jawab antara objek? Keputusan: memberikan tugas kepada seseorang yang memiliki informasi yang diperlukan untuk memenuhi kewajiban ini.
- Pencipta Masalah: siapa yang harus bertanggung jawab untuk membuat objek baru? Solusi: kelas B harus membuat instance kelas A jika satu atau lebih kondisi berikut ini benar:
- kelas B agregat atau berisi instance A
- B menulis A
- B aktif menggunakan A
- B memiliki data inisialisasi A - Kopling rendah Masalah: bagaimana cara mengurangi dampak perubahan? Bagaimana cara meningkatkan kemungkinan penggunaan kembali? Solusi: sebarkan tanggung jawab sehingga konektivitas rendah. Kopling adalah ukuran seberapa kaku elemen-elemen terhubung, seberapa besar mereka bergantung satu sama lain. Yaitu Disarankan untuk menghubungkan objek sehingga mereka tahu tentang satu sama lain hanya minimum yang diperlukan.
- Gearing tinggi ( Kohesi Tinggi ). Masalah: Bagaimana cara saya mengelola kompleksitas? Solusi: sebarkan tanggung jawab agar keterlibatan tinggi tetap terjaga. Keterlibatan tinggi berarti bahwa tanggung jawab satu elemen difokuskan pada satu bidang.
- Pengendali Masalah: siapa yang harus bertanggung jawab untuk menangani acara masukan? Solusi: tentukan kelas sebagai penanggung jawab, yang mewakili seluruh sistem atau subsistem sebagai keseluruhan (pengontrol eksternal), atau satu skrip khusus (skrip atau pengontrol sesi). Pada saat yang sama, pengontrol tidak menerapkan reaksi terhadap peristiwa, melainkan mendelegasikan ini ke pelaksana yang relevan.
- Polimorfisme ( Polimorfisme ). Masalah: bagaimana cara menangani berbagai perilaku berdasarkan jenis? : , , , .
- ( Pure Fabrication ). : , ? : , .
- ( Indirection ). : , Low Coupling ? : .
- Resistensi terhadap perubahan ( Variasi yang Dilindungi ). Masalah: bagaimana merancang objek dan subsistem sehingga perubahan di dalamnya tidak memiliki efek yang tidak diinginkan pada elemen lain? Solusi: temukan kemungkinan titik ketidakstabilan dan buat antarmuka yang stabil di sekitarnya, berkomunikasi hanya melalui antarmuka semacam itu.
Pola GRASP secara konstan berpotongan dengan pola Gang Four dan prinsip SOLID . Ini normal, karena mereka semua memecahkan masalah umum - untuk menyederhanakan pembuatan perangkat lunak berkualitas tinggi.Baca lebih lanjut: satu (Rusia) , dua (Inggris) , tiga (Rusia)PADAT
Prinsip-prinsip SOLID. Ini adalah lima prinsip pemrograman dan desain berorientasi objek (singkatannya dibuat dari huruf pertama namanya). Mendapatkan ketenaran berkat Robert Martin pada awal 2000-an. Tujuan utama dari prinsip-prinsip ini adalah menciptakan perangkat lunak yang mudah dipahami, dipelihara, dan dikembangkan.- Prinsip tanggung jawab tunggal ( single Prinsip Tanggung Jawab, SRP ). Kelas atau modul seharusnya hanya memiliki satu tanggung jawab. "Lakukan hanya satu hal, tetapi lakukan dengan baik."
- / ( Open Closed Principle, OCP ). (, , ) , . : , .
- ( Liskov Substitution Principle, LSP ). , . Yaitu - .
- ( Interface Segregation Principle, ISP ). , . , . , , . , .
- Ketergantungan Inversi Prinsip ( dari ketergantungan Pembalikan Prinsip, DIP ). Modul tingkat atas tidak harus bergantung pada modul tingkat bawah. Semua modul harus bergantung pada abstraksi. Abstraksi tidak harus bergantung pada detail. Rinciannya harus bergantung pada abstraksi. Sebagai contoh, baik antarmuka maupun kelas konkret tidak boleh mengandung atau menerima kelas konkret lainnya sebagai argumen dari metode mereka, tetapi hanya antarmuka (dalam arti Java dan C #).
Baca lebih lanjut: satu (Rusia) , dua (Inggris) , tiga (Inggris)Lainnya
Abi
Antarmuka Biner Aplikasi. Antarmuka aplikasi biner. Ini adalah seperangkat konvensi yang mendefinisikan interaksi modul biner (file yang dapat dieksekusi, perpustakaan, OS). Dua modul harus dibuat sesuai dengan satu ABI - ini adalah prasyarat untuk kompatibilitas biner mereka, dalam hal ini mereka dapat berinteraksi tanpa masalah (misalnya, file yang dapat dieksekusi dihubungkan ke perpustakaan dan dieksekusi oleh sistem operasi).Contoh ABI adalah format file yang dapat dieksekusi ELF di Linux dan PE pada Windows. Setiap OS mengharapkan bahwa data yang diperlukan (sumber daya, titik masuk, dll.) Terletak di file biner sesuai dengan format yang sesuai. Jelas, ELF dan PE berbeda, karena program Linux tidak berjalan langsung di Windows dan sebaliknya.Pada tingkat library dan executable, ABI dapat menentukan penempatan bidang dalam suatu kelas, kelas dasar dalam turunan, mekanisme untuk mengimplementasikan fungsi virtual, format frame panggilan stack, aturan untuk meneruskan argumen ke fungsi yang dipanggil, dll., Dll.C ++ tidak memiliki satu pun ABI standar , yang tidak mengherankan, karena itu tergantung pada arsitektur dan OS. Sebagai contoh, kompiler C ++ untuk banyak sistem operasi mirip Unix (Linux, FreeBSD, MacOS) pada x86_64 ikuti System V AMD64 ABI , pada ARM - ARM C ++ ABI . Visual C ++ ABI tidak dipublikasikan secara resmi, tetapi setidaknya sebagian direkayasa ulang. Sangat berbeda dari System V ABI, mereka memiliki aturan yang sama sekali berbeda untuk menyembunyikan nama (mangling) danmeneruskan argumen ke fungsi yang dipanggil (Linux menggunakan 6 register, Windows menggunakan 4 register), dan banyak perbedaan lainnya.Bahkan jika API dan ABI tetap sama, dan hanya detail implementasi yang berubah, kompatibilitas biner mungkin rusak . Misalnya, dalam C ++ 11, ada persyaratan untuk string untuk menyimpan karakter secara berurutan (seperti dalam vektor). Karena itu, GCC 5 harus mengubah implementasi string ( SAP digunakan sebelumnya ), yang menyebabkan ketidakcocokan biner.Baca lebih lanjut: sekali (Rusia) , dua (Inggris) dan semua tautan dari dua paragraf sebelumnya.Sapi
Salin Saat Menulis. Salin saat merekam. Ini adalah mekanisme manajemen sumber daya, juga dikenal sebagai berbagi implisit dan salinan malas. Idenya adalah bahwa ketika salinan diperlukan, sumber daya tidak benar-benar disalin, tetapi tautan ke sana dibuat. Dan hanya ketika ada permintaan untuk perubahan - dalam aslinya atau di "copy" - hanya pada saat pembuatan salinan lengkap terjadi.Keuntungan dari SAP jelas: menyalin objek apa pun terjadi secara instan. Jika objek sering disalin tetapi jarang berubah, peningkatan kinerja bisa signifikan.Contoh penggunaan COW :- Manajemen memori proses virtual di Linux. Ketika
fork()
halaman dipanggil , memori proses tidak disalin, tetapi hanya ditandai sebagai dibagikan. - Snapshots di beberapa sistem file (Btrfs, ZFS) dan database (MS SQL Server).
- Sebelum C ++ 11, beberapa implementasi
std::string
menggunakan SAP . Dalam C ++ 11, persyaratan untuk std::string
telah berubah (lihat ABI ). - Banyak jenis dalam Qt menggunakan SAP .
Baca lebih lanjut: satu kali (bahasa Inggris) , dua (bahasa Inggris)FBC, FBCP
Kelas Dasar Rapuh (Masalah). Masalah kelas dasar yang rapuh. Ini adalah masalah OOP mendasar, intinya adalah bahwa perubahan kelas dasar yang benar dapat menyebabkan kesalahan pada salah satu ahli waris.Misalnya, untuk rekursi yang tak terbatas struct Base { virtual void method1() {
Anda dapat memecahkan masalah FBC hanya dengan meninggalkan pewarisan yang mendukung komposisi, misalnya, atau memperluas antarmuka dalam terminologi Java (dalam C ++, ini akan mewarisi hanya untuk kelas dasar abstrak tanpa implementasi negara dan metode). Dalam kasus lain, Anda hanya dapat mencoba meminimalkan kemungkinan FBCP dengan tips berikut:- Larang pewarisan atau pendefinisian ulang di tempat yang tidak diperlukan (kata kunci
final
dalam C ++ dan Java). - Ahli waris tidak boleh memiliki akses ke interior kelas dasar, komunikasi hanya dapat melalui antarmuka publik.
- Metode pewaris hanya dapat memanggil metode virtual yang dipanggil dalam metode redefined dari kelas dasar, dan metode redefined itu sendiri.
Baca lebih lanjut: satu (Inggris) , dua (Inggris) , tiga (Inggris)LRU
Paling Baru Digunakan. Ekstrusi sudah lama tidak digunakan. Ini adalah salah satu algoritma caching (mereka juga kebijakan preemptive). Secara umum, cache dapat dianggap sebagai penyimpanan cepat pasangan nilai kunci, salah satu karakteristik utamanya adalah rasio hit. Semakin tinggi level ini, semakin sering nilai yang diinginkan ada di cache cepat dan semakin jarang itu harus dicari dalam penyimpanan lambat. Tetapi karena memori tidak pernah kenyal, ukuran cache harus dibatasi. Tugas algoritma caching adalah menentukan elemen mana yang harus dibuang dari cache yang diisi, jika perlu, untuk memaksimalkan tingkat hit.LRUmenggantikan elemen cache mereka, yang tidak ada yang mengakses paling lama. Ini mungkin adalah algoritma caching yang paling terkenal. Mungkin karena kombinasi efisiensi dan kesederhanaan. Konsumsi memori LRU adalah O (n), waktu akses rata-rata ke nilai adalah O (1), waktu rata-rata untuk menambahkan elemen juga O (1). Untuk implementasi, tabel hash dan daftar tertaut ganda biasanya digunakan.Misalnya saja template <class K, class V> class LRU { private: using Queue = std::list<std::pair<K, V>>; using Iterator = typename Queue::iterator; using Hash = std::unordered_map<K, Iterator>; Queue queue_; Hash hash_; const size_t limit_; public: LRU(size_t limit) : limit_(limit) { } std::optional<V> get(const K& key) { const auto it = hash_.find(key); if (it == hash_.end()) { return {}; } it->second = reorder(it->second); return { it->second->second }; } void add(K&& key, V&& value) { if (hash_.size() >= limit_) { pop(); } queue_.emplace_front(std::move(key), std::move(value)); const auto it = queue_.begin(); hash_[it->first] = it; } private: Iterator reorder(Iterator it) { queue_.emplace_front(std::move(it->first), std::move(it->second)); queue_.erase(it); return queue_.begin(); } void pop() { hash_.erase(queue_.back().first); queue_.pop_back(); } };
Kelemahan yang jelas dari LRU adalah konsumsi memori yang tinggi, karena menggunakan dua struktur elemen n masing-masing. Selain LRU, ada banyak algoritma caching lainnya untuk berbagai kasus: MRU (Paling Baru Digunakan), LFU (Paling Sering Digunakan), LRU Tersegmentasi, 2Q, dll.Baca lagi: satu kali (Inggris) , dua (Rusia) , tigaPS
Jika saya melewatkan sesuatu atau keliru di suatu tempat - tulis di komentar.