Ruby: Time Comparisons Seem Backwards Due to Asian Culture

I found a weird quick in Ruby best explained by the fact it’s written by a Japanese dude. Nerd post below. In Ruby, when you compare two time signatures, you use the operator:

<=>

It compares two Time objects and then returns -1, 0, +1, or nil. So this is how it looks in practice:

comparison_result = today_time <=> yesterday_time

What’s the value of “comparison_result?” The answer is 1. 1? I stared at this for a long time and my inclination was to think it should return whichever side was bigger. There was very little documentation I could find on this topic, but I finally figured out why.

The reason WHY is that time flows down or backwards in Asian culture, and Ruby is written by a Japanese dude. Confirmation in this wiki article.

So the conclusion is that this operator should be read as, “Which side is smaller?” As in: left side = -1, right side = +1, 0 = same, and nil = invalid.

Come on, Facebook

Facebook just had their annual F8 conference, and it was a snooze-fest to me. Examples of things they could have done that would be ACTUAL game changers:

  • An HTML5-based social application platform (currently missing from their mobile strategy and making embedded FB apps less important on mobile)
  • Embedded contextual ads on existing Facebook widges, complete with rev-sharing – yep, it would be hated
  • A truly threatening Adsense competitor for off-Facebook publishers – yep, could be hated too
  • A FB credits fee of 5% (from 30%), and enable physical e-commerce – yep, threatens a working business model
  • A connect-to-pay Paypal clone – yep, would increase Facebook’s financial liabilties

Yes they might harm them. Yes they’re risky. But they’re game changers. They flip the market upside down. They make existing competitors freak out. It pushes you even further as a leader. And, thus, the absence of such a risk shows how conservative Facebook has become.

Instead, they announced a glorified scrap book and some cool automated like buttons.

I’m sorry, but the timeline is hardly revolutionary. How is this remotely on par with the introduction of apps or the Graph API at previous F8 conferences? As a company approaching IPO, this was their moment to really show the world what Facebook’s potential could be. And so they showed off a bunch of visual fluff. The press is fawning over the newly released changes like the second coming of Jesus.

Not to mention all of these new integration points don’t even work on their current web-based or native mobile applications! What am I missing here?

I am disappointed.

“Michi’s Minions” – On Respecting Co-workers

In my relatively short, but unusual, career I’ve heard the phrase “Michi’s minions” a number of times. People use it to jokingly refer to my staff. They say it in private, so I think some people might conclude it’s just a crass joke. Perhaps. For people that know my crude sense of humor, my offense to this joke probably takes you by surprise. Every time I hear that phrase, I immediately conclude the other person is not somebody I want to work for and that they have a naive understanding of professional relationships. History usually proved that conclusion correct.

To me, it indicates a certain condescending/naive attitude that the person has toward employees that is absolutely unacceptable. I once heard the analogy that management is like a rowing team. You’re the coxwain that helps keep the rowboat straight. Yet, when you think about it, you don’t lift a finger to help the results get done. If somebody gets tired or wants to quit, you can’t take out a whip and start cracking. At the same time, without the coxwain, the team will never make it to the finish line. You both need each other. All of my greatest accomplishments as a leader in an organization were because of the hard work the team put in. To forget that your staff were the ones furiously rowing is ignorant if not insulting.

When somebody thinks that “managing” equates to “having minions,” it’s not pretty to watch them get a little power. I’ve seen this a few times now and it had disturbing results every time. The usual trend is:

  1. They give their staff all the boring, dirty work
  2. They scold in public and praise in private (if at all)
  3. They say, “I don’t need to be liked as long as work is getting done”
  4. People start quitting

I want to address #3 really quickly. “Being liked” and “getting things done” are not mutually exclusive. A good leader will get both done together, every time. If you can’t create a work environment where people are happy, you aren’t qualified to be a leader. Think about the last job where you constantly went above and beyond. Did you like your boss? I bet you did. I am very confident in the importance of having a good relationship with those you work with.

