-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: minor changes and improvements (#2)
Adds a couple of more functions and changes behaviour of fallback in a non breaking way. Also, it completes the documentation. This should be the last release in a long time.
- Loading branch information
1 parent
85f058c
commit 20d895e
Showing
8 changed files
with
591 additions
and
20 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,74 @@ | ||
Best Practices | ||
============== | ||
|
||
## Pass `Context` as the first argument of the function or method | ||
The `Context` api is definitely a new pattern and approach to solve the context passing problem in PHP. | ||
Whenever a new pattern is introduced, is always important to define some best practices for its good use. | ||
|
||
## Don't overuse `Context\with_value` for related values | ||
These are some of what we consider to be those best practices. | ||
|
||
## Use Enums as Keys | ||
## Custom functions SHOULD be defined to work with `Context` | ||
|
||
## Do not store `Context` inside objects | ||
Context is all about composition, and you should also compose the base context functions to provide a nicer api | ||
to store or retrieve context values, like we did in the logger example. Of course, you could also rely on | ||
static methods, but in my personal opinion, functions are nicer. | ||
|
||
## Avoid immutable values inside `Context` | ||
You can even go as far as to create your own `Context` implementation that composes a `Context`. We do that for some | ||
of our libraries. But we even discourage that. The thinner you can keep `Context` api surface, the better. | ||
|
||
## Do not store services inside the `Context` | ||
## `Context` SHOULD be the first argument of the function or method | ||
|
||
Whenever a function or method call accepts a `Context`, this should be the first argument of the function, and | ||
it should be named `$ctx`. We know some people hate abbreviations and prefer more explicit names. I agree with that | ||
suggestion almost in every situation, but in this case the abbreviation does not yield any sort of confusion and | ||
is pretty universal and easily understood. | ||
|
||
It also has the benefit that it is short, and since `Context` is there to be added to your public api, we want | ||
to minimize as much as possible the space impact that has in your method's argument list. | ||
|
||
## Enums SHOULD be used as keys rather than strings | ||
|
||
When calling `Context\with_value()` prefer enums as keys. They are lightweight, offer autocompletion, and they cannot | ||
collide like strings could. In the case that your application still does not support PHP 8.1 and above, you MUST use | ||
string keys with a vendor namespace. | ||
|
||
## `Context` SHOULD NOT be stored inside other data structures | ||
|
||
Always explicitly pass `Context`. Do not store it inside objects or arrays, unless is explicitly necessary. For | ||
instance, if you are using the `Context` api in PSR-7 applications, it is very likely your `Context` instance | ||
will be stored in the Request attributes (which is implemented by an array). This is acceptable, but for a better | ||
HTTP layer supporting context natively, we recommend `castor/http`. | ||
|
||
## `Context\with_value` SHOULD NOT be overused | ||
|
||
Because of its particular implementation, every time you add a value to a `Context`, you increase the potential call | ||
stack size to reach the value by 1. Although the performance impact of this is negligent, is still slower than fetching | ||
a value directly from a map, for instance. | ||
|
||
So, bottom line, don't overuse `Context\with_value`. This means that if you have to store related values in | ||
`Context`, store a data structure instead and not each value individually. | ||
|
||
Again, the performance impact of not doing this is negligible, so measure and make decisions based on that. | ||
|
||
> In a potential new major version, we are considering swapping the `Context\with_value()` implementation by using a | ||
[`DS\Map` if the extension is available][https://www.php.net/manual/en/class.ds-map.php] to avoid the performance | ||
penalty. | ||
|
||
## `Context` SHOULD NOT contain immutable values | ||
|
||
A `Context` implementation is already immutable, and it's lifetime does not go outside the request. This means it is | ||
safe for manipulation and free of unexpected side effects. | ||
|
||
As long as `Context` holds values derived from the request, whose lifetime will also die with it, then it is safe to | ||
store mutable values in it. If you store immutable values and decide that a new reference of that value needs to be | ||
passed down the call stack it means the value should have never been immutable in the first place. You'll have to call | ||
`Context\with_value` again and "override" that value. | ||
|
||
## Services SHOULD NOT be stored inside `Context` | ||
|
||
We greatly discourage storing services inside `Context`. It is not a good idea to mix request-scoped values with | ||
application scoped-values like services. Always prefer dependency injection instead of passing services down the | ||
context. | ||
|
||
There could be some use cases when this could make sense. For instance, if you need to pass an event loop instance | ||
down the call stack to reach some method and make it work asynchronously. I would say that is part of the execution | ||
context, although an event loop can be classified as a service. |
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
Oops, something went wrong.