tfw you’ve created something that excites you like nothing in years but it feels like you have to write a book first to lay the context to make wide appreciation even possible
Look y’all, it’s all public on my GitHub. I just don’t know how to go the path of testability → loose coupling → hexagonal architecture → service locator without losing 95% of the audience at step two by the latest. I’ve extracted something I’ve used successfully for years and applying it to other work projects was always a HUGE improvement but you only get one chance to make a first impression.

@hynek I like what I see, can it layer contexts/disposal/dependency?

We have a little monster in pytest for managing fixture's

@hynek I have at least 15 projects where I want such a things,but it's hard in python and the pattern is so often despised
@hynek but to be fair,this is also sliced bread: 😜
@hynek a key issue i presume from examples is that factorys ain't context managers

@ossronny yes, they’re much better.

The container is an `with closing(container)` context manage and the factories are pytest-style generators. MUCH more ergonomic in practice.

@hynek pytest style fixtures are a bit of an mistake in terms of concern Separation, they make a convenient api but the lack of a porcelain level that hasn't concrete language level construct's and layer's makes pinpoint Testing insanity tricky and typically sidestepped
@ossronny everybody has and I’ve decided I don’t care anymore after having projects with ~10 resources and 100s of lines of boilerplate. The main reason I’m holding it back is that… I just don’t know how to promote it such that people “get it”.
@hynek the solution includes ai designed face huggers with a hexagonal payload
@hynek the thing is that for full features set you need a layered resources Manager, a service locators and a dependency injector working together and that's choke sized instead of bite sized thing
@ossronny Maybe the fact that everybody is trying to do all of that is the whole problem? At this point I’m happy to admit I have a 95% solution, but it has made all my services across all frameworks (so far: Flask, Pyramid, AIOHTTP) more readable, more concise, and easier to test. I feel like once you need more, off-the-shelf isn’t gonna cut it anymore anyways.

@hynek all of the frameworks model their needs as they grow, the results are molded by fate

I'd like to get to a place where collaboration gets us out of that trap

@hynek I believe a key is the interaction of the components, so many concepts are very similar but wired up ever so slightly different

@ossronny I’ve been using this for years, so this is not a first attempt to solve a problem, it’s _my_ trade-off at comprehensibility vs functionality.

It always depends what you compare it to. I compare it to the boilerplatey get_x (Flask) and add_request_method (Pyramid) patterns. Got it working with FastAPI too, which gets super verbose with its own DI once you have more than 2 dependencies.

@hynek I absolutely agree with that perspective
@ossronny the question for me is really how to promote it because I really don’t know. you need so much context both in experience (many services) and knowledge/pain (hex arch, loose coupling, etc) and from structlog I know that the amount of people who have both is very slim
@hynek @ossronny it doesn't help that the term 'services' is very overloaded in this context
@tintvrtkovic @ossronny yes, and i’m unhappy but i didn’t want to make up my own nomenclature
@hynek @ossronny it wasn't a dig against you, but we as a community need to come up with something better
@tintvrtkovic @hynek everything around that topic currently got me into a state where i want my inner SpongeBob SquarePants to come up with the names, not Sure if therapy can help

@hynek @ossronny

I think if the present audience is really that small, it's okay to let the package speak for itself for now. You will continue to extract value from it personally until the audience grows large enough for it to be worth proper thorough communication.

If the target audience is growing, you'll get many more chances at first impressions even a year down the road than today, and maybe the API will have hardened a bit by then and it'll also be easier to communicate.

@blakeNaccarato @ossronny One of the things is that I’d love to get qualified feedback before freezing the API. It’s super nice to just iterate and push out releases https://github.com/hynek/svcs/blob/main/CHANGELOG.md
svcs/CHANGELOG.md at main · hynek/svcs

A Lightweight Service Locator for Python. Contribute to hynek/svcs development by creating an account on GitHub.

GitHub
@hynek @blakeNaccarato one thing i recommend is to have inner plumbing in Terms of Python primitives like context managers, it's a key pain point for making a load of things in pytest testable, and it's hell to replumb
@hynek I am interested, but on vacation right now. Will try to remember when I am back. This is kinda my backyard with ZCA and such in the past.
@hynek - i am a huge fan of your work. I'll find your GitHub and sign into it. I've spent a career explaining complex material.
@hynek if one was familiar with dependency injection, layering your business logic for testability and that sort of things, but not formally acquainted with hexagonal architecture, would you recommend any pointers?
@georges I have _just_ pushed a huge update to the glossary and I looks like you’re the perfect person to give me feedback on it: https://svcs.hynek.me/en/latest/glossary.html
Glossary

We are trying to make the purpose and best use of svcs as clear as possible, even if you’re unfamiliar with all the concepts it’s based on. As such, the glossary got slightly out of hand, but we ho...

svcs

@hynek ah, yes, so it appears I was familiar with the idea from my previous job, but not the name.

