Cluster ERP mimari kurallarını hafızada değil testlerde tutar. Bu sayfa bunu yapan üç test dosyasını açıklar: tests/test_architecture_boundaries.py, tests/test_metadata_driven_rules.py ve tests/test_static_quality.py. Her testin neyi okuduğunu, neyi reddettiğini ve neyi görmediğini anlatır. EventBus'ın kendisi olay veri yolu sayfasında açıklanır.
Kısaca¶
- Hiçbir modül başka bir modülü import edemez. Tek istisna
cluster_erp.modules.auth.guards'tır (tests/test_architecture_boundaries.py:24,tests/test_architecture_boundaries.py:46-57). - Her modül klasöründe bir
module.pyve kendine ait en az bir HTTP rotası vardır (tests/test_architecture_boundaries.py:60-72). - Genel web motorları iş modülü adlarıyla karşılaştırma yapmaz (
tests/test_architecture_boundaries.py:75-87). - Bir zamanlar genel web kodunda duran kurallar artık modül metadata'sında bildirilir ve testler metadata'yı denetler (
tests/test_metadata_driven_rules.py:1-5). - Ruff ve mypy yalnız değişen dosyalarda değil, tüm pakette sıfır bulgu bildirmelidir (
tests/test_static_quality.py:1-11).
Nasıl çalışır¶
Sınır testi kaynak dosyaları metin veya sözdizimi ağacı olarak okur. Modülleri import etmez. Metadata testi her modülü import eder ve get_metadata çağırır. Statik test Ruff ve mypy'yi alt süreç olarak çalıştırır.
Akış şeması, sınır testinin bir modül klasöründeki dosya için hangi import'lara izin verdiğini gösterir.
flowchart TD
file["src/cluster_erp/modules/X içindeki Python dosyası"] --> imp{"cluster_erp.modules.Y import ediyor mu?"}
imp -->|hayır| ok1["izinli"]
imp -->|"Y, X'e eşit"| ok2["izinli"]
imp -->|"ad DOOR'a eşit"| ok3["izinli"]
imp -->|"başka herhangi bir Y"| fail["ihlal: yol, satır, import"]Düzyazıyla: cluster_erp.modules.* adını taşımayan bir import geçer. Dosyanın kendi modülünün import'u geçer. Tam olarak cluster_erp.modules.auth.guards import'u geçer. Bir modülün diğer her import'u yolu ve satırıyla ihlal olarak listelenir (tests/test_architecture_boundaries.py:48-56).
Modül yalıtımı¶
MODULE_NAMES, src/cluster_erp/modules/ altında __ ile başlamayan her klasördür (tests/test_architecture_boundaries.py:25-27). _imports her dosyanın sözdizimi ağacını gezer ve import ile from ... import adlarını satır numaralarıyla toplar (tests/test_architecture_boundaries.py:31-39). test_modules_exist boş bir taramaya karşı korur: en az 20 modül klasörü ister (tests/test_architecture_boundaries.py:42-43).
Her modül bir uygulamadır¶
test_every_module_is_an_application_with_its_own_api önce module.py dosyası olmayan modülleri listeler. Sonra her modülde @router.get( gibi rota dekoratörlerini sayar ve hiç olmayanları listeler (tests/test_architecture_boundaries.py:60-72).
Genel motorlar ve iş adları¶
BUSINESS_MODULES, auth, records ve logs dışındaki her modüldür (tests/test_architecture_boundaries.py:28). Test gen-list.js, gen-detail.js, gen-form.js, entity.js ve gen-settings.js dosyalarında bu adlardan biriyle yapılan bir karşılaştırma veya case arar (tests/test_architecture_boundaries.py:75-87).
Metadata güdümlü kurallar¶
tests/test_metadata_driven_rules.py her modülün metadata'sını ModuleRegistry().discover() ile yükler (tests/test_metadata_driven_rules.py:23-29). Denetimleri şunlardır:
| Test | Koruduğu kural | Kaynak |
|---|---|---|
test_every_is_active_column_declares_the_active_flag_formatter |
Bir is_active liste sütunu active_flag biçimleyicisini bildirir |
tests/test_metadata_driven_rules.py:36-48 |
test_guided_party_creation_is_declared_in_metadata |
Taraf oluşturma customer, supplier ve employee rollerini metadata'dan sunar |
tests/test_metadata_driven_rules.py:51-60 |
test_record_documents_provider_is_declared_by_capability |
record_documents yeteneğini tam olarak bir modül sağlar ve bu documents'tır |
tests/test_metadata_driven_rules.py:63-74 |
test_assistant_starters_are_module_metadata_in_both_languages |
Asistan başlangıç soruları İngilizce ve Türkçe etiket taşır | tests/test_metadata_driven_rules.py:77-82 |
test_generic_web_code_names_no_module_paths_permissions_or_language_columns |
On bir genel web dosyası /documents/ yolu, document. yetkisi, label_tr veya label_en sütunu ve dil dalı adlandırmaz |
tests/test_metadata_driven_rules.py:85-112 |
test_home_screen_has_no_layout_rewrite_shims |
home.js yerleşim göç yamaları içermez |
tests/test_metadata_driven_rules.py:115-119 |
test_ui01_rewrites_retired_tiles_and_stamps_the_layout |
ui01 göçü emekli ana ekran kutucuklarını yeniden yazar ve tekrar çalıştırmaya dayanıklıdır |
tests/test_metadata_driven_rules.py:122-155 |
test_home_widgets_are_module_metadata_rendered_by_module_bundles |
Ana ekran bileşenleri modüllerce bildirilir ve her modülün kapılı paketiyle çizilir | tests/test_metadata_driven_rules.py:158-193 |
test_working_calendar_is_the_calendars_modules_custom_tab |
Çalışma takvimi sekmesi calendars modülüne ait bir custom sekmedir |
tests/test_metadata_driven_rules.py:196-214 |
Statik kalite mandalı¶
test_ruff_is_zero_across_the_repo, ruff check komutunu src/, tests/ ve scripts/ üzerinde çalıştırır (tests/test_static_quality.py:26-35). test_mypy_is_zero_across_the_package, mypy komutunu src/cluster_erp üzerinde çalıştırır (tests/test_static_quality.py:21-23, tests/test_static_quality.py:38-46). İkisi de herhangi bir bulguda başarısız olur.
Neden böyle kurulmuştur¶
Sınır testinin modül belge dizesi kuralların "held by a test instead of by memory" olduğunu ve koruma kapısının "a platform dependency injection, not a business call" olduğunu söyler (tests/test_architecture_boundaries.py:1-7). Metadata testi, bir kuralı genel koda geri gömen bir gerilemenin "fails here first" olduğunu söyler (tests/test_metadata_driven_rules.py:1-5). Statik test, yalnız değişeni ölçen bir süitin "lets old debt grow back silently" olduğunu söyler (tests/test_static_quality.py:3-6).
Kurallar ve sınırlar¶
- Modüller arası iş
src/cluster_erp/core/contracts.pyiçindeki sözleşmelerden geçer. Bu dosyadaEvent'ten türeyen 146 veQuery'den türeyen 118 sınıf vardır (grep -c "^class .*(Event):"vegrep -c "^class .*(Query):"ile sayıldı). - Koruma kapısı
src/cluster_erp/modulesaltında 146 kez import edilir (grep -rn "cluster_erp.modules.auth.guards"ile sayıldı). - Başka bir modülün verisine ihtiyaç duyan modül veri yolu üzerinden sorar. Örnek: ürün kırılımı doğrulaması
products_and_servicestarafından işlenenValidateProductBreakdowngönderir (src/cluster_erp/core/product_breakdown.py:11-13,src/cluster_erp/modules/products_and_services/module.py:131).
Diğer parçalarla etkileşim¶
src/cluster_erp/server/routes/ içindeki uygulama katmanı taranan klasörün dışındadır. party_composite.py dosyasının belirttiği gibi tek bir istekte birden çok modül servisini çağırabilir (src/cluster_erp/server/routes/party_composite.py:4-9). Yalnız EventBus ile iletişim karar kaydı kuralın bağlamını verir. Metadata güdümlü arayüz kaydı web kurallarını kapsar.
Sınırlar ve açık noktalar¶
- Sınır testi yalnız Python import'larını inceler. Ham SQL ile başka bir modülün tablosuna ulaşan bir modül saptanmaz. Herhangi bir modülün bunu yapıp yapmadığı koddan belirlenemedi; bunu arayan test yok.
- Genel motor testi beş dosyayı ve yalnız iş modülü adlarına karşı karşılaştırma kalıplarını denetler (
tests/test_architecture_boundaries.py:76-78). - CI Ruff'ı yalnız
srcvetestsüzerinde çalıştırır (.github/workflows/ci.yml:51); betik klasörü yalnızpytesttests/test_static_quality.pydosyasını çalıştırdığında denetlenir.
Tanıtılan terimler¶
| Terim | Kod tanımlayıcısı | Tanım | Türkçe terim | Kaynak |
|---|---|---|---|---|
| guards door | DOOR |
Diğer her modülün import edebileceği tek modül yolu: cluster_erp.modules.auth.guards. |
Koruma kapısı | tests/test_architecture_boundaries.py:24 |
| business module | BUSINESS_MODULES |
Genel motor testinin kullandığı, auth, records ve logs dışındaki her modül klasörü. |
İş modülü | tests/test_architecture_boundaries.py:28 |
| static quality ratchet | test_static_quality.py |
Kod tabanının tamamında herhangi bir Ruff veya mypy bulgusunda başarısız olan pytest dosyası. | Statik kalite mandalı | tests/test_static_quality.py:1-11 |
İlgili sayfalar¶
92f8051 numaralı commit ile 2026-11-13 tarihinde doğrulandı.