Ensure derived class does not refer to properties in the base class - c#

Purpose
How do I through any method, for the purposes of a unit test, make sure that a derived class does not refer to any properties in the base class? I understand that Reflection won't cut it, here. Could I create a mock of the base class somehow and observe if a property is called at the wrong time? Or any other way?
Background
I have a series of classes that are participating in serialization. There is a natural hierarchy of parts and pieces, so that for example, a Chunk1 knows how to serialize itself (starting, ending, delimiters) but will delegate the serialization of its inner parts to a Blob that itself serializes several lines.
Here is the interface that all the parts implement:
public interface ICoolSerializable {
void Serialize(Writer w);
}
And given this desired serialization result:
Chunk1:/Line1
/Line2
There is a Chunk1 class that is responsible for "Chunk1:" and inherits from the Blob class, which in turn is responsible for "/Line1", the newline, and "/Line2". (Both implement ISerializable.)
Note: please assume for the sake of the question that I truly do want an is-a relationship, and it is correct for the Chunk1 to inherit from the Blob (the Blob can be used in many different chunks, and the Chunk1 just determines how the Blob is interpreted, but not how it is serialized beyond the initial label).
The Problem
I see a potential gotcha for me or another developer in the future writing more classes like this and attempting to copy the pattern. Since the constructor of Chunk1 accepts an IEnumerable of Line items to pass to its base Blob, the developer will have in mind how the base is constructed, and might easily make this mistake in the Chunk1 serialize method:
public override void Serialize(Writer w) {
w.Write("Chunk1:");
w.WriteEnumerable(Lines); // wrong, this is a forbidden base.Lines!
}
This would yield the wrong serialization result (missing the slashes):
Chunk1:Line1
Line2
Full disclosure: I did make this mistake, and then initially "fixed" it by writing "/" before each Line from the derived class. Of course, the moment another class inherited from the base, it also was missing the slashes—I'd fixed it the wrong way.
The Question
So how can I inspect the Serialize method or take any other measure to ensure that base.Lines is never accessed from within it? Instead of the wrong way above, it needs to work like this:
public override void Serialize(Writer w) {
w.Write("Chunk1:");
base.Serialize(w); // Remember to let the superclass decide how to serialize itself
}
This pattern is not global throughout. Not all classes implementing my ICoolSerializable interface have sub-parts, nor do all of them inherit from anything else. In some cases, it may make sense to wrap another class instead of subclass from it.
Some Thoughts
For those interested, since strings are implicitly convertible to ICoolSerializable, I wish I could do this:
public override void Serialize(Writer w) {
w.WriteCoolSerializables,
"Chunk1:",
base
}
}
However, base here cannot refer to the base instance, and if I cast the current class as its parent, it still wouldn't work because the derived Serialize method (it's override!) would be called and thus cause a loop, eventually resulting in a stack overflow.
Update
I suspect that the right answer will be refactoring, but I'm not sure how that refactoring will work right now. I suspect that I may lean more heavily on Reflection, and on the serialization process working through properties or a returned series of property-or-value-accessing objects, rather than on a procedural statement. This would enable the property-accessing-objects to be inspected to see what they're referring to. This could also enable the parent class to indicate (through attributes or an attribute-like method that returns information) how it relates to any child class, a sort of template that says "the child class may only hook onto my serialization components at the head", which can then be enforced.

In this case I wouldn't make your Serialize method inheritable.
protected void SerializeCore(Writer w) { }
public void Serialize(Writer w) {
SerializeCore(w);
...
}
This way you control how your base class is serialised. If you want to be stricter you could use reflection with attributes to perform serialisation.
Example base class for the attributes:
public abstract class CustomSerializeAttribute : Attribute
{
public abstract void SerializeProperty(Writer w, object value);
}

Make the properties in the base class private.

