Hi Stas,

I'll comment your PS, since I'm the author of the PR.

On Sun, Aug 14, 2016 at 6:11 PM, Stanislav Malyshev <smalys...@gmail.com>
wrote:

> 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?
>

I wanted to come up with a solution before writing an RFC.
The problem that is not yet solved in that PR is the check of instantiation
without being scoped. Example:

<?php

namespace Foo;

$bar = new ThisIsAPrivateClass();

This should work... but this code:

<?php

$bar = new \Foo\ThisIsAPrivateClass();

Should break.
The problem is that opline have no scope context, so at both of them the
scope = NULL.

We could easily add a scope every time a namespace is declared and remove
when ended, but as Nikita highlighted (here:
https://github.com/php/php-src/pull/947#issuecomment-224934615 ), this is
not the correct solution.

I hit a dead end on that PR. Changing opline (or oparray) to support a new
struct _zend_namespace is over my internals knowledge. I'd love if someone
could take over and complete it. I can write the RFC while someone else
finalize the code.


>
>
--
> Stas Malyshev
> smalys...@gmail.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


-- 
Guilherme Blanco
Lead Architect at E-Block

Reply via email to