Hi!

> - PHP 7 has private classes through anonymous/inner classes.

It's not exactly the same, and I suspect the same is true for Ruby. It's
true that anonymous classes can not be instantiated by other code. But
that is not what we were discussing here. This particular effect is
somewhat similar, the purpose of the feature is different.

Of course, some languages have them. Others don't. The point is saying
"it's not OO unless it implements $favorite_feature_of_mine" is not very
meaningful, at least at this point.

> abstract class Data {
>   protected $id;
>   protected $name;
>   protected function __construct() {}
>   protected function __clone() {}
> }
> 
> final class Entity extends Data {
>   public function getId() {
>     return $this->id;
>   }
>   public function getName() {
>     return $this->name;
>   }
> }
> 
> final class Builder extends Data {
>   private $entity;
>   public function build() {
>     return clone $this->entity;
>   }
>   public function setId($id) {
>     $this->entity->id = $id;
>   }
>   public function setName($name) {
>     $this->entity->name = $name;
>   }
> }
> 
> ?>

I'm afraid I don't understand this code. Why both entity and builder are
Data? It looks like combining factory object with actual data object.
This is why __construct/__clone exists - so the object could take care
of the details and the factory didn't have to know about it in details.

I presume you want to say that Data object should be private class. I
think - at least from my partial understanding of the code - that it
shouldn't exist at all, especially given you don't want to expose it to
the user.

> Another example that is not solvable with friend classes would be the
> strategy pattern of hidden strategies as we find it for example in
> Symfony's process component.
> 
> https://github.com/symfony/process/tree/master/Pipes
> 
> The pipes are purely internal to work around differences between PHP on
> Unix and Windows. They are not meant for consumption through users, they

Sure, they aren't useful for most, but I see no problem in somebody
using them if necessary. Say, you may want to use Unix pipe on Windows
because you are in unix emulation environment, or you have a weird OS
that is not Unix and now Windows and want to reuse parts of these
classes to deal with it. There could be many cases we can't foresee when
we design it for our ideal use case.

> At trivago we have hundreds of applications, packages, libraries and
> developers who work in a very fast moving environment. Reading
> documentation is not something most people spend time with. 

I find so many things not right with this statement I don't know where
to start... So I just leave it with a note that having no time to do
things right usually means doing things wrong many times, and *then*
being forced to spend time to do things right because the whole jenga
tower crashes on your head. That is not a criticism of you or your
employer, but rather the result of experience learned the hard way. You
can get away with it from time to time, true, but it's just luck.

> It's also easy to work around property and method access modifiers.
> However, that is no argument to remove them now.

Not very easy. The only way to work around private is to use heavy
machinery like reflection. This is why, btw, private should be used very
carefully - when if you're *sure* nobody will need or is advised to
access that thing directly. Overuse of private, especially for methods,
leads to classes that are not extendable without horrendous amounts of
copypaste.

Also, there's a difference IMO between classes and class' properties.
Class details may be - indeed, need to be - hidden because this is what
the class is, one of it's reasons to exist - a tool to reduce complexity
by hiding irrelevant information and exposing only relevant information
as class' public API. You hide things not because you're afraid evil
users would abuse them - but as a service to the user to not overload
their mental models with irrelevant details and allow to deal with the
class by only considering the important things.

However, if we're talking about collection of classes sharing a
namespace, there's no such thing as "namespace's API", at least not in
common use. There's a concept of library's API, but it's not derived
from classes alone - it's usually what documentation does, while class
API can be yet figured from it's methods, library API is usually
impossible to figure out just looking at the classes - you need the next
level, documentation.
So in my opinion, if you hide some classes from instantiation from
outside namespace (which by itself carries a lot of assumptions, such as
every class that will ever need it will share the same namespace),
reduction in complexity is almost none, since nobody uses "list of
available classes in package/namespace" as a way to work with the
package anyway.

P.S. BTW I still don't know why you need to refactor namespaces to have
namespace-private classes anyway. Isn't it just a matter of the match
between current scope and target class name?

-- 
Stas Malyshev
smalys...@gmail.com

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to