امنیت، هویت، استقرار و تابآوری · فصل ۶ — Chaos، Feature Flags، Rollout و ADR · 108
Architecture Change Control, ADR و Supersession
میتواند سرویس را اجرا کند اما lifecycle، health، rollout، observability و recovery را بهصورت سیستماتیک مدیریت نمیکند. موضوع جاری: «Architecture Change Control, ADR و Supersession». میتواند برای «Architecture Change Control, ADR و Supersession» run/release model و signals/recovery checks لازم را برای یک سرویس محدود طراحی کند.
خلاصهٔ درس
میتواند سرویس را اجرا کند اما lifecycle، health، rollout، observability و recovery را بهصورت سیستماتیک مدیریت نمیکند. موضوع جاری: «Architecture Change Control, ADR و Supersession».
میتواند برای «Architecture Change Control, ADR و Supersession» run/release model و signals/recovery checks لازم را برای یک سرویس محدود طراحی کند.
خروجی این درس
میتواند برای «Architecture Change Control, ADR و Supersession» run/release model و signals/recovery checks لازم را برای یک سرویس محدود طراحی کند.
1. مسئله: تصمیم معماری اگر فقط در چت بماند، قابل حسابرسی نیست
یک تصمیم معماری ممکن است ابتدا در جلسه یا چت شکل بگیرد، بعد در کد اجرا شود و چند ماه بعد هیچکس نداند چرا آن انتخاب انجام شده است. مشکل شدیدتر زمانی رخ میدهد که متن تصمیم پذیرفتهشده بعداً بیسروصدا ویرایش شود؛ در این حالت تاریخچه از بین میرود و reviewer نمیتواند تشخیص دهد تصمیم اولیه چه بوده، چه چیزی تغییر کرده و چرا.
خروجی این درس Architecture Decision Supersession Record v1 است. این رکورد decision را از implementation جدا نگه میدارد، accepted history را حفظ میکند، supersession را صریح ثبت میکند و drift بین تصمیم جاری و شواهد اجرا را پنهان نمیکند.
2. ADR چیست و چه چیزی را ثبت میکند
ADR یا Architecture Decision Record برای ثبت یک انتخاب معماری مهم استفاده میشود. در راهنمای AWS، هر ADR تصمیم، context و consequences را ثبت میکند و مجموعه ADRها یک decision log میسازد. هدف اصلی این است که فقط «چه چیزی انتخاب شد» نماند؛ دلیل، شرایط و trade-offهای انتخاب هم برای اعضای فعلی و آینده قابل بازیابی باشد.
ADR یک architecture specification کامل نیست. همچنین جای implementation، test یا runtime evidence را نمیگیرد. آن را بهعنوان رکورد تصمیم ببین، نه اثبات اجرای تصمیم.
3. Lifecycle: Proposed، Accepted، Rejected و Superseded
یک ADR معمولاً از حالت Proposed وارد review میشود. تیم میتواند آن را برای rework باز نگه دارد، Reject کند یا Accept کند. راهنمای AWS میگوید پس از acceptance، ADR بهعنوان یک رکورد immutable در نظر گرفته میشود. اگر insight جدید تصمیم را تغییر دهد، راه درست ساخت ADR جدید و طیکردن review جدید است.
وقتی ADR جدید پذیرفته شد، ADR قبلی Superseded میشود. این به معنی پاککردن یا بازنویسی ADR قدیمی نیست؛ تصمیم قدیمی باید در decision log باقی بماند تا زنجیره تاریخ قابل ردیابی باشد.
4. حداقل محتوای یک ADR قابل review
حداقل مفید برای ADR شامل Context، Decision و Consequences است. AWS همچنین status و changelog را برای reviewability لازم میداند و توصیه میکند context راهحلهای بررسیشده را هم نشان دهد. در این درس، برای evidence دقیقتر Alternatives و Trade-offs را نیز صریح ثبت میکنیم.
اگر یک یادداشت فقط بگوید «از Kafka استفاده میکنیم» یا «PostgreSQL انتخاب شد»، هنوز معلوم نیست مشکل چه بوده، گزینههای دیگر چه بودهاند و چه هزینههایی پذیرفته شده است. چنین یادداشتی برای change control ضعیف است.
5. Architecturally significant را از انتخاب جزئی جدا کن
هر تغییر کد ADR نمیخواهد. تصمیمهایی که ساختار، non-functional requirements، dependencyها، interfaceهای منتشرشده یا construction techniqueهای مهم را تغییر میدهند معمولاً معماریترند. در مقابل، نام یک متغیر محلی یا یک refactor بیاثر روی boundary و رفتار سیستم معمولاً ADR مستقل لازم ندارد.
این مرز کاملاً مکانیکی نیست. judgment انسانی لازم است: اگر انتخاب، دامنه تغییر، coupling، operational behavior یا هزینه برگشت معنیداری ایجاد میکند، ثبت آن بهعنوان ADR قابل دفاعتر میشود.
6. Decision Log و مالکیت تصمیم
ADR منفرد زمانی ارزش بیشتری دارد که در یک decision log مرکزی قرار گیرد. هر رکورد باید ID، status، owner/date و ارتباطش با تصمیمهای قبلی را روشن کند. تاریخچه تغییر نیز باید نشان دهد چه کسی و چه زمانی state یا metadata مجاز را تغییر داده است.
این مالکیت به معنی «مالک تصمیم هرگز اشتباه نمیکند» نیست. یعنی مسئول review، ارتباط و نگهداری record مشخص است و تغییر تصمیم از مسیر قابل ردیابی انجام میشود.
7. Supersession: تغییر تصمیم بدون پاککردن گذشته
فرض کن ADR-002 قبلاً accepted شده و انتخاب A را ثبت کرده است. حالا constraints جدید نشان میدهد B مناسبتر است. anti-pattern این است که ADR-002 را باز کنی و متن Decision را از A به B تغییر دهی. با این کار مشخص نمیشود سیستم در دوره قبل بر چه مبنایی طراحی شده بود.
الگوی سالم: ADR-003 را بساز، context جدید و alternatives را ثبت کن، آن را review کن و اگر accepted شد، در ADR-003 فیلد supersedes: ADR-002 را قرار بده؛ سپس وضعیت ADR-002 را Superseded کن و هر دو را نگه دار.
8. Documentation state با Implementation state یکی نیست
ممکن است decision log کاملاً درست باشد اما runtime هنوز مطابق تصمیم قدیمی کار کند. بنابراین Accepted بودن ADR جدید بهتنهایی conformance را ثابت نمیکند. برای change control، باید implementation evidence جداگانه داشته باشی: code/config snapshot، manifest، test یا architecture check متناسب با scope.
در این درس، پیوند ADR با implementation evidence یک extension آموزشی MAKNOW است. هدف این است که «تصمیم پذیرفتهشده» را با «چیزی که واقعاً مشاهده شده» یکی نگیریم.
9. Architecture Drift را OPEN نگه دار
اگر active ADR میگوید interaction باید async باشد ولی manifest هنوز sync path قدیمی را نشان میدهد، document را تغییر نده تا با runtime جور شود. discrepancy را بهعنوان drift ثبت کن. Record باید بگوید evidence چیست، conformance فعلی چیست، review trigger چیست و reconciliation action چه خواهد بود.
وقتی evidence کافی نیست نیز نتیجه را UNKNOWN نگه دار. نداشتن شاهد مجوز ساختن نتیجه مثبت نیست.
10. Failure probe: ویرایش silent یک Accepted ADR
در fixture اول، checksum نسخه تاریخی ADR با نسخه فعلی یکی نیست و ADR قبلاً Accepted بوده است. سبز بودن tests یا درست بودن تصمیم جدید این مشکل را پاک نمیکند. ابتدا باید historical record preserved شود یا نسخه معتبر آن بازیابی شود؛ سپس change از طریق ADR جدید دنبال شود.
اگر accepted history را rewrite کنی، بعداً نمیتوانی causal chain تصمیم و implementation قبلی را بازسازی کنی. این شکست اصلی تمرین است.
11. Failure probe: دو ADR پذیرفتهشده بدون supersedes link
حالت دوم ظاهراً تمیزتر است: ADR قدیمی و جدید هر دو وجود دارند و هر دو Accepted هستند، اما ADR جدید مشخص نمیکند کدام تصمیم را supersede میکند. نتیجه دو تصمیم ظاهراً current و متعارض است.
Repair باید relationship را صریح کند و review state را دوباره معتبر سازد. صرفاً جدیدتر بودن timestamp نباید بهصورت مخفیانه تعیین کند کدام تصمیم active است.
12. Record را ردیفی و evidence-first بساز
برای هر تصمیم این ستونها را پر کن: ADR ID، Status، Context، Alternatives، Decision، Consequences، Supersedes، Implementation Evidence، Conformance، Drift، Review Trigger و Reconciliation Action. هر conclusion باید به observation یا authority مشخص متصل باشد.
سه نوع statement را قاطی نکن: direct evidence، inference/policy choice و unknown. این تفکیک باعث میشود reviewer بداند کدام بخش مشاهده شده و کدام بخش judgment است.
13. Reconciliation Action باید متناسب با mismatch باشد
اگر مشکل فقط missing supersedes link است، repair در decision history انجام میشود. اگر decision chain درست است ولی code با تصمیم فعال نمیخواند، action روی implementation یا روی تصمیم جدید خواهد بود. اگر evidence ناقص است، action اول جمعآوری evidence است، نه force کردن PASS.
هدف «سبز کردن جدول» نیست؛ هدف این است که وضعیت فعلی و مسیر reconciliation قابل دفاع باشند.
14. Lab: زنجیره تصمیم را از fixture بازسازی کن
تمرین محلی هشت case مصنوعی دارد: baseline سالم، accepted-history tamper، missing supersedes link، implementation drift، تصمیم trivial، proposal هنوز پذیرفتهنشده، decision rejected و یک transfer با مسئله معماری متفاوت. run_checks.py فقط ساختار fixture را بررسی میکند؛ پاسخ تصمیم را در starter قرار نداده است.
در starter.py هشت dimension را برای هر case برگردان: decision status، historical integrity، option set، supersession link، active decision، implementation conformance، drift register و significance judgment. هر چیزی که از evidence قابل اثبات نیست باید OPEN/UNKNOWN بماند.
15. Transfer: یک decision chain متفاوت را از صفر بساز
در transfer، موضوع تصمیم، alternatives، status history و mismatch اجرا تغییر میکنند. identifier یا نتیجه case اول را کپی نکن. ابتدا significance را بسنج، context و option set را بساز، active decision را از status/supersession chain استخراج کن و بعد implementation evidence را با همان active decision مقایسه کن.
خروجی زمانی قابل دفاع است که accepted history حفظ شده باشد، supersession صریح باشد، documentation و runtime evidence جدا سنجیده شوند، و هیچ drift یا unknown با rewrite کردن تاریخچه پنهان نشده باشد.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
Q1 retrieval
What changes after an ADR is accepted if new insight requires a different architecture decision?
Q2 application
An accepted ADR has been silently edited. What must the change-control record do first?
Q3 diagnosis
The ADR chain is valid but code still implements the superseded decision. How should the state be recorded?
Q4 decision
A developer wants an ADR for a local variable rename. What should be checked before creating one?
Q5 transfer
A second repository has different alternatives and a new status history. How is the current decision determined?
ملاکهای ارزیابی (rubric)
A passing response must:
- preserve accepted decision history instead of silently rewriting it;
- capture context, alternatives, decision, consequences, status, and change relationship for an architecturally significant choice;
- make supersession explicit and derive the active decision from the decision chain rather than timestamp recency;
- compare implementation evidence with the active decision and keep nonconformance as OPEN drift;
- preserve UNKNOWN when evidence is insufficient;
- distinguish an architecturally significant choice from a trivial local code preference;
- rebuild the transfer case independently rather than copying identifiers or the first-case conclusion.
منابع و تازگی
مطالعهٔ موارد (case studies)
تصاویر درس
فایلهای آزمایشگاه
This exercise uses synthetic local evidence only. No production repository, credential, customer data, or external service is required.
- Run
python run_checks.pyto verify the fixture structure. - Implement
analyze_change(case)instarter.py. - For each case, return these eight keys:
decision_status,historical_integrity,option_set,supersession_link,active_decision,implementation_conformance,drift_register,significance_judgment. - Base every value on the supplied fields. Keep unsupported conclusions OPEN or UNKNOWN.
- Rebuild the transfer case from its own concern, alternatives, status history, and implementation evidence. Do not copy the baseline decision.
The structural check does not reveal the expected classifications. It only proves that the evidence needed for the exercise is present.