On Thu, Sep 20, 2018 at 4:50 PM Levi Morrison <le...@php.net> wrote:
>
> This will be my last reply to this thread. Fundamentally:
>
> class User {
>      public ?int $id;
>      public ?string $preferred_name;
>      public ?string $username;
>  }
>
> ^ This permits null properties at all times. This is acceptable
> behavior if null is valid for the domain. It is not valid for this
> domain -- all 3 are required.

If all three are required, your constructor needs to reflect that.

The reason constructors even exist in the first place is to initialize
the object's data members and establishing the invariant of the class.

Constructors are supposed to prepare objects for use.

Your (empty, implicit) constructor isn't doing that.

Your reasoning about this is circular - you want your properties to
be optionally initialized and non-null at the same time. You get
around this by coming up with a new term "undefined" for a
special kind of null that triggers run-time exceptions on read.

The whole idea is unnecessarily complex, and will certainly lead
to silent bugs that allow partially-initialized domain objects to
pass through many layers of a system without getting caught
until some code tries to read an "uninitialized" property.

function make_foo(): Foo {
   return new Foo(); // missing a property
}

function x() { ... }
function y() { ... }
function z() { ... }

x(y(z(make_foo()));

The instance travels through layers and layers of callls and
fails somewhere in the x() or y() function because of a missing
value ... why was the value missing? why wasn't it initialized?
where was it supposed to have been initialized? where did
this bad instance of Foo even come from?

All that information is lost in a call-stack that's long gone by
the time you invoke x() and you'll have to backtrack through
layers and layers of code to try to figure out where this bad
instance came from.

This will be an everyday thing with code like that.

To say that we don't need to enforce invariants at the time of
construction is to say we don't need to enforce them at all -
enforcing them "maybe later" is the same as not enforcing
them. That is, when they trigger an error, it's no different
from a null-value triggering a similar error.

No matter how you twist it, uninitialized is the new null.

I'm fine with unintialized as an implementation detail that
ensures you can't read from properties while the constructor
is busy establishing the invariant.

I'm not at all fine with unintialized as a new language feature.

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

Reply via email to