代码简化!!






3.05/5 (8投票s)
本文重点介绍如何利用 .NET 的现有功能来提高代码的可维护性,从而降低圈复杂度并减少代码行数。
引言
如今,任何软件实现都在与外部或内部系统(例如,SOA)通信,存在大量实体、大量代码,当然也有大量映射。 本文重点介绍如何利用 .NET 的现有功能来提高代码的可维护性,从而降低圈复杂度并减少代码行数。
背景
几天前,我正在实现一个新功能,发现在现有代码中,使用大量实体,并且只有一对一的映射却需要大量的代码。 我运行了代码度量(来自 VS 2010),发现代码不可维护。 如果这段代码对于我这样一个开发人员来说都很难阅读和理解,那么以后维护它的人呢?
这促使我搜索了一些小的调整来提高代码质量。
代码之美
在编写代码时,有很多简单的方法(我们通常会忘记或忽略)可以使我们的代码看起来美观且易于维护。
- 内联初始化
所以,不要这样:
PersonalInfo entity = new PersonalInfo();
AddressEntity nameAndAddress = new AddressEntity();
nameAndAddress.DayPhone = Convert.ToString(orderEntity.dely_phone_day);
nameAndAddress.EveningPhone = Convert.ToString(orderEntity.dely_phone_eve);
nameAndAddress.AddressLine1 = orderEntity.dely_address1;
nameAndAddress.AddressLine2 = orderEntity.dely_address2;
nameAndAddress.AddressLine3 = orderEntity.dely_address3;
nameAndAddress.AddressLine4 = orderEntity.dely_address4;
nameAndAddress.AddressLine5 = orderEntity.dely_address5;
nameAndAddress.ZipCode = orderEntity.Postcode;
nameAndAddress.FirstName = orderEntity.NickName;
nameAndAddress.Title = orderEntity.dely_address_no.ToString();
entity.Address = nameAndAddress;
我们可以这样写:
AddressEntity nameAndAddress = new AddressEntity()
{
DayPhone = Convert.ToString(orderEntity.dely_phone_day),
EveningPhone = Convert.ToString(orderEntity.dely_phone_eve),
AddressLine1 = orderEntity.dely_address1,
AddressLine2 = orderEntity.dely_address2,
AddressLine3 = orderEntity.dely_address3,
AddressLine4 = orderEntity.dely_address4,
AddressLine5 = orderEntity.dely_address5,
ZipCode = orderEntity.Postcode,
FirstName = orderEntity.NickName,
Title = orderEntity.dely_address_no.ToString()
};
通过这种方式,您可以实现:
- 更好的可读性
- 更好的可维护性
- 在计算代码度量时,这将被视为一行。 因此,这将减少代码行数(对于此示例,从 13 行代码减少到 1 行)
- 将防止重复赋值(对于具有大量属性的实体,这将非常有用)
- 更快地编码
2. 映射函数
当进行一对一映射时,我们首先做什么? 我们编写一个方法,类似于这样
public static MyEntity MapServiceEntityToMyEntity(ServiceEntity response)
这就是它的调用方式
ServiceEntity response = GetServiceResponse(params);
MyEntity entity = Mapper.MapToMyEntity(response);
mapper 类逐渐增长。
当有多个开发人员在同一段代码上工作,而你的一个同事在实现一个新功能时,无法正确找到这个函数并决定编写他自己的映射方法时,就会出现问题。 类似于这样
public static MyEntity MapToMyEntity(ServiceEntity response)
接下来发生了什么? 代码编译通过,映射也起作用。 但是这增加了代码行数,它有重复的代码,并且最重要的是,维护这段代码的人会祈祷你死
我们能做些什么呢? 始终记住一件事。 当你将类型 "A" 转换为类型 "B" 时,你的映射类/方法应该始终只有一个函数来完成此操作。 我们可以通过创建扩展方法来确保这一点。 我们也可以就命名约定达成一致。
我选择重载名为 "Map" 的所有函数。 因此,我的 "Mapper.cs" 包含所有名为 "Map" 的方法。 下面是一个例子。
public static MyEntity Map(this ServiceEntity response)
通过这种方式,您可以实现:
- 防止映射函数的重复
- 易于编码
ServiceEntity response = GetServiceResponse(params);
MyEntity entity = response.Map();
您可以让它更容易
MyEntity entity = GetServiceResponse(params).Map();
- 减少代码行数
当我们映射一个列表时,我看到很多人这样做:
List<AddressEntity> listOfAddresses = new List<AddressEntity>();
foreach (ServiceResponse serviceAddress in response)
{
AddressEntity address = new AddressEntity();
address.DayPhone = serviceAddress.DayPhone;
address.EveningPhone = serviceAddress.EveningPhone;
address.HouseNumber = serviceAddress.HouseNo;
address.Road = serviceAddress.Road;
address.City = serviceAddress.City;
address.Country = serviceAddress.Country;
address.ZIpCOde = serviceAddress.ZipCode;
listOfAddresses.Add(address);
}
我们可以通过使用 Linq 来直接改进这一点
List<AddressEntity> listOfAddresses =
new List<AddressEntity>(response.Select<ServiceResponse,AddressEntity>(serviceAddress =>
new AddressEntity()
{
DayPhone = serviceAddress.DayPhone,
EveningPhone = serviceAddress.EveningPhone,
HouseNumber = serviceAddress.HouseNo,
Road = serviceAddress.Road,
City = serviceAddress.City,
Country = serviceAddress.Country,
ZipCOde = serviceAddress.ZipCode
}));
如果内部映射需要一些繁重的操作(例如计算总数或检查属性),并且您不关心列表中元素的顺序,则可以进一步使用并行 Linq 或 PLinq(请记住 - 确保在并行循环下使用的操作/变量/方法都是线程安全的)
List<AddressEntity> listOfAddresses =
new List<AddressEntity>(response.AsParallel().Select<ServiceResponse,AddressEntity>(serviceAddress =>
new AddressEntity()
{
DayPhone = serviceAddress.DayPhone,
EveningPhone = serviceAddress.EveningPhone,
HouseNumber = serviceAddress.HouseNo,
Road = serviceAddress.Road,
City = serviceAddress.City,
Country = serviceAddress.Country,
ZipCOde = serviceAddress.ZipCode
}));
有关并行编程的更多信息 - http://msdn.microsoft.com/en-us/library/ff963553。
当你以这种方式重构你的代码时,确保性能完好无损。 虽然这超出了本文的范围,但我建议对循环进行一些性能调整,并为特定逻辑使用最佳选项(for、foreach、Linq、Plinq、Parallel for 和 foreach)。
一个好的链接是 - https://codeproject.org.cn/Articles/6759/FOREACH-Vs-FOR-C