I would love to write an RFC, but I don't seem to have write access to the wiki. At the very least, I'm not able to create page, but I'm pretty sure I can't even edit them (at least not in the namespaces I've tried).

So let me start by bringing it up here. I've been a PHP developer for a long time (and before that, C / C++ ) and as I saw code grow and change, I developed design patterns to help ensure maintainability in the long term. In fact, as a founder of a business (and not just a programmer), I value the readability and maintainability of code even more than things like elegance, expressiveness, or programmer talent, because it scales better and is more robust, letting programmers get up to speed.

Anyway I noticed that the following always seems to happen over time: in any project, a set of functions and classes is created, which may or may not become a reusable library. There is code that calls these functions. Over time, the classes get more methods, and the functions may be overloaded to handle more functionality. The classes are designed to expand nicely, and nothing needs to be done. But the functions start looking pretty bad after a few years, because of the parameter mechanism. By necessity, the order of the parameters corresponds to the time at which they are introduced, and not something more logical. Providing defaults for the parameters does very little to mitigate this. Experience has shown that hardly anyone ever predicts at the outset how a library will evolve, and currently function "interfaces" are something that needs to be planned carefully at the start, or else can devolve into some nonsense that requires calls like:

myFunc(3, 4, null, 4, 8, null, "blah")

Besides being hard to follow, it's also cryptic to the reader of the call. We are not sure what the null or 4 corresponds to, without looking up the function definition (perhaps in a tooltip in an IDE).

The solution is simple. I've gotten into a habit of defining almost all my functions like this:

function myFunc($required1, $required2, array $optional = array()) { }

As the function's interface evolves over time, new required parameters cannot be introduced (as it would break the old calls to the function, which may be in the wild). However, functionality can be extended via optional parameters. Also, the calls to the function always look much cleaner:

myFunc(3, 4, array('clean' => true, 'name' => 'title'))

Inside the actual function implementation, I may very well just do: extract($optional). The $optional array can override existing parameters, etc... in fact, I can very easily set some defaults, with either one of these two patterns:

$clean = true; $name = 'default'; extract($optional);

or the javascript-like way:

$defaults = array('clean' => true, 'name' => 'default'); extract(array_merge($defaults, $optional));

So why am I saying all of this? Well, PHP up until 4 had a reputation for lots of bad coding style, spaghetti code, etc. With PHP 5 and better OOP, this reputation has lessened, especially with the great libraries out there (Zend Framework, Kohana, symfony, etc.) But there is still a problem. We (or at least I) would want PHP 6's reputation to be even better, and the reputation is largely based on how maintainable and cost-effective the code is, which is written by programmers actually using PHP. Blaming newbie programmers is one thing, and may even have some truth to it (PHP is simple - thus attracts newbies) but it's always good for a language to steer you in the right direction by default, and make it easier to write maintainable code.

PHP has a great opportunity to do this, by implementing a very simple change, turning all current PHP 5 code, and all code that will be written in the future, into maintainable code. Moreover, it won't break any existing code, like some other additions to PHP 6 might do. This one simple tweak will make PHP 6 code much more reusable and maintainable, just like namespace support will potentially make future PHP code more interoperable without having to write Artificial_Namespace_Class, like ZF and PEAR do.

So here is my proposal. Let's have named parameters. Yes, I know this has been brought up before and rejected -- although I don't know what the discussion was, so I would like to have one in light of what I said above. Other languages have elegant solutions to this ... python, javascript, etc. and yes I realize that a common response is "PHP is PHP and not those other languages". But this might be a short-sighted response, as other languages may have winning features that really make it possible for programmers to write better code, and develop better coding and thinking patterns, at no cost, and we would do well to consider whether PHP could benefit from a feature like that.

I propose we do two things in PHP 6:

1) Extend function call syntax and semantics so that providing parameters to a function has exactly the same syntax as creating an array. Namely:

