Attualmente sto creando moduli di importazione Excel per alcuni dati complessi. Non ho pianificato bene e ho incontrato problemi di riutilizzo del codice. Ho realizzato i primi moduli e ho capito che i prossimi moduli avranno bisogno di alcuni metodi da questi che ho già realizzato. La mia prima opzione era di risolverla con una gerarchia di ereditarietà semplice. Sfortunatamente non potevo farlo, perché alcune sottoclassi avevano bisogno di funzioni da due superclassi, il che significa che dovevo usare l'ereditarietà multipla, che non è supportata nel linguaggio che uso (C #). L'unico altro modo per risolverlo che potevo pensare era quello di creare più interfacce e le loro implementazioni per ogni metodo che dovevo riutilizzare. L'ho fatto e l'aspetto della struttura completa ora è il seguente:
public interface IImportAssistant<TReturn, TSearchKey>
{
bool TryGetNewOrChanged(TSearchKey searchKey, out TReturn object);
}
public interface IMaterialImportAssistant : IImportAssistant<Material, string>
{
}
public interface ICustomerImportAssistant : IImportAssistant<Customer, string>
{
}
public class MaterialImportAssistant : IMaterialImportAssistant
{
public bool TryGetNewOrChanged(
string materialId,
Dictionary<string, Material> materialToIdMappings,
Dictionary<string, MaterialServiceItemDto> materialFromServiceToIdMappings,
out Material material)
{
bool materialFoundInService = materialFromServiceToIdMappings.TryGetValue(materialId, out MaterialFromServiceItemDto materialFromService);
if (!materialFoundInService)
throw new ImportValidationException("Material could not be found");
bool materialFound = materialToIdMappings.TryGetValue(materialId, out material);
if (materialFound)
{
if (material.Name == materialFromService.Name
&& material.SupplyProducerName == materialFromService.SupplyProducerName
&& material.SupplyProducerId == materialFromService.SupplyProducerId)
return false;
material.Name = materialFromService.Name;
material.SupplyProducerName = materialFromService.SupplyProducerName;
material.SupplyProducerId == materialFromService.SupplyProducerId;
return true;
}
else
{
material = new Material()
{
Name = materialFromService.Name,
SupplyProducerName = materialFromService.SupplyProducerName,
SupplyProducerId == materialFromService.SupplyProducerId
};
return true;
}
}
}
public class CustomerImportAssistant : ICustomerImportAssistant
{
//Code simmilar to material but with Customer entity
}
Esistono altre implementazioni per ciascuna entità che ho dovuto inserire nel mio sistema da un file excel. Come puoi vedere, verifica se l'entità esiste nel sistema esterno, quindi controlla se è già presente nel nostro database e se è stata modificata. È un metodo semplice, ma non volevo copiarlo incollandolo in ogni modulo di importazione, che deve controllare l'entità data. Ora, mentre lo guardo e oltre una dozzina di interfacce e le loro implementazioni, mi chiedo se dovrei fare solo una grande interfaccia e implementazione per tutti questi metodi. Il vantaggio che posso vedere sono meno file con codice e meno dipendenza da iniettare nelle classi di costruzione. Lo svantaggio è che sarebbe come un sacchetto funzionale, che è contro la responsabilità di una singola classe e le linee guida generali OOP. Sono un programmatore principiante e penso di conoscere bene gli strumenti linguistici, ma mi manca una prospettiva più ampia e le mie azioni postumi, quindi impatto sulla manutenibilità e sull'espansibilità di ciò che faccio. Potresti dirmi se ci sono altri vantaggi o svantaggi di entrambe le animazioni? O forse c'è qualche altro schema di progettazione, che risolve questi casi? Quali sono le migliori pratiche in tali situazioni?