Athena Dependency Injection v0.2.0 Release Notes

Release Date: 2020-06-09 // almost 4 years ago
  • ๐Ÿ“š This release includes an overhaul of the DI implementation; in turn bringing about many improvements to the shard. See the linked sections in the API documentation for more details/examples.

    Highlights

    • The ADI::Service module is no longer required to register a service
    • Service dependencies are now automatically resolved (for the most part)
    • ๐Ÿ”จ Internal refactors to make the code easier to maintain, more extendable, and fixes a bunch of edge cases

    โฌ†๏ธ Dependency Upgrades

    โž• Additions

    • Introduces concept of lazy services
      • Lazy services are not instantiated in the container until manually retrieved (if public), or used as a dependency of another service
      • Defaulted to true, but can be overwritten by setting lazy: false within the ADI::Register annotation
      • In the future, this could possibly be expanded to only instantiate them when they are first used (i.e. some method being called)
    • Introduce concept of Aliasing Services
      • Allows defining a "default" service that will be injected when an argument restricted to that default service's interface is encountered
    • Introduce concept of Bindings
      • Bindings allow scalar values, or those that could not otherwise be handled via aliases, to be auto registered
      • Bindings can also be declared with a type restriction to allow taking the type restriction of the argument into account
    • ๐Ÿ”ง Introduce concept of Auto Configuration
      • Allows applying service configuration, such as public, tags, or lazy options to any service of a specific type
      • A common use case would be wanting to apply a specific tag to all instances of an interface, versus having to manually apply the tag to each implementation
    • Introduce the ADI::Inject annotation
      • Allows specifying which constructor will be used for injection
    • ๐Ÿ‘ Allow Generic Services
      • Allows services to be registered based on a generic type
      • Generic arguments are provided as positional arguments within the ADI::Register annotation

    ๐Ÿ”„ Changes

    • ๐Ÿ”จ Refactor Tagged Services
      • Uses a more robust implementation, fixes some edge cases
      • Initial implementation for tag metadata, currently only supports priority which controls the order in which the services are injected; the higher the priority the sooner in the array it would be
    • ๐Ÿ”จ Refactor Optional Services to be based on type restrictions/default values
    • (breaking-change) The syntax for manually providing service dependencies has changed to using the argument's name prefixed with a _ symbol as named arguments within the ADI::Register annotation
      • If the argument was @debug : Bool you would add _debug: true into the annotation
      • The syntax is similar as it was before for services, @my_service : MyService would be _my_service: "@my_service"
    • (breaking-change) Service names are now based on the FQN of the type downcase underscored by default
      • MyApp::SomeModule::Service would become my_app_some_module_service
      • Can still be overwritten via the name field within the ADI::Register annotation

    Removals

    • (breaking-change) The ADI::Service module has been removed
      • Only the ADI::Register annotation is required now to register a service with the container
    • (breaking-change) Service dependencies are now resolved automatically
      • Arguments no longer have to be supplied as positional arguments
      • See the Basic Usage example for more details
      • Compile time errors are raised if a service could not be auto registered due to a missing service, ambiguity, or a scalar value without a binding
    • (breaking-change) Removes the @? syntax as it is no longer needed
    • (breaking-change) Removes some methods on the container including: #get, #has?, #resolve, #tagged, and #tags
      • #has? has been replaced with container.responds_to? :my_service
      • #get/#resolve and #tagged/#tags are now obsolete
    • (breaking-change) Removes the ADI::Injectable module
      • This was kind of an anti-pattern for allowing non services to use services
      • A more proper solution is to make everything a service to make use of the automatic dependency resolution
      • Alternatively, services could be make public and retrieved directly from the container within the non service; although this still slightly a code smell