On Tue, Jun 30, 2015 at 8:15 AM, Bob Weinand <bobw...@hotmail.com> wrote:
>> 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

Just to time in with my $0.02: I feel that using macros as an
abstraction in this case is bad practice. I believe that in *most*
cases macros as an abstraction is a bad practice. Furthermore, there
isn't any reason that `zend_string_*` functions cannot act as an
abstraction layer since zend_string's are passed by pointer.

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

Reply via email to