0

I'm practicing C# on Testdome.com, I solved the coding exercise (AlertService) below but still not convinced by the purpose of point 3 and 4:

Refactor the AlertService and AlertDAO classes:

1- Create a new interface, named IAlertDAO, that contains the same methods as AlertDAO.

2- AlertDAO should implement the IAlertDAO interface.

3- AlertService should have a constructor that accepts IAlertDAO.

4- The RaiseAlert and GetAlertTime methods should use the object passed through the constructor.

This is the code I write, I added the constructor and the interface that AlertDAO implements, at the end The Compilation was OK but I need to know if this is the right way to solve it:

public class AlertService   
{
    private readonly AlertDAO storage = new AlertDAO();

    //Constructor
    public AlertService(IAlertDAO alert)
    {
        storage = (AlertDAO)alert;
    }

    public Guid RaiseAlert()
    {
        return this.storage.AddAlert(DateTime.Now);
    }

    public DateTime GetAlertTime(Guid id)
    {
        return this.storage.GetAlert(id);
    }

    static void Main(string[] args)
    {
        IAlertDAO alertDao = new AlertDAO();
        AlertService alert = new AlertService(alertDao);
        Guid id = alert.RaiseAlert();
        Console.WriteLine(alert.GetAlertTime(id));
        Console.ReadKey();
    }
}

public class AlertDAO : IAlertDAO
{
    private readonly Dictionary<Guid, DateTime> alerts = new Dictionary<Guid, DateTime>();

    public Guid AddAlert(DateTime time)
    {
        Guid id = Guid.NewGuid();
        this.alerts.Add(id, time);
        return id;
    }

    public DateTime GetAlert(Guid id)
    {
        return this.alerts[id];
    }   
}

public interface IAlertDAO
{
    Guid AddAlert(DateTime time);
    DateTime GetAlert(Guid id);
}
5
  • 3
    The ctor for AlertService doesn't make sense. Why pass an interface if it's cast to a concrete class anyway? The backing field (storage) should be declared with IAlertDAO as well. Also, what is the main method doing there? It has no business being in a class dedicated to something else entirely. Commented Nov 22, 2019 at 18:06
  • 1
    Change your storage Variable to IAlertDAO also, and you are fine. The cast is crashing the idea of the use of an interface. Commented Nov 22, 2019 at 18:06
  • @lennart I added that constructor because it's asked to in point 3 and 4 Commented Nov 22, 2019 at 18:17
  • 4
    @WalidGhodhbani I think his point was to not cast the interface to a specific type. Instead declare storage as an IAlertDAO. Commented Nov 22, 2019 at 18:21
  • 1
    @WalidGhodhbani If you do as Rufus suggests then you (or anyone else) can make a different class that implements IAlertDAO at any time and pass that into the constructor instead. This is the basis of dependency injection with inversion of control, which is very useful when you need it, but appears pointless when you don't. Commented Nov 22, 2019 at 18:29

2 Answers 2

4

Almost right, but you need to change storage variable to IAlerDAO. It's needed to follow one of principles in OOP (SOLID).

See Dependency Injection

TL;DR: it allows you to decouple your service from actual implementation of data access layer, so, you can pass another implementation of interface, which stores the data to different place. Or you can create unit tests by creating 'dumb' implementation, which stores data in memory instead of read DB (you do not need to rely on DB status).

Sign up to request clarification or add additional context in comments.

Comments

2

Few things others have pointed out. storage should be of type IAlertDAO, so there is no need to cast in your constructor. No need to new it up in its declaration.

public class AlertService   
{
    private readonly IAlertDAO storage;

    //Constructor
    public AlertService(IAlertDAO alert)
    {
        storage = alert;
    }

    public Guid RaiseAlert()
    {
        return this.storage.AddAlert(DateTime.Now);
    }

    public DateTime GetAlertTime(Guid id)
    {
        return this.storage.GetAlert(id);
    }

    static void Main(string[] args)
    {
        IAlertDAO alertDao = new AlertDAO();
        AlertService alert = new AlertService(alertDao);
        Guid id = alert.RaiseAlert();
        Console.WriteLine(alert.GetAlertTime(id));
        Console.ReadKey();
    }
}

public class AlertDAO : IAlertDAO
{
    private readonly Dictionary<Guid, DateTime> alerts = new Dictionary<Guid, DateTime>();

    public Guid AddAlert(DateTime time)
    {
        Guid id = Guid.NewGuid();
        this.alerts.Add(id, time);
        return id;
    }

    public DateTime GetAlert(Guid id)
    {
        return this.alerts[id];
    }   
}

public interface IAlertDAO
{
    Guid AddAlert(DateTime time);
    DateTime GetAlert(Guid id);
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.