🌍 مثالهای واقعی از Extension Memberها
در Web APIها، معمولاً نیاز داریم اطلاعاتی از HttpContext استخراج کنیم.
بهجای تکرار کدهای مشابه، میتوانیم extension بنویسیم تا کد تمیزتر شود ✨
public static class ApiHttpContextExtensions
{
extension(HttpContext context)
{
public string CorrelationId =>
context.Request.Headers["X-Correlation-ID"].FirstOrDefault()
?? Guid.NewGuid().ToString();
public string ClientIp =>
context.Request.Headers["X-Forwarded-For"].FirstOrDefault()
?? context.Connection.RemoteIpAddress?.ToString()
?? "Unknown";
public bool IsApiRequest =>
context.Request.Path.StartsWithSegments("/api");
public string? GetBearerToken()
{
var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
if (authHeader?.StartsWith("Bearer ") == true)
{
return authHeader.Substring("Bearer ".Length).Trim();
}
return null;
}
public T? GetQueryParameter<T>(string key)
{
if (context.Request.Query.TryGetValue(key, out var value))
{
try
{
return (T?)Convert.ChangeType(value.ToString(), typeof(T));
}
catch
{
return default;
}
}
return default;
}
public void AddResponseHeader(string key, string value)
{
context.Response.Headers[key] = value;
}
}
extension(HttpContext)
{
public static bool IsValidPath(string path) =>
!string.IsNullOrWhiteSpace(path) && path.StartsWith("/");
}
}
حالا middleware و controllerها بسیار خواناتر میشوند 🧼
public class RequestLoggingMiddleware(
RequestDelegate next,
ILogger<RequestLoggingMiddleware> logger)
{
public async Task InvokeAsync(HttpContext context)
{
_logger.LogInformation(
"Request {Method} {Path} from {ClientIp} with CorrelationId {CorrelationId}",
context.Request.Method,
context.Request.Path,
context.ClientIp,
context.CorrelationId);
context.AddResponseHeader("X-Correlation-ID", context.CorrelationId);
await _next(context);
}
}
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[HttpGet]
public IActionResult GetOrders(HttpContext httpContext)
{
var pageSize = httpContext.GetQueryParameter<int?>("pageSize") ?? 10;
var pageNumber = httpContext.GetQueryParameter<int?>("page") ?? 1;
var orders = orderService.GetPaged(pageNumber, pageSize);
return Ok(orders);
}
}
📌 نتیجه؟
کد خواناتر 📖، تمیزتر 🧹 و بدون تکرار منطق پیچیدهی استخراج header و query parameterها، با defaultهای معقول ✅
✅ بهترین روشها برای سازماندهی کدهای Extension در C# 14 🧩✨
🗂 چطور Extension Blockها را سازماندهی کنیم؟
وقتی از کلیدواژه extension استفاده میکنید، میتوانید چندین extension member که روی یک type اعمال میشوند را داخل یک extension block قرار دهید.
این کار باعث کاهش تکرار 🔁 و کنار هم ماندن کدهای مرتبط میشود 🧠
همچنین میتوانید در یک static class چند extension block داشته باشید؛
مثلاً برای receiverهای متفاوت یا generic type parameterهای مختلف 👇
public static class CollectionExtensions
{
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
public bool HasItems => source.Any();
public int Count => source.Count();
}
extension(IEnumerable<string> source)
{
public string JoinWithComma() => string.Join(", ", source);
public IEnumerable<string> NonEmpty() => source.Where(s => !string.IsNullOrEmpty(s));
}
extension<T>(List<T> list)
{
public void AddIfNotExists(T item)
{
if (!list.Contains(item))
{
list.Add(item);
}
}
}
}
🔄 ترکیب syntax قدیمی و جدید
میتوانید syntax قدیمی (this) و syntax جدید (extension) را در یک کلاس با هم استفاده کنید 👍
public static class StringExtensions
{
// Traditional syntax
public static bool IsEmail(this string value)
{
return value.Contains("@");
}
// New syntax
extension(string value)
{
public bool IsUrl =>
Uri.TryCreate(value, UriKind.Absolute, out _);
public string ToTitleCase() =>
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value.ToLower());
}
}
🚫 از ساختن Extension Classهای غولپیکر اجتناب کنید
یک کلاس بزرگ با extension برای دهها type مختلف، بهمرور تبدیل به کابوس نگهداری میشود 😵💫
بهتر است extensionها را بر اساس domain یا کاربرد گروهبندی کنید 👇
public static class ProductExtensions
{
extension(Product product)
{
// Product-specific extensions
}
}
public static class ValidationExtensions
{
extension(Order value)
{
// Validation logic
}
extension(OrderItem value)
{
// Validation logic
}
}
📌 انتخاب ساختار مناسب کاملاً به نیاز پروژه بستگی دارد:
یا یک static class برای هر type
یا گروهبندی بر اساس functionality
🧮 برای مقادیر محاسباتی از Extension Property استفاده کنید
اگر extensionای دارید که پارامتری نمیگیرد و فقط یک مقدار برمیگرداند،
بهتر است بهجای method، آن را property تعریف کنید 👌
extension(Order order)
{
public decimal TotalPrice =>
order.Items.Sum(item => item.Price * item.Quantity);
}
✍️ نامگذاری معنادار انتخاب کنید
ءExtension propertyها باید طوری خوانده شوند که انگار عضو اصلی type هستند.
از نامهایی که «داد میزنند extension هستند» پرهیز کنید ❌
// Good
public bool IsEmpty => !source.Any();
public string DisplayPrice => price.ToString("C");
📚 ءExtensionها را مستند کنید
در پروژههای بزرگ، حتماً از XML Comment استفاده کنید تا بقیه اعضای تیم دقیقاً بدانند این extension چه کاری انجام میدهد 🧑💻📖
extension(Product product)
{
/// <summary>
/// Gets whether the product is currently available for purchase.
/// </summary>
/// <remarks>
/// A product is available if its stock quantity is greater than zero.
/// </remarks>
public bool IsAvailable => product.StockQuantity > 0;
}
🧾 جمعبندی
کلیدواژه extension در C# 14 اختیاری است ✅
تمام extension methodهای قبلی شما بدون هیچ تغییری همچنان کار میکنند.
اما زمانی که:
میخواهید property اضافه کنید 🧩
ءmemberهای static داشته باشید 🏗
یا کدهای مرتبط را تمیزتر و یکجا نگه دارید 🧹
ءsyntax جدید تجربه توسعهدهنده بسیار بهتری فراهم میکند ✨
اگر با C# 14 و NET 10. کار میکنید، حتماً extension propertyها را در پروژههایتان امتحان کنید.
بهزودی متوجه میشوید چقدر جا دارد methodها به property تبدیل شوند و کدها طبیعیتر و قابلفهمتر شوند 🧠💡
امیدوارم این مطلب براتون مفید بوده باشه 🙌
تا مطلب بعدی، موفق باشید 👋
پند روز جمعه: 🔥 یه نظر متفاوت درباره «دوباره اختراع کردن چرخ»:
شاید… واقعاً اتلاف وقتِ خوبی باشه ⏳😉
ادعای رایج منطقیه؛ مخصوصاً وقتی هدفت، تحویل سریع ارزش به کاربره 🚀
اما بیاید از یه زاویه دیگه نگاه کنیم 👀
برای یادگیری، میتونه فوقالعاده باشه.
بهخصوص وقتی اول مسیرت هستی 🌱
وقتی چیزی رو از صفر میسازی، حتی اگه هزار بار قبلاً ساخته شده باشه، مجبور میشی مفاهیم زیرساختی رو عمیقاً بفهمی 🧠
✨ چه اتفاقی میافته؟
• با تصمیمهای طراحی واقعی درگیر میشی 🧩
• با چالشهایی روبهرو میشی که اصلاً انتظارش رو نداشتی ⚠️
• و مهمتر از همه، واقعاً میفهمی چیزها «چطور» کار میکنن 🔍
🍳 بهش اینطوری فکر کن:
هیچکس فقط با خوندن کتاب آشپزی، سرآشپز حرفهای نمیشه.
باید دستهات رو توی آشپزخونه کثیف کنی! 👨🍳🔥
همین موضوع دقیقاً درباره مهندسی نرمافزار هم صدق میکنه 💻
اگه هدفت یادگیری عمیقتر و درک واقعی مفاهیمه، چرا خودت نسازی؟
🔄 الگوی (Saga Pattern) Saga (بخش ششم)
الگوی Saga Pattern برای مدیریت distributed transactions در چندین سرویس استفاده میشود. این الگو با شکستن یک تراکنش توزیعشده به دنبالهای از local transactions کار میکند.
هر local transaction فقط دادههای همان سرویس را تغییر میدهد و سپس یک event یا message منتشر میکند تا مرحله بعدی شروع شود 📣
اگر در هر مرحله خطایی رخ دهد، compensating transactions اجرا میشوند تا تغییرات مراحل قبلی را خنثی کنند و data consistency بین سرویسها حفظ شود 🔁
⚙️ ءSaga چگونه کار میکند؟
1️⃣ یک Saga زمانی شروع میشود که یک فرآیند تجاری نیاز به تغییر داده در چند سرویس داشته باشد
2️⃣ ءSaga coordinator تراکنش توزیعشده را به چند local transaction (یکی برای هر سرویس) تقسیم میکند
3️⃣ هر سرویس local transaction خودش را اجرا میکند و یک event مبنی بر موفقیت یا شکست منتشر میکند
4️⃣ ءCoordinator به این eventها گوش میدهد و مرحله بعدی را فعال میکند 👂
5️⃣ اگر همه مراحل با موفقیت انجام شوند، Saga پایان مییابد و تراکنش کامل تلقی میشود ✅
6️⃣ اگر هر مرحلهای شکست بخورد، compensating transactions بهترتیب معکوس اجرا میشوند تا تغییرات قبلی undo شوند ♻️
7️⃣ دو رویکرد اصلی برای پیادهسازی وجود دارد:
ءChoreography: سرویسها از طریق eventها با هم هماهنگ میشوند 🎭
ءOrchestration: یک coordinator مرکزی جریان کار را مدیریت میکند 🎼
🌟 مزایا (Benefits)
✔️ امکان اجرای distributed transactions در معماری microservices بدون نیاز به distributed locks یا two-phase commit
✔️ حفظ سازگاری دادهها با استفاده از compensating transactions بهجای rollbackهای سنگین
✔️ مناسب برای long-running business processes با تحمل خطای بالاتر 🛡
✔️ مقیاسپذیری بهتر، چون هر سرویس فقط مسئول local transaction خودش است 📈
⚠️ معایب (Drawbacks)
❌ پیچیدگی بالا در طراحی و پیادهسازی compensating transaction برای هر مرحله
❌ ایجاد eventual consistency که ممکن است باعث وضعیتهای موقتاً ناسازگار برای کاربر شود ⏳
❌ سختتر شدن debugging و monitoring چون تراکنشها در چند سرویس و در طول زمان پخش شدهاند
❌ سناریوهای پیچیدهی مدیریت خطا، مخصوصاً زمانی که خود compensating transaction هم شکست بخورد
🎯 موارد استفاده (Use cases)
📌 ءworkflowهای چندمرحلهای در سیستمهای enterprise که هر مرحله توسط یک سرویس جداگانه انجام میشود
📌 هر فرآیند تجاری که نیاز به تغییر هماهنگ دادهها در چند microservice دارد، بدون استفاده از distributed lock
✨ جمعبندی:
ءSaga Pattern یک راهحل کلیدی برای مدیریت تراکنشهای پیچیده در معماریهای توزیعشده است. اگرچه پیادهسازی آن ساده نیست، اما برای سیستمهای microservice-scale تقریباً اجتنابناپذیر است.
ما ۰.۱ ثانیه توی اجرا صرفهجویی کردیم، ولی ۳ روز از عمر تیم رو به باد دادیم!
چند وقت پیش توی پروژهای بودم که یکی از بچهها وسواس عجیبی روی سرعت داشت. ما یه کد تر و تمیز داشتیم که کار میکرد. ولی این همکارم گفتش که: "نه، این تابعی که نوشتی کنده! بذار پرفورمنسش رو ببرم بالا."
شروع کرد به تغییرات عجیب به بهانهی اینکه فراخوانی توابع سربار (Overhead) داره، توابعِ کوچیک و خوانا رو حذف کرد و همه رو ریخت توی یه تابعِ. شرطهای if/else شفاف رو تبدیل کرد به یک خط محاسبهی ریاضی پیچیده تا CPU کمتری مصرف بشه.
ما اولش هیجانزده بودیم و میگفتیم که دمت گرم! الان چون کد کوتاهتر شده و تابع کمتر صدا زده میشه، حتما درخواستا خیلی سریع پردازش میشن.
نتیجه؟ کاربر نهایی اصلا متوجه اون سرعت ناچیز نشد (چون گلوگاه اصلا اونجا نبود). اما چند وقت بعد، وقتی بیزینس یه تغییر کوچیک خواست، ما فلج شدیم.
کدی که قبلا توی ۱۰ دقیقه ادیت میشد، حالا شده بود یه میدون مین. هیچکس نمیفهمید اون خط طولانی ریاضی دقیقا داره چیکار میکنه. ما خوانایی رو قربانی یه سرعت توهمی کرده بودیم.
اینجا بود که یاد جملهی معروف دونالد کنوث افتادم: "بهینهسازی زودهنگام (Premature Optimization)، ریشهی تمام دردسرهاست."
ما داشتیم دقیقا همین مصیبت رو سر خودمون میاوردیم و قانونِ طلایی Uncle Bob رو فراموش کرده بودیم:
قانون ۱۰ به ۱: ما ۱۰ برابر زمانی که کد مینویسیم، صرف خوندن کد میکنیم. اون کدی که دوستمون زد، شاید نوشتنش ۱ ساعت طول کشید، ولی خوندن و دیباگ کردنش ۱۰ ساعت از وقت کل تیم رو گرفت. هر خط کدی که به بهانهی Performance ناخوانا میشه، داره هزینهی نگهداری رو تصاعدی میبره بالا.
ما یاد گرفتیم بهینهسازی واقعی این نیست که کد رو فشرده کنی. بهینهسازی واقعی اینه که کدی بنویسی که نفر بعدی (یا خود ۶ ماه بعدت) بتونه راحت بخونه و توسعهش بده.
چند وقت پیش توی پروژهای بودم که یکی از بچهها وسواس عجیبی روی سرعت داشت. ما یه کد تر و تمیز داشتیم که کار میکرد. ولی این همکارم گفتش که: "نه، این تابعی که نوشتی کنده! بذار پرفورمنسش رو ببرم بالا."
شروع کرد به تغییرات عجیب به بهانهی اینکه فراخوانی توابع سربار (Overhead) داره، توابعِ کوچیک و خوانا رو حذف کرد و همه رو ریخت توی یه تابعِ. شرطهای if/else شفاف رو تبدیل کرد به یک خط محاسبهی ریاضی پیچیده تا CPU کمتری مصرف بشه.
ما اولش هیجانزده بودیم و میگفتیم که دمت گرم! الان چون کد کوتاهتر شده و تابع کمتر صدا زده میشه، حتما درخواستا خیلی سریع پردازش میشن.
نتیجه؟ کاربر نهایی اصلا متوجه اون سرعت ناچیز نشد (چون گلوگاه اصلا اونجا نبود). اما چند وقت بعد، وقتی بیزینس یه تغییر کوچیک خواست، ما فلج شدیم.
کدی که قبلا توی ۱۰ دقیقه ادیت میشد، حالا شده بود یه میدون مین. هیچکس نمیفهمید اون خط طولانی ریاضی دقیقا داره چیکار میکنه. ما خوانایی رو قربانی یه سرعت توهمی کرده بودیم.
اینجا بود که یاد جملهی معروف دونالد کنوث افتادم: "بهینهسازی زودهنگام (Premature Optimization)، ریشهی تمام دردسرهاست."
ما داشتیم دقیقا همین مصیبت رو سر خودمون میاوردیم و قانونِ طلایی Uncle Bob رو فراموش کرده بودیم:
قانون ۱۰ به ۱: ما ۱۰ برابر زمانی که کد مینویسیم، صرف خوندن کد میکنیم. اون کدی که دوستمون زد، شاید نوشتنش ۱ ساعت طول کشید، ولی خوندن و دیباگ کردنش ۱۰ ساعت از وقت کل تیم رو گرفت. هر خط کدی که به بهانهی Performance ناخوانا میشه، داره هزینهی نگهداری رو تصاعدی میبره بالا.
ما یاد گرفتیم بهینهسازی واقعی این نیست که کد رو فشرده کنی. بهینهسازی واقعی اینه که کدی بنویسی که نفر بعدی (یا خود ۶ ماه بعدت) بتونه راحت بخونه و توسعهش بده.
یه زمانی فکر میکردم هرچی async/await تو کدم بیشتر باشه، سیستم مثل مووووشک کار میکنه
یعنی کد رو باز میکردی، همهجا async، همهجا await…
با خودم میگفتم: «این دیگه تهشه، این سیستم موشکه.»
بعد سیستم رفت زیر بار…
موشک بوووود ولی همون اول ترکید.
همهچی ظاهراً درست بود.
دیدم CPU داره کارشو میکنه، رم هم داشت نفس میکشید، لاگها هم چیز خاصی نمیگفتن.
ولی response time داشت زیاد میشد، کاربرها غر میزدن، منم داشتم به مانیتور زل میزدم که «مگه async نبود؟»
اونجا بود که فهمیدم async قرار نیست بیاد پیشونیتو ماچ کنه و بگه تو نگران نباش همه چی با من.
درواقع async فقط میگه: «داداش من منتظرم، اون Thread بیصاحبو ول کن بره یه کار دیگه بکنه.»
ولی مشکل از جایی شروع میشه که وسط این asyncهای خوشگیلی موووشگیل،
یه کار CPU-bound بندازی.
یا بدتر…
یه .Result یا .Wait بزنی و بگی: «ستون وایسا کارت دارم.»
اینجاست که Thread Pool میاد بیرون میگه یه لیوان آب به من بده ناموسن
میبینی Threadها یکییکی مفقود الاثر میشن
تمام Requestهای جدید میرسن، میبینن جا نیست، چهار زانو میشینن دم در سرور.
سیستم از بیرون مثل بنز جی کلاس، از تو شاهین اتومات.
بدترین قسمتش چیه؟
هیچ اروری نمیبینی.
نه exception، نه crash، نه هیچی.
فقط کاربره که هر ۵ ثانیه یه بار رفرش میزنه و مرده و زندتو مورد دعای خیر قرار میده.
اونجا بود که فهمیدم async بودن به معنی سریع بودن نیست.
اگر منتظر دیتابیس، شبکه یا دیسکی، async عالیه.
اگر داری CPU رو به خاک میدی، async فقط یه اسم قشنگه روش.
و اگر این دوتا رو قاطی کنی، Thread Pool که دیگه واویلا.
از اون روز به بعد، قبل از اینکه async بنویسم، از خودم میپرسم:
الان واقعاً منتظرم؟
یا فقط دارم خودمو گول میزنم؟
خیلی وقتا مشکل performance این نیست که کدت بده.
مشکل اینه که فکر میکنی async یعنی «همه چی حل شد».
نه.
درواقع async ابزار حرفهایه،
ولی اگه نفهمی چی دستته، خیلی سریع تبدیل میشه به سلاح کشتار جمعی.
یعنی کد رو باز میکردی، همهجا async، همهجا await…
با خودم میگفتم: «این دیگه تهشه، این سیستم موشکه.»
بعد سیستم رفت زیر بار…
موشک بوووود ولی همون اول ترکید.
همهچی ظاهراً درست بود.
دیدم CPU داره کارشو میکنه، رم هم داشت نفس میکشید، لاگها هم چیز خاصی نمیگفتن.
ولی response time داشت زیاد میشد، کاربرها غر میزدن، منم داشتم به مانیتور زل میزدم که «مگه async نبود؟»
اونجا بود که فهمیدم async قرار نیست بیاد پیشونیتو ماچ کنه و بگه تو نگران نباش همه چی با من.
درواقع async فقط میگه: «داداش من منتظرم، اون Thread بیصاحبو ول کن بره یه کار دیگه بکنه.»
ولی مشکل از جایی شروع میشه که وسط این asyncهای خوشگیلی موووشگیل،
یه کار CPU-bound بندازی.
یا بدتر…
یه .Result یا .Wait بزنی و بگی: «ستون وایسا کارت دارم.»
اینجاست که Thread Pool میاد بیرون میگه یه لیوان آب به من بده ناموسن
میبینی Threadها یکییکی مفقود الاثر میشن
تمام Requestهای جدید میرسن، میبینن جا نیست، چهار زانو میشینن دم در سرور.
سیستم از بیرون مثل بنز جی کلاس، از تو شاهین اتومات.
بدترین قسمتش چیه؟
هیچ اروری نمیبینی.
نه exception، نه crash، نه هیچی.
فقط کاربره که هر ۵ ثانیه یه بار رفرش میزنه و مرده و زندتو مورد دعای خیر قرار میده.
اونجا بود که فهمیدم async بودن به معنی سریع بودن نیست.
اگر منتظر دیتابیس، شبکه یا دیسکی، async عالیه.
اگر داری CPU رو به خاک میدی، async فقط یه اسم قشنگه روش.
و اگر این دوتا رو قاطی کنی، Thread Pool که دیگه واویلا.
از اون روز به بعد، قبل از اینکه async بنویسم، از خودم میپرسم:
الان واقعاً منتظرم؟
یا فقط دارم خودمو گول میزنم؟
خیلی وقتا مشکل performance این نیست که کدت بده.
مشکل اینه که فکر میکنی async یعنی «همه چی حل شد».
نه.
درواقع async ابزار حرفهایه،
ولی اگه نفهمی چی دستته، خیلی سریع تبدیل میشه به سلاح کشتار جمعی.
🧩 7️⃣ الگوی Sidecar (Sidecar Pattern) (بخش هفتم)
ءSidecar Pattern یک کامپوننت کمکی را در کنار container اصلی اپلیکیشن شما deploy میکند که وظیفه ارائه قابلیتهای پشتیبان مانند logging، monitoring، configuration یا networking را بر عهده دارد. 🛠
ءSidecar در همان محیط اجرایی اپلیکیشن اصلی اجرا میشود و lifecycle مشترکی با آن دارد. این موضوع باعث میشود بتوان بدون تغییر کد اپلیکیشن، قابلیتهای جدیدی به آن اضافه کرد. 🔌
⚙️ نحوه کار (How it works):
یک sidecar container در کنار container اصلی اپلیکیشن و در همان container یا host اجرا میشود 🧱
هر دو container از یک network namespace مشترک استفاده میکنند و میتوانند از طریق localhost با هم ارتباط برقرار کنند 🌐
ءSidecar میتواند ترافیک ورودی و خروجی را intercept کند و مسئول cross-cutting concernهایی مانند logging، جمعآوری metrics یا قابلیتهای service mesh باشد 📊
ارتباط بین اپلیکیشن و sidecar از طریق local network calls انجام میشود 🔄
قابلیتهای sidecar میتوانند مستقل از اپلیکیشن بهروزرسانی شوند، بدون نیاز به تغییر یا redeploy کد اصلی ♻️
امکان اتصال چند sidecar به یک اپلیکیشن واحد برای اهداف مختلف وجود دارد 🧩🧩
✅ مزایا (Benefits):
جداسازی دغدغههای زیرساختی از کد اپلیکیشن و تمرکز کد بر business logic 🧠
پشتیبانی از polyglot architecture، چون sidecar مستقل از زبان یا framework اپلیکیشن عمل میکند 🌍
سادهسازی توسعه اپلیکیشن با استفاده از کامپوننتهای زیرساختی قابل استفاده مجدد ♻️
امکان بهروزرسانی مستقل قابلیتهای زیرساختی بدون redeploy اپلیکیشن 🚀
کاهش code duplication بین سرویسها با متمرکز کردن قابلیتهای مشترک در sidecar 📦
⚠️ معایب (Drawbacks):
افزایش مصرف منابع، چون هر instance اپلیکیشن یک یا چند sidecar اضافی اجرا میکند 💾
افزایش پیچیدگی در پیکربندی deployment و orchestration 🧩
احتمال افزایش latency به دلیل hopهای شبکهای اضافی بین اپلیکیشن و sidecar ⏱️
🎯 موارد استفاده (Use cases):
• پیادهسازی Service Mesh برای مدیریت ترافیک، امنیت و observability 🔐📈
• ءCentralized logging که در آن sidecar لاگهای اپلیکیشن را جمعآوری و به سیستمهای logging ارسال میکند 📝
• ءConfiguration management که sidecar پیکربندیها را بهصورت داینامیک دریافت و بهروزرسانی میکند ⚙️
• یکپارچهسازی Event-driven که در آن sidecar مدیریت messaging را از طریق queueهای قابل تعویض (مثل Kafka، RabbitMQ، Azure Service Bus) انجام میدهد و امکان تغییر آنها بدون دست زدن به کد اپلیکیشن را فراهم میکند (برای مثال با استفاده از Dapr) 🔄
چالش برنامهنویسی🔥
یک شیء در یک static field نگهداری میشود و در هیچ جای دیگری استفاده نمیشود.
رفتار Garbage Collector نسبت به این شیء چیست؟ An object is referenced only by a static field and nowhere else. What will the Garbage Collector do?
یک شیء در یک static field نگهداری میشود و در هیچ جای دیگری استفاده نمیشود.
رفتار Garbage Collector نسبت به این شیء چیست؟ An object is referenced only by a static field and nowhere else. What will the Garbage Collector do?
Anonymous Quiz
12%
Collect it immediately
14%
Collect it in Gen 0
67%
Never collect it
8%
Throw a runtime exception