Refactoring 029 – NULL را با مجموعه جایگزین کنید

ویژگی های اختیاری را به مجموعه های خالی برای کد تمیزتر ، ایمن تر و چند شکل تبدیل کنید و اشتباه میلیارد دلاری را از بین ببرید
TL ؛ DR: برای از بین بردن چک های تهی و پلی مورفیسم اهرم ، ویژگی های اختیاری قابل تهی را با مجموعه های خالی جایگزین کنید.
- ویژگی های اختیاری قابل تهی را شناسایی کنید که می توانند مجموعه باشند
- اشیاء قابل برگشت را با مجموعه های خالی جایگزین کنید
- تمام چک های تهی مربوط به این ویژگی های اختیاری را حذف کنید
- روش های کار را برای کار با مجموعه ها به جای اشیاء منفرد به روز کنید
قبل
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
private Coupon coupon = null;
public void addItem(Item item) {
this.items.add(item);
}
public void redeemCoupon(Coupon coupon) {
this.coupon = coupon;
}
public double total() {
double total = 0;
for (Item item : this.items) {
total += item.getPrice();
}
// This a polluted IF and null check
if (this.coupon != null) {
total -= this.coupon.getDiscount();
}
return total;
}
public boolean hasUnsavedChanges() {
// Explicit null check
return !this.items.isEmpty() || this.coupon != null;
}
public boolean hasCoupon() {
return this.coupon != null;
}
}
public class ShoppingCart {
private final List<Item> items = new ArrayList<>();
// This version uses Optionals
// Not all programming languages support this feature
private Optional<Coupon> coupon = Optional.empty();
public void addItem(Item item) {
items.add(item);
}
public void redeemCoupon(Coupon coupon) {
// You need to understand how optionals work
this.coupon = Optional.ofNullable(coupon);
}
public boolean hasUnsavedChanges() {
return !items.isEmpty() || !coupon.isPresent();
}
public boolean hasCoupon() {
return coupon.isPresent();
}
}
بعد از
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
// 1. Identify nullable optional attributes
// that could be collections
// 2. Replace single nullable objects with empty collections
private List<Coupon> coupons = new ArrayList<>();
public void addItem(Item item) {
this.items.add(item);
}
// Step 4: Work with collection
// instead of single nullable object
public void redeemCoupon(Coupon coupon) {
this.coupons.add(coupon);
}
// Step 4: Simplified logic without null checks
public double total() {
double total = 0;
for (Item item : this.items) {
total += item.getPrice();
}
// 3. Remove all null checks
// related to these optional attributes
for (Coupon coupon : this.coupons) {
total -= coupon.getDiscount();
}
return total;
}
// Consistent behavior with empty collections
public boolean hasUnsavedChanges() {
// 4. Update methods to work with collections
// instead of single objects
return !this.items.isEmpty() || !this.coupons.isEmpty();
}
// 3. Remove all null checks
// related to these optional attributes
// Collection-based check instead of null check
public boolean hasCoupon() {
return !this.coupons.isEmpty();
}
}
هنگامی که تمام نقاط دسترسی به ویژگی های مجموعه را کنترل می کنید ، این اصلاح مجدد به طور کلی بی خطر است.
شما باید اطمینان حاصل کنید که هیچ کد خارجی انتظار مقادیر تهی را ندارد و با API های داخل آن مقابله می کند.
اصلاح مجدد در حالی که منطق داخلی را ساده می کند ، همان رفتار بیرونی را حفظ می کند.
شما باید تأیید کنید که همه سازندگان و روشهای کارخانه به طور صحیح مجموعه ها را به درستی انجام می دهند.
کد اصلاح شده استثنائات اشاره گر تهی را از بین می برد و پیچیدگی مشروط را کاهش می دهد.
مجموعه های خالی و مجموعه های غیر خالی به صورت چند شکل رفتار می کنند و به شما امکان می دهد با یکنواخت با آنها رفتار کنید.
این کد از آنجا که مجموعه ها همیشه (حداقل خالی) وجود دارند و به همان عملیات پاسخ می دهند ، قابل پیش بینی تر می شود.
پیاده سازی های روش کوتاه تر و متمرکز بر منطق کسب و کار به جای رسیدگی به تهی هستند.
این رویکرد با اصل ساختن حالت های غیرقانونی در مدل دامنه شما مطابقت دارد و منجر به کد قوی تر و حفظ می شود.
مجموعه های خالی و مجموعه های غیر خالی هستند چند شکلبشر
در دنیای واقعی ، ظروف حتی در صورت خالی بودن وجود دارند.
شما با ارائه مجموعه های اختیاری به عنوان مجموعه های خالی و نه تهی ، شما یک مدل دقیق تر از واقعیت ایجاد می کنید.
تهی در دنیای واقعی وجود ندارد و همیشه زندگی را می شکند.
این امر مکاتبات یک به یک بین مفاهیم دنیای واقعی و مدل محاسباتی شما را حفظ می کند و یک نقشه برداری خوب ایجاد می کند.
هنگامی که یک مجموعه را به جای تهی باز می گردانید ، اتصال را نیز کاهش می دهید.
این اصلاح مجدد ممکن است مناسب نباشد وقتی NULL معنی معنایی متفاوت از “خالی” داشته باشد. برخی از API های میراث ممکن است انتظار مقادیر تهی داشته باشند و به لایه های سازگاری نیاز دارند.
برای جلوگیری از حالتهای تهی و خالی ، باید تمام مسیرهای کد را به طور مداوم به طور مداوم اطمینان دهید.
[X] متوسطپیشنهاد سریع: 1. 1. ویژگی های اختیاری قابل تهی را که می تواند مجموعه باشد ، شناسایی کنید.
تصویر توسط Eak K. در Pixabay
این مقاله بخشی از سری Refactoring است.