On Sat, Jan 4, 2020, at 3:25 PM, Mike Schinkel wrote:
> > On Jan 3, 2020, at 2:52 PM, Larry Garfield <la...@garfieldtech.com> wrote:
> > 
> > There's two broad reasons I think this is a bad idea.
> > 
> > 1) Constants are one thing.  Function calls are another.  They serve 
> > different purposes.  Trying to mutate them into one thing can only lead to 
> > confusion and lack of understanding about what is actually going on.
> > 
> > 2) The approach you describe (of starting with constants everywhere and 
> > refactoring to method calls later)... I would never do and do not endorse.  
> > What you describe is basically "make globals nicer to work with", whereas I 
> > am 100% firmly in the camp of "if I could remove globals from the language 
> > entirely I would".  Frankly, the use of constants for configuration is an 
> > anti-pattern to begin with; they should be used only for things that are 
> > truly constant.  Honestly, I cannot recall the last time I used constants 
> > for anything other than giving some other compile-time value a nicer name.  
> > (Eg, DEFAULT_THING_VALUE or giving nice names to bit flags or something 
> > like that.)
> > 
> > For configuration, my answer is frankly "put your configuration behind a 
> > nice configuration object from the very beginning and then you won't have 
> > to refactor it later; Problem solved."  You can use env vars for 
> > configuration, and wrap those into a nice object, possibly using one of the 
> > many DotEnv implementations that already exist to make them nicer to work 
> > with in development.  That is superior in basically every conceivable way 
> > to semi-mutable globals passing themselves off as pseudo-constants.
> > 
> > I *would* love to see property accessors come back, which would have a side 
> > effect of making what you describe a little easier, but at no point is it 
> > pretending to be a compile time value when it isn't.
> > 
> > --Larry Garfield
> 
> <sigh>  So much to unpack here, but I will just hit the most important points.

*snip*

> Symfony — which many PHP developers hold in high regard including 
> Drupal developers — uses constants:

Just an FYI: I assume you mention Drupal specifically here because of my 
history with the project.  What Drupal developers hold in high regard matters 
not even 0% for me at this point; "Drupal does it" is not an argument that will 
carry any weight with me.

*snip*

> I think this analysis proves many PHP developers do use constants in 
> ways you claim you would never.  IOW, the use-cases I am trying to 
> address exist to a significant degree in the wild.
> 
> Further I believe I have made the case that there would be significant 
> value in allowing developers who previously used constants because of 
> prior lack of skill or too-tight timelines to be able to evolve their 
> code to initialize their  constants with code instead of forcing their 
> users to change their code or worse.
> 
> -Mike

I think you are overstating my case.  I am not arguing that one should never 
use constants.  In fact, a majority of the examples you cite I would say are 
reasonable uses of constants, at least in concept.  (I cannot speak to the 
particulars of the individual code bases.)

I am saying that the behavior of a constant is that it is... constant.  A 
proper constant is evaluated at compile time and appears as a literal in the 
final runtime code, with no dereferencing.  AIUI, `const` in PHP does exactly 
that, in contrast to `define`.  That is fundamentally conceptually incompatible 
with a value that is derived at runtime and happens to use constant-style 
syntax.  I am firmly opposed in principle to having a language construct that 
looks like a constant and makes you think it's a constant but is actually a 
method call that does who knows what.

There's really two different use cases here, I think, that we're conflating.  
("We" meaning I think we're all doing it to an extent.)

1) I want an approximately global value that is auto-memoized on first usage, 
so I can access it from anywhere without having to recompute it or do the work 
of memoizing it myself.

2) I have a code base with lots of constants, and I've changed my mind about 
the API (for whatever reason) and want them to no longer be constant but 
runtime defined.

For point 1, I'd love it if we had some way to auto-memoize a result.  That 
would be sweet.  There's a couple of ways we could go about it... but I firmly 
believe that sticking it behind a const-like API is the wrong way to do it for 
the reasons above.  (I wouldn't want to limit it to global-ish things, either, 
because global-ish things are, as stated, bad in every way and should be 
avoided whenever possible.  Yes, I know there's a lot of bad code out there 
already with it; that doesn't mean encouraging it.)

For point 2... if you want to change your API, then your API is going to 
change.  That's what it means to change an API.  It's no different than 
deciding to rename a method or class.  It may or may not be hard depending on 
the API and the install base, but that it's a constant doesn't change matters.  
Making code easier to refactor is all well and good, but not if it violates all 
expectations around what a constant is.

For derive-once global constants, you may be looking for `define`.  That's a 
runtime operation and effectively boils down to a set-once global.  It doesn't 
help with constants defined in a class, but for an already-global constant 
`define` already gives you a one-time set operation, just not on-demand.  
That's probably the better avenue to pursue for option 2, though again it's not 
one that I find worth compromising the language design for.

--Larry Garfield

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

Reply via email to