抽象如何帮助 DRY?

How does abstractions help in DRY?

我们搜索"Don't repeat yourself" on Wikipedia的时候,第一句话是:

In software engineering, don't repeat yourself (DRY) is a principle of software development aimed at reducing repetition of software patterns, replacing them with abstractions...

我知道软件工程中的抽象意味着隐藏API的行为如何实现的实现复杂性,但这句话中的"abstractions"似乎不​​是我以前所知道的。有人可以向我解释抽象在这里意味着什么吗?如果能举个例子就更好了

I know that abstractions in software engineering mean hiding implementation complexity of how the behaviors of an API are realized

是的,这意味着 (absstraction@wikipedia) 也可以利用完全相同的概念来减少重复!或者换句话说,它可以用来练习DRY。

让我试着用一个例子来解释。首先我将展示非 DRY 代码(没有抽象),然后通过使用抽象我会尝试减少重复。

假设您想根据申请人填写的申请表详细信息构建一个电子邮件视图模型,并且有一个电子邮件视图 class 使用此 emailViewModel 来显示来自的所有 non-null 详细信息申请表。你可以像下面的例子那样写(第一次尝试)

public class ApplicationForm
{
        public AddressDetail AddressDetail { get; set; }
        public CustomerDetail CustomerDetail { get; set; }
        public ProductDetail ProductDetail { get; set; }
}

public class EmailViewModel
{
    public EmailViewModel(ApplicationForm applicationForm)
    {
        Address = GetAddressDetail(applicationForm.AddressDetail);
        Customer = GetCustomerDetail(applicationForm.CustomerDetail);
        Product = GetProductDetail(applicationForm.ProductDetail);
    }

    public string Address { get; set; }
    public string Customer { get; set; }
    public string Product { get; set; }
}

//view code assume razor view
@if(Model.Address!=null)
{
    // method for showing address
}
@if(Model.Customer!=null)
{
    // method for showing customer
}
//and other properties

上面的代码我一直很简单;只有三个属性并且没有显示转换方法的声明。如果有 50 个属性怎么办!在第一种方法中,您将在三个地方进行繁琐的更改。现在我将向您展示如何创建接口(一种抽象方式)实现 DRY 的第二个示例代码。

    interface IFormDetail
{
    IFormDetailView GetDetail();
}
interface IFormDetailView
{
    string ShowView();
}

public class ApplicationForm
{
        public List<IFormDetail> FormDetails {get;set;}
}

public class EmailViewModel
{
    public EmailViewModel(ApplicationForm applicationForm)
    {
        if(applicationForm.FormDetails!=null)
        {
            FormDetails = new List<IFormDetailView>();
            foreach(var detail in applicationForm.FormDetails)
            {
                FormDetails.Add(detail.GetDetail());
            }
        }
    }

    public List<IFormDetailView> FormDetails { get; set; }

}

//view code assume razor view
@f(Model.FormDetails!=null)
{
    foreach(var detail in Model.FormDetails){
        detail.ShowView();
    }
}

在第二个代码示例中,当您有一个新的 属性 时,您只需在创建一个新的申请表 属性 时进行一次更改。

因此,虽然我们隐藏了细节呈现方式等的复杂性,但我们也在利用它来减少重复。