D
D
Dmitry2016-08-16 21:51:19
ASP.NET
Dmitry, 2016-08-16 21:51:19

How often do you use interfaces?

Hello! I deal with the topic of interfaces, asking the question "why, why do we need interfaces", I often received an answer for the loose coupling of components / interchangeability of components, for better testing. And the question is how often do you surround your application layers with interfaces, or something else? How often have you had that your repositories surrounded by interfaces use MSSQL, and there are still the same repositories but already using MongoDB, for example, and where do you replace one with another? Have you often had that you have 2 different layers of services surrounded by interfaces, and again you replace one with another? This is really possible, if it is unlikely, or the probability is small, it turns out that interfaces are mainly used for testing, so that you can use mocks? So, explain, chew, give real examples,

Answer the question

In order to leave comments, you need to log in

7 answer(s)
Z
Zelimkhan Beltoev, 2016-08-16
@Beltoev

The simplest example that comes to mind: imagine that you want to be notified about website errors via email/sms/whatever.
With interfaces, your solution would look something like this:

// Собственно, сам интерфейс оповещений
public interface INotification
{
    void Notify(string text);
}

public class EmailNotification : INotification
{
    public void Notify(string text)
    {
    // код по отправке почты
    }
}

public class SmsNotification : INotification
{
    public void Notify(string text)
    {
    // код по отправке смс
    }
}

// ... Еще какие-нибудь классы оповещений


// В каком-нибудь классе, где может появиться ошибка
public class MaybeErrorClass
{
    private INotification _notification;

    public MaybeErrorClass(INotification notification)
    {
    // Класс не должен знать, по какому каналу оповещать об ошибках.
    // Он работает с абстракцией
        this._notification = notification;
    }

  // Очень простой пример метода, в котором ожидаем генерацию ошибки
  public void DoSomething()
  {
    try {
      // какой-то блок, в котором можем получить ошибку
    }
    catch (Exception e)
    {
      this._notification.Notify("А у нас тут ошибка!");
    }
  }
}

Now you can create instances of this class, passing it the desired alert type:
var maybeErrorEmail = new MaybeErrorClass(new EmailNotification());
var maybeErrorSms = new MaybeErrorClass(new SmsNotification());

Now a tricky question: how would you solve a similar problem without interfaces?
Only abstract classes come to mind (by the way, an interface is also an abstract class), but it is better to use them only if the derived classes have some kind of common logic that you would not want to duplicate.

S
Stanislav Makarov, 2016-08-17
@Nipheris

How often do you use interfaces?

Let's see what we have in the standard library:
The developer faces all these interfaces every day. Either use them or implement them. For example, the same yield return works thanks to IEnumerable. All LINQ is based on IEnumerable and IQueryable.
Often. For example, the ADO.NET architecture allows you to write an application so that it does not depend on the database driver used at all, and a specific ado.net driver can be specified in the application's config file. Those. a specific database can be chosen by the USER, not by the developer. Moreover, if there is no driver for some database yet, and later it appears, then it can be used without recompiling the application. Only because interfaces are used.

A
Alexey Nemiro, 2016-08-17
@AlekseyNemiro

