There's more benefits to abstracting 3rd party libraries though. - Wrapping calls to the library with common functionality like logging, metrics, circuit breakers, etc - Encapsulating certain features of the SDK (ie: I don't want a class that should only have read-only access to a DB to have a reference to a DbContext) - Can be easier to mock out for testing Not saying that you should always write abstraction layers but I generally have seen the above reasons as incentives rather than the mentioned ability to swap the library for another one. It can be a difficult choice to make for sure.
@stevep25133 жыл бұрын
Another great one. I save ALOT of time writing raw sql in my application services layer + integration testing. Simple CRUD and transaction script where things are simple, swap to CQRS/ES when things get complex. I find when using lots of mocks/abstraction layers it makes "unit tests" very brittle and a mirror of the implementation. Adhere to YAGNI, you won't need to replace your database ( if you choose Postgres (: )
@sathyajithps0133 жыл бұрын
I've thought about this. Haven't implemented abstraction for 3rd party service though. I went with their own SDK.Thanks for giving a lecture on this.
@CodeOpinion3 жыл бұрын
There isn't a right or wrong because it depends on your context.
@DaveRogersEsq2 жыл бұрын
I kinda agree with this. It's a case-by-case basis. The MS logging abstraction is a good example where you WOULD use the abstraction. And many loggers make it easy for you to do this by putting out a package that implements that abstraction itself.
@codiguard3 жыл бұрын
I would still go with abstraction in example you have shown. To be honest I haven't used Message Brokers, but I assume that when done wisely we still can abstract a lot of things and most of the API will remain intact on the client side in case of message broker "provider" change. Of course there still can be changes to the contract when replacing underlying implementation as you said, but in case of abstraction we need to change part of the API - not all API in case when there is no abstraction at all. Thanks for the video!
@hectorluisbarrientosmargol9303 Жыл бұрын
Totally agree, if inversion of control and interfaces are used wisely I think abstraction can be applied in almost all cases
@ddddddddd3452 жыл бұрын
The rule of thumb for abstractions/interfaces is that their value is equal to volume of things abstracted out divided by complexity & area of interface surface required for the interface to work. In other words: you want to abstract large amount of "stuff" (complexity; logic, whole external systems, etc.) using as small & simple interface as possible. Utility libraries with complex APIs are in practice in-abstractable: they have huge and often complex surface of which most will be used directly by your code.
@marna_li3 жыл бұрын
I used to believe in ”best practice” by wrapping everything, but for things that you will not change it is quite an useless overhead. Libraries that themselves are abstractions, like EF Core, is a good example. There are case when you want to wrap, but as you lean towards, they are few. Of course, unit testing is a valid reason for abstracting away certain dependencies.
@CodeOpinion3 жыл бұрын
Ya, I forgot to mention testing. That being said, don't take a dependency on something (if you can) that has no good testing story.
@marna_li3 жыл бұрын
@@CodeOpinionBefore ILogger, I have seen a lot of less than ideal abstractions on top of logging frameworks. Nowadays, I just expect the de-facto interfaces to be implemented.
@codiguard3 жыл бұрын
There are some scenarios when abstracting data access layer still make sense. For example in case if you don't know what underlying data structure will be - DB, simple file, etc. Of course this is rare case because we usually go with databases for the most part, but still - something to keep in mind. For example "Uncle Bob" in one of his books mentioned that he started some project with simple files as a data structure for testing purposes and then he found out that they actually don't need DB at all and text files are enough also for production environment :)
@marna_li3 жыл бұрын
@@codiguardI would create services that abstracts away everything that I don’t consider standards and things that rarely change in a project.
@walidlezzar23572 жыл бұрын
Thanks for the video! For me the idea has never been to abstract the technical functionalities of a sdk. I wouldn't expose the outbox pattern, stateful messaging etc. in my abstraction. Instead, the idea for me is to abstract the functionality part: in the case of the messaging example, my abstraction would very likely be an interface with a single method "sendEvent" and that's it!
@CodeOpinion2 жыл бұрын
If your abstraction is as simple as exposing one method, then sure. Often times, it's much more than that however. As an example with messaging, if you wanted to have encrypted messages or properties, that's going to be implemented in a very opinionated way by the library you're using.
@berkes2 жыл бұрын
I concur about the reason for abstractions. So I keep another rule of thumb for when to apply or forego: if the abstraction does not simplify the library or make it more concrete, just use the library/SDK/orm. An abstraction would have a chargeCard(), rather than a Card.changeAttribute(chargedAmount: 1337).save(). This makes it more concrete and simpler. But a AuthLib.isAllowed(user, 'update', profile) is hardly made simpler or more concrete by an abstraction layer. Obviously, benefit of less dependencies, unstable third parties, testability, etc still apply, so even if an abstraction does not simplify or concretise the lib, it may still be a good idea.
@evancombs51592 жыл бұрын
This is what I see as the primary purpose. Simplify the use of the dependency by hiding all of the ceremony and/or repetitive code. I don't want my code to have to worry about how it works.
@brandon924711 ай бұрын
Perhaps the issue comes from a tendency to conflate the bridge and adapter patterns? When I was following along, it was unclear whether we were talking about an abstraction vs. adapter.
@donflamingo43253 жыл бұрын
The Abstraction Layer in big enterprise applications is one of the fundaments. If You are using the N-Layer architecture, You must separate the application, from the infrastructure. From experience, the best way to get it is through abstractions. Why? 1. Infrastructure can be replaced, if You must use technical edge cases in Your abstractions, You did something wrong. 2. Directly working on core SDK is dangerous, when the external library will be updated, Your code can be broken or may have a lo changes.
@Zikakoo3 жыл бұрын
On point 2. But if you are updating the SDK then your abstraction might not work. So then you must update your abstraction and now you are most likely slowly coupling your abstraction to the the underlying SDK
@donflamingo43253 жыл бұрын
@@Zikakoo But You need only change to one place, not the whole application :-). That's a little difference Friend :-)
@CodeOpinion3 жыл бұрын
This is why I lean towards vertical slices rather than layers. At the end of the day it's about limiting coupling and increasing cohesion. Almost everything I talk about on this channel is rooted in coupling. FWIW, if you haven't already, check out the video on Vertical Slices. kzbin.info/www/bejne/mYe5fpWrgNKBm9U
@bobbycrosby97653 жыл бұрын
I still like to add a layer when I only use a tiny subset of features of a library. For the swap it out argument, it's the most lazy one I encounter. Anyone that says this I ask "oh, how many different libraries did you test to see if your abstraction layer works?" The answer is almost always 1. This is one of my big problems with over-abstraction. It's false flexibility, and it turns your code into a lie. When you create an interface, as a reader of code, it should be a contract of "I thought about this, I made my code flexible, here, use it". In a lot of enterprise software, it's actually "I looked at one scenario, layered an interface on top of it because I could, good luck using it in any other scenario".
@CodeOpinion3 жыл бұрын
"I looked at one scenario, layered an interface on top of it because I could, good luck using it in any other scenario". 😆 Very true.
@johnf77553 жыл бұрын
As usual Derek I appreciate your content but have to respond because while what you're saying is true it's a bit like "If you're going to do abstraction wrong - don't do it". Here's an idea. Instead of trying to abstract all the functionality of the 3rd party library, how about just making a "small client specific interface". Now your code can depend on that, and through the magic of the adapter pattern, not even know that the 3rd party library exists. And the implementation of that interface can use all the features of the 3rd party library. The driver for this is never that I might want to substitute an alternative implementation later. It's so that my code (my business logic, not all the code I need to write to call the 3rd party library) can be pure and deterministic and live in a project with minimal package dependencies. It isolates business logic into one place. It prevents coupling between 3rd party dependencies. Unit tests on that project build fast. As an example, say your class wants to read a file, process the data, and write a file. There's no need for System.IO.Abstractions, just an interface with 2 methods. The implementation of which can just call File.ReadAllText etc.
@CodeOpinion3 жыл бұрын
Well the issue is that you don't know you're doing it wrong. If you're creating an abstraction that starts off small and you keep adding to it to expose more underlying functionality from the dependency, as you need it, you only know you're "doing it right" if you have multiple different underlying implementations. Now as we both mentioned, yes creating an indirection/abstraction to prevent direct coupling has a lot of benefits and should be a goal, absolutely. My point is that that's not always the case depending on the tool your abstracting. Is it beneficial, most of the time, likely. All the time, no. My concrete example of a messaging library is one that you shouldn't abstract. If you were using NServiceBus, you'll cause yourself more complexity by abstracting it. Appreciate the comment, John.
@johnf77553 жыл бұрын
Fair point if the interface keeps growing but this is less likely if you're sticking to the client (class) specific interface (ISP). And I maintain that the interface is the contract between your code and the dependency. Other possible implementations are irrelevant.
@0x72733 жыл бұрын
I love wacthing your videos and having those 'Aha' moments when things click in my head.
@MuhammadAdam-ko8my3 жыл бұрын
abstraction layer ought to be implemented when you want your code to interact with specific set of APIs which will be remained same or minimal change whatever implementation added behind that APIs .. If changing implementation affecting exposed interface to be changed greatly or the abstraction layer is mostly driven by implementation then I think it is better to use it directly rather add more complexity.
@CodeOpinion3 жыл бұрын
Pretty much sums up what I was saying!
@sarabwt2 жыл бұрын
@@CodeOpinion The problem is that the abstraction is thought as implementation. If I create a Repository interface and I define query as Repository.query(String sql, Class result) this means that my abstraction is not an abstraction. I know the example is kind of exaggerated, so it is obvious, but it can be way subtler and bite you after. When you gave the messaging example I think you are talking about doing something like MessageAbstraction.send(topic, payload) (tied to implementation) and not something like EventRepository.somethingHappened(context) right? I think that the problem comes from doing abstraction over a library/framework/tool/technicality and not over something that has to be done.
@jayhey25772 жыл бұрын
So what is alternative???
@rickpowell13113 жыл бұрын
This is great! Thank you for all your advice Interesting that you gave the outboxing pattern as an example of something you might look to 3rd party libraries to manage the abstraction. I'm yet to find a decent package in .Net however. Any recommendations?
@CodeOpinion3 жыл бұрын
NServiceBus, MassTransit, Brighter, CAP
@jaroslavsurala15373 жыл бұрын
What about MassTransit library it is some kind of abstraction from real event bus. It is bad?
@CodeOpinion3 жыл бұрын
MassTransit, like NServiceBus, are abstractions over a transport that also provide implementation for various messaging patterns (like I mentioned).
@frotes3 жыл бұрын
MassTransit is exactly like the messaging library mentioned in the video. Just use it Plus it’s OSS, so you aren’t going to get burned if it goes away. You can also grab it and make modifications as needed
@jimhart57973 жыл бұрын
How does impact testing? Say I wanted to implement RabbitMQ. Typically I would creat an interface abstraction for the dependency, and use DI so it is testable.
@CodeOpinion3 жыл бұрын
It doesn't. Don't use a dependency that doesn't have a good testing story behind it. The RabbitMQ client returns interfaces I believe so fake that rather than your own interface. Or better yet, don't use the RabbitMQ SDK directly and use a messaging library that has a full blown testing story.
@bronekjelonek33233 жыл бұрын
You also might want to have an option: use X or use Y (like in-memory/file based/fake). For tests, for the demo, etc. That's why I like intermitent layer, not sure abstraction is the name. I want to just, i.e. send the message. The same I use for filesystems, for event store, where I have my own implementation on files... However event store is quite complex thing and it took me some time to make something not very buggy.
@MaxPicAxe2 жыл бұрын
No abstraction is better than a bad abstraction imo. At the same time, it is a good exercise for learning to try to build abstractions. Anyway, you learn most from your mistakes.
@iliyan-kulishev3 жыл бұрын
The more reusable we try to make something, the less usable it gets.
@CodeOpinion3 жыл бұрын
Often very true.
@iliyan-kulishev3 жыл бұрын
What kind of things you still abstract in your projects?
@CodeOpinion3 жыл бұрын
Database is often abstracted in a lot of places. File/Blob storage is usually abstracted since the API surface is very limited. Sending to an email service is abstracted if not using SMTP but rather say the API to AWS SES. Again, limited API surface. Using an Messaging Library to abstract a transport.
@FlaviusAspra3 жыл бұрын
Before watching the video: Once you have your regular hexagonal architecture, do not introduce abstractions which are not used in at least two different parts of the code. Still, stronger principles: keep your domain free of any vendors by using pure fabrications. Also stronger: if the new dependency is a whole adapter, then do introduce that, and inside it use your new vendor. An adapter/port provides enough isolation. Don't forget: a microservice has in itself also an architecture, so you can have a set of microservices, each of them following hexagonal.
@brandonpearman92183 жыл бұрын
I disagree with your base reasoning for abstraction. Abstraction should reveal the required functionality. There for any tech or 3rd party library should be able to fulfill that requirement, ie if the lib/tech has more feature that what your abstraction allows for, it is irrelevant because you dont require that anyway. I think the problem you are describing is not fundamental to abstraction but a result of architects trying to create company wide abstraction that can cater for 100 different teams. Then all they are doing is trying to expose all the functionality of the underlying tech/lib... leading to all the problems you are discussing. Abstraction done right allows easy change of tech, change/upgrade of libs, can offer more functionality by combining multiple techs/libs and simplifying tech/libs to your specific use case.
@CodeOpinion3 жыл бұрын
Thanks for the comment! I agree pretty much. "Done Right" is the interesting part there though.
@brandonpearman92183 жыл бұрын
@@CodeOpinion Yeah any pattern is good or bad depending on implementation and use case. The moment a pattern becomes popular it gets misused, then everyone says its bad and moves to the next shiney pattern... until that becomes misused... and the circle continues. You do videos on how to do CQRS right, but that is becoming an abomination in many orgs. Same goes for microservices. :( but dont think they are throw away ideas, because of bad implementations.
@brandonpearman92183 жыл бұрын
@@CodeOpinion Also not trying to be difficult or combative on the idea, but I personally think its a serious problem in the industry. DDD is another one, which i have seen you do a video on. We need some unpopular ideas.
@CodeOpinion3 жыл бұрын
@@brandonpearman9218 No, I appreciate the comment and discussion. The point of my video was be careful what you abstract because it can turn into a net negative. I'm not saying don't abstract, that would be insane. I'm saying not everything needs to be abstracted. In a different context, per Sandi Metz, prefer duplication over the wrong abstraction.
@yasinnabi2 жыл бұрын
wow wonderful channel... I enjoyed watching. SUBBED ! a fellow creator ...;;;