Traffine I/O

Bahasa Indonesia

2022-11-21

Arsitektur Onion

Apa itu Arsitektur Onion

Arsitektur Onion adalah pola arsitektur untuk merancang aplikasi perangkat lunak. Arsitektur ini digambarkan secara visual dalam lapisan-lapisan konsentris yang menyerupai bawang, oleh karena itu dinamakan demikian. Pola ini menerapkan kontrol dependensi yang ketat, di mana dependensi mengalir ke dalam, sementara interaksi terjadi dari lapisan terluar menuju pusat.

Tujuan utama arsitektur ini adalah mengatasi masalah umum dalam desain perangkat lunak, seperti keterikatan yang kuat dan pemisahan masalah, sehingga memungkinkan kemudahan pemeliharaan dan adaptabilitas dalam struktur aplikasi.

Prinsip-prinsip

Arsitektur Onion didasarkan pada beberapa prinsip panduan:

  • Domain adalah Inti
    Inti dari aplikasi adalah domain, yang mencakup aturan bisnis dan logika fundamental. Ini termasuk entitas bisnis dan objek nilai yang penting untuk fungsi aplikasi. Dalam Arsitektur Onion, entitas domain tidak bergantung pada hal lain. Mereka bersifat murni, karena mereka mengandung properti dan metode yang berkaitan langsung dengan apa yang mereka wakili.

  • Dependensi ke dalam
    Lapisan-lapisan arsitektur hanya boleh bergantung pada lapisan-lapisan dalam dan tidak pada lapisan-lapisan di luar. Ide ini adalah menjaga domain dan lapisan aplikasi terpisah dari masalah eksternal seperti UI, Infrastruktur, atau Pengujian. Dengan memastikan keterikatan hanya menuju pusat, arsitektur ini memungkinkan lapisan-lapisan luar dapat saling dipertukarkan dan dimodifikasi dengan mudah tanpa mempengaruhi lapisan-lapisan dalam.

  • Pemisahan dari Infrastruktur
    Prinsip lain dari Arsitektur Onion adalah penyembunyian kepentingan infrastruktur di dalam lapisan-lapisan terluar. Dengan demikian, perubahan dalam infrastruktur, seperti perubahan perangkat lunak database atau antarmuka pengguna, tidak mempengaruhi organisasi dan operasi lapisan-lapisan dalam. Pendekatan ini memudahkan pengujian komponen inti tanpa perlu dependensi terkait infrastruktur.

  • Kemandirian Kode Inti Aplikasi
    Semua kode inti aplikasi dapat diuji tanpa antarmuka pengguna, database, server web, atau elemen eksternal lainnya. Dengan fokus pada inti, aplikasi menjadi lebih mudah dipelihara, lebih mudah ditingkatkan skalabilitasnya, dan lebih sedikit kesalahan yang mungkin terjadi.

Lapisan dalam Arsitektur Onion

Dalam Arsitektur Onion, aplikasi dibagi menjadi beberapa lapisan dengan tanggung jawab yang berbeda, masing-masing berkomunikasi dengan lapisan langsung di dalam atau di luar lapisannya.

Onion architecture
Onion Architecture

Lapisan Model Domain

Lapisan model domain berada di tengah-tengah Arsitektur Onion. Lapisan terdalam ini mengkapsulasi aturan bisnis, kebijakan, dan entitas yang penting untuk domain aplikasi. Model domain terdiri dari entitas bisnis dan objek nilai yang secara langsung mewakili konsep dan perilaku dunia nyata yang berlaku untuk domain tersebut.

Objek domain tidak boleh mengandung referensi ke masalah eksternal seperti database atau antarmuka pengguna, sehingga membuatnya tidak bergantung pada persistensi. Mereka bersifat murni dalam arti bahwa mereka mengkapsulasi properti dan perilaku yang penting bagi domain bisnis.

Lapisan Layanan Domain

Di luar lapisan model domain adalah lapisan layanan domain. Layanan dalam lapisan ini menangani operasi bisnis yang melibatkan beberapa entitas atau objek nilai dalam domain. Mereka mengkapsulasi logika bisnis yang tidak secara alami sesuai dengan objek domain.

Layanan domain digunakan untuk mengoordinasikan tugas antara beberapa entitas, melakukan perhitungan kompleks, atau menerapkan aturan bisnis yang melibatkan beberapa entitas. Seperti objek domain, layanan domain harus tetap terisolasi dari masalah infrastruktur.

Lapisan Layanan Aplikasi

Layanan aplikasi, juga dikenal sebagai kasus pengguna, mengoordinasikan interaksi antara domain dan dunia luar. Mereka tidak mengandung aturan bisnis atau pengetahuan, tetapi bertanggung jawab atas tugas seperti pengelolaan transaksi dan memicu peristiwa domain.

