Imagine there is an interface IPriceProvider which supposed to serve 2 needs: historical and latest. So I think we have 2 options here.
First:
PriceInfo GetLatestPrice(string symbol);
PriceInfo GetHistoricalPrice(string symbol, DateTime pointInTime);
Second:
PriceInfo GetPrice(string symbol, DateTime pointInTime);
In my opinion the second one is better, cause it’s more flexible. Imagine, you have a Report which is as of now – so it calls this price provider like this:
GetPrice("EURUSD", _dateTime.Now);
So if there is a task to show what this exact report was showing yesterday at 17:35, I will just set _dateTime.Now to that point and my report will just work. But in case of the first approach, where I call it this way:
GetLatestPrice("EURUSD");
I will need to have a second implementation of IPriceProvider, then I will have wiring issue, I will need to configure my DI container in a special way and so on…
Am I missing something?
What are the Pros and Cons in these 2 approaches?
Update:
The Report class might look like this:
public class Report
{
private readonly IDateTime _dateTime;
private readonly IPriceProvider _priceProvider;
public Report(IDateTime dateTime, IPriceProvider priceProvider)
{
_dateTime = dateTime;
_priceProvider = priceProvider;
}
public void Run()
{
var latestPrice = _priceProvider.GetPrice("EURUSD", _dateTime.Now);
// do the report calc here
}
}
4
Judging from the conventions you’re using, you come from the C# world. Here’s how to solve this with an optional argument in C#:
public PriceInfo GetPrice(string symbol, DateTime pointInTime = null)
The idea is if you call this with only the string:
GetPrice("EURUSD");
then pointInTime
will be it’s default value _dateTime.Now
. If you have to, use some flag value like null
to signal that a method needs to be called to get the value now. This way the above will be the same as:
GetPrice("EURUSD", _dateTime.Now);
5
I think you are actually mixing two different things here. One being the definition of an interface, the other an implementation detail of your report.
Regarding the design of the interface I would go for your first approach even though I would avoid the word Historical. Requirements can change and you might want to query a price which is not yet valid. Therefore I would define the interface like so:
PriceInfo GetCurrentPrice(string symbol);
PriceInfo GetPriceAt(string symbol, DateTime pointInTime);
In the report I would then use only GetPriceAt
and pass DateTime.Today
when no other date is specified. But as mentioned above this is an implementation detail.