If you are willing to wrap the functionality provided by your properties with functions, you could check the caller's source file against a blacklist or whitelist of which files can't/can contain code that accesses those properties.
Within the Blob implementation, for each property (wrapper) you want to monitor you can do something along these lines:
public int GetExampleProp([System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "")
{
CheckCaller(sourceFilePath);
return ExampleProp;
}
public void SetExampleProp(int value, [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "")
{
CheckCaller(sourceFilePath);
ExampleProp = value;
}
and then check if the call is valid in CheckCaller
private void CheckCaller(string path)
{
if (!_whitelist.Contains(path)) {
// report error
}
}

Related

C#: Force constructor signature using abstract class?

I've been searching for a while on this because I'm naturally forgetful and I thought it would be nice to build something (an abstract class, interface, etc.?) that would force me to implement certain bits of code in a class I was writing.
In particular, I would like to force a new class to always have a constructor that takes a single parameter typed as itself in order to make duplication of the object easier. I've seen articles/questions elsewhere that talk about this, but I'm not sure this particular question has been asked (at least that I can find) or I'm simply not understanding enough of the other articles/questions to realize it. My apologies in advance.
I'm not interested in having a constructor in an abstract class, interface, etc. actually do anything. I'm merely interested in defining the requirement for a constructor signature in a derived class.
My ideal class would look like this:
public class GoodClass
{
public GoodClass(GoodClass goodClass)
{
// copy components of goodClass to this instance
}
}
So, I first began researching interfaces and also started reading up on abstract classes. I was thinking something like the code below would work, but alas I get errors. Is what I'm trying to do even possible? Is there any other way I could accomplish my goal without putting a sticky note on my monitor? :)
abstract class SelfConstructor
{
abstract public SelfConstructor(SelfConstructor) { }
}
class NewClass : SelfConstructor
{
//Required by SelfConstructor:
public NewClass(NewClass newClass)
{
// copy components of newClass to this instance
}
}
You could write a ReSharper plugin that recognises this case and highlights the class if it doesn't have a "copy constructor". This would be a daemon stage that would process the file as it's being edited, and add highlights. You can look through the abstract syntax tree of the file, look for all instances of IConstructorDeclaration, and then get the constructor's parameters from the ParameterDeclarations property. You can check that there is a constructor that only has one parameter, and that parameter is the same type as the class it's declared in.
You can compare the types by getting the constructor's parameter's TypeUsage and trying to downcast to IUserTypeUsage. You can then use ScalarTypeName.Reference.Resolve() to get an instance of IDeclaredElement. Compare this against the class's IClassDeclaration.DeclaredElement to see if they're the same instance.
In C++, what you are talking about is a copy constructor, you actually get one by default!
C# doesn't have that concept (though of course you can define one); however, it is easier (and preferred) to simply implement ICloneable (MSDN), which requires you to implement the Clone method, that does the same thing.
Instead of:
object myObj = new CloneableObject(otherObj);
You write:
object myObj = otherObj.Clone();
The other thing you could do is force a constructor signature by not having a default:
public class BaseClass
{
//No abstract constructors!
public BaseClass(BaseClass copy)
{
}
}
Now when you derive, you have to use that overload in the constructor. Nothing will force the derived signature, but at least you have to explicitly use it:
public class DerivedClass : BaseClass
{
public DerivedClass() : base(this)
{
}
}
The above example clearly shows that it doesn't "force" you to have a copy constructor, but like a sticky note, would serve as a good reminder.
I would definitely go the interface route, as that is what is there for (and you can use an abstract implementation!).
Note that you can take advantage of Object.MemberwiseClone if you want a shallow copy for free. All objects get this, no interface required.

ReadOnlyCollection vs Liskov - How to correctly model immutable representations of a mutable collection

Liskov-substitution principle requires that subtypes must satisfy the contracts of super-types. In my understanding, this would entail that ReadOnlyCollection<T> violates Liskov. ICollection<T>'s contract exposes Add and Remove operations, but the read only subtype does not satisfy this contract. For example,
IList<object> collection = new List<object>();
collection = new System.Collections.ObjectModel.ReadOnlyCollection<object>(collection);
collection.Add(new object());
-- not supported exception
There is clearly a need for immutable collections. Is there something broken about .NET's way of modeling them? What would be the better way to do it? IEnumerable<T> does a good job of exposing a collection while, at least, appearing to be immutable. However, the semantics are very different, primarily because IEnumerable doesn't explicitly expose any of state.
In my particular case, I am trying to build an immutable DAG class to support an FSM. I will obviously need AddNode / AddEdge methods at the beginning but I don't want it to be possible to change the state machine once it is already running. I'm having difficulty representing the similarity between the immutable and mutable representations of the DAG.
Right now, my design involves using a DAG Builder up front, and then creating the immutable graph once, at which point it is no longer editable. The only common interface between the Builder and the concrete immutable DAG is an Accept(IVisitor visitor). I'm concerned that this may be over-engineered / too abstract in the face of possibly simpler options. At the same time, I'm having trouble accepting that I can expose methods on the my graph interface that may throw NotSupportedException if the client gets a particular implementation. What is the right way to handle this?
You could always have a (read-only) graph interface, and extend it with a read/write modifiable-graph interface:
public interface IDirectedAcyclicGraph
{
int GetNodeCount();
bool GetConnected(int from, int to);
}
public interface IModifiableDAG : IDirectedAcyclicGraph
{
void SetNodeCount(int nodeCount);
void SetConnected(int from, int to, bool connected);
}
(I can't figure out how to split these methods into get/set halves of a property.)
// Rubbish implementation
public class ConcreteModifiableDAG : IModifiableDAG
{
private int nodeCount;
private Dictionary<int, Dictionary<int, bool>> connections;
public void SetNodeCount(int nodeCount) {
this.nodeCount = nodeCount;
}
public void SetConnected(int from, int to, bool connected) {
connections[from][to] = connected;
}
public int GetNodeCount() {
return nodeCount;
}
public bool GetConnected(int from, int to) {
return connections[from][to];
}
}
// Create graph
IModifiableDAG mdag = new ConcreteModifiableDAG();
mdag.SetNodeCount(5);
mdag.SetConnected(1, 5, true);
// Pass fixed graph
IDirectedAcyclicGraph dag = (IDirectedAcyclicGraph)mdag;
dag.SetNodeCount(5); // Doesn't exist
dag.SetConnected(1, 5, true); // Doesn't exist
This is what I wish Microsoft had done with their read-only collection classes - made one interface for get-count, get-by-index behaviour etc., and extend it with an interface to add, change values etc.
I don't think that your current solution with the builder is overengineered.
It solves two problems:
Violation of LSP
You have an editable interface whose implementations will never throw NotSupportedExceptions on AddNode / AddEdge and you have a non-editable interface that doesn't have these methods at all.
Temporal coupling
If you would go with one interface instead of two, that one interface would need to somehow support the "initialization phase" and the "immutable phase", most likely by some methods marking the start and possibly end of those phases.
Read only collections in .Net do not go against LSP.
You seem bothered by the read only collection throwing a not supported exception if the add method is called, but there is nothing exceptional about it.
A lot of classes represent domain objects that can be in one of several states and not every operation is valid in all states: streams can only be opened once, windows cannot be shown after they are disposed, etc..
Throwing exceptions in those cases is valid as long as there is a way to test the current state and avoid the exceptions.
The .Net collections were engineered to support the states: read-only and read/write. Which is why the method IsReadWrite is present. It allows callers to test the state of the collection and avoid exceptions.
LSP requires subtypes to honor the contract of the super type, but a contract is more than just a list of methods; it is a list of inputs and expected behavior based on the state of the object:
"If you give me this input, when I'm in this state expect this to happen."
ReadOnlyCollection fully honors the contract of ICollection by throwing a not supported exception when the state of the collection is read only. See the exceptions section in the ICollection documentation.
You can use explict interface implementations to separate your modification methods from the operations needed in the read-only version. Also on your read-only implementation have a method that takes a method as an argument. This allows you to isolate your building of the DAC from the navigation and querying. see the code below and its comments:
// your read only operations and the
// method that allows for building
public interface IDac<T>
{
IDac<T> Build(Action<IModifiableDac<T>> f);
// other navigation methods
}
// modifiable operations, its still an IDac<T>
public interface IModifiableDac<T> : IDac<T>
{
void AddEdge(T item);
IModifiableDac<T> CreateChildNode();
}
// implementation explicitly implements IModifableDac<T> so
// accidental calling of modification methods won't happen
// (an explicit cast to IModifiable<T> is required)
public class Dac<T> : IDac<T>, IModifiableDac<T>
{
public IDac<T> Build(Action<IModifiableDac<T>> f)
{
f(this);
return this;
}
void IModifiableDac<T>.AddEdge(T item)
{
throw new NotImplementedException();
}
public IModifiableDac<T> CreateChildNode() {
// crate, add, child and return it
throw new NotImplementedException();
}
public void DoStuff() { }
}
public class DacConsumer
{
public void Foo()
{
var dac = new Dac<int>();
// build your graph
var newDac = dac.Build(m => {
m.AddEdge(1);
var node = m.CreateChildNode();
node.AddEdge(2);
//etc.
});
// now do what ever you want, IDac<T> does not have modification methods
newDac.DoStuff();
}
}
From this code, the user can only call Build(Action<IModifiable<T>> m) to get access to a modifiable version. and the method call returns an immutable one. There is no way to access it as IModifiable<T> without an intentional explicit cast, which isn't defined in the contract for your object.
The way I like it (but maybe that's just me), is to have the reading methods in an interface and the editing methods in the class itself. For your DAG, it is highly unlikely that you will have multiple implementations of the data structure, so having an interface to edit the graph is kind of an overkill and usually not very pretty.
I find having the class representing the data-structure and the interface being the reading structure pretty clean.
for instance:
public interface IDAG<out T>
{
public int NodeCount { get; }
public bool AreConnected(int from, int to);
public T GetItem(int node);
}
public class DAG<T> : IDAG<T>
{
public void SetCount(...) {...}
public void SetEdge(...) {...}
public int NodeCount { get {...} }
public bool AreConnected(...) {...}
public T GetItem(...) {...}
}
Then, when you require editing the structure, you pass the class, if you just need the readonly structure, pass the interface. It's a fake 'read-only' because you can always cast as the class, but read-only is never real anyway...
This allows you to have more complex reading structure. As in Linq, you can then extend your reading structure with extension methods defined on the interface. For instance:
public static class IDAGExtensions
{
public static List<T> FindPathBetween(this IDAG<T> dag, int from, int to)
{
// Use backtracking to determine if a path exists between `from` and `to`
}
public static IDAG<U> Cast<U>(this IDAG<T> dag)
{
// Create a wrapper for the DAG class that casts all T outputs as U
}
}
This is extremely useful to separate the definition of the datastructure from 'what you can do with it'.
The other thing that this structure allows is to set the generic type as out T. That allows you to have contravariance of argument types.
I like the idea of designing my data structures immutable in the first place. Sometimes it's just not feasible but there's a way to accomplish this quite often.
For your DAG you most probably have some data structure in a file or a user interface and you could pass all the nodes and edges as IEnumerables to your immutable DAG class' constructor. Then you can use the Linq methods to transform your source data to nodes and edges.
The constructor (or a factory method) can then build the class' private structures in a way that's efficient for your algorithm and do upfront data validations like acyclicy.
This solution distinguishes from the builder pattern in a way that iterative construction of the data structure is not possible but often that's not really required.
Personally, I don't like the solutions with separate interfaces for read and read/write access implemented by the same class because the write functionality is not really hidden... casting the instance to the read/write interface exposes the mutating methods. The better solution in such a scenario is having an AsReadOnly method that creates a really immutable data structure copying the data.

c# practices for correct object oriented techniques

I have some c# code that has been working well for a while now.. and I have to say, whilst I understand the basics of OO principles, there is obviously more than one way to skin a cat (although I hate that phrase!).
So, I have a base abstract class that is acting as a basic data service class as follows (much simplified just for ease of reading):
public abstract class dataservice
{
public enum OutputType : int { XmlTOJson = 0, Xml = 1, Json=2 }
protected object SomeDBcall(string StoredProcedure)
{
// Just assume we are using SQLclient/DB access..
object SomeReturnObjValue = db.ExecuteScalar(cmd);
return SomeReturnObjValue;
{
}
.. so basically I might have a few basic DB retrieve/update/delete calls in the abstract class.. mainly as there are the basis of any DB operation I have in my app.
So now we have a class that implements the base class, say in my case a customer class:
public class Customer : dataservice
{
Public String CustomerDoSomething(string SomeDataEtc)
{
// Ok, so again for simplicity sake, we are going to use the base class to
// call a DB retrieve
object ReturningObj = SomeDBcall("my stored procedure");
return ReturningObj.ToString();
}
}
So I guess my question is this: Is the above method "ok" to use? considering a virtual method could be over-ridden if required, however in this case I only want the base class to use those methods which are protected as the means to call the DB operations.
Any clarity/guidance very appreciated!
Sure, it's "ok", though I see no reason for the base class to be abstract. abstract classes are great for implementing some common logic and leaving the rest up to derived classes to implement. However, you have no abstract/virtual methods, so I don't see the point here.
Perhaps you can let your abstract class be concrete and use it as some kind of helper class which handles the database related stuff you need. As far as the example code shows, there is no need to have multiple database accessing classes, just different parameters.
Overview
Many times, your "development itself will guide you".
Practical answer.
(1) You define a base class "dataservice", and from that class, several other classes will be based upon. You marked as "abstract", thats good. It's not mean to have variables by itself.
Some developers won't mark that class as "abstract", its not obligatory, but, its a not a bad idea, but, its a "good practice", to marked "abstract".
And, other methods will be added, used by the subclasses, maybe overriden, maybe not.
For know, those methods are protected, and anot mean to be used outside the object, but, by other methods. That's ok.
Maybe, later, a method may be required to be used outside the class, and may have to change to public.
(2) You add a subclass "Customer" that is a descendant from "DataService" You add a method that has to be used outside the class, and marked as "public", good.
It's only meant to be used by this class, not the parent class. So, no "virtual" or "override" required. Good.
(3) Your example its very simple. Most things you did, seems fine to me.
Eventually, when you add more code, things may change, example a method in the base class that was private may become public, or you may "rename" or "refactor" a method, like "dosomething", and found out that its better to be in the base class, or maybe not.
Summary
There are other answers, that mention, rules, or concepts. Seems to me that they are OK, but, skip the fact that you are learning to use O.O.P. better. Some people just try to "eat the cake in one wingle big bite", and that's not a good idea.
P.D. "can ur skin ur rabbit", sounds better to me.
Cheers.
You might want to look to the Template pattern to define the interface in the base (abstract or not) class with defined protected virtual hooks that can be overridden in the concrete subclasses. As mentioned by another poster, if you just intend to add DB services to each of your domain areas you might look to encapsulate the basic database service methods into a helper class rather than deriving from the database service.
Thanks #jgauffin for questioning my LSP violation statement. It was not correct and has been removed. There are lots of cases where extending the public interface of the base class by subclasses is warranted. Of course, by doing that one needs to be careful that you have an instance of a Y and not an X or a Z when performing a Y-specific operation A(), assuming that both Y and Z derive from X where Y adds the new public method A() and Z does not.
An example of the Template pattern in the OP's context would allow better encapsulation of custom functionality within subclasses without extending the public interface. However, this only works if there is not external influence exerted on the subclass instance, such as the OP's SomeDataEtc parameter. This works best when the instance is immutable.
public abstract class DataService
{
protected object myWidget = new Widget();
public object SomeDataBaseCall(string storedProcedure)
{
DoSomeCustomThing();
//do db stuff
object SomeReturnObjValue = db.ExecuteScalar(storedProcedure);
return SomeReturnObjValue;
}
protected void DoSomeCustomThing() {}
}
public class Customer : DataService
{
override protected void DoSomeCustomThing()
{
// do your custom thing here
}
}
Additionally, in the OP's example, it would seem prudent to use delegation within the derived class's new public method to call the base class's SomeDBCall method to execute the stored procedure. If you are redundantly coding the db access methods then there is no benefit to the proposed inheritance.
As was also mentioned elsewhere, you might be better off altogether by using composition rather than inheritance for the data service functionality.
No. Guess your following data access object pattern (DAO). Either way your Customer is not your data access class. It uses a class for data access. What I mean is that your DAO should favor composition over inheritance.
Something like:
public class Customer : IDataAccessObject
{
public Customer()
{
_dataAccess = new DataAccess();
}
public string CustomerDoSomething(string SomeDataEtc)
{
object ReturningObj = _dataAccess.SomeDBcall("my stored procedure");
return ReturningObj.ToString();
}
}
Why? Your objects get's a single responsibility which means that it's easier to extend and refactor them.
You can read up about SOLID which is some fundamental programming principles.
Since you are a .NET developer I also recommend that you embrace the naming guidelines.

Force calling the derived class implementation within a generic function in C#?

Ok so I'm currently working with a set of classes that I don't have control over in some pretty generic functions using these objects. Instead of writing literally tens of functions that essentially do the same thing for each class I decided to use a generic function instead.
Now the classes I'm dealing with are a little weird in that the derived classes share many of the same properties but the base class that they are derived from doesn't. One such property example is .Parent which exists on a huge number of derived classes but not on the base class and it is this property that I need to use.
For ease of understanding I've created a small example as follows:
class StandardBaseClass {} // These are simulating the SMO objects
class StandardDerivedClass : StandardBaseClass {
public object Parent { get; set; }
}
static class Extensions
{
public static object GetParent(this StandardDerivedClass sdc) {
return sdc.Parent;
}
public static object GetParent(this StandardBaseClass sbc)
{
throw new NotImplementedException("StandardBaseClass does not contain a property Parent");
}
// This is the Generic function I'm trying to write and need the Parent property.
public static void DoSomething<T>(T foo) where T : StandardBaseClass
{
object Parent = ((T)foo).GetParent();
}
}
In the above example calling DoSomething() will throw the NotImplemented Exception in the base class's implementation of GetParent(), even though I'm forcing the cast to T which is a StandardDerivedClass.
This is contrary to other casting behaviour where by downcasting will force the use of the base class's implementation.
I see this behaviour as a bug. Has anyone else out there encountered this?
I see this behaviour as a bug.
This behavior is correct. Since your method DoSomething is constraining T to StandardBaseClass, you only have access to the specific methods of StandardBaseClass, not any methods or properties of a derived class. Since StandardBaseClass does not have a Parent property, this is invalid, and should be invalid, by design.
There are two potential options here - You can use reflection to pull out the Parent property, or use C# 4's dynamic type, and treat this as a dynamic object. Both bypass the standard type checking in the compiler, however, so will require you to do extra type checking at runtime to verify that the Parent property exists.
Create an interface that contains the Parent property. Have each class that has a Parent property implement that interace. You will then be able to create a generic method that accepts a parameter of type IHaveParent, and it will do the right thing.
For anyone that is interested an succinct answer to this situation is answered by Stephen Cleary on msdn here:
http://social.msdn.microsoft.com/Forums/en-AU/csharpgeneral/thread/95833bb3-fbe1-4ec9-8b04-3e05165e20f8?prof=required
To me this is a divergence in the class hierarchy. By this this I mean that either the base class has parent, or the derived classes with Parent are derived from an abstract child of the base.
Lol as John says, an interface as opposed to an abstract class is sufficient too.
You idea won't work because the compiler can never guarantee that the base class actually would have such a property. And it won't just select the "right" one based on if it has it or not.
The only way you can do this is using reflection and then test at runtime if the requested property exists on the inspected class. You have to judge yourself if that is a viable way to do for your project (reflection is slow and requires maximum rights).
This is correct, as the compiler only knows that it can bind to your type as a StandardBaseClass. The binding is not done at runtime (where it could potentially decide to use the StandardDerivedClass overload.
If you know that it's a StandardDerivedClass, then why not just cast it as such?
object Parent = ((StandardDerivedClass)foo).Parent;
It's a bit ugly, but you can accomplish this using a Registration system, where you register delegates for different possible derived classes that expose the 'shared' property/method and then use something like a Dictionary<Type,Func<SomeT>> to store the delegates. If you know all of the derived types ahead of time and don't have to load plug-ins or the like, you can also use the classic ugly if/else-if structure. Either way you're basically creating your own substitute for what should have been supported by the virtual method table.

C# - Practical example - rigidness of abstract class

I understand that
"Abstract classes can be modified without breaking the API ".
once a version (say 1.0.0.0) of class library is supplied to the party,when i design the another version (say 1.1.0.0) with modification,won't it break the code ?
can you give very simple example ,how is it possible ?
Abstract classes, and interfaces (to a lesser degree), are both what we consider a contract. Abstract classes can be more complex than interfaces in that they can have implementation as well as a contract definition. Both types can be modified without breaking a contract (API) in a couple ways. There are three basic kinds of contract changes:
Add a member
Remove a member
Modify a member
In C#, members can be methods, properties, indexers, and fields. The simplest, and first non-breaking change, is additions of members. Adding a member augments the API, but in no way changes the API that existed previously. Removal of a member is a breaking change, as the previous API does change when a member is removed.
The final option, modification of members, may or may not necessarily be breaking in C#. In the case of fields, the only modification is a rename. Renaming a public field is always a breaking change. Properties could be renamed, or they could have a setter/getter added or removed. Adding a setter/getter is not breaking, but all other property changes are breaking. Indexers and methods may be changed without breaking contract by the addition of a params parameter at the end of an existing parameter list. Any other changes to indexers and methods would also be breaking changes.
Beyond the API level, behavioral changes should also be taken into account. While we should always strive to keep the API and behavior as decoupled as possible, it is not always as cut and dry as that. Take important behavioral nuances and their effect on the use of an API into account when creating a new version. Such nuances might be exceptions thrown by a method, usage of other API members by an API member, etc.
Once you understand the three kinds of changes and how they affect a contract, you should be able to better control how you version your abstract classes and interfaces. Non-breaking changes are often labeled with a minor version change, or perhaps only a revision change. Breaking changes are often labeled with a major version change. If you take a careful approach to versioning, it should be a very manageable problem...just make sure you fully understand the impact before making breaking changes.
I think that statement means that the method body in abstract class can be changed-- without changing the interface.
Considering this:
public abstract class Animal
{
public virtual string Speak()
{
return "erm";
}
}
Later if you find out that the Animal is not speaking erm, but speaking ya, so in your version 1.1.0.0, you can just change the code to:
public abstract class Animal
{
public virtual string Speak()
{
return "ya";
}
}
In this case, if your client inherit Animal in other classes using your assembly version 1.0.0.0, then he doesn't have to change his code in order to compile with your 1.1.0.0.
In these terms, I understand the API as the contract (set of public method definitions) that client code is able to utilize to when using version (1.0.0.0) of the class. Not "breaking the API", is possible only if, in the new version of the abstract class (1.1.0.0), the new methods you are defining are non-abstract. Any new methods that are abstract in version 1.1.0.0 implements will "break the API". (Also, altering method definitions that are non-abstract will "break the API".).
First, i would say that this is not specific to abstract classes, but to classes in general.
Consider the following class:
public class SomeClass
{
public bool IsValid(string input)
{
return !string.IsNullOrEmpty(input);
}
}
It defines a method that takes a string and returns a bool. It will return false if the string is null or empty. Now, let's change it:
public class SomeClass
{
public bool IsValid(string input)
{
return !string.IsNullOrEmpty(input);
}
}
In this case we added a new method. The previus method is untouched. This change does not in any way affect code that uses the class. Next change:
public class SomeClass
{
public bool IsValid(string input)
{
if (string.IsNullOrEmpty(input))
{
return false;
}
return input.Length > 5;
}
public void SomeNewMethod() { }
}
Now we have altered the behaviour of IsValid. Old code will still complile without alteration, but the result for some input values have changed. This is one form of breaking change. Next change:
public class SomeClass
{
public void IsValid(DateTime input)
{
// do something with the input
}
public void SomeNewMethod() { }
}
Now we have altered the signature of IsValid. This will cause calling code to not compile. This is another type of breaking change.
And as you can see, these examples of breaking API has nothing to do with whether the class is abstract or not.
A little esoteric, but we've been hit by this - If your assembly is strong named and contains configuration data, you can break code by changing the version number. Unless you upgrade app|web.config when you upgrade assemblies, if a full binding path is used (say to reference a type), the new assembly will fail to load.
A more conventional answer could be you fixed a bug in the abstract class without needing to change any members.
A version policy is also recommeded, but it needs team-wide adoption to work.
Abstract classes can be modified
without breaking the API.
That's just plain wrong, or totally misleading at best. An API is not only the syntactical aspect of a classes interface, but also its semantics - i.e. the described behaviour of a certain method.
Here's an example of what I mean:
// v1
public abstract class A
{
void DoSomething()
{
...
if (someCondition)
{
throw new SomeException();
}
}
}
Now in the next version you might have:
// v2
public abstract class A
{
void DoSomething()
{
...
if (someCondition)
{
throw new DifferentException();
}
}
}
And your 'API' - seemingly remaining unchanged - might look like this:
public class B: A
{
...
void DoSomething(); // inherited from base
}
But actually, when replacing the base class v1 with v2, you didn't keep the API constant, because there might be some calling code that relies on SomeException to be thrown, not DifferentException.
Sure, you can make modifications that leave both syntax and semantics unchanged, but that's what you always do when making a new version, and there's a lot of different techniques for that. It's not specific to base classes, be they abstract or not.

Categories

Resources