Add a parameter or create a new method?

Say I have a long-established repository:

interface IDonutRepository { public IEnumerable<Donut> GetDonuts(); } 

That was a long time ago, and the GetDonuts method does what it says. Then one day I need to add a new screen that shows all the donuts in the database, and it turns out that the method has a hidden function - it filters out all the donuts, where stale = true . But on my new screen I want to show them all, even outdated ones! What is the best approach here?

Assuming this method is ubiquitous and the default behavior should remain the same, is it best to add a new method called GetAllDonuts that does not filter, or should I just add onlyFresh to the GetDonuts method?

I suppose this is fair, but I wonder if there are more reasonable answers there?

+4
source share
5 answers

I would overload the method by creating a new overload that accepts the showStale parameter, and then modify the old method to use the new false overload transmission for the parameter value.

The interface will look like this:

 interface IDonutRepository { public IEnumerable<Donut> GetDonuts(); public IEnumerable<Donut> GetDonuts(bool showStale); } 

Or, if you are using .NET 4.0, you can use the optional parameter:

 interface IDonutRepository { public IEnumerable<Donut> GetDonuts(bool showStale = false); } 
+9
source

Why not use an optional parameter? This way you are not breaking existing code:

 interface IDonutRepository { public IEnumerable<Donut> GetDonuts(bool onlyFresh); } 

Implementation:

 public IEnumerable<Donut> GetDonuts(bool onlyFresh = false) { if (onlyFresh) // do stuff else // do other stuff } 
+2
source

It really comes down to personal preference, to some extent ...

If you have the ability to change the API, I would (personally) rename the current method so that it is obvious that it does not return all instances of Donut . I was expecting the GetDonuts repository GetDonuts get all the donuts. This can be done using a parameter or another name of your choice.

At the same time, the overload method with an additional parameter is probably the best option for moving forward if maintaining compatibility is critical. (It depends a lot on who and where this API is used ...)

+1
source

Depending on the circumstances, you might consider introducing a property to access donuts.

 interface IDonutRepository { IEnumerable<Donut> Donuts { get; } .. or .. IQueryable<Donut> Donuts { get; } } 

It is fairly easy to implement this interface if you are using a Linq-dependent ORM such as Entity Framework or NHibernate.

The old GetDonuts method can be renamed to GetFreshDonuts (), or you can redirect calls to it in the form:

 repository.Donuts.Where(x => !x.Stale) 
+1
source

One of the growing trends in software design is separating the interface from the implementation. The principle of dividing modules into public and private parts, so that you can change the private part without coordination with other modules. However, there is another difference - one between public and published interfaces. This difference is important because it affects how you work with the interface.

http://www.martinfowler.com/ieeeSoftware/published.pdf

0
source

Source: https://habr.com/ru/post/1344966/


All Articles