 Howdy. I'm John. I'm going to talk about modernizing the galaxy back end with typing and dependency injection The work that we've been doing on the galaxy back end working group over the last year A longer version of this video the real version of this video is linked there This is just sort of a preview these slides are derived from the galaxy architecture slides part of the galaxy training network The link is there with the 21 on one release of galaxy We added my pie static type checking to to galaxy Thanks to the work of Nicola and others We now have a Python 3 only only Codebase and the annotations are really nice in this syntax If you're developing galaxy You use the talks there the talks man listed there to to run my pie And do the checking Well, there's links here to a nice blog post about why you add sort of types to Python code and a cheat sheet for using my pie and Doing typing at the and the typing module that sort of helps create useful annotation develop galaxies back end at all You've come across this app component. It's a big object that we stick a bunch of various back-end components on to It is a prime example of a God object God object According to Wikipedia is an object that knows too much or does too much and is a code smell Not only does app know and do too much in Galaxy's case. It also has used too many places Every interesting component every controller every web transaction has a reference to this app object And what's the problem? We've been working on and thinking about for years Here's a very typical example of a galaxy back-end component on that consumes app Unlike a lot of other components I was trying to d d d couple it from app So I pulled off just what I needed from app and the constructor and and the data set collection manager doesn't have a reference to app But it does still use app to construct all of its dependencies in various ways and and it does use the model and the security subcomponents of the app object In the longer version of this I go through you know one typing scheme We could have used for app And but I sort of will just skip for expediency sake to the structured app that we did land up using it's an interface and We use this interface and sort of make the imports cleaner and try to get closer to a Directed acyclic graph for the components of Galaxy's back-end We can now sort of With my pie and in typing we can now sort of say app is a structured app And and we now have my pie providing type checking inside of here and the IDE can provide type hints You know app.model exists. I'm the idea you can tell you that We're still constructing these dependencies directly And this is unfortunate For a few different reasons. I'll just highlight one here and that's You know, we just want to use a history manager We don't want to know how to construct a history manager, right? I mean as we can see here the different dependencies are constructed in different ways You thinking about unit testing makes it really clear, you know, if I'm going to unit test this I need to construct this app, right? And so what what what components of app are necessary? It's the only way to really know that is to come in here and look at it And if I'm constructing, you know that history manager from inside of here, how do I stub that out from the outside? This is this is not a good setup for unit testing Doing dependency injection where we actually send the dependencies that are needed for the object During construction makes unit testing a lot better and actually if we look at it now We're not using app anywhere in here. We've got nice type signatures about what parts of app are needed Yeah, there's a much better way to design the data set collection manager In fact, we did make this change and we're in the process of making this change to other components Problem with that approach is that we've created complexity inside the constructor for complexity and calling the constructor Now the thing that's Initiating initializing the data set collection manager needs to know what these six components are and how to build them We use to address this is a type-based dependency injection The idea here is that we have a container which keeps track of recipes for how to build objects of a given type Then when we need a dependency for an object We can sort of recursively check the container for how to build that dependency with this approach constructing that data Set collection manager becomes as easy as saying container give me your data set collection manager It's a few different libraries for doing this Lagom is a very modern one written to be pipe type written to be Python 3 native and and type-based and the longer version of this talk I go through how dependency injection and types sort of make each other better. I go through how You know, we were able to use dependency injection to Unify the two kinds of controllers that we currently have in the in the galaxy code base and you know The newer fast API controllers in the older Galaxy framework controllers and we're able to use dependency injection uniformly across every layer of the application Including the new salary tasks Which leverage a dependency injection and also talk about you know deconstructing the galaxy app object a little bit further You don't have time for any of that I'll just sort of give some final tips for designing galaxy backend components consume only the related components that you need avoid Up whenever possible and it take inputs to the component with Python types Use interface types to shield consumers from implementation detail and rely on galaxies dependency injection to construct the component and provide it to its consumers Thanks