2010-05-10 22 views
13

Estoy contemplando dos diseños de clases diferentes para manejar una situación donde algunos repositorios son de solo lectura mientras que otros son de lectura-escritura. (No preveo ninguna necesidad de un repositorio de sólo escritura.)Cuál es el mejor diseño de clase C# para tratar con lectura + escritura versus solo


Diseño Clase 1 - proporcionar toda la funcionalidad de una clase base, a continuación, exponer la funcionalidad aplicable públicamente en subclases

public abstract class RepositoryBase 
{ 
    protected virtual void SelectBase() { // implementation... } 
    protected virtual void InsertBase() { // implementation... } 
    protected virtual void UpdateBase() { // implementation... } 
    protected virtual void DeleteBase() { // implementation... } 
} 

public class ReadOnlyRepository : RepositoryBase 
{ 
    public void Select() { SelectBase(); } 
} 

public class ReadWriteRepository : RepositoryBase 
{ 
    public void Select() { SelectBase(); } 
    public void Insert() { InsertBase(); } 
    public void Update() { UpdateBase(); } 
    public void Delete() { DeleteBase(); } 
} 

Diseño clase 2 - clase de lectura y escritura se hereda de la clase de sólo lectura

public class ReadOnlyRepository 
{ 
    public void Select() { // implementation... } 
} 

public class ReadWriteRepository : ReadOnlyRepository 
{ 
    public void Insert() { // implementation... } 
    public void Update() { // implementation... } 
    public void Delete() { // implementation... } 
} 

¿Es uno de estos diseños claramente más fuerte que el otro? Si es así, ¿cuál y por qué?

P.S. Si esto suena como una pregunta de tarea, no lo es, pero siéntete libre de usarlo como uno si quieres :)

+1

¿Por qué es necesario distinguir entre los dos tipos de repositorio? –

+0

@John, bueno, tal vez no lo es, pero estaba pensando que quiero asegurarme de proteger las tablas de la base de datos que no se supone que cambien de ediciones accidentales. – devuxer

+1

@DanM: ¿qué dice tu DBA al respecto? La mayoría sentirá que el lugar para proteger la base de datos está en la base de datos, no en su código. –

Respuesta

25

¿Qué tal una tercera opción, estrechamente relacionado con el primero, pero el uso de interfaces lugar:

public interface IReadRepository { 
    public void Select(); 
} 

public interface IWriteRepository { 
    public void Insert(); 
    public void Update(); 
    public void Delete(); 
} 

// Optional 
public interface IRepository : IReadRepository, IWriteRepository { 
} 

public class Repository : IRepository { 
    // Implementation 
} 

De esta manera la aplicación es (o puede ser) en un solo lugar, y la distinción se hace sólo a qué interfaz estás mirando

+1

+1. Me gusta mucho este enfoque * porque * un método puede especificar con precisión qué tipo de acceso necesita para un 'Repositorio ': si el acceso de solo lectura es suficiente, exige un' IReadRepository'; si necesita acceso de escritura, exige 'IWriteRepository'; si necesita acceso de lectura-escritura, exige un 'IRepository'. Un efecto secundario curioso de esto es que la definición de 'get' y' set' de una propiedad puede separarse en dos interfaces. – stakx

+0

Creo que este es un patrón interesante, ya que puede aplicar al menos un tipo de seguridad "semántica" al dar a los objetos en su programa el acceso "necesario acceso de escritura y acceso de escritura" a las interfaces "grabables".No solo pensaría en esto como un problema de seguridad (porque las preocupaciones de seguridad son un problema de permiso de base de datos), sino también como un "minimizar la cantidad de interfaz que le das a varios objetos dentro del sistema", como un buen principio de POO. –

+0

Pero aún así, a menos que el dominio llame para las clases WriteOnly, vincularía las 2 interfaces (IWriteRepository: IReadRepository) y eso significa que la pregunta de herencia se ha desplazado a las interfaces. –

0

Diría que el diseño 2 es el más fuerte. Si desea tener una implementación de solo lectura, no necesita saber nada sobre la escritura. Tiene mucho sentido ampliar la implementación de solo lectura con los métodos de inserción, actualización y eliminación. También creo que este diseño es el que más se ajusta al Open-Closed principle.

5

(Editar:.. Creo que Eric Petroelje ofrece una solución basada en interfaz muy agradable en su respuesta que probablemente voten por su sugerencia, en primer lugar)

Desde sus dos opciones, me votaría claramente por diseño # 2.

Con un diseño # 1, creo que no tiene sentido tener una clase de "sólo lectura" que internamente no es de sólo lectura en absoluto:

  1. La lectura solo la clase es "más pesada" de lo que necesita ser.

  2. Cualquiera puede derivar de su clase de solo lectura y luego llamar a cualquiera de los métodos de modificación de la clase base. Por lo menos, con el diseño n. ° 1, debe crear la clase de solo lectura sealed.

Con el diseño # 2, es mucho más clara que la clase de sólo lectura es una versión reducida (clase base) de la clase con todas las funciones, o redactadas de manera diferente.

+0

Sí. Este es exactamente el diseño que utilicé en mis proyectos que necesitaban interfaces RW y R separadas. –

+1

Creo que prefiero la solución de Eric también, pero +1 para su punto n. ° 2. Es un problema que no había pensado. – devuxer

1

Primero déjeme admitir que estoy haciendo algunas suposiciones sobre lo que podría intentar hacer.Si esto pasa por alto, házmelo saber.

No estoy seguro de cómo Utiles las clases serían en cualquiera de sus dos opciones. Supongo que tendrías un código de llamada que usaría una instancia de un repositorio de solo lectura y otras veces una instancia de un repositorio de lectura/escritura, pero las interfaces no coinciden por lo que tendrías que diferenciar en tu código de todos modos.

Podría ser mejor para proporcionar una interfaz común y luego lanzar excepciones si se intenta escribir en el repositorio cuando está readony y tienen su código de manejar las excepciones.

1

yo diría que el diseño # 2, pero entonces debería cambiar el nombre de la ReadOnlyRepository a algo así como ReadRepository.

Inheritance define un IS-A relación entre las clases, Ans diciendo 'un ReadWriteRepository es un ReadOnlyRepository' no suena lógico. Pero 'ReadWriteRepository es un ReadingRepository'.

0

Sugeriría tener una clase base ReadableFoo, con una clase derivada sellada ImmutableFoo cuyo constructor toma un ReadableFoo, y una clase derivada posiblemente heredable MutableFoo, y posiblemente una clase ReadableShadowFoo cuyo constructor tomaría un ReadableFoo (que puede o puede no ser mutable), pero que actuaría como un contenedor de solo lectura.

0

La respuesta de Eric significa PRINCIPIO DE PRINCIPIO SÓLIDO. Es tan fácil y básico de usar.

Cuestiones relacionadas