Re: Initializing constants once, with code?
| From: | Mike Schinkel | Date: | Mon, 06 Jan 2020 20:28:56 +0000 |
| Subject: | Re: Initializing constants once, with code? | ||
| References: | 1 2 3 4 5 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108012@lists.php.net to get a copy of this message | ||
> On Jan 6, 2020, at 1:07 PM, Larry Garfield <larry@garfieldtech.com> wrote:
>
> Do not put words in my mouth and presume to know what I would think in some hypothetical
> situation. That is rude and inappropriate.
I do not mean to nor want to start any conflict here. I know I felt some of your phrasing rude and
so I was probably writing in frustration. Hopefully we can both moderate as conflict is not good for
any of us.
> You also repeatedly are accusing Rowan and I of "status quo bias" as though it were a
> bad thing. Let me be clear: I entirely agree with Zeev that in a language used by millions of
> people a "status quo bias" is a *very good thing*.
You are misunderstanding the definition of "status quo bias." Here is part of the
definition:
"Status quo bias is an emotional bias. The current baseline (or status quo) is taken as a
reference point, and any change from that baseline is perceived as a loss. Status quo bias should be
distinguished from a rational preference for the status quo ante, as when the current state of
affairs is objectively superior to the available alternatives, or when imperfect information is a
significant problem."
When I used that phrase I was specifically referring to the emotional reaction vs. the rational
reaction. I understand and agree when rational arguments are used, but lately in our political
climate people seem to often to start with emotional arguments. And calling something an
anti-pattern or the alternative a "best practice" is not a rational argument; both of
those are loaded words.
From: https://en.wikipedia.org/wiki/Status_quo_bias
But if I mischaracterized your objections I apologize.
> So you call something an anti-pattern, then get on my case for "appeal to authority"
> for calling something an anti-pattern? Your argument style needs work, dude.
I notice you did not quote my full statement. I explicitly called out the irony of my own usage and
made the distinction that I was not using the phrase to argue against someone else's proposal
which is why I felt ok to use it, because I was not using it to block anyone else's needs.
Again, my goal is not conflict but hopefully improving PHP.
> Global data is well-recognized across the industry as dangerous, and the larger the system the
> more dangerous it is.
Eh, not exactly. Global data that is *mutable* is bad. Immutable global data — especially
constants — are not necessarily bad, at least per the highest voted answer which means the topic
is definitely debatable:
https://stackoverflow.com/a/1265684/102699
And a constant that is initialized at runtime is still immutable through the life of the execution.
> It violates pure functions, and pure functions are how you get any semblance of predictability
> in your code. I do not have the time or inclination to go through all the details of that here; you
> can find ample resources for that yourself.
I am very familiar with pure functions, you don't need to go through the detail with me.
That said, class methods in PHP are not pure functions and PHP has not embraced pure functions so I
am not sure why you are using this your rational other than maybe you wish PHP was a pure-function
language? Of course if it was limited to pure functions, we'd not be able to configuration
from outside the program anyway.
> (And for the record, "appeal to authority" is only a logical fallacy if the authority
> being appealed to is not a qualified authority on the topic at hand. Appealing to Tiger
> Woods's authority on golf clubs is not a logical fallacy because he really would have more
> knowledge and experience than most; appealing to his authority on baseball gloves would be a logical
> fallacy.)
When you said it was an anti-pattern you used passive voice and did not include a reference to any
authority.
That said, I have been programming professionally for 30 years now and I have seen many best
practices from "authorities" be promoted, and then later seen a tidal wave of developer
sentiment argue against those same best practices, i.e. inheritance and then containment, as one
example.
I've also seen authorities promote an idea and then watched as developers latched onto it and
give it a life of its own, far outpacing what the authority orginally intended, e.g. Bob Martin and
the single responsibility principle.
In my experience "best practice" and "anti-patterns" are too often used in
debate even when they do not actually apply to the use-case, so I prefer to dispense with those
words when trying to debate actual pros and cons of an approach.
> I work for Platform.sh, which has been doing environment-per-bit-branch longer than Pantheon
> has.
That statement was in response to Rowan's comment, not yours.
> In my experience, systems that configure themselves via constants are the worst.
Of course they are the worst! Because you can't initialize constants dynamically.
That is exactly what I am trying to change.
> It makes any sort of dynamic override (which you *must* do in a cloud hosting environment) a
> PITA.
Exactly.
> The best option are systems that are configured by env vars, and have a very clearly set of
> documented env vars to populate. Env vars are also globally readable but you're not tricked
> into thinking they're compiled out at compilation time (as things with
>
const are.) They're also by far the easiest for me to work
> with as the person writing that glue code.
The word "tricked" is a pejorative and not helpful for our discussion.
What I read here is that you have a preference for using Env vars directly and I have a preference
for encapsulating them into constants. I don't see that either of us are more
"right" than the other, we just have different preferences.
I still have not heard a real reason why Api::URL is somehow worse to use than $config->api_url()
other than your claim that the former is "global" and thus bad, which I challenge because
the former would be immutable. This is one of the areas where I think the "anti-pattern"
does not apply.
> Adding language features that make it easier for people to take the approach that is in my
> experience the most painful option is something I am not going to support. :-)
Have you worked with other languages besides PHP where dynamically initialized constants were
possible, and this caused problems?
> To the use cases, "I'm changing the API but don't want to change the API"
> (what you're calling evolving here)
As you said above that it was rude to put words in your mouth, it is also rude to keep changing my
words to better fit your argument. Let us both not do that.
> "Sometimes a constant is not a constant".
What I proposed will always be a constant. Again, it would be immutable once set. The fact is it
set at compile time does not make it constant, per the lin
> From one perspective one could look at dynamically valued constants as a zero parameter
> self-memoizing function with some syntactic sugar.
Yes.
Although I tend to avoid using the term "memoizing" because most people I know have to
look it up and then ponder over its meaning.
> I can see a use for const variables, especially const class variables.
I assume you mean immutable variables that still use the $, like 'let' in Javascript?
Those would definitely be very useful, but unfortunately would not address the use-case I presented.
> So the more general request here is for dynamically valued constants beyond the current
> declare support. Which... I could potentially get behind.
> Self-memoizing functions is one way they could be implemented, if you don't mind (). (I
> don't.) That would also have a lot of other benefits.
I am confused. This sounds like you are now agreeing with the need for dynamic constants?
BTW, the requirement for () means it would not address the use-case of allow code to be evolved.
> The caveat in both cases is dependencies. Memoizing an impure function can lead to all sorts
> of time-dependent silliness. The same concern applies to dynamically valued constants. If their
> generation code is a pure function (however expressed), then cool, that's a safe and nice
> feature. If it has unpredictable dependencies, though, the behavior can be equally unpredicatable.
> That includes depending on $_GET or env vars.
Totally agree that people could write bad code. But there are a thousand ways they can already write
bad code.
If a dynamic constant were to use $_GET or $_ENV it could be problematic, but it could also be
coding in a manner than it would be completely robust, and making it robust is not hard.
> (Remember, PHP has plenty of users outside of shred-nothing requests, and with FFI and
> preloading hopefully more of them wil get used more often.)
Maybe there is something here I am missing? Can you present a problem that dynamic initialization of
a constant would create only a statically defined constant in these cases. I cannot think of one,
but I will be honest and admit that does not mean there is not one.
> So I could get behind dynamically valued constants and/or auto-memoizing functions. That would
> probably mean they still have a $ on them, which doesn't bother me. That clearly separates
> them visually from macro constants, which I like.
Having the $ requirement blocks my primary use-case, so it would bother me.
> The potential for hard to find bugs here is high; although the counter point is that using a
> function/method to emulate them today, which you can absolutely do, offers the exact same risk.
And that's the key point. It really is no different from what we have today, except that what I
proposed would provide evolvability.
> The trick is when exactly these run, because they're impure functions so whether they run
> at code compile time or first-access could mean a dramatic difference in their resulting value. And
> that is precisely why I am very, very nervous about allowing impure functions to be cached, whatever
> the syntax on top of them. (Constant-like or not.)
When you say "cached," what are you thinking the lifetime would be? And how would that
really be different from a static constant?
Are you concerned that the code could fail and leave the constant in an invalid state?
A potential way to address that is for a dynamic constant to require type hinting, and thus if it
did not return the correct type it would fail with an easy to trace error output. And also disallow
throwing errors outside of the constant. That would force developers to write robust dynamic
constant code.
-Mike