TG Telegram Group & Channel
کانال مکتب‌خانه DDD | United States America (US)
Create: Update:

🎯معرفی کوتاه Behavior as Data Pattern

در جریان طراحی و توسعه دومین‌های نرم‌افزاری پیچیده، بارها و بارها با چالشی تکراری مواجه شدم:
فیلدی در مدل دامنه که ابتدا صرفاً یک مقدار داده‌ای (Data) به نظر می‌رسد، مثلاً Type، Category یا Status، اما به‌مرور زمان، همین فیلد ساده شروع می‌کند به تعیین رفتارسیستم. درظاهر هنوز با داده سروکار داریم، ولی در واقع داریم با «رفتار کد شده در دل داده»مواجه می‌شویم.

این مسئله را در دامنه‌های گوناگون تجربه کردم: از حسابداری گرفته تا فروش، از سیستم‌های پرداخت آنلاین تا رزرو آنلاین بلیت هواپیما. در هر مورد، ساختار اولیه‌ی سیستم به‌ظاهر ساده و قابل مدیریت بود، اما به‌مرور زمان شرط‌ها (if/switch) رشد می‌کردند، تست‌پذیری کاهش می‌یافت،و تغییرات جدید باعث ریسک شکستن بخش‌های قدیمی می‌شدند.

برای پاسخ به این چالش، به تدریج الگوی Behavior as Data را فرموله کردم، مدل ذهنی‌ای برای تشخیص زمان مناسب برای عبور از«داده» به «رفتار».

👁‍🗨 یک مثال واقعی ببینیم:
یک JournalEntry با فیلدی از جنس JournalEntryType که می‌تونست Sales، Purchase یاAdjustment باشه. در ابتدا با یک switch ساده در متد PostTo() کار راه می‌افتاد. اما به‌مرور زمان با افزوده شدن قوانین مالیاتی، تفاوت‌های بین انواع ثبت، و استثناهای تجاری متعدد، این فیلد تبدیل شد به گره‌ای بحرانی از منطق پراکنده، کدهای شرطی و دردسرهای تست‌پذیری و قص علی هذا.

enum JournalEntryType {
Sales,
Purchase,
Adjustment
}

class
JournalEntry {
JournalEntryType Type;
void PostTo(Ledger ledger) {

switch(Type) {

case Sales:
ledger.Credit(...); break;

case Purchase: ledger.Debit(...); break;

case Adjustment: ledger.Adjust(...); break;

}
}
}


این طراحی در ابتدا قابل قبول بود، اما هر تغییر دامنه‌ای باعث رشد شرط‌ها و شکنندگی کد می‌شد.

برای رفع این مشکل، به الگوی Behavior as Data رسیدم. در این الگو، وقتی می‌بینیم مقدار یک فیلد باعث تغییر در رفتار سیستم می‌شود، آن فیلد دیگر «داده» نیست، بلکه «نماینده‌ی رفتار» است


interface IPostingStrategy {
void PostTo(Ledger ledger);
}
class SalesEntry : IPostingStrategy { ... }
class
JournalEntry {
IPostingStrategy Strategy;
void PostTo(Ledger ledger) =>Strategy.PostTo(ledger);
}

نتیجه:
تست‌پذیری بهتر، حذف شرط‌ها، و گسترش‌پذیری بدون اثر جانبی.
----------------

🧠 معرفی Behavior as Data Pattern
الگوی
Behavior as Data یک الگوی ساختاری صرف نیست، بلکه یک بینش طراحی (modeling insight) است. الگوی Behavior as Data به ما می‌گوید:
اگر مقدار یک فیلد باعث تغییر در رفتار سیستم می‌شود، آنگاه آن فیلد دیگر صرفاً یک داده نیست، بلکه نماینده‌ی یک رفتار است و باید به یک مدل رفتاری (Behavioral Model) تبدیل شود.

به زبان ساده، هر زمان که سیستم به جای "تصمیم‌گیری با داده"، وارد فاز "تغییر رفتار بر اساس داده" می‌شود، زمان استفاده از این الگو فرارسیده است.
به عبارت دیگر:
💡اگر سیستم به جای آنکه با داده تصمیم بگیرد، بر اساس داده عمل متفاوتی انجام می‌دهد، زمان بازطراحی فرا رسیده.

