Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial Internet of Things >> Komputasi awan

SOLID:Prinsip Desain Berorientasi Objek

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.

Apakah Prinsip SOLID itu?

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.

SOLID:5 Prinsip Dijelaskan

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)

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:

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)

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)

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)

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 Pembalikan Ketergantungan (DIP)

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:

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.

Mengapa Perlu Prinsip SOLID?

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.

Apakah Prinsip SOLID Masih Relevan?

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.

Kesimpulan

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

  1. C# Kata Kunci statis
  2. C# Kelas Bersarang
  3. Template Kelas C++
  4. Kelas Anonim Java
  5. Kelas Java ObjectOutputStream
  6. Java Generik
  7. Kelas File Java
  8. 5 prinsip desain untuk menerapkan interkoneksi yang kuat untuk aplikasi intensif data
  9. C# - Warisan
  10. C# - Polimorfisme