7

为了提供对我数据库中对象的访问,我为所有团队成员创建了一个接口,以便像这样使用(简化示例):

public interface IDatabase
{
   ObservableCollection<Animal> Animals{ get; }
}

我不希望团队访问数据库上下文或某些 oracle 对象(封装)之类的内部结构......

我实现了两个用于现实生活和单元测试的特定类:

public class TestDatabase : IDatabase
{ }

public class OracleDatabase : IDatabase
{ }

经过一些使用,团队成员要求越来越多的功能,我必须在我的界面中添加方法:

public interface IDatabase
{
   ObservableCollection<Animal> Animals{ get; }
   ObservableCollection<Animal> Animals(Gender gender);
   ObservableCollection<Animal> Animals(Gender gender, Race race);
}

一些过滤和排序的东西当然可以由开发人员自己完成,但最好放在数据库中。


现在的问题是我的界面正在爆炸,它每天都在获得更多的专业功能,它远非稳定并且一直在变化。

我的设计从一开始就存在缺陷吗?

解决该问题的一些想法:

  1. 向所有开发人员公开数据库上下文对象(我认为不好)
  2. 添加一个接受 linq 查询的函数
4

2 回答 2

6

您正在尝试重新发明 Repository/UnitOfWork 模式,但这样做并不完全正确。

正确的方法将接近此:

// shared between repositories
public interface IGenericRepository<T> 
{
    T CreateNew();

    void Delete( T item );
    void Update( T item );
    void Insert( T item );

    IEnumerable<T> FindAll();
    T FindOne( int id );
}

// specific repositories
public interface IAnimalRepository : IGenericRepository<Animal>
{
    IEnumerable<Animal> FindByNumberOfLegs( int NumberOfLegs );
    // ... anything specific follows
}

public interface IHumanRepository : IGenericRepository<Human>
{
    IEnumerable<Human> FindByGender( Gender gender );
    //  ... specific repository logic follows
}

// unit of work - a service for clients
public interface IUnitOfWork : IDisposable
{
    IAnimalRepository AnimalRepository { get; }
    IHumanRepository  HumanRepository { get; }
    // .. other repositories follow

    void SaveChanges(); 
}

这样,您的服务层依赖于存储库层,您可以轻松地在实现之间切换,例如用于单元测试。你的客户写

// example code
using ( IUnitOfWork uow = new YourImplementationOfUnitOfWork() )
{
   var animals = uow.AnimalRepository.FindByNumberOfLegs( 3 );

   var person = uow.HumanRepository.CreateNew();
   person.Name = "John";
   uow.HumanRepository.Insert( person );

   uow.SaveChanges();
}

如果您打算限制方法的数量,您可以稍微修改存储库接口:

// shared between repositories
public interface IGenericRepository<T> 
{
    T CreateNew();

    void Delete( T item );
    void Update( T item );
    void Insert( T item );

    IQueryable<T> Query { get; }
}

这样您的客户就可以使用 LINQ:

// example code
using ( IUnitOfWork uow = new YourImplementationOfUnitOfWork() )
{
   var animals = uow.AnimalRepository.Query.Where( a => a.NumberOfLegs == 3 );

   var person = uow.HumanRepository.CreateNew();
   person.Name = "John";
   uow.HumanRepository.Insert( person );

   uow.SaveChanges();
}
于 2013-08-01T13:19:47.703 回答
2

我可以建议应用接口隔离原则吗?即将你的接口分成逻辑组。这也将允许您界面的用户不实现他们不使用/不需要的部分。稳定性也应该提高,因为您将拥有更多谨慎的可测试代码。

于 2013-08-01T13:18:06.360 回答