برنامه نویسی

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

ویژگی های اختیاری را به مجموعه های خالی برای کد تمیزتر ، ایمن تر و چند شکل تبدیل کنید و اشتباه میلیارد دلاری را از بین ببرید

TL ؛ DR: برای از بین بردن چک های تهی و پلی مورفیسم اهرم ، ویژگی های اختیاری قابل تهی را با مجموعه های خالی جایگزین کنید.

  1. ویژگی های اختیاری قابل تهی را شناسایی کنید که می توانند مجموعه باشند
  2. اشیاء قابل برگشت را با مجموعه های خالی جایگزین کنید
  3. تمام چک های تهی مربوط به این ویژگی های اختیاری را حذف کنید
  4. روش های کار را برای کار با مجموعه ها به جای اشیاء منفرد به روز کنید

فهرست مطالب

قبل

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();
  }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

[X] نیمه اتوماتیک

هنگامی که تمام نقاط دسترسی به ویژگی های مجموعه را کنترل می کنید ، این اصلاح مجدد به طور کلی بی خطر است.

شما باید اطمینان حاصل کنید که هیچ کد خارجی انتظار مقادیر تهی را ندارد و با API های داخل آن مقابله می کند.

اصلاح مجدد در حالی که منطق داخلی را ساده می کند ، همان رفتار بیرونی را حفظ می کند.

شما باید تأیید کنید که همه سازندگان و روشهای کارخانه به طور صحیح مجموعه ها را به درستی انجام می دهند.

کد اصلاح شده استثنائات اشاره گر تهی را از بین می برد و پیچیدگی مشروط را کاهش می دهد.

مجموعه های خالی و مجموعه های غیر خالی به صورت چند شکل رفتار می کنند و به شما امکان می دهد با یکنواخت با آنها رفتار کنید.

این کد از آنجا که مجموعه ها همیشه (حداقل خالی) وجود دارند و به همان عملیات پاسخ می دهند ، قابل پیش بینی تر می شود.

پیاده سازی های روش کوتاه تر و متمرکز بر منطق کسب و کار به جای رسیدگی به تهی هستند.

این رویکرد با اصل ساختن حالت های غیرقانونی در مدل دامنه شما مطابقت دارد و منجر به کد قوی تر و حفظ می شود.

مجموعه های خالی و مجموعه های غیر خالی هستند چند شکلبشر

در دنیای واقعی ، ظروف حتی در صورت خالی بودن وجود دارند.

شما با ارائه مجموعه های اختیاری به عنوان مجموعه های خالی و نه تهی ، شما یک مدل دقیق تر از واقعیت ایجاد می کنید.

تهی در دنیای واقعی وجود ندارد و همیشه زندگی را می شکند.

این امر مکاتبات یک به یک بین مفاهیم دنیای واقعی و مدل محاسباتی شما را حفظ می کند و یک نقشه برداری خوب ایجاد می کند.

هنگامی که یک مجموعه را به جای تهی باز می گردانید ، اتصال را نیز کاهش می دهید.

این اصلاح مجدد ممکن است مناسب نباشد وقتی NULL معنی معنایی متفاوت از “خالی” داشته باشد. برخی از API های میراث ممکن است انتظار مقادیر تهی داشته باشند و به لایه های سازگاری نیاز دارند.

برای جلوگیری از حالتهای تهی و خالی ، باید تمام مسیرهای کد را به طور مداوم به طور مداوم اطمینان دهید.

پیشنهاد سریع: 1. 1. ویژگی های اختیاری قابل تهی را که می تواند مجموعه باشد ، شناسایی کنید.

[X] متوسط

تصویر توسط Eak K. در Pixabay


این مقاله بخشی از سری Refactoring است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا