TG Telegram Group Link
Channel: کانال مکتب‌خانه DDD
Back to Bottom
بالاخره فهمیدم که Monad اونقدرها هم وحشتناک نیست! 🤔

به بیان ساده، Monad یک الگوی طراحی هست که از Category Theory وام گرفته شده و در برنامه‌نویسی، به خصوص در زبان‌های functional، برای ترکیب عملیاتی که نیاز به تغییر state دارند (و به عبارت دیگه دارای side effects هستند) به یک روش predictable، clear و declarative استفاده می‌شود.

مونادها به ما این امکان رو میدن که عملیات‌ها رو به راحتی پشت هم بچینیم، بدون اینکه نگران خطاها یا مشکلات اجرایی باشیم.

حالا سوال اینه که Monads چطور کمک می‌کنه؟ 🤔

به زبان ساده، Monad یک ساختار داده‌ای هست که می‌تونه مقادیر رو در خودش نگه داره و به طور امن و مرتب عملیات‌های مختلف رو روش انجام بده. مهم‌تر از همه، اینکه می‌تونه با خطاها یا کارهای asynchronous به شکل ساده برخورد کنه.

ویژگی‌های اصلی Monad

یک Monad معمولاً سه ویژگی اساسی دارد:

1- ویژگی return یا unit یا construct: این متد یک مقدار رو به نوع Monadic تبدیل می‌کنه. به عبارت دیگه، اگر شما یک مقدار ساده (مثل یک عدد یا رشته) داشته باشید، با استفاده از این متد می‌تونید آن رو در یک Monad قرار بدید.

2- ویژگی bind یا flatMap: این متد به شما این امکان رو می‌ده که عملیات‌هایی رو روی مقدار داخل Monad انجام بدید. bind تضمین می‌کنه که نتیجه هر عملیات همچنان یک Monad باقی می‌مونه و می‌تونید آن رو به راحتی به عملیات‌های بعدی وصل کنید.

3- ترکیب آسان با سایر عملیات‌ها: Monads به شما این امکان رو می‌دهند که چندین عملیات رو به شکلی صاف و بدون نیاز به نوشتن کد پیچیده ترکیب کنید. این امکان به‌ویژه در asynchronous programming و side effects بسیار مفید است. ⚙️


در واقع، Monads ساختارهایی هستند که می‌تونند مقادیر رو توی خودشون نگه دارند و عملیات‌های مختلف رو بر روی آن مقادیر انجام بدهند، به طوری که می‌توان از آن‌ها در شرایط مختلف مانند side effects، asynchronous بودن، و مدیریت خطاها استفاده کرد.

یه مثال ساده

فرض کنید داریم یک سفارش آنلاین می‌گیریم. اول باید چک کنیم که آیا موجودی داریم یا نه، بعد پرداخت رو انجام بدیم، و در نهایت وضعیت سفارش رو به روز کنیم. اگر هرکدوم از این مراحل با مشکلی مواجه بشه (مثلاً موجودی کافی نباشه یا پرداخت شکست بخوره)، باید خطا رو مدیریت کنیم.

پیاده‌سازی مثال بالا در Haskell:

data Order
= Order { orderId :: Int, product :: String, quantity :: Int }

checkStock:: Order -> Maybe Order
checkStock
order
| quantity order > 0 = Justorder
| otherwise = Nothing

processPayment
:: Order -> Maybe Order
processPayment
order = Just order

updateOrder:: Order -> Maybe Order
updateOrder
order = Just order

processOrder
:: Order -> Maybe Order
processOrderorder = do
stockChecked <- checkStock
order
paymentProcessed <-processPayment stockChecked
updateOrder paymentProcessed

main :: IO ()

main = do
let order = Order { orderId = 1,product = "Laptop", quantity = 5 }
case processOrder order of
Just o -> putStrLn $ "Order processed:
" ++ show o
Nothing -> putStrLn"Order failed"





به نظرتون شما در زبان‌هایی مثل C# یا Java چطور می‌تونید از این ویژگی استفاده کنید؟
🔁 در پست قبلی گفتیم Monad چیه و چطور می‌تونه به ما کمک کنه که عملیات‌های پیچیده رو به صورت امن، خوانا و قابل پیش‌بینی اجرا کنیم—حتی وقتی با چیزهایی مثل async، side effect یا خطا سروکار داریم.
👨‍💻 حالا می‌تونیم یه ابزار واقعی رو ببینیم که برای همین موضوع توسعه دادم و این مفاهیم رو توی c# پیاده‌سازی کردم!

