Лучшие посты
за три месяцабез подписи
#روایت_تجربه (Storytelling) چند وقت پیش، یکی از مهندسهای یک شرکت تعریف میکرد که بعد از چند ماه کار روی یک قابلیت جدید، بالاخره آن را وارد محیط Production کردند. همهچیز عالی پیش رفت. هیچ Errorی ثبت نشد.Latency هم طبیعی بود. همه فکر میکردند انتشار موفقیتآمیز بوده است. اما چند روز بعد، تیم محصول گزارش داد که کاربران تقریباً از آن قابلیت استفاده نمیکنند. مشکل از کد نبود. مشکل این بود که قابلیتی ساخته شده بود که کسی واقعاً به آن نیاز نداشت. او میگفت: «ما موفق شدیم چیزی را بسازیم که هیچکس منتظرش نبود.» این جمله مدتها در ذهنم ماند. چون ما مهندسها معمولاً موفقیت را با معیارهای فنی میسنجیم: باگ نداشت. تستها پاس شدند. Performance خوب بود. Deployment بدون مشکل انجام شد. اما بیزینس سؤال دیگری میپرسد: «آیا این قابلیت ارزشی برای کاربر ایجاد کرد؟» اگر جواب این سؤال «نه» باشد، ممکن است از نظر فنی یک شاهکار ساخته باشیم، اما از نظر محصول، شکست خورده باشیم. از آن روز، هر بار که درباره کیفیت یک Feature صحبت میشود، یادم میآید که کیفیت فقط به این نیست که درست کار کند. باید دلیل وجود داشتنش هم درست باشد. چون در مهندسی نرمافزار،ساختن چیز درست،بهاندازهی ساختن چیزِ درست برای کاربر مهم نیست.
#AI_Software_Engineering مدتی قبل فکر میکردم برای کار کردن با AI حتماً باید یک فرآیند جدید، یک چارچوب پیچیده و یک روش توسعه کاملاً متفاوت داشته باشیم.Prompt Engineering. Workflowهای عجیب. قوانین سخت برای استفاده از AI. اما کمکم یک سؤال در ذهنم شکل گرفت: نکند بخشی از این پیچیدگیها را خودمان ساختهایم، فقط چون هنوز نمیدانیم چطور با این ابزار جدید کنار بیاییم؟ ما سالها برای اینکه سیستمها قابل کنترل باشند، ساختار ایجاد کردیم. Architecture. Design Pattern. Code Review. Testing. Documentation. همه اینها ارزشمند هستند. اما شاید بخشی از آنها، پاسخی به محدودیتهای گذشته بودهاند. امروز یک AI Agent میتواند در چند دقیقه کاری را انجام دهد که قبلاً ساعتها زمان میبرد. Refactor کردن یک بخش بزرگ از سیستم. پیدا کردن Dependencyها. نوشتن Test. پیشنهاد تغییرات. حتی آماده کردن یک Pull Request. اینجا یک سؤال مهم مطرح میشود: آیا ما باید AI را مجبور کنیم مثل یک Developer قدیمی کار کند؟ یا باید یاد بگیریم چطور سطح تعامل خودمان با سیستمها را بالاتر ببریم؟ چون شاید در آینده، ارزش یک مهندس کمتر در این باشد که: «چقدر سریع کد مینویسی؟» و بیشتر در این باشد که: «آیا میدانی چه چیزی باید ساخته شود؟» اما یک نکته هنوز تغییر نکرده. AI میتواند تغییر ایجاد کند. اما مسئولیت تصمیمگیری هنوز با انسان است. چون یک سیستم اشتباه، اگر با AI سریعتر ساخته شود... فقط سریعتر به یک مشکل بزرگ تبدیل میشود. شاید آینده برنامهنویسی این نباشد که انسانها کمتر کد بنویسند. شاید آینده این باشد که انسانها کمتر درگیر جزئیات شوند و بیشتر روی تفکر مهندسی تمرکز کنند. چون ابزارها همیشه تغییر میکنند. اما توانایی تشخیص یک تصمیم درست از یک تصمیم اشتباه، همیشه ارزشمند باقی میماند.
без подписи
🚨 چرا خرابی یک سرویس، کل سیستم را از کار میاندازد؟
#تصمیمهای_مهندسی (Engineering Decisions) یکی از سختترین تصمیمهای مهندسی، انتخاب بین درست بودن و در دسترس بودن است. فرض کنید Database اصلی شما از دسترس خارج شده است. یک Replica دارید که چند ثانیه از دیتای اصلی عقبتر است. حالا دو انتخاب دارید. انتخاب اول: کاربر را منتظر نگه دارید یا حتی درخواست را Fail کنید، تا مطمئن شوید دادهای که نمایش میدهید کاملاً بهروز است. انتخاب دوم: درخواست را از Replica پاسخ دهید. کاربر سرویس را دریافت میکند... اما شاید اطلاعاتی را ببیند که چند ثانیه قدیمی است. کدام تصمیم درست است؟ اگر در حال نمایش تعداد لایک یک پست باشید، احتمالاً چند ثانیه اختلاف اهمیتی ندارد. اما اگر موجودی حساب بانکی یا تعداد باقیمانده بلیت یک کنسرت را نمایش میدهید، همان چند ثانیه میتواند یک فاجعه ایجاد کند. به همین دلیل، مهندسان باتجربه هیچوقت نمیپرسند: «ءConsistency بهتر است یا Availability؟» بلکه میپرسند: «در این Domain، هزینهی کدام اشتباه بیشتر است؟» چون هیچ معماریای وجود ندارد که در هر شرایطی، هم بیشترین Availability را داشته باشد و هم قویترین Consistency را. هر تصمیم، یک Trade-off است. و ارزش یک مهندس، در انتخاب تکنولوژی نیست. در درک هزینهی انتخابها است. چون در مهندسی نرمافزار، بهترین تصمیم، تصمیمی نیست که هیچ هزینهای نداشته باشد. بهترین تصمیم، تصمیمی است که هزینهی درست را بپردازد.
🚦 چه زمانی در 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(قسمت 1️⃣)
без подписи
🚀 ءGitHub Actions برای NET: Build، Test. و انتشار با Docker(قسمت 2️⃣)
без подписи
#تحلیل_و_طرز_تفکر (Engineering Mindset) یک سؤال هست که مهندسهای باتجربه بیشتر از بقیه از خودشان میپرسند: «اگر من شش ماه دیگر از این تیم بروم، چه اتفاقی برای این سیستم میافتد؟» اگر جواب این باشد که: فقط خودم میدانم این بخش چطور کار میکند. فقط خودم میتوانم آن را Deploy کنم. فقط خودم میتوانم باگش را پیدا کنم. فقط خودم میدانم چرا این تصمیم را گرفتهایم. شاید مسئله، مهارت بالا نباشد. شاید سیستم، بیش از حد به یک نفر وابسته شده است. یکی از نشانههای بلوغ مهندسی این نیست که خودت بتوانی همه مشکلات را حل کنی. این است که دیگران هم بتوانند بعد از تو سیستم را ادامه دهند. به همین دلیل، مستندسازی، Code Review، Naming مناسب، تست و ثبت تصمیمهای معماری فقط برای امروز نیستند. همهی آنها برای روزی هستند که شخص دیگری باید بدون حضور تو، روی همان سیستم کار کند. یک مهندس خوب، سیستم میسازد. یک مهندس بالغ، سیستمی میسازد که به خودش وابسته نباشد. چون در نهایت، بهترین کد، کدی نیست که فقط نویسندهاش آن را بفهمد. بهترین کد، کدی است که نبودِ نویسندهاش، تیم را متوقف نکند.
🚦 ءBack Pressure؛ چطور جلوی از کنترل خارج شدن سیستم را بگیریم؟
без подписи
🎫 وقتی فقط یک صندلی باقی مانده باشد، چگونه مطمئن میشوید فقط یک نفر آن را رزرو میکند؟
- 6 авг.224 просмотров
8. Leaderless replication —- 1. Designing Data Intensive Applications - Replication [6] /three-lens-tutor Leaderless replication @thisisnabi_dev
⏰ ءQuartz.NET؛ چرا تقریباً هر پروژهای دیر یا زود به یک Scheduler نیاز پیدا میکند؟
🚀 آیا تا به حال از <IProgress<T در #C استفاده کردهاید؟
#باور_غلط_یا_واقعیت؟ ❌ باور غلط «هرچه معماری تمیزتر باشد، سیستم بهتر است.» ✅ واقعیت معماری تمیز، همیشه معماری مناسب نیست. گاهی یک تیم، هفتهها زمان صرف میکند تا: همه چیز Interface داشته باشد. هر کلاس فقط یک مسئولیت داشته باشد. Dependencyها کاملاً از هم جدا شوند. همه چیز "طبق اصول" باشد. نتیجه؟ کدی که از نظر تئوری فوقالعاده است... اما توسعهدهنده جدید برای پیدا کردن یک منطق ساده باید از میان ۱۲ فایل عبور کند. گاهی آنقدر روی تمیز بودن معماری تمرکز میکنیم که فراموش میکنیم هدف اصلی چیست. کم کردن هزینهی تغییر. اگر یک معماری: فهم سیستم را سختتر کند، ءDebug کردن را طولانیتر کند، ءOnboarding اعضای جدید را دشوار کند، و هر تغییر کوچک را به دهها فایل بکشاند، شاید بیش از حد «تمیز» شده باشد. معماری خوب، معماریای نیست که بیشترین Pattern را داشته باشد. معماری خوب، معماریای است که حل مسئله را سادهتر کند، نه اینکه خودش به مسئله تبدیل شود. 💡 جمعبندی بین «کد تمیز» و «سیستم قابلفهم» همیشه علامت مساوی وجود ندارد. در مهندسی نرمافزار، زیبایی معماری را با تعداد Patternها نسنج. با سرعتی بسنج که تیم میتواند با اطمینان آن را تغییر دهد.
🗂چکلیست امنیت آپلود فایل در ASP.NET Core