This post isn’t about watching your language. It’s about watching your attitude.

You need your staff more than they need you.

Social Payments: the Future is Unified

Physical credit cards will soon be a thing of the past. Is the rest of the US startup industry ready?

The next real-world cash-replacement could be powered by Facebook, Google, Apple, Square, Intuit, Paypal, or some other company hiding in the wings.  There’s a few obvious names in there, and then there’s a few left-field ones to some people. This post isn’t about how those left-field plays could happen. I simply wanted to explain how the landscape is changing.

There’s a convergence happening right now between social, payments, and e-commerce. Imagine this predictable future:

You buy some coffee at Starbucks. You take out your phone and swipe it at the terminal. Your [insert phone app name here] Bucks (from here forth known as: “Phone Bucks”) are deducted from your account. Your purchase is optionally posted on your Facebook/Twitter stream. You get highly-targeted Groupon-clone notice for a Starbucks coupon redeemable online immediately. You decide to buy it using your Phone-Bucks — no signing in, no additional authorizations — by clicking a button.

We’re talking about a future where your online wallet (today, known as Paypal, Facebook Credits, etc.) follows you into the real world and ties directly into your mobile phone. This represents a single unified wallet. And it makes sense. That’s the future. That’s where we are headed now. I’ve been watching this trend happen for the past few years, and it’s exciting to finally see some big players waking up to this reality. Which players are the closest to achieving this? In this order:

1. Facebook – Due to its large install base (virtually all smart phones) and an existing currency platform (Credits), they are best positioned to move into the real world. And they recently made a huge move indicating a desire to do exactly this (creating a subsidiary is the first step in buffering liabilities that come with real-world payments).
2. Square (or Intuit depending on how things play out) – They would solve this from the other direction: they have a stronger real-world presence, and moving into the digital space might be easier than vice-versa.
3. Google – They will approach this from the platform (Android) by opening it (Google Checkout 2.0) up to developers and creating an ecosystem. They also recently stole a key exec from Paypal, so you know they’re serious.

It’s my belief that any startup entering the e-commerce landscape right now needs to make sure they are thinking about this convergence. To get big valuations, I think a startup needs to not only understand these trends, but be the first to market in the new paradigm that will be coming (really soon!). This convergence will create an opportunity for new players to emerge and destroy existing leaders. All mobile startups around commerce, Groupon, Paypal, and even the advertising arm of Google are probably already adjusting to these trends. Is your startup?

Think about it.

Quick Command Line Method to Get Memcached Stats

I had to look for a while to figure this out:

echo stats | nc 127.0.0.1 11211

This assumes the memcached instance is running on a local instance with the standard port. This will output a bunch of statistics about the machine. The one to watch is “evictions,” which represent items getting overwritten before they naturally expired. This would indicate items being cached too long or the server running out of memory.

Wireshark and Stealing Data

I saw a pretty interesting video series today about sniffing network data. It really helps illustrate the importance of using HTTPS for any remotely-sensitive transactions. I’ve created a playlist you can find below:

Did Digg Miss the Boat Again?

So Digg released a new layout the other day, and I feel like another boat was missed. They made a big splash about this and it was covered in numerous places (for example, TCMashable). The new layout is noticeably faster to load, which is a huge plus. They tout that this new version emphasizes a “My news” approach to Digg, where they personalize the Digg site based on what you dugg in the past. In practice, unless you’re a power user, your news ends up spammed with news from one or two blogs you frequent.

I feel they are addressing their threats in the wrong order. Their website wasn’t perfect, but it wasn’t their weakness either. Consider:

  1. The Like button is dominating right now. Virtually every blog has it.
  2. Facebook is a HUGE news traffic driver. Way bigger than Digg.
  3. A lack of personalization was never Digg’s problem. Plenty of news sites on the web are popular with no personalization functionality.

