Created
June 9, 2017 15:02
-
-
Save nlundquist/85467d08a4cc2868e4c6146e0bdaee2b to your computer and use it in GitHub Desktop.
can-connect behavior mutual interface ordering problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Mutual Interface Ordering Problem: | |
Two behaviors (A1, A2) implement the same interface properties. A third interface (B) depends on that interface, but requires being ordered after a specific implementation of A. How can we allow arbitrary insertion order of these behaviors and still end up with the dependency correctly satsified? | |
For the purpose of the example below B depends on being ordered after A1. | |
e.g | |
We should be able run code like: | |
` | |
var con = connect(); | |
con.insert(B); | |
con.insert(A2); | |
con.insert(A1); | |
` | |
and end up with the connection having the behaviors ordered A1, B, A2. | |
Real world examples of this include: | |
How cache-requests (which implements getList and depends on getList) needs to be ordered after data/url (which also implements getList) but before data/callbacks (which also implements getList). A potential issue arising from misordering would be requests fulfilled by the cache not triggering data callbacks. | |
How data/parse depends on data/url (both offer the same interface), but constructor/constructor must follow the implementation offered by data/parse (since it returns a format constructor/constructor can utilize). | |
Since we want to allow behavior insertion in any order, and when evaluating positions by interface alone there are multiple positions that satisfy the dependency of B, solutions to this problem require some sort of ordering based on something other than the interface properties. | |
There are a few types of solution possible: | |
- canonical behavior ordering | |
- explicit behavior ordering | |
- categorized behavior ordering | |
- prioritized behavior ordering | |
- more ordering rules | |
Canonical Ordering: | |
What we have now, a single master ordering of behaviors that define specifically how behaviors should be arranged. | |
Pros: | |
- Easiest to implement and understand | |
Cons: | |
- Requires a custom behavior creator to modify canonical order | |
- Chance for error when creating canonical order | |
Explicit Ordering: | |
Behaviors define specifically what behaviors they must follow by name. Not much different than canonical ordering. | |
Pros: | |
- Easy to implement | |
- Doesn't require an ordering other than what's specified by the behavior | |
Cons: | |
- Harder to modify | |
- insertion of a custom behavior between existing behaviors requires the creator modify requirements specified by other behaviors or use the name of an existing behavior | |
- Chance for error when creating explicit order | |
Categorized Ordering: | |
Behaviors are assigned to categories that indicate what range of the prototype chain they should be positioned in. | |
e.g | |
data/url is part of a 'data provider' category | |
data/parse is part of a 'data mutator' category | |
constructor/constructor is part of a 'instance provider' category | |
the hierarchy of categories indicates data providers are at the highest position in the prototype chain, followed by data mutators and then instance providers | |
thus no matter the order of insertion these behaviors are always ordered as expected | |
Pros: | |
- Easy to implement | |
Cons: | |
- Insertion of a custom behaviors between existing categories likely requires adding a new category of behaviors to the heirarchy | |
- Still requires a canonical order of categories | |
- Chance for error when assigning behavior to category or ordering categories | |
Prioritized Ordering: | |
Behaviors are defined with a priority (eg. on a scale of 1 - 100000) which indicates how far up the prototype chain they should be positioned. | |
e.g | |
A1 and A2 implement the same interface, | |
A2 depends on A1, | |
B depends specifically on the interface provided by A1, | |
Desired ordering is A1, B, A2 | |
A1 is priority 10000, | |
A2 is priority 8000, | |
B is priority 9000 | |
` | |
var con = connect(); | |
con.insert(B); // is inserted as sole behavior | |
con.insert(A2); // is inserted after B due to B's higher priority | |
con.insert(A1); // is inserted before B due to A1's higher priority | |
// con proto from top to bottom === A1, B, A2 | |
` | |
Pros: | |
- Easy & flexible insertion and replacement | |
- Easy to implement | |
- Doesn't require an ordering other than what's specified by the behavior | |
- Easy to move existing behaviors by reassiging their priorities | |
- unlikely to be require in most use cases | |
Cons: | |
- Somewhat harder to understand, but easy once grasped | |
- Potential for "crowding" a region of the priority range | |
- Chance for error when assigning priority | |
More Ordering Rules: | |
Rather than just positioning a behavior where it satisfies its interface requirements, we provide addition positoning directives so that it ends up where it's actually required. | |
Additional directives like: | |
- what interface needs to follow the behavior | |
- if it should be inserted as high as possible, or low as possible in the ordering | |
- etc. | |
Pros: | |
- Doesn't require a prexisting ordering | |
Cons: | |
- Complex and difficult to understand | |
- Difficult for custom behvaior creators to use | |
- Can't think of an implementation that is completely unaffected by insertion order | |
- Insertion rules of existing behaviors may need to be re-evaluated when adding later behaviors | |
- Chance for error when creating ordering rules | |
Recommendations: | |
- Continue using a canonical ordering, exposing it for custom behavior creators to modify. This is the easiest to understand and implement and resolves the issue conclusively. However more overhead since custom behavior creators will need to modify the canonical ordering. | |
or, | |
- Adopt prioritized ordering. This is easy for custom behavior creators to understand, doesn't require an ordering other than what's specified by the behavior, providing somewhat more flexibility. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment