What's the Cost of Indirection & Abstractions?

Ғылым және технология

Indirection is fundamental to software design. Creating abstractions is one common way of creating indirection. The benefits are reuse, isolating complexity, encapsulation of dependencies, and more. But what's the cost of indirection & abstractions? Cognitive load to fully understand all of the layers of a request and performance.
Dotnetos Essentials is a new, free online course that provides you the basics (and some advanced topics) of async programming and concurrency, C# 9.0 and .NET diagnostics. 3 online courses gathered in one place for you to enjoy! Sign up on our website for 1 month free access to Async Expert, .NET Diagnostics Expert and C# 9.0 Professional.
essentials.dotnetos.org/?utm_...
🔔 Subscribe: / @codeopinion
💥 Join this channel to get access to source code & demos!
/ @codeopinion
🔥 Don't have the JOIN button? Support me on Patreon!
/ codeopinion
📝 Blog: codeopinion.com
👋 Twitter: / codeopinion
✨ LinkedIn: / dcomartin
0:00 Intro
0:45 What is Indirection
3:48 Code Example
5:52 Mental Capacity (Cognitive Load)
7:12 Performance Implications
#softwarearchitecture #softwaredesign #softwareengineering

Пікірлер: 35

  • @seangwright
    @seangwright2 жыл бұрын

    I often use indirection (even when I have simple use-cases) because it gives me a seam across which I can lay my cross-cutting concerns (logging and caching primarily). That said, I find vertical slices to be far more important, because with them you can opt-into indirection per-feature, if it's needed.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Bingo!

  • @teriyakov
    @teriyakov2 жыл бұрын

    I struggled with the first part of the video but after the code example and diagrams, it was clear as day. Thank you for this. Usually when you join a team, you tend to get bogged down in whatever abstractions or indirections are in place. Always assuming there is a reason why the path of data is so convoluted. Sometimes there are excellent reasons for it. Sometimes, it's just down to following patterns we're used to. I know i'm guilty of that myself. It's refreshing to see things differently and even better to have the chance to implement this on new projects. Because lets face it, once it goes live, whatever architecture you have is stuck in place for a very long time. Thanks again.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Thanks for the comment! Insightful.

  • @johnf7755
    @johnf77552 жыл бұрын

    A good thing to think about for sure but I feel like your example belongs in a video about not misusing LINQ instead. The indirection here isn't the issue, it's that .FirstOrDefault() should be added to the query before the database hit. Also you imply that the specification pattern was used to allow reuse, which seems like misdirection, as sure it allows reuse but there are plenty of reasons for not wanting to embed your queries in handlers. You could have solved the problem by adding another specification for example.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Thanks for taking the time to comment, I appreciate it. Could the code be changed to provide another method on the Repository to include as specification that only returned Single() rather than List(), yes. That would eliminate having to fetch a lot of records you don't need, but it doesn't solve selecting the wrong properties for a given use case. Using a repository that returns whole object graphs for every use case is causing all of this because it's an creating a more narrow abstraction (and indirection) from another abstraction (EF).

  • @abdulhamidalsalman
    @abdulhamidalsalman2 жыл бұрын

    thank very much for taking the time to develop these awesome tutorials and sharing your wisdom 👍

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    No worries!

  • @brandonpearman9218
    @brandonpearman92182 жыл бұрын

    100% agree, glad you brought this up. I feel many developers just keep adding more and more without ever considering the cost. But I'd say that not all indirection is equal. eg I'd say queueing and mediatr is definitely more complex than a DAL (your DAL example is a little more complex than it needs to be, and like you say its performance issue is due to it being very generic for reuse, but id say that's a "generic vs specific" argument rather than an indirection issue). I find messaging is more complex for a few reasons 1. where does it get handled, local or another service 2. is it publish where there may be multiple handlers 3. is there a pipeline/behavior before it hits the handler 4. have to navigate the project to find the handler because the IDE cant "go to implementation", etc. VS a DAL which is a method call, "go to implementation"... done.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Yes agree, I could of used a different example however I was just trying to think of something "simple" that could get the point across. Often the issue with I find is exactly "generic vs specific" with indirection because folks are trying to isolate dependencies which ultimately end up making them generic abstractions on top of it. Yes it being generic is causing the perf issues but the root of the issue was because of adding indirection. I appreciate the comment.

  • @alibayat3884
    @alibayat38842 жыл бұрын

    Amazing video! Thanks for sharing.

  • @Unleash132
    @Unleash1322 жыл бұрын

    Amazing video! I'm always baffled whether to use repository pattern with ef core or not. ef core is already uow + repository pattern so it feels silly and a lot of work to add the repository layer.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    I can somewhat understand why some do it. I'll be creating a video about when and where I do use a repository that should hopefully clear up some of my thoughts about it and some of the code examples I have.

  • @andrii_ky
    @andrii_ky2 жыл бұрын

    Hey Derek. Great channel. Can't stop binge-watching it :). Wanted to ask if we can consider adding new level of abstraction and indirection as applying DI principle. It looks like it for me. Because a lot of young devs consider DIP only as applying IoC container.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Youn mean Inversion of Control? Adding a DI container (applying IoC) is adding indirection, yes.

  • @andrii_ky

    @andrii_ky

    2 жыл бұрын

    @@CodeOpinion No, I'm asking if adding an additional level of abstraction and indirection also can be considered as applying DIP. For example, adding Repository for getting data(and transformaing it to domain objects) from EF instead of directly getting data from service classes. Or adding Factory method classes to create objects instead of creating them directly? Or on a higher level, instead of directly communicating between services, using a message broker instead. Are these examples a DIP implementation?

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    @@andrii_ky Yes, because depending on an abstraction is ultimately adding indirection.

  • @andrewreiser3584
    @andrewreiser35842 жыл бұрын

    This video is more an exercise in refactoring bad code, rather than making any good points about abstractions. Repositories do suck and I do not use them, but that doesn't mean we should throw the baby out with the bath-water. The power which the message-bus / pipeline which Mediatr adds outweighs any disadvantages. I tend to not use it for GET requests though. There's a lot less to validate/process with a get request.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Of course not all abstraction is bad. The purpose of the video was to that all indirection and abstractions have a cost and in our industry, specifically because of cargo-cult, we tend to overuse them. I created another video recently that points out when NOT to abstract, specifically tools: kzread.info/dash/bejne/pqWlqsGCksLNdMY.html

  • @haraheiquedossantos4283
    @haraheiquedossantos42832 жыл бұрын

    Great video

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Thanks!

  • @AdroSlice
    @AdroSlice2 жыл бұрын

    It's much higher than most might think...

  • @DarkLegacyBlue
    @DarkLegacyBlue2 жыл бұрын

    You could inherit that new OrderSummaryViewModel by OrderViewModel so at least the shared fields become reused. So an OrderViewModel is just an extended OrderSummaryViewModel, though you'd probably want an interface as well to bridge them better. Also, that Controller -> EF -> Database process is really quick to prototype but my god is it a PITA to refactor as things become more complex.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    Yup, it can be a total disaster if you're not paying attention. Context matters on the size of the application you're building and how application code gets executed. How you want to handle coupling, dependencies, etc. all play a factor.

  • @DarkLegacyBlue

    @DarkLegacyBlue

    2 жыл бұрын

    @@CodeOpinion We inherited a code base that used the Controller -> EF -> Database model exclusively and code duplication was rampant. I'm certain with better discipline you can avoid it but in this case it was rife with abuse and I'd argue that the simple flow process encourages it. I am of the opinion that having even a single layer of abstraction is important simply to instill code reuse among your teams even if you don't utilize the mediator, IOC, dependency injection, etc patterns that you displayed in the sample project here.

  • @ghevisartor6005

    @ghevisartor6005

    2 жыл бұрын

    I tried inheritance between viewmodels in a similar case where we had 3 types of products and a ordersummary viewmodel, it can be also a nightmare. Composition is more flexible in such cases imho.

  • @chrisser364
    @chrisser364 Жыл бұрын

    ur so smart.

  • @mtalhamadni6605
    @mtalhamadni66052 жыл бұрын

    I want a little code implementation example in C++

  • @mtalhamadni6605

    @mtalhamadni6605

    2 жыл бұрын

    Can You send me with explanation or any video link of indirection pattern implementation in code

  • @feelingeverfine
    @feelingeverfine2 жыл бұрын

    Big fan of Ardalis’s specification library but you are using it all wrong. You should project inside of your spec to keep everything as an IQueryable until you are done with that spec. You should also compose your specs. This solves the entire problem you were having with reading everything in memory and then selecting.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    The code I was looking at was not mine but from the was from the eShopOnWeb sample application from github.com/dotnet-architecture/eShopOnWeb While I can the specification being useful to centralize filtering logic on an entity, that's only useful to me if there are many queries requiring it. But regardless of that, it's only filtering, not specifying what data to select from an entity. That's the cause of the repository abstracting EF and not wanting to leak EF.

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    I really need to create a video on why I don't use the repository pattern for queries but will use them to build an aggregate for commands.

  • @bernhardkrickl5197
    @bernhardkrickl51978 ай бұрын

    The only problem in software that you can't solve by adding indirection is too much indirection.

  • @ruirodrigues705
    @ruirodrigues7052 жыл бұрын

    Bottom line... don't over-engineer things! :)

  • @CodeOpinion

    @CodeOpinion

    2 жыл бұрын

    The problem is knowing you're doing that. Experience is the difference between "let's add this just in case" vs. "let's add this because {context}".

Келесі