Introduction
I have a public abstract class, with an abstract method, which I want to call from a worker thread.
When the method is called, the respective instance should be locked down in order to prevent state changes during calculation.
I only want to work with the abstract class, as the implementation of the inheritors is done by third parties.
public abstract class MyClass
{
public abstract MyResult GetData();
}
The problem
My library is used by third parties, I have to assume that they know nothing about the internal implementation of the library.
I don't want to force them to study the documentation of my class, before they are able to implement their own inheritor as I consider this bad form.
My approach
My first idea was to add a protected lock object to the class and lock on it when calling the method.
However, in order for this to be useful, the third party would have to lock on it as well, and thus know about it.
As I don't want to force the third party to know about the internals, I don't like this option.
public abstract class MyClass
{
protected readonly object myLock = new object();
public MyResult GetData()
{
MyResult result;
lock(myLock)
{
result = GetDataInternal();
}
return result;
}
protected abstract MyResult GetDataInternal();
}
Background
I'm working on a data pipeline, which runs on a separate thread.
This pipeline requests data in a specific format and processes it in the background.
Providing the data can take some time and the provided data relies on properties of the objects.
In this case, its a preparation pipeline for 3D models.
The question
How can I lock a whole object without knowing its implementation?
If there is no such way, then is there an agreed upon pattern or something like that for this problem?
My library is used by third parties, I have to assume that they know nothing about the internal implementation of the library.
(..)
When the method is called, the respective instance should be locked down in order to prevent state changes during calculation.
I think that the best way is to .. make them know, and make sure they know that they are responsible for it. You can easily make it intuitive without (much) documentation.
Consider changing your abstract class to something like:
public interface ILockable
{
void FreezeDataForCalculations();
void ThawAfterCalculations();
}
public abstract class MyBaseClass<T> where T:ILockable
{
public abstract T GetData();
}
Usage:
public class MyThingie : MyBaseClass<TheActualData>
{
}
public class TheActualData : ILockable
{
public string Foo {get;set;}
public void FreezeDataForCalculations() { ...???...}
public void ThawAfterCalculations() { ....???.... }
}
Now, you effectively ensured that:
whoever wants to implement it, has to provide his own type, that implements extra interface
whoever implementa that extra interface will notice this two methods, and they will at least think "wtf", and will either understand immediatelly, or will try consulting the documentation
you do no locking for the data, creator of the class is responsible for it
implementor now can choose whever to actually implement freeze/thaw pair, or leave them empty and simply write their own code to not modify the data in the meantime
your code now has to call 'Freeze' and 'Thaw' appropriatelly, and can assume the implementor did what he was expected to
On the contrary, if you can't assume that he did was he was expected to, then change API of your library and don't allow user-defined types, and restrict the API to only your own types that you can ensure that will play nice.
Related
Ok, so working on a dotnet Core 2 console app that I'm designing to run either on Windows or *Nix. Now the the part I'm trying to figure out is I want to only have one code base and let the code determine if it's running on Win then go one path, or if on *Nix go another path.
So what I'm thinking is create an Interface with the way I want the classes for the two paths to look as far as properties and methods, then create a Win and Nix class implementing the interface.
Seems straightforward, but what I am racking my brain on is how exactly do I create the object based on the OS? I have wrapper code for "IsWindows" and "IsNix" that returns a boolean each, so my thought is to use a If statement to do this. Not sure how to create a generic global variable, then instantiate it in the conditional statement.
Maybe I'm off my rocker and trying to do something odd here, if I am I'm not afraid to be told that. My only other thought is to perform the work inside the conditional statement, but that really would negate my desire to create the object in the conditional based on the OS, then call the same code going forward, using the classes that implement the Interface to make the different code calls as appropriate.
So I feel like a complete idiot with brain lock. Simply creating an object of the type of the Interface is all I needed to do, then set it to an instance of the class in the conditional statement. Easy peasy, not sure why I had a brain fart on that one.
Having common interface and two classes implementing it for different OS'es is definitelly good approach. So let's assume you have
public interface IMyInterface
{
void DoSomething();
}
public class WinClass: IMyInterface
{
public void DoSomething()
{
//Implementation of DoSomething for Windows
}
}
public class NixClass : IMyInterface
{
public void DoSomething()
{
//Implementation of DoSomething for *nix
}
}
Common way to instantiate different implementations of interface (or abstract class) based on certain conditions is using Factory pattern. This might look like this:
public static class MyInterfaceFactory
{
public static IMyInterface CreateMyInterface()
{
if (IsWindows)
return new WinClass();
else if (IsNix)
return new NixClass();
else
throw new PlatformNotSupportedException();
}
}
This is the only platform-dependent part of your code, rest of your code will use only IMyInterface and will be platform independent. You can either use this factory whenever you need to create new instance implementing IMyInterface, or you can use Singleton pattern to ensure, that only one objects will be created for entire application:
public static class MyInterfaceSingleton
{
static MyInterfaceSingleton()
{
Instance = MyInterfaceFactory.CreateMyInterface();
}
public static IMyInterface Instance { get; private set; }
// In C# 7, you can use just this instead:
// public static IMyInterface Instance { get; } = MyInterfaceFactory.CreateMyInterface();
}
Your application then simply call MyInterfaceSingleton.Instance.DoSomething(); whenever needed, in a platform independent way.
New to OOP here. I have defined an interface with one method, and in my derived class I defined another public method. My client code is conditionally instantiating a class of the interface type, and of course the compiler doesn't know about the method in one of the derived classes as it is not part of the underlying interface definition. Here is what I am talking about:
public interface IFileLoader
{
public bool Load();
}
public class FileLoaderA : IFileLoader
{
public bool Load();
//implementation
public void SetStatus(FileLoadStatus status)
{
//implementation
}
}
public class FileLoaderB : IFileLoader
{
public bool Load();
//implementation
//note B does not have a SetStatus method
}
public enum FileLoadStatus
{
Started,
Done,
Error
}
// client code
IFileLoader loader;
if (Config.UseMethodA)
{
loader = new FileLoaderA();
}
else
{
loader = new FileLoaderB();
}
//does not know about this method
loader.SetStatus (FileStatus.Done);
I guess I have two questions:
What should I be doing to find out if the object created at run-time has the method I am trying to use? Or is my approach wrong?
I know people talk of IOC/DI all the time. Being new OOP, what is the advantage of using an IOC in order to say, "when my app asks
for an IFileLoader type, use concrete class x", as opposed to simply
using an App.Config file to get the setting?
Referring to your two questions and your other post I'd recommend the following:
What should I be doing to find out if the object created at run-time has the method I am trying to use? Or is my approach wrong?
You don't necessarily need to find out the concrete implementation at runtime in your client code. Following this approach you kinda foil the crucial purpose of an interface. Hence it's rather useful to just naïvely use the interface and let the concrete logic behind decide what's to do.
So in your case, if one implementation's just able to load a file - fine. If your other implementation is able to the same and a bit more, that's fine, too. But the client code (in your case your console application) shouldn't care about it and just use Load().
Maybe some code says more than thousand words:
public class ThirdPartyLoader : IFileLoader
{
public bool Load(string fileName)
{
// simply acts as a wrapper around your 3rd party tool
}
}
public class SmartLoader : IFileLoader
{
private readonly ICanSetStatus _statusSetter;
public SmartLoader(ICanSetStatus statusSetter)
{
_statusSetter = statusSetter;
}
public bool Load(string fileName)
{
_statusSetter.SetStatus(FileStatus.Started);
// do whatever's necessary to load the file ;)
_statusSetter.SetStatus(FileStatus.Done);
}
}
Note that the SmartLoader does a bit more. But as a matter of separation of concerns its purpose is the loading part. The setting of a status is another class' task:
public interface ICanSetStatus
{
void SetStatus(FileStatus fileStatus);
// maybe add a second parameter with information about the file, so that an
// implementation of this interface knows everything that's needed
}
public class StatusSetter : ICanSetStatus
{
public void SetStatus(FileStatus fileStatus)
{
// do whatever's necessary...
}
}
Finally your client code could look something like the follwing:
static void Main(string[] args)
{
bool useThirdPartyLoader = GetInfoFromConfig();
IFileLoader loader = FileLoaderFactory.Create(useThirdPartyLoader);
var files = GetFilesFromSomewhere();
ProcessFiles(loader, files);
}
public static class FileLoaderFactory
{
public static IFileLoader Create(bool useThirdPartyLoader)
{
if (useThirdPartyLoader)
{
return new ThirdPartyLoader();
}
return new SmartLoader(new StatusSetter());
}
}
Note that this is just one possible way to do what you're looking for without having the necessity to determine IFileLoader's concrete implementation at runtime. There maybe other more elegant ways, which furthermore leads me to your next question.
I know people talk of IOC/DI all the time. Being new OOP, what is the advantage of using an IOC [...], as opposed to simply using an App.Config file to get the setting?
First of all separating of classes' responsibility is always a good idea especially if you want to painlessly unittest your classes. Interfaces are your friends in these moments as you can easily substitute or "mock" instances by e.g. utilizing NSubstitute. Moreover, small classes are generally more easily maintainable.
The attempt above already relies on some sort of inversion of control. The main-method knows barely anything about how to instantiate a Loader (although the factory could do the config lookup as well. Then main wouldn't know anything, it would just use the instance).
Broadly speaking: Instead of writing the boilerplate factory instantiation code, you could use a DI-Framework like Ninject or maybe Castle Windsor which enables you to put the binding logic into configuration files which might best fit your needs.
To make a long story short: You could simply use a boolean appSetting in your app.config that tells your code which implementation to use. But you could use a DI-Framework instead and make use of its features to easily instantiate other classes as well. It may be a bit oversized for this case, but it's definitely worth a look!
Use something like:
if((loader as FileLoaderA) != null)
{
((FileLoaderA)loader).SetStatus(FileStatus.Done);
}
else
{
// Do something with it as FileLoaderB type
}
IoC is normally used in situations where your class depends on another class that needs to be setup first, the IoC container can instantiate/setup an instance of that class for your class to use and inject it into your class usually via the constructor. It then hands you an instance of your class that is setup and ready to go.
EDIT:
I was just trying to keep the code concise and easy to follow. I agree that this is not the most efficient form for this code (it actually performs the cast twice).
For the purpose of determining if a particular cast is valid Microsoft suggests using the following form:
var loaderA = loader as FileLoaderA;
if(loaderA != null)
{
loaderA.SetStatus(FileStatus.Done);
// Do any remaining FileLoaderA stuff
return;
}
var loaderB = loader as FileLoaderB
if(loaderB != null)
{
// Do FileLoaderB stuff
return;
}
I do not agree with using is in the if. The is keyword was designed to determine if an object was instantiated from a class that implements a particular interface, rather than if a cast is viable. I have found it does not always return the expected result (especially if a class implements multiple interfaces through direct implementation or inheritance of a base class).
I have a class hierarchy responsible for parsing or mapping one model (or message) to another. It has non-trivial logic.
internal interface IMessageParser<T, K>
where T : class
where K : class
{
K Serialize(T originalMessage);
T Deserialize(K concreteMessage);
}
internal abstract class OriginalToConcreteMessageParser : IMessageParser<OriginalMessage, ConcreteMessage>
{
// some private methods that do stuff and are called in the Serialize() method
public virtual ConcreteMessage Serialize(OriginalMessage originalMessage)
{
// some stuff
}
}
There are 21 of these concrete parsers:
internal sealed class OriginalToConcreteMessageParserFooMessageParser : OriginalToConcreteMessageParser
{
}
internal sealed class OriginalToConcreteMessageParserBarMessageParser : OriginalToConcreteMessageParser
{
}
I want to add a new private method to OriginalToConcreteMessageParser and call it in Serialize(). Let's call this method Baz().
I could create OriginalToConcreteBazMessageParser and make all 21 concrete implementations inherit from this but I would prefer not to have to do this.
The functionality that Baz() provides is definitely at the abstraction level of OriginalToConcreteMessageParser.
In summary, I want to inject a method into OriginalToConcreteMessageParser and call it in Serialize() without touching OriginalToConcreteMessageParser.
I think that you could try some implementation of the decorator pattern, or maybe the strategy pattern
The decorator, has this motivation, that more or less is the same that you have:
As an example, consider a window in a windowing system. To allow scrolling of the window's contents, we may wish to add horizontal or
vertical scrollbars to it, as appropriate. Assume windows are
represented by instances of the Window class, and assume this class
has no functionality for adding scrollbars. We could create a subclass
ScrollingWindow that provides them, or we could create a
ScrollingWindowDecorator that adds this functionality to existing
Window objects. At this point, either solution would be fine.
Now let's assume we also desire the ability to add borders to our windows. Again, our original Window class has no support. The
ScrollingWindow subclass now poses a problem, because it has
effectively created a new kind of window. If we wish to add border
support to all windows, we must create subclasses WindowWithBorder and
ScrollingWindowWithBorder. Obviously, this problem gets worse with
every new feature to be added. For the decorator solution, we simply
create a new BorderedWindowDecorator—at runtime, we can decorate
existing windows with the ScrollingWindowDecorator or the
BorderedWindowDecorator or both, as we see fit.
but probably it will be harder to implement than strategy, and probably too powerful for what you actually need. Decorator is good when a child class will merge the functionality of one, two, or more classes, but using the exact interface as it if where just one class.
With strategy, you can easily switch specific behaviors of a class. Is good when the only think that changes is a function, and the behavior is not usually composed,, but simply different between diferent implementations. Lets say that all the classes have a common behavior, but in the moment of the serialization, the can perform some slightly different operations. How to handle it? well, you make your IMessageParser capable of receive a parsing strategy (an object implementing an interfaz with probably just a function, so all the code you was thinking of putting in BAZ() will be in the strategy object ). And in every concrete class, if the strategy is present, the serialize function uses it. If the strategy is null, the concrete class just use the default behavior.
This is good since know, you want to use that Baz() function to add some functionality to your serialize function, but only in some cases, and this does the trick. And, also in the future, it allows you to add some further behavior to perform during the serialization, just creating new strategy objects.
I would use strategy. You create a SerializeStrategy interface, with a execute method. And then one or more concrete classes implementing that interface. Then you define a setStrategy method in the IMessageParser interface, and implement it in the base class, OriginalToConcreteMessageParser or any other at that level, and save there the strategy object. In the child classes just check if there is a strategy to use.
If you read the pattern carefully, and you take care of having all the participants as decoupled as you can, you can build a SOLID model, and easy to maintain application.
as we can read in the same link above:
This allows better decoupling between the behavior and the class that
uses the behavior. The behavior can be changed without breaking the
classes that use it, and the classes can switch between behaviors by
changing the specific implementation used without requiring any
significant code changes. Behaviors can also be changed at run-time as
well as at design-time. For instance, a car object’s brake behavior
can be changed from BrakeWithABS() to Brake() by changing the
brakeBehavior member to: brakeBehavior = new Brake(); This gives
greater flexibility in design and is in harmony with the Open/closed
principle (OCP)
You could use a delegate for that, but you'd obviously have to change the method signature:
internal abstract class OriginalToConcreteMessageParser : IMessageParser<OriginalMessage, ConcreteMessage>
{
public virtual ConcreteMessage Serialize(OriginalMessage originalMessage, Func<OriginalMessage, ConcreteMessage> baz)
{
return baz(originalMessage);
}
}
You could optionally add overloads of Serialize to your concrete classes that inject the Baz method:
OriginalToConcreteMessageParserFooMessageParser:
internal sealed class OriginalToConcreteMessageParserFooMessageParser : OriginalToConcreteMessageParser
{
public ConcreteMessage Serialize(OriginalMessage originalMessage)
{
Func<OriginalMessage, ConcreteMessage> baz = message =>
{
ConcreteMessage foo = ToFoo(message);
return foo;
};
return base.Serialize(originalMessage, baz);
}
}
OriginalToConcreteMessageParserBarMessageParser:
internal sealed class OriginalToConcreteMessageParserBarMessageParser : OriginalToConcreteMessageParser
{
public ConcreteMessage Serialize(OriginalMessage originalMessage)
{
Func<OriginalMessage, ConcreteMessage> baz = message =>
{
ConcreteMessage bar = ToBar(message);
return bar;
};
return base.Serialize(originalMessage, baz);
}
}
I have a class that upon construction, loads it's info from a database. The info is all modifiable, and then the developer can call Save() on it to make it Save that information back to the database.
I am also creating a class that will load from the database, but won't allow any updates to it. (a read only version.) My question is, should I make a separate class and inherit, or should I just update the existing object to take a readonly parameter in the constructor, or should I make a separate class entirely?
The existing class is already used in many places in the code.
Thanks.
Update:
Firstly, there's a lot of great answers here. It would be hard to accept just one. Thanks everyone.
The main problems it seems are:
Meeting expectations based on class names and inheritance structures.
Preventing unnecessary duplicate code
There seems to be a big difference between Readable and ReadOnly. A Readonly class should probably not be inherited. But a Readable class suggests that it might also gain writeability at some point.
So after much thought, here's what I'm thinking:
public class PersonTestClass
{
public static void Test()
{
ModifiablePerson mp = new ModifiablePerson();
mp.SetName("value");
ReadOnlyPerson rop = new ReadOnlyPerson();
rop.GetName();
//ReadOnlyPerson ropFmp = (ReadOnlyPerson)mp; // not allowed.
ReadOnlyPerson ropFmp = (ReadOnlyPerson)(ReadablePerson)mp;
// above is allowed at compile time (bad), not at runtime (good).
ReadablePerson rp = mp;
}
}
public class ReadablePerson
{
protected string name;
public string GetName()
{
return name;
}
}
public sealed class ReadOnlyPerson : ReadablePerson
{
}
public class ModifiablePerson : ReadablePerson
{
public void SetName(string value)
{
name = value;
}
}
Unfortunately, I don't yet know how to do this with properties (see StriplingWarrior's answer for this done with properties), but I have a feeling it will involve the protected keyword and asymmetric property access modifiers.
Also, fortunately for me, the data that is loaded from the database does not have to be turned into reference objects, rather they are simple types. This means I don't really have to worry about people modifying the members of the ReadOnlyPerson object.
Update 2:
Note, as StriplingWarrior has suggested, downcasting can lead to problems, but this is generally true as casting a Monkey to and Animal back down to a Dog can be bad. However, it seems that even though the casting is allowed at compile time, it is not actually allowed at runtime.
A wrapper class may also do the trick, but I like this better because it avoids the problem of having to deep copy the passed in object / allow the passed in object to be modified thus modifying the wrapper class.
The Liskov Substitution Principle says that you shouldn't make your read-only class inherit from your read-write class, because consuming classes would have to be aware that they can't call the Save method on it without getting an exception.
Making the writable class extend the readable class would make more sense to me, as long as there is nothing on the readable class that indicates its object can never be persisted. For example, I wouldn't call the base class a ReadOnly[Whatever], because if you have a method that takes a ReadOnlyPerson as an argument, that method would be justified in assuming that it would be impossible for anything they do to that object to have any impact on the database, which is not necessarily true if the actual instance is a WriteablePerson.
Update
I was originally assuming that in your read-only class you only wanted to prevent people calling the Save method. Based on what I'm seeing in your answer-response to your question (which should actually be an update on your question, by the way), here's a pattern you might want to follow:
public abstract class ReadablePerson
{
public ReadablePerson(string name)
{
Name = name;
}
public string Name { get; protected set; }
}
public sealed class ReadOnlyPerson : ReadablePerson
{
public ReadOnlyPerson(string name) : base(name)
{
}
}
public sealed class ModifiablePerson : ReadablePerson
{
public ModifiablePerson(string name) : base(name)
{
}
public new string Name {
get {return base.Name;}
set {base.Name = value; }
}
}
This ensures that a truly ReadOnlyPerson cannot simply be cast as a ModifiablePerson and modified. If you're willing to trust that developers won't try to down-cast arguments in this way, though, I prefer the interface-based approach in Steve and Olivier's answers.
Another option would be to make your ReadOnlyPerson just be a wrapper class for a Person object. This would necessitate more boilerplate code, but it comes in handy when you can't change the base class.
One last point, since you enjoyed learning about the Liskov Substitution Principle: By having the Person class be responsible for loading itself out of the database, you are breaking the Single-Responsibility Principle. Ideally, your Person class would have properties to represent the data that comprises a "Person," and there would be a different class (maybe a PersonRepository) that's responsible for producing a Person from the database or saving a Person to the database.
Update 2
Responding to your comments:
While you can technically answer your own question, StackOverflow is largely about getting answers from other people. That's why it won't let you accept your own answer until a certain grace period has passed. You are encouraged to refine your question and respond to comments and answers until someone has come up with an adequate solution to your initial question.
I made the ReadablePerson class abstract because it seemed like you'd only ever want to create a person that is read-only or one that is writeable. Even though both of the child classes could be considered to be a ReadablePerson, what would be the point of creating a new ReadablePerson() when you could just as easily create a new ReadOnlyPerson()? Making the class abstract requires the user to choose one of the two child classes when instantiating them.
A PersonRepository would sort of be like a factory, but the word "repository" indicates that you're actually pulling the person's information from some data source, rather than creating the person out of thin air.
In my mind, the Person class would just be a POCO, with no logic in it: just properties. The repository would be responsible for building the Person object. Rather than saying:
// This is what I think you had in mind originally
var p = new Person(personId);
... and allowing the Person object to go to the database to populate its various properties, you would say:
// This is a better separation of concerns
var p = _personRepository.GetById(personId);
The PersonRepository would then get the appropriate information out of the database and construct the Person with that data.
If you wanted to call a method that has no reason to change the person, you could protect that person from changes by converting it to a Readonly wrapper (following the pattern that the .NET libraries follow with the ReadonlyCollection<T> class). On the other hand, methods that require a writeable object could be given the Person directly:
var person = _personRepository.GetById(personId);
// Prevent GetVoteCount from changing any of the person's information
int currentVoteCount = GetVoteCount(person.AsReadOnly());
// This is allowed to modify the person. If it does, save the changes.
if(UpdatePersonDataFromLdap(person))
{
_personRepository.Save(person);
}
The benefit of using interfaces is that you're not forcing a specific class hierarchy. This will give you better flexibility in the future. For example, let's say that for the moment you write your methods like this:
GetVoteCount(ReadablePerson p);
UpdatePersonDataFromLdap(ReadWritePerson p);
... but then in two years you decide to change to the wrapper implementation. Suddenly ReadOnlyPerson is no longer a ReadablePerson, because it's a wrapper class instead of an extension of a base class. Do you change ReadablePerson to ReadOnlyPerson in all your method signatures?
Or say you decide to simplify things and just consolidate all your classes into a single Person class: now you have to change all your methods to just take Person objects. On the other hand, if you had programmed to interfaces:
GetVoteCount(IReadablePerson p);
UpdatePersonDataFromLdap(IReadWritePerson p);
... then these methods don't care what your object hierarchy looks like, as long as the objects you give them implement the interfaces they ask for. You can change your implementation hierarchy at any time without having to change these methods at all.
Definitely do not make the read-only class inherit from the writable class. Derived classes should extend and modify the capabilities of the base class; they should never take capabilities away.
You may be able to make the writable class inherit from the read-only class, but you need to do it carefully. The key question to ask is, would any consumers of the read-only class rely on the fact that it is read-only? If a consumer is counting on the values never changing, but the writable derived type is passed in and then the values are changed, that consumer could be broken.
I know it is tempting to think that because the structure of the two types (i.e. the data that they contain) is similar or identical, that one should inherit from the other. But that is often not the case. If they are being designed for significantly different use cases, they probably need to be separate classes.
A quick option might be to create an IReadablePerson (etc) interface, which contains only get properties, and does not include Save(). Then you can have your existing class implement that interface, and where you need Read-only access, have the consuming code reference the class through that interface.
In keeping with the pattern, you probably want to have a IReadWritePerson interface, as well, which would contain the setters and Save().
Edit On further thought, IWriteablePerson should probably be IReadWritePerson, since it wouldn't make much sense to have a write-only class.
Example:
public interface IReadablePerson
{
string Name { get; }
}
public interface IReadWritePerson : IReadablePerson
{
new string Name { get; set; }
void Save();
}
public class Person : IReadWritePerson
{
public string Name { get; set; }
public void Save() {}
}
The question is, "how do you want to turn a modifiable class into a read-only class by inheriting from it?"
With inheritance you can extend a class but not restrict it. Doing so by throwing exceptions would violate the Liskov Substitution Principle (LSP).
The other way round, namely deriving a modifiable class from a read-only class would be OK from this point of view; however, how do you want to turn a read-only property into a read-write property? And, moreover, is it desirable to be able to substitute a modifiable object where a read-only object is expected?
However, you can do this with interfaces
interface IReadOnly
{
int MyProperty { get; }
}
interface IModifiable : IReadOnly
{
new int MyProperty { set; }
void Save();
}
This class is assignment compatible to the IReadOnly interface as well. In read-only contexts you can access it through the IReadOnly interface.
class ModifiableClass : IModifiable
{
public int MyProperty { get; set; }
public void Save()
{
...
}
}
UPDATE
I did some further investigations on the subject.
However, there is a caveat to this, I had to add a new keyword in IModifiable and you can only access the getter either directly through the ModifiableClass or through the IReadOnly interface, but not through the IModifiable interface.
I also tried to work with two interfaces IReadOnly and IWriteOnly having only a getter or a setter respectively. You can then declare an interface inheriting from both of them and no new keyword is required in front of the property (as in IModifiable). However when you try to access the property of such an object you get the compiler error Ambiguity between 'IReadOnly.MyProperty' and 'IWriteOnly.MyProperty'.
Obviously, it is not possible to synthesize a property from separate getters and setters, as I expected.
I had the same problem to solve when creating an object for user security permissions, that in certain cases must be mutable to allow high-level users to modify security settings, but normally is read-only to store the currently logged-in user's permissions information without allowing code to modify those permissions on the fly.
The pattern I came up with was to define an interface which the mutable object implements, that has read-only property getters. The mutable implementation of that interface can then be private, allowing code that directly deals with instantiating and hydrating the object to do so, but once the object is returned out of that code (as an instance of the interface) the setters are no longer accessible.
Example:
//this is what "ordinary" code uses for read-only access to user info.
public interface IUser
{
string UserName {get;}
IEnumerable<string> PermissionStrongNames {get;}
...
}
//This class is used for editing user information.
//It does not implement the interface, and so while editable it cannot be
//easily used to "fake" an IUser for authorization
public sealed class EditableUser
{
public string UserName{get;set;}
List<SecurityGroup> Groups {get;set;}
...
}
...
//this class is nested within the class responsible for login authentication,
//which returns instances as IUsers once successfully authenticated
private sealed class AuthUser:IUser
{
private readonly EditableUser user;
public AuthUser(EditableUser mutableUser) { user = mutableUser; }
public string UserName {get{return user.UserName;}}
public IEnumerable<string> PermissionNames
{
//GetPermissions is an extension method that traverses the list of nestable Groups.
get {return user.Groups.GetPermissions().Select(p=>p.StrongName);
}
...
}
A pattern like this allows you to use code you've already created in a read-write fashion, while not allowing Joe Programmer to turn a read-only instance into a mutable one. There are a few more tricks in my actual implementation, mainly dealing with persistence of the editable object (since editing user records is a secured action, an EditableUser cannot be saved with the Repository's "normal" persistence method; it instead requires calling an overload that also takes an IUser which must have sufficient permissions).
One thing you simply must understand; if it is possible for your program to edit the records in any scope, it is possible for that ability to be abused, whether intentionally or otherwise. Regular code reviews of any usage of the mutable or immutable forms of your object will be necessary to make sure other coders aren't doing anything "clever". This pattern also isn't enough to ensure that an application used by the general public is secure; if you can write an IUser implementation, so can an attacker, so you'll need some additional way to verify that your code and not an attacker's produced a particular IUser instance, and that the instance hasn't been tampered with in the interim.
I have a question concerning holding common code in a base class and having the derived class call it, even though the derived class's trigger method has been dispatched from the base. So, base->derived->base type call stack.
Is the following look OK, or does it smell? I have numbered the flow steps...
public abstract class LayerSuperType
{
public void DoSomething() // 1) Initial call from client
{
ImplementThis(); // 2) Polymorphic dispatch
}
protected abstract void ImplementThis();
protected void SomeCommonMethodToSaveOnDuplication(string key) // 4)
{
Configuration config = GetConfiguration(key);
}
}
public class DerivedOne : LayerSuperType
{
protected virtual void ImplementThis() // 2)
{
SomeCommonMethodToSaveOnDuplication("whatever"); // 3) Call method in base
}
}
public class DerivedTwo : LayerSuperType
{
protected virtual void ImplementThis() // 2)
{
SomeCommonMethodToSaveOnDuplication("something else"); // 3) Call method in base
}
}
That looks absolutely fine. Perfect example of why you'd use an abstract class over an interface. It's a bit like a strategy pattern and I have used this fairly regularly and successfully.
Make sure that what the class doing is still dealing with one 'concern' though, only doing one task. If your base class does repository access but the objects are representing documents, don't put the functionality in the base class, use a separate repository pattern/object.
Looks like a very simplified Template Method Pattern where your sub-classes do some specific kinds of things at the right points in the implementation of your algorithm, but the overall flow is directed by a method on the base class. You've also provided some services to your sub-classes in the form of base class methods; that's ok too as long as you're good as far as SOLID goes.
Why not public abstract void DoSomething() and forget about ImplementThis() altogether?
The only reason I can see to leave ImplementThis() is if you want to maintain a consistent interface with DoSomething() which later on down the road will allow the signature of ImplementThis() to change without a breaking change to callers.
I agree that you should maintain a single concern with the class's responsibility but from an overall OOP perspective this looks fine to me. I've done similar on many occasions.
It does smell a little that SomeCommonMethodToSaveOnDuplication is being called in two different ways. It seems to be doing two unrelated things. Why not have two methods?