Let's say library A, B and C are all custom math libraries. They may or may not use the same data types. The libraries have methods that accept data type inputs like ProcessAsync(DataTypeA)
or ClusterByFeature(IDataTypeB, Func<IDataTypeB, double>)
.
These libraries will be developed for modularity. E.g. Future graduate students can come and use the library for their needs.
I thought that these libraries should:
- either provide concrete implementations of the inputs they accept and manipulate on, like
DataTypeA
,DataTypeB
,DataTypeC
- or, request that the users supply an object of type
IDataTypeA
,IDataTypeB
,IDataTypeC
Which design I should choose seems to be dependent on many factors.
I've come up with a few:
- If it's just a container, it should be an interface
- If
DataTypeA
,DataTypeB
,DataTypeC
are all very similar, use interfaces - let the invoking framework supply the implementation by inheriting all the interfaces - If
DataTypeA
requires complicated operations, use classes - If
DataTypeA
requires simple operations, use interfaces and aDataTypeAManipulator
class
I see other open-source libraries overwhelmingly use classes instead of interfaces, so I think classes should be the way to go. But is there no place for data interfaces then?
--
A better example of the problem that I faced: There's a 3D object that needs to be manipulated on. Library A handles vertices, Library B handles vertices and deformation by bone joints, Library C handles vertices and texture mapping. 3 different data objects - they're actually different views of a single data object, but the libraries don't/shouldn't know that! So should I use data interfaces to show different perspectives of a 3D object, or copy values to data classes instead.
ClusterByFeature(IDataTypeB, Func<IDataTypeB, double>)
the user defined function gets passed the interface. It benefit from receiving the concrete type instead. But you didn't specify enough context to really analyze your problem.