I use interfaces if necessary :-) As I understand it, it's hard to say that this is necessary. Everything depends on the task. If we consider the issue from the perspective of creating interfaces, then sometimes it can be obvious, and sometimes you have to think about whether to use interfaces or not. Pushing them anywhere is a bad idea.
Ready-made interfaces, yes, are often used. The most popular in .NET will probably be IDisposable :-)
From publicly available practical examples of using native interfaces:

  • A simple interface describing just one method.
    interface ILoginForm
    {
    
      void WebDocumentLoaded(System.Windows.Forms.WebBrowser webBrowser, Uri url);
    
    }

    There are 100500 forms in the project . Some forms may require custom processing of results, like here . But for others , no. All forms inherit from a base class where I can check if the current instance implements the interface with a custom result handler or not and call it.
    if (typeof(ILoginForm).IsAssignableFrom(this.GetType()))
    {
      this.CanLogin = false;
      Debug.WriteLine("ILoginForm", "LoginForm");
      ((ILoginForm)this).WebDocumentLoaded(this.webBrowser1, e.Url);
    }

  • Here is another interface example .
    export interface ILocalization {
    
      Loading: string;
    
      LoadingFileContents: string;
    
      // ...
    }

    Localization resource files implement this interface .
    export class RU implements ILocalization {
    
      public Loading: string = 'Загрузка...';
    
      public LoadingFileContents: string = 'Получение содержимого файла...';
    
      // ...
    }

    It just makes it easier to work with the code and nothing else.
    It would be possible to use ordinary text keys, but then programmers would have to constantly look at what keys are, make a lot of unnecessary movements, and the likelihood of errors increases.
  • Another example of an interface for auxiliary classes for working with databases. It simply describes what the class should be.
    interface IDBClient
    {
        
      public function ExecuteNonQuery();
      public function ExecuteScalar();
      public function GetRow();
      // ...
    
    }

    And it makes no sense.
    I often make interfaces for interaction layers with the database, with a swing to replace the DBMS, but it won’t work beautifully anyway, you still have to make adjustments when changing the data source, so there is little practical use from such interfaces, but sometimes it is, only for other purposes.
  • And here I have implemented a lot of ready-made interfaces to get the desired properties and class behavior. For example, the IConvertible interface allows you to respond appropriately to Convert.To* . The ISerializable interface allows you to describe the rules for serializing an instance of a class. Etc.
    // реализация метода ToInt32
    public int ToInt32(IFormatProvider provider)
    {
      // если пусто, возвращаем ноль
      if (!this.HasValue) { return 0; }
      // если что-то есть, извлекаем числа и пробуем вернуть int32
      return Convert.ToInt32(OAuthUtility.GetNumber(this.Data));
    }

  • Here is an example where you could use interfaces, but I decided in favor of base classes (early). Some OAuth providers allow you to renew and/or revoke an access token, but not all. In the base class of the lower level for the definitions of these features, I made two properties , and not even abstract ones.
    public bool SupportRevokeToken { get; protected set; }
    public bool SupportRefreshToken { get; protected set; }

    Clients that need these properties set them in the constructor, it looks like this .
    public GoogleClient(string clientId, string clientSecret) : base(/*...*/)
    {
      // ...
      base.SupportRevokeToken = true;
      base.SupportRefreshToken = true;
    }

    It's not very pretty, but it's not a mistake. If I used interfaces, then to revoke and update the marker, I would have to make two different interfaces, each with one bool property, or empty (but with an explicitly defined property for other programmers, everything would be more obvious; this is also a moot point). It was possible to go further and grind other features into interfaces, but this would be a bad decision, because. programmers would have to specify a footcloth of interfaces, and then write a lot of code. With base classes, you don't need to write code, you don't even need to delve into how it works; in most cases, it's enough to just do a simple configuration of the child class in the constructor. But I cannot say 100% that this is the best solution for this case.
  • An example where ReactJS and TypeScript make interfaces riveted and I'm not at all happy about this.
    export interface ILoginState {
    
      Username?: string;
      Password?: string;
    
      // ...
    
    }
    
    export default class Index extends Page<any, ILoginState> {
    
      constructor() {
    
        this.state = {
          Username: '',
          Password: ''
        };
    
      }
    
      // ...
    
    }

    You can forget and use anonymous types, but for the order and convenience of working with the code, you will have to open your own factory for the production of interfaces :-)

#
#algooptimize #bottize, 2016-08-16
@user004

The benefits of interfaces are so obvious, I don't even know where to start.
Read about OOP, patterns, testing.

Z
Zakharov Alexander, 2016-08-16
@AlexZaharow

Everyone has their own understanding of the interface, and depending on this, programs are written using certain templates. Usually, a technology stack is chosen for the task, and if it is chosen successfully, then the program will live happily ever after. Well, if not, then ... out of luck.

M
Michael, 2016-08-17
@Milk92

I start from the understanding of polymorphism .. that is, the variety of forms of an object (interface link). This is written in any book on the C # language and on any other language with the OOP paradigm.. Here
you yourself need to understand when to use it.
regardless of the source..
That is:

public interface IDataAccess{
void Connection();
void BeginTransaction();

}
public class MySqlDal:IDataAccess{
      public void Contection(){
         //TODO implement method!
    }
     public void BeginTransaction(){
       //TODO implement method!
    }
}
public class MsSqlDal:IDataAccess{
      public void Contection(){
         //TODO implement method!
    }
     public void BeginTransaction(){
       //TODO implement method!
    }
}

And then use it like this:
public IDataAccess mySqlDal = new MySqlDal();
public IDataAccess msSqlDal = new MsSqlDal();

I know it's a rough example, but something like this.

A
Alexander Ryzhov, 2016-08-29
@RyzhovAlexandr

At the risk of repeating myself, let me describe my vision.
There are several cases where it is convenient to use interfaces:
As for when to introduce an interface, I usually introduce an interface if I see the point in it for the reasons described above, if there is no sense, then I’m not in a hurry to introduce it, because it can always be distinguished, the main thing is that there is a clear reason for you.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question