tag:blogger.com,1999:blog-80966426209790091592024-02-18T22:11:43.394-05:00sə-rē'brə-fôrm'Hell-bent on bettering.Unknownnoreply@blogger.comBlogger35125tag:blogger.com,1999:blog-8096642620979009159.post-49746973249886236032022-08-10T14:33:00.000-04:002022-08-10T14:33:01.230-04:00On the Fight for Software Liberty<p><a href="https://www.gnu.org/people/speakers.html#Stallman">RMS</a> writes in <a href="https://www.gnu.org/philosophy/open-source-misses-the-point.en.html"><i>Why Open Source Misses the Point of Free Software</i></a>:</p>
<blockquote><p>Sometimes [developers of proprietary software] produce a program that is powerful and reliable, even though it does not respect the users' freedom. Free software activists and open source enthusiasts will react very differently to that.</p>
<p>A pure open source enthusiast, one that is not at all influenced by the ideals of free software, will say, “I am surprised you were able to make the program work so well without using [the Open Source] development model, but you did. How can I get a copy?” This attitude will reward schemes that take away our freedom, leading to its loss.</p>
<p>The free software activist will say, “Your program is very attractive, but I value my freedom more. So I reject your program. I will get my work done some other way, and support a project to develop a free replacement.” If we value our freedom, we can act to maintain and defend it.</p>
</blockquote>
<p>The last sentence is crucial, and yet RMS fails to convey the import: "we <i>can</i> act", sure, but to "maintain and defend" freedom one <i>must</i> fight for it.</p>
<p>In a 2002 <a href="https://www.gnu.org/philosophy/rms-hack.html">interview</a>, RMS states:</p>
<blockquote><p>[W]e need to think about right and wrong in making our decisions...</p></blockquote>
<p>Every decision, every time, we must choose the path that defends freedom and liberty.</p>
<p>Proprietary software aims to maximize control. Open source software aims to maximize distribution. Neither aims to maintain liberty, because neither made their first decisions around user freedom: the right to determine their use of software, not to be dictated by the software's regime.</p>
<p>Every right conveys a freedom, and every right requires a responsibility. Your responsibility, to yourself, your family, and your community, is to fight for your freedom with every choice.</p>
<p>This is all easy to say and difficult to do, once accustomed to convenience or the illusion of control. For example, I write this now on a MacOS using Safari. Google Fiber provides my Internet. My car is computer controlled, and I have no idea how that software operates. My phone is Android, Google again. I choose these because they're functional for my needs, I choose to work within the features they offer, and I can afford them. But I am beholden to them.</p>
<p>In <a href="https://www.gnu.org/philosophy/who-does-that-server-really-serve.html"><i>Who does that server really serve?</i></a>, RMS writes:</p>
<blockquote><p>[P]ower is something we must resist.</p></blockquote>
<p>From awareness comes suspicion and from suspicion comes resistence.</p>
<p>Everyone will have their own journey along the path, but I encourage readers to start by raising their own awareness to the software around them that holds power over them. Then to begin by questioning whether that power is something you want to give away. If not, consider how you begin your own resistance and fight toward a future where all software is under your control.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-14815952415760323292020-07-14T22:03:00.000-04:002020-07-14T22:03:11.975-04:00rm != rg<p>I use <a href="https://github.com/BurntSushi/ripgrep">ripgrep</a>, <code>rg</code>. It's like recursive <code>grep</code>, only 100x better.</p>
<p>Today, I had this session:</p>
<code><pre>$ rm pattern
rm: pattern: No such file or directory
$ rg pattern
$</pre></code>
<p>See that? I meant to type "rg pattern" the first time, but typed "<b>rm</b> pattern". Luckily no harm was done in this case. But what if I had typed "rm tod*", wanting to search for the string "to" followed by zero or more "d"? Well, I might just blow away my <code>todo</code> file, since it matches the <i>glob</i> <code>tod*</code>. And then I'd be sad.</p>
<p>I'm not sure if the ergomomics of rg as a command name have come up before, but this scary close encounter has me thinking. Maybe I should do this sly manuever, as suggested by a colleague: <code>alias ag=rg</code>.</p>
<p>I don't know. I think I'm tempted more so to make <code>rm</code> with its dangerous side effects harder to invoke. Like so:</p>
<code><pre>
alias remove=rm
rm() {
echo "If you want to destroy a file, use remove."
echo "If you want to find a file, use rg."
}</pre></code>
<p>What do you think?</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-103117100284591842018-10-30T00:33:00.001-04:002018-10-30T09:55:29.153-04:00Emulating block scope in PHP<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXnlYnI7ZtZLBIrl1LsQ-yI_bOM_3i59Uj0KSkVtVHhV4fPrVMT7wnBGBsuJqxyw5IOwBjj8ViHX09VCkJS23Rib4ugl53jvKL_-dBg5AkZWAwGrFlw8GXhUHpGbzPYddv-epGUPVFl-oy/s1600/my_tombstone+%25281%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="313" data-original-width="400" height="250" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXnlYnI7ZtZLBIrl1LsQ-yI_bOM_3i59Uj0KSkVtVHhV4fPrVMT7wnBGBsuJqxyw5IOwBjj8ViHX09VCkJS23Rib4ugl53jvKL_-dBg5AkZWAwGrFlw8GXhUHpGbzPYddv-epGUPVFl-oy/s320/my_tombstone+%25281%2529.jpg" width="320" /></a></div>
<p>Variables are born, they live their lives, and then they die. But beware! (Cue spoopy theme music.) Zombie variables lurk in the simplest of PHP.</p>
<a name='more'></a><br />
<p>Tonight's code horror opens with pseudo-code for a loop:</p>
<pre><code class='language-c'>array $array = 1..10;
for (int $i=0; $i ≤ count($array); $i++) {
// do a bunch of stuff
}
echo $i;</code></pre>
<p>What's the output value of <code>$i</code>?</p>
<ul><li><b>The Java dude</b> declares "Simple, it's undefined!"</li>
<li><b>The Javascript gal</b> hesitates "Probably... 10?".</li>
<li><b>The PHP guy</b>, <em>hardened by years of being language-slapped</em>, waffles: "Well, the count of $array is 10, but there could be a break, or a reassignment then break, or $array could be modified in that do a bunch of stuff, so I can't be certain, but I'll agree with the Javascript gal and say 'it should be 10'."</li></ul>
<p>The answer all depends on how the language supports block scope, which is what you get inside an <code>if</code>, <code>while</code> and the like. Java has mandatory block scope. When you declare a variable in a <code>for</code>, that variable exists only in that loop. Javascript has optional block scope, available since ES6 as <code>let</code>. PHP, alas, has no block scope, at all. PHP has global and function scope, and every variable defined in this scope is available in that scope from that point on. This can get messy.</p>
<p>Block-scope helps us reason about the code flow. We know that variables minted in a block scope are <i>guaranteed</i> to not exist outside that block. We can safely use and re-use their names at disparate parts of a function and not worry about refactor bugs. Block-scoping helps make code reasonable, and reasonability is a pillar of well-written code.</p>
<p>Let's look at opted-in block scope inside Javascript, a language familiar to many PHP programmers:</p>
<pre><code class="language-javascript">for (let i=0; i<arr.length; i++) {
// do something here
}
console.log(i); // ReferenceError</code></pre>
<p>Simple. We know that this <code>i</code> cannot interfere with any other <code>i</code> in this current scope. That's a guarantee, and guarantee's are central to analyzing code.</p>
<p>How might we implement this in PHP? Well, the language gives us two scopes, so we need to re-use one of those. The trick is to abuse function scope with an <a href="https://en.wikipedia.org/wiki/Immediately-invoked_function_expression"><abbr title="Immediately Invoked Function Express">IFFE</abbr></a>:</p>
<pre><code class="language-php">(function () use ($array) {
for ($i=0; $i<count($array); $i++) {
// do something here
}
})();
// $i undefined here
if ($condition) (function () use (&$array) {
$count = count($array); // $count is local to this condition
$array[] = 'foo'; // we declared $array pass-by-ref (&$array) in the use
// etc...
})();</code></pre>
<p>Encase the block you want to define inside an inline function, and run that function. Done. There are two obvious down-sides.</p>
<p>First, there's the verbose <code>use</code> bit to import variables from the outer scope into the inner scope. We can hope that PHP someday gains short-function syntax<sup><a href="https://wiki.php.net/rfc/short_closures">[1]</a>,<a href="https://wiki.php.net/rfc/arrow_functions">[2]</a></sup> or <a href="https://www.reddit.com/r/PHP/comments/3x2f2f/why_does_php_closure_force_us_to_import_local/">automatic import of all outer scope variables</a> to mitigate this concern.</p>
<p>Second is performance. What's the overhead, what's the cost to this safety net? Turns out, in my experiments, it's a little over 2.0%:</p>
<pre><code class="language-php"><?php
foreach ([1000, 10000, 100000] as $N) {
$begin = -microtime(true);
for ($i = 0; $i < $N; $i++) {
echo uniqid($i);
}
fprintf(STDERR, "%d %.6fs\n", $N, $t1 = ($begin + microtime(true)));
$begin = -microtime(true);
for ($i = 0; $i < $N; $i++) {
(function () use ($i) {
echo uniqid($i);
})();
}
fprintf(STDERR, "%d %.6fs %+.3f%%\n", $N, $t2 = ($begin + microtime(true)), ($t2-$t1)/$t1*100);
}</code></pre>
<pre><code class="language-bash">$ php -d error_reporting=-1 try1.php >/dev/null
1000 0.172234s
1000 0.176464s +2.456%
10000 1.729247s
10000 1.761645s +1.874%
100000 17.303003s
100000 17.670502s +2.124%</code></pre>
<p>I can't say I'll be using this technique. I'd rather just write small functions (25 lines or fewer) and be able to reason about them using just function scope. But not everyone is into hyper-decomposition like I am, so I can see a built-in block-scoping language feature being useful for those cases where less decomposition is required.</p>
<p>What do you think: is this technique ever worth the cost? Should PHP introduce language support to enforce block-scoped variable declarations?</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-52939679134474731202017-09-08T19:00:00.000-04:002017-09-08T19:00:02.370-04:00Choosing the first available program from list of optionsGNU <code>tar</code> accepts an external program to perform compression, via the option <code>--use-compress-program</code>. I'd normally want <code>pigz</code> if it's available, but if not, fallback to <code>gzip</code>. Is there a compact way to get represent this? Yes!
<pre>
which --skip-alias --skip-functions pigz gzip 2>/dev/null | head -1
</pre>
GNU <code>which</code> accepts multiple arguments, printing out the resolution for each as they're found or an error if not. GNU <code>which</code> also allows finding only full-fledged binaries, not aliases or functions. This is exactly what we want: list the paths to these programs, in the order I gave, then pluck the first one.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-1350611970601965482017-03-27T15:13:00.003-04:002017-03-27T15:17:25.163-04:00What is a @dataProvider?<p>I'm asked about data providers almost every time I introduce a developer to PHPUnit. Once you understand them, they're quite clear, but on first pass they seem to give developers pause.
<p>So what are they? Practically, a data provider is any static method that produces an array of arrays. The outer array defines the iterations of the test loop, while the inner arrays are the arguments to pass to each iteration. Let's look at an example. First, annotate a test method's docblock:
<pre><code class='language-php'>/**
* @dataProvider provides_foo_and_bar
*/
public function test_frobnicator($foo, $bar) { /* ... */ }
</code></pre>
<p>Then define the data provider:
<pre><code class='language-php'>public static function provides_foo_and_bar() {
return [
[ 'FOO', 'BAR' ],
[ 'BAZ', 'QUUX' ],
];
}
</code></pre>
<p>PHPUnit will call <code>provides_foo_and_bar</code> twice. The first time it will pass <code>test_frobnicator</code> with "FOO" and "BAR". The second time it will call <code>test_frobnicator</code> with "BAZ" and "QUUX". Note that the data provider is both public and static: PHPUnit requires that.
<p>Pro-top: by default, phpunit runs all data sets. But, you can select specific data sets to run easily: <code>phpunit FrobnicateModel.php test_frobnicate#1</code> runs only one loop, with the 1-index elements "BAZ" and "QUUX".Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-15595104428607444292016-12-15T14:19:00.000-05:002016-12-17T14:29:14.896-05:00Approximating GNU parted in WindowsI partition disks in Linux all the time. But, thanks to <a href="https://en.wikipedia.org/wiki/Ghost_(software)">disk ghosting</a>, I don't do much partitioning in Windows. When I do need to partition in Windows (like external drives), what do I use? Enter the Windows <a href="https://technet.microsoft.com/en-us/library/bb457110.aspx">Disk Management Snap-in</a>, <code>diskmgmt.msc</code>, first available in Windows 98.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKeiCXFyytAYAECGodIw8TslUnK3s9_N0S6d5XjmFIU6XRcuS5IBrmB-41x51pRbMDXLVD72ILn-ktsNBSRxy_M17BLh6DkCZ9zoKu5-JfiZ0uFnAjWzvXEMuSdHq9QoAikcBFUzyRaibB/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKeiCXFyytAYAECGodIw8TslUnK3s9_N0S6d5XjmFIU6XRcuS5IBrmB-41x51pRbMDXLVD72ILn-ktsNBSRxy_M17BLh6DkCZ9zoKu5-JfiZ0uFnAjWzvXEMuSdHq9QoAikcBFUzyRaibB/s320/Capture.PNG" width="320" height="254" /></a></div>
If you're familiar with <code>GNU parted</code>, this Windows tool will make perfect sense. You see immediately your list of hard drives, their partitions, and can click on them to delete or resize. Click on free space to partition.
There are some limitations, though. For example, you can't delete recovery partitions. For that, you can drop to the Windows command line and run <code>diskpart</code>. This tool is like Linux's <code>fdisk</code>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-11798119363463238792016-12-08T09:55:00.000-05:002017-11-03T14:47:34.888-04:00Identifying specific vulnerabilities in WordPress, by version<p>Exactly <em>how vulnerable</em> is your WordPress version? Ask the good folks over at <a href='https://wpvulndb.com'>the WordPress vulnerability database</a> who have not only assembled a vulnerability list by version, but also provided a nice API for querying.</p>
<pre><code class='language-bash'># WordPress 4.4.2 vulnerabilities, by type
$ curl -sS https://wpvulndb.com/api/v2/wordpresses/442 |\
jq -r '.["4.4.2"]|.["vulnerabilities"]|.[].vuln_type' |\
sort | uniq -c
1 BYPASS
1 CSRF
1 LFI
1 SSRF
1 UNKNOWN
5 XSS
</code></pre>
Same thing, but list the titles and take a version as a parameter:
<pre><code class='language-bash'>wpvulndb() {
version=${1:?Check which WordPress version for vulnerabilities (eg 4.8.3)?}
curl -sS "https://wpvulndb.com/api/v2/wordpresses/${version//./}" | \
jq -r --arg version "$version" '.[$version]|.["vulnerabilities"]|.[].title'
}
wpvulndb 4.8.3
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-69035018543168813412016-11-30T16:14:00.002-05:002016-12-01T03:01:41.468-05:00Pasting a remote file into your local clipboard (* mouse not required)<p>So, I'm updating a configuration file on a remote server (using MobaXterm), and I need to copy the contents into some Trello documentation running in a browser on my local Windows machine.</p>
<p>The old fashioned way to do it is to select it with the mouse (which MobaXterm interprets as copying to my Windows clipboard), then <kbd>Shift</kbd>+<kbd>Insert</kbd> it into the browser. Well, turns out you can use the command line:</p>
<pre><code class='language-bash'>[Bishop@Cygwin]$ ssh user@host "< /path/to/file" | clip
</code></pre>
<p>On Windows, <code>clip</code> is a program to read from standard in and put into the Windows clipboard. On Mac OSX, replace <code>clip</code> with <code>pbcopy</code> for the same effect.</p>
<p>You could extend this approach: instead returning the whole file, return the result of a pipe line. Neat. Like magic, no more mouse needed.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-83359966208148053362016-11-11T10:50:00.003-05:002017-01-05T10:10:46.992-05:00Bypassing private and protected visibility in PHP<blockquote>
<p>Members declared protected can be accessed only within the class itself and by inherited classes. Members declared as private may only be accessed by the class that defines the member.
</p>
<footer>
<cite><a href='http://php.net/manual/en/language.oop5.visibility.php#language.oop5.visibility'>PHP documentation on property visibility</a></cite>
</footer>
</blockquote>
<p>This is true only in an academic sense: code <i>outside</i> the object <i><b>can still</b></i> get and set private and protected members. As usual in PHP, all it takes is a little magic.</p>
<a name='more'></a><hr class="section" />
<p>Let's see how. Start with a completely sealed object, then use some magic to modify it from "outside":</p>
<pre><code class='language-php'><?php
class Sealed { private $value = 'foo'; }
$sealed = new Sealed;
var_dump($sealed); // private $value => string(3) "foo"
call_user_func(\Closure::bind(
function () use ($sealed) { $sealed->value = 'BAZ'; },
null,
$sealed
));
var_dump($sealed); // private $value => string(3) "BAZ"
</code></pre>
<p>The magic lay in <code>\Closure::bind</code>, which allows an anonymous function to bind to a particular class scope. The documentation says:
<blockquote>
<p>If an object is given, the type of the object will be used instead. This determines the visibility of protected and private methods of the bound object.</p>
<footer>
<cite><a href='http://php.net/manual/en/closure.bind.php#refsect1-closure.bind-parameters'>PHP documentation on <code>\Closure::bind()</code></a></cite>
</footer>
</blockquote>
<p>So, effectively, we're adding a run-time setter to <code>$sealed</code>, then calling that setter. This can be elaborated to generic functions that can force set and force get object members:</p>
<pre><code class='language-php'><?php
function force_set($object, $property, $value) {
call_user_func(\Closure::bind(
function () use ($object, $property, $value) {
$object->{$property} = $value;
},
null,
$object
));
}
function force_get($object, $property) {
return call_user_func(\Closure::bind(
function () use ($object, $property) {
return $object->{$property};
},
null,
$object
));
}
force_set($sealed, 'value', 'quux');
var_dump(force_get($sealed, 'value')); // 'quux'
</code></pre>
<p>I personally use this in testing and debugging, where I need a quick monkey-patch to accomplish a goal without having the formal architecture to support it. But you should <i>probably not</i> rely on this ability for production quality code. Then again, Composer <a href='https://github.com/composer/composer/blob/96bf605b31e15130f56aa524795a75b351896e25/src/Composer/Autoload/AutoloadGenerator.php#L776-L781'>uses this technique</a> so maybe you can, too.</p>
<hr />
<p><strong>Updated November 12, 2016:</strong> A commenter pointed out @ocramius blogged on this in 2013. To differentiate the two articles, I'll add that one can also use this technique to call private or protected methods:
<pre><code class='language-php'><?php
function force_call($object, $method, ...$args) {
return call_user_func(\Closure::bind(
function () use ($object, $method, $args) {
return call_user_func_array([ $object, $method ], $args);
},
null,
$object
));
}
class Sealed {
private function init($value) {
return strtoupper($value);
}
}
$sealed = new Sealed;
echo force_call($sealed, 'init', 'foo'); // string(3) 'FOO'
</code></pre>
<p><strong>Updated January 5, 2017:</strong> I stumbled upon <a href="http://kzykhys.com/blog/accessing-private-fields-using-closure/">a similar blog post by Kazuyuki Hayashi</a> today.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-25481028395876283792016-03-23T09:41:00.001-04:002016-12-01T03:02:10.371-05:00The end of the mouse era<a href="http://www.computinghistory.org.uk/det/613/the-history-of-the-computer-mouse/">Doug Englebart invented</a> the computer mouse nearly 50 years ago. Before HD, before GPU, before UX, the mouse let people interact with an information rich virtual space with ease.<br />
<br />
The generation whose work productivity preceded the mouse are retiring. Today's work force learned young or grew up with computer mice. We are comfortable with them. But the plunging cost of touch screen, the integration of draw-capable technologies in underlying OS, and the rise of hand-held form factor computing all spell the end of the mouse age.<br />
<br />
Our generation may find it difficult to imagine a world without mice. But consider, if price were not an object, would you rather have a mouse or a touch screen?<br />
<br />
Fundamentally, a mouse is the wrong tool for the job. If you want to select, move, shrink or otherwise manipulate windows, keyboard chords provide the necessary precision and do not change your <a href="http://www.usabilityfirst.com/glossary/locus-of-attention/">locus of attention</a>. If you want to scroll, page and cursor keys provide two resolutions of movement. If you want to draw a freehand shape, a touch screen or a <a href="http://www.digitaltrends.com/mobile/best-stylus-for-tablets/">digitizing tablet</a> offers measurably better precision.<br />
<br />
In the future, we'll see a world without mice. A world with keyboards and touch screens. When economic factors allow cheap, ubiquitous touch input, mice commodity will become a novelty. Good riddance I say.<br />
<br />
<hr />
<b>Addendum</b><br />
I was just asked how I navigate web pages without a mouse. The answer: <a href="https://vimium.github.io/">vimium</a>. Since I use vi, this is a natural move more me. Props to mjmccull for introducing this extension to me years ago. Read up on vimium in this <a href="http://luigimontanez.com/2010/mouseless-monday-1-vimium-google-chrome/">quick guide</a>.<br />
<hr />
<b>Bonus</b><br />
Did you know that <kbd>Windows</kbd>+<kbd>B</kbd>+<kbd>Enter</kbd> opens the Windows system tray? Here's a running list of Windows 10 keyboard shortcuts to help you cut your mouse cord.
<br />
<table>
<thead><tr><th>Shortcut Key Combination</th><th>Action or Effect</th></tr></thead>
<tbody>
<tr><td><kbd>Windows</kbd>+<kbd>B</kbd>+<kbd>Enter</kbd></td><td>Raise the Windows system tray. Use your cursor keys to navigate the tray icons</td></tr>
<tr><td><kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>Right</kbd></td><td>Move the active window right. Try also with the left cursor key.</td></tr>
</tbody>
</table>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-89976723656260238442016-03-03T10:19:00.000-05:002016-12-01T02:24:28.951-05:00Evoking all possible test failure modes in PHPUnitWhen you're writing your own <a href="https://phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.PHPUnit_Framework_TestListener">PHPUnit test listener</a>, you need a test case that evokes all the different PHPUnit test states. Here's you go:
<pre><code class='language-php'><?php
class EvokesTest extends \PHPUnit_Framework_TestCase
{
public function test_pass()
{
}
public function test_fail()
{
$this->fail(__FUNCTION__);
}
public function test_error()
{
throw new \RuntimeException(__FUNCTION__);
}
public function test_skipped()
{
$this->markTestSkipped(__FUNCTION__);
}
public function test_incomplete()
{
$this->markTestIncomplete(__FUNCTION__);
}
public function test_risky()
{
throw new \PHPUnit_Framework_RiskyTestError;
}
}
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-82755139135501922752016-02-25T10:42:00.000-05:002016-12-01T02:26:24.808-05:00Disabling Plugins in JenkinsIf a plugin upgrade causes problems, Jenkins may not restart. You'll be welcomed by an error message and a stack trace. Don't panic! Go into your Jenkins plugin directory, list files by date, and then disable the most recent ones:
<pre><code class='language-bash'>$ cd $JENKINS_HOME/plugins
$ ls -ltr *.jpi
-rw-r--r--. 1 root root 169194 Feb 22 10:12 script-security.jpi
-rw-r--r--. 1 root root 516115 Feb 22 10:12 next-executions.jpi
-rw-r--r--. 1 root root 739004 Feb 22 10:12 email-ext.jpi
$ touch email-ext.jpi.disabled next-executions.jpi.disabled script-security.jpi.disabled
$ service jenkins restart
</code></pre>
Files ending in <code>.disabled</code> instruct Jenkins to disable the corresponding plugin. Delete the disabling files until you've found the offending plugin. Then you can go into Jenkins and revert it to an earlier version.
Word of advice: Upgrade plugins in small batches. Doing so helps you isolate early problematic plugins.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-22039476084404878492016-02-18T08:32:00.000-05:002016-02-18T08:32:08.901-05:00Big list of files to edit? vim to the rescue (again)Did you know that you can treat the text under the cursor as a filename, and open that up for editing right in vim? Here's how:
<br />
<br />
<ul>
<li><kbd>gf</kbd> will open the filename under the cursor in the current window</li>
<li><kbd>^Wf</kbd> will open it in a split window</li>
<li><kbd>^Wgf</kbd> will open it in a new window</li>
</ul>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-20937467699469622942016-02-11T10:34:00.000-05:002016-02-11T10:34:02.766-05:00Today's fortune<blockquote>
<p>Let us not look back in anger or forward in fear, but around us in awareness.</p>
<footer>
— <cite><a href="https://en.wikipedia.org/wiki/James_Thurber">James Thurber</a></cite>
</footer>
</blockquote>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-50573854680508060742016-02-04T15:41:00.000-05:002016-02-04T15:41:04.949-05:00Private methods are collaborators in disguisePrivate methods cannot be unit tested, only integration tested through whatever public methods call them. I find this unsettling. I want to unit test private methods, so that I know the public methods are composed of independently verified code. What to do?<div>
<br /></div>
<div>
My first tactic is to avoid private methods. When behaviors are small enough, the need for private methods diminishes.</div>
<div>
<br /></div>
<div>
My second tactic is to promote them to public, but document that they aren't part of the API. This feels like a hack. A trick that's necessary because I've not thought about the design deep enough. I do this more than I like, honestly, because it's so quick and cheap to do.</div>
<div>
<br /></div>
<div>
Today, I thought of another approach that reinforces the first tactic. Maybe the apparent need for private methods is a signal that what I really want is a collaborator. Instead of privately doing a bit of work in furtherance of a class behavior goal, delegate that work to a first-class worker. Example? Sure!</div>
<div>
<br /></div>
<div>
Suppose I'm writing a class to model a web request. Part of web requests are MIME content type headers. These headers have specific formats for which a parser is needed. I could build parsing into my web request class, undoubtedly through several private methods that implement MIME content type parsing <a href="http://tools.ietf.org/html/rfc2045#section-5.1">RFC 2045</a>. These will be hard to test.</div>
<div>
<br /></div>
<div>
Instead of those private methods to parse the headers, I want to defer the parsing to a first class delegate. An actual, red-blooded class that knows only how to parse RFC 2045. Turns out, open source libraries already exist, and I don't have to do the work. A happy side effect.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-40472954607053190992016-01-28T12:00:00.000-05:002016-01-28T12:00:05.277-05:00Vim gem: built-in calculationVim is my go-to editor. Has been for 20 years. Besides being an all-around awesome editor for composing text, it also has some handy built-ins, like calculations:<br />
<br />
<ul>
<li>In insert mode, <kbd>^R=</kbd> accepts a mathematical expression, the result of which will be inserted in place.</li>
<li>In normal mode, <kbd>^A</kbd> increments the number at (or to the right of) the cursor by one, while <kbd>^X</kbd> decrements it by one. These accept repeats, so <kbd>5^A</kbd> will add 5 to the number.</li>
</ul>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-60587916156671245122016-01-21T12:00:00.000-05:002016-01-22T13:34:21.257-05:00Using vim to replace string functions with their multi-byte equivalentThe PHP INI option <span style="font-family: Courier New, Courier, monospace;"><a href="http://php.net/manual/en/mbstring.overload.php">mbstring.func_overload</a></span> override certain string functions (like <span style="font-family: Courier New, Courier, monospace;">strpos</span>, <span style="font-family: Courier New, Courier, monospace;">substr</span>, etc.) with multi-byte aware implementations. This makes it super easy to migrate a legacy code base to UTF-8, but immediately restricts interaction with vendor products (<a href="https://github.com/sensiolabs/SensioDistributionBundle/issues/169" target="_blank">Symfony</a>, <a href="https://github.com/mikepultz/netdns2/issues/41" target="_blank">Net_DNS2</a>, etc.).<br />
<div>
<br /></div>
<div>
The proper integration is to manually replace string functions with their multi-byte equivalent. In one legacy code base I'm improving, there are on the order of 10k instances of these functions. I want to change and verify each replacement, but I don't want to type much. Time for some vim-fu:</div>
<div>
<pre class="">:argdo %s/strpos/mb_strpos/gc | wn</pre></div>
<div>
This performs a confirmed find and replace, writes the change to disk, then moves on to the next file.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-63864149771021322332016-01-14T12:00:00.000-05:002016-01-14T12:00:16.574-05:00Jenkins + Slack + Fortune<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiapd21b3NgefXNZVJ1285A8iO9K-BaltUGzjQMHVyui2SQJrV1l0tUjGZDQ5JEA6Eevl_2henP_LUdS8v5AKqrNcITlM3uwS2DtrtouOlq23pqGU0TrlbE8gP740mMT5ia96NaCCIpORFr/s1600/jenkins-slack-fortune.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="91" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiapd21b3NgefXNZVJ1285A8iO9K-BaltUGzjQMHVyui2SQJrV1l0tUjGZDQ5JEA6Eevl_2henP_LUdS8v5AKqrNcITlM3uwS2DtrtouOlq23pqGU0TrlbE8gP740mMT5ia96NaCCIpORFr/s400/jenkins-slack-fortune.png" width="400" /></a></div>
<br />
<div>
<a name='more'></a>I love Jenkins, and I love Slack. But the stock Slack build message is boring as hell. If you feel the same way, here's how to get a fun message to follow the notification:</div>
<div>
<ol>
<li>Install Jenkins, the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Slack+Plugin" target="_blank">Slack notification plugin</a>, and importantly the <a href="https://wiki.jenkins-ci.org/display/JENKINS/EnvInject+Plugin" target="_blank">EnvInject plugin</a>.</li>
<li>Configure job to <a href="https://my.slack.com/services/new/jenkins-ci" target="_blank">notify slack</a> on build success, failure, etc. </li>
<li>Add an "Execute Shell" build step, which runs your witty command writes it to a file as an environment variable.<br /><b>Tip:</b> Surround your message with ``` to format it nicely in Slack.</li>
<li>Add an "Inject env variables" build step to pull in the file created in the previous step.</li>
<li>Add the environment variable to the Jenkins Slack custom message.</li>
</ol>
<div>
There you go! Here's what those steps look like. I'm using the UNIX fortune command for these:</div>
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSyh7t4EucUAm8wgfB2z7QQ4JFHBGYSK9aR68UkgLbURBd-8_Un9xVD21TH5fltykABK_Wa6qpkyumXZjRBh1Gahy5Km1WOtdU-ozH1AruQTz8HB_6KTmEr6drujkwasKqoKpgMlhE0VMZ/s1600/jenkins-example-config.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSyh7t4EucUAm8wgfB2z7QQ4JFHBGYSK9aR68UkgLbURBd-8_Un9xVD21TH5fltykABK_Wa6qpkyumXZjRBh1Gahy5Km1WOtdU-ozH1AruQTz8HB_6KTmEr6drujkwasKqoKpgMlhE0VMZ/s640/jenkins-example-config.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This Jenkins setup populates an environment variable with a fun message.</td></tr>
</tbody></table>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihGMzRT0AjwEZ_rJRtDpc0hH7vGvLkw3lXSM3p79GrvIMKu4WfK4P00We4FTJhyphenhyphenru8C4eiRAfU3BjyC8CNGJGRxyk05hkqOlyiOixX40eHSn8nJn2boYAAQuDkxHhzMQ2T43_hbNrFT63X/s1600/jenkins-custom-message.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihGMzRT0AjwEZ_rJRtDpc0hH7vGvLkw3lXSM3p79GrvIMKu4WfK4P00We4FTJhyphenhyphenru8C4eiRAfU3BjyC8CNGJGRxyk05hkqOlyiOixX40eHSn8nJn2boYAAQuDkxHhzMQ2T43_hbNrFT63X/s640/jenkins-custom-message.PNG" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This publishes the environment variable to Slack.</td></tr>
</tbody></table>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-49118328641763921582016-01-11T15:39:00.000-05:002016-01-22T13:35:58.565-05:00[Proposed] Elephpant EtiquetteYes, I do believe PHP internals needs a guide to etiquette. But, no, not a code of conduct. Internals is a decades (plural) old <a href="http://oss-watch.ac.uk/resources/governancemodels" target="_blank">cathedral-like meritocracy</a>. There is no benevolent dictator. There is no functional oversight group. No rigorous process (like Go <a href="https://golang.org/conduct" target="_blank">has</a>) will work in the internals ecosystem.<br />
<br />
Anthony's draft sets the stage, but I don't think it'll draw the crowds. For that, we need a moderate approach that emphasizes the definition of acceptable behavior while limiting the authoritative scope. Here's my second attempt at a custom-fit "code of conduct" roughly based on <a href="https://golang.org/conduct">the one from Go</a>:<br />
<br />
<a name='more'></a><h2>
Elephpant Etiquette (v1.1)</h2>
<div>
We, the international community of PHP contributors, affirm our need to maintain cordial online collaborative spaces and do adopt this etiquette as our guide in doing so.</div>
<div>
<br /></div>
<h3>
(I) Collaborative Spaces</h3>
<div>
Our online collaborative spaces are the nerve center of PHP evolution. We all share these spaces and are all responsible for keeping them welcoming, friendly, and focused. We define these spaces as:</div>
<div>
<ul>
<li>The PHP mailing lists</li>
<li>The PHP IRC channels</li>
<li>The PHP Twitter feed</li>
<li>The PHP Facebook page</li>
<li>The PHP Github accounts and the PHP SVN documentation repositories</li>
<li>The PHP.net documentation, including comments</li>
<li>The PHP bugs and feature request database</li>
</ul>
<div>
Anyone who contributes to any of these channels is a <i>de facto</i> contributor.</div>
<div>
<br /></div>
<h3>
(II) Contributors' rights and responsibilities</h3>
</div>
<div>
As a PHP contributor, you have the right to:</div>
<div>
<div>
<ul>
<li>Converse in our collaborative spaces without fear of harassment</li>
<li>Present your own thoughts and ideas</li>
<li>Submit changes to PHP, its extensions, and documentation</li>
<li>Walk away of your own volition</li>
<li>Become a community moderator through the vote of other contributors</li>
</ul>
</div>
</div>
<div>
As a contributor, you also represent PHP and are responsible for:</div>
<div>
<ul>
<li>Your contributions:</li>
<ul>
<li>Adhere to submission guidelines</li>
<li>Timely respond to inquiries about your submissions</li>
<li>Remember that constructive criticism isn't personal</li>
</ul>
<li>Your words:</li>
<ul>
<li>Be understanding</li>
<li>Be <a href="http://www.londonschool.com/language-talk/language-tips/5-tips-for-polite-and-diplomatic-language/" target="_blank">polite</a></li>
<li>Be <a href="https://oilpatchwriting.wordpress.com/2011/04/14/the-five-cs-of-writing-%E2%80%93-part-3-conciseness/" target="_blank">concise</a></li>
<li>Speak honestly with <a href="http://personalexcellence.co/blog/constructive-criticism/" target="_blank">constructive language</a></li>
<li><a href="http://www.nizkor.org/features/fallacies/ad-hominem.html" target="_blank">Discuss the position, not the person</a></li>
</ul>
<li>Your behavior:</li>
<ul>
<li><a href="http://www.skillsyouneed.com/ips/active-listening.html" target="_blank">Actively listen</a> to those who are speaking</li>
<li>Affirm what you hear</li>
<li>Remain calm (strive for <a href="https://en.wikipedia.org/wiki/Equanimity" target="_blank">equanimity</a>)</li>
<li>Keep your voice down (NO CAPS)</li>
<li>Stay out of other's <a href="https://en.wikipedia.org/wiki/Proxemics#Personal_space" target="_blank">personal space</a></li>
<li>Heed the advice of community moderators</li>
</ul>
</ul>
<div>
We encourage contributors to apply this etiquette outside our collaborative spaces.</div>
<div>
<br /></div>
<div>
</div>
</div>
<h3>
(III) Community moderation</h3>
<div>
Our collaborative spaces are moderated. Community moderators are stewards of the community's interest in collaboration. They proactively encourage collaborators to adhere to our etiquette. They provide advice and guidance to individuals and mediate dispute between contributors. They listen without judging. They keep specific details in confidence.</div>
<div>
<br />
Community moderators exist to resolve conflicts in the most harmonious possible manner. They enjoin contributors to corrective behaviors. They can recommend censure for repeated or egregious missteps of etiquette.<br />
<br />
To reach a moderator, email moderators@php.net.<br />
<br />
To add or remove a moderator requires a 4/5 majority vote by the deliberative body of electors holding voting karma. Contributors without voting karma may lobby karma holders, but there is no means for direct voting. All votes for community moderators are anonymous.</div>
<div>
<div>
<br /></div>
<div>
To become a moderator, email moderators@php.net. In your own words, describe why you want to moderate (this your purpose statement). Include a relevant bio illustrating your diplomatic prowess. Existing community moderators will help you polish your application into an RFC and shepherd it through the voting process.<br />
<br />
Community moderators are themselves contributors, but are expected to model the etiquette without fail. Any contributor may petition to remove a moderator. To remove a moderator, email moderators@php.net with your petition. Existing moderators will help you shape your petition into an RFC and shepherd it through the voting process.<br />
<br />
Moderators are facilitators and shepherds. Moderators do not cull applications or petitions.</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-12470097013126652312016-01-08T22:46:00.002-05:002016-01-08T23:09:53.175-05:00PHP Contributor EtiquetteI was the first to publically +1 the <a href="https://wiki.php.net/rfc/adopt-code-of-conduct" target="_blank">Code of Conduct RFC</a>. I'd love to see a policy that fosters diversity and inclusion, because <i>damn</i> the PHP crowd is <a href="http://www.facesoftheelephpant.com/archive" target="_blank">startlingly similar</a>. But, after hearing the arguments, I can't endorse the code as written. It's too focused on process and punishment. I believe we need to look at this from a definition of rights and responsibilities. This is my attempt.<br />
<br />
<a name='more'></a><br />
<h2>
PHP Contributor Etiquette</h2>
<div>
<div>
PHP exists because programmers, admins, and writers from all over the world volunteer their time and talent. Through mostly digital media, these volunteers collaborate to improve PHP. It's a social system revolving around intensely technical details. Like any social setting, there is a need to define the code of ethical behavior and conventions of communication. Our etiquette aims to foster an environment where all voices are welcomed and heard:</div>
</div>
<h4>
(I) You are a contributor to, and representative of, PHP if you:</h4>
<div>
<ul>
<li>Join any of the PHP communication channels (mailing lists, IRC channels, Twitter feeds, or Facebook group) and start or reply to a conversation.</li>
<li>Post comments on php.net or bug/feature requests on bugs.php.net.</li>
<li>Submit comments, issues, or patches to PHP or its extensions through Github.</li>
<li>Attend any conference authorized to use the PHP logo.</li>
</ul>
</div>
<h4>
(II) As a contributor to PHP, you have the <u>right</u> to:</h4>
<div>
<ul>
<li>Participate in conversations without fear of harassment</li>
<li>Present your thoughts and ideas</li>
<li>Submit changes to PHP, its extensions, and documentation</li>
<li>Walk away (both in person and digitally)</li>
<li>Become a community moderator through the vote of other collaborators</li>
</ul>
</div>
<h4>
(III) As a representative of PHP, you are <u>responsible</u> for:</h4>
<div>
<ul>
<li>Your contributions:</li>
<ul>
<li>Adhere to submission guidelines</li>
<li>Timely respond to inquiries about your submissions</li>
</ul>
<li>Your words:</li>
<ul>
<li>Be understanding: everyone's perspective is different</li>
<li>Be <a href="http://www.londonschool.com/language-talk/language-tips/5-tips-for-polite-and-diplomatic-language/" target="_blank">polite</a></li>
<li>Be <a href="https://oilpatchwriting.wordpress.com/2011/04/14/the-five-cs-of-writing-%E2%80%93-part-3-conciseness/" target="_blank">concise</a></li>
<li><a href="http://www.nizkor.org/features/fallacies/ad-hominem.html" target="_blank">Discuss the position, not the person</a></li>
</ul>
<li>Your behavior:</li>
<ul>
<li><a href="http://www.skillsyouneed.com/ips/active-listening.html" target="_blank">Actively listen</a> to those who are speaking</li>
<li>Affirm what you hear</li>
<li>Remain calm (strive for <a href="https://en.wikipedia.org/wiki/Equanimity" target="_blank">equanimity</a>)</li>
<li>Keep your voice down (NO CAPS)</li>
<li>Stay out of other's <a href="https://en.wikipedia.org/wiki/Proxemics#Personal_space" target="_blank">personal space</a></li>
<li>Heed the advice of community moderators</li>
</ul>
</ul>
<div>
Community moderators are stewards of the community's interest in collaboration. They proactively encourage collaborators to adhere to our etiquette. They provide advice and guidance to individuals and mediate dispute between collaborators. They listen without judging. They keep specific details in confidence.</div>
</div>
<div>
<br /></div>
<div>
To reach a moderator, email moderators@php.net.</div>
<div>
<br /></div>
<div>
To become a moderator, email moderators@php.net. In your own words, describe why you want to moderate (this your purpose statement). Include a bio. Existing community moderators will help you shape and polish your purpose statement and bio, then present your application for an anonymous vote. With a 4/5 confidence, you will become a community moderator. You may request a copy of the tally, with specific email addresses scrubbed.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-79219055109584404762015-11-13T16:38:00.002-05:002016-12-01T02:32:33.716-05:00Wielding PHP magic with the Callable Object PatternThe PHP magic method <code>__invoke</code> provides a powerful way to encapsulate functionality while separating state from results and errors.
<a name='more'></a><hr class="section" />
I'm no warlock. I eschew the magic methods PHP offers in favor of explicit method signatures. I feel this approach has served we well over the years. But I've taken a liking to <a href="http://php.net/manual/en/language.oop5.magic.php#object.invoke" target="_blank">__invoke</a> recently.<br />
<br />
If you don't know <code>__invoke</code>, it allows you to call your object as if it were a function. Wikipedia calls these "function objects" and <a href="https://en.wikipedia.org/wiki/Function_object" target="_blank">says</a>:<br />
<blockquote class="tr_bq">
A function object is a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function).</blockquote>
Here's an example, just to get the concept down:<br />
<br />
<pre><code class='language-php'><?php
class Yell {
public function __invoke($message) {
echo $message;
}
}
$yell = new Yell();
$yell('Hello');
</code></pre>
<br />
Notice that <code>$yell</code> is an <i>object, </i>but is called as if it were a <i>function</i>.<br />
<br />
<h2>
Why use function objects?</h2>
<br />
<h3>
Decorating</h3>
<div>
Since you're dealing with an object, you have the opportunity to configure how the object will behave before you invoke the function:</div>
<div>
<br /></div>
<div>
<pre><code class='language-php'><?php
class Yell {
public function setEnclosingTags($before, $after) {
$this->before = $before;
$this->after = $after;
}
public function __invoke($message) {
echo $this->before . $message . $this->after;
}
private $before = '';
private $after = '';
}
$yell = new Yell();
$yell->setEnclosingTags('<b>', '</b>');
$yell('hello'); // outputs <b>hello</b>
</code></pre>
<br />
Were you to write a function for this behavior, the signature would look like this:<br />
<br />
<pre><code class='language-php'><?php
yell(string $message, string $begin = null, string $end = null): void</code></pre>
<br />
For such a simple function, this signature would suffice. But this is only a simple example. Imagine your state setup was more complicated. You might end up with <a href="https://github.com/sebastianbergmann/phpunit/blob/5.0.0/src/TextUI/ResultPrinter.php#L125" target="_blank">a method having 6 or more arguments</a>. That's just unmaintainable. Object methods make for much cleaner code.</div>
<br />
<h3>
Separating errors from results</h3>
<div>
Let's take this a little further. Suppose we want to know the total number of characters yelled and whether there was an error yelling them:</div>
<div>
<br /></div>
<div>
<pre><code class='language-php'><?php
class Yell {
public function setOutputStream($stream) {
$this->stream;
}
public function __invoke($message) {
$bytes = fprintf($this->stream, $message);
$this->error = (strlen($message) !== $bytes);
return $bytes;
}
public function writeError() {
return $this->error;
}
private $stream = STDOUT;
private $error = false;
}
$yell = new Yell();
$bytes = $yell('hello');
if ($yell->writeError()) {
die('Whoops, only managed to yell this many bytes: ' . $bytes);
}
</code></pre>
<br /></div>
<div>
Clean. The function result comes from the invocation. The error state comes from the object. Perhaps this is the best of both worlds.</div>
<br />
<h2>
Why use magic when an explicit method will do?</h2>
<div>
I was of this school for a long time. My past self would instead have defined an explicit method:</div>
<div>
<br /></div>
<div>
<pre><code class='language-php'><?php
class Yell {
public function output($message) {
echo $message;
}
}
</code></pre>
<br /></div>
<div>
I've come to appreciate syntactic sugar that clarifies my code. To me, the value of PHP function objects lay in being able to <i>clearly pass the object to any method taking a callable</i>.</div>
<div>
<br /></div>
<div>
<pre><code class='language-php'><?php
$yell = new Yell();
$yell->setEnclosingTags('[', ']');
$words = [ 'goodbye', 'cruel', 'world' ];
array_walk($words, $yell);
// vs the awkward: array_walk($words, [ $yell, 'output' ]);
</code></pre>
</div>
<br />
<h2>
The Callable Object Pattern</h2>
<div>
Every function could be replaced by a function object. That kind of <a href="http://www.joelonsoftware.com/articles/fog0000000018.html" target="_blank">astronaut architecture</a> is dangerous, and I plan to stick with explicit methods in the main. Yet, I feel there are two use cases for the Callable Object Pattern that avoid becoming anti-pattern-like.</div>
<div>
<br />
<h3>
Decorators</h3>
</div>
<div>
Two properties of decorators suggest to me they'd be good for following the Callable Object Pattern:</div>
<div>
<ol>
<li>They usually have a lot of setup. For this reason, decorator classes either develop long-winded function signatures or require dedicated configuration objects. Instead, the callable object could have all the setup methods on it.</li>
<li>They may be run multiple times, with slight variations on setup. Callable objects have a relatively large setup (the new call, then any setup methods) for the relatively small pay-off of function invocation. However, if the invocation needs to be made several times, with little change in the setup, the initial setup pays off.</li>
</ol>
</div>
<br />
<h3>
Higher-order functions</h3>
<div>
This use case started my deep consideration of __invoke. In the code I'm currently writing, which is fixing a legacy system from terrible, procedural PHP 5.3-ish code to PHP 5.6 code, I needed to do several things in several different places:</div>
<div>
<ul>
<li>Copy files from network locations, using different protocols, but retrying if the copy fails</li>
<li>Capture any PHP emitted errors and report them</li>
</ul>
<div>
These aren't related pieces of code. Both have several different unrelated use cases, but do intersect in a few places. So, I want the capturing to work on any arbitrary block of code. I want the copy-with-retry to work on any arbitrary copy command. I need to use them in many different, separate, uncoupled classes as well as together.</div>
<div>
<br /></div>
<div>
I settled on a higher-order function implementation that goes like this:</div>
<div>
<br /></div>
<div>
<pre><code class='language-php'><?php
use Haldayne\Fox\Retry, Haldayne\Fox\CapturingErrors;
$retry = new Retry(
$capture = new CapturingErrors(
function ($src, $dst) {
return copy($src, $dst);
}
)
);
$capture->setCapturedErrorTypes(E_ALL|~E_STRICT);
$retry->setAttempts(5);
$result = $retry('ssh.sftp2://user@host/file', 'file');
if (false === $result) {
die($capture->getCapturedErrors()->implode(PHP_EOL);
}
</code></pre>
</div>
<div>
Taking those inside-out. CapturingErrors runs the function inside of it, but wraps the call in an error handler that spools any triggered errors (except for E_STRICT). Retry runs the function up to 5 times, exponentially backing off in case of failure. When the whole pipeline resolves, I check the return code and can display the captured errors.</div>
<div>
<br /></div>
<div>
Each individual class using the Callable Object Pattern only knows it receives a function. It doesn't care what that function is. In this use case, that function happens to be another class implementing the Callable Object Pattern. This leads to greater composability, because __invoke is treated as an implicit interface.</div>
<br />
<h2>
What do you think?</h2>
<div>
I've made a case for using the Callable Object Pattern in a couple of specific cases. Do you agree? Do you use __invoke in this way? Or other ways?</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-90784436340370816732015-11-06T09:18:00.000-05:002015-11-06T09:19:58.033-05:00Fear Factory celebrates 25th Anniversary of Demanufacture<a href="http://metalhammer.teamrock.com/news/2015-07-07/fear-factory-mark-demanufacture-anniversary" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_WC1hc6ferYHQCWETjT5a9slxhEQZnfehbaDYn09E6gCB4_VyUKfnNcOd2_CwMqoAP_jLzp_UxUEbEJzOPZzKrmzOqd9qetAX6KiGNPqC17qYXStvidV6GAYhNwaeuUXIiVkbakTAjZNu/s1600/original-flyer-demanufacture-25th.jpg" width="75%" height="75%" /></a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-4891897360472708822015-10-27T17:09:00.000-04:002016-12-08T09:57:36.058-05:00PHP array de-duplication trick that'll save you lots of CPU (* YMMV)<blockquote>
<p>Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.</p>
<footer>
<cite>― <a href="http://stackoverflow.com/a/878436/2908724" target="_blank">John Woods</a></cite>
</footer>
</blockquote>
<p>Today, I discovered this curious gem in legacy code:</p>
<pre><code class='language-php'><?php
// ✂ ...snip... wall of code that creates array $ids
$ids = array_flip($ids);
$ids = array_flip($ids);
// ✂ ...snip... wall of code using $ids
</code></pre>
<p>Looks like a cut and paste error, and my gut reaction was to delete the second line. But, a sneaking suspicion stalled my reaction: the developer-that-no-longer-works-here who wrote that code had a talent for writing clever, uncommented code. Perhaps this was another instance of that pattern, and I'd better check myself.</p>
<p>PHP arrays map keys to values. <a href="http://php.net/manual/en/function.array-flip.php" target="_blank"><code>array_flip</code></a> spins the mapping around, values to keys. If the code <em>intended</em> to flip the array, then I'd expect to see iteration over values to keys. What I observed in later logic was instead iteration of keys to values, as if the flip never happened. So what was this code doing?</p>
<p>It's a de-duplication trick, <a href="http://php.net/manual/en/function.array-unique.php#24831" target="_blank">first seen in a 2002 comment about <code>array_unique</code></a>. Purportedly, double flip is <em>significantly</em> faster than the equivalent <code>array_unique</code> call for large arrays. Before you rush off and change all your code to use this trick, keep these things in mind:</p>
<ul>
<li><code>array_unique()</code> and <code>array_flip(array_flip())</code> produce different results where keys are concerned: <code>array_unique</code> keeps the <i>first</i> unique (key, value) pair while <code>array_flip</code> keeps the <i>last</i>.</li>
<li><code>array_unique([0, false, 0])</code> produces the <a href="https://3v4l.org/vKUNm">expected result</a>. Double flip does not (and raises a warning to boot).</li>
<li>For small arrays, the performance difference is <i>invisible</i>.</li>
<li>For very large arrays of <em>numbers</em>, the difference between <code>array_unique($a, SORT_NUMERIC)</code> and <code>array_flip(array_flip())</code> is <em>negligible</em>. On a medium Amazon EC2 instance, 0.27s vs 0.4s for 10M integers.</li>
<li>For very large arrays of <em>strings</em>, the difference is <em>significant</em>. On a medium Amazon EC2 instance, 1.2s vs 10.9s for 10M strings of random length between 3 and 5 ASCII characters.</li>
</ul>
<p>That's a real savings, and so this trick definitely has a place in the developer's tool box. But please, <em>please</em> for the love of all that is holy, comment the trick so that's clear what's going on. My preferred way of seeing this trick deployed is:
<pre><code class='language-php'>$ids = array_flip(array_flip($ids)); // want unique values, don't care about keys
</code></pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-38125066028793242062015-10-14T11:17:00.002-04:002015-10-14T11:17:43.850-04:00404 <p>I'm terribly sorry, but I can't find the page you have requested.</p>
<p>Believe me, I looked for it. Really! You can't even imagine the
millions of calculations I had to go thru to look in all the places
my owner could have left what you asked for. But I couldn't find it. It's not there! :-(</p>
<p>No, it's not your fault, it's all my own. I'm a bad server. I know. Terrible.
I should get a new job one day or another, but what else can I do?</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8096642620979009159.post-309410716663129912015-10-13T09:59:00.001-04:002015-10-13T09:59:07.594-04:00On collaboration.<blockquote>
<p>If you want to walk fast, walk alone.<br />
If you want to walk far, walk together.</p>
<footer>
<a href="http://www.africanprisons.org/want-walk-fast-walk-alone-want-walk-far-walk-together-app-walks-justice-law-order-sector-officials-uganda/">-- African proverb</a>
</footer>
</blockquote>Unknownnoreply@blogger.com0