HipHop & Commercial Implications
So the blogs are a twitter and the tubes are getting clogged with all the chat about HioHop, well at least in the PHP Community. The buzz is really not bad considering that the HipHop translator hasn't even been published yet (at least at the time of writing it has not been put on github) and there really are a metric ton of posts about what it is and what it could mean to the community or not, but one of the things I've yet to see addressed are the business implications of HipHop.
So, here I am, a PHP developer who has never touched HipHop, what am I doing writing about the business implications? Well that's actually fairly simple, like every other developer in the known world, I have a home business too (at least I'm trying to have one) and one of the things I've been playing with is the idea of creating a static package to sell has been an interesting one. In PHP if you sell a package or library you generally deliver either a. a file structure exposing every line of PHP written or b. a mess of files that have been "obfuscated" or locked through a tool like Zend_Encoder or Ion Cube. The thing is if you're wanting to sell something as closed source, currently it's not really possible to compile and send a binary form to the end customer, well HipHop will be changing that, in ways that we haven't even really fully thought about or discussed, being able to deliver an executable with an exposed api (via services at the very least) rather excites me.
Beyond the excitement to me, this also means more to the community, being able to attract businesses who want to sell a product will only improve the PHP support in HipHop and drive training in the language, especially once HipHop supports Windows. One of the other things I've been seeing lately is talk about getting HipHop to support running through a fastcgi interface, if that's the case then we could easily run via IIS alongside of ASP.NET, it'll be interesting to see what happens in the long-term though because I'm sure there are other implications I haven't even thought about yet.
Code Readability Part 2, Code Structure
After reading some of the comments from
Part 1 I've really been motivated to continue this series (I'm sorry
for being late to approve comments.) While writing comments can
really speak to the frame of mind, and the intent, at the time of
writing it can only go so far to ensure that the reader and/or
maintainer of your code can clearly read and understand the
creativity that you spent so long to write. I've had the pleasure of
maintaining a legacy application developed by people who were past
deadline the second they had their assignment handed to them in the
past and it can get really interesting rather quickly when you see
how sloppy you can get when you are in such a hurry. Here are some
guidelines I've given myself to ensure that the structure is correct
at the end of the day.
-
Break large files apart into
smaller, more digestible pieces. This has become rather more
important these days, I have sifted through a 20,000 line source
file in the past, and there are some instances where grep just can't
help. Object Oriented code makes this significantly easier as you
can easily write a small object that you can interact with and
separate it from your business logic. While I'm sure I could easily
come up with a simple example of what I'm talking about I think it
would take up too much space here. Suffice it to say that generally
you should try to cut file length at about 1,000 lines, it makes
searching a file a little more manageable and consuming said file
more efficient for future developers as our brains like things
conveniently cut down to size. -
Using naming conventions is an
integral part of making code easier to read and write, for example,
I ran into an error the other day where I wasn't thinking and called
the class Transferobject, I was able to quickly catch that error
upon reviewing the source code as we use a CamelCaps convention for
naming our classes. There is reason for this madness, we use
autoloaders (not necessarily the best idea for scalability but it
works for our purposes) as far as the Unix file system is concerned
capitalize and lowercase letters differ significantly so calling
TransferObject differs from transferObject, transferobject, and
Transferobject. A standard will make sure that you can look at
variable, class, interface, function, etc names and see where an
error might be. -
While we are on Variable, Class,
Function, etc names, make sure your name, at least loosely,
describes what it contains. I've seen countless references in a
past coworkers code that called variables as $array, $arrayer,
$arrayor, $a, $b, $c etc. The reason why you want to describe what
you're containing should be obvious but let me expand just a bit.
Let's say that I'm interacting with a function that was predefined
and I'm trying to understand what input it takes<?php function someFunction($a,$b) { … } ?>is not going to yield as
much information to me as perhaps<?php function someFunction($startDate, $endDate) { … } ?>or
<?php function someFunction(Date $startDate, Date $endDate) { … } ?>would
be. In the first function all I can see is that this function takes
two arguments, much reading and digesting will occur now (provided
the writer didn't strongly comment his function which even then I
have to go read the DocBlocks.) The second example is a bit more
intuitive, now I know I'm working with a date range that starts with
the first argument and ends with the second; however, I don't know
that I'm dealing with an Object (in this case PEAR Date) which is
what example 3 conveys, it type hints the arguments and as such also
gives us a bit of error handling. -
Structure your directories, I'm
sure this one will bring questions of “How do directories interact
with code readability” well that's an easy one to answer, if you
separate out your View, Models, Controllers, Base Libraries,
Templates, etc it will be a lot easier to find the specific thing
you're looking for. MVC, MVP, and N-Tier does make this a lot easier
as it gives us better specifications of how to lay out the
directories and how to effectively use them. -
Structure your source, for each
level of execution you should indent a uniform amount of characters
(personally I go with a tab for every level.) It can be very painful
to try to read<?php if (somecondition) { if (someothercondition) if (lastcondition) { ... } else { ... } } elseif (someothercondition2) { } else { ... } } else { } ?>rather than
<?php if (somecondition) { if (someothercondition) { if (lastcondition) { ... } else { ... } } elseif (someothercondition2) { ... } else { ... } } else { ... } ?>incidentally there is a error in the first execution block, see if you can find it.
-
While on the subject on
conditional statements, I've seen Error Checking and Input
Validation as a pet peeve for a long time. There are two major
things I've noticed, most developers I've worked with either
completely skip Input Validation and Error Checking or write these
ugly and long conditonals:<?php /** * Recursive version of in_array * * @param string $needle * @param array $haystack * @param bool $strict * @return bool */ function in_rarray($needle, $haystack, $strict = false) { //check to ensure that passed haystack is an array for recursion if (is_array ( $haystack )) { $array = new RecursiveIteratorIterator ( new RecursiveArrayIterator ( $haystack ) ); foreach ( $array as $element ) { //if strict mode enabled use the strict comparison operate if ($strict == true) { if ($element === $needle) { return true; } } else { if ($element == $needle) { return true; } } } return false; } else { throw new exception ( 'Haystack is not an array' ); } } ?>Where it could be written as:
<?php /** * Recursive version of in_array * * @param string $needle * @param array $haystack * @param bool $strict * @return bool */ function in_rarray($needle, $haystack, $strict = false) { //check to ensure that passed haystack is an array for recursion if (!is_array($haystack)) { throw new exception('Haystack is not an array'); }$array = new RecursiveIteratorIterator ( new RecursiveArrayIterator ( $haystack ) ); foreach ( $array as $element ) { //if strict mode enabled use the strict comparison operate if ($strict == true) { if ($element === $needle) { return true; } } else { if ($element == $needle) { return true; } } } return false; } ?>The
lesson to be learned here, write your flow of execution in such a
way that it stops right away during a check should it fail rather
than basing execution on a condition and adding an unnecessary level
of complexity.
That concludes part 2 of my
mini-series, in part 3 I will be discussing how to build decent user
requirements and API Documentation. I hope everyone is having as
much fun reading this as I am writing it. I hope to do better with
comments in the near future and will be looking for a way to handle
spam blocking without having to validate everyones comments.