> Am 30.06.2015 um 12:53 schrieb François Laupretre <franc...@php.net>:
> 
>> De : Bob Weinand [mailto:bobw...@hotmail.com]
>> 
>> Precisely. Instead of tight coupling to the structure, we now couple to the
>> macro… and it's not like the macro will be left untouched once we change the
>> underlying structure.
> 
> There are different levels of encapsulation : 1st level can be seen as the C 
> structure, 2nd level is the macro (allows to change the structure 
> organization), 3rd level provides separate read-only getters and write-only 
> setters. If you look at https://github.com/php/php-src/pull/1381, you will 
> see the API I want to integrate (not sure there is enough time before 7.0 
> freeze). It doesn't use macros any more but active methods/functions. There, 
> ZSTR_LEN() is a pure getter, which cannot be used as lvalue. ZSTR_SET_LEN() 
> is the corresponding write-only setter. I don't say that such API is supposed 
> to resist any implementation change but it should already allow a lot. When 
> we achieve this encapsulation level on arrays/HashTables, we'll be much more 
> comfortable with future potential changes.
> 
> I understand your pov. If any future change in the underlying implementation 
> requires changing the API, this API is much less valuable. You think that 
> zend_string internal implementation will never evolve without requiring API 
> changes. I don't think the same, I make no assumption on other's creativity, 
> I just know that, if the need for a better isolation arises someday, it will 
> be too late. So, I prefer to have it from the beginning. In zend_string, the 
> need comes more from the countless number of locations accessing the API than 
> from the implementation complexity. Of course, when we have both, like on 
> arrays, isolation is still more important.
> 
> Once again, zend_string is just an example. Zval needs some work too but is 
> somewhat easier as an extensive API already exists and most people use it, it 
> just needs to be made 'stricter'. Making the zval API stricter (with separate 
> getters/setters) will allow for a lot of debugging/monitoring instrumentation 
> to be added to the API. Some of them are also interesting for zend_strings. 
> Just imagine simple checks in debug mode ensuring the string length remains 
> in allocated bounds. If you set the length using a '->len' assignment or a 
> macro, it cannot be trapped and checked. It is really the simplest example of 
> what encapsulation makes possible. When we work on zend_string/smart_str 
> integration, code can also be inserted to measure the efficiency of various 
> over-allocation policies. With you '->len', what will you do ? "grep '--' 
> '->len' `find . -type f`" and rewrite thousands of occurrences ?

I see where you're heading to. But I still hold my position that you're 
overvaluing abstraction in that particular case. Like… it would be ideal to 
automatically reset the hash value on each change. Do we want that? No. It'd do 
millions of useless hash-resetting operations. So… what we end up? Having to 
manually control hash values. We always need to fallback to low-level control, 
even though we have an API. That's not good.
It'd be nice to abstract it away, but that's at a cost we aren't willing to 
pay. You only can have a certain level of abstraction without paying the price.

I think, zend_string * may evolve without structure changes. But in case we 
change the structures, something will have changed so drastically that the 
higher level APIs need change too.
I doubt that it will allow a lot.

Let's take your example with "stricter" API. What can you now debug/monitor? 
Like how a value changes? That you easily can right now with every smart C 
debugger… setting a watchpoint.
Also, smart string is an own API, with dedicated functions. We can very well 
test that at that level. No need to leak that over onto zend_string *. Smart 
string is a high-level API on top of zend_string *, _using_ the primitive 
zend_string API.

Oh, a check if it's in allocated bounds? Only issue is that we actually don't 
store the boundaries (also no reason to) … anyway, I can guarantee that the 
prefect abstraction will be leaky, or include a ton of functions operating on 
them. That's not the way to go.
Example… reallocing a string without setting a length (to extend but not 
knowing the exact final length yet) … not possible, currently. I'm sure, if you 
search for cases where the abstraction is leaky, you'll find enough.
Do NOT introduce leaky abstractions where it's not hiding complexity.

>> Like … PHP 7 changed the semantics of Z_TYPE() macro… you can no longer
>> assign directly to it. We anyway have to change our code.
>> It's rare that such underlying changes don't leak through the API.
> 
> No, we need to change our code because the zval API's encapsulation level was 
> not high enough. It type setters and getters had been already separate in PHP 
> 5, switching to PHP 7 wouldn't have required changing our code. That's why 
> defining access macros is not enough. We need stricter 'methods', designed as 
> services.

Okay. Other example. Refcounts. The macro itself still works… just that it'll 
badly fail when you try to refcount a primitive type now. The changes leak on 
all levels … Oh sure. You could have added a branch for each refcount checking 
the type… Just that will cost precious instructions.

Or IS_REFERENCE handling. A new type. Needs to be handled at all levels and 
beyond.
Or having now Z_STR() … sure, Z_STRVAL(), Z_STRLEN() still work, but became 
inefficient to use.

I could continue that list...

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

Reply via email to