Hi Tim,
on Mon, Mar 19, 2012 at 09:09:58AM +1100, Tim Starling wrote:
On 18/03/12 20:37, Christian Aistleitner wrote:
Dear all,
should we allow using PHP's assert [1] in MediaWiki code?
It would allow us to formulate and automatically verify conditions about code, while at the same time providing readable documentation of code for free.
Possible, exemplary use cases would be:
- automatically verifyable documentation of code's intent
- guarding against logic pitfalls like forgetting to set a variable in all branches of switches, if/else cascades
- guarding against using uninitialized variables
What do you think?
We use exceptions for that.
Yes, this was the motivation for my email.
'If'-guards are fine. Just as exceptions are. They are excellent tools for conditions that /typically/ hold at run-time--but eventually they might fail. In such a case, we want to do classical error handling. It's the right tool for the job.
We can of course decide to keep using if-guards/exceptions when modelling conditions that /unconditionally and always/ hold. However, PHP introduced asserts some 12 years back for just this and only this use case. It's a proven tool. assert is tailored for conditions that /unconditionally and always/ hold. So why not allow this standard tool in our toolbox?
Due to this narrower use case, assert comes with some benefit over if-guards/exceptions in terms of code readability and quality: - We can turn off checking the conditions on production machines, to lower the impact. - assert's syntax shows the condition that holds. [1] - asserts produce good error messages without condition duplication. [2] - asserts clearly stand out in code. [3] - asserts just add the bare necessities to the code and do not clutter up code so much - asserts are less code to write.
P.S.: For typical MediaWiki use cases, PHP's assert is even faster than throwing exceptions behind 'if'-guards.
That's funny, for me "if" is about 10 times faster than assert() in the non-throwing case.
Have you tried real world examples?
Consider for example
$this->isOpen() && $this->mConn
This is a typical condition one could add in many places of DatabaseMysql.php. For this condition asserts are ~16% faster [4].
For this real-world example, the fact that assert takes the condition as string (hence unevaluated) outperforms the penalty due to the function call.
But speed is just in the "P.S.". assert's real benefit would be improved readability, as pointed out above.
Kind regards, Christian
[1] If guards show the negated condition. Hence, when reading the code, you have to mentally negate the condition again before actually knowing what has to hold.
[2] An
assert( 'condA && condB' );
would relate to
if ( ! condA || ! condB ) { throw new MWException( 'condA && condB was violated' ) }
Hence, if e.g.: condA changes, asserts just changes condA and we are done. For if-guards/exceptions, we have to adapt both occurrences of condA. This is somewhat error prone and it's easier for the conditions to run apart.
[3] if-guards/exceptions look like normal code. Hence, you have to mentally reparse it again and again and detect them. Typically IDEs cannot help or highlight only those guards that document code.
IDEs can easily detect and understand asserts. Even REs can find them ;)
[4] Please verify the number yourself. It was obtained by the attached assert_test.php. The output for me was:
RUNS: 10, ITERATIONS: 1000000 assert: 1.818 ifGuard: 2.148 assert: 1.798 ifGuard: 2.151 assert: 1.795 ifGuard: 2.162 assert: 1.798 ifGuard: 2.148 assert: 1.801 ifGuard: 2.154 assert: 1.800 ifGuard: 2.134 assert: 1.788 ifGuard: 2.140 assert: 1.790 ifGuard: 2.141 assert: 1.791 ifGuard: 2.146 assert: 1.797 ifGuard: 2.141 total: assert: 17.976 total: ifGuard: 21.464 assert is ~16% faster than ifGuard