📦 کتابخونه‌ی Quantum.MonadicTasks یه لایبرری مینیمال و تمیز برای کار با Task<T> به شکل Monadic هست. باهاش می‌تونی:
ملیات‌های async رو زنجیره‌ای و functional ترکیب کنی
از متدهایی مثل .Bind(), .Map(), .Fail() و .Tap() استفاده کنی
بدون try/catch شلوغ، خطاها رو مدیریت کنی
کدت رو مثل do notation در Haskell بنویسی
کدی قابل تست، قابل خواندن، و قابل توسعه بنویسی

📌 چند تا از امکانات مهمش:
• .Bind() برای زنجیره کردن عملیات async
• .Map() برای تغییر نتیجه بدون await دستی
• .Fail() برای تولید خطا به‌صورت monadic
• .PerformSideEffect() برای side effectهایی مثل log یا metric
• .Sequence() برای اجرای چند عملیات async باهم
• .GetResultAsync() برای گرفتن نتیجه یا throw کردن خطا

📁 یه مثال واقعی از سفارش آنلاین: بررسی موجودی، انجام پرداخت، و آپدیت سفارش… همه توی یه زنجیره‌ی امن، بدون کد اضافی یا if تو در تو!

await MonadicTask<Order>.Return(order)
.Bind(CheckStockAsync)
.PerformSideEffect(LogStockChecked)
.Bind(ProcessPaymentAsync)
.PerformSideEffect(LogPaymentSuccess)
.Bind(UpdateOrderStatusAsync)
.GetResultAsync();



📍 این لایبرری برای پروژه‌های واقعی و مقیاس‌پذیر طراحی شده و توی Benchmark هم عملکرد قابل قبولی از خودش نشون داده.


🔗 کدش اینجاست، خوشحال می‌شم ببینی و نظرت رو بگی:

👉 https://github.com/Quantum-Space-Org/MonadicTasks

مکتب‌خانه DDD
@DomainDrivenDesign_ir
💡 مقایسه‌ی پارادایم‌های برنامه‌نویسی — از Flow-Based تا State-Centric

در مسیر تحول برنامه‌نویسی، از تفکر flow-based با تکیه بر functionها، رفتیم به سمت ساختارهای state-centric و assignment-driven — و در این بین، شاید چیزی مهم مثل وضوح جریان داده رو از دست دادیم.

۱- Functional Programming (FP) — function-driven، flow-based

توابع هسته‌ی اصلی محاسبات هستن.
توابع به‌عنوان داده در نظر گرفته می‌شه؛ می‌تونه ترکیب بشه.
تمرکز روی جریان صریح داده بین functionهاست.
ساده، قابل پیش‌بینی، بدون state پنهان.
⚠️ مدل‌سازی سیستم‌های واقعی و stateful در این پارادایم محدودتره.

۲- Object-Oriented Programming (OOP) — state-centric، assignment-driven

توابع مرتبط به‌همراه state مشترک در قالب objectها قرار می‌گیرن.
باعث modularity و استفاده‌ی مجدد از کد می‌شه.
⚠️ ولی جریان هندل کردن یک سناریو implicit می‌شه — توی methodها و تغییرات داخلی state پنهانه.
⚠️ منطق حول assign و تغییر وضعیت- change state- می‌چرخه، نه حول جریان.

۳- Actor Model — agent-centric، message-driven

پارادایم OOP رو یه قدم جلوتر می‌بره: objectها به agentهای مستقل تبدیل می‌شن.
این agentها فقط با پیام‌های async با هم حرف می‌زنن.
برای سیستم‌های concurrent و توزیع‌شده عالیه.
⚠️ اما باز هم جریان داده پراکنده و پنهانه — در زنجیره‌های پیام و actorهای جدا.
--------------------------------------

👉 در این مسیر، از flow-based logic به سمت ساختار و مقیاس‌پذیری رفتیم — ولی اغلب با هزینه‌ی از دست دادن وضوح جریان داده.

🧭 آیا می‌تونیم دوباره بین این‌ها تعادل ایجاد کنیم؟
Loop vs Recursion.pdf
330.4 KB
🎯 درک عمیق control flow یکی از پایه‌های اصلی برنامه‌نویسیه. در این مقاله به بررسی تفاوت‌های بین loop و recursion پرداختم و نشون دادم که چرا این انتخاب‌ها فراتر از syntax ساده هستن و به mental models ما برمی‌گردن.

اگه شما هم تجربه‌ای در این زمینه دارید یا سوالی براتون پیش اومده، حتماً تو کامنت‌ها باهام به اشتراک بذارید. خوشحال میشم نظر شما رو هم بدونم .
معرفی کتاب ریاضی ارزشمند "How to Solve It" (چگونه مسئله را حل کنیم)

✍️ اثر ماندگار ریاضیدان برجسته، جورج پولیا

📖 این کتاب که در سال 1945 منتشر شد، فراتر از یک راهنمای حل مسائل ریاضی است و به یک مرجع بی‌نظیر در زمینه‌ی آموزش تفکر ساختاریافته و توسعه‌ی مهارت‌های حل مسئله در تمامی جوانب زندگی تبدیل شده است. پولیا در این اثر، با زبانی ساده و گیرا، یک چهارچوب عملی و فلسفی برای مواجهه با چالش‌ها و یافتن راه‌حل‌های مؤثر ارائه می‌دهد.

🔑 مفهوم اصلی "How to Solve It" بر پایه‌ی یک فرآیند چهار مرحله‌ای استوار است:

1️⃣ درک مسئله (Understanding the Problem):
ضروری است که مسئله به طور کامل درک شود. پولیا بر اهمیت پرسیدن سؤالات کلیدی تأکید می‌کند:

- مجهول چیست؟ (What is the unknown?)
- داده‌ها کدامند؟ (What are the data?)
- شرایط چیست؟ (What is the condition?)
- آیا امکان ترسیم شکل یا نمودار وجود دارد؟
- آیا مسئله مشابهی دیده‌اید؟
- آیا می‌توان مسئله را به بخش‌های -
کوچک‌تر تقسیم کرد؟
درک صحیح مسئله، نیمی از راه‌حل است.

2️⃣ طرح‌ریزی (Devising a Plan):یافتن ارتباط بین داده‌ها و مجهول و طرح‌ریزی استراتژی. پولیا "روش‌های مکاشفه‌ای" (heuristics) را معرفی می‌کند، مانند:

- حدس زدن و آزمایش کردن (Guessing and checking)
- جستجو برای الگو (Looking for a pattern)
- رسم شکل (Drawing a diagram)
- کار کردن به عقب (Working backward)
- استفاده از مسئله‌ی مشابه (Using a related problem)
- تجزیه و تحلیل (Breaking down the problem)
- ساده‌سازی (Simplifying the problem)
💡 طرح‌ریزی یک فرآیند اکتشافی است.

3️⃣ اجرا (Carrying out the Plan):اجرای دقیق و گام به گام طرح. صبر، دقت و توجه به جزئیات مهم است. هر گام باید منطقی و صحیح باشد و آمادگی برای مواجهه با مشکلات پیش‌بینی‌نشده وجود داشته باشد.

4️⃣ بازنگری (Looking Back):
بررسی و ارزیابی راه‌حل به دست آمده برای یادگیری و بهبود. سؤالاتی که باید پاسخ داده شوند:

- آیا راه‌حل صحیح است؟
- آیا روش دیگری برای حل وجود دارد؟
- آیا می‌توان از این روش برای مسائل مشابه استفاده کرد؟
- چه درس‌هایی آموختیم؟
🧐 بازنگری به بهبود عملکرد در آینده کمک می‌کند.

🌟 اهمیت و تأثیر "How to Solve It":
این کتاب با رویکرد عملی، زبان ساده و تأکید بر فرآیند تفکر، تأثیر عمیقی بر آموزش ریاضیات و مهارت‌های حل مسئله داشته است و در زندگی روزمره، علوم، مهندسی، مدیریت و سایر حوزه‌ها کاربرد دارد. پولیا با تأکید بر پرسش‌های درست، جستجو برای الگوها، استفاده از تجربیات و بازبینی، چارچوبی قدرتمند برای توسعه‌ی تفکر انتقادی و توانایی حل مسئله ارائه می‌دهد.

📚 "How to Solve It" همچنان یک منبع الهام‌بخش برای همگان است.



https://en.m.wikipedia.org/wiki/How_to_Solve_It
کانال مکتب‌خانه DDD
معرفی کتاب ریاضی ارزشمند "How to Solve It" (چگونه مسئله را حل کنیم) ✍️ اثر ماندگار ریاضیدان برجسته، جورج پولیا 📖 این کتاب که در سال 1945 منتشر شد، فراتر از یک راهنمای حل مسائل ریاضی است و به یک مرجع بی‌نظیر در زمینه‌ی آموزش تفکر ساختاریافته و توسعه‌ی مهارت‌های…
🎬 ویدئو: "ذهن درخشان پولیا: هنر تدریس و حل مسئله"

کاوشی در ذهن پولیا: چگونه عمیق‌تر فکر کنیم (ویژه توسعه‌دهندگان و مالکان محصول)

اگر به دنبال ارتقای سطح تفکر و توانایی حل مسائل پیچیده در کارتون هستید، پیشنهاد می‌کنم علاوه بر خواندن کتاب How To Solve It این ویدئو جالب و ارزشمند رو هم مشاهده کنید. این ویدئو، شما را به تماشای یک کلاس درس و کارگاه با جورج پولیا، نویسنده‌ی کتاب ارزشمند "How to Solve It"، دعوت می‌کند.

پولیا در این محتوا، نه فقط تکنیک‌های حل مسئله، بلکه نگرش عمیق خود به فرآیند یادگیری و مواجهه با چالش‌ها را به اشتراک می‌گذارد. او با تاکید بر این ایده محوری که "تدریس، فرصت دادن به دانش‌آموزان برای کشف بهتر چیزهاست"، یک اصل کلیدی در توسعه‌ی فردی و تیمی را برجسته می‌سازد.

چرا تماشای این ویدئو برای شما مفید است؟

👨‍💻 برای توسعه‌دهندگان: با مشاهده‌ی رویکرد پولیا به ساختاربندی مسائل و تشویق به تفکر مستقل برای یافتن راه‌حل، می‌توانید الگوهای ذهنی قدرتمندتری در مواجهه با مشکلات فنی ایجاد کنید. این ویدئو به تقویت تفکر تحلیلی و خلاقیت شما کمک می‌کند.

📦 برای مالکان محصول: درک فلسفه‌ی پولیا در مورد تسهیل فرآیند یادگیری و کشف، می‌تواند به شما در طراحی محصولاتی که کاربران را به تعامل عمیق و حل مسائل واقعی دعوت می‌کنند، الهام بخشد. این نگرش همچنین در رهبری تیم و اتخاذ تصمیمات استراتژیک مبتنی بر درک عمیق‌تر مسائل، مؤثر خواهد بود.

این ویدئو، یک آموزش سطحی نیست؛ بلکه فرصتی برای درک عمیق‌تر شیوه‌ی تفکر یک استاد برجسته است که می‌تونه نگرش شما به چالش‌ها و فرآیند یادگیری را متحول کنه.

🔗 لینک ویدئو: https://www.youtube.com/watch?v=h0gbw-Ur_do&t=928s

مکتب‌خانه DDD
@DomainDrivenDesign_ir
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
S3Pattern.pdf
426.2 KB
📝 State/Status Segregation (S3) Pattern
Making Systems More Predictable by Separating Lifecycle from Context

🔍 In complex systems, mixing up state and status often leads to bloated models, fragile logic, and unpredictable behavior.

This paper, written by Masoud Bahrami, introduces the State/Status Segregation (S3) pattern, a modeling principle that cleanly separates lifecycle control (state) from contextual signals and side conditions (status).

❇️ By applying S3, you can design systems with clearer APIs, more predictable behavior, and codebases that are easier to test, evolve, and reason about.
Please open Telegram to view this post
VIEW IN TELEGRAM
کانال مکتب‌خانه DDD
Introducing Behavior as Data Pattern.pdf
4.2 MB
Behavior as Data Pattern