myFunc(3, 4, 'a' => 'b', 'c' => 'd') would be possible, just like array(3, 4, 'a' => 'b', 'c' => 'd')

COMPATIBILITY:

This shouldn't break any userland code in earlier versions of PHP, because current function calls are simply a subset of the proposed functionality. They will continue to work in exactly the same way, from the point of view of userland.

PROS:

a) Makes understanding the language easier for everyone, since now there is only one thing to remember rather than two (current docs are a bit hard to grasp regarding references). Two concepts are unified into one, reducing mind clutter. Passing parameters becomes like creating an array, and references are handled nicely within this unified paradigm.

b) Most importantly, makes EVERY function and method extensible as I described above. No more adding parameters ad-hoc in the order they are dreamed up. Instead, they can be added as named parameters, just like the $optional array I was using above. While programmers can choose to use my design pattern, those that didn't plan out all future versions of the function (let's face it, the majority) still get to reap the advantage of this design pattern, simply via named parameters. Leading to *vastly more maintainable code*, which is what I am really advocating here.

c) Calls to functions will no longer be cryptic, but actually descriptive. Compare myFunc(3, 4, null, null, array(), 5) to myFunc(3, 4, 'max' => 5)

CONS:
There is only one I can think of. Named parameters are superior to parameters with default values (foo = "bar") in every way except one: because the defaults are assigned within the function implementation, they have to be documented separately (in DocBlocks, for example). I had someone bring up the objection that code using this design pattern would be less self-documenting. My response is that a) with magic methods, PHP hardly encourages self documenting code anyway, and b) the actual maintainability gains that result from sensible function interfaces will far outweigh whatever negligible benefit one may get from knowing parameter defaults from function signatures. If anything, it'll cause more people to document defaults properly, using DocBlocks or another method.

2) Extend func_get_args to be able to return associative arrays.

ANALYSIS:
This shouldn't break existing function calls, and here's why. Old versions of the function won't use this feature, so function calls to them won't need to change, either. New versions of the function will be written after this feature is introduced (i.e. in PHP6), so will be aware of the possibility of named parameters. Old calls to new versions of the function simply won't use the feature, so they won't need to change, either. New calls to new versions of the function have the option of using the feature, or not. So nothing is broken at all, but new functionality is there for you to use in PHP6.

PROS:

a) This once again makes PHP more elegant and unified. One of PHP's most notorious / cool features is that it lets you use array() for both numerically indexed arrays and associative arrays (a.k.a. maps, hashes, dictionaries, etc.) Why not weave this into PHP function calls as well? PHP is so function oriented. And this would give developers a lot of expressive power while at the same time promoting better code and the maintainability we talked about. I personally feel it's purely awesome whenever an extension is able to achieve both of those.

b) Lots of PHP programmers also work with Javascript. This would make them happy -- they can use what they consider to be a very useful coding pattern in JS (jQuery and most other popular frameworks use it), and start doing it in PHP:

function myFunc($a, $b) {
        $id = uniqid();
        $title = 'People hi';
        extract(func_get_args()); // possibly overriding the parameters
}

CONS:

a) Maybe there are some internal problems to implementing this, so serious that it's infeasible?

b) Will this break any PECL extensions? If so, are we planning to maintain compatibility with all PECL extensions written for earlier versions of PHP? Is it worth it to introduce this feature?

What do you guys think? I really want PHP 6 to rock and have an even better reputation among businesses, programmers, etc.

Sincerely,
Greg Magarshak

On Mar 30, 2010, at 2:37 AM, Philip Olson wrote:


On Mar 29, 2010, at 9:36 AM, GM wrote:

Hey guys. I'm glad to be on the internals list -- I just signed up. I've been a PHP developer for many years, and I have a couple ideas that might make PHP 6 better. Is this a good forum to bring up proposals of that kind?

Greetings Gregory,

Writing an RFC for largish features is typically a good idea:

 http://wiki.php.net/rfc

But you may want to first discuss these ideas on this list.

Regards,
Philip



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

Reply via email to