5️⃣: ترجیح دادن پرتاب استثناهای سفارشی (Custom Exceptions) 💥
حالا بیایید در مورد پرتاب کردن استثناها صحبت کنیم. من دوست دارم از استثناها فقط برای شرایط "استثنایی" استفاده کنم، و از آنها برای کنترل جریان در کدم استفاده نمیکنم.
با این حال، اگر شما میخواهید از استثناها برای کنترل جریان استفاده کنید، بهتر است از استثناهای سفارشی استفاده کنید.
شما میتوانید اطلاعات زمینهای ارزشمندی را معرفی کرده و دلیل پرتاب استثنا را بهتر توصیف کنید.
و اگر میخواهید این استثناها را به صورت سراسری مدیریت کنید، میتوانید یک کلاس پایه ایجاد کنید تا بتوانید استثناهای خاصی را catch کنید.
public void Process(Order? order)
{
if (!IsProcessable(order))
{
return;
}
if (order.Items.Count > 15)
{
throw new TooManyLineItemsException(order.Id);
}
if (order.Status != "ReadyToProcess")
{
throw new NotReadyForProcessingException(order.Id);
}
order.IsProcessed = true;
}
static bool IsProcessable(Order? order)
{
return order is not null &&
order.IsVerified &&
order.Items.Any();
}
6️⃣: رفع اعداد جادویی (Magic Numbers) با ثابتها (Constants) 🔢
یک code smell رایج که من میبینم، استفاده از اعداد جادویی است.
آنها معمولاً به راحتی قابل تشخیص هستند زیرا برای بررسی اعمال شدن یک شرط عددی استفاده میشوند.
مشکل اعداد جادویی این است که هیچ معنایی ندارند.
استدلال در مورد کد دشوارتر و مستعد خطا میشود.
رفع اعداد جادویی باید سرراست باشد و یک راهحل، معرفی یک ثابت (constant) است.
const int MaxNumberOfLineItems = 15;
public void Process(Order? order)
{
if (!IsProcessable(order))
{
return;
}
if (order.Items.Count > MaxNumberOfLineItems)
{
throw new TooManyLineItemsException(order.Id);
}
if (order.Status != "ReadyToProcess")
{
throw new NotReadyForProcessingException(order.Id);
}
order.IsProcessed = true;
}
static bool IsProcessable(Order? order)
{
return order is not null &&
order.IsVerified &&
order.Items.Any();
}
7️⃣: رفع رشتههای جادویی (Magic Strings) با Enumها 📜
مشابه اعداد جادویی، ما code smell رشتههای جادویی را داریم.
یک مورد استفاده معمول برای رشتههای جادویی، نمایش نوعی از وضعیت (state) است.
شما متوجه خواهید شد که ما مقدار Order.Status را با یک رشته جادویی مقایسه میکنیم تا بررسی کنیم آیا سفارش آماده پردازش است یا نه.
چند مشکل با رشتههای جادویی:
🔹 امکان اشتباه کردن (اشتباه تایپی) آسان است.
🔹 عدم وجود تایپ قوی (strong typing).
🔹 در برابر بازآرایی (refactoring) مقاوم نیستند.
بیایید یک enum به نام OrderStatus برای نمایش وضعیتهای ممکن ایجاد کنیم: 🏷
enum OrderStatus
{
Pending = 0,
ReadyToProcess = 1,
Processed = 2
}
و حالا باید از OrderStatus مناسب در چک استفاده کنیم:
const int MaxNumberOfLineItems = 15;
public void Process(Order? order)
{
if (!IsProcessable(order))
{
return;
}
if (order.Items.Count > MaxNumberOfLineItems)
{
throw new TooManyLineItemsException(order.Id);
}
if (order.Status != OrderStatus.ReadyToProcess)
{
throw new NotReadyForProcessingException(order.Id);
}
order.IsProcessed = true;
order.Status = OrderStatus.Processed;
}
static bool IsProcessable(Order? order)
{
return order is not null &&
order.IsVerified &&
order.Items.Any();
}