我试图学习更好的软件设计,最近发现了存储库和服务层模式。根据我的理解,存储库基本上包含数据访问代码,服务层调用存储库来获取数据,然后对该数据执行一些逻辑和处理。
到目前为止,阅读这些内容通常并不是存储库所具有的一系列方法。但是,存储库通常有以下几种方法:
我试图了解存储库的命名约定。我该怎么称呼" List / Get / Read / etc。"方法?我举一个例子。
我目前正在开发一个可以从一堆目录和文件中读取的项目。这些文件表示由完全独立且已存在的系统生成的传感器读数。
方法名称应该特定于特定类型的存储库还是更常用的声音名称?如:
通用名称:
interface ISensorRepository
{
IEnumerable<Sensor> GetAll(); / IEnumerable<Sensor> ListAll(); / etc.
Sensor GetByID(int id);
}
实体特定名称:
interface ISensorRepository
{
IEnumerable<Sensor> GetAllSensors(); / IEnumerable<Sensor> ListAllSensors(); / etc.
Sensor GetSensorByID(int id);
}
答案 0 :(得分:3)
Repository
定义为域和数据映射层之间的中介,它的作用类似于内存域对象集合。
因为它应该像内存集合一样,我喜欢命名我的方法如下。
public interface IRepository<T> where T : class {
T Create(T entity);
void Create(IList<T> entities);
T Update(T entity);
T FirstOrDefault(Expression<Func<T, bool>> clause);
IEnumerable<T> Where(Expression<Func<T, bool>> clause);
IEnumerable<TResult> Select<TResult>(Expression<Func<T, TResult>> selector);
T First();
IEnumerable<T> All();
}
有关模式的简短讨论,请参阅http://martinfowler.com/eaaCatalog/repository.html
答案 1 :(得分:2)
我会选择通用命名。
为什么呢?它是为了避免 smurf命名约定(它是programming jargon),这是你在不断重复时所做的事情。
您已经命名了存储库所代表的实体类型,为什么要重复所有重复的工作?如果你坚持使用Single Responsibility Principle,你就不必担心你的抽象被泄漏了。
以下是我尽量避免的事情:
Employee
- EmployeeID
- EmployeeFirstName
- EmployeeLastName
- EmployeeAddress
- EmployeeNumber
- EmployeeAge
- EmployeeEmail
- EmployeeHiringDate
- EmployeeThis
- EmployeeThat
- EmployeeBlabla
- Employee...
- Employee...
有点疯狂吗?
答案 2 :(得分:0)
考虑消费者可能命名的存储库变量。我会写一些类似的东西:
public void DoSomethingWithSensors(ISensorRepository sensors)
{
//Which looks better?
foreach (var sensor in sensors.All)
//Or:
foreach (var sensor in sensors.GetAllSensors())
}
我通常希望尽可能避免冗余。人们不可能忘记他们正在调用All
的存储库,因此我将其命名为,并为其他操作使用类似的通用名称。这也为您提供了将基本接口抽象为一种通用类型的优势:
public interface IRepository<T>
{
IQueryable<T> All { get; }
void Update(T entity);
T Get(int id); //If you have a standard type for IDs
//etc.
}
我会避免使用类似的方法(不要选择3dd&#39;答案很好):
T FirstOrDefault(Expression<Func<T, bool>> clause);
List<TResult> Select<TResult>(Expression<Func<T, TResult>> selector);
如果沿着这条路走下去,您可能会发现很快就会在界面中声明所有LINQ。只需暴露一个IQueryable<T>
并依赖LINQ来提供所有这些选项。如果你正在使用EntityFramework,我会坚持IQueryable
而不是IEnumerable
。
另一个考虑因素是这种模式可能会打破Interface Segregation Principle。很多消费者只会抓取IRepository
个实例来查询,永远不会写。将其分解为两个接口的额外复杂性是否值得解决此问题取决于软件的预期生命周期以及是否有许多其他系统可能依赖于您的代码。