Is using many interfaces a bad programming practice?

Asked

Viewed 1,478 times

57

I am a student in Information Systems and I am modeling a game, a virtual pet that has its needs and conversation with its owner, below follows the modeling of classes and interfaces.

I showed it to a friend with a degree in computer science, he thought it had a lot of interfaces, it wasn’t necessary, I argued that if in the future I could maintain and implement pets the way I wanted without much effort, can create a pet hybrid between animal and robot, and assigning to it its behaviors through the interfaces, but finally it came with arguments of application performance.

My question is whether my modeling (which is not ready, just an outline) with so many interfaces is a bad programming practice? When to use an interface?

inserir a descrição da imagem aqui

Image link

7 answers

46

When modeling an object-oriented system, one of the most important things we should do is to assign to each type (whether interface, class, structure, enumeration or delegate) a set of concepts and responsibilities.

You are practically making an interface for each important method of your pets. Virtually every animal sleeps and eats, for example. You could create a single interface to group these features. This helps a lot to keep the job simple because:

  • If you have to add one more feature to the animals, just work on a single interface. No need to go to each class and make it implement another new interface;
  • if you have to change the signature of some method, you won’t have to run through all your animals to see which ones are affected, i.e.: it’s much easier to control who is affected by a change of a specific interface.

Another thing, several animal sounds have their own interfaces in their implementation. A more common approach is to have a single method (again, this goes in the general interface for animals). You could call the method "talk" or "Speak". Hence, if the animal will bark, yell, meow or call the judge to complain of foul shall be charged with implementing the method in the class using the inheritance.

Finally, you ask: Okay, I’ve put all the methods together into a single interface called Pet. But what if I have some animal that doesn’t use any functionality? For example, a slug would never mortal jump back. In that case, you have several options:

  • Treat this in an abstract method and give some indication that the slug can’t somersault back;
  • Be a bastard and cast a Notimplementedexception;
  • Be a double bastard and leave the method empty.

In all cases, document well what you are doing ;)

Note that there is no need for specific classes for dinosaurs and dogs if you think so. The amount of common functionality between the two is simply too great to justify such specialization.

You might have some need for specialization, if you did something like:

  • A single interface called Pet, which can for example evolve and move;
  • Three "sub" interfaces: animal, plant and robot;
  • Hence you assign to each "sub" interface only that which is specific to it. Robot does not grow (I think), plant does not speak and animal does not release death ray.

Good Luck and happy coding!

  • 9

    +1. I would include: "Being a triple bastard and lying, returning True but ignoring."

  • 1

    I agree with the implementation of the method Speak(), But I don’t know, in a way, separate each action into its own interface until it makes sense because it would make it much easier to create secondary interfaces. Imagine two types of "animals", Automaton and Android. They’re both the type Robot (interface) which in turn is a Pet, but each one is more specific than the other.

  • 1

    An Automaton would be any machine with one or more purpose(s) only(s), whereas an Android could speak and "sleep". And with specific methods on separate interfaces the way it is you can easily achieve this goal without prejudice to the polymorphism because in the eyes of the Application all will be Pet.

  • 1

    @Brunoaugust general rule: specializing too much in interfaces is a shot in the foot. Just look at how interfaces are used in large frameworks like Java or .NET. In general, interfaces are as comprehensive as possible. Case in point: Icollection.

  • 1

    I’m not saying it’s right, I don’t have the deep grasp to hammer that hard. Nor am I saying that all these interfaces are really essential, that there is even no possibility of extending the scope of one or the other. But that makes a certain sense.

  • 2

    @Brunoaugusto There are even reasons to have interfaces with only one method (or few), this is not enough to be a big problem but it makes no sense to separate behaviors that are related. I even understand what you are saying, there are reasons to do it this way (I explain in my reply) but at the moment he is not doing it. When he changes the design and you can post another question to help with the new configuration. Then maybe some interfaces are really useful. That would be nice and do this. To see if he got the hang of it or needs more guidance.

  • 1

    @Renan (Shut up and take my +1!) is a pity that we can not favorite answers, one of the best I’ve read here on SO-pt.

  • 1

    @Renan An object should not publish a method that is not his behavior. If a slug can’t somersault backwards, why does it have a method to trigger this impossible behavior? If the slug publishes this method we are faced with a design error.

  • I believe it is right at this point that I tried to reach, @Caffé. Again, I’m not saying that the diagram modeling is correct BUT, having each action on a different interface, it’s like arriving at a mall, at those candy stores, and saying "I want this, this, that and a little bit of that other" and each time something different will come out, that does more or less things than the previous without overloading anyone, without publishing unnecessary methods and etc.

  • 1

    In the case of the slug, it would be best to have at least one interface separating this behavior (or behaviors), otherwise you would be performing a breach of contract. The Principle of Liskov’s replacement talks about it.

  • +1 for humor! hauahuahuahua

Show 6 more comments

23

Abstract Class X Interface

You started creating the class Pet with common properties among derived classes. Is there any reason not to continue doing this for methods and events? If I pass these joint members to the Pet already simplifies a lot. Renan suggested to join everything in an interface called Pet. But you already have this interface. An abstract class is both a class and an interface. The abstract class Pet is your interface.

Generalize what you can

Follow Renan’s recommendation and turn the methods of sound emission of Pets into something generic. Remember that the sound emission is the unique action, the way the sounds are emitted is that it will vary, that is, the implementation varies. What you did was exactly what is described in link contributed by Joshua Eduardo.

You probably still don’t quite understand the concept of what the interface is. It declares actions and not the mechanism (normally, but we will not make the mechanism being used in other ways, not all language does this), the implementation of these actions. Understand that abstract interfaces and methods of abstract classes define behavior, but do not implement this behavior. Only concrete classes can implement the behaviors. When you treat a bark or a neigh without the abstraction of the ability of animals to emit sounds, you are leaving aside one of the advantages of object orientation which is real abstraction (having an abstraction of bark to implement a bark is an artificial abstraction).

Perhaps all these sound emissions are already included in the method Talk() and only the different implementations are necessary. At this point I disagree with Renan that each type of Pet does not need specific classes. You need to be able to make the specific implementations in these classes. The suggested solution would only work if all sound emissions were equal.

If the Talk() serves another thing, you can create another generic method to denote the action of emitting sounds of pets, Speak() maybe?.

When you do this, all interfaces, individually, will be implemented in only one class each. Can you tell why this is necessary? If you have a good reason, ok, if you don’t have it, finish it. In general an interface is only interesting when it is used in at least two classes. Future use is not a good reason. If in the future need, there you create the interfaces. There are no problems in creating an interface and putting in an existing class since the design class is right. An existing class can assume a new interface if it already has the desired behavior. This hurts no principle and creates no problems.

I say more. If you can abstract the pairs of methods (do not force the bar, only do it if it is the best to do), Eat and Recharge, Sleep and Maintenance, Poop and OilLeak, you may find that they are the same action with different implementations.

Future implementation

If you ever need one HybridPet implementing some methods (and events obviously) unique to the AnimalPet And also some unique methods of RoboticPet, then you create the IAnimalPet which will be used in the class AnimalPet and in the HybridPet and the IRoboticPetwhich will be used in the RoboticPet and HybridPet. This is if they really help something. You only need two interfaces.

Completion

Have you noticed that you need zero interfaces? In your case, you have many interfaces. In current modeling, an interface is very.

Don’t forget that in abstract classes, unlike interfaces you can give a standard implementation of the methods if they match some types of pets.

Don’t worry about the future in this case. If you have difficulty creating a consistent interface in the future it is because your model was wrong, not because you failed to create the interface before.

I find your case quite simple and don’t need to make the gambit of making a specialization an exception (and probably generate an exception in Runtime in this case) as suggested by Renan.

If improve the modeling and still have questions post new question to continue helping with the new problem.

10

In this case it is bad practice because you are writing useless code. Create only the interfaces that are needed now.

Leave to create in the future the interfaces that will be needed in the future. This will not increase your effort at all - the IDE automatically creates interfaces for you and already changes the code that references the implementation to reference the interface, and even if the IDE did not do so the effort would be no more than a "search and replace".

Contrary to what your friend said, the performance of the application will not change at all, but your code will become simpler, which, among other benefits, decreases waste.

  • It’s the famous principle YAGNI

7

Expensive if you have an interface for an implementation, I see no use having the interface. Many people use as an argument: "if you need to one day extend the class is easier", but that day never comes.

If you have more than one implementation for the interface, ok... but why the use of the interface ? from the practical point of view, it is necessary ??... don’t blow up your code just to be "architecturally beautiful" the simpler the better.

I advise you to take a look at this blog Adam Bien, and also look for some of his workshops. Although it is Java-oriented, it has some very interesting concepts about OO, which apply to any language.

  • Aham... And OCP blows itself up, right? The way this modeling is today, in the future, whether it’s close or not, it can easily create a completely new animal, with unique characteristics, most likely (it will depend on the implementation) without even touching the code that makes the animal eat, sleep, talk...

  • 3

    @Brunoaugusto OCP and interfaces do not relate. Even if you do not have an interface today doesn’t mean the class can’t be extended. You can add an interface whenever you want without causing any problem (if so, the design was wrong, it was not the lack of interface). Of course, in order not to modify the class, the new interface in an existing class must be on top of something already implemented (or defined in the case of an abstract class). You would just be saying that something existing now happens to be part of an interface. Create before violates YIAGNI or even KISS, which is worse.

  • As you noticed in the other comments I see from another angle, maybe wrong, but OCP is for the strong :p. I think that if there is an interface of its own through which the Application performs, I don’t know, an action of eating, any resource that can actually eat can be created at any time without the need to modify the consumer Application. If you have as many interfaces in the same direction you can close the consumer application for modifications because through the polymorphism provided by the interface Pet any class would be accepted and would have their eating action performed successfully.

  • 1

    @Brunoaugusto But you don’t need to change the "consumer" (as you say), you won’t change it. You need to include the interface, not the implementation. OCP has to do with implementation. So much so that one of the best known techniques of Refactoring is the Extract Interface which is done on the basis of existing implementation. Adding a new interface to an existing class does not change the class implementation, let alone break any build contract or Runtime.

  • I’ve always had a hard time understanding some of the paradigms like that, just on a theoretical basis. And the fact that quality material on subject matter related to language that I like does not exist or is very scarce does not contribute anything. What gives me more anger is that you’re explaining, you’re explaining and I can’t visualize the same way you(s). I think I need a coffee. >.<

  • @Brunoaugusto ,I believe the bigown and I share the same point of view: the practical. Whenever thinking about architecture/structure ask "why do I need it?" "can it be simpler?". Another thing that the bigown stated that I approve 100%. is the question of abstract class instead of interfaces, to have a standard behavior.

  • Yeah, I know that. But since I don’t program professionally I can "afford" to consider that kind of scenario as viable.

Show 2 more comments

5

To answer your question: It is not bad practice. But you should follow some principles when doing the modeling, according to the principle YAGNI you do not need to create interfaces for all your classes for the simple fact that you will never use, but if you are in doubt when modeling a certain class I suggest creating an interface, especially if you are developing a package or using and want a low-level coupling.

5

Only use Interfaces if you use Design by contract (Dbc).

If you don’t use Dbc, keep your code dry without using interfaces.

This is "the best" from the values of Lean Software Development because it eliminates waste. Obviously, from other values, this "best" may be different.

I believe that the use of an interface serves to ensure that an object has required properties at the time it will be used, forcing the execution of this with typing. If I don’t need this guarantee, then the creation and implementation of the interface is a wasted effort. If I expect a Logger object, I hope it has a method that allows me to register a string, so I say that the Logger object I will receive should at least have a method foo(string) and then I’ll make sure the app works. But this is valid only if the possibilities of Logger injection are more than one, as for example, when you develop a library that saves logs, but expects the logger to be injected by the application that will use your library.

  • 3

    'Cause this is the best thing to do?

  • @bigown, this is "the best" from the values of Lean Software Development as it eliminates waste. Obviously, from other values, this "best" may be different.

  • 2

    ok, but what’s the advantage? What waste? If I need to bathe I’m not wasting water? If I leave the shower on and I will do something else I am. Because the interface is not waste c/Dbc but is if not use it? I believe you have some support for what you have said but as it is something that seems to go against everything that is studied on the subject, we cannot simply rely on your statement. Give us some additional information to learn something new.

  • I understand. I will edit my answer and you give me your opinion.

  • It has improved a lot but I still don’t understand the relationship with Dbc. All this you explained is necessary regardless of the Dbc being used. Unless you have a different definition of Dbc than I do. The compiler refuse to compile something that is not of the proper type (does not have the required interface) for you is Dbc?

  • I see that the fact of not compiling is only a technical detail, but rather the architecture planned for the orientation to the contract and Dependence Injection is what really matters this applies also to languages where we do not compile a build.

Show 1 more comment

-1

Using interface for everything is a bad practice because it makes it very difficult to know where the interface is actually being used in a useful way (if any is being), that is, directed to the purpose that it was created.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.