Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OO Design - Exposing implementation details through an interface

Tags:

c#

oop

interface

I have a class, which holds some details in a large data structure, accepts an algorithm to perform some calculations on it, has methods to validate inputs to the data structure. But then I would like to return the data structure, so that it can be transformed into various output forms (string / C# DataTable / custom file output) by the View Model.

class MyProductsCollection {
    private IDictionary<string, IDictionary<int, ISet<Period>>> products;

    // ctors, verify input, add and run_algorithm methods
}

I know that you are supposed to use the "depend on interface not implementation" design principle, so I want to create an interface for the class.

How can I avoid writing the following interface? Reason being it would expose implementation details and bind any other concrete implementations to return the same form.

interface IProductsCollection {
    IDictionary<string, IDictionary<int, ISet<IPeriod>>> GetData();
    // other methods
}

How can I easily iterate over the data structure to form different varieties of outputs without bluntly exposing it like this?

EDIT:

Since the class takes in IFunc<IDictionary<string, IDictionary<int, ISet<IPeriod>>>> in the constructor to iterate over the data structure and perform calculations, I could supply it with another IFunc, which would construct the output instead of running calculations. However, I don't know how I could do this aside from the concrete class constructor.

like image 769
oskarm Avatar asked Oct 31 '22 20:10

oskarm


1 Answers

The structure of the IDictionary<string,IDictionary<int,ISet<Period>>> is very suspicious indeed - when you see a dictionary of dictionaries, good chances are that you have missed an opportunity or two to create a class to encapsulate the inner dictionary.

Without knowing much of the domain of your problem, I would suggest defining an interface to encapsulate the inner dictionary. It looks like something that associates a number to a set of periods, so you would define an interface like this:

interface IYearlyPeriods {
    bool HasPeriodsForYear(int year);
    ISet<Periond> GetPeriodsForYear(int year);
}

I have no idea what's in the periods, so you would need to choose a domain-specific name for the interface.

Moreover, you can wrap the next level of IDictionary too:

interface IProductDataSource {
    IEnumerable<string> ProductNames { get; }
    IYearlyPeriods GetProductData(string productName);
}

Now you can define an interface like this:

interface IProductsCollection {
    IProductDataSource GetDataSource();
    // other methods
}

The main idea is to use domain-specific interfaces in place of generic collections, so that the readers and implementers of your code would have some idea of what's inside without referring to the documentation.

You could go even further, and replace the IDictionary with the complex structure that you keep internally with an IDictionary of IProductPeriods implementation. If you would like to keep IYearlyPeriods that you expose to the users immutable, but would like to be able to make modifications yourself, you can make a mutable implementation, and keep it internal to the implementing class.

like image 50
Sergey Kalinichenko Avatar answered Nov 12 '22 18:11

Sergey Kalinichenko