C# Geeks (.NET)
Статистика- Последний пост
- 14 авг.
- Последнее чтение
- 15 авг.
- Постов за неделю
- 9
- Всего постов
- 41
- Тип
- открытый
- Язык
- персидский
- В каталоге с
- 13 авг.
- 1/24сутки в ленте
- 122
- 1/48двое суток
- 139
- 1/72трое суток
- 150
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
یک نکتهی تکمیلی: تجمیع مایگریشنها (Squashing Migrations) یکی از مباحث پیشرفته و حساس در نگهداری بلندمدت پروژههای مبتنی بر EF Core است. زمانی که یک پروژه چند سال فعال است یا در جریان یک بازنویسی سنگین صدها مایگریشن برای افزودن، حذف یا تغییر فیلدها ایجاد میشود، حجم بالای این فایلها سرعت بیلد، اجرای تستها و زمان پردازش مدل را کاهش میدهد. در این شرایط، هدف از Squashing این است که تاریخچه طولانی و خرد مایگریشنها به یک مایگریشن اولیه و یکپارچه (Initial/Baseline) تبدیل شود. چالش اصلی چیست؟ اگر شما صرفاً تمام فایلهای مایگریشن قبلی را پاک کنید و یک مایگریشن جدید به نام InitialCreate بسازید: در دیتابیس جدید: همهچیز عالی کار میکند و دیتابیس با آخرین ساختار ساخته میشود. در دیتابیسهای عملیاتی (Production/Staging): با خطای بحرانی مواجه میشوید! چون EF Core جدول __EFMigrationsHistory را چک میکند؛ این جدول نام تکتک مایگریشنهای قدیمی را دارد اما مایگریشن جدید شما (InitialCreate) را ندارد. در نتیجه تلاش میکند تمام جداول را از اول بسازد و با خطای Table already exists یا تخریب دیتابیس متوقف میشود. راهکار استاندارد EF Core برای تجمیع بدون شکستن دیتابیسهای موجود برای اینکه دیتابیسهای عملیاتی متوجه شوند که نیازی به اجرای مجدد ساختار ندارند، از تکنیک هماهنگسازی تاریخچه استفاده میشود: 1️⃣ ایجاد مایگریشن نهایی و خالی (Checkpoint Migration): پیش از دست زدن به فایلهای قدیمی، ابتدا مطمئن شوید تمام محیطهای عملیاتی به آخرین وضعیت مدل آپدیت شدهاند. سپس یک مایگریشن خالی به عنوان نقطه پایان (Checkpoint) بسازید: dotnet ef migrations add CheckpointSync این مایگریشن هیچ تغییری در کالبد ایجاد نمیکند اما یک رکورد با Timestamp مشخص تولید میکند. نام کامل این فایل (شامل عدد تاریخ/زمان ابتدای آن، مثلاً 20260814050000_CheckpointSync) را یادداشت کنید. 2️⃣ اعمال مایگریشن نهایی روی تمامی محیطهای موجود: دستور زیر را روی تمام دیتابیسهای عملیاتی، تست و توسعه اجرا کنید تا نام این مایگریشن در جدول __EFMigrationsHistory ثبت شود: dotnet ef database update 3️⃣ حذف فیزیکی مایگریشنهای قبلی: تمام فایلهای مایگریشن موجود در پوشه Migrations پروژه (از جمله فایل مایگریشن مرحله ۱) را حذف کنید. دقت کنید: فقط فایل Snapshot یا کدهای اصلی دیتابیس را دستکاری نکنید، صرفاً فایلهای لیست مایگریشنها را پاک کنید. 4️⃣ ایجاد یک مایگریشن جامع جدید: اکنون دستور ساخت مایگریشن جدید را صادر کنید تا تمام مدل فعلی در قالب یک فایل منفرد تجمیع شود: dotnet ef migrations add InitialBaseline 5️⃣ تطبیق نام و Timestamp مایگریشن جدید با Checkpoint: نام فایل، نام کلاس داخل فایل #C و همچنین مقدار شناسه درون فایل Snapshot تولیدشده را تغییر دهید تا دقیقاً برابر با همان نام و Timestamp مرحله اول (20260814050000_CheckpointSync) شود. نتیجه این فرآیند چیست؟ برای پایگاهدادههای موجود (Production): وقتی برنامه را بالا میآورید، EF Core جدول __EFMigrationsHistory را بررسی میکند. میبیند که رکورد 20260814050000_CheckpointSync قبلاً ثبت و اجرا شده است؛ بنابراین هیچ کدی اجرا نمیکند و دیتابیس دستنخورده باقی میماند. برای پایگاهدادههای جدید (New Deployments / Local Test DBs): دیتابیس تازه هیچ رکوردی در جدول تاریخچه ندارد؛ بنابراین همین یک مایگریشن تجمیعشده را از ابتدا اجرا میکند و تمام جداول را دقیقاً مطابق با آخرین مدل میسازد. چه زمانی باید مایگریشنها را Squash کنیم؟ انتشار نسخه ماژور (Major Release): زمانی که نسخه جدیدی از محصول ارائه میشود و میخواهید تمام تغییرات نسخههای قبل را پاکسازی و یکدست کنید. کاهش زمان بیلد و تست: در پروژههای بزرگ با صدها مایگریشن، سرعت ایجاد دیتابیس موقت برای تستهای یکپارچگی (Integration Tests) به شدت افزایش مییابد. تغییرات پرشمار در فاز توسعه (قبل از Production): در شاخههای فیچر پرحجم، تجمیع مایگریشنها پیش از Merge به برنچ اصلی (Main) تاریخچهای تمیز به جا میگذارد.
💡ءAPI Versioning در ASP.NET Core
#تحلیل_و_طرز_تفکر (Engineering Mindset) گاهی یک سؤال ساده میتواند کیفیت یک طراحی را مشخص کند: «اگر این بخش سیستم فردا خراب شود، چه چیزی باید بتواند بدون آن ادامه دهد؟» خیلی از سیستمها برای حالت سالم طراحی میشوند. ءDatabase در دسترس است. ءRedis سالم است. ءMessage Broker کار میکند. ءExternal API پاسخ میدهد. ءNetwork پایدار است. همهچیز طبق انتظار پیش میرود. اما Production دقیقاً جایی است که این فرضها شروع به شکستن میکنند. ءDatabase ممکن است ۳۰ ثانیه کند شود. ءRedis ممکن است از دسترس خارج شود. یک Message ممکن است دوبار Deliver شود. یک External API ممکن است Timeout کند. و Network ممکن است Packet Loss داشته باشد. اینجاست که تفاوت بین یک سیستم معمولی و یک سیستم Resilient مشخص میشود. سیستم خوب فقط نمیگوید: «اگر همهچیز سالم باشد، چه اتفاقی میافتد؟» بلکه میپرسد: «اگر یکی از وابستگیهای من خراب شود، دقیقاً چه چیزی باید همچنان کار کند؟» مثلاً اگر Notification Service از دسترس خارج شد، آیا ثبت سفارش هم باید Fail شود؟ اگر Analytics Service Down شد، آیا کاربر باید نتواند وارد سیستم شود؟ اگر Recommendation Service پاسخ نداد، آیا صفحه محصول باید Error بدهد؟ پاسخ این سؤالها را نمیتوان با یک Pattern آماده داد. باید از Business Requirement بیاید. به همین دلیل، Resilience فقط اضافه کردن Retry و Circuit Breaker نیست. اول باید مشخص کنی: کدام شکستها قابل تحملاند و کدامها نیستند. بعد برایشان طراحی کنی. چون در سیستمهای واقعی، خرابی Exception نیست. بخشی از شرایط عادی سیستم است که باید برایش طراحی شده باشی.
🎯 ایده اصلی کتاب چیست؟ مهمترین ایده کتاب این است که Engineering Management ادامهی طبیعی Senior Software Engineering نیست؛ یک نقش متفاوت با مسئلهای متفاوت است. وقتی Engineer هستی، بخش زیادی از خروجی تو مستقیماً از چیزهایی میآید که خودت میسازی: Code → Feature → System → Result اما وقتی Manager میشوی، دیگر قرار نیست خودت بیشترین کد را بنویسی. خروجی تو بیشتر از این مسیر میآید: People → Team → Environment → Engineering Output بنابراین کتاب تلاش میکند به کسی که تازه وارد Management شده یاد بدهد چگونه از حالت «خودم انجام میدهم» به «شرایطی ایجاد میکنم که تیم بتواند انجام دهد» تغییر کند. 📚 کتاب چه چیزهایی را آموزش میدهد؟ 1. 🧭 ورود به نقش Manager 🧠 2. اول خودت را مدیریت کن 👥 3. مدیریت افراد 🎯 4. ءDelegation؛ یکی از مهمترین مهارتها 🔥 5. ءMicromanagement 🗣 6. ءFeedback و Performance 🧑🏫 7. ءCoaching و Mentoring 🏗 8. ساختن یک Team خوب 📈 9. رشد شغلی افراد 🧩 10. فقط تیم خودت مهم نیست 📌 در یک جمله اگر بخواهم کتاب را خیلی خلاصه کنم: این کتاب به تو یاد نمیدهد چگونه Developerهای بیشتری مدیریت کنی؛ به تو یاد میدهد چگونه محیطی بسازی که Developerها بتوانند بهتر کار کنند، رشد کنند و خروجی بهتری بهعنوان یک تیم داشته باشند.
видео или голосовое, без подписи
#مهندس_فکر_کن قسمت:7️⃣
#فرمون_دادن یک اشتباه رایج در تیمهای نرمافزاری این است که فکر میکنیم برای سریعتر شدن، باید آدمهای بیشتری را وارد یک کار کنیم. پروژه عقب افتاده؟ آدم اضافه کن. تسک زیاد شده؟Developer اضافه کن. ءDeadline نزدیک است؟ تیم را بزرگتر کن. روی کاغذ منطقی به نظر میرسد. اما نرمافزار مثل خط تولید کارخانه نیست که با اضافه کردن آدم، خروجی همیشه بیشتر شود. فرض کنید یک تیم ۴ نفره روی یک Feature کار میکند. حالا برای اینکه سریعتر تمام شود، ۶ نفر دیگر هم اضافه میشوند. ناگهان باید: جلسههای بیشتری برگزار شود. Context بیشتری منتقل شود. Code Reviewهای بیشتری انجام شود. تصمیمهای بیشتری هماهنگ شود. و افراد بیشتری منتظر یکدیگر بمانند. یعنی بخشی از زمانی که قرار بود صرف ساختن شود، صرف هماهنگ شدن میشود. مشکل از آدمهای جدید نیست. مشکل این است که Complexity ارتباطی هم همراه آنها رشد میکند. برای همین، قبل از اینکه بگویی: «آدم بیشتری اضافه کنیم.» یک سؤال مهمتر بپرس: «مشکل واقعاً کمبود آدم است یا کمبود تمرکز؟» گاهی یک تیم کوچک که دقیقاً میداند چه چیزی باید بسازد، از یک تیم بزرگ که مدام در حال هماهنگ شدن است، سریعتر حرکت میکند. در مهندسی نرمافزار، تعداد بیشتر، همیشه به معنی سرعت بیشتر نیست. گاهی برای سریعتر شدن،باید بهجای اضافه کردن آدم، موانع را کم کنیم.
🗂چکلیست امنیت آپلود فایل در ASP.NET Core
#باور_غلط_یا_واقعیت؟ ❌ باور غلط «هرچه معماری تمیزتر باشد، سیستم بهتر است.» ✅ واقعیت معماری تمیز، همیشه معماری مناسب نیست. گاهی یک تیم، هفتهها زمان صرف میکند تا: همه چیز Interface داشته باشد. هر کلاس فقط یک مسئولیت داشته باشد. Dependencyها کاملاً از هم جدا شوند. همه چیز "طبق اصول" باشد. نتیجه؟ کدی که از نظر تئوری فوقالعاده است... اما توسعهدهنده جدید برای پیدا کردن یک منطق ساده باید از میان ۱۲ فایل عبور کند. گاهی آنقدر روی تمیز بودن معماری تمرکز میکنیم که فراموش میکنیم هدف اصلی چیست. کم کردن هزینهی تغییر. اگر یک معماری: فهم سیستم را سختتر کند، ءDebug کردن را طولانیتر کند، ءOnboarding اعضای جدید را دشوار کند، و هر تغییر کوچک را به دهها فایل بکشاند، شاید بیش از حد «تمیز» شده باشد. معماری خوب، معماریای نیست که بیشترین Pattern را داشته باشد. معماری خوب، معماریای است که حل مسئله را سادهتر کند، نه اینکه خودش به مسئله تبدیل شود. 💡 جمعبندی بین «کد تمیز» و «سیستم قابلفهم» همیشه علامت مساوی وجود ندارد. در مهندسی نرمافزار، زیبایی معماری را با تعداد Patternها نسنج. با سرعتی بسنج که تیم میتواند با اطمینان آن را تغییر دهد.
🚀 آیا تا به حال از <IProgress<T در #C استفاده کردهاید؟
видео или голосовое, без подписи
🚦 ءBack Pressure؛ چطور جلوی از کنترل خارج شدن سیستم را بگیریم؟
🚨 چرا خرابی یک سرویس، کل سیستم را از کار میاندازد؟
8. Leaderless replication —- 1. Designing Data Intensive Applications - Replication [6] /three-lens-tutor Leaderless replication @thisisnabi_dev
#تصمیمهای_مهندسی (Engineering Decisions) یکی از سختترین تصمیمهای مهندسی، انتخاب بین درست بودن و در دسترس بودن است. فرض کنید Database اصلی شما از دسترس خارج شده است. یک Replica دارید که چند ثانیه از دیتای اصلی عقبتر است. حالا دو انتخاب دارید. انتخاب اول: کاربر را منتظر نگه دارید یا حتی درخواست را Fail کنید، تا مطمئن شوید دادهای که نمایش میدهید کاملاً بهروز است. انتخاب دوم: درخواست را از Replica پاسخ دهید. کاربر سرویس را دریافت میکند... اما شاید اطلاعاتی را ببیند که چند ثانیه قدیمی است. کدام تصمیم درست است؟ اگر در حال نمایش تعداد لایک یک پست باشید، احتمالاً چند ثانیه اختلاف اهمیتی ندارد. اما اگر موجودی حساب بانکی یا تعداد باقیمانده بلیت یک کنسرت را نمایش میدهید، همان چند ثانیه میتواند یک فاجعه ایجاد کند. به همین دلیل، مهندسان باتجربه هیچوقت نمیپرسند: «ءConsistency بهتر است یا Availability؟» بلکه میپرسند: «در این Domain، هزینهی کدام اشتباه بیشتر است؟» چون هیچ معماریای وجود ندارد که در هر شرایطی، هم بیشترین Availability را داشته باشد و هم قویترین Consistency را. هر تصمیم، یک Trade-off است. و ارزش یک مهندس، در انتخاب تکنولوژی نیست. در درک هزینهی انتخابها است. چون در مهندسی نرمافزار، بهترین تصمیم، تصمیمی نیست که هیچ هزینهای نداشته باشد. بهترین تصمیم، تصمیمی است که هزینهی درست را بپردازد.
⏰ ءQuartz.NET؛ چرا تقریباً هر پروژهای دیر یا زود به یک Scheduler نیاز پیدا میکند؟
#تحلیل_و_طرز_تفکر (Engineering Mindset) یک سؤال هست که مهندسهای باتجربه بیشتر از بقیه از خودشان میپرسند: «اگر من شش ماه دیگر از این تیم بروم، چه اتفاقی برای این سیستم میافتد؟» اگر جواب این باشد که: فقط خودم میدانم این بخش چطور کار میکند. فقط خودم میتوانم آن را Deploy کنم. فقط خودم میتوانم باگش را پیدا کنم. فقط خودم میدانم چرا این تصمیم را گرفتهایم. شاید مسئله، مهارت بالا نباشد. شاید سیستم، بیش از حد به یک نفر وابسته شده است. یکی از نشانههای بلوغ مهندسی این نیست که خودت بتوانی همه مشکلات را حل کنی. این است که دیگران هم بتوانند بعد از تو سیستم را ادامه دهند. به همین دلیل، مستندسازی، Code Review، Naming مناسب، تست و ثبت تصمیمهای معماری فقط برای امروز نیستند. همهی آنها برای روزی هستند که شخص دیگری باید بدون حضور تو، روی همان سیستم کار کند. یک مهندس خوب، سیستم میسازد. یک مهندس بالغ، سیستمی میسازد که به خودش وابسته نباشد. چون در نهایت، بهترین کد، کدی نیست که فقط نویسندهاش آن را بفهمد. بهترین کد، کدی است که نبودِ نویسندهاش، تیم را متوقف نکند.
🎫 وقتی فقط یک صندلی باقی مانده باشد، چگونه مطمئن میشوید فقط یک نفر آن را رزرو میکند؟
🚦 چه زمانی در ASP.NET Core باید از CancellationTokenSource استفاده کنیم؟ یکی از قابلیتهایی که از NET 4. به این طرف وارد فریمورک شد، Cooperative Cancellation است. قبل از آن، برای متوقف کردن Threadها معمولاً از APIهایی مانند Thread.Abort() استفاده میشد؛ APIهایی که میتوانستند Thread را در هر نقطهای متوقف کنند و باعث ناپایداری برنامه شوند. به همین دلیل مایکروسافت مدل جدیدی را معرفی کرد: هیچ عملیاتی نباید به زور متوقف شود؛ خود عملیات باید تصمیم بگیرد که چه زمانی متوقف شود. به این مدل Cooperative Cancellation گفته میشود. 💡 سه بازیگر اصلی در Cancellation مستندات NET. سه جزء اصلی را معرفی میکنند: 1️⃣ CancellationTokenSource این کلاس مسئول ارسال درخواست لغو است. using var cts = new CancellationTokenSource(); 2️⃣ CancellationToken این ساختار فقط وضعیت لغو را نگه میدارد. CancellationToken token = cts.Token; هرگز خودش عملیات را متوقف نمیکند. 3️⃣ عملیاتی که Token را دریافت میکند مثلاً: HttpClient EF Core Task.Delay Stream File APIs Parallel APIs همگی Token را دریافت میکنند. await Task.Delay( TimeSpan.FromSeconds(10), token); اگر درخواست لغو ارسال شود، خود Task.Delay تصمیم میگیرد عملیات را متوقف کند. 🏗 جریان کار چگونه است؟ CancellationTokenSource │ │ Cancel() ▼ CancellationToken │ ▼ HttpClient / EF Core / Task / ... │ ▼ OperationCanceledException نکته مهم: ءCancellationTokenSource هیچ Task یا Threadی را Kill نمیکند. فقط اعلام میکند: "اگر هنوز مشغول کار هستی، لطفاً متوقف شو." این دقیقاً همان چیزی است که Microsoft از آن با عنوان Cooperative Cancellation یاد میکند. 🎯 حالا سؤال اصلی: در ASP.NET Core چه زمانی باید خودمان CancellationTokenSource بسازیم؟ ✅ سناریو اول: Timeout اختصاصی فرض کنید فراخوانی یک سرویس پرداخت نباید بیشتر از ۵ ثانیه طول بکشد. using var cts = new CancellationTokenSource( TimeSpan.FromSeconds(5)); await gateway.PayAsync( request, cts.Token); بعد از ۵ ثانیه: cts.Cancel() به صورت خودکار اجرا میشود. طبق مستندات، این یکی از رایجترین کاربردهای CancellationTokenSource است. ✅ سناریو دوم: لغو دستی عملیات فرض کنید کاربر دکمه Cancel را فشار میدهد. cts.Cancel(); از این لحظه تمام عملیاتهایی که این Token را دریافت کردهاند متوجه درخواست لغو میشوند. ✅ سناریو سوم: ترکیب چند Token در ASP.NET Core معمولاً این Token را دارید: HttpContext.RequestAborted این Token زمانی Cancel میشود که: مرورگر بسته شود. Client ارتباط را قطع کند. حالا فرض کنید علاوه بر آن، میخواهید Timeout هم داشته باشید. مایکروسافت پیشنهاد میکند: using var timeout = new CancellationTokenSource( TimeSpan.FromSeconds(10)); using var linked = CancellationTokenSource .CreateLinkedTokenSource( HttpContext.RequestAborted, timeout.Token); در این حالت اگر هر کدام از Tokenها Cancel شوند، عملیات نیز Cancel خواهد شد. ❌ اشتباه رایج در بسیاری از پروژهها میبینیم: public async Task Handle() { using var cts = new CancellationTokenSource(); ... } بدون هیچ دلیل مشخصی. در حالی که ASP.NET Core خودش Token مناسب را در اختیار شما قرار داده است: public async Task<IActionResult> Create( CancellationToken cancellationToken) اگر فقط میخواهید عملیات در صورت لغو Request متوقف شود، همان Token را به تمام لایهها پاس دهید. ساخت CancellationTokenSource جدید، ارتباط عملیات با Request اصلی را قطع میکند. ⚠️ نکتهای که خیلیها نمیدانند ءCancellationTokenSource از IDisposable پیروی میکند. مایکروسافت صراحتاً توصیه میکند بعد از اتمام کار آن را Dispose کنید. using var cts = new CancellationTokenSource(); ⚠️ یک باور اشتباه بعضیها تصور میکنند: Cancel() یعنی Task فوراً متوقف میشود. اما مستندات دقیقاً برعکس این را میگویند. بعد از ارسال درخواست لغو، این خود عملیات است که باید: token.ThrowIfCancellationRequested(); را بررسی کند یا APIای که Token را دریافت کرده، به آن واکنش نشان دهد. به همین دلیل به این مدل میگویند: Cooperative Cancellation نه Forced Cancellation.
🚀 ءGitHub Actions برای NET: Build، Test. و انتشار با Docker(قسمت 2️⃣)