Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructure @Dependency property and use BFS for DependencyManager #112

Merged
merged 18 commits into from
Aug 13, 2024

Conversation

Supereg
Copy link
Member

@Supereg Supereg commented Jul 31, 2024

Restructure @Dependency property and use BFS for DependencyManager

♻️ Current situation & Problem

The Module and dependency system is very powerful and useful infrastructure of the Spezi framework ecosystem allowing it to be modularized. There was immense thought put into it to generalize the concept of dependency declaration between modules. With recent PRs it has become even more powerful support a lot of different use cases like dynamism (e.g., like modeling Bluetooth devices as modules).

However, it some scenarios the @Dependency property lacks the expressiveness as required in certain use cases. For example, it is currently always required to either specify a default value (either manually or through DefaultInitializable) or declare it as an optional dependency. Simply, declaring a required dependency that is assumed to be present, cannot be modeled. For example, a module A, might configure a module B and C, where B has a required dependency to C (as it knows it is always configured by A and therefore can safely assume that C is present). This is currently not possible with either a) having to unwrap a optional dependency all the time or b) declaring a dependency with a default value which might be not always be possible if there are initializer arguments required.

Secondly, you currently cannot have a guarantee that a given module instance you provide to the @Dependency property wrapper is actually loaded as it is always used as a default argument and a module declared on the outside takes precedence.

The changes of this PR are listed in the next section.

⚙️ Release Notes

This PR introduces several changes to the dependency system.

  • You can specify required modules without providing a default value like below:
    • @Depenency(Example.self) var example
  • You can manually request loading a module in any case by calling the special initializer _example = Dependency(load: myInstance) or using any array based initializers.
  • The PR makes certain initializers to require to specify the Module type as we are reaching a point where Swift has troubles resolving the different non-argument initializers:
    • Instead of specifying @Dependency var example: Example? you have to specify `@Dependency(Example.self) var example: Example?.
    • Instead of specifying @Dependency var example: Example (for DefaultInitializable), you will specify @Dependency(Example.self) var example for a required dependency. The default value will automatically be created.
  • Lastly, this PR changes the DependencyManager from using a depth-first search to a breath-first search to avoid unexpected initialization of default values.

Old initializers are marked deprecated and shall be removed in the next major version release.

📚 Documentation

This PR updates documentation to refer to the most recent versions of the @Dependency property wrapper.

✅ Testing

New unit tests were added to cover new cases. We added some verification that deprecated initializers still work as expected.

📝 Code of Conduct & Contributing Guidelines

By submitting creating this pull request, you agree to follow our Code of Conduct and Contributing Guidelines:

@Supereg Supereg requested a review from PSchmiedmayer July 31, 2024 14:35
@Supereg Supereg changed the title Restructure declarations @Dependency Restructure @Dependency property and use BFS for DependencyManager Jul 31, 2024
Copy link

codecov bot commented Jul 31, 2024

Codecov Report

Attention: Patch coverage is 93.97590% with 15 lines in your changes missing coverage. Please review.

Project coverage is 90.33%. Comparing base (d87e3d8) to head (0847c72).

Files Patch % Lines
.../Spezi/Spezi/SpeziNotificationCenterDelegate.swift 0.00% 10 Missing ⚠️
Sources/Spezi/Dependencies/DependencyManager.swift 97.60% 3 Missing ⚠️
...pezi/Dependencies/Property/DependencyContext.swift 90.91% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #112      +/-   ##
==========================================
+ Coverage   88.03%   90.33%   +2.30%     
==========================================
  Files          47       47              
  Lines        1470     1602     +132     
==========================================
+ Hits         1294     1447     +153     
+ Misses        176      155      -21     
Files Coverage Δ
...pezi/Capabilities/Lifecycle/LifecycleHandler.swift 88.89% <ø> (ø)
...pabilities/Notifications/NotificationHandler.swift 50.00% <ø> (ø)
...pabilities/ViewModifier/ViewModifierProvider.swift 94.45% <ø> (ø)
...pezi/Dependencies/Property/DependencyBuilder.swift 100.00% <100.00%> (ø)
...i/Dependencies/Property/DependencyCollection.swift 98.91% <100.00%> (+4.97%) ⬆️
...dencies/Property/DependencyCollectionBuilder.swift 40.00% <100.00%> (ø)
.../Dependencies/Property/DependencyDeclaration.swift 100.00% <ø> (ø)
...endencies/Property/DependencyPropertyWrapper.swift 93.94% <100.00%> (+1.26%) ⬆️
Sources/Spezi/Module/ModuleBuilder.swift 100.00% <ø> (ø)
Sources/Spezi/Spezi/Spezi.swift 98.88% <100.00%> (+0.82%) ⬆️
... and 4 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d87e3d8...0847c72. Read the comment docs.

Copy link
Member

@PSchmiedmayer PSchmiedmayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the great addition @Supereg!

I am wondering if we should keep a simple "worry-free" approach with DefaultInitializable for now but am happy to mark this as deprecated if there is good reason we want to remove it on the long run.

@PSchmiedmayer PSchmiedmayer added the enhancement New feature or request label Aug 4, 2024
Copy link
Member

@PSchmiedmayer PSchmiedmayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@Supereg Supereg merged commit 6599bac into main Aug 13, 2024
15 checks passed
@Supereg Supereg deleted the feature/dependency-restructure branch August 13, 2024 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants