You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We use fractal pretty religiously throughout our REST API and recently have had need to extend its capabilities a bit so that we can more efficiently load our entities as we're traversing the scope tree.
That's a separate topic, but what it's brought to light is a lot of difficulty in extending the library due to circular dependencies and muddled responsibilities between the scope and the transformer classes, as well as some private methods that would be very useful if protected.
I'll try my best to summarize discoveries and make suggestions:
Scope would be better as an interface
With the introduction of the ScopeFactory, this would allow us to implement our own scopes more easily without having to extend and adapt to the base scope.
Scope toArray mixes responsibility with transformer private methods
The toArray method in the scope is a recursive mechanism that transforms the resource into an array, then merges in the necessary "included" resources by calling toArray on those child scopes.
The issue arises in that it calls processIncludedResources(Scope $scope, $data) on the transformer.
This is immediately a circular dependency, as the scope depends on the transformer and the transformer depends on the current scope. This is more illustrated by the call chain that occurs within this method:
publicfunctionprocessIncludedResources(Scope$scope, $data) {
// call figureOutWhichIncludes// call includeResourceIfAvailable foreach include
}
// Private which prevents `processIncludedResources` from being overloadable unless you // reimplement (copy paste) this entire method in your child class.privatefunctionfigureOutWhichIncludes(Scope$scope) {
// ...
}
// Private which prevents `processIncludedResources` from being overloadable unless you // reimplement (copy paste) this entire method in your child class.privatefunctionincludeResourceIfAvailable(
Scope$scope,
$data,
$includedData,
$include
) {
// Here is the main issue... From this method we call:$scope->toArray();
// Now we've completed the full circle.
}
// If this was public it could be called from the scope instead of by// private methods in the transformer classes. The scope is already responsible for // calling the `transform` method, so this would make sense.protectedfunctioncallIncludeMethod(Scope$scope, $includeName, $data) {
// ...
}
Where I expect that the responsibility of the Scope is to call all the necessary include and transform methods on the transformer and then compose those into the array as part of toArray, instead there is a complex call chain the mixes these responsibilities between the two classes.
Recommend that the TransformerAbstract really be a stupid object with the include and transform methods and let the Scope object (or some new higher level of abstraction) compose the data. So essentially move a lot of the logic from the transformer into the scope class to remove the circular dependency and make it easier (and possible) to modify the logic of traversing the fractals when creating our own scope implementations.
Let me know if anything is unclear here and I'll be happy to try to clarify a bit better.
The text was updated successfully, but these errors were encountered:
I removed this circular dependency in my fork. Since processIncludedResources and callIncludeMethod is marked as @internal I don't even think that this is BC break.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 4 weeks if no further activity occurs. Thank you for your contributions.
We use fractal pretty religiously throughout our REST API and recently have had need to extend its capabilities a bit so that we can more efficiently load our entities as we're traversing the scope tree.
That's a separate topic, but what it's brought to light is a lot of difficulty in extending the library due to circular dependencies and muddled responsibilities between the scope and the transformer classes, as well as some
private
methods that would be very useful ifprotected
.I'll try my best to summarize discoveries and make suggestions:
Scope would be better as an interface
With the introduction of the
ScopeFactory
, this would allow us to implement our own scopes more easily without having to extend and adapt to the base scope.Scope
toArray
mixes responsibility with transformer private methodsThe
toArray
method in the scope is a recursive mechanism that transforms the resource into an array, then merges in the necessary "included" resources by callingtoArray
on those child scopes.The issue arises in that it calls
processIncludedResources(Scope $scope, $data)
on the transformer.This is immediately a circular dependency, as the
scope
depends on the transformer and the transformer depends on the current scope. This is more illustrated by the call chain that occurs within this method:Where I expect that the responsibility of the
Scope
is to call all the necessary include and transform methods on the transformer and then compose those into the array as part oftoArray
, instead there is a complex call chain the mixes these responsibilities between the two classes.Recommend that the
TransformerAbstract
really be a stupid object with theinclude
andtransform
methods and let theScope
object (or some new higher level of abstraction) compose the data. So essentially move a lot of the logic from the transformer into the scope class to remove the circular dependency and make it easier (and possible) to modify the logic of traversing the fractals when creating our own scope implementations.Let me know if anything is unclear here and I'll be happy to try to clarify a bit better.
The text was updated successfully, but these errors were encountered: