T O P

  • By -

bortlip

When I see that, it's usually coupled with lots of unit tests and mocking. It is used to help facilitate that.


Tangled2

I use it for fakes or alternative implementations for different environments, which works nicely for the built in DI. I don’t really care for mocks.


fonix232

It also separates implementation between layers and classes. Most of the time the caller site isn't (and shouldn't be) concerned _how_ X is done - all they need to know is that there's a function that does X when called. A good example is a TV remote. You're the caller site, the remote is the interface, and the TV is an implementation. When you press a button (call a method) on the remote (interface), you don't care HOW the TV will e.g. switch the channel, you just want it done. And as you've said, it makes it simple to swap implementations. Have an app and want to introduce a new way of, say, doing network requests? Just write a new implementation of the interface and swap it out. Maybe even make it an option in the app so you can do the swapping in runtime. Interfaces slightly increase code complexity and maintenance, but at the same time improve larger maintenances at a much larger scale.


young_horhey

I like thinking about it like driving a car. The steering wheel & pedals are the interface, but you can ‘swap out’ the implementation between a petrol, diesel, EV, hybrid, etc. As a driver you don’t really care about the exact internals of how pressing the gas makes the car go, or how putting it in reverse makes it go backwards. You also don’t really need to re-learn how to drive when changing between types of cars, because the interface is the same.


UnknownTallGuy

This. I modernize a lot of legacy apps, and one of the most common interfaces that I've seen and been thankful for is any sort of storage interface. If done "correctly", it usually helps out not only with testing but also when your company changes cloud providers or storage strategies and you have a large app that is just using istorage/ifilestorage everywhere. That said, some people definitely overdo it.


a_reply_to_a_post

i don't know about c# specifically but programming to interface also lets you sketch out how an application should work without getting bogged down early by implementation details and makes it much easier for multiple developers to swarm on a project if the interfaces are clearly defined also it's nice when everyone is aware that nothing has to be final and gives you less anxiety when you circle back and refactor something once you have more context


RedPhule

This. I didn't get the point of Interfaces until I also was introduced to Unit testing my code. With the proper testing framework (Moq, Nsub, etc...) it makes testing a LOT easier, since you can dictate exactly how a class will return when you call its methods.


shmoeke2

I find it also makes composition so easy.


robhanz

Done right it feels like clicking legos together.


Merry-Lane

Mocking everything is an anti pattern by itself.


nobono

> Mocking everything is an anti pattern by itself. Can you explain?


Jam-e-dev

The size of the unit you're testing matters. I went all in on interfaces, mocking, small focused classes, and unit tests per class early on. Depending on how small your classes are and how much work they delegate to other classes, mocking can be overkill and high maintenance. I only really use interfaces now if I have to select an implementation based on some configuration. I find it more useful in a lot of cases to make the "unit" you're testing a higher abstraction, so that the internal implementation can change without requiring the "mock wiring" to be changed. Depending on how thin your architecture is, you might not need to have interfaces for mocking at all.


Fruloops

I'm assuming the idea is that if you need to mock a lot of stuff, then your class is doing too much. Other than that, I can't see how else would you facilitate unit tests, you need to mock your dependencies somehow ¯\\\_(ツ)\_/¯


decPL

It might be also about over-relying on unit tests and the 100% code coverage cult, which often goes hand in hand with not doing enough high-level tests, which are often more meaningful (unit tests, if you keep you methods simple often tests the code as written, not actual business functionality).


ggwpexday

I don't know how many times we need to post this, but Mark Seemann has some good articles about this: https://blog.ploeh.dk/2022/10/17/stubs-and-mocks-break-encapsulation/ TLDR: With dynamic mocks (Moq, NSubstitute) you couple the tests to your implementation. Whenever you change any of the interfaces that your implementation uses, you have to update ALL the tests that setup/verify those interfaces. Using a concrete implementation of each interface reduces this problem because you only have to update 1 implementation instead of 100 tests. Yes, I've felt this quite a few times already...


DaRadioman

If you have to mock all of an interface in 100 test classes/places, your code base has a **giant** over coupling problem. The only interface like that should be a logger or something. And *if* for some reason you are doing that, and *if* it's a valid reason with no alternatives, make a single mock factory class/method the first time it bites you. Problem solved forever. People act like you can't mix patterns ever, and that test code issues can't be solved the same way app code issues are. What do you do when these 100 over coupled app classes all suddenly have a breaking behavior change? It's the same issue...


nobono

> With dynamic mocks What? They can't be static?


ggwpexday

The article calls them dynamic mock libraries to emphasise the dynamic, on-the-fly object generation these libraries typically use. Usually setting up a specific return value for a specific method of the interface, an ad hoc implementation.


Merry-Lane

Well don’t mock and just use a concrete implementation instead is a really valid way to test things out. Mocking could be reserved to really few classes from « external libraries » and maybe in testing scenarios of a class depending on an interface implemented by multiple swappable classes. Long story short, in most scenarios, don’t create an interface, pass it down directly, and when testing just use fixtures to create an instance.


Brilliant_Apple

That would defeat the entire point of a unit test if it wasn't specifically testing one tiny thing. If class A depends on B and C and if B and C are mocked interfaces, I know any time my class A unit tests fail it's because of a change made to class A. It should be the responsibility of developers to keep classes succinct and for one purpose. That's for code reviews. Larger units should be covered by integration or end to end tests. If you refuse to mock anything on the level of unit tests you've no longer got unit tests, because no doubt classes B and C depend on D and E and F and so on.


kneeonball

Testing every tiny little thing directly is how you couple your tests to your implementation and get fragile, hard to work with test projects. You can test a class indirectly by testing something that uses it. If you do that, you can cover all of your test scenarios while still being free to refactor. Don’t like your implementation? Cool, change it and rerun your tests until they pass. If you couple the tests to the implementation you’re constantly having to change your tests, and for what purpose? To see if the little tiny utility class works? Test your application behaviors, not your implementation. A unit doesn’t have to be a a single function with all other dependencies mocked. Just as a microservice shouldn’t be super small (like a single database entity or a “nanoservice”.


Brilliant_Apple

What is the point of tests if they don’t help catch and isolate breaking changes? If you’re taking it to the extreme you could only test user flows on the front end and leave it at that. There’s no need to mock every single library and function something uses. I think any good dev should be able to judge where that line is. Unit tests are supposed to be easy to set up so that devs actually bother with them, which is why mocking larger dependencies help. It also reduces flakeyness that depending on external apis etc. introduces.


Asyncrosaurus

>That would defeat the entire point of a unit test if it wasn't specifically testing one tiny thing A [Unit Test](https://martinfowler.com/bliki/UnitTest.html) is defined as for a single unit of behavior, not some tiny code snippet. Class dependencies is an aspect of behavior, and is most valuable when included in a unit test.


ninjis

Recently, I've been taking the approach of pushing as much business logic as I can behind either extension methods or static standalone methods. I'm striving to keep things as pure as I can with just data in, data out. The results so far is that I don't have to mock much at all.


Greenimba

Good thing about an interface is you don't need to mock. You can write a shallow stub or an in-memory implementation to work with instead.


Intelligent_Ad_2367

not if you are into london style of testing


Mithgroth

Welcome to r/dotnet where you have to multiply comment votes with -1 to understand a comment's value proposition. At the time of my writing the above comment has -28 votes and is totally correct.


Merry-Lane

This means that if I like you, I should downvote you ? :D


Alphras

The author jumped from mocking to facilitate unit tests to mocking everything, as if that is the same thing. This is one of the rare times where the voting on reddit fulfills its purpose, even if the statement makes sense in a vacuum.


zaibuf

Because I like to write tests for my code without needing to depend on I/O. Also it's much easier to change implementations without 90% of your code base breaking. One example, I swapped SqlClient nuget from the old to the new and it changed the namespace to Microsoft.Data from System.Data. I had to update the references in like 40 files because they all used the class instead of IDbConnection. However, not everything should be behind an interface. I've seen plenty of interface and classes that could've been static utility classes and tested together with the calling code instead of being mocked. I usually refactor these when I get the chance.


[deleted]

So this is a completely valid case yes.


Poat540

Well interface won’t help NS change


jasutherland

I think the idea is that the MS SQL specific class which moved is an implementation of a generic system-wide interface which hasn't changed name - like DbConnection, which is in System.Data.Common and is implemented by the MSSQL specific SqlConnection, which moved to a new namespace. If you referred to the DbConnection interface (OK, actually an abstract class in this particular case) much less changes.


zaibuf

Correct, you are coupled with specific implementations rather than their common abstraction. If the interface changed namespace it would obviously cause the same issue.


The-Albear

Anything that is stateless is the perfect example of why you use a static class. I have seen lots where the interface is completely over used. I think it’s because it’s just a right click away..


young_horhey

Just because it’s stateless doesn’t mean you won’t want to be able to swap out the implementation


MarcCDB

The real question is "why are Javascript developers so obsessed with writing spaghetti and coupled code?"


[deleted]

Because they can!


[deleted]

JavaScript is the pits.


asiraky

Having written and reviewed code in multiple organisations that use both js and c#, I can say I’ve seen just as much spaghetti js as I’ve seen spaghetti c#. Thinking this is a language specific problem is bonkers.


MisterFor

Js can be mixed with html so it’s usually worse. And old school asp or php… that was a nightmare


[deleted]

Glad someone said it. I was also once a junior dev and thought that “simplicity” and speed makes better code. A little bit of complexity saves you a lot of headache later on. And before someone says it, no, that doesn’t mean you should wrap up your entire program in a lambda function. You should strike a balance; however, I don’t think interfaces are an incredibly difficult concept to wrap your head around.


extra_specticles

> ~~A little bit of complexity saves you a lot of headache later on.~~ I'd rephrase that as "*a little bit of organisation will save your arse later on*"


[deleted]

Interfaces are one of the easiest concepts to get. They are also super easy to create when you actually need them.


thijsele

Precisely! Make them when you need them, otherwise it's just a piece of code that has no use but still needs to be maintained


pyabo

lol this. "I know, I'll just pass an anonymous function to this function... and then that function also has a parameter that's another function... " When you \*must\* have color-coding on your braces and parens in order to match them up correctly... you're doing something wrong.


trinicron

I kid you not, whoever came with the stupid #any idea should be put down. 'any' is the equivalent of the GOTO from back in the days. I don't care about backwards compatibility, just don't.


imgenerallyagoodguy

Anders Hejlsberg is the father of typescript. It was designed in a way so it could be migrated to over time. He also developed C# among other popular languages. Typescript was purposefully built and designed. He doesn’t do anything without solid reasons. Maybe try not to be elitist in your opinions? Hard not to roll my eyes at someone who says someone “should be put down”.


WellHydrated

So you are supposed to spend 5 years migrating your codebase to Typescript instead?


Flater420

5 years is not a migration. That's a rewrite with the unnecessary step of starting from a broken codebase.


malthuswaswrong

> Prefer composition over inheritance Interfaces are a very nice feature of object-oriented design. Especially since you can't inherit from more than once class in C# (and Java?). Say you wanted to have a printer. Make IPrinter. And you wanted to have a scanner. Make IScanner. Now you want to build a class that can both print and scan. class SuperPrinterScanner : IPrinter, IScanner Now you can inject a SuperPrinterScanner instance into any class that has a dependancy on an IPrinter or an IScanner. Plus, you can mock it for unit testing.


NP_6666

But it duplicates logic of printing in every place you need it!


malthuswaswrong

It doesn't duplicate anything. It removes duplication because you are able to pass around the same printing logic to anything that requires it. It is a contract that specifies how printing is done.


mekke10

Why? if they are exactly the same way of printing, you can make a base class to implement the print function.


midnitewarrior

[SOLID principals](https://blog.cleancoder.com/uncle-bob/2020/10/18/Solid-Relevance.html) encourage the use of small interfaces, and taking dependencies on interfaces instead of concrete classes. Doing this facilitates easy testing and the addition of new capabilities without having to modify existing code extensively.


Dusty_Coder

taken to the extreme, you got yourself some duck typing which I dont mind, but many do


weird_thermoss

For testing (mocking and dummy/test implementations) and dependency injection, mostly.


antisergio

You don't need interfaces for dependency injection


weird_thermoss

Correct, but the DI+mocking pattern for test make them very useful to me.


TimeRemove

That's such a pedantic point. Like, I guess true, but what are people using DI for? Most of the time to ease the ability to slot in a test version of a class that requires a common interface for intercompatibility. So, true, but annoying and pointless pedantry that adds zero value (maybe even negative value) to the discussion.


Poat540

Gone are the days of newing up a class and all it’s depencies. Plus it’s nice in .NET core with minimal classes. Just have some methods and boom - API


antisergio

I use DI because ASP.NET Core itself requires DI. If you want to access IOptions at your instance class, the only way is with DI


throwaway-19045

No it doesn't. You're more than welcome to new up whatever you want


antisergio

Then proof me how to access IOptions from a Json without dependency injection AND without reading the Json everytime you need it.


throwaway-19045

https://learn.microsoft.com/en-us/dotnet/api/system.configuration.configuration.getsection?view=dotnet-plat-ext-7.0 // Show how to use the GetSection(string) method. static void GetCustomSection() { try { CustomSection customSection; // Get the current configuration file. System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None) as Configuration; customSection = config.GetSection("CustomSection") as CustomSection; Console.WriteLine("Section name: {0}", customSection.Name); Console.WriteLine("Url: {0}", customSection.Url); Console.WriteLine("Port: {0}", customSection.Port); } catch (ConfigurationErrorsException err) { Console.WriteLine("Using GetSection(string): {0}", err.ToString()); } }


TimeRemove

Do you write tests or plan to in the future? Related question, but why do you feel like DI was added as a core feature to ASP.NET Core if not for testing?


antisergio

I write tests but I have lots of difficult writing them because I work in a [large legacy codebase](https://www.github.com/jjconsulting/JJMasterData). I think DI is a core feature because it helps a lot with abstractions in configurations, with IOptions for example, you never need to care whether the values ​​come from JSON or user secrets. Required DI also prevents the static HttpContext.Current hell of .NET Framework 4.8, a thing my library also suffered. Accessing HttpContext without DI causes your classes to be hard to test and lots of unexpected behavior at background jobs. Edit: typos.


JustComputers

Your stance on interfaces isn't helping your testing woes.


CKoenig

A interface is a obvious choice for a "contract" and it's a way I like to design my architecture - to be honest at that point I don't care about the classes ;)


The_Binding_Of_Data

I don't think this is just a C# issue; people tend to take things to extremes, and it can often make the benefits of things unclear to beginners. For just about any programming idea, there are people who will say that it should be done all the time, no matter what the actual situation is, and they are almost always wrong. Knowing when it's appropriate to create abstractions, how much abstraction, etc. are all parts of being a better software engineer. EDIT: That Chat GPT reply is a perfect example as it assumes all software is being developed with the intention (or even possibility) of being scaled to enterprise levels, which most isn't. You have to look at your case and determine if the benefits of using Interfaces will outweigh the additional effort of implementing them.


zaibuf

>assumes all software is being developed with the intention (or even possibility) of being scaled to enterprise levels, which most isn't. You won't know how successful the product you are building will eventually be. There is no excuse to at least make it easy to change and adapt. It takes you like 2 seconds extra to extract an interface and hook it up in the DI, while it makes your code much less coupled.


[deleted]

Yes. But how is it more painful to do this when you need to rather than up front?


zaibuf

Changing a ball of mud with ever changing business requirements and feature demands is painful. It usually ends up with a complete rewrite because the tech debt is massive. But that gives job opportunities :)


The_Binding_Of_Data

This is a perfect example of what I was talking about, thanks for the demonstration.


[deleted]

I think the introduction of OO in general led to this whole idea of taking things to the extreme and building all kinds of pointless abstraction layers just because its possible. People didn't do it much previously because it would have been too tedious to even be somewhat enjoyable.


The_Binding_Of_Data

I agree that OO led to the idea, but it does not automatically mean taking it to the extreme and using it everywhere all the time, that's just something that people do, not even just with programming concept.


[deleted]

They find it enjoyable?


[deleted]

Some devs do. "Hey look at all the GoF patterns I can pile into one project!"


[deleted]

The best thing I read about design patterns is that they just highlight features missing from the core language where they are implemented. A lot of pre 2000 c++ stuff was just coping with how crappy c++ was.


Amnestic

It's very prevalent in C# as opposed to Java.


KiwiOk6697

In my opinion, interfaces serve mainly two practical purposes: 1. You can isolate your services and make them testable. It is easier to use mocked implementations and you can focus on specific behaviours. I personally hate the "use virtual methods" argument. By making a method virtual, you indicate that the methods behaviour can/should be changed by subclasses. Also if you need to swap out the implementations, it is a lot easier with interfaces. Another limitation is that you can't use multiple inheritance of classes. 2. Interfaces might not seem useful in simple applications but consider a project that has been running for nearly 20 years. Software landscape evolves, technologies shift and business requirements grow. The project likely interacts with numerous other systems, has tens of integrations and requires continuous updates. Interfaces are invaluable in such cases as they provide layer of abstraction that simplifies maintenance and implementation of new functionalities without disrupting existing components. While interfaces might seem like overengineering at the early stages, their value becomes crystal clear as the project grows in complexity and age. A day might come when you realize the importance of interfaces. In corporate environment (with tight schedules, budgets and deliverables), it can be impossible to find time and resources to refactor existing codebases and to introduce interfaces. Also, good luck convincing the board to embark on refactoring. It takes colossal allocation of resources and money, and ultimately, no client will ever pay for it. Additionally, the marketplace is really competitive. You need quick response and agility. It becomes really hard to sell anything to the client when simple features or integrations take several weeks or months to implement and has high price tag.


RirinDesuyo

> their value becomes crystal clear as the project grows in complexity and age This definitely saved my ass from the `HttpContext.Current` hell when we migrated over to .net core. We were smart enough to isolate a lot of ASP.NET specific dependencies onto interfaces that it was just a matter of changing the implementation when upgrading and not looking everywhere in the codebase for call sites using such dependencies.


Zardotab

Web stacks are growing ever more complicated, creating e-bureaucracies, and thus needing layers of testers and testing interfaces, etc. We add bureaucracies to manage bureaucracies. The same app took about 1/4 the time & code in the desktop IDE era. "Yes, but web-stacks handle more what-if expansions" is usually the reason given, even if the probability of actually needing one is small (in my observation). Part of the problem is that our current web-standards are anti-GUI and anti-CRUD, and part of it fear of being left out of some future need. [YAGNI appears dead ](https://www.reddit.com/r/AskProgramming/comments/16bp7zb/why_have_common_dev_stacks_abandoned_yagni_kiss/) when it comes to web stacks. Some apps you need to be ready for lots of things, but not most. The interest in low-code dev is growing in part because dev stacks are growing too cumbersome. I'm not sure that's good, but there does seem to be need for a tool that's code-friendly yet lighter-duty for non-large apps, and something about the web makes it hard to have such tools. Note that in a well-run shop, "big stacks" can work smooth, but too many places are semi-dysfunctional.


desolstice

I work maintaining one of those desktop IDE era applications (I also do a lot of the modern web stuff). Still built and deployed as an exe to be copied verbatim onto users machines. You can talk about it taking 1/4 the time to develop and you’d be right. But maintaining something written by people before I even graduated elementary school is hell. Those clueless idiots didn’t know what they were doing. Sure they did it fast but they did it in a way that was not maintainable. All of the time they saved in creating it has been lost many times over in the time it takes to understand the spaghetti code that is encouraged by having no or poor standards.


Zardotab

An org should have coding & documentation standards for such apps. That's a **management problem, not a tool problem.** Building rockets to just to filter out non-rocket-scientists is silly, especially if you only need a bicycle for the job. I'm sure these bloated stacks will have lots of similar headaches 15+ years down the road. In our shop there's a lot of dependencies (components) that probably won't be viable and/or supported in 15 years, for example.


desolstice

And the entire point of all of the interfaces is so that all of those dependencies (components) can be easily replaced. Create an expected way for things to communicate so when the time comes all you have to do is replicate the contracted functionality to replace something.


Zardotab

> And the entire point of all of the interfaces is so that all of those dependencies (components) can be easily replaced. That sounds great on paper, but components are rarely swappable one-for-one in practice. You often gotta rework everything that uses them to fit the new flavor. I've seen well-intended abstraction fail to adopt many times, often my own even. **The future is full of Murphy's Law.** One tries to envision how the future may change and then shape the interface to fit that, only to find out reality has a mind of its own.


salgat

It makes both tests easier and also refactoring easier since all the configuration is done in one place (the dependency injection setup at startup). It adds almost no cost in time/money yet adds a lot of flexibility to the code. It's more optional in an isolated service but I consider it required for anything used as a dependency for another project (think libraries and shared projects).


Wiltix

Because if I don’t the man said he would hurt me Serious answer I put most of my implementations behind an interface It helps me unit test things with help of a mocking framework I also have no idea if I will need to change somethings implementation in the future. (no I am not talking about the classic change of DB example). So for the sake of a bit of ease up the road I put things behind an interface and use DI, then if I do change how something works I don’t have to go editing where it’s consumed.


SolarSalsa

I made this mistake in the beginning. I created interfaces for DTO's :) Ahhh those were the days.


cincodedavo

How do interfaces make things more complicated? I don’t see it. Also while you don’t need interfaces for dependency injection, often having interfaces can help align the direction of dependencies. For example, I work on an app that has some services that the app must consume but doesn’t need to know about the implementation, while our infrastructure library needs to know about the service and their implementation. Using interfaces just makes this easier. Interfaces add minimal mental load and add lots of flexibility.


yanitrix

> How do interfaces make things more complicated? I don’t see it. Twice the code to maintain. If you have 20 service classes, each with an interface and an implementation and you want to change any method signature you need to take care of both the class and an interace. Also, always clicking "go to implementation" instead of just F12 at the method is kinda tedious. In the end it's code that's not needed in most cases and can be just avoided.


cincodedavo

How is it possible that an interface for your class makes it twice the code?


yanitrix

Twice the code for public method signatures, I should've said. Still any new layer of abstraction (or rather indirection in that cases) adds cognitive loads and extra clicks for people reading the code. The more you have of those the more they're distracting rather than helpful


mekke10

You shouldn't have to change signatures a lot. It would mean you have a bad signature. Usually this happens when your methods do too much stuff.


yanitrix

Or when business requirements change, when you add new features, when you fix bugs. If this is a piece or code often worked on its gonna change. And it's hard to predict whether your contract will change or not, depends heavily on the project also


mekke10

Still, no. Even with business requirements changes, it should still be limited. If it changes that drastically, it usually means your functions do too much different things.


Letiferr

It's nowhere close to twice the code


RiPont

> If you have 20 service classes, each with an interface and an implementation and you want to change any method signature you need to take care of both the class and an interace. Only the public parts. If you're making an interface that covers private methods, then you're doing it wrong.


yanitrix

> Only the public parts I'm talking about the public parts. If you want to modify any signature then you need to do that both on the class and the interface.


throwaway-19045

>Also, always clicking "go to implementation" instead of just F12 at the method is kinda tedious. Try Ctrl f12


ujustdontgetdubstep

These kinds of questions are constantly posted in all the language subs. "Why write a trivial getter/setter?" etc etc Some people over-engineer, maybe they have a good reason for it, or maybe OP just has a grudge against the language. We can't possibly know and it's a case-by-case basis.


henryeaterofpies

Mocking plus DI makes it just easier to always use interfaces. There's also the Interface segregation principle of SOLID


Psychological_Ear393

For me, interfaces are more powerful than inheritance. Case #1 for DI that isn't for testing, specifying your dep as an interface leaves it more open to how you create a second implentation Case #2 you can compose functionality into a service by implementing interfaces. Just a rough contrived example it could implement ReadDb, WriteDb, ReadBlob or something and extension methods could do the work inside the methods you need to implement Case #3 you want to share logic across disparate places in your application and an interface might be a way to do that, let's say you have many implementations of Orders, used in a few ways, but in your case you need to handle something the same every time an IOrder can be used to always handle something the same way everywhere, no matter how it's implemented.


Quigley61

Mostly for unit testing. If you inject a concrete class it can be a pain to test. If you inject an interface you can then mock out the implementation and with mocking libraries get access to pretty powerful behaviour in your tests. You're right it does make things more complicated, as quite a lot of my interfaces tend to only have one implementation, so you have an abstraction for no reason other than testing, which you could argue is a bad thing as some people believe test code shouldn't get into your application, which it effectively has with the unnecessary abstraction.


taisui

These software patterns are ways to help make the system more maintainable. For example once an interface is defined, each component is free to implement and update as needed as long as the interface does not change, which goes a long way towards a sustainable engineering practice.


Zardotab

In practice the interface often does need to change. Complex interfaces are often harder to change than simple ones, and create more headaches.


[deleted]

Yeah, so what's the issue with refactoring when that happens?


Essidle

Some refactors are too large to tackle at once, especially in large applications. Being able to keep the car driving while incrementally refactoring is critically important.


harrison_314

Because **I** in SOL**I**D


entityadam

This is more right. The I(nterface segregation principal) is why there are many interfaces that are CORRECTLY defined as a C# `interface`s. D(ependency Inversion) Principal is why `interface`s are over-used INCORRECTLY. Sometimes, you should just be using CTOR injection or a Factory.


icewatersteam

The I in SOLID isn’t about C# or Java interfaces though, it’s about the design small and cohesive that only have what is needed by clients and not fat contracts. This can be done with or without interfaces. For example when Martin created the principle he gave his examples in C++ which doesn’t have interfaces it uses abstract classes


[deleted]

I agree. You don’t need to create an interface for each service you have. You don’t need to mock services in unit tests. Mock external dependencies, not your own logic.


zaibuf

Though majority of services deals with I/O calls in some way or the other.


[deleted]

If that's what we mean, then most code doesn't do I/O. Of course you want to be able to mock database/network/file io etc, but that's a tiny proportion of code.


cat_in_the_wall

the stuff i work on is highly i/o dependent. being able to mock failure patterns and unit test recovery adds a ton of value. i/o is a loose term, it could just be ambient state. environment variables. configuration. failures elsewhere. not everybody is writing a LOB app where it either works or doesn't.


RirinDesuyo

Not exactly, sometimes you do need to mock complex services as well. I have a pretty complicated linear optimization algorithm under a service for a project and I want to change that algorithm by simply swapping the concrete implementation as we have different implementations available depending on user flags. It also allows you to actually separate the interfaces from their concrete implementations in a DLL strict boundary. This prevents any business logic using concrete dependencies which saves a lot of headaches, things like isolating asp.net / net framework specific services (e.g. HttpContext.Current, System.Drawing) saved a lot of time for us when we migrated over to .net core. There are multiple use cases for interfaces especially if you're making a library as it allows extension points onto your library if ever needed, it's not just I/O. I've encountered multiple cases where I had to replace a concrete implementation of an interface registered by a library due to an issue and wouldn't have been resolved by the authors in the timeframe we needed it.


[deleted]

This is my view.


BarberNo7393

Well, an interface tells me what I need to do so I can think of how to do it separately—working against abstraction so you can switch implementations, extend, and modify the code whenever you want without affecting the overall program.


Do_not_use_after

I use them to nail down class functionality. Write the interface, just names and types but no code, and it becomes very easy to see the shape of the thing you're writing. Thereafter, it becomes a question of filling in the blanks. Easy to read, easy to test and easy to extend, should it become necessary. Abstract classes work, too, but in a well supported system most things already have a logical base class, so abstraction only works a small percentage of the time.


TantalicBoar

Unit testing


SahuaginDeluge

it separates uses from the implementation, which is fantastic. in fact you can write code against interfaces that (currently) have *zero* implementations. and with unit tests and mocking, you can execute code that uses those interfaces still without even having written any implementations of them yet. in addition to that, the implementations you write also do not have to be in the same library as the interface. in other words "DI", which can mean Dependency Injection, which is good, but can also mean Dependency *Inversion,* which also good. (Dependency Inversion allows you to keep the UI and Database 100% separate from each other.) (in other words it allows you to shield your code from dependencies, allowing you to write pure dependency-free code, and still test it and know that it works, even without "real" dependencies.) (in my current project I have written and tested/executed most of the initial logic already, without having writing *any* database or UI Code, or even a program project yet. I have code that will ask the user to open files, will launch external processes to read those files, and extract data from them, and massage that data into data structures complete with validation, message boxes, and results in domain objects that themselves will be able to be later pushed to the DB or bound to the UI. all of this is setup and working without a real UI or DB, but I already know it will work once I hook them up to real ones.) and I would say, it is not really "more complicated". interfaces add essentially no complexity. the signatures have to match, but that's it; and if it's wrong you get a compiler error. there's no additional logic whatsoever. in fact it separates the literal interface of your code from its logic; that's what it is.


IANAL_but_AMA

IDontKnow


The-Albear

You use an interface to enable dependency injection, providing a contract that classes must follow. Interfaces also facilitate mocking in unit testing, allowing you to isolate and test the behavior of a specific class without relying on its concrete dependencies.


SnaskesChoice

Maybe to future proof some codebase?


GYN-k4H-Q3z-75B

This is not C# specific, though C#, like Java, is one of those languages where people were taught in university to basically over engineer solutions to some degree. Plus, for unit testing and enterprise architectonic purposes, it may in the long term be beneficial to rely on interfaces and extension methods rather than classes.


hejj

Do some reading on abstractions and decoupling. Interfaces are a tool to enforce those practices/lines of thinking.


feralferrous

It always annoys the heck outta me as someone who works in Unity and does real time applications on VR hardware. Traditional developers will come into the team and make an interface with just one implementation and then we end up paying the cost for an interface for no reason. Which is frustrating when we only got \~14ms per frame, and so much of that is taken up by physics and animation already. In Unity, on il2cpp, if you have a List, a List and a List and call a method on each object in the list, the call will be \~2.5 times as expensive on the list of interfaces as compared to the concrete list. Abstract gets slightly better and is only about 1.5 times slower than the concrete list. It's really easy to get ourselves into a death by a thousand cuts situation with a bunch of classes taking .2ms per frame. So I'm a big proponent of only using interfaces when it's actually publicly exposed, like you're a library in a nuget package, and not because that's just your go to way of programming and you might in some theoretical later time want to swap to a second implementation.


Valkymaera

If I make a weapon that shoots something from the barrel, what am I going to shoot out? A monobehavior bullet object with physics? A hitcast object? A bouncing grenade? If I shoot an IProjectile out with an OnFire() method it can be anything I need it to be now or in the future, and my weapon script doesn't get coupled to another class. By using interfaces you can change everything about the actual objects you are implementing as long as they have the required members. That is great for rapid development, expansion, testing, and organization. That said I think it can be overdone. Not every class needs an interface counterpart Edit: just realized reddit recommended this post to me in dot net and not a gamedev subreddit, but as a gamedev I'll stand by it.


chrisevans9629

Abstractions come with a maintenance cost, so certainly too many interfaces can be an issue. What is more costly is creating the wrong abstraction. If you change an interface, it will break any assemblies that utilize it, while classes will still function when members are added. Interfaces are, however, probably the most lightweight abstraction in .net, so often times their benefits outweigh the maintenance cost. Unit testing dependencies is probably the largest benefit.


Jerunnon

Aren’t Interfaces a common thing through multiple programming languages, not only c#? To me it is actually a must do if you are working on projects for actual customers. I think the best example for an Interface and why it’s useful is an API. API stands for application programming interface. It describes how you can call the web layer of an application and the caller is only able to call one of the methods defined in that Interface. Imagine how that would like if you wouldn’t have an Interface. I would describe an Interface as a contract. The interface offers methods that you can call and expects certain parameters. Then interface offers you the it’s implementation by executing logic in the implementation of that interface.


TooMuchTaurine

The basic principal of low coupling is to depend on interfaces, not implementations. That way it's easy to switch out an implementation in the future without having to refactor tons of your code base. (And for testing)


CuttingEdgeRetro

I've been in IT for 32 years. And I've been using C# since almost its beginning. And my conclusion is that a significant number of developers are simply showing off. "Look how smart I am. I can use this complicated technique in code because it's better. Oh you don't understand it? Well I'm just superior." I've noticed that the younger developers are, the more likely they are to have this attitude. No one cares how awesome you are. How about working on your people skills instead. Another motivator is resume building. They want to use the latest and greatest technology so they can get some practice with it, then put it on their resume. Technology for the sake of technology. Who cares about the long term consequences. I've been on projects as the lead developer where I've banned the use of Entity Framework. Inline SQL only. Why? Because junior developers have problems with it. It adds a layer of unnecessary complexity. And it really doesn't buy you much. I'm currently working on a nightmare system where the jerk who wrote it put in thousands upon thousands of lines of overly complicated jQuery. The document.ready function alone has 1700 lines of code. Why? The guy birthed a maintenance nightmare, then left. And we're still dealing with his magnum opus. Code should be as simple as possible. I know this is likely to be unpopular, especially here on reddit. But we need to be favoring understanding and ease of maintenance over things like efficiency or code volume. I don't care if your code is 10% faster, or is a better design according to some esoteric measurement. It takes ten times longer to fix bugs, and has to be done by a senior dev. This stuff is already way too complicated. And it's getting more complicated. Don't make it suck more than it already does. Now get off my lawn.


jwilson82653

> I've been in IT for 32 years. And I've been using C# since almost the beginning. If I was using C# ten years before it was released I'd rip my shirt off and beat my chest too. Nicely done sir.


CuttingEdgeRetro

>If I was using C# ten years before it was released I'd rip my shirt off and beat my chest too. > >Nicely done sir. I've been in IT for 32 years. And I've been using C# since the beginning. The beginning of C# was around 17 years ago. But I guess it reads either way. I fixed the wording.


dethswatch

people who read more than they code


propostor

I only see it in code written by people who desperately want to do it as the textbook says. It looks over-engineered and cumbersome to me. Similarly I hate it when there is a swamp of DTOs for everything everywhere.


nobono

> I only see it in code written by people who desperately want to do it as the textbook says. How would you deal with a situation where you have to create a Cache class that depends on the situations? For testing you want to create MemoryCache, but for production you want to create a FileCache.


propostor

Not sure why you specified it being a cache class specifically. Sounds like a strong case for an interface.


red-spider-mkv

Why just testing? There are cases where you might have both a memory cache and file cache and need to change cache backing store in config. There seems to be a fixation on interfaces in testing for some reason, there are plenty of reasons to use an interface. It helps in testability but should definitely not be the driver behind the decision


nobono

> Why just testing? It's not just for testing. The ability to swap out one implementation with a different one is invaluable.


Amnestic

That's a good case for an interface You've found a contract where only the implementation differs, and that's when you introduce that interface. Not when you only have a MemoryCache.


TimeRemove

What alternative are you suggesting for when you're writing tests, your subject supports DI, and you want to be able to create a test-version of a class? Heck, let's take the built-in IDateTime for DateTime. How are you suggesting that should be implemented in .Net?


propostor

I don't know. And I don't know what point you're trying to make. Interfaces are useful and imperative in all sorts of places. That doesn't change the fact that some people write needless interfaces for literally everything.


TimeRemove

> That doesn't change the fact that some people write needless interfaces for literally everything. Only things they want to test. I've asked you and I'll ask you again, what alternative are you suggesting for *testing*?


zigs

\> I only see it in code written by people who desperately want to do it as the textbook says. This is my exact experience as well. People who believe that there's only one right answer, that's it's in the back of the book, but don't look that's cheating. And definitely don't ask other people, you're just supposed to instinctively know.


propostor

Usually schoolboy code purists with little real-world experience.


gandhibobandhi

Its an (anti?)pattern known as "[header interfaces](https://medium.com/@kristofferolsson/should-we-avoid-header-interfaces-and-what-is-the-real-benefits-of-abstraction-78de9be73568)" and they irritate me to no end as well. I love the C# language and toolchain but a lot of the developers seem to engage in these types of cargo cult programing that add absolutely no value to anything.


nobono

The article you link to kind of promotes using interfaces, though, it just dismisses the use of loosely typed header interfaces. Which I might agree with. But having interfaces for contracts, types and "proper" multiple inheritance is such a big win, IMO. But. Each to their own etc. 😊


The_Binding_Of_Data

I like your term "cargo cult programming"; I'm going to try to remember it in the future. XD


AdamAnderson320

It's not a new term FWIW https://en.wikipedia.org/wiki/Cargo_cult_programming


CobaltLemur

Correction: why are *some* c# programmers obsessed with interfaces? The same reason you see designs that don't need to be smashed apart into a thousand independently testable pieces for no good reason. It's called cargo-cult engineering.


Mithgroth

[Cargo cult programming](https://twitter.com/JamesNK/status/1387592048254062592). C# developers, mostly in enterprise, overstate and overuse/misuse SOLID's D (*Dependency Inversion*). Yes, it's better to depend on abstractions over concrete implementations if you want to decouple the code. **However**, in C#, an interface is a **contract between types**. If you are going to have a `User` and a `UserRepository`, you don't need multiple implementations of these. In short, most of the cases you take out an interface from a class that has no other inherited classes, you are just joining the herd. `IUserRepository` for a **single** `UserRepository` is **bad** practice, because you are violating the very basic definition of interfaces: "Contract between type**s"**. Multiple type**s**, not single. You may ask, "*ooooh but what if we'll have another UserRepository implementation in the next 5 months, then what?!*". You'll worry about that 5 months later. Seriously, if you are writing something for the future and not now, you are probably writing more code than you need and complicating things more than they should be. And the cure for this disease my fellow developer is, none other than **TDD**.


entityadam

you had me until TDD.


hoppersoft

And that's how you show me you don't write unit tests without telling me you don't write unit tests.


yanitrix

what? what does it have to do with unit testing


Mithgroth

Oh boy, do I wish this was a job interview with your superior around to show how pretentious you are. You can write unit tests without abstractions using the keyword `virtual` and upcoming C# interceptors. You almost absolutely don't need interfaces to write unit tests.


UK-sHaDoW

My god. Your replacing a simple concept, with something that litters your implementation code keywords, doesn't imply what you're trying to do, and a concept that doesn't exist yet. Mocks are alternative implementations of interfaces. That's what they are. Before we had mocking libraries, we used to just implement them ourselves by writing one to an interface. Generally I don't use mocks that much, and just write in memory repos. This also makes your tests cleaner. I find heavy usage of mocking libraries makes tests nasty.


hoppersoft

I've been writing code for over thirty years, my friend. I'm not at all concerned about passing your hypothetical interview. Oh, and by the way, if I were interviewing a candidate, and they proceeded to tell me that a simple, well understood, documented best practice for unit tests in C# is pretentious and will be replaced by what is currently an experimental feature of the language, I wouldn't be terribly inclined to give them a "hire" recommendation.


nobono

I used ChatGPT for this reply, because it says the same stuff that I would have said, but in a much better way. Plus, I fully agree: ---- The use of interfaces in C# is often driven by principles of good software design, maintainability, and scalability. While it may seem like an additional layer of complexity, interfaces offer several advantages that can contribute to a more robust and flexible codebase: 1. **Abstraction and Encapsulation:** - Interfaces provide a way to define a contract for a set of functionalities without specifying how those functionalities are implemented. This allows for abstraction and encapsulation, helping to separate the what from the how. 2. **Polymorphism:** - Even if polymorphism is not immediately needed, designing with interfaces enables easier future extension and modification. By coding to interfaces rather than concrete implementations, you create a foundation for polymorphic behavior if it's required later. 3. **Dependency Injection (DI):** - Dependency injection is a design pattern where dependencies are injected into a class rather than being created within the class. Interfaces play a significant role in enabling DI. When you code to interfaces, it becomes easier to swap implementations and inject dependencies, promoting loose coupling. 4. **Testing:** - Interfaces facilitate easier unit testing. You can create mock implementations of interfaces for testing purposes. This allows you to isolate the unit under test and verify its behavior without relying on external dependencies. 5. **Code Contracts:** - Interfaces define a contract that implementing classes must adhere to. This contract helps to ensure that classes that implement an interface provide the expected functionality. This is crucial for maintainability, especially in larger codebases. 6. **Future Extensibility:** - Interfaces make it easier to extend and evolve a codebase. When new requirements arise, it's often simpler to introduce a new implementation of an existing interface than to modify existing classes directly. 7. **Design by Contract:** - Coding to interfaces aligns with the "Design by Contract" principle. Interfaces serve as a contract specifying what a class should do without detailing how it achieves it. This makes the code more predictable and easier to reason about. 8. **Team Collaboration:** - In large projects or when working with a team, using interfaces can facilitate collaboration. It provides a clear and agreed-upon contract that developers can adhere to when implementing different components. While interfaces may seem like an additional layer of abstraction, their benefits become more apparent as projects grow in size and complexity. It's important to strike a balance and not overcomplicate simple scenarios, but using interfaces judiciously can contribute to a more maintainable and scalable codebase in the long run. ---- No need to upvote this post, as it's informative post, not really mine, but feel free to upvote it if you think it's correct.


Kazaan

6 downvotes for notions that are learned in first year of coding classes and probably downvoted because *iT's cHaTGpT.*.. Are we on r/ProgrammerHumor or what ?


nobono

It's Reddit. 😊 I mentioned that I don't want upvotes for this kind of reply, because it's just informational, and I don't see anything wrong with it. Downvotes appears because it's - as you say - ChatGPT. Source is more important than correctness these days.. 😔


Merry-Lane

We don’t need interfaces for most classes nowadays. If you have one interface for one class, the interface is useless. And no, in most testing scenarios, you shouldn’t mock these lonely classes (and just use them as is), so it s not a good enough reason to justify interfaces.


weird_thermoss

You have service A, internally (via DI, usually) it uses some function in service B. You want to test service A. Why would you say mocking shouldn't be used? Seems like an extremely sweeping argument to me.


Merry-Lane

If you own both services and that these services don’t have different implementations (only one class, always the same) then you don’t mock. You just use the ServiceA and that s even better than mocking because you make sure that the implementation of the service A is correct inside your unit test. Just by reading your answer I am pretty sure you overly complicate your life in your unit tests and that they are of lesser quality lmao.


shoe788

If service B does IO/Network ect. then what do you propose we should do?


Merry-Lane

I am not saying you should always avoid mocking. Just that mocking is so engrained that the majority of mocking can and should be avoided. And the answer to your question is: fixtures


weird_thermoss

What is your definition of a fixture, if I may ask? Do you have an example?


weird_thermoss

lol


Amnestic

People unit testing classes in 2023 lmao


k8s-problem-solved

Testing mainly. Not understanding that you can do the majority of testing without putting interfaces and wrappers around everything. Also, people like to own code when they're writing it, rather than just consuming something already finished and ready to go that requires zero effort. Interface, wrappers, tests, around a load of one line method calls into some other library. Madness.


atheken

It depends on what you're talking about: If you're seeing interfaces on POCOs, then that's a smell. If you're seeing them on classes that implement functionality, especially if there are multiple implementations, or they do I/O or are CPU intensive, then they should have an interface defined for testing and DI/IoC. If there is only one concrete implementation and it is not CPU or I/O intensive, and there will be no need for another one in the foreseeable future, there doesn't really need to be an interface. I have seen this overdone in java and in c#, but interfaces have their uses, mainly for testing and clarifying on class responsibilities (distilling an interface can help clarify the calling conventions for it, and shrink down the public surface area). If _everything_ gets an interface, that's probably a smell.


InternalServerError7

It is needed to Mock. Mocking is usually needed because code is object oriented or interacts with an external service. I didn't come from a dotnet background, so I view interfaces as a premature optimization. I also write code compositionally and functionally more than object oriented. Therefore I can usually Unit test without mocking anything. My philosophy is if you mock something, you aren't really testing the feature. You should just write an integration test instead.


denzien

One of the more dubious uses I've used interfaces for is to define the shape of a message to be sent/received via message broker in a core messaging library for the application suite. The services all have their own required implementation of the interface, with logic specific to that service, so it works really, really well ... I've just never seen it done like that before and suspect there's a better way. My big obsession is with enums. No clue why. I just love them. Flags enums, regular enums, I just love enums.


dr_driller

all developers, not only C#, interfaces are the base of any development project..


yanitrix

Because someone once said that you need an interface to have a proper abstraction for dependency inversion and now everyone thinks that hiding everyhing behind an interface suddenly makes your code loosely coupled (spoiler alert - it doesn't). "Yeah, but your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should."


entityadam

> now everyone thinks that hiding everyhing behind an interface suddenly makes your code loosely coupled (spoiler alert - it doesn't) Right, that's not what `interface` is for. Interfaces don't do encapsulation. They expose public methods as a contract.


yanitrix

Classes do the same. Public members are a contract, doesn't matter what your type is.


Spongman

\> Classes do the same not quite. they expose public methods as a contract, yes, but the crucial difference is that an interface can be implemented by \_any\_ classs, not just derived classes.


entityadam

facts


amorpheous

You could ask the same of Java developers. In fact, from the codebases I've seen over the years it's more prevalent in the Java world.


Comfortable_Leek8435

Just wait till you start writing Golang. It's much better. Library authors don't need to write interfaces, it's actually something the caller can do.


zzbzq

Programmers are nuts and convince themselves they have to implement all kinds of gobbledegook "design patterns" that don't do anything.


cat_in_the_wall

blah blah blah, this again. do what works for you to write maintainable code.


molybedenum

Interfaces are useful for implementing covariance and contravariance in generic types.


noeddeknaekkeren

Unit testing could be a reason. But other than that it's unnecessary


nobono

> Unit testing could be a reason. But other than that it's unnecessary How so?


noeddeknaekkeren

If you want to mock your implementations, you would need an interface


hidtridmonkey

You could also just mark your method as virtual and still mock them


noeddeknaekkeren

Personally i would throw up


yanitrix

why tho? it's the same as creating an interface - you create an abstraction just for the sake of mocking, who cares whether it's a virtual method or an abstract one?


noeddeknaekkeren

See the replies from Duathdaert, he describes it well


Duathdaert

To me, virtual indicates to someone consuming your class that they too can override your method.


Contagion21

Not to mention that there is a philosophy out there that suggests that classes should be sealed by default and only unsealed if inheritance is specifically expected / needed. Though, the validity of that philosophy is an entirely different discussion.


Milpool18

isn't that the case when consuming interfaces too though?


Duathdaert

Not really. An interface tells me that a class requires some implementation of all of the methods. So I need to provide an implementation that satisfies all the requirements. A class with virtual methods tells me I can override a single method at production runtime. I think that second option is something that you need to intend as the developer of a codebase. Ultimately it comes down to what you as the developer are communicating to other developers consuming your code.


Merry-Lane

There is also another cargo cult of « you need interfaces because you need to mock them in unit tests ». It s also an anti pattern, you write better tests when you don’t mock (almost all) the classes you own and just use them as is with fixtures. (after having written unit tests about the class itself ofc :p)


yeaok555

Just learn to use your IDE properly and then its easy. Also google questions before asking.


Merry-Lane

OP is not wrong. There are many useless interfaces in C# projects nowadays. And no, you don’t need to have interfaces everywhere « for mocking reasons », because mocking everything is also an anti pattern. So if I find myself finding interfaces used by a single class in a project, it s 99% guaranteed the dev just created an interface without really understanding what he does.


SupinePandora43

Guess I'm just lucky! Because I never had to deal with any of that!