遍历枚举是一项单一职责吗?
Is looping over an enumeration a single responsibility?
遍历集合是一项单一职责吗,我是否必须自己实现它class?
这是一般问题的具体示例:我有一个 class,它有一个方法,它遍历枚举并处理每个项目:
internal class StorageRestorer
{
#region log4net
private static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(StorageRestorer<TEntity>));
#endregion log4net
private ServiceController _serviceController;
/// <summary>
/// Creates a new instance of the StorageRestorer class.
/// </summary>
/// <param name="serviceController">Service controller, where to resore the storage.</param>
public StorageRestorer(ServiceController serviceController)
{
_serviceController = serviceController;
}
/// <summary>
/// Restores the given storage items into the service controller.
/// </summary>
/// <param name="items">Storage items to be restored.</param>
public void Restore(IEnumerable<StorageItem> items)
{
foreach (var item in items)
Restore(item);
}
private void Restore(StorageItem item)
{
if (item.Status == EntityStates.Added)
{
_serviceController.AddObject(item.Entity);
return;
}
_serviceController.AttachObject(item.Entity);
switch (item.Status)
{
case EntityStates.Deleted:
_serviceController.DeleteObject(item.Entity);
break;
case EntityStates.Modified:
_serviceController.UpdateObject(item.Entity);
break;
}
}
}
我现在的问题是:这个class是否因为循环而违反了单一职责原则?
我知道你不希望你的代码被同行评审,所以我会坚持问题。我不认为您的 class 违反了 SRP。您的 class 是 "storage restorer",而这正是 class 所做的。事实上,实际操作(添加、附加、删除和更新)是在另一个 class 中实现的,它符合执行原子操作的责任。该代码易于阅读且易于理解,所以没有问题。也许有人会争辩说代码可以更改为:
public void Restore(IEnumerable<StorageItem> items)
{
foreach (var item in items)
item.Restore(_serviceController);
}
并将个别物品恢复的责任交给存储物品本身,但我认为 class 可以按原样处理。
关于一般问题,循环只是实现你想要完成的事情的一种手段,而不是责任本身。有时为了实现职责要求,你需要写好几个循环,if条件,嵌套开关,这并不意味着你需要为你写的每个结构都写一个class。也许编写有助于阅读代码的私有函数是个好主意,只要私有函数可以帮助您实现 class 真正需要做的事情,而不是别的(完成它的责任)。
您的 class 的唯一责任是通过 Status
派遣实体。所以,没有违规。更重要的是,您的 class 看起来像是 Repository
模式的截断版本。但我想这超出了你的问题。
我唯一要注意的是
void Restore(StorageItem item) // [1]
方法public
。您将扩展 StorageRestorer
的界面而不会出现任何违规行为。方法
void Restore(IEnumerable<StorageItem> items) // [2]
不过是个小帮手。在您的情况下,方法 [2]
可以很容易地丢弃。没有任何理由使方法 [1]
成为 private
。如果您现在不使用它,并不意味着您以后不会使用它。如果您可以对集合内的元素执行一些操作,而不是集合本身,那么您应该能够对单个元素执行这些操作。
否则以后可能会出现这样的情况:
resporer.Restore(new [] { item }); // OMG, who wrote that API? o.O
此外,不是在您的特定情况下,此类助手可以应用一些内部优化。例如,这就是 List<T>.AddRange
实际所做的。
所以,回到你的问题。没有任何实际违规,但也不是最佳设计选择。拥有像 [2]
这样的方法 可能 是合理的。主要取决于您的整个代码库。如果您从不对单个元素进行操作,只对枚举进行操作,那么这种权衡将符合您的需要。
遍历集合是一项单一职责吗,我是否必须自己实现它class?
这是一般问题的具体示例:我有一个 class,它有一个方法,它遍历枚举并处理每个项目:
internal class StorageRestorer
{
#region log4net
private static log4net.ILog _log = log4net.LogManager.GetLogger(typeof(StorageRestorer<TEntity>));
#endregion log4net
private ServiceController _serviceController;
/// <summary>
/// Creates a new instance of the StorageRestorer class.
/// </summary>
/// <param name="serviceController">Service controller, where to resore the storage.</param>
public StorageRestorer(ServiceController serviceController)
{
_serviceController = serviceController;
}
/// <summary>
/// Restores the given storage items into the service controller.
/// </summary>
/// <param name="items">Storage items to be restored.</param>
public void Restore(IEnumerable<StorageItem> items)
{
foreach (var item in items)
Restore(item);
}
private void Restore(StorageItem item)
{
if (item.Status == EntityStates.Added)
{
_serviceController.AddObject(item.Entity);
return;
}
_serviceController.AttachObject(item.Entity);
switch (item.Status)
{
case EntityStates.Deleted:
_serviceController.DeleteObject(item.Entity);
break;
case EntityStates.Modified:
_serviceController.UpdateObject(item.Entity);
break;
}
}
}
我现在的问题是:这个class是否因为循环而违反了单一职责原则?
我知道你不希望你的代码被同行评审,所以我会坚持问题。我不认为您的 class 违反了 SRP。您的 class 是 "storage restorer",而这正是 class 所做的。事实上,实际操作(添加、附加、删除和更新)是在另一个 class 中实现的,它符合执行原子操作的责任。该代码易于阅读且易于理解,所以没有问题。也许有人会争辩说代码可以更改为:
public void Restore(IEnumerable<StorageItem> items)
{
foreach (var item in items)
item.Restore(_serviceController);
}
并将个别物品恢复的责任交给存储物品本身,但我认为 class 可以按原样处理。
关于一般问题,循环只是实现你想要完成的事情的一种手段,而不是责任本身。有时为了实现职责要求,你需要写好几个循环,if条件,嵌套开关,这并不意味着你需要为你写的每个结构都写一个class。也许编写有助于阅读代码的私有函数是个好主意,只要私有函数可以帮助您实现 class 真正需要做的事情,而不是别的(完成它的责任)。
您的 class 的唯一责任是通过 Status
派遣实体。所以,没有违规。更重要的是,您的 class 看起来像是 Repository
模式的截断版本。但我想这超出了你的问题。
我唯一要注意的是
void Restore(StorageItem item) // [1]
方法public
。您将扩展 StorageRestorer
的界面而不会出现任何违规行为。方法
void Restore(IEnumerable<StorageItem> items) // [2]
不过是个小帮手。在您的情况下,方法 [2]
可以很容易地丢弃。没有任何理由使方法 [1]
成为 private
。如果您现在不使用它,并不意味着您以后不会使用它。如果您可以对集合内的元素执行一些操作,而不是集合本身,那么您应该能够对单个元素执行这些操作。
否则以后可能会出现这样的情况:
resporer.Restore(new [] { item }); // OMG, who wrote that API? o.O
此外,不是在您的特定情况下,此类助手可以应用一些内部优化。例如,这就是 List<T>.AddRange
实际所做的。
所以,回到你的问题。没有任何实际违规,但也不是最佳设计选择。拥有像 [2]
这样的方法 可能 是合理的。主要取决于您的整个代码库。如果您从不对单个元素进行操作,只对枚举进行操作,那么这种权衡将符合您的需要。