I am trying to understand how this will be done in practice so as not to violate the principle of Open Closed.
Say I have an HttpFileDownloader class that has one function that takes a url and loads a file that returns html as a string. This class implements the IFileDownloader interface, which has only one function. So throughout my code, I have references to the IFileDownloader interface, and I have an IoC container that returns an HttpFileDownloader instance whenever IFileDownloader is allowed.
Then, after some use, it becomes clear that sometimes the server is too busy at that time and an exception is thrown. I decide that in order to get around this, I am going to automatically retry 3 times if I get an exception and wait 5 seconds between each attempt.
So, I create an HttpFileDownloaderRetrier, which has one function that uses an HttpFileDownloader in a for loop with max 3 loops and 5 seconds of waiting between each loop. So that I can test the ability to "repeat" and "wait" for the HttpFileDownloadRetrier, I have the HttpFileDownloader dependency introduced by creating the HttpFileDownloaderRetrier constructor using IFileDownloader.
So now I want all IFileDownloader permission to return HttpFileDownloaderRetrier. But if I do, then the HttpFileDownloadRetrier IFileDownloader dependency will receive an instance of itself, not the HttpFileDownloader.
So, I see that I can create a new interface for the HttpFileDownloader called IFileDownloaderNoRetry and change the HttpFileDownloader to implement it. But that means that I am modifying the HttpFileDownloader, which violates Open Closed.
Or I could implement a new interface for the HttpFileDownloaderRetrier called IFileDownloaderRetrier, and then change all my other code to reference it, not IFileDownloader. But then again, now I'm breaking Open Closed in all my other code.
So what am I missing here? How to transfer an existing implementation (loading) with a new level of implementation (retrying and waiting) without changing the existing code?
Here is some code if it helps:
public interface IFileDownloader { string Download(string url); } public class HttpFileDownloader : IFileDownloader { public string Download(string url) {
c # dependency-injection ioc-container open-closed-principle
Dividendium
source share