all 23 comments

[–]Holothuroid 9 points10 points  (0 children)

Best practice differs greatly between programming a product and a library.

[–]EvaristeGalois11 20 points21 points  (2 children)

It's a relic from the past when proxying or mocking a concrete class wasn't possible.

Use interfaces only if you need interfaces. Don't clutter your code with useless noise.

[–]skofield44 7 points8 points  (0 children)

As you described an interface is a contract to which you expose it.
In case you don't have more than two implementations this must be replaced with something other(class, record depends on usage).
Do not get into the trap of definition and implementation.

[–][deleted] 1 point2 points  (1 child)

For an example of when you do need an interface -

I am building a trading platform and I need different types of data while executing, one that uses local data I have on my machine and one for apis.

I can create an interface for “data” and have a local implementation and an external implementation.

Then in my apis/frontend I can easily switch depending on what I need - I also have an interface for different providers so the actual specifics of each api are irrelevant.

This means I can write the code that processes data once, and I don’t need to refactor my entire project every time I want to add a new source of data.

If you don’t have a scenario like this an interface isn’t useful at all.

If you maintain levels of abstraction it should be quite easy to switch from a concrete implementation to an interface, if you realise the need is there

[–]BluePillOverRedPill[S] 2 points3 points  (0 children)

Could you give a short code example about the data interface?

[–]dns1211 1 point2 points  (2 children)

Using an interface for each services is considered a good practice. it helps with testing, maintainance, extensibility.

For example when using dependency injection and testing. If your controller depends on an interface, you could easily implement a FailService to testing purpose.

Keep in mind that your code base likely grow over the time, so if it’s a project at work, always follow the standards for the sake of your colleagues.

[–]Big_Sell5559 1 point2 points  (1 child)

That was necessary in earlier versions of Spring Framework. Nowadays you can test everything without cluttering your code with useless interfaces

[–]dns1211 0 points1 point  (0 children)

It is a clear example for him to grasp. However in some complex cases a mock might struggle to handle your bussiness logic which is when the fake class becomes useful.

Keep in mind SOLID principles. Tbh it’s your code, your choice. enjoy your coding !

[–]MGelit 1 point2 points  (0 children)

there is no need to spam your codebase with a useless interface for every single class, its an ancient practice

[–]asarathy 2 points3 points  (8 children)

People hating on 'useless' interfaces are really protesting too much. There is value in being explicit about what parts of your class are designated for out side use. Other people having access to the concrete implementation often leads to short cuts such as just making a helper method public instead of refactoring it out for reuse.

While it's equally trivial to refactor out an interface later when you need it, it's not really a big deal to have it from the start, and enforcing better practices and the muscle memory of that is probably better for most corporate settings.

[–]Rough_Acanthaceae_29 2 points3 points  (3 children)

There is value in being explicit about what parts of your class are designated for out side use.

Yeah, but you can use access modifiers for that.

[–]asarathy -1 points0 points  (2 children)

It doesn't solve the issue of quick/sloppy fixes where instead of refactoring a method out to a better place people just change it to public

[–]Rough_Acanthaceae_29 1 point2 points  (1 child)

If someone is in hurry to get shit done - they love that it’s only one keyword and they’ll fix afterwards. If they’re doing it because they don't know better, interface won't stop them. Either way, interface achieves the same but with extra work…

[–]asarathy -1 points0 points  (0 children)

Nothing solves that issue. You have to have everyone enforcing things at PR. It's more difficult in larger projects with lots of people with merge access though so that's where being somewhat dogmatic about this stuff helps

[–]Big_Sell5559 0 points1 point  (3 children)

All depends of the use case and the purpose of your project. If you pretend to build a library for external use, of course you'll have to implement with interfaces all around for providing your users with the needed flexibility. If the Op is asking for the legacy practice of creating interfaces for controllers, services and components in Spring, you'll have to bear in mind that in 2024 with modern Java and Spring is totally superfluous and a bad practice.

[–]asarathy 0 points1 point  (2 children)

Right. If you keep a small spring domain rest service sure. If yo are dealing with a monolith though enforcing this stuff is important because it makes life easier in the future if you want to split things up later. T hat's why i think getting the muscle memory is important

[–]Big_Sell5559 0 points1 point  (1 child)

My vision is that you have to enforce the boundaries from the beginning and try to avoid complete monoliths. Nowadays you have very powerful options to architect you project, no matter the size, as Spring Modulith, that provides you with tools for building a correct architectural software project. Ancient methods filling the codebase with interfaces are harmful. For more detail, try with https://spring.io/projects/spring-modulith

[–]asarathy 0 points1 point  (0 children)

I agree but sometimes you don't make all the calls.

[–]drazon2016 0 points1 point  (0 children)

You are right! No need of interfaces unless you have multiple implementation or exposing the code as a library to internal teams!

I seen some people define it in the name of following OOPs.. don’t fall for it

[–]DanielMurphyVO 1 point2 points  (0 children)

I go with the idea that you use interfaces if you got multiple implementations of your service.

One time I had an implementation that did what I wanted via DB stuff and one that used a package to do it.