BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

AutoMapper及静态类之争论

| 作者 Jonathan Allen 关注 595 他的粉丝 ,译者 邵思华 关注 3 他的粉丝 发布于 2016年3月17日. 估计阅读时间: 5 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

在进行API设计时,静态类的使用有时会为设计者带来一些烦恼。应该将某个函数暴露为静态函数还是实例方法,这一点常常会造成人们的争论。

静态函数的主要优点在于其简便性。调用者可以在代码中的任意位置使用静态函数,而无需为实例的创建、管理以及依赖注入等问题而烦恼。并且由于没有创建新的实例,因而也不存在垃圾回收的问题,从而使性能也得以提高。

如果没有维护状态的需求,以上的论点确实是成立的。如若不然,则设计者必须保证静态函数的线程安全,而这往往牵涉到开销较大的加锁与同步等技术。而且即便独立的调用是线程安全的,但调用者也往往需要将一系列调用过程封装为一个原子性的事务。AutoMapper目前也遇到了这方面的麻烦。

AutoMapper最初是围绕着静态函数而设计的,但随着时间的推移,它的可配置性也在逐步提高。每当出现新的配置选项,就需要管理更多的状态,而潜在的线程问题也在逐渐加剧。因此,今年1月,Jimmy Bogard将AutoMapper 4.2版本中的静态函数一律标记为过时(obselete)方法,并打算最终完全移除这些函数。

在我开发AutoMapper 4.2版本的过程中,脑海中突然有灵光一闪。过去这十年间,我多次在讲座与播客中谈到了如何长期维护开源代码的问题。对于AutoMapper,我最大的遗憾就是在一开始设计了一套静态的API。AutoMapper最初的测试与原型中都是通过“Mapper.CreateMap”与“Mapper.Map”等方法调用的。当时我向我的老板Jeffrey Palermo展示了我的代码,并询问他对代码的看法。他当时说道:“这看上去很棒Jimmy,不过API似乎不应该设计成静态的”,而我则回应说:“开玩笑吧,这不可能!”。

之后,我开始意识到静态函数的问题,至今都为此感到懊悔。在即将发布的新版本中,我利用这次机会设计了一个不再使用静态方法的原型,它表现得很出色,我也准备好将整个静态API标记为过时方法。

这一改动也确实造成了某些问题。AutoMapper的特性之一是支持fluent API,它能够配合LINQ表达式链工作。这一特性需要用到扩展方法,而扩展方法往往都是通过静态函数的方式定义的。

我选择的临时方案是仍然提供对LINQ的支持,但改变了它的方式,使其不再利用全局的状态。使用者需要将AutoMapper配置信息传递给LINQ表达式,这种方式稍嫌冗长,但从某些方面来看,它提供了更大的灵活性。

以下示例是从“静态API迁移指南”中所摘录的一段代码:

public class ProductsController : Controller {
    public ProductsController(MapperConfiguration config) {
        this.config = config;
    }
    private MapperConfiguration config;

    public ActionResult Index(int id) {
        var dto = dbContext.Products
                               .Where(p => p.Id == id)
                               .ProjectTo(config)
                               .SingleOrDefault();

        return View(dto);
    }    
}

可就在一个月后,Jimmy Bogard又决定让这些静态函数重新回归。他写道:

静态API的一大困扰在于使用者可以随时对配置进行改动,而我却无法强制要求使用者对配置的步骤进行清理。但在进一步思考之后,我发现静态API的使用并没有任何问题,它只是要求使用者在进行映射之前必须完成初始化工作。因此我决定在后续版本中仍然允许这种使用方式。实例API如今已经彻底完善了,而静态API实际上只是一种轻量级的封装,使用者可以简单地调用静态Initialize方法,而无需直接调用实例的构造函数。

新发布的版本移除了某些过时属性,并且恢复了在LINQ映射时使用静态配置的特性。

关于应当使用有状态的静态函数,还是只允许使用实例方法,InfoQ希望聆听读者的意见。

查看英文原文AutoMapper and the Static Class Debate

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT