NILL DevelopersPhoto
در حال توسعه یک اپلیکیشن هستم
یک سناریویی در پیش روم قرار داشت:
۱) کاربر یک qr code رو اسکن میکنه
۲) متد من فراخوانی میشه
داخل این متد من باید چند کار مختلف انجام بدم:
۱) باید جدولی رو آپدیت کنم که نشون میده چه کاربری چه شیای رو اسکن کرده
۲) سپس اون شی رو به کالکشن شخص وصل کنم(یه raw جدید اضافه کنم)
۳) طبق دو سناریو بیام xp کاربر رو محسابه کنم
۴) آیدی رو return کنم
خب یک نگاه سرسری بندازیم اینجوریه که خب خط به خط مینویسیم و کاری که گفتی رو انجام میدیم
اما نه!
وقتی تعداد کاربرایی که میخوان اسکن کنن بصورت تساعدی بره بالا(برنامه بره زیر بار) ما با افزایش شدید مصرف منابع روبرو میشیم
تا جایی که شاید کاربر timeout بخوره!💀
اما راه حل؟
راه حل میتونه استفاده از outbox pattern باشه، وقتی کاربر شی رو اسکن کرد یک event در لایه دامنه raise بشه. موقع save change اون ایوینت در outbox massage با فلگ pending ذخیره بشه
هر ۵ ثانیه outbox processor (که یک بکگراند جاب هست) میاد و میخونه و اون ایونتایی که pending هستند و notification پکیج mediatR رو صدا میزنه
این یعنی از لایه infra.rabbit خیلی نا محسوس به لایه بالا سریمون(app service) فهموندیم خبرایی هست!
اونجا میام طبق اصل liskov یک کلاس بیس مینویسم و سپس کلاسهایی رو از جنس همون ایونتی که اتفاق افتاده میسازم
پس event raised شد و ما خبر شدیم
تووی متد مورد نظر هستیم برای انجام فرمان!
برای تمیز کاری بیشتر هم xp rules رو بردم داخل لایه domain service تا کامل separate concerns داشته باشیم
ببین چقد تمیز شد🥹
#ddd #outbox #liskov #clean_architecture #event #edd #cqrs #csharp #dotnet
6 · 1.1K · Photo
click to show
click to show
سلام دوستان عزیز روزتون بخیر امیدوارم حالتون خوب باشه. 😎✌️
ما برای فاز اول یه پروژه کراس پلتفرم نیازمند دولوپر #react_native یا #flutter هستیم.
🔹پروژه دارای ۳ فلو اصلیه که لازمه برای #android و #ios توسعه داده بشه که به شرح زیره:
• OTP flow
• QR code flow
• Search flow | در جلسه آنلاین توضیح داده میشود
🔹 حداکثر بودجه در نظر گرفته شده برای این پروژه مبلغ ۱۸ میلیون هست که پس از هر اسپرینت واریز میشه. همچنین ددلاین پروژه تا پایان ماه مهر هست و ادامه همکاری برای فاز های بعد پس از ددلاین مشخص میشه.
🔸 دیزاین، بک و پنل محتوا پیاده شده و تمامی api ها در دسترس هست منتها به دلیل فورس بودن پروژه تنها خواسته ما تحویل پروژه منطبق بر دیزاین و رعایت اصول pixel perfect هست.
📨 لطفا رزومه و نمونه کارهای خودتون رو به آیدی های Peyman Kalani و یا Mohammad Nazari در لینکداین و یا آیدی @nill_devs در تلگرام بفرستید. ☺️🙏
2 · 185 · Link
click to show
click to show
هرجایی رو میبینی نوشته از AsNoTracking استفاده کن همچی سریعتر میشه
اما واقعیت پشت پرده Change tracker efcore چیه که همه موقع خوندن داده اینقد باهاش بدن ولی میخوان ذخیره کنن دست به دامنش هستن؟!
خب بیایم در این پست گام به گام چرخه کار این جانور چهارپا رو بررسی کنیم!!
مقدمه
ابتدا بگم که Change Tracker در EF Core مثل یک ناظر دقیق عمل میکنه که تغییرات روی entityها رو ردیابی میکنه. وقتی entityها رو از دیتابیس لود میکنی (مثل با Find یا ToList)، اونا رو track میکنه تا ببینه چی تغییر کرده، اضافه شده، حذف شده یا نه. این کار overhead داره (مصرف مموری و CPU برای snapshot گرفتن از حالت اولیه entityها)، واسه همین تو سناریوهای read-only همه میگن AsNoTracking بزن تا tracking خاموش بشه و پرفورمنس بهتر شه. اما وقتی میخوای تغییرات رو سیو کنی (با SaveChanges)، بدون tracking نمیتونی تغییرات رو detect کنی – پس دست به دامن Change Tracker میشی!
چرخه حیات
حالا چرخه کاملش شامل ۴ مرحله (یا بهتر بگم ۴ state اصلی برای entityهای tracked) میشه که entityها توشون جابهجا میشن. این stateها بر اساس مستندات رسمی EF Core هستن:
۱. مرحله Unchanged: این حالت اولیهست وقتی entity رو از دیتابیس لود میکنی و هنوز هیچ تغییری روش ندادی. Change Tracker یک snapshot از پروپرتیها میگیره و منتظر میمونه. اگه تغییری ندی، موقع SaveChanges هیچ کاری نمیکنه – entity دستنخورده میمونه.
۲. مرحله Modified: اگه یکی از پروپرتیهای entity رو تغییر بدی (مثل user.Name = “NewName”)، state به Modified میره. Change Tracker تغییرات رو با مقایسه snapshot اولیه detect میکنه و موقع SaveChanges، فقط فیلدهای تغییرکرده رو آپدیت میکنه تو دیتابیس. اینجاست که قدرت tracking مشخص میشه!
۳. مرحله Added: وقتی یک entity جدید میسازی و به context اضافه میکنی (مثل context.Users.Add(new User()))، stateش Added میشه. Change Tracker میفهمه این رکورد جدیده و موقع SaveChanges، یک INSERT تو دیتابیس اجرا میکنه. بعد از سیو، state به Unchanged برمیگرده.
۴. مرحله Deleted: اگه entity رو حذف کنی (مثل context.Users.Remove(user))، state به Deleted میره. Change Tracker مارک میکنه که این رکورد باید حذف بشه، و موقع SaveChanges یک DELE
3 · 1.1K · Photo
click to show
click to show
امروز در یک جلسه مصاحبه شرکت کردم
مجموعه سوالاتی گرد آوری کردم که قصد دارم در چند پست متوالی منتشرشون کنم
بیایم از این یکی شروع کنیم:👇🏻
⸻
💥 AggregateException در .NET چیه؟
وقتی چند عملیات همزمان (مثل چند Task یا Parallel loop) اجرا میکنی و بیش از یکی از اونها خطا میده، .NET همهٔ اون خطاها رو داخل یه شئ به نام AggregateException جمع میکنه و بهت برمیگردونه.
به زبان ساده:
بهجای اینکه فقط یه Exception بگیری، یه “جعبهٔ استثناها” داری که چند خطای مختلف توش بستهبندی شدن.
📍 کجاها باهاش برخورد میکنی؟
• وقتی از Task.WaitAll() یا Parallel.ForEach() استفاده میکنی
• وقتی بهجای await از Task.Result یا Task.Wait() استفاده میکنی
• در عملیاتهای async یا multi-threaded که چند Exception همزمان رخ میدن
میتونی خطاهای داخلش رو با ex.InnerExceptions مرور کنی یا با ex.Flatten() همهشون رو باز کنی.
🎯 هدفش چیه؟
مدیریت شفاف خطاها در دنیای همزمانی — چون توی Parallel programming، یه خطا تنها خطا نیست!
201 · اینو تو فیسبوک دیدم، خیلی قشنگ بود:
«استاد، من کتابهای زیادی خواندهام… اما بیشترشان را فراموش کردهام. پس فایدهی خواندن چیست؟»
این پرسشِ شاگردی کنجکاو بود از استادش.
استاد پاسخی نداد، فقط در سکوت به او نگاه کرد.
چند روز بعد، کنار رودخانهای نشسته بودند.
پیرمرد ناگهان گفت:
«تشنهام. برایم کمی آب بیاور… اما با آن آبکش قدیمی که آنجاست.»
شاگرد متعجب شد. درخواست عجیبی بود — چطور میشد با آبکشِ پر از سوراخ، آب آورد؟
اما جرئت نکرد مخالفت کند.
آبکش را برداشت و تلاش کرد.
یکبار… دوبار… بارها و بارها…
سریعتر دوید، زاویهاش را عوض کرد، حتی سعی کرد سوراخها را با انگشتهایش بپوشاند.
هیچکدام کارساز نشد. نتوانست حتی یک قطره آب نگه دارد.
خسته و ناامید، آبکش را کنار پای استاد انداخت و گفت:
«متأسفم، نتوانستم. غیرممکن بود.»
استاد با مهربانی به او نگریست و گفت:
«تو شکست نخوردی. به آبکش نگاه کن.»
شاگرد نگاهی انداخت… و چیزی دید.
آبکشِ قدیمی و سیاه و کثیف، حالا میدرخشید.
آب، هرچند در آن نمانده بود، اما بارها و بارها از آن گذشته و شسته بودش تا براق شده بود.
استاد ادامه داد:
«خواندن هم همینگونه است.
مهم نیست اگر هر جزئیات را به خاطر نسپاری،
مهم نیست اگر دانستههایت مثل آب از ذهنت بیرون میروند…
زیرا در هنگام خواندن، ذهنت تازه میشود،
روحت نیرو میگیرد،
افکارت نفس میکشند،
و حتی اگر بلافاصله متوجه نشوی، درونت در حال دگرگونی است.»
این است معنای واقعیِ خواندن —
نه برای پُر کردن حافظه،
بلکه برای شستن و غنیساختنِ روح.
1 · 169 · 🚀 چطور سرعت Build داکر رو چند برابر کردم؟ تجربهای که واقعاً زندگیم رو راحتتر کرد!
چند وقت پیش مجبور بودم برای یک پروژه چندین بار پشتسرهم Docker Image بسازم. هر بار ۳–۴ دقیقه منتظر موندن… واقعاً کلافهکننده بود.
فکر کردم شاید مشکل از زیرساخت باشه. اما نه — مشکل از Dockerfile خودم بود!
بعد از چند روز آزمونوخطا، به چند نکته ساده اما معجزهگر رسیدم که سرعت build رو بهطور جدی بالا برد. شاید برای شما هم مفید باشه:
🔥 1) لایهبندی درست Dockerfile = کاهش زمان تا ۷۰٪
اگر اول dependencyها رو نصب کنید و بعد سورسکد رو اضافه کنید، Docker مجبور نمیشه هر بار از صفر بسازه.
این نکته رو که فهمیدم، انگار turbo رو روشن کردم!
🔥 2) Multi-Stage Build: هم سریعتر، هم سبکتر
کد compile یه جا
run یه جا
نتیجه؟
یک ایمیج سریعتر، تمیزتر، امنتر و چند برابر کوچکتر.
🔥 3) فعالسازی BuildKit: یک جهش واقعی
BuildKit رو که فعال کردم، انگار داکر از خواب بیدار شد!
بعضی buildها تا ۲ برابر سریعتر شدن.
هم caching بهتر، هم parallel steps.
🔥 4) .dockerignore نجاتدهنده واقعی
صادقانه بگم: نصف کندی من بخاطر این بود که چیزهای عجیبوغریب داشت وارد context میشد!
Logها، tempها، node_modules، target…
وقتی .dockerignore رو درست کردم، همهچیز سریعتر شد.
🎯 خروجی این تغییرات؟
بدون حتی یک ریال هزینه سختافزاری:
✔️ سرعت build چند برابر
✔️ حجم ایمیجها کمتر
✔️ اعصاب راحتتر 😄
✔️ زمان بیشتر برای کارهای مهمتر
اگر پروژههاتون به داکر وابستهست، پیشنهاد میکنم همین امروز ۱۰ دقیقه وقت بذارید و Dockerfileتون رو بازنویسی کنید.
نتیجهش بیشتر از چیزی که فکر میکنید ارزش داره.
منبع: یکی از رفقا در لینکدین
7 · 215 · NILL Developers🚀 چطور سرعت Build داکر رو چند برابر کردم؟ تجربهای که واقعاً زندگیم رو راحتتر کرد!
چند وقت پیش مجبور بودم برای یک پروژه چندین بار پشتسرهم Docker Image بسازم. هر بار ۳–۴ دقیقه منتظر موندن… واقعاً کلافهکننده بود.
فکر کردم شاید مشکل از زیرساخت باشه. اما نه — مشکل از Dockerfile خودم بود!
بعد ا
دوستان این پست یکی از رفقا تووی لینکدین بود
نتونستم مجددا پروفایلش رو پیدا کنم و منشنش کنم
اگر کسی میدونه در بخش منابع لینک پروفایلشون رو بذاره
بسیار کمک کننده بود در پروژه من
193 · Link
click to show
click to show
https://www.linkedin.com/posts/mhmdnzr_%DA%86%D9%86%D8%AF-%D9%88%D9%82%D8%AA-%D9%BE%DB%8C%D8%B4-%D8%AF%D8%A7%D8%B4%D8%AA%D9%85-%D8%AF%D8%B1-%D9%85%D9%88%D8%B1%D8%AF-%DB%8C%D9%87-%D8%B3%D8%B1%DB%8C-%D9%85%D8%AA%D8%BA%DB%8C%D8%B1%D9%87%D8%A7%DB%8C-activity-7402965678644854784-9JyV?utm_source=share&utm_medium=member_ios&rcm=ACoAADAxjPcBWUjevaTqQy5s82swxBAYI12rQrU
204 · Photo
click to show
click to show
📚نام کتاب :
Microservices Design Patterns in .NET 2nd Edition: Making sense of microservices design and architecture using .NET 10 and C# 14
📌انتشارات:
Packt
🖋نویسنده:
Trevoir Williams
📆سال انتشار :
2025
🌐خرید اینترنتی :
https://mahdibookshop.com/product/1068/Microservices%20Design%20Patterns%20in%20.NET%202nd%20Edition:%20Making%20sense%20of%20microservices%20design%20and%20architecture%20using%20.NET%2010%20and%20C#%2014
👨🏻💻خرید از طریق پشتیبانی:
@MahdiBooksupp
➖➖➖➖➖➖➖➖
🆔@mahdibookshop
📞جهت مشاوره خرید :
02166487517
09122727954
یا خرید حضوری از کتابفروشی مهدی (عج)
#انتشارات_مهدی
#Mehdi_Publisher
1 · 167 · این یکی از کتابهای خوبیه که مدتیه دارم در موردش تووی لینکدین پست میذارم
152 · Link
click to show
click to show
سال پیش وقتی رفتم مصاحبه شرکت داتین از من سوال پرسیدن که فرق بین dynamic vs object چیه؟
من نمیدونستم تا وقتی که رفتم برای اون کتاب Pro DLR in .NET 4 رو خوندم
دانشم رو دوست داشتم با شما به اشتراک بذارم
براش یه صفحه بلاگ توضیح دادم:
https://mhmdnzr.drl.ink/post/dynamic-vs-object-in-csharp
110 · Link
click to show
click to show
سرویس پرداخت Dr.Link رو ریفکتور کردم. تمرکزم فقط روی معماری بود — تمیز کردن ساختار، جداسازی لایهها. نه latency, نه reliability.
بعداً فهمیدم اشتباه بوده. تو یه سرویس پرداخت با لود بالا، معماری تمیز بهتنهایی هیچ تضمینی نمیده. باید از همون اول بدونی سیستم زیر فشار چطور رفتار میکنه و اگه چیزی خراب شد، چی میشه.
الان دارم کتاب Latency از Pekka Enberg رو میخونم تا این خلأ رو جبران کنم — دربارهی consistency models (strong, eventual, causal, session) و trade-offهاشون.
#SoftwareEngineering #DistributedSystems #Payments #DrLink
پست جدیدم رو اینجا میتونید بخونید 👇
توضیح consistency models در سیستمهای توزیعشده · وبلاگ دارکپرو
3 · 124 · Link
click to show
click to show
من یه مقاله به تازگی نوشتم در خصوص چرایی وجود یک سری primitives keyword ها در سی شارپ و چجوری اینا میتونن به توسعه و کاهش latency سیستم به ما کمک کنند با مثال واقعی:
https://mhmdnzr.drl.ink/post/concurrent-file-uploader
1 · 117 · Link
click to show
click to show
پارسال رفته بودم مصاحبه Asan Pardakht برای نیروی دات نت
یک سوالی اونجا ازم کرد که خیلی برام جالب بود، پرسید فرق بین for vs foreach تووی سی شارپ چیه؟
خب این یه سوال به ظاهر خیلی سادست اما وقتی ترکیب میشه با دیتابیس و فچ دیتا میبینی انگار چوب جادوی هری پاترو انگار پیدا کردی
تووی این بلاگ سعی کردم در مورد این موضوع بییشتر صحبت کنم که چیشد اینجوری شد!
پ.ن: البته اینم بگم که من قبول نشدم تووی مصاحبه اما هربار که من fail میشم خلاهای بیشتری رو در خودم کشف میکنم و به ظرف دانش یک قسمت دیگه اضافه میکنم تا بهتر از دیروز بشم
#csharp #dotnet #software #architecture #pattern #learning
https://mhmdnzr.drl.ink/post/for-vs-foreach
2 · 151 · Link
click to show
click to show
دارم روی یه سری پست کار میکنم که موضوعش دور و بر همون چیزیه که این روزها خیلی درگیرشم: latency، consistency، و اون لحظههایی که سیستم یه چیزی رو "فکر میکنه" داره درست انجام میده ولی در واقع نداره. این پست از دل یه بحث واقعی دراومد — یه سناریوی ساده که همهمون یه جایی باهاش برخورد کردیم ولی خیلیها (منم قبلاً) دقیق بهش فکر نکردیم که چرا واقعاً خطرناکه.
بذارید مستقیم بریم سراغ صحنهی جرم.
https://mhmdnzr.drl.ink/post/distributed-lock
1 · 120 · Link
click to show
click to show
فراتر از Npgsql: راهنمای کامل PgBouncer، Pgpool-II، Odyssey و پروکسیهای ابری Postgres برای اپلیکیشنهای C#
https://mhmdnzr.drl.ink/post/npgsql-pgbouncer-pgpool-ii-odyssey-postgres-c
97 · Link
click to show
click to show
یه جایی توی پروژهمون به خودمون گفتیم:
«بابا Notification که دیگه این همه داستان نداره! یه API میزنیم، پیامو میفرستیم، تموم.»
و واقعاً هم همین کارو میشه کرد.
سادهست، سریع پیاده میشه، Infrastructure خاصی نمیخواد و تا وقتی همهچی خوب پیش میره، خیلی هم قشنگه :)
ولی مشکل از جایی شروع میشه که همهچی خوب پیش نمیره!
مثلاً:
پیام توی DB ذخیره شده، ولی سرویس قبل از Publish کردن به RabbitMQ میمیره.
تبریک میگم!
پیام داری ولی Event نداری :)
یا OTP و Campaign رو ریختی توی یه Queue و یهو چند هزار تا پیام Campaign اومده.
حالا کاربر منتظر OTPـه و Queue داره با خودش حال میکنه!
اینجاست که داستان کمکم تبدیل میشه به یه فاجعه کوچیکِ قابل مدیریت و باید بری سراغ چیزهایی مثل:
Outbox
Retry
Idempotency
Queue Isolation
Hangfire
Critical Workers
و کلی چیز دیگه.
البته اینجا هم فکر نکنی همهچی حل شد!
هر راهحل جدید خودش یه عالمه پیچیدگی، Monitoring، Failure Mode و در نهایت یه مقدار بگ....یی!! جدید با خودش میاره :))
توی NotificationHub دقیقاً سعی کردم همین مسیر رو بررسی کنم:
هر تصمیم معماری چه مشکلی رو حل میکنه؟
چه مزیتی داره؟
چه هزینهای ایجاد میکنه؟
و مهمتر از همه، کِی اصلاً نباید ازش استفاده کنیم؟
اگه با Backend و Distributed Systems سروکله میزنی، احتمالاً این داستان برات آشناست.
اینجا فقط یه بخش کوچیکشو گفتم.
اگه کنجکاو شدی ببینی آخرش این فاجعه رو چطوری جمع کردیم، بنظرم ارزش وقت گذاشتن و خوندن رو داره:
🔗 https://mhmdnzr.drl.ink/post/5086561b
#SoftwareArchitecture #Backend #DotNet #DistributedSystems #SystemDesign
16 · 533 · Link
click to show
click to show
این جمله درسته که همیشه دیتای حجیم باعث مرگ سیستم میشه؟ یا یک hot path در لایه infra SQL باعث میشه به ددلاک بخوریم؟
چجوری میشه حلش کرد؟ صرفا چندتا راه همیشگی AsNoTracking, AsSplitQuery, projection, N+1 problem و... یا استفاده از compiled query مارو از این منجلاب بیرون میکشه؟
یا شاید در زبان سی شارپ و ویژگی هاش باید دیپ تر بشیم؟
خب بنظرم گزاره دوم درسته، ما فهم ناقصی از سیستم کارکرد سی شارپ داشتیم
تووی این مقاله سعی کردم راه حلمو با for vs foreach ترکیب کنم و بهتون ارائه بدم.
میتونین از طریق لینک زیر مطالعه کنید:
https://mhmdnzr.drl.ink/post/d0040081
89 · Link
click to show
click to show
ما اکثرا از FirstOrDefault استفاده کردیم تا بخوایم بر اساس کلید یا یک ستون بریم داخل دیتا بیس پیدا کنیم، اما بقیش چی؟ کلا پنج تابع اصلی داریم برای پیدا کردن. اونا چیکار میکنن؟ تبدیل به چه کوئری میشه در نهایت؟
همه و همه در این مقاله جا شدن:
تفاوت در پیدا کردن است!
https://mhmdnzr.drl.ink/post/4ff4fb50
80 · Link
click to show
click to show
چرا وقتی میخوایم بدونیم یه آیتم توی دیتابیس یا یک persistent store هست یا نه، باید از Any استفاده کنیم نه Count() > 0؟
این سؤال رو توی مصاحبهها زیاد میپرسن، چون جوابش فقط سر syntax نیست، سر چیزیه که پشت صحنه اجرا میشه.
روی یک IQueryable (مثلاً EF Core):
users.Any(u => u.Id == id)
users.Count(u => u.Id == id) > 0
اولی به EXISTS یا SELECT TOP(1) ترجمه میشه؛ دیتابیس همین که یه ردیف مچ پیدا کنه متوقف میشه.
دومی به COUNT(*) ترجمه میشه؛ دیتابیس مجبوره (بسته به index) همهٔ ردیفهای مچ رو بشمره، حتی اگه فقط بخوای بدونی حداقل یکی هست.
روی دیتاست بزرگ این فرق فقط تئوری نیست؛ رو query plan، I/O، و latency واقعاً اثر میذاره.
توی حافظهٔ خود برنامه (نه دیتابیس) هم یه داستان مشابه با جزئیات متفاوت هست: enumerator، closure allocation، و اینکه چرا struct بودن Enumerator باعث میشه فرق اصلی سر heap نباشه، سر تعداد iteration باشه.
کل تحلیلش رو با کد، جدول پیچیدگی زمانی، و رسم Stack/Heap توی این پست نوشتم:
[لینک مقاله]
66 ·