Komputasi awan
SOLID adalah akronim mnemonic untuk desain kelas dalam pemrograman berorientasi objek. Prinsip-prinsip tersebut melembagakan praktik yang membantu mengembangkan kebiasaan pemrograman yang baik dan kode yang dapat dipelihara.
Dengan mempertimbangkan pemeliharaan kode dan ekstensibilitas dalam jangka panjang, prinsip SOLID memperkaya lingkungan pengembangan kode Agile. Menghitung dan mengoptimalkan dependensi kode membantu menciptakan siklus pengembangan perangkat lunak yang lebih mudah dan terorganisir.
SOLID mewakili seperangkat prinsip untuk mendesain kelas. Robert C. Martin (Paman Bob) memperkenalkan sebagian besar prinsip desain dan menciptakan akronim.
SOLID adalah singkatan dari:
Prinsip SOLID mewakili kumpulan praktik terbaik untuk desain perangkat lunak. Setiap ide mewakili kerangka kerja desain, yang mengarah ke kebiasaan pemrograman yang lebih baik, desain kode yang lebih baik, dan lebih sedikit kesalahan.
Cara terbaik untuk memahami bagaimana prinsip SOLID bekerja adalah melalui contoh. Semua prinsip saling melengkapi dan berlaku untuk kasus penggunaan individu. Urutan penerapan prinsip tidak penting, dan tidak semua prinsip dapat diterapkan dalam setiap situasi.
Setiap bagian di bawah ini memberikan gambaran umum dari setiap prinsip SOLID dalam bahasa pemrograman Python. Gagasan umum SOLID berlaku untuk bahasa berorientasi objek apa pun, seperti PHP, Java, atau C#. Generalisasi aturan membuatnya berlaku untuk pendekatan pemrograman modern, seperti layanan mikro.
Prinsip tanggung jawab tunggal (SRP) menyatakan:“Seharusnya tidak ada lebih dari satu alasan untuk suatu kelas berubah.”
Saat mengubah kelas, kita hanya boleh mengubah satu fungsi, yang berarti setiap objek hanya boleh memiliki satu pekerjaan.
Sebagai contoh, lihat kelas berikut:
# A class with multiple responsibilities
class Animal:
# Property constructor
def __init__(self, name):
self.name = name
# Property representation
def __repr__(self):
return f'Animal(name="{self.name}")'
# Database management
def save(animal):
print(f'Saved {animal} to the database')
if __name__ == '__main__':
# Property instantiation
a = Animal('Cat')
# Saving property to a database
Animal.save(a)
Saat membuat perubahan apa pun pada save()
metode, perubahan terjadi di Animal
kelas. Saat membuat perubahan properti, modifikasi juga terjadi di Animal
kelas.
Kelas memiliki dua alasan untuk berubah dan melanggar prinsip tanggung jawab tunggal. Meskipun kode berfungsi seperti yang diharapkan, tidak menghormati prinsip desain membuat kode lebih sulit untuk dikelola dalam jangka panjang.
Untuk menerapkan prinsip tanggung jawab tunggal, perhatikan bahwa kelas contoh memiliki dua pekerjaan berbeda:
get_name()
).(save()
).Oleh karena itu, cara terbaik untuk mengatasi masalah ini adalah dengan memisahkan metode manajemen database ke dalam kelas baru. Misalnya:
# A class responsible for property management
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'Animal(name="{self.name}")'
# A class responsible for database management
class AnimalDB:
def save(self, animal):
print(f'Saved {animal} to the database')
if __name__ == '__main__':
# Property instantiation
a = Animal('Cat')
# Database instantiation
db = AnimalDB()
# Saving property to a database
db.save(a)
Mengubah AnimalDB
kelas tidak memengaruhi Animal
kelas dengan prinsip tanggung jawab tunggal diterapkan. Kode ini intuitif dan mudah dimodifikasi.
Prinsip terbuka-tertutup (OCP) menyatakan:“Entitas perangkat lunak harus terbuka untuk ekstensi tetapi ditutup untuk modifikasi.”
Menambahkan fungsionalitas dan kasus penggunaan ke sistem seharusnya tidak memerlukan modifikasi entitas yang ada. Kata-katanya tampak kontradiktif – menambahkan fungsionalitas baru memerlukan perubahan kode yang ada.
Idenya mudah dipahami melalui contoh berikut:
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'Animal(name="{self.name}")'
class Storage:
def save_to_db(self, animal):
print(f'Saved {animal} to the database')
Storage
class menyimpan informasi dari Animal
contoh ke database. Menambahkan fungsi baru, seperti menyimpan ke file CSV, memerlukan penambahan kode ke Storage
kelas:
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'Animal(name="{self.name}")'
class Storage:
def save_to_db(self, animal):
print(f'Saved {animal} to the database')
def save_to_csv(self,animal):
printf(f’Saved {animal} to the CSV file’)
save_to_csv
metode memodifikasi Storage
. yang ada kelas untuk menambahkan fungsionalitas. Pendekatan ini melanggar prinsip buka-tutup dengan mengubah elemen yang ada saat fungsi baru muncul.
Kode mengharuskan penghapusan Storage
untuk tujuan umum class dan membuat class individual untuk disimpan dalam format file tertentu.
Kode berikut menunjukkan penerapan prinsip buka-tutup:
class DB():
def save(self, animal):
print(f'Saved {animal} to the database')
class CSV():
def save(self, animal):
print(f'Saved {animal} to a CSV file')
Kode ini sesuai dengan prinsip buka-tutup. Kode lengkapnya sekarang terlihat seperti ini:
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return f'"{self.name}"'
class DB():
def save(self, animal):
print(f'Saved {animal} to the database')
class CSV():
def save(self, animal):
print(f'Saved {animal} to a CSV file')
if __name__ == '__main__':
a = Animal('Cat')
db = DB()
csv = CSV()
db.save(a)
csv.save(a)
Memperluas dengan fungsionalitas tambahan (seperti menyimpan ke file XML) tidak mengubah kelas yang ada.
Prinsip substitusi Liskov (LSP) menyatakan:“Fungsi yang menggunakan pointer atau referensi ke kelas dasar harus dapat menggunakan objek dari kelas turunan tanpa mengetahuinya.”
Prinsipnya menyatakan bahwa kelas induk dapat menggantikan kelas anak tanpa perubahan fungsi yang mencolok.
Lihat contoh penulisan file di bawah ini:
# Parent class
class FileHandling():
def write_db(self):
return f'Handling DB'
def write_csv(self):
return f'Handling CSV'
# Child classes
class WriteDB(FileHandling):
def write_db(self):
return f'Writing to a DB'
def write_csv(self):
return f"Error: Can't write to CSV, wrong file type."
class WriteCSV(FileHandling):
def write_csv(self):
return f'Writing to a CSV file'
def write_db(self):
return f"Error: Can't write to DB, wrong file type."
if __name__ == "__main__":
# Parent class instantiation and function calls
db = FileHandling()
csv = FileHandling()
print(db.write_db())
print(db.write_csv())
# Children classes instantiations and function calls
db = WriteDB()
csv = WriteCSV()
print(db.write_db())
print(db.write_csv())
print(csv.write_db())
print(csv.write_csv())
Kelas induk (FileHandling
) terdiri dari dua metode untuk menulis ke database dan file CSV. Kelas menangani kedua fungsi dan mengembalikan pesan.
Dua kelas anak (WriteDB
dan WriteCSV
) mewarisi properti dari kelas induk (FileHandling
). Namun, kedua anak membuat kesalahan saat mencoba menggunakan fungsi tulis yang tidak sesuai, yang melanggar prinsip Substitusi Liskov karena fungsi utama tidak sesuai dengan fungsi induk.
Untuk kode berikut menyelesaikan masalah:
# Parent class
class FileHandling():
def write(self):
return f'Handling file'
# Child classes
class WriteDB(FileHandling):
def write(self):
return f'Writing to a DB'
class WriteCSV(FileHandling):
def write(self):
return f'Writing to a CSV file'
if __name__ == "__main__":
# Parent class instantiation and function calls
db = FileHandling()
csv = FileHandling()
print(db.write())
print(csv.write())
# Children classes instantiations and function calls
db = WriteDB()
csv = WriteCSV()
print(db.write())
print(csv.write())
Kelas anak sesuai dengan fungsi induk dengan benar.
Prinsip pemisahan antarmuka (ISP) menyatakan:“Banyak antarmuka khusus klien lebih baik daripada satu antarmuka tujuan umum.”
Dengan kata lain, antarmuka interaksi yang lebih luas dibagi menjadi yang lebih kecil. Prinsipnya memastikan kelas hanya menggunakan metode yang mereka butuhkan, mengurangi redundansi secara keseluruhan.
Contoh berikut menunjukkan antarmuka tujuan umum:
class Animal():
def walk(self):
pass
def swim(self):
pass
class Cat(Animal):
def walk(self):
print("Struts")
def fly(self):
raise Exception("Cats don't swim")
class Duck(Animal):
def walk(self):
print("Waddles")
def swim(self):
print("Floats")
Kelas anak mewarisi dari Animal
induknya kelas, yang berisi walk
dan fly
metode. Meskipun kedua fungsi tersebut dapat diterima untuk hewan tertentu, beberapa hewan memiliki fungsi yang berlebihan.
Untuk menangani situasi ini, bagi antarmuka menjadi bagian-bagian yang lebih kecil. Misalnya:
class Walk():
def walk(self):
pass
class Swim(Walk):
def swim(self):
pass
class Cat(Walk):
def walk(self):
print("Struts")
class Duck(Swim):
def walk(self):
print("Waddles")
def swim(self):
print("Floats")
Fly
kelas mewarisi dari Walk
, menyediakan fungsionalitas tambahan untuk kelas anak yang sesuai. Contoh memenuhi prinsip pemisahan antarmuka.
Menambahkan hewan lain, seperti ikan, memerlukan atomisasi antarmuka lebih lanjut karena ikan tidak dapat berjalan.
Prinsip inversi ketergantungan menyatakan:“Bergantung pada abstraksi, bukan konkresi.”
Prinsipnya bertujuan untuk mengurangi koneksi antar kelas dengan menambahkan lapisan abstraksi. Memindahkan dependensi ke abstraksi membuat kode menjadi kuat.
Contoh berikut menunjukkan ketergantungan kelas tanpa lapisan abstraksi:
class LatinConverter:
def latin(self, name):
print(f'{name} = "Felis catus"')
return "Felis catus"
class Converter:
def start(self):
converter = LatinConverter()
converter.latin('Cat')
if __name__ == '__main__':
converter = Converter()
converter.start()
Contoh memiliki dua kelas:
LatinConverter
menggunakan API imajiner untuk mengambil nama Latin untuk hewan (kode keras “Felis catus
” untuk mempermudah).Converter
adalah modul tingkat tinggi yang menggunakan instance LatinConverter
dan fungsinya untuk mengubah nama yang diberikan. Converter
sangat bergantung pada LatinConverter
kelas, yang tergantung pada API. Pendekatan ini melanggar prinsip.Prinsip inversi ketergantungan memerlukan penambahan lapisan antarmuka abstraksi antara dua kelas.
Contoh solusi terlihat seperti berikut:
from abc import ABC
class NameConverter(ABC):
def convert(self,name):
pass
class LatinConverter(NameConverter):
def convert(self, name):
print('Converting using Latin API')
print(f'{name} = "Felis catus"')
return "Felis catus"
class Converter:
def __init__(self, converter: NameConverter):
self.converter = converter
def start(self):
self.converter.convert('Cat')
if __name__ == '__main__':
latin = LatinConverter()
converter = Converter(latin)
converter.start()
Converter
kelas sekarang bergantung pada NameConverter
antarmuka alih-alih pada LatinConverter
secara langsung. Pembaruan di masa mendatang memungkinkan penentuan konversi nama menggunakan bahasa dan API yang berbeda melalui NameConverter
antarmuka.
Prinsip SOLID membantu melawan masalah pola desain. Tujuan keseluruhan dari prinsip SOLID adalah untuk mengurangi ketergantungan kode, dan menambahkan fitur baru atau mengubah bagian dari kode tidak merusak keseluruhan build.
Sebagai hasil dari penerapan prinsip-prinsip SOLID pada desain berorientasi objek, kode menjadi lebih mudah untuk dipahami, dikelola, dipelihara, dan diubah. Karena aturan lebih cocok untuk proyek besar, menerapkan prinsip SOLID meningkatkan kecepatan dan efisiensi siklus hidup pengembangan secara keseluruhan.
Meskipun prinsip-prinsip SOLID sudah berusia lebih dari 20 tahun, prinsip-prinsip tersebut masih memberikan dasar yang baik untuk desain arsitektur perangkat lunak. SOLID memberikan prinsip-prinsip desain suara yang berlaku untuk program dan lingkungan modern, bukan hanya pemrograman berorientasi objek.
Prinsip SOLID berlaku dalam situasi di mana kode ditulis dan dimodifikasi oleh orang-orang, disusun menjadi modul, dan berisi elemen internal atau eksternal.
Prinsip-prinsip SOLID membantu menyediakan kerangka kerja dan panduan yang baik untuk desain arsitektur perangkat lunak. Contoh dari panduan ini menunjukkan bahwa bahkan bahasa yang diketik secara dinamis seperti Python mendapat manfaat dari penerapan prinsip pada desain kode.
Selanjutnya, baca tentang 9 prinsip DevOps yang akan membantu tim Anda memaksimalkan DevOps.
Komputasi awan
Orang menggunakan sirkuit pemanas induksi untuk memanaskan bahan konduktif dalam proses non-kontak. Ini juga merupakan perangkat yang menggunakan medan magnet frekuensi tinggi untuk memanaskan keramik dan logam feromagnetik. Selain itu, pemanas induksi cocok untuk melelehkan dan menempa baja serta a
Diperkirakan lebih dari setengah komponen elektronik gagal karena tegangan tinggi akibat lingkungan termal. Beberapa tahun terakhir telah menyaksikan perangkat luas sirkuit terpadu skala besar dan skala besar (IC) dan teknologi pemasangan permukaan (SMT) dan produk elektronik mulai merangkul arah pe
Meskipun dimungkinkan untuk menggunakan manufaktur aditif untuk mereplikasi bagian yang ada yang diproduksi menggunakan metode tradisional, itu bukan penggunaan manufaktur aditif terbaik. Untuk memaksimalkan kinerja suku cadang, penghematan biaya, dan penggunaan material, yang terbaik adalah mendesa
Ingin membuat model untuk program robot Anda tanpa mengkhawatirkan model CAD yang cerdik? Plugin baru untuk Solid Edge memungkinkan Anda mendapatkan kekuatan teknologi sinkron dengan pemrograman robot RoboDK yang mudah. Setiap orang memiliki program CAD favorit mereka. Ketika saya akan melalui