iLearn
24 subscribers
16 links
Download Telegram
Channel created
Channel photo updated
این کانال رو زدم صرفا جهت اشتراک دانشی که از مطالعاتم بدست میارم
سپاس گزارم از همراهی شما🌱
❤1
من یه مقاله به تازگی نوشتم در خصوص چرایی وجود یک سری primitives keyword ها در سی شارپ و چجوری اینا میتونن به توسعه و کاهش latency سیستم به ما کمک کنند با مثال واقعی:
https://mhmdnzr.drl.ink/post/concurrent-file-uploader
❤1
پارسال رفته بودم مصاحبه Asan Pardakht برای نیروی دات نت
یک سوالی اونجا ازم کرد که خیلی برام جالب بود، پرسید فرق بین for vs foreach تووی سی شارپ چیه؟
خب این یه سوال به ظاهر خیلی سادست اما وقتی ترکیب میشه با دیتابیس و فچ دیتا میبینی انگار چوب جادوی هری پاترو انگار پیدا کردی
تووی این بلاگ سعی کردم در مورد این موضوع بییشتر صحبت کنم که چیشد اینجوری شد!
پ.ن: البته اینم بگم که من قبول نشدم تووی مصاحبه اما هربار که من fail میشم خلاهای بیشتری رو در خودم کشف میکنم و به ظرف دانش یک قسمت دیگه اضافه میکنم تا بهتر از دیروز بشم
#csharp #dotnet #software #architecture #pattern #learning

https://mhmdnzr.drl.ink/post/for-vs-foreach
❤1
دارم روی یه سری پست کار می‌کنم که موضوعش دور و بر همون چیزیه که این روزها خیلی درگیرشم: latency، consistency، و اون لحظه‌هایی که سیستم یه چیزی رو "فکر می‌کنه" داره درست انجام می‌ده ولی در واقع نداره. این پست از دل یه بحث واقعی دراومد — یه سناریوی ساده که همه‌مون یه جایی باهاش برخورد کردیم ولی خیلی‌ها (منم قبلاً) دقیق بهش فکر نکردیم که چرا واقعاً خطرناکه.

بذارید مستقیم بریم سراغ صحنه‌ی جرم.
https://mhmdnzr.drl.ink/post/distributed-lock
❤1
یه جایی توی پروژه‌مون به خودمون گفتیم:

«بابا 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
❤2
این جمله درسته که همیشه دیتای حجیم باعث مرگ سیستم میشه؟ یا یک hot path در لایه infra SQL باعث میشه به ددلاک بخوریم؟
چجوری میشه حلش کرد؟ صرفا چندتا راه همیشگی AsNoTracking, AsSplitQuery, projection, N+1 problem و... یا استفاده از compiled query مارو از این منجلاب بیرون میکشه؟
یا شاید در زبان سی شارپ و ویژگی هاش باید دیپ تر بشیم؟
خب بنظرم گزاره دوم درسته، ما فهم ناقصی از سیستم کارکرد سی شارپ داشتیم
تووی این مقاله سعی کردم راه حلمو با for vs foreach ترکیب کنم و بهتون ارائه بدم.
میتونین از طریق لینک زیر مطالعه کنید:

https://mhmdnzr.drl.ink/post/d0040081
❤1
ما اکثرا از FirstOrDefault استفاده کردیم تا بخوایم بر اساس کلید یا یک ستون بریم داخل دیتا بیس پیدا کنیم، اما بقیش چی؟ کلا پنج تابع اصلی داریم برای پیدا کردن. اونا چیکار میکنن؟ تبدیل به چه کوئری میشه در نهایت؟
همه و همه در این مقاله جا شدن:
تفاوت در پیدا کردن است!

https://mhmdnzr.drl.ink/post/4ff4fb50
❤1
چرا وقتی میخوایم بدونیم یه آیتم توی دیتابیس یا یک 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 توی این پست نوشتم:
[لینک مقاله]
❤2