Search code examples
c#design-patternsarchitectureclass-design

Which is the better C# class design for dealing with read+write versus readonly


I'm contemplating two different class designs for handling a situation where some repositories are read-only while others are read-write. (I don't foresee any need for a write-only repository.)


Class Design 1 -- provide all functionality in a base class, then expose applicable functionality publicly in sub classes

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(); }
}

Class Design 2 - read-write class inherits from read-only class

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

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

Is one of these designs clearly stronger than the other? If so, which one and why?

P.S. If this sounds like a homework question, it's not, but feel free to use it as one if you want :)


Solution

  • How about a third option, closely related to the first, but using interfaces instead:

    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
    }
    

    This way the implementation is (or can be) all in one place, and the distinction is made only by which interface you are looking at.