Regarding the contract between the domain and repository, I gather it’s best to avoid an all-encompassing generic IRepository interface with methods such as Create() and Delete()? Unless, of course, it’s natural to have these methods available for all the entities I’m working with. Which I imagine is a rare scenario.
Instead, should I create a basic IRepository contract with as many – perhaps “as few” would be more appropriate – common methods (e.g., GetByID()) as makes sense? All repositories could implement the contract and then specialize.
Or is it better to go the route of multiple specialized interfaces, à la ICreatable, IDeletable, IRetrievable, etc.?
I think you should only create an basic IRepository if the methods within the interface are used by all repositories. If you have some repositories that will implement only a part of the methods, than you should go for the more specialized interfaces.
Also the last option will give you more flexibility in adding behaviour later to your repository when needed. If you use the basic IRepository interface and have to add a new method to it, than you will have to update all repositories. If you use the specialized version than you only have to update the repositories to which you want to apply this behaviour.