Related
At my work, I'm trying to create more modular systems, as we tend to use similar mechanics in our games that have minor variances. To do this, I have been making use of interfaces, but have been getting stumped on certain problems, particularly ones relating to the addition of small features.
EXAMPLE:
Take for instance our evolution system. I have created the IEvolvable interface, which has a property for the evolution level and an Evolve() method.
public interface IEvolvable
{
int evolution { get; }
bool IncreaseEvolution(int numEvolutions);
}
I then have an implementation of this interface on a Character class, and based on some conditions via my Evolution handling class, I want to evolve my character.
public class EvolutionHandler
{
public IEvolvable evolvable;
public void TryEvolveCharacter
{
if(someCondition)
{
evolvable.IncreaseEvolution(1);
}
}
}
Then, later down the line, we say, we want the character to evolve based on level! Fantastic. We have an ILevellable interface which contains Level, xp, etc.
public interface ILevellable
{
int Level{ get; }
int MaxLevel{get;}
int XP {get;}
bool LevelUp(int numLevels);
}
We can use this data to control when evolution takes place based on the change in level. But here's my problem:
My evolve handler class interfaces with IEvolvable... not ILevellable... So what do I do?
I can have IEvolvable extend ILevellable or vice-versa... or I can create a new interface which extends IEvolvable and ILevellable. Now I also have to modify my evolve handler to accomodate for these changes.
But what happens if we don't want the evolve handler to take into consideration the Level anymore in our new game? Do use the old code? Was I supposed to extend my old code to include the Ilevellable interfacing?
public interface ILevelEvolver : ILevellable, IEvolvable
{
}
public class EvolutionHandler2
{
public ILevelEvolver levelEvolvable;
public void TryEvolveCharacter
{
if(levelEvolvable.Level > 10)
{
evolvable.IncreaseEvolution(1);
}
}
}
the key words are :
separate what varies from what stay the same
one of SOLID principles : open for extension closed for modification
finally in your case would use Strategy pattern :
public interface IEvilutionChecker{
bool AllowEvolution();
}
public class EvolutionCheckerA : IEvilutionChecker{
private ILevellable levelEvolvable;
public EvolutionCheckerA(ILevellable levelEvolvable){
this.levelEvolvable = levelEvolvable;
}
public bool AllowEvolution(){
return levelEvolvable.Level > 10;
}
}
public class EvolutionCheckerB : IEvilutionChecker{
private IEvolvable evolvable;
public EvolutionCheckerB(IEvolvable evolvable){
this.evolvable = evolvable;
}
public bool AllowEvolution(){
return someCondition;
}
}
public class EvolutionHandler2
{
public IEvolvable evolvable;
public IEvilutionChecker EvolutionChecker {get;set;};
public void TryEvolveCharacter
{
if(EvolutionChecker.AllowEvolution())
{
evolvable.IncreaseEvolution(1);
}
}
}
The interfaces should not extend each other. Keep them separated. Also you should keep concepts separated. By that, EvolutionHandler should only accept IEvolable.
In TryEvolveCharacter method, you can check if the property is a ILevelable.
Take a look at the code:
class EvolutionHandler
{
public IEvolable Evolable { get; set; }
public void TryEvolveCharacter()
{
if (Evolable is ILevelable levelable && levelable.Level > 10)
{
Evolable.IncreaseEvolution(1);
}
else if (someCondition)
{
Evolable.IncreaseEvolution(1);
}
}
}
so at the future, if a character extends ILevelable, that level will be considered, if not, someCondition take place.
Once you are running into these types of issues it becomes evident I think that OOP has limitations, or rather it makes some things too easy. That doesn't mean it should be scrapped entirely and something else adopted, there's a lot we can still use it for. What if rather than using the interface you make meaningful changes to directly you pass around a service interface that acts as an adapter to the internal interface.
public interface IEvolutionService {
TryEvolveCharacter(IEvolvable evolvable);
}
The concrete implementation can have something like
public void TryEvolveCharacter(IEvolvable evolvable){
if (evolvable.Level > 10) {
evolvable.IncreaseEvolution(1);
..Maybe do something new that the IEvolvable just exposed but without changing our consumed interface!
}
}
It does add code and things to make these but you have options there too, a single service can stand in for multiple interfaces, but then you are violating the Single Responsibility Principle in SOLID, and basically just making things more complex than they should in an effort at making it less complex.
You could make this a method on static class, although that interferes with testability, so I'd say refactoring and adding in a new service to handle things like service.TryEvolveCharacter(someIEvolvable). You'd still have to maintain the interface on your public facing service, but that could be more manageable than the raw interface with nothing abstracted in front of it.
I gave my answer to be as close to your question as possible, but to me it is still less than ideal. I would consider having immutable structs (which can have interfaces, and also stick to the L2 CPU cache) for the data and passing those to services (which would be pure functions, that is to say stateless, they only deal with what is passed in). If you are writing game code and performance is an issue then that's going to be very useful.
If you were only using games as a metaphor maybe less so :)
A helpful article on structs, L2, and performance
In many cases, having an interface that includes members which would be meaningful for some implementations but not others can be a better pattern than trying to use different interfaces for different combinations of functionality. As a simple example, if Java or .NET had included in their basic enumerable interface a function to report a count if available, along with one to indicate if and how the count would be performed, then a wrapper class that concatenates two enumerations could efficiently report how many elements were in the combined enumeration if the constituent enumerations supported a count function, and could also let clients know whether its count function would be efficient and/or cacheable.
Another pattern that can be useful is for an interface to include asXX function which a class may implement as either returning a reference to itself (if it supports XX functionality) or constructing a wrapper object of suitable type. If XX is a wrapper-class type, functionality may be added to the wrapper class without having to change the interface that includes the asXX member or implementations thereof.
I'm writing a CAD program. Let's say I have in input class, this class reads various data from a text file and creates lots of lists/dictionaries and .... These data need to be accessed by other methods in other classes to be modified. Now here is how I have done it so far:
I have one static class: Building.cs When I create/or load a project this class holds all the data like list of columns, beams, points, etc. All of these are stored as private fields. I can access these using the class's public methods like GetColumns or GetPoints ...
Now I also have non-static classes. They contain 2-3 public methods. and do some stuff on various parts of the building.
public static class Building
{
private static List<Column> columns;
private static List<Beams> beams;
private static List<Points> points;
public static List<Column> GetColumns()
{
return Columns;
}
}
public class ColumnsService()
{
private List<Columns> columns;
public GroupColumns(List<Columns> columns)
{
this.columns = columns;
}
public void Group()
{
// group columns
}
}
var columns = Building.GetColumns();
var columnsService = new ColumnsService(columns);
columnsService.Group();
I was wondering is this the way to go? How else can I store the data. The data needs to be accessible throughout the lifetime of the program to most of the classes. What are the best practices.
What, semantically, is a Building?
To me, the name implies that it's an instance of a structure. That, in the overall business domain, there can be many "buildings" and at any given moment one is interacting with one of them.
If that's the case, then it seems unintuitive to me to make it static. If there's more than one, it should be an instance model. It would contain attributes which describe it and operations which interact with it. The business domain being modeled should drive the structure of this object before any consideration is given to how other objects are going to interact with it.
So let's assume we make it an instance model:
public class Building
{
// attributes and operations
}
Then, as you ask, how do other objects interact with it?
Depends on the interactions.
Let's say an object needs to "render" a building in some way. Let's call it BuildingPrinter for lack of a better term. Clearly it needs a Building to "print". So it requires one for that operation:
public class BuildingPrinter
{
public void Print(Building building)
{
// implementation
}
}
Or perhaps you have an object which "wraps" a building in some way. Something which can't meaningfully exist without a building, regardless of the operations performed. I can't think of one for that particular business domain, so let's just call it a BuildingWidget. Since it needs a building to exist at all, it requires one:
public class BuildingWidget
{
private Building currentBuilding;
private BuildingWidget() { }
public BuildingWidget(Building building)
{
currentBuilding = building;
}
}
The point is, from the perspective of the models which construct the overall domain, if something is required then it must be supplied. The models shouldn't go out to some global data store, tightly coupling with that data store, to get what they need. This is called the Dependency Inversion Principle.
But where will the consuming code which orchestrates the interactions of these models get instances of a Building? There are a number of potential solutions to that.
Two common patterns would be to have a static factory or a repository. For example:
public class BuildingFactory
{
public static Building FetchBuilding(int buildingId)
{
// implementation
}
}
This factory might have a static cached building object. The building itself isn't static, but for performance reasons an instance of it is cached statically so that it's not constantly re-fetched from a backing data store (such as a database). You might also add methods to invalidate the cache and re-fetch, or encapsulate that logic into the factory itself (such as always re-fetch after 5 minutes or after 10 accesses or some other rule). (Behind the scenes, this factory might even use a repository, shown below, to re-fetch that instance. In which case, you guessed it, a BuildingRepository would be required on the BuildingFactory constructor.)
This factory object may also be responsible for creating a building based on some specifications, if for example you have reason to make the Building constructor private.
Or, to re-fetch from data, consider a repository:
public class BuildingRepository
{
public Building GetBuilding(int buildingId)
{
// fetch from database
}
public Building SaveBuilding(Building building)
{
// save to database, return updated version
}
}
Then other code throughout the domain, including the consuming code, can use these objects to get/save buildings. The factory is static, so that can be invoked anywhere. The repository is instance but doesn't need to be globally distinct, so that can be instantiated anywhere (or pulled form a dependency injection container).
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.
In order to separate concerns, on my current project, I've decided to completely separate my DAL and BLL/Business objects in separate assemblies. I would like to keep my business objects as simple structures without any logic to keep things extremely simple. I would like if I could keep my Business Logic separate from my DAL also. So my application will tell my DAL to load my objects, my DAL will run off to the database and get the data, populate the object with the data and then pass it back to my BLL.
Question - how can I have my DAL in a separate assembly and push data into the read only fields?
If I set the getter as protected then inherited objects can access it which isn't really what I want as I'd be returning the inherited object types, not the original object types.
If I set the getter as internal, then my DAL must reside in the same assembly as my BLL which I don't want.
If I set the getter as public, then anyone can read/write to it when it should be read only.
Edit: I note that I can have a return type of ObjectBase but actually be returning an object or collection of objects that are derived form ObjectBase so to the outside world (outside my DAL) the properties would be read-only, but my derived types (only accessible inside my DAL) the properties are actually read/write.
You can set the read only property via a constructor.
This is a situation without a silver-bullet; the simplest options are limited or don't meet your requirements and the thorough solutions either begin to have smells or begin to veer away from simplicity.
Perhaps the simplest option is one that I haven't seen mentioned here: keeping the fields / properties private and passing them as out / ByRef parameters to the DAL. While it wouldn't work for large numbers of fields it would be simple for a small number.
(I haven't tested it, but I think it's worth exploring).
public class MyObject()
{
private int _Id;
public int Id { get { return _Id; } } // Read-only
public string Name { get; set; }
// This method is essentially a more descriptive constructor, using the repository pattern for seperation of Domain and Persistance
public static MyObject GetObjectFromRepo(IRepository repo)
{
MyObject result = new MyObject();
return repo.BuildObject(result, out _Id);
}
}
public class MyRepo : IRepository
{
public MyObject BuildObject(MyObject objectShell, out int id)
{
string objectName;
int objectId;
// Retrieve the Name and Value properties
objectName = "Name from Database";
objectId = 42;
//
objectShell.Name = objectName;
Console.WriteLine(objectShell.Id); // <-- 0, as it hasn't been set yet
id = objectId; // Setting this out parameter indirectly updates the value in the resulting object
Console.WriteLine(objectShell.Id); // <-- Should now be 42
}
}
It's also worth noting that trying to keep your domain / business objects to the bare-minimum can involve more than you think. If you intend to databind to them then you'll need to implement IPropertyNotifyChanged, which prevents you from using automatically-implemented properties. You should be able to keep it fairly clean, but you will have to make some sacrifices for basic functionality.
This keeps your SoC model nicely, it doesn't add in too much complexity, it prevents writing to read-only fields and you could use a very similar model for serialization concerns. Your read-only fields can still be written to by your DAL, as could your serializer if used in a similar fashion - it means that conscious effort must be taken by a developer to write to a read-only field which prevents unintentional misuse.
Model Project
namespace Model
{
public class DataObject
{
public int id { get; protected set; }
public string name { get; set; }
}
}
Data Project
namespace Data
{
class DALDataObject : DataObject
{
public DALDataObject(int id, string name)
{
this.id = id;
this.name = name;
}
}
public class Connector
{
public static DataObject LoadDataObject(int objectId)
{
return new DALDataObject(objectId, string.Format("Dummy object {0}", objectId));
}
public static IEnumerable<DataObject> LoadDataObjects(int startRange, int endRange)
{
var list = new List<DataObject>();
for (var i = startRange; i < endRange; i++)
list.Add(new DALDataObject(i, string.Format("Dummy object {0}", i)));
return list;
}
}
}
How about just live with it?
Implement with those guidelines, but don't add such a hard constraint in your model. Lets say you do so, but then come another req where you need to serialize it or do something else, and then you are tied with it.
As you said in other comment, you want pieces that are interchangeable ... so, basically you don't want something that's tied into specific relations.
Update 1: Perhaps "just live with it" was too simplistic, but I still have to stress out that you shouldn't go too deep into these things. Using simple guidelines, keeping your code clean and SOLID its the best you can do at the beginning. It won't get in the way of progress while refactoring when everything is more settled isn't hard.
Make no mistake, I am not at all a person that goes writing code without any thinking on it. But, I have gone with such approaches and only in a handful cases they pay off --- without any indication that you wouldn't have a similar result by going simple and evolving it.
IMHO this one does not fit into important architecture concerns that need to be addressed at the very beginning.
Pre-emptive follow up: beware if you can't trust your team into following simple guidelines. Also make sure to begin with some structure, pick a couple scenarios that set a structure in with real stuff, the team will know their way much better when there is something simple there.
In my opinion, the best way to handle this is to have the business objects and the DAL in the same assembly separated by namespace. This separates the concerns logically and allows you to use internal setters. I can't think of any benefit to separating them into their own assemblies because one is useless without the other.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have over the course of a few projects developed a pattern for creating immutable (readonly) objects and immutable object graphs. Immutable objects carry the benefit of being 100% thread safe and can therefore be reused across threads. In my work I very often use this pattern in Web applications for configuration settings and other objects that I load and cache in memory. Cached objects should always be immutable as you want to guarantee they are not unexpectedly changed.
Now, you can of course easily design immutable objects as in the following example:
public class SampleElement
{
private Guid id;
private string name;
public SampleElement(Guid id, string name)
{
this.id = id;
this.name = name;
}
public Guid Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
}
This is fine for simple classes - but for more complex classes I do not fancy the concept of passing all values through a constructor. Having setters on the properties is more desirable and your code constructing a new object gets easier to read.
So how do you create immutable objects with setters?
Well, in my pattern objects start out as being fully mutable until you freeze them with a single method call. Once an object is frozen it will stay immutable forever - it cannot be turned into a mutable object again. If you need a mutable version of the object, you simply clone it.
Ok, now on to some code. I have in the following code snippets tried to boil the pattern down to its simplest form. The IElement is the base interface that all immutable objects must ultimately implement.
public interface IElement : ICloneable
{
bool IsReadOnly { get; }
void MakeReadOnly();
}
The Element class is the default implementation of the IElement interface:
public abstract class Element : IElement
{
private bool immutable;
public bool IsReadOnly
{
get { return immutable; }
}
public virtual void MakeReadOnly()
{
immutable = true;
}
protected virtual void FailIfImmutable()
{
if (immutable) throw new ImmutableElementException(this);
}
...
}
Let's refactor the SampleElement class above to implement the immutable object pattern:
public class SampleElement : Element
{
private Guid id;
private string name;
public SampleElement() {}
public Guid Id
{
get
{
return id;
}
set
{
FailIfImmutable();
id = value;
}
}
public string Name
{
get
{
return name;
}
set
{
FailIfImmutable();
name = value;
}
}
}
You can now change the Id property and the Name property as long as the object has not been marked as immutable by calling the MakeReadOnly() method. Once it is immutable, calling a setter will yield an ImmutableElementException.
Final note:
The full pattern is more complex than the code snippets shown here. It also contains support for collections of immutable objects and complete object graphs of immutable object graphs. The full pattern enables you to turn an entire object graph immutable by calling the MakeReadOnly() method on the outermost object. Once you start creating larger object models using this pattern the risk of leaky objects increases. A leaky object is an object that fails to call the FailIfImmutable() method before making a change to the object. To test for leaks I have also developed a generic leak detector class for use in unit tests. It uses reflection to test if all properties and methods throw the ImmutableElementException in the immutable state.
In other words TDD is used here.
I have grown to like this pattern a lot and find great benefits in it. So what I would like to know is if any of you are using similar patterns? If yes, do you know of any good resources that document it? I am essentially looking for potential improvements and for any standards that might already exist on this topic.
For info, the second approach is called "popsicle immutability".
Eric Lippert has a series of blog entries on immutability starting here. I'm still getting to grips with the CTP (C# 4.0), but it looks interesting what optional / named parameters (to the .ctor) might do here (when mapped to readonly fields)...
[update: I've blogged on this here]
For info, I probably wouldn't make those methods virtual - we probably don't want subclasses being able to make it non-freezable. If you want them to be able to add extra code, I'd suggest something like:
[public|protected] void Freeze()
{
if(!frozen)
{
frozen = true;
OnFrozen();
}
}
protected virtual void OnFrozen() {} // subclass can add code here.
Also - AOP (such as PostSharp) might be a viable option for adding all those ThrowIfFrozen() checks.
(apologies if I have changed terminology / method names - SO doesn't keep the original post visible when composing replies)
Another option would be to create some kind of Builder class.
For an example, in Java (and C# and many other languages) String is immutable. If you want to do multiple operations to create a String you use a StringBuilder. This is mutable, and then once you're done you have it return to you the final String object. From then on it's immutable.
You could do something similar for your other classes. You have your immutable Element, and then an ElementBuilder. All the builder would do is store the options you set, then when you finalize it it constructs and returns the immutable Element.
It's a little more code, but I think it's cleaner than having setters on a class that's supposed to be immutable.
After my initial discomfort about the fact that I had to create a new System.Drawing.Point on each modification, I've wholly embraced the concept some years ago. In fact, I now create every field as readonly by default and only change it to be mutable if there's a compelling reason – which there is surprisingly rarely.
I don't care very much about cross-threading issues, though (I rarely use code where this is relevant). I just find it much, much better because of the semantic expressiveness. Immutability is the very epitome of an interface which is hard to use incorrectly.
You are still dealing with state, and thus can still be bitten if your objects are parallelized before being made immutable.
A more functional way might be to return a new instance of the object with each setter. Or create a mutable object and pass that in to the constructor.
The (relatively) new Software Design paradigm called Domain Driven design, makes the distinction between entity objects and value objects.
Entity Objects are defined as anything that has to map to a key-driven object in a persistent data store, like an employee, or a client, or an invoice, etc... where changing the properties of the object implies that you need to save the change to a data store somewhere, and the existence of multiple instances of a class with the same "key" imnplies a need to synchronize them, or coordinate their persistence to the data store so that one instance' changes do not overwrite the others. Changing the properties of an entity object implies you are changing something about the object - not changing WHICH object you are referencing...
Value objects otoh, are objects that can be considered immutable, whose utility is defined strictly by their property values, and for which multiple instances, do not need to be coordinated in any way... like addresses, or telephone numbers, or the wheels on a car, or the letters in a document... these things are totally defined by their properties... an uppercase 'A' object in an text editor can be interchanged transparently with any other uppercase 'A' object throughout the document, you don't need a key to distinguish it from all the other 'A's In this sense it is immutable, because if you change it to a 'B' (just like changing the phone number string in a phone number object, you are not changing the data associated with some mutable entity, you are switching from one value to another... just as when you change the value of a string...
Expanding on the point by #Cory Foy and #Charles Bretana where there is a difference between entities and values. Whereas value-objects should always be immutable, I really don't think that an object should be able to freeze themselves, or allow themselves to be frozen arbitrarily in the codebase. It has a really bad smell to it, and I worry that it could get hard to track down where exactly an object was frozen, and why it was frozen, and the fact that between calls to an object it could change state from thawed to frozen.
That isn't to say that sometimes you want to give a (mutable) entity to something and ensure it isn't going to be changed.
So, instead of freezing the object itself, another possibility is to copy the semantics of ReadOnlyCollection< T >
List<int> list = new List<int> { 1, 2, 3};
ReadOnlyCollection<int> readOnlyList = list.AsReadOnly();
Your object can take a part as mutable when it needs it, and then be immutable when you desire it to be.
Note that ReadOnlyCollection< T > also implements ICollection< T > which has an Add( T item) method in the interface. However there is also bool IsReadOnly { get; } defined in the interface so that consumers can check before calling a method that will throw an exception.
The difference is that you can't just set IsReadOnly to false. A collection either is or isn't read only, and that never changes for the lifetime of the collection.
It would be nice at time to have the const-correctness that C++ gives you at compile time, but that starts to have it's own set of problems and I'm glad C# doesn't go there.
ICloneable - I thought I'd just refer back to the following:
Do not implement ICloneable
Do not use ICloneable in public APIs
Brad Abrams - Design Guidelines, Managed code and the .NET Framework
System.String is a good example of a immutable class with setters and mutating methods, only that each mutating method returns a new instance.
This is an important problem, and I've love to see more direct framework/language support to solve it. The solution you have requires a lot of boilerplate. It might be simple to automate some of the boilerplate by using code generation.
You'd generate a partial class that contains all the freezable properties. It would be fairly simple to make a reusable T4 template for this.
The template would take this for input:
namespace
class name
list of property name/type tuples
And would output a C# file, containing:
namespace declaration
partial class
each of the properties, with the corresponding types, a backing field, a getter, and a setter which invokes the FailIfFrozen method
AOP tags on freezable properties could also work, but it would require more dependencies, whereas T4 is built into newer versions of Visual Studio.
Another scenario which is very much like this is the INotifyPropertyChanged interface. Solutions for that problem are likely to be applicable to this problem.
My problem with this pattern is that you're not imposing any compile-time restraints upon immutability. The coder is responsible for making sure an object is set to immutable before for example adding it to a cache or another non-thread-safe structure.
That's why I would extend this coding pattern with a compile-time restraint in the form of a generic class, like this:
public class Immutable<T> where T : IElement
{
private T value;
public Immutable(T mutable)
{
this.value = (T) mutable.Clone();
this.value.MakeReadOnly();
}
public T Value
{
get
{
return this.value;
}
}
public static implicit operator Immutable<T>(T mutable)
{
return new Immutable<T>(mutable);
}
public static implicit operator T(Immutable<T> immutable)
{
return immutable.value;
}
}
Here's a sample how you would use this:
// All elements of this list are guaranteed to be immutable
List<Immutable<SampleElement>> elements =
new List<Immutable<SampleElement>>();
for (int i = 1; i < 10; i++)
{
SampleElement newElement = new SampleElement();
newElement.Id = Guid.NewGuid();
newElement.Name = "Sample" + i.ToString();
// The compiler will automatically convert to Immutable<SampleElement> for you
// because of the implicit conversion operator
elements.Add(newElement);
}
foreach (SampleElement element in elements)
Console.Out.WriteLine(element.Name);
elements[3].Value.Id = Guid.NewGuid(); // This will throw an ImmutableElementException
Just a tip to simplify the element properties: Use automatic properties with private set and avoid explicitly declaring the data field. e.g.
public class SampleElement {
public SampleElement(Guid id, string name) {
Id = id;
Name = name;
}
public Guid Id {
get; private set;
}
public string Name {
get; private set;
}
}
Here is a new video on Channel 9 where Anders Hejlsberg from 36:30 in the interview starts talking about immutability in C#. He gives a very good use case for popsicle immutability and explains how this is something you are currently required to implement yourself. It was music to my ears hearing him say it is worth thinking about better support for creating immutable object graphs in future versions of C#
Expert to Expert: Anders Hejlsberg - The Future of C#
Two other options for your particular problem that haven't been discussed:
Build your own deserializer, one that can call a private property setter. While the effort in building the deserializer at the beginning will be much more, it makes things cleaner. The compiler will keep you from even attempting to call the setters and the code in your classes will be easier to read.
Put a constructor in each class that takes an XElement (or some other flavor of XML object model) and populates itself from it. Obviously as the number of classes increases, this quickly becomes less desirable as a solution.
How about having an abstract class ThingBase, with subclasses MutableThing and ImmutableThing? ThingBase would contain all the data in a protected structure, providing public read-only properties for the fields and protected read-only property for its structure. It would also provide an overridable AsImmutable method which would return an ImmutableThing.
MutableThing would shadow the properties with read/write properties, and provide both a default constructor and a constructor that accepts a ThingBase.
Immutable thing would be a sealed class that overrides AsImmutable to simply return itself. It would also provide a constructor that accepts a ThingBase.
I dont like the idea of being able to change an object from a mutable to an immutable state, that kind of seems to defeat the point of design to me. When are you needing to do that? Only objects which represent VALUES should be immutable
You can use optional named arguments together with nullables to make an immutable setter with very little boilerplate. If you really do want to set a property to null then you may have some more troubles.
class Foo{
...
public Foo
Set
( double? majorBar=null
, double? minorBar=null
, int? cats=null
, double? dogs=null)
{
return new Foo
( majorBar ?? MajorBar
, minorBar ?? MinorBar
, cats ?? Cats
, dogs ?? Dogs);
}
public Foo
( double R
, double r
, int l
, double e
)
{
....
}
}
You would use it like so
var f = new Foo(10,20,30,40);
var g = f.Set(cat:99);