Learn how a simple modeling shift can replace scattered conditionals with clean, testable behaviors.
دوستان خوب و عزیزم

امیدوارم که همگی در کمال آرامش و سلامت به سر ببرید. در این ساعت‌های پرتنش همه‌مون بیش از هر زمان دیگه‌ای به آرامش و هوشیاری نیاز داریم. لطفا حواس‌تون به خودتون و عزیزاتون باشه

امیدواریم خیلی زود، دوباره روزهای آروم(تر) و بی‌دغدغه‌تر رو به همراه آرامش تجربه کنیم 🌿❤️
💡 Mixed Responsibility Smell

فرض کنید متدی دارید که پول را به حساب کاربر برمی‌گرداند و در همان لحظه مقدار جدید موجودی را هم برمی‌گرداند:
public Money Refund(Money amount)
{
Balance += amount;
return Balance;
}


چرا ممکن است این کار را بکنیم
شاید برای سادگی، یا چون می‌خواهیم بلافاصله بعد از عملیات، موجودی جدید را در تست‌ها Assert کنیم یا آن را به کاربر نمایش دهیم. این سناریوها کاملاً معقول به نظر می‌رسند!

اما سوال اینجاست:
آیا درسته که یک متد هم وضعیت را تغییر دهد و هم مقدار به‌روز شده رو برگرداند؟ در واقع سوال مهم در باره نحوه‌ی مدل کردن و پیاده‌سازی سناریوهایی که در بالا اشاره شد، است.

در جواب باید بگم:
این دقیقاً همون جاییه که با یک Code Smell به نام Mixed Responsibility Smell روبرو هستیم.

قطعاً ما نیاز به متد دیگری داریم که صرفاً موجودی را به ما بدهد. در واقع، نمی‌توانیم برای دریافت موجودی تنها به متد Refund تکیه کنیم؛ چرا که این امر ما را مجبور می‌کند برای هر بار خواندن موجودی، یک عملیات Refund انجام دهیم که نه منطقی است و نه قابل قبول. این یعنی عملاً ما هیچ‌گاه به یک موجودی ثابت و قابل اتکا دسترسی نداریم. علاوه بر بحث عدم قطعیت (indeterministic behavior) و موارد مشابه، این وضعیت یک Code Smell جدی محسوب می‌شود. حداقل پیامد آن این است که ما یک منطق یکسان (یعنی محاسبه موجودی) را در دو نقطه مختلف تکرار می‌کنیم: هم در متد Refund و هم در متدی مانند GetBalance، حتی اگر GetBalance تنها شامل return Balance; باشد.


سوال بعدی اینه که: چرا این مشکل‌ساز است
این «بوی بد» زمانی اتفاق می‌افته که یک متد یا کامپوننت بیش از یک مسئولیت یا وظیفه را بر عهده بگیره و باعث شود:

ابهام در نقش و وظیفه اصلی کد
پیچیدگی در فهم، تست و نگهداری کد
تکرار منطق مشابه در چند نقطه
مثل منطق محاسبه یا به‌روزرسانی موجودی که هم در متد Refund و هم در متد GetBalance تکرار می‌شود (حتی اگر در GetBalance صرفاً return Balance; باشد)
کاهش انعطاف‌پذیری و سختی توسعه کد
رفتار نامعین (Indeterministic Behavior): اگر برای گرفتن موجودی مجبور باشیم همیشه Refund را صدا بزنیم، هیچ‌وقت موجودی واقعی و پایدار در اختیار نخواهیم داشت، چون هر بار با گرفتن موجودی، وضعیت تغییر می‌کند!



مثال بهتر:
// command
public void Refund(Money amount)
{
Balance += amount;
}

// query
public Money GetBalance()
{
return Balance;
}


نتیجه اینکه:
هشدار مهمی که Mixed Responsibility Smell به ما میده اینه که:

یک متد یا کامپوننت باید تنها یک مسئولیت واضح و مشخص داشته باشد.
تفکیک درست مسئولیت‌ها باعث میشه که کد:
ساده‌تر و قابل فهم‌تر شود
راحت‌تر تست و نگهداری شود
توسعه و تغییرات آینده بدون دردسر انجام شود
HTML Embed Code:
2025/07/01 07:30:40
Back to Top