Layanan aplikasi mengoordinasikan lapisan domain dengan lapisan infrastruktur. Mereka memanggil layanan domain dan entitas domain untuk melakukan operasi terkait aturan bisnis, dan berinteraksi dengan lapisan infrastruktur untuk menangani tugas seperti penyimpanan, caching, atau pengiriman pesan.

Lapisan Infrastruktur, Pengujian, dan Antarmuka Pengguna

Lapisan terluar dalam Arsitektur Onion berisi elemen seperti antarmuka pengguna, pengujian, dan tugas-tugas infrastruktur. Ini adalah area perangkat lunak yang rentan terhadap perubahan dari waktu ke waktu karena perkembangan teknologi dan persyaratan. Oleh karena itu, mereka dipisahkan dari aturan bisnis inti, sehingga memastikan bahwa lapisan inti tidak terpengaruh oleh perubahan di lapisan-lapisan luar.

Sub-lapisan Infrastruktur mengkapsulasi masalah seperti persistensi data dan komunikasi jaringan, biasanya melalui repositori dan objek akses data.

Sub-lapisan Pengujian terdiri dari semua pengujian yang mendorong pengembangan dan memastikan kebenaran aplikasi. Ini termasuk pengujian unit, pengujian integrasi, dan pengujian end-to-end.

Akhirnya, sub-lapisan Antarmuka Pengguna menangani semua interaksi pengguna, termasuk logika presentasi dan penanganan masukan pengguna. Ini bisa mencakup antarmuka web, REST API, aplikasi desktop, dan lain-lain.

Mengimplementasikan Arsitektur Onion dalam Python

Implementasi Arsitektur Onion dalam Python melibatkan mendefinisikan kelas-kelas yang mewakili lapisan-lapisan yang berbeda dalam arsitektur: Model Domain, Layanan Domain, Layanan Aplikasi, dan Infrastruktur. Mari kita jelajahi bagaimana kita dapat strukturkan aplikasi sederhana mengikuti Arsitektur Onion.

Sebelum melanjutkan, mari kita pertimbangkan domain hipotetis, seperti sistem pemrosesan pesanan dasar.

Lapisan Model Domain

Pertama, mari kita definisikan entitas domain. Dalam contoh kita, ini bisa menjadi kelas-kelas Order dan Product. Kelas-kelas ini tidak mengandung logika terkait infrastruktur atau layanan aplikasi, fokusnya hanya pada logika bisnis.

domain_model.py
class Product:
    def __init__(self, id, name, price):
        self.id = id
        self.name = name
        self.price = price

class Order:
    def __init__(self, id, product, quantity):
        self.id = id
        self.product = product
        self.quantity = quantity
        self.total = self.calculate_total()

    def calculate_total(self):
        return self.product.price * self.quantity

Lapisan Layanan Domain

Selanjutnya, kita mengimplementasikan layanan domain. Layanan ini berisi operasi terkait logika bisnis yang melibatkan lebih dari satu entitas domain. Dalam contoh kita, mari kita pertimbangkan DiscountService yang menghitung diskon untuk suatu pesanan.

domain_services.py
class DiscountService:
    def apply_discount(self, order, discount_percentage):
        if discount_percentage < 0 or discount_percentage > 100:
            raise ValueError("Invalid discount percentage")

        order.total -= order.total * (discount_percentage / 100)
        return order

Lapisan Layanan Aplikasi

Lapisan layanan aplikasi berfungsi sebagai jembatan antara domain dan infrastruktur. Dalam contoh kita, OrderProcessingService dapat bertanggung jawab atas pembuatan pesanan dan penerapan diskon.

application_services.py
from domain_services import DiscountService

class OrderProcessingService:
    def __init__(self, order_repository, product_repository):
        self.order_repository = order_repository
        self.product_repository = product_repository
        self.discount_service = DiscountService()

    def process_order(self, order_id, product_id, quantity, discount_percentage):
        product = self.product_repository.get(product_id)
        order = Order(order_id, product, quantity)
        self.discount_service.apply_discount(order, discount_percentage)
        self.order_repository.save(order)

Lapisan Infrastruktur

Lapisan infrastruktur dapat mencakup repositori untuk mengakses data dari database. Dalam skenario dunia nyata, ini mungkin melibatkan kueri ke database SQL atau NoSQL, tetapi untuk kesederhanaan, kita akan menggunakan daftar dalam memori.

infrastructure.py
class OrderRepository:
    def __init__(self):
        self.orders = []

    def save(self, order):
        self.orders.append(order)

class ProductRepository:
    def __init__(self):
        self.products = []

    def get(self, product_id):
        for product in self.products:
            if product.id == product_id:
                return product

Referensi

https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/
https://medium.com/expedia-group-tech/onion-architecture-deed8a554423
https://dev.to/barrymcauley/onion-architecture-3fgl
https://iktakahiro.dev/python-ddd-onion-architecture
https://github.com/iktakahiro/dddpy
https://github.com/microsoft/cookiecutter-python-flask-clean-architecture/blob/main/docs/onion-architecture-article.md

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!