Architettura per DAL Mockable su progetti di grandi dimensioni

3

Recentemente ho letto un articolo sulla creazione di un blog utilizzando ASP.NET e MVC e nell'articolo l'utente divide il Data Access Layer in una libreria di classi separata e crea un'interfaccia per consentire al DAL di essere deriso per i test.

Funziona benissimo per piccoli progetti, ma sto facendo fatica a vedere come questo si ridimensionerà. Ad esempio nell'articolo si finisce con la seguente interfaccia:

public interface IBlogRepository
{
    IList<Objects.Post> Posts(int pageNo, int pageSize);
    int TotalPosts(bool checkIsPublished = true);

    IList<Objects.Post> PostsForCategory(string categorySlug, int pageNo, int pageSize);
    int TotalPostsForCategory(string categorySlug);
    Objects.Category Category(string categorySlug);

    IList<Objects.Post> PostsForTag(string tagSlug, int pageNo, int pageSize);
    int TotalPostsForTag(string tagSlug);
    Objects.Tag Tag(string tagSlug);

    IList<Objects.Post> PostsForSearch(string search, int pageNo, int pageSize);
    int TotalPostsForSearch(string search);

    Objects.Post Post(int year, int month, string titleSlug);

    IList<Objects.Category> Categories();
    IList<Objects.Tag> Tags();

    IList<Objects.Post> Posts(int pageNo, int pageSize, string sortColumn, bool sortByAscending);

    void AddPost(Objects.Post post);
}

C'è quindi un file .cs associato con l'implementazione di questa interfaccia.

Come implementeresti un'architettura simile per un progetto molto più ampio? Ad esempio, il progetto che ho al lavoro è composto da 25 controller, ciascuno con un elenco minimo, aggiungere, modificare, visualizzare, eliminare e contare. Ciò porterebbe a un'interfaccia con oltre 150 funzioni.

Questo tipo di architettura è ancora adatto a progetti più grandi e, in caso affermativo, come lo struttureresti per evitare di avere un singolo file che implementa più di 150 funzioni?

    
posta Gavin Coates 28.05.2013 - 10:56
fonte

1 risposta

2

Dai un'occhiata a un repository di base generico che contiene alcune delle funzionalità comuni tra tutti i repository.

interface IRepository<T>
{
     void Save();
     T GetById(int id);
     int GetCount();
}

Da questo puoi creare repository personalizzati per ogni azione.

interface IUserRepository : IRepository<UserPosts>
{
    UserPosts GetPostsByUserId(int userId);
}

interface IOtherRepository : IRepository<OtherObject>
{
    void OtherRepositoryAction(int id);
}

In questo modo puoi ridurre il numero di azioni che ogni singolo repository ha. Inoltre, salva un singolo repository "God" che esegue tutte le azioni per l'applicazione.

Le strategie per la creazione dei repository includono:

  • Una per tabella del database
  • Uno per itinerario di aggregazione

Per il modello di rotta aggregato dai un'occhiata a Domain Driven Design. Eric Evans ha un eccellente libro su Domain Driven Design.

Per ciascun repository che si crea, si deve applicare l'integrazione della dipendenza per collegare l'interfaccia a un tipo concreto. I contenitori DI comprendono:

  • Autofac
  • StructureMap
  • Ninject

A seconda dell'architettura, questi repository possono essere chiamati come segue (NOTA: non sto dicendo che questo è il modo migliore, ma è un modo):

public class UserController: Controller
{
    private readonly IUserService _userService;
    UserController(IUserService userService)
    {
         _userService = userService;
    }
    public void SaveUser(User user)
    {
        _userService.SaveUser(user);
    }
}

public UserService : IUserService
{
     private readonly IUserRepository _userRepository;
     public UserService(IUserRepository userRepository)
     {
        _userRepository = userRepository;
     }
     public void SaveUser(User user)
     {
         _userRepository.Save(user);
     }
}
    
risposta data 28.05.2013 - 11:22
fonte

Leggi altre domande sui tag