First, Digg needs to figure out a way to make article submission “fair” for the little guy (read: long tail of users). They should have fixed the fundamentally flawed “democracy” where certain users effectively had 1000 votes. Personalization is an approach to the problem, but it ultimately doesn’t stop popular individuals from heavily influencing all of their followers’ feeds (and thus accumulate votes). The main complaint was that only power users could effectively get articles to the front page. Perhaps the algorithm should better incorporate Digg-to-viewer ratios or weight Diggs from non-followers as greater. The point is, until this is fixed, Digg will never fully engage its non-power users due to a lack of incentive. This represents the vast majority of its user base.

Second, Digg needs to up readership engagement. They should really look at their Digg button and see how it compares against the infamous Like button. It needs to be as brainless as the Like button. Clicking on “Digg This” should instantly submit the article to Digg. No windows; no dialogs. This is how the Like button works, and its pervasiveness shows how simplicity can trump everything else. Of course, doing this might mean changing how article submissions work on Digg — no problem: let power users check a setting where they ARE prompted for a custom title or description. The point is, the process needs to have as few places as possible where a user can change their mind about participating in the Digging process.

The website, I think, was never the problem.

PHP Tip: Always Put Constants on the Left in Boolean Comparisons

This was a standard I enforced at my last company:

Whenever you are doing a boolean check (such as an IF or WHILE), always place constants on the left side of the comparison.

The following is BAD:

