Interface Segregation Principle Refactorings

We can refactor the Interface Segregation Principle Demo

We can move the methods for the card reading from the IBankTerminal to a new interface.

public interface IReadersCommunicable
{
    bool isContactReaderOnPort(string comPort);
    bool IsNonContactReaderOnPort(string comPort);
    string FindContactReader();
    string FindNonContactReader();
}

Then we can delete the unimplemented methods from the ZonTerminal and implement the [[interface]] in the other terminals.


    public class ZapTerminal : IBankTerminal, IReadersCommunicable
    {
        private ZapTerminalServiceCommunicator _service = new ZapTerminalServiceCommunicator();
        public void Start() {}
        public void Stop() {}
        public void Ping() {}
        public void BankHostTest() {}

        event EventHandler<PaymentOperationCompletedEventArgs> PaymentCompleted;
        event EventHandler<PaymentOperationCompletedEventArgs> CancellationCompleted;
        event EventHandler<TransactionCompletedEventArgs> TransactionCompleted;

        bool IsContactReaderOnPort(string comPort)
        {
            return _service.IsContactReaderOnPort(comPort);
        }
        bool IsNonContactReaderOnPort(string comPort)
        {
            return _service.IsNonContactReaderOnPort(comPort);
        }
        string FindContactReader()
        {
            return _service.FindContactReader();
        }
        string FindNonContactReader()
        {
            return _service.FindNonContactReader();
        }
    }

    public class ZonTerminal : IBankTerminal
    {
        public void Start() {}
        public void Stop() {}
        public void Ping() {}
        public void BankHostTest() {}
        event EventHandler<PaymentOperationCompletedEventArgs> PaymentCompleted;
        event EventHandler<PaymentOperationCompletedEventArgs> CancellationCompleted;
        event EventHandler<TransactionCompletedEventArgs> TransactionCompleted;
    }

    public class PdqTerminal : IBankTerminal, IReadersCommunicable
    {
        private PdqTerminalServiceCommunicator _service = new PdqTerminalServiceCommunicator();
        public void Start() {}
        public void Stop() {}
        public void Ping() {}
        public void BankHostTest() {}
        event EventHandler<PaymentOperationCompletedEventArgs> PaymentCompleted;
        event EventHandler<PaymentOperationCompletedEventArgs> CancellationCompleted;
        event EventHandler<TransactionCompletedEventArgs> TransactionCompleted;

        bool IsContactReaderOnPort(string comPort)
        {
            return _service.IsContactReaderOnPort(comPort);
        }
        bool IsNonContactReaderOnPort(string comPort)
        {
            return _service.IsNonContactReaderOnPort(comPort);
        }
        string FindContactReader()
        {
            return _service.FindContactReader();
        }
        string FindNonContactReader()
        {
            return _service.FindNonContactReader();
        }
    }

    public class CardReadersCommunicatorViewModel
    {
        private readonly IReadersCommunicable _readersCommunicable;

        public CardReadersCommunicatorViewModel(IReadersCommunicable readersCommunicable)
        {
            _readersCommunicable = readersCommunicable;
        }

        public bool TestContactReaderOnPort(string port)
        {
            return _readersCommunicable.IsContactReaderOnPort(port);
        }

        public bool TestNonContactReaderOnPort(string port)
        {
            return _readersCommunicable.IsNonContactReaderOnPort(port);
        }

        string FindContactReader()
        {
            return _readersCommunicable.FindContactReader();
        }

        string FindNonContactReader()
        {
            return _readersCommunicable.FindNonContactReader();
        }
    }
}

We should segregate the configuration [[interface]]. The report class should only know the configuration related to the reports.

namespace SOLID.ISP.Config
{
    public class Report
    {
        private readonly IReportsConfig _reportsConfig;

        public Report(IReportsConfig reportsConfig)
        {
            _reportsConfig = reportsConfig;
        }

        public string Generate()
        {
            return  $"Income: {_reportsConfig.Income}" + "\n" +
                    $"Expenses: {_reportsConfig.Expenses}" + "\n" +
                    $"Total Revenue: {_reportsConfig.TotalRevenue";
        }
    }

    public interface IAppConfig
    {
        string ServerId { get; set; }
        string ServerIP { get; set; }
        string ServerPort { get; set; }
        int LoggingSwitch { get; set; }
        int AppSkinId { get; set; }
    }

    public interface IReportsConfig
    {
        decimal Income { get; set; }
        decimal Expenses { get; set; }
        decimal TotalRevenue { get; set; }
    }

    [DataContract(Namespace = "")]
    public class AppConfig : IAppConfig, IReportsConfig
    {
        private AppConfig(){...}

        [DataMember(IsRequired = true)]
        public string ServerId { get; set; }

        [DataMember(IsRequired = true)]
        public string ServerPort { get; set; }

        [DataMember(IsRequired = true)]
        public string LoggingSwitch { get; set; }

        [DataMember(IsRequired = true)]
        public int AppSkinId { get; set; }

        [DataMember(IsRequired = true)]
        public decimal Income { get; set; }

        [DataMember(IsRequired = true)]
        public decimal Expenses { get; set; }

        [DataMember(IsRequired = true)]
        public decimal TotalRevenue { get; set; }

        public static AppConfig Config { get; private set; }

        public static void Initialize()
        {
            using (Stream s = File.OpenRead("config.xml"))
            {
                Config = (AppConfig) new DataContractSerializer(typeof(AppConfig)).ReadObject(s);
            }
        }
    }

}