My code has the concept of a command:
public abstract class BaseCommand { public BaseCommand() { this.CommandId = Guid.NewGuid(); this.State = CommandState.Ready; } public Guid CommandId { get; private set; } public CommandState State {get; private set; } protected abstract void OnExecute(); public void Execute() { OnExecute(); State = CommandState.Executed; } }
And some specific implementations like this one:
public class DeleteItemCommand { public int ItemId {get; set;} protected override void OnExecute() { var if = AnyKindOfFactory.GetItemRepository(); if.DeleteItem(ItemId); } }
Now I want to add some validation. The first thing I can do is add an if / throw check:
public class DeleteItemCommand { public int ItemId {get; set;} protected override void Execute() { if(ItemId == default(int)) throw new VeryBadThingHappendException("ItemId is not set, cannot delete the void"); var if = AnyKindOfFactory.GetItemRepository(); if.DeleteItem(ItemId); } }
Now I am trying to use Code Contracts, because I am quite confident in its usefulness to reduce the risk of errors. If I rewrote the method as follows:
public class DeleteItemCommand { public int ItemId {get; set;} public void Execute() { Contract.Requires<VeryBadThingHappendException>(ItemId != default(int)); var if = AnyKindOfFactory.GetItemRepository(); if.DeleteItem(ItemId); } }
The method is compiled, verification is performed at runtime. However, I received a warning:
warning CC1032: CodeContracts: the method "MyProject.DeleteItemCommand.Execute" overrides "MyProject.BaseCommand.Execute", so it cannot add Requires.
I understand that this warning is issued because I violate the Liskov principle.
However, in my case, the conditions differ from one particular class to another. My BaseCommand class actually defines some common attributes, such as CommandIdentifier, state, and other final functions, which I removed here to make a simple question.
As long as I understand the concepts of this principle, I don’t know what I need to do to properly remove the warning (do not tell me about #pragma warning remove ).
- Should I stop using code contracts in this case, where specific implementations have special requirements?
- Do I have to rewrite my command mechanism to have, for example, a separation between the “arguments” and “execution” commands? (having one
CommandeExecutor<TCommand> for a particular class). This will lead to a significant increase in the number of classes in my project. - Any other suggestion?
- [Change] As suggested by adrianm , convert properties to readonly, add constructor parameters to populate properties, and check properties in constructor