> On Jan 5, 2020, at 1:24 PM, Rowan Tommins <rowan.coll...@gmail.com> wrote:
> 
>> class Environments {
>>    const PRODUCTION = 'master';
>>    const STAGING = 'stage';
>>    const TESTING = 'test';
>>    const DEVELOPMENT = 'dev';
>> }

How are enums a terrible example? They are exactly my use-case. PHP does not 
have declared enums, so class constants suffice.

BTW, what are "true constants" in this context?  For one of my client's these 
get changes based upon the APIs environments that have the updated data.

> In a sense, that's nitpicking at the example, but I think it's teling: the 
> kinds of constants that are "scannable" are generally not the kind that would 
> be replaced by configuration in the way you're suggesting.
> 
> If instead you have:
> 
> class API {
>     const URL = 'https://production.api.example.com';
>     const VERSION = 1.5;
> }
> 
> ...then being "scannable" isn't particularly relevant, because these are 
> completely separate values.

The benefits of being scannable are not limited to enum use-cases. The above is 
more scannable than the following, especially if I had 10+ values:

class API {
   function URL(): string{ 
      return 'https://production.api.example.com';
   }
   function VERSION(): string{ 
      return 1.5;
   }
}

So I don't get your arguments.

> I suppose it would be possible to design a language which maximised 
> "evolvability" by using interchangeable syntax for different concepts. For 
> instance, properties and constants could all just be special method calls; 
> perhaps "const FOO=42" would be sugar for "static function FOO() { return 42; 
> }" and "SomeClass::FOO" would always be the same as "SomeClass::FOO()".

NOW you are talking!  :-)

> However, there will always be new requirements that require a breaking change.

Clearly. But inability to optimize for perfect should not disallow optimizing 
for good.

> So it's not enough to say "everything should be evolvable", we need to ask 
> whether this specific scenario is common enough to design the language 
> around, and what the possible downsides of the feature might be.

Agreed.

> I disagree, I think constants being a literal value is a design decision, not 
> an implementation one.

How is this not just status-quo bias?

> Off the top of my head, I can think of three types of things that you might 
> call "constants":
> 1. A value that will never change, and you just want to give a name to. For 
> instance, MINUTES_IN_HOUR=60
> 2. A value set at compile-time, to hard-code a particular condition. For 
> instance, DEBUG=false
> 3. A value which is set at run-time, but happens not to change during the 
> course of the application, so should not be over-written.

While I totally agree with #1 there are constants like hours that will always 
have 60 minutes and #3 is my use-case, I don't see many values for #2 that I 
would not want to be able to change at runtime.

> Your proposed feature changes constants to instead be type 3, which I think 
> is a fundamentally different concept - much more like a property with extra 
> restrictions.

Again, how is this not just status-quo bias?

> I think it would be very confusing for the syntax which everyone is used to 
> meaning "hard-coded or at most compile-time value" could now actually mean 
> "global value different on every request":
> 
> const USER_ID {
>     return $_GET['user_id'];
> }

As I just replied to Larry, there are continuous changes in PHP that require 
developers to learn new features. How is this just not a new feature to learn?

What if instead of the above we allow this?

immutable USER_ID {
    return $_GET['user_id'];
}

Then const would be for type #1 and immutable would be for type #2 and #3. But 
they would both be accessed by ClassName::USER_ID. This would meet my objective 
for evolvability of code. 

You can say that people can't know which one it is when they use it, but I 
would ask why can't we expect them to know the API they are using?

BTW, if such a thing were added to PHP then we would document it to so that the 
code contained within must be very robust and be limited to the types of things 
that cannot fail, but if they do fail then failure should be handled internally 
and a proper value should always be returned.

> During the discussion of short closures a suggestion came up that the syntax 
> could be reused for single-expression methods, so you'd write this:
> 
> class Environments {
>    public static fn getUrl() => 'https://api.example.com';
> }
> 
> As you say, that still requires callers to know that they're calling a 
> method, not referencing a constant; we evidently disagree on whether that's a 
> good thing.

I am assuming in this case I would have to call it like Environments::getUrl(). 
 So this would address the use-case for people who proactively choose to use 
functions instead of constants.  IOW, it would be a 1/2 win for my proposed 
use-cases.


> As Larry mentions, the proposal is also limited by "globalness". Since 
> constants are always static, the initialisation code can only access global 
> and static state, so you can't inject a configuration object into your 
> constructor then use it to initialise constants.

I don't see why this is a limitation:

class API {
   function URL(): string{
      $config_class = defined('CONFIG_CLASS')
         ? CONFIG_CLASS
         : 'DefaultConfig';
      $config = new $config_class();
      return $config->get('api_url');
   }
}


> And since they're write-once, you can't use them for Laravel-style "facades", 
> where the access is static, but can be swapped out at run-time.

Since I am not up to speed on Laravel, I am not sure what you mean here by 
"swapped out at runtime."  Laravel can have different facades are different 
times during the page load?  Wow, that seems worse that having an initialized 
constant immutable for the entire page.

That said, it would show that developers can and do handle changes in 
expectation.

> Perhaps a better angle to look at is something like the C Pre-Processor - 
> manipulating the code at compile-time so that multiple different versions of 
> the code can be created from the same source, but constants are still 
> constant at run-time. I know there are tools out there already to do this, 
> but have never used one.

Oh God no!  Pre-processors are definitely an anti-pattern, in my book.  I came 
to that conclusion sometime in the 80's and have yet to see anything that 
changed my mind.

-Mike

Reply via email to