ERP'leri neden önce modüler monolit olarak kuruyoruz
Bölme kararı en çok neden erken ve yanlış verilir
Bir ERP projesinde ilk mimari toplantısı genelde şöyle geçer: stok, sipariş, faturalama ve müşteri yönetimi ayrı servisler olarak çizilir, çünkü konferans sunumlarındaki mimariler böyle görünür. Altı ay sonra aynı ekip, stok düşme, sipariş oluşturma ve fatura satırı açmanın üç servise yayıldığı bir işlemi hata ayıklamaya çalışır. Bu oturum, özelliği tek bir uygulama içinde yazmaktan daha uzun sürer. ERP projelerinin çoğu teknik değil mimari nedenlerle zorlanır ve sorun genelde bu ilk haftada başlar.
Biz ERP'leri önce modüler monolit olarak kuruyoruz. Bugüne kadar bu karardan pişman olduğumuz bir proje olmadı. Amaç karmaşıklıktan kaçmak değil. Neyin gerçekten birlikte değişmesi gerektiğini, neyin tutarlı kalması gerektiğini mimariye doğru yansıtmak.
Modül sınırı nereye çizilir
Modüler monolit tek parça, birbirine karışmış bir kod tabanı değildir. Tipik bir Java/Spring Boot ERP'de sınırı iş yeteneğine göre çiziyoruz: stok, satış siparişleri, satın alma, faturalama, müşteri kayıtları. Her modülün kendi paketi, kendi tablo kümesi var, çoğunlukla aynı PostgreSQL veritabanında kendi şeması. Bir modül diğerine yalnızca açık bir arayüz üzerinden ulaşır, başka bir modülün repository sınıfına doğrudan girmez.
- Stok modülü seviyeleri, rezervasyonları ve hareketleri sahiplenir.
- Satış modülü siparişi, fiyatlandırmayı, teslimat durumunu sahiplenir.
- Faturalama modülü fatura belgesini ve ödeme durumunu sahiplenir.
- Müşteri kayıtları iletişim bilgisini, ödeme koşulunu, yazışma geçmişini sahiplenir.
Kod incelemesinde tek kural geçerli: bir modül başka bir modülün servis arayüzünü çağırabilir, ama tablolarını sorgulayamaz. Bu kural tek başına sınırı ileride servise ayırmayı mümkün kılar, çünkü sınır daha ilk günden ağ çağrısı formatında düşünülmüş olur, henüz gerçek bir ağ çağrısı olmasa bile.
Tek işlemde kalması gereken ne
Bir ERP'de atomik olması gereken işlemler, tam olarak servisler arası atomik yapılması zor olan işlemlerdir: stok rezerve edip siparişi onaylamak, fatura kesip sipariş durumunu güncellemek, ödeme işleyip kredi bloğunu kaldırmak. Modüler monolitte bunlar tek veritabanı işlemi içinde, sıradan ACID garantisiyle çalışır. Erken bölünmüş bir yapıda aynı işlem bir saga, telafi adımları ve sistemin tutarsız kaldığı bir pencere gerektirir. Destek taleplerinin büyük kısmı tam da o pencereden çıkar.
Modüller arası bir olay mekanizması kullanıyoruz: aynı işlemde bir outbox tablosuna yazılıyor, sonra asenkron işleniyor. Ama yalnızca gecikmeye tahammülü olan etkiler için: bildirim göndermek, raporlama izdüşümünü güncellemek, belge üretimini tetiklemek. Kullanıcının bir sonraki ekranda görmesi gereken her şey işlem sınırının içinde kalır.
Ne zaman ayırıyoruz
Bir modülü ayrı servise çıkarmayı iki şey haklı çıkarır: gerçekten farklı bir ölçeklenme profili, ya da gerçekten farklı bir ekibin sahiplenmesi. Ağır toplama sorgularını işlemsel çekirdek yerine bir okuma replikası üzerinde çalıştırması gereken raporlama modülü farklı ölçeklenir, bu yüzden genelde ilk ayırdığımız parça o olur. Aynı ERP kataloğu üzerine kurulan müşteriye dönük bir e-ticaret vitrini de doğal bir bölünmedir, çünkü kendi dağıtım temposuna ve kendi kullanılabilirlik gereksinimine ihtiyaç duyar; bunların arka ofisteki toplu içe aktarma işine bağlı kalması gerekmez.
Sınırlar zaten temiz olduğu için bu ayırma mekanik bir iş haline gelir: iç arayüz bir HTTP ya da mesajlaşma sözleşmesine dönüşür, modül kendi dağıtım hattını alır, sistemin geri kalanı aynı arayüzü kullanmaya devam eder. Bunu canlı müşteri sistemlerinde, yeniden yazmadan yaptık.
Önerimiz
Her ERP'ye sıkı iç sınırları ve tek veritabanı olan bir modüler monolit olarak başlayın. Şu an gerçekten tutarlı kalması gereken işlemsel çekirdeği, gerekli olduğu sürece bu sınırın içinde tutun. Bir modülü yalnızca somut bir ölçekleme ya da sahiplik gerekçesi olduğunda ayrı servise çıkarın, bir diyagram öyle gösteriyor diye değil. İlk günde yapılan sınır işi, o ayırmayı bir yeniden yazım yerine ucuz bir adıma çevirir.