On Sat, Sep 12, 2020 at 10:23 PM Olle Härstedt <olleharst...@gmail.com>
wrote:

> Hi internals!
>
> Separation of data and behaviour is both a fun and hard discussion,
> especially considering:
>
> * "It should be possible to add new features without touching old code";
> and
> * "Principle of Least Privilege" (never expose more than you have to)
> (https://en.wikipedia.org/wiki/Principle_of_least_privilege).
>
> There should (could) be a way to add new behaviour to old data without
> touching the old data (class). Traits won't work in this use-case,
> since they assume the same internal structure for all trait-using
> classes. Imagine the `stringable` interface and a `toString` trait. A
> __toString() method needs knowledge about the internal structure of a
> class Foo. Yet if we want to keep adding behaviour to Foo, we'll end
> up with either exposing too much of Foo, or expanding the class file
> indefinitely. Please note that composition is not a proper solution,
> since it requires exposure of Foo; composition leads to lack of proper
> encapsulation, or representation exposure.
>
> In Haskell it's possible to split instance implementation of
> type-classes into separate files. In Rust you can have a struct with
> private fields and put impl of behaviour in different files (but same
> crate).
>
> A similar feature in PHP could look like (using new keyword `expand`
> but could be anything, or even `extend` in new context):
>
> ```
> // File FooStringable.php
> expand Foo implements stringable {
>   public function __toString() {
>     // Full access to Foo's all private fields here.
>     // Assumes you can autoload Foo.
>     // Assumes usage of $foo->__toString(); will be configured with
> autoload to dynamically find the correct behaviour of Foo.
>   }
> }
> ```
>
> If you'd use composition instead, you'd maybe have a formatter class
> with a method `$formatter->toString(stringable $foo)`. This has the
> problem I mentioned with exposing too much of $foo; it breaks
> encapsulation. It has the benefit of being able to provide multiple
> toString methods with different formats, but would have to assume
> similar structure of the objects passed to it (defined with an
> interface), which is not always possible or desirable.
>
> The other way is inheritance, which doesn't scale over multiple
> behaviours. `FooWithStringable extends Foo`? No.
>
> Was I clear here? Do you understand the issues that this design
> pattern is trying to solve? Its purpose is to solve "keep adding new
> feature to old data" in a clean and proper way, while keeping
> information encapsulation.
>

Do I understand you correctly, it would be somewhat like "opening" up a
class and making changes to it in another file?

Certainly a powerful concept, but I would be very interested in the details
how that would interact with autoloading. If I have a class Foo loaded, and
its "extension" FooString with toString method not, then it would lead to
the "toString" code missing.

>
> Enjoy the weekend!
> Olle
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
>

Reply via email to