مزایا و آثار این بازطراحی

حذف منطق شرطی تودرتو
تسهیل تست واحد برای هر رفتار
باز بودن مدل برای توسعه رفتارهای جدید بدون تغییر ساختار اصلی
بهبود شفافیت مدل دامنه برای ذینفعان (توسعه‌دهندگان، مدیران محصول و تحلیل‌گران)
----------------

چه زمانی باید از Behavior as Data استفاده کرد؟
برای تشخیص نیاز به این الگو، می‌توان از این هیوریستیک‌ها استفاده کرد:
🟠 مقدار فیلد منطق رفتار را تعیین می‌کند
آیا تغییر مقدار Type باعث تغییر در اجرای متدی مثل Submit() یا Process() می‌شود؟
🔵 وجود شرط‌های متعدد و در حال رشد بر اساس آن فیلد
آیا در نقاط مختلف سیستم شرط‌هایی مشابه if (type == ...) در حال تکرار است؟
🟣 نیاز به تست مستقل هر رفتار وجود دارد
آیا نمی‌توان به‌راحتی رفتار مرتبط با یک مقدار خاص را به‌صورت جداگانه تست کرد؟


چرا این الگو مهم است؟
در یک کلام باید بگم که بسیاری از مشکلات مزمن در طراحی سیستم‌ها (مثل پیچیدگی تدریجی، شرط‌های کلافه کننده، تست‌ناپذیری، و وابستگی‌هایشدید و شکننده) از همین بی‌توجهی به تمایز بین «داده» و «رفتار» ناشی می‌شود.

📘 این الگو بخشی از مجموعه الگوهای طراحی و مدلسازی من در کتاب «Language-Driven Design» که در حال نگارش آن هستم، است.


📎 مطالعه مقاله‌ی کامل الگو، با مثال‌های متنوع و تکنیک‌های بازطراحی:

https://medium.com/@masoudbahrami/introducing-behavior-as-data-pattern-1e4c82d1ede6

🎯معرفی کوتاه Behavior as Data Pattern

در جریان طراحی و توسعه دومین‌های نرم‌افزاری پیچیده، بارها و بارها با چالشی تکراری مواجه شدم:
فیلدی در مدل دامنه که ابتدا صرفاً یک مقدار داده‌ای (Data) به نظر می‌رسد، مثلاً Type، Category یا Status، اما به‌مرور زمان، همین فیلد ساده شروع می‌کند به تعیین رفتارسیستم. درظاهر هنوز با داده سروکار داریم، ولی در واقع داریم با «رفتار کد شده در دل داده»مواجه می‌شویم.

این مسئله را در دامنه‌های گوناگون تجربه کردم: از حسابداری گرفته تا فروش، از سیستم‌های پرداخت آنلاین تا رزرو آنلاین بلیت هواپیما. در هر مورد، ساختار اولیه‌ی سیستم به‌ظاهر ساده و قابل مدیریت بود، اما به‌مرور زمان شرط‌ها (if/switch) رشد می‌کردند، تست‌پذیری کاهش می‌یافت،و تغییرات جدید باعث ریسک شکستن بخش‌های قدیمی می‌شدند.

برای پاسخ به این چالش، به تدریج الگوی Behavior as Data را فرموله کردم، مدل ذهنی‌ای برای تشخیص زمان مناسب برای عبور از«داده» به «رفتار».

👁‍🗨 یک مثال واقعی ببینیم:
یک JournalEntry با فیلدی از جنس JournalEntryType که می‌تونست Sales، Purchase یاAdjustment باشه. در ابتدا با یک switch ساده در متد PostTo() کار راه می‌افتاد. اما به‌مرور زمان با افزوده شدن قوانین مالیاتی، تفاوت‌های بین انواع ثبت، و استثناهای تجاری متعدد، این فیلد تبدیل شد به گره‌ای بحرانی از منطق پراکنده، کدهای شرطی و دردسرهای تست‌پذیری و قص علی هذا.
enum JournalEntryType {
Sales,
Purchase,
Adjustment
}

class
JournalEntry {
JournalEntryType Type;
void PostTo(Ledger ledger) {

switch(Type) {

case Sales:
ledger.Credit(...); break;

case Purchase: ledger.Debit(...); break;

case Adjustment: ledger.Adjust(...); break;

}
}
}


این طراحی در ابتدا قابل قبول بود، اما هر تغییر دامنه‌ای باعث رشد شرط‌ها و شکنندگی کد می‌شد.

برای رفع این مشکل، به الگوی Behavior as Data رسیدم. در این الگو، وقتی می‌بینیم مقدار یک فیلد باعث تغییر در رفتار سیستم می‌شود، آن فیلد دیگر «داده» نیست، بلکه «نماینده‌ی رفتار» است


interface IPostingStrategy {
void PostTo(Ledger ledger);
}
class SalesEntry : IPostingStrategy { ... }
class
JournalEntry {
IPostingStrategy Strategy;
void PostTo(Ledger ledger) =>Strategy.PostTo(ledger);
}

نتیجه:
تست‌پذیری بهتر، حذف شرط‌ها، و گسترش‌پذیری بدون اثر جانبی.
----------------

🧠 معرفی Behavior as Data Pattern
الگوی
Behavior as Data یک الگوی ساختاری صرف نیست، بلکه یک بینش طراحی (modeling insight) است. الگوی Behavior as Data به ما می‌گوید:
اگر مقدار یک فیلد باعث تغییر در رفتار سیستم می‌شود، آنگاه آن فیلد دیگر صرفاً یک داده نیست، بلکه نماینده‌ی یک رفتار است و باید به یک مدل رفتاری (Behavioral Model) تبدیل شود.

به زبان ساده، هر زمان که سیستم به جای "تصمیم‌گیری با داده"، وارد فاز "تغییر رفتار بر اساس داده" می‌شود، زمان استفاده از این الگو فرارسیده است.
به عبارت دیگر:
💡اگر سیستم به جای آنکه با داده تصمیم بگیرد، بر اساس داده عمل متفاوتی انجام می‌دهد، زمان بازطراحی فرا رسیده.

مزایا و آثار این بازطراحی

حذف منطق شرطی تودرتو
تسهیل تست واحد برای هر رفتار
باز بودن مدل برای توسعه رفتارهای جدید بدون تغییر ساختار اصلی
بهبود شفافیت مدل دامنه برای ذینفعان (توسعه‌دهندگان، مدیران محصول و تحلیل‌گران)
----------------

چه زمانی باید از Behavior as Data استفاده کرد؟
برای تشخیص نیاز به این الگو، می‌توان از این هیوریستیک‌ها استفاده کرد:
🟠 مقدار فیلد منطق رفتار را تعیین می‌کند
آیا تغییر مقدار Type باعث تغییر در اجرای متدی مثل Submit() یا Process() می‌شود؟
🔵 وجود شرط‌های متعدد و در حال رشد بر اساس آن فیلد
آیا در نقاط مختلف سیستم شرط‌هایی مشابه if (type == ...) در حال تکرار است؟
🟣 نیاز به تست مستقل هر رفتار وجود دارد
آیا نمی‌توان به‌راحتی رفتار مرتبط با یک مقدار خاص را به‌صورت جداگانه تست کرد؟


چرا این الگو مهم است؟
در یک کلام باید بگم که بسیاری از مشکلات مزمن در طراحی سیستم‌ها (مثل پیچیدگی تدریجی، شرط‌های کلافه کننده، تست‌ناپذیری، و وابستگی‌هایشدید و شکننده) از همین بی‌توجهی به تمایز بین «داده» و «رفتار» ناشی می‌شود.

📘 این الگو بخشی از مجموعه الگوهای طراحی و مدلسازی من در کتاب «Language-Driven Design» که در حال نگارش آن هستم، است.


📎 مطالعه مقاله‌ی کامل الگو، با مثال‌های متنوع و تکنیک‌های بازطراحی:

https://medium.com/@masoudbahrami/introducing-behavior-as-data-pattern-1e4c82d1ede6
👌51


>>Click here to continue<<

کانال مکتب‌خانه DDD






Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)