Let me rephrase to see if I've understood:

The term "dependency injection" is specifically about your code getting its dependency as input arguments. Service locator is a different mechanism, that shares a common goal.

Aside from that, hexagonal architecture cares more about where you draw your lines, what you call your components and interfaces.

@hynek so to put that together in a sentence:

My previous job was using a hexagonal architecture, with different components for the http views, the business logic, the database access, and the network call to other services.

All of this was tied together with dependency injection (implemented is scala as argument to classes, with the glue being one big main that instances everything in order).

Does that sound coherent with what you were explaining in the glossary?

@georges yep sounds mostly right to me! hexagonal is mostly about thinking more clearly about components and less about “layers” (each component can have arbitrary layers, too).

and the diff between injection and locator is literally just the acquisition mechanism with upsides and downsides on both side. it’s explained a bit deeper in https://svcs.hynek.me/en/latest/why.html#is-this-dependency-injection – I should probably transplant some of the text

Why? - svcs UNRELEASED documentation

@hynek thanks, things are now way more clear in my head than they were this morning :)

It also looks like on that topic I should resume reading Architecture Patterns with Python. (And wrap my head around how to use sqlalchemy properly in this context)

@hynek coming from you - sounds super interesting!
@hynek please do share what you're creating next 😀​
@hynek so you invented sliced bread ,I have bad news for you 
@hynek a blog post might be enough? 😅 (even a long one, like NJS's blog post for trio?)
@tshirtman njs blog post :: war and peace 😅
@hynek i mean, it's not waitbutwhy, but it's kind of long :)
@hynek is this a new health and wellness movement or a new test framework?
@sgillies is there even a difference, practically speaking?

@hynek FWIW, as far as I can tell this is pretty cool. If I ever have to use Flask again, I'll insist on using this, and if I write something using another framework, I'll at least spend 30m thinking whether I should write and contribute an svcs.<framework> plugin.

I'm...a pretty easy sell? It's a little bit like the Pyramid registry (which I love) and a little bit like Twisted Componentized (also awesome), but palatable to others.

@hynek (If I use Django, the changes are higher than if I use Pyramid, because Pyramid registry does 80% of that...OTOH, if I implement it for Pyramid, it'll be "you get the svcs registry from Pyramid registry")
@moshez I’ve got pyramid integration working and in prod too, but i’m not shipping it because pyramid currently doesn’t work on 3.12 and i don’t work around it: https://gist.github.com/hynek/b59604c155aed2a32cca8a6596e9b3f2
pyramid.py

GitHub Gist: instantly share code, notes, and snippets.

Gist

@hynek That definitely changes the cost/benefit analysis on using it with Pyramid! I'd give >70% then that I'll use it in my next web project (up to ~99% if it's in flask)

Thank you so much, this is awesome.

@hynek Dependency injection vs service locator

I didn’t have that distinction in mind

In Python i felt most Of the DI libraries were too complex, with type annotation inference and what not.

I ended up using punq, which is actually service locator if I follow these definitions.

It looks like svcs is essentially punq plus generator definition & cleanup functionality?

@florimond dunno, I have not used punq. I’ve started by wrapping wired, started adding stuff I needed and eventually realized I just need a dict and my own additions are the actually interesting part
@florimond Also fun fact: I didn’t know about service locators either. I’ve just implemented one by accident and learned about the concept later.

@hynek I was wondering if you'd be solving the worst part, but I think "The main downside is that it's impossible to verify whether all required dependencies have been configured without running the code." answers my question there.

That's always the tough thing; how to be sure your various environments provide the same necessary set of capabilities when not every code path is going to reach those service discovery steps. Even 100% test coverage doesn't save you :(

@offby1 I find it very easy to test if you make sure that every resource is set in the same place depending on some flag/setting. Also there’s Sentry/monitoring I find people are making a big deal out of nothing but maybe my arch style is just very different. You can just as well misconfigure something I don’t feel this is adding a new error category.
@hynek I don't think it's adding a new one, per se, but — depending on how you started -- it might be pushing the errors into surprising places in your call flow instead of having them happen up front. There is something to be said for having an expensive startup that binds ALL THE THINGS right then, so that you never get to wonder when one of your users will call something that fails to init much later, or conditionally depending on the availability of external systems.
@offby1 @hynek I've been pestering him about this too, but I think this is surprisingly difficult to do while keeping the result actually usable. I have a completely different style of architecting my services which is also vulnerable to this.

@tintvrtkovic @hynek honestly, after a decade or more of professional focus on availability, this is largely why I avoid late-binding dependencies.

That's not to say it's automatically bad; it is, as so many things are, a tradeoff between developer ergonomics, architecture, stability, startup time, etc, etc... this definitely fills a need, and I can see why someone would use it. I’d probably use it depending on what I was building.

@offby1 @hynek Yeah, def agreed. If your errors can't be statically detected, they should at least be at import time (or start time), not request time.