Fəsil 04 · 4 dəq oxu

Decomposition və boundary-lər

Decomposition və boundary-lər

Hər architecture, mahiyyət etibarilə, xətlər toplusudur. Xəttin bir tərəfində şeylər sərbəst dəyişə bilər; onu keçmək razılaşma tələb edir. Xətləri yaxşı çəkin — komandalar paralel işləyər və dəyişikliklər lokal qalar. Pis çəkin — hər feature danışıqlara çevrilər.

Bu fəsil xətləri harada çəkməkdən bəhs edir.

Məqsəd: high cohesion, low coupling

Bu iki söz o qədər təkrarlanıb ki, kəskinliyini itirib. Yenidən ifadə edək:

  • boundary daxilindəki şeylərin birlikdə dəyişmə dərəcəsidir. module elə module-dur ki, tək bir biznes səbəbi adətən yalnız ona toxunur.
  • boundary-nin müxtəlif tərəflərindəki şeylərin birlikdə dəyişməyə məcbur olma dərəcəsidir. module cütü elə cütdür ki, birindəki dəyişiklik digərində dəyişikliyə məcbur edir.

Praktik test diaqram deyil. Change history-dir. Son əlli pull request-ə baxın. Hansı fayllar birlikdə dəyişdirilir? Bu fayllar eyni module-da olmaq istəyir. Hansı module-lar birlikdə dəyişdirilir? Bu module-ların ya problemi var, ya da onlar bir module olmalıdır.

Technical layer-ə görə yox, domain-ə görə decompose edin

Ən geniş yayılmış decomposition səhvi texniki xətlər üzrə dilimləməkdir: "services" package-i, "repositories" package-i, "controllers" package-i. Bu düzülüş hər biznes dəyişikliyinin hər package-ə toxunmasına zəmanət verir.

Domain anlayışına görə decomposition isə, əksinə, ordering, inventory, billing kimi module-lar verir. Endirimlərin işləmə qaydasına dəyişiklik bir yerdə yaşayır. Technical layer-lər hələ də mövcuddur, amma hər domain module-unun içində.

Domain-driven design bu ideyaya ad verir: — model-in və onun lüğətinin ardıcıl olduğu ərazi. Billing context-ində "Customer"in credit limit-i var; marketing context-ində "Customer"in segment-i və preference set-i var. Onları bir obyektə sığışdırmağa məcbur etmək heç kimi qane etməyən bir əcaib yaradır.

Boundary-nin yanlış yerdə olmasının əlamətləri

  • Chatty interface-lər. Bir operation ərzində bir-birini onlarla dəfə çağıran iki module iki papaq geyinmiş bir module-dur.
  • Shared mutable data. Hər iki tərəf eyni cədvələ yazırsa, boundary yoxdur, sadəcə slayddakı xətt var.
  • Anemic yarılar. Bir tərəf bütün data-nı, digəri bütün logic-i saxlayır. Boundary anlayışın ortasından kəsir.
  • Sızan lüğət. Interface məqsədli qurulmuş contract əvəzinə daxili data model-i açır, ona görə daxili refactoring-lər çevrilir.
  • Eynivaxtlı . İki həmişə birlikdə ship olunursa, onların müstəqilliyi uydurmadır.

Interface-lər vədlərdir

Boundary yalnız onun üzərindəki contract qədər yaxşıdır. Üç xüsusiyyət contract-ı davamlı edir:

  1. Dar. Implementation-da olanı deyil, consumer-lərin ehtiyac duyduğunu açın. Nə qədər az field və operation varsa, bir o qədər az şey sına bilər.
  2. Mənada sabit. status adlı field gələn il də eyni mənanı daşımalıdır. Adı dəyişmədən semantics-i dəyişmək pozmanın ən amansız növüdür.
  3. Niyyətlə versioned. Additive dəyişikliklər pulsuz olmalıdır. nadir, explicit və migration dövrü ilə müşayiət olunan olmalıdır.

Consumer tərəfdə tolerant reader-lər kömək edir: başa düşmədiyiniz field-ləri nəzərə almayın, çatışmayan optional field-lərə dözün və ordering-dən asılı olmayın.

Data ownership

Ən nəticəli boundary qərarı data-ya kimin sahib olduğudur. Distributed sistemlərdə qayda ifadə etmək üçün sadə, əməl etmək üçün çətindir: hər data parçasının tam olaraq bir writer-i var. Qalan hər kəs copy, view və ya API alır.

real edən məhz bu qaydadır. İki service bir database cədvəlini share edirsə, birindəki schema dəyişikliyi hər ikisində schema dəyişikliyidir və əlinizdə var: bütün network xərci, heç bir autonomy.

Copy-lərə ehtiyac olan yerdə freshness barədə explicit olun. "Search-də göstərilən inventory sayları otuz saniyəyə qədər stale ola bilər" — bu, product adamlarının üzərində düşünə biləcəyi design qərarıdır. Səssiz staleness baş verməyi gözləyən bug report-dur.

Boundary-lər və komandalar

deyir ki, sistemlər onları quran təşkilatların kommunikasiya strukturunu əks etdirir. Əksi də doğrudur və daha faydalıdır: müəyyən sistem strukturu istəyirsinizsə, komandaları ona uyğun düzün.

Hər tərəfində bir komanda olan boundary-yə hörmət ediləcək, çünki onu keçmək söhbət tələb edir. Bir komandanın ortasına düşən boundary aşınacaq, çünki contract-a əməl etməkdənsə o tərəfə uzanmaq daha sürətlidir. Heç biri yanlış deyil, amma hansını aldığınızı bilməlisiniz.

Mövcud sistemin decomposition-ı

başlayanda işləyən ardıcıllıq budur:

  1. müəyyən edin — change history-dən və domain lüğətindən istifadə edərək.
  2. içində explicit edin: published interface-lərə malik module-lar, aralarında shared cədvəllər yoxdur. Bu, Fəsil 3-dəki .
  3. Bununla yaşayın. Bir çox sistem elə burada dayanmalıdır.
  4. Yalnız səbəb olduqda extract edin və səbəb demək olar ki, həmişə : bir module fərqli scale olunmalı, independent olunmalı və ya başqa dildə yenidən yazılmalıdır.

extraction-ı incremental edir: traffic-in bir dilimini yeni component-ə route edin, verify edin, genişləndirin, köhnə path-i təqaüdə göndərin. Big-bang rewrite-lar iki il itirməyin ən etibarlı yoludur.

Hazırkı sisteminiz haqqında suallar

  1. Son əlli dəyişiklikdə hansı fayllar həmişə birlikdə dəyişir, amma fərqli module-larda yaşayır?
  2. Hansı cədvəlin birdən çox writer-i var?
  3. İki komandanın hörmət etdiyi bir boundary-nin və tək komandanın müntəzəm olaraq saymadığı bir boundary-nin adını çəkin.