// BAD
if($user == LOGGED_IN) {

The following is good:

// GOOD
if(LOGGED_IN == $user) {

Why is this such a big deal? Imagine the typo where you forget the second equals sign:

// Oops! This always evaluates to true!
if($user = LOGGED_IN) {

This sort of bug is fairly common. C# went as far as to say boolean conditions must always have boolean return values, thereby eliminating the possibility of accidental assignments. Well, since PHP can’t do that, this is the next best thing. Notice how this convention will save your butt:

// Fatal error. Bug caught immediately.
if(LOGGED_IN = $user) {

Think about it. :)

Is Your Blog Not Receiving Pingbacks? I Fixed Mine.

I recently noticed that my blog was no longer registering pingbacks (the automatic in-comment notification that occurs when somebody else blogs about your post). I like these because they help me understand which of my articles are gaining traction.

My symptoms

  • My other blogs hosted on the same server seem to be pinging fine; however, those have far less posts and plugins
  • I am able to send pingbacks, apparently
  • But ping backs TO my content were dropped (even when I am self-pinging)

The fix

I figured the issue was somehow related to my recent upgrades of WordPress. After scouring the web, I found that the issue was due to a poorly designed timeout setting in WordPress.

  1. Open wp-includes/cron.php in your blog folder
  2. Go to the line that starts with: wp_remote_post( in the spawn_cron function
  3. Change ‘timeout’ => 0.01 to ‘timeout’ => 1 (or any other far more reasonable value)

This will fix blogs that are plagued by this bug.

Autocast Variables Whitepaper: What I Want to See in PHP 6

Introduction to Autocasting

This is a white paper on a feature that does not exist in PHP. It is an idea I came up with and hashed out here in this article.

Autocast variables. An autocast variable is like a container for data — everything going into an autocast variable type will always be converted to the current type of that variable. As in, if you assign a string into an integer variable, the variable will become the integer representation of the string (via implicit and immediate typecasting).

The idea is a hybrid of limited type safety where only some variables are type safe and operator overloading of the equals sign on native and complex datatypes. To help explain the idea: it would act almost like somebody following around your cursor and typing (int), (string), etc. all over your code before variable assignments EXCEPT that it can also done with non-native datatypes like classes.

The goal is to allow a developer to be – when desired – 100% certain they are working with a specific data type.

To declare a variable as an autocast, simply place a colon after the dollar sign in a variable name. Then, everything assigned to that variable is now automatically typecast to the datatype of the variable. For example

// This variable is now a container for integers
$:orderTotal = 0;
// assign a float value
$:orderTotal = 1.01;
// outputs 1; 1.01 was typecast to an integer
echo $:orderTotal;

NOTE: Why the new syntax? I toyed with the idea of an autocast keyword, but the paradigm broke down when you started assigning objects. The problem is that objects are pass-by-reference. This meant a programmer could change the datatype of an autocast variable by altering its reference. The other problem was that by not having a visual marker, it would make things very confusing  since one could never tell if they were working with an autocast until runtime. Lastly, why the dollar-colon? I would have prefered straight colon, but most of the good single-character syntax would conflict with existing PHP systems (# is a comment, : is used in ternary operators, % is modulus, ^ is a bitwise operator, etc.). A dollar sign is universally understood as a variable, so I thought the next best thing was to alter the variable in a way that today’s PHP would recognize as invalid (and thus introducing the syntax would not conflict with legacy code).

The concept is simple, but gets more complicated as you introduce objects, magic methods, and method signatures into the equation. Don’t worry, I’ve thought about all of those scenarios. Key summary of benefits:

  • New coding paradigms allow for simpler interaction between different data types (see first Practical Example)
  • Refactoring can be done in a way never before possible (see second Practical Example)
  • Code is now more “reliable” because unintended data types aren’t used (such as during boolean checks)
  • Many fatal errors can now be avoided
  • Potential use in the realm of dependency injection
  • Possibilities for true function overloading since expected datatypes are known (although, this is possible today, to be honest)

Read on to learn more!

Autocasting: Defined

You can skip this section and review it later. Note that the rest of this article will review the specifics of autocasting. Here are the basic rules:

  1. Declaration: Autocast variables are set at declaration, but the actual data type is optional and is inferred during the first variable assignment
  2. Declaration: Once an autocast variable is explicitly cast or declared as a certain data type, it can no longer change data types
  3. Usage: The colon is part of the variable name. A variable with the same name without the colon is a different variable.
  4. Null: Null always counts as a different datatype and assigning it will always trigger autocasting behavior
  5. Arrays: For arrays, non-array values are inserted as the 0th index of the array and all other values are truncated
  6. Classes:For uninitialized objects, the constructor is automatically called prior to autocasting behavior (no arguments)
  7. Classes:For initialized objects, if no autocast magic method is defined, the assigned value is dropped and a warning is thrown
  8. Magic Method:__autocast is only called when a different datatype is being assigned
  9. Scope: Autocast behavior is linked to the declared variable, NOT its contents — think of it as a container. Assigning an autocast variable into a non-autocast variable creates a copy. This MUST be so because any other implementation would allow a developer to change the contents of the autocast variable by using a reference.

Forced Native Datatype Conversions

PHP would work exactly the same as before except that certain variables could be declared as autocast. When a variable is declared as a specific type, all data going into it is automatically cast to that type. For example:

$:counter = 0; // OK, this is now an INTEGER
$:counter = 1.01; // attempting to assign a float
echo $:counter; // outputs 1, not 1.01

Another example:

$:orderTotal = 0.00; // OK, this is now a FLOATING POINT NUMBER
$:orderTotal = "0.00"; // THIS IS A STRING BEING ASSIGNED
print_r($:orderTotal); // outputs 0.00 (as a float, not a string)

Where did I get this idea? Actionscript 2, when I played with it years ago. In AS2, they had just introduced optional compile-time type checking. The goal was to allow developers to optionally set a variable’s type to trigger compile errors. I have been thinking about this solution for literally years. I didn’t like the notion of breaking existing PHP code and introduce strong typing. Besides, since PHP isn’t compiled, doing “compile time type checking” is fruitless. Thus, the solution is to encourage more thoughtful OOP by allowing developers to “declare” variable types.

What happens if you assign an autocast into a regular variable?

$:counter = 0; // OK, this is now an INTEGER
$counter = $:counter; // create a new counter variable
$counter = 1.01; // attempting to assign a float
$:counter = 1.01; // attempting to assign a float
echo $counter; // outputs 1.01
echo $:counter; // outputs 1

Answer: The assignment from an autocast to a regular variable makes a copy of the variable sans the autocast behavior.

Converting Things to Objects with __autocast

The idea does not stop at native types. I want to take this a step further and introduce magic methods that specifically deal with the autocasting behavior!

/**
 * This base64encodes data
 */
Class Borg {
    public $:slaves = "";
    /*
     * This is called during assignments of the wrong types
     *
     * @param $type the class name or native data type of the assigned value
     * @param $assignment the variable being assigned into the autocast
     */
    function __autocast($type, $assignment) {
        switch($type) {
            // note that I want to use namespaces here, but not everybody
            // has seen those yet in 5.3 and I don't want to distract from
            // the example... I made these constants up.
            case PHP_CONSTANTS_DATATYPE_STRING:
            case PHP_CONSTANTS_DATATYPE_INTEGER:
            case PHP_CONSTANTS_DATATYPE_DOUBLE:
            case PHP_CONSTANTS_DATATYPE_BOOLEAN:
                // for these native data types, just encode
                $this->:slaves = base64_encode($assignment);
                break;
            default:
                // non native data type! Borg defenses activate!
                $this->:slaves = base64_encode(serialize($assignment));
               break;
        }
    }
}

The following example assigns a string into the object, yet in the next line, the object remains intact — and taken over by the Borg!

// the variable is currently uninitialized, but is declared as type autocast Borg
Borg $:borg; // autocast variables can be declared differently
$:borg = $_POST['slave_names']; // ASSIGNING a string to the variable
echo $:borg->:slaves; // this works!

The following example shows how objects can also be converted using the magic method:

$:borg = new Borg; // the variable is now Borg
$:borg = new EnterpriseFodder(); // Did the $:borg become EnterpriseFodder?
// $:borg is still of type Borg and this outputs serialized(EnterpriseFodder)
echo $:borg->:slaves;

Before we get too far, I also want to clarify that autocast objects CAN be overwritten so long as the assignment datatype is the same or of a derived child class.

$:borg = new Borg; // the variable is now Borg
$:borg->:slaves = 'I CHANGED IT'; // changes registered correctly
$:borg = new Borg(); // Did the $:borg become EnterpriseFodder?
// empty because we overwrote the old Borg instance
echo $:borg->:slaves;

Because of the dollar-colon marker, autocast variables won’t introduce “invisible bugs.” Callers will be very aware that they are dealing with autocast variables.

Converting Objects to Other Types with __castTo

Another feature that should be possible is for for objects to define how they are cast into other datatypes. For example, imagine the following code:

$status = new Status();
Boolean $:isReady;
// $:isReady = true
$:isReady = $status;

The problem with this situation is that I have no control in how the Status class is converted into a Boolean. In this case, it would probably just convert to true. Wouldn’t it be nice if I had control over that?

class Status {
    $status = 0;
    function __castTo($type) {
        // The below uses namespaces, which is my preferred way PHP
        // would do things. I made these up.
        // We are checking if the attempt is to cast to a boolean
        if(\PHP\CONSTANTS\DATATYPE::BOOLEAN == $type) {
            // return 0 to boolean attempts
            return $this->status;
        }
        else {
            // otherwise just settle with default behavior
            return $this;
        }
    }
}

$status = new Status();
$:isReady = true; // boolean

// $:isReady = 0 = false
$:isReady = $status;

// $check = non-empty object = 1
$check = (int) $status;
echo (bool) $check; // 1 = true

The return value of __castTo becomes the value that is represented to the casting operatoin. Thus in the example above, $:isReady would only see the value of $this->status (which is 0) because $:isReady wants a Boolean. For any other data type conversion, Status would return $this (itself). This is why the second cast operation behaves totally differently and ends up equaling 1. So in terms of order of operations, __castTo is called before any attempts at casting an object, giving the object a chance to define how it should be converted.

I did want to state that the __castTo concept is 100% possible without autocast. I think it might be a cool feature all on its own that just so happened to work very well with the autocast idea.

Global autocast magic function

Just like the object magic method __autocast, there should also be a global __autocast function. This function would allow a developer to override native autocast behavior. Note that if the __autocast magic function fails to cast a variable, then the native behavior should be triggered. Returning false will suppress the native assignment (so you must make it!):

function __autocast($assignee, $assigneeType, $assigner, $assignerType) {
    // for those of you that HATE autocasting, you can make it throw exceptions
    if($assigneeType != 'Borg') {
        throw new Exception('Autocast behavior was triggered');
        // alternatively returning false here would prevent an assignment
        // from happening
    }
    // return true so that regular autocast behavior is retained
    return true;
}

Function Argument Autocasting to Enhance Type Hinting

Autocasting functionality should be used to augment function method declarations as well:

function sortData(string $:data) {

Now your code that expects a string doesn’t need to check if the data is actually a string (which is just spaghetti code anyway). Why would you want to ensure a string? How many times have you tried to echo a variable and it printed “Array” because an array snuck in and replaced your variable?

Here’s another example of function argument autocasting:

function myXMLParsingFunction(XmlReader $:parser, $data) {

What’s this do? The idea is that if you pass something in I’m not expecting, the regular autocasting behavior is triggered right there. Now I can write my method’s code worry about how to parse that data rather than if the parser is actually an instance of XmlReader. Key point: if the caller passes in a autocast variable into an autocast argument (and the types match up), all regular pass-by-ref/value logic is used. If there is a mismatch, a copy is made instead.

Dynamic Autocasting

Inline autocasting should also be possible for variables that aren’t necessarily autocast. This functionality is important where you are method chaining (prevents fatal errors). For example:

$culprit = ((autocast Borg) getBorg())->toString();

Behind the scenes, if getBorg() returns something that is not a Borg, an in-memory Borg conversion takes place. The result is then used to make the toString() call. If we took the same example, but took away the chaining, we would see another side effect of autocasting:

$borg = (autocast Borg) getBorg();
$culprit = $borg->toString();

Since autocast behavior is associated to the declared variable and not the contents, autocast functionality would NOT be inherited by the $borg variable. This way, if something crazy happens inside the getBorg() method that we aren’t expecting, we can still be sure that we get back a datatype that we expect. If the goal is to always return Borg types from getBorg(), the author could prepend the dynamic autocast before the return call:

function autocast Borg getBorg() {
    return (autocast Borg) "Enterprise Fodder";
}

Note that in the event the $borg variable is autocast to another type (i.e., if $borg is declared as autocast to a string), the Borg instance would be converted again to the type $borg wants (a string). Note that each time an autocast is assigned into a non-autocast variable, a copy is made. Thus the best thing to do in the second example  would be to declare $borg as an autocast ($:borg).

Autocast Return Types

The alternate approach to the dynamic autocasting problem on methods is to allow autocast return types in the function declarations. The idea is that in the declaration, the method author can force a dynamic autocast on all return values from the current function. This way, if a function has many exit points, the return type can be guaranteed to be consistent.

function autocast Borg getBorg() {
    return "Enterprise Fodder";
}

In this example, a Borg instance is passed back in an autocast container. If the caller is assigning the return value to an autocast variable, it is then passed-by-reference. If the caller is using a regular variable, a copy is assigned in. This way, the functionality can be introduced without breaking legacy code.

Practical Example: Models

So what’s a practical use for this aside from lessening code and cleaning up mundane “do I have what I’m expecting” code? Here’s a very simple example:

class Model {
    public $:amount = 0.00; // float!
    public $:name = ""; // string!
    public $:id = 0; // integer!
    function __autocast($type, $assignment) {
        // we are checking for if an array was assigned into this class
        if(\PHP\CONSTANTS\DATATYPE::ARRAY == $type) {
            $this->:amount = $assignment['amount'];
            $this->:name = $assignment['name'];
            $this->:id = $assignment['id'];
        }
        else {
            trigger_error('Error!Only autocasts arrays.', E_USER_WARNING);
        }
    }
}

What’s the above accomplish? Check out the sexy things I can do:

$row = array('amount' => '0.00', 'name' => 'Michi', 'id' => '1');
$:model = new Model;
$:model = $row;
echo $:model->:amount; // outputs a FLOAT (not a string) value: 0.00

The following accomplished the EXACT SAME THING because of the __autocast magic method.

$row = array('amount' => '0.00', 'name' => 'Michi', 'id' => '1');
$:model = $row;
echo $:model->:amount; // outputs a FLOAT (not a string) value: 0.00

Not only that, but we also squashed the unintended non-zero bug on the amount column! It means the future PHP models that represent database data will finally have properties that mirror the datatypes of the database, rather than just being the string representation.

Practical Example: Refactoring for Code Scaling

PHP’s greatest weakness is its ability to “scale” the code base. As the code gets larger and poor coding practices are used, it becomes very difficult to go back and fix things without completely gutting everything (see my article about this). Autocasting fixes this.

For example, nobody thinks twice when they see code like this:

$someObject->processQuery($db, $query); // drives Michi crazy

How do you know $query is a string, let alone a query? How do you know $db is an object? Do realize that if $db isn’t an object, PHP quits with a fatal error saying some method can’t be called on a non-object? This is a serious problem! And yet it’s just business as usual in the PHP world. Type hinting is NOT the full solution here, and it is worthless when you consider in refactoring. Type hinting ultimately triggers a fatal error that the developer is powerless to stop during run-time. Yes, type hinting lets you control what your function deals with, but the answer is NOT to take your toys and go home when you get something you didn’t intend. Let’s illustrate; imagine this code:

function processData($data) { // implied string (bad!)

And the author later realizes, “Wait, I want to make $data a class so I can do more to it.” So the author changes it:

function processData(Data $data) {
    $data->process();
}

But the problem is that now if somebody passes in a string/array/integer/etc., they get a FATAL ERROR! So then the function caller ends up doing crazy spaghetti that looks like this (actually 90% of the time, the caller won’t do this until after the bug hits production and a fatal error happens :( ):

    if(!($data instanceOf Data)) {
        $dataObject = new Data();
        $dataObject->setData($data); // ugh, exposed public setter method needed!
        $data = $dataObject;
    }
    processData($data);

}

That’s no good! In virtually every language, this kind of refactor is not possible without causing serious problems to the outside developers. In statically typed languages, the compiler catches these types of things, and then everybody does a mass re-write. But in dynamic languages, you can’t find these issues until you run the code. So how does autocasting solve the problem?

function processData(Data $:data) {
    $:data->process();
}
// leave the complicated stuff to the __autocast magic method!
class Data {
    private $:payload = "";
    function __autocast($type, $assignment) {
        // for now, we only worry about strings, but in the future we could do
        // a check for LegacyData types and convert those too!
        $this->:payload = $assignment;
    }
    function getData() {
        return $this->:payload;
    }
    function process() {
        return "data: " . base64_encode($this->getData());
    }
}

So if a caller passes in a string into processData, it gets assigned into :payload, and the code keeps on working. One thing that’s neat is that we don’t need to expose a public setter method just to make things backwards compatible. Additionally, if we want to do any special processing or data conversions, we can do that in the magic method. Lastly, if we upgrade things again later, we can create a new logic fork inside the autocast magic method to help convert the legacy object type to the new one.

// Oh no! Changed the argument again!!
function processData(XmlBLob $:data) {
    $:data->process();
}

class XmlBlob {
    private $:payload = "";
    function __autocast($type, $assignment) {
        // If it's of type Data, convert it over
        // otherwise, roll back to the uber legacy behavior
        // I'd really love it if this sort of comparison is legal
        if(Data == $type) {
            // convert the data to the format we want
            // we could use a magic method here too if
            // $this->:payload was a class instead of a native
            $this->:payload = self::toXML($assignment->getData());
        }
        else {
            // note this is autocast to string
            $this->:payload = $assignment;
        }
    }
    static function toXML(string $:data) {
        // do some XML conversion magic here
        return $:data;
    }
    function process() {
        return "data: " . base64_encode($this->:payload);
    }
}

In short, autocasting allows library writers to hide complexity from implementing developers. And, as a super-added bonus, it makes changing/deprecating method signatures actually possible!

Implications

There’s a number of substantial implications with this feature. Summary of points:

  • Might make things messier since autocasting is “automagical”
  • IDEs can do even cooler things since types can be known
  • True function overloading is within reach
  • Native dependency injection is also within reach
  • Possible speed improvements, but possible speed issues

First of all, this could make PHP even messier than before. But that’s the case for any new feature that is poorly used. But I do admit that introducing “magic” and “shortcuts” can eventually lead to code that looks like the nightmare we all know as Perl (zing!). That said, I see overwhelmingly cool things that become possible with this. Most importantly, PHP becomes “type safer.” Think about it: today, I will bet you good money that almost every code base has a function where the method author wrote code checking if the caller passed the right data types in — or vice versa. The reality is that even in a loosely typed language, datatypes are important. So while some portion of the population might use this to write some really crazy Perl-like code, I think the benefits outweigh the costs. These changes make it easier for library authors to maintain and understand their code (which I believe is a more important battle to win). Autocasting allows authors to put up a moat around their libraries/classes where they can absolutely control the types of variables they are dealing with — without forcing fatal errors everywhere.

It also means IDEs can do even more error checking and type hinting. Imagine if the IDE warned you when you setup a situation that, without autocast, would have triggered a fatal error! It means that when a caller tries to use the return value of a declared autocast function return type, the IDE can warn the developer.

This feature might also open the door to true polymorphic PHP. For example, a class could have two constructors: one with an autocast string argument and one with a generic argument. At run time, using some simple rules, PHP might use different versions of the same function name depending on the variable types. Voila! If a method signature can state what TYPES of arguments it wants, and we can explicitly state what we are passing in, isn’t that the first step in setting up true function overloading? While this is beyond the scope of my idea, I thought it was an interesting secondary benefit that somebody smarter than I could explore.

You might notice that autocasting behaves a lot like typical dependency injection patterns. Since constructors are automatically called for uninitialized variables, it would be possible to simulate dependency injection in functions very easily (a boon this is for testing!). In earlier examples, I showed you cases where a $parser or $db variable was passed in. Imagine if in those examples, such a variable was passed in as NULL (not provided). Now, PHP would automatically construct them from scratch, leaving the function implementer free from the burden of constructing the object. If you think about it, this puts us within striking distance of some kind of dependency injection in PHP. Then, somebody smarter than I can suggest a static __inject() magic method that gets called during automatic object construction… :)

Finally, while I’m not a C programmer, I wanted to take a moment to say that it’s possible that autocasting could provide memory/speed optimizations for PHP since certain variable memory spaces wouldn’t constantly change. Again, I’m not a C programmer and I don’t know how PHP’s memory allocation is designed, but I thought I’d throw that out there. On the same note, all of the casting logic could prove to be quite taxing. Thus, it could negate any perceived performance gains.

Spread the Idea

This is something I’ve been internalizing for no less than half a decade. I would genuinely love to see it in a future version of PHP, but I’m too busy to evangelize the idea. I’ve also never met somebody else who fully understood my idea. I’m finally releasing the idea into the wild and hoping for the best. It’ll probably sit in the Internet Idea Junk Yard. :) Please feel free to share this idea with your peers and pass it along to other PHP developres.