De situatie: ik heb een .NET library geschreven voor een API van een derde partij, deze library kan gebruikt worden voor interactie met de API. De API is in de basis zeer eenvoudig, je kan er een zoekopdracht aan sturen en je krijgt resultaat terug. Dit resultaat is qua structuur wel enorm complex, mijn library doet het parsen en returnt het resultaat als simpele classes met properties.
Nu is het zo dat de API een aantal varianten heeft, je hebt een basis resultaat met bepaalde velden, maar afhankelijk van de variant kunnen er velden bij komen. Op dit moment heb ik alles op een hoop gegooid, maar dat vind ik niet ideaal, omdat als je de basis variant gebruikt, je resultaat vervuild wordt met allerlei properties waar je niks mee te maken hebt. Ook zijn sommige properties classes die ook weer uitbreidbaar kunnen zijn.
Voorbeeld:
Waar ik nu mee worstel is hoe dit op de beste manier op te lossen is. Een deelt is natuurlijk op te lossen met inheritance:
Maar hoe ga je hier dan mee om, en wat doe je met de ExtraComplexType
Ik denk dat het in ieder geval wel een goed idee is om de enkele Search te vervangen door specifieke methods die het juiste type SearchResult returnen (er zijn in totaal 9 varianten)
Dan hou je nog het probleem dat een ExtraSearchResult geen ComplexType, maar ExtraComplexType moet returnen. Ik kwam zelf op twee opties.
Optie 1, dit werkt wel, maar voelt niet helemaal lekker
Optie 2 is om ExtraComplexType niet van ComplexType te laten erven, maar dat vind ik ook niet ideaal omdat het resultaat dan verspreid wordt over meerdere properties.
Er is ook een optie 3 dat in het eenvoudige voorbeeld zou werken, maar in de praktijk niet (met tien properties die een class zijn is dat geen doen):
Ik hoop dat het probleem na dit lange verhaal een beetje duidelijk is en ben benieuwd naar jullie meningen
Het voorbeeld is nu in C#, maar hetzelfde probleem en eventuele oplossingen zullen in andere talen ook van toepassing zijn.
Nu is het zo dat de API een aantal varianten heeft, je hebt een basis resultaat met bepaalde velden, maar afhankelijk van de variant kunnen er velden bij komen. Op dit moment heb ik alles op een hoop gegooid, maar dat vind ik niet ideaal, omdat als je de basis variant gebruikt, je resultaat vervuild wordt met allerlei properties waar je niks mee te maken hebt. Ook zijn sommige properties classes die ook weer uitbreidbaar kunnen zijn.
Voorbeeld:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class SearchResult { // standaard properties voor alle varianten public string MyString { get; set; } public ComplexType MyType { get; set; } // extra veld uit andere variant public string MyExtraString { get; set;} // resultaat uit derde variant public string YetAnotherString { get; set; } } public class ComplexType { public int Number { get; set; } } |
Waar ik nu mee worstel is hoe dit op de beste manier op te lossen is. Een deelt is natuurlijk op te lossen met inheritance:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class SearchResult { // standaard property voor alle varianten public string MyString { get; set; } } public class ExtraSearchResult : SearchResult { // extra veld uit andere variant public string MyExtraString { get; set;} } public class YetAnotherSearchResult : ExtendedSearchResult { // resultaat uit derde variant public string YetAnotherString { get; set; } } public class ExtraComplexType : ComplexType { public int ExtraNumber { get; set; } } |
Maar hoe ga je hier dan mee om, en wat doe je met de ExtraComplexType
C#:
1
2
3
4
| public ICollection<SearchResult> Search(string query) { // .. } |
Ik denk dat het in ieder geval wel een goed idee is om de enkele Search te vervangen door specifieke methods die het juiste type SearchResult returnen (er zijn in totaal 9 varianten)
C#:
1
2
3
4
5
6
7
8
9
| public ICollection<ExtraSearchResult> ExtraSearch(string query) { // .. } public ICollection<YetAnotherSearchResult> YetAnotherSearch(string query) { // .. } |
Dan hou je nog het probleem dat een ExtraSearchResult geen ComplexType, maar ExtraComplexType moet returnen. Ik kwam zelf op twee opties.
Optie 1, dit werkt wel, maar voelt niet helemaal lekker
C#:
1
2
3
4
5
| public class ExtraSearchResult : SearchResult { // .. public new ExtraComplexType MyType { get; set; } } |
Optie 2 is om ExtraComplexType niet van ComplexType te laten erven, maar dat vind ik ook niet ideaal omdat het resultaat dan verspreid wordt over meerdere properties.
C#:
1
| public ExtraComplexType ExtraMyType { get; set; } |
Er is ook een optie 3 dat in het eenvoudige voorbeeld zou werken, maar in de praktijk niet (met tien properties die een class zijn is dat geen doen):
C#:
1
2
3
4
5
6
7
8
9
| public ICollection<SearchResult<ComplexType>> Search(string query) public ICollection<ExtraSearchResult> ExtraSearch(string query) public class SearchResult<TComplexType> { public TComplexType MyType { get; set; } } public class ExtraSearchResult : SearchResult<ExtraComplexType> |
Ik hoop dat het probleem na dit lange verhaal een beetje duidelijk is en ben benieuwd naar jullie meningen

Kater? Eerst water, de rest komt later