开发者

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 :)


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.


(Edit: I think Eric Petroelje offers a very nice interface-based solution in his answer. I would probably vote for his suggestion, first of all.)

From your two choices, I would clearly vote for design #2.

With design #1, I think it doesn't make sense to have a "read-only" class that internally isn't read-only at all:

  1. The read-only class is "heavier" than it needs to be.

  2. Anyone can derive from your read-only class and then call any of the base class' modification methods. At the very least, with design #1, you ought to make the read-only class sealed.

With design #2, it's much clearer than the read-only class is a reduced version (base class) of the full-featured class, or phrased differently.


I would say design #2, but then you ought to change the name of the ReadOnlyRepository to something like ReadRepository.

Inheritance defines an IS-A relation between the classes, ans saying 'a ReadWriteRepository is a ReadOnlyRepository' doesn't sound logical. But 'ReadWriteRepository is a ReadingRepository' does.


First let me admit that I am making some assumptions about what you might intend doing. If this misses the point then let me know.

I am not sure how usefull the classes would be in either of your two options. I assume you would have calling code that would use an instance of a readonly repository and at othertimes an instance of a read/write repository, but the interfaces do not match so you would have to differenciate in your code anyway?

It might be better to provide a common interface and then throw exceptions if you try to write to the repository when it is readony and have your code handle the exceptions.


I would certainly say that design 2 is the strongest. If you want to have a read-only implementation, it does not need to know anything about writing. It makes perfect sense to extend the read-only implementation with the insert, update, and delete methods. I also think this design is the one that conforms the most to the Open-Closed principle.


I would suggest having a base class ReadableFoo, with a sealed derived class ImmutableFoo whose constructor takes a ReadableFoo, and a possibly-inheritable derived class MutableFoo, and possibly a class ReadableShadowFoo whose constructor would take a ReadableFoo (which may or may not be mutable), but which would act as a read-only wrapper to it.


The answer by Eric means SOLID Principle ISP. It´s so easy and basic to use.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