I am currently creating Excel import modules for some complex data. I didn't plan it well and I have met code reuse issues. I have made first modules and I realized that next modules will need some methods from these I have already made. My first option was to solve it by simple inheritance hierarchy. Unfortunately I couldn't do it, because some subclasses needed functions from two superclasses, which means that I had to use multiple inheritance, which is not supported in language that I use (C#). The only other way to solve it that I could think of, was to create multiple interfaces and their implementations for each method that I had to reuse. I did it and whole structure looks now like this:
public interface IImportAssistant<TSearchKey, TReturn>
{
bool TryGetNewOrChanged(TSearchKey searchKey, out TReturn object);
}
public interface IMaterialImportAssistant : IImportAssistant<string, Material>
{
}
public interface ICustomerImportAssistant : IImportAssistant<string, Customer>
{
}
public class MaterialImportAssistant : IMaterialImportAssistant
{
private Dictionary<string, Material> _materialByIds;
private Dictionary<string, MaterialServiceItemDto> _serviceMaterialByIds;
public bool TryGetNewOrChanged(string id, out Material material)
{
bool foundInService = _serviceMaterialByIds.TryGetValue(id, out MaterialFromServiceItemDto serviceMaterial);
if (!foundInService)
throw new ImportValidationException("Material could not be found.");
bool materialFound = _materialByIds.TryGetValue(id, out material);
if (materialFound)
{
if (material.Name == serviceMaterial.Name
&& material.SupplyProducerName == serviceMaterial.SupplyProducerName
&& material.SupplyProducerId == serviceMaterial.SupplyProducerId)
return false;
material.Name = serviceMaterial.Name;
material.SupplyProducerName = serviceMaterial.SupplyProducerName;
material.SupplyProducerId = serviceMaterial.SupplyProducerId;
return true;
}
else
{
material = new Material()
{
Name = serviceMaterial.Name,
SupplyProducerName = serviceMaterial.SupplyProducerName,
SupplyProducerId = serviceMaterial.SupplyProducerId
};
return true;
}
}
}
public class CustomerImportAssistant : ICustomerImportAssistant
{
//Code simmilar to material but with Customer entity
}
There are other implementations for each entity I had to put in my system from an excel file. As you can see method checks if entity exists in outside system, then checks if it already is in our database and if it has changed. It is simple method, but I didn't want to copy paste it in every import module, which has to check given entity. Now as I look at it and at over a dozen interfaces and their implementations, I wonder if I should make just one big interface and implementation for all these methods. The advantage that I can see, is less files with code and less dependency to inject in constructor classes. The disadvantage is that it would be like a function bag, which is against single class responsibility and general OOP guidelines. I am a beginner programmer and I think I know language tools well, but I lack at bigger perspective and my actions after-effects, hence impact on maintainability and expansibility of what I do. Could you tell me if there are other advantages or disadvantages of both soultions? Or maybe there is some other design pattern, which solves such cases? What are best practices in such situations?