Hi, On Wed, Mar 16, 2016 at 9:21 PM, Ryan Pallas <derokor...@gmail.com> wrote:
> On Wed, Mar 16, 2016 at 12:50 PM, Larry Garfield <la...@garfieldtech.com> > wrote: > > > On 3/16/16 11:36 AM, Phil Sturgeon wrote: > > > >> > >> 2. This whole temporary nullability situation, where unset properties > >> will error on attempted usage if not set. Should they instead error > >> after the constructor has been called if they are still not holding a > >> value? > >> > > > > I fall back to a statement I made in a blog post a while back: > > > > http://www.garfieldtech.com/blog/empty-return-values > > > > " But consider what you could do instead that would not force me to throw > > is_null() around my code, because throwing is_null() around my code makes > > me sad. NULL should be the return value of last resort, because it means > > nothing. (Literally.)" > > > > Allowing default-null on properties means that as someone using that > > property, I have two options: > > > > 1) Throw a lot of is_null() calls around my code. > > 2) Assume that whoever initialized the code provided a value by the time > > initialization is done and skip those extra checks. > > > > Insert that old adage about what happens when you assume. > > > > End-of-constructor checks seem like a good approach; they have to be > > uninitialized at some point when new is called initially, but they should > > be guaranteed set as soon as possible. End of the constructor is "as > soon > > as possible", and I think reasonably static-analysis-catchable. (Meaning > > my IDE can yell at me appropriately.) > > > > That removes is_null() calls from the rest of my codebase, which is a > good > > thing. > > > > > I'm not sure I like the "after contructor" because that's not necessarily > when the object is finished being initialized. Consider this: > > abstract class Contract > { > private function __construct() {} > > public static function fromArray(array $aProps) : Contract > { > $s = new static(); > foreach ($aProps as $k => $v) { > if (property_exists(static::class, $k)) { > $s->$k = $v; > } > } > > return $s; > } > } > > class User extends Contract { > public int $id; > public string $name; > } > > $user = User::fromArray(['id' => 123, 'name' => 'derokorian']); > > In this example, the constructor finishes but the properties still are not > initialized at time of finishing. This is a pretty common pattern as well. > Also, a LOT of code would end up with e.g. a default value of 0 for an integer property, still having to check if it was properly populated with a positive value - not much of an improvement over NULLs. Cheers, Andrey.