Bitcetera TechBlog http://www.bitcetera.com/en/rss/ en-us 40 News about Bitcetera products, services and the technologies used. Eagerness <p>Don&#8217;t worry, this is not about greedy bankers, megalomaniac corporations nor currupt politicians &#8211; although I would love to have a simple fix for these at hand, too.</p> <h2>Simple Example</h2> <p>With eagerness I mean a simple yet important and too often unknown concept of regular expressions. Take this Ruby example, it would yield the same results in any other language such as JavaScript or even <span class="caps">PHP</span>:</p> <pre> "Hello Ruby friend".sub(/^(.*)e/, 'X') # =&gt; "Xnd" "Hello Ruby friend".sub(/^(.*?)e/, 'X') # =&gt; "Xllo Ruby friend" </pre> <p>By default, the <code>*</code> quantifier is eager which means it will eat its way though the string until it hits the <strong>last</strong> subsequent <code>e</code>. If you want it to go no further than the <strong>first</strong> subsequent <code>e</code>, you have to put it in non-eager mode &#8211; and the question mark behind the <code>*</code> quantifier does just that.</p> <p>The eagerness questionmark works behind any quantifier, but for obvious reasons makes sense only behind <code>*</code>, <code>+</code> and <code>{n,m}</code>.</p> <p>&#8220;Fine, dude, but can we use this eagerness thing for anything real?&#8221;</p> <h2>Real World Examples</h2> <p>Yes, we can! If you are using Cucumber, chances are you find a step definition similar to the following in your code:</p> <pre>/^I am using rvm "([^\"]*)" with gemset "(.*)"$/</pre> <p>This works, but the &#8220;anything but apostrophe&#8221; construct is a little cumbersome &#8211; and utterly avoidable:</p> <pre>/^I am using rvm "(.*?)" with gemset "(.*?)"$/</pre> <p>As you see, this is both more readable as well as more consistent. (Okay, the question mark in the second group is not really necessary, but it doesn&#8217;t hurt and thing&#8217;s won&#8217;t break if you ever decide to add a third group.)</p> <p>Bottom line: Eagerness may make the difference between a cumbersome and an elegant regular expression, at least if you belong to those who don&#8217;t think of the latter as a paradox. And as we&#8217;re all eager to learn, you might want to add eagerness to your regex toolbox.</p> <p>If you liked this tip, you might want to take a look at the <a href="/en/techblog/2008/04/01/regex-in-a-nutshell">Regex in a Nutshell Cheat Sheet</a> as well.</p> Mon, 08 Mar 2010 10:35:00 GMT http://www.bitcetera.com/en/techblog/2010/03/08/eagerness/ http://www.bitcetera.com/en/techblog/2010/03/08/eagerness/ From ZenTest to autotest <p>Many people install the <a href="http://www.zenspider.com/ZSS/Products/ZenTest/index.html">ZenTest suite</a> only to get the autotest tool and thus carry around quite a bit of overhead. Yet, not any longer! Michael Grosser has released the <a href="http://github.com/grosser/autotest">autotest</a> gem which contains an improved fork of only the autotest tool. (Should you ever need the full functionality of ZenTest, you can always install the <a href="http://github.com/grosser/zentest">zentest</a> gem along with it.)</p> <p>Following the &#8220;only happy developers do proper testing&#8221; mantra, the popular <a href="/en/products/autotest-growl">autotest-growl</a> and <a href="/en/products/autotest-fsevent">autotest-fsevent</a> gems as of version 0.2.0 released today no longer depend on ZenTest but on Michael&#8217;s autotest. Other new feature include support for more platforms and icon sets, see the <span class="caps">CHANGELOG</span> for the details.</p> <p>If you are upgrading from versions prior to 0.2.0, you should uninstall ZenTest or things might show funky behaviour. Please refer to the <span class="caps">README</span> for more on this.</p> Wed, 03 Feb 2010 16:05:18 GMT http://www.bitcetera.com/en/techblog/2010/02/03/from-zentest-to-autotest/ http://www.bitcetera.com/en/techblog/2010/02/03/from-zentest-to-autotest/ Inconsolata XL Font <h2>Sound Familiar?</h2> <p>I&#8217;m sure you&#8217;ve heard this rap before: &#8220;You&#8217;re sleeping a third of your entire life, so you&#8217;d better get a really nice mattress.&#8221; However beaten that phrase may be, there is some truth in it. And guess what, as a software developer you might spend another nice chunk of your life in front of a code editor and <tt>Courier</tt> or <tt>Monaco</tt> just aren&#8217;t as good as it gets.</p> <h2>Inconsolata</h2> <p>Enter <tt>Inconsolata</tt> created by <a href="http://www.levien.com">Raph Levien</a>. It&#8217;s a monospaced font that reads exceptionally well even at small sizes and is equally suited for use with a code editor, the terminal or for reading non-<span class="caps">HTML</span> mails. However, Raph hasn&#8217;t added bold font weight yet. This is not usually a problem as many applications such as <a href="http://macromates.com">TextMate</a> or the terminal render a fake bold if needed. <a href="/page_attachments/0000/0024/sample.png">Here&#8217;s a sample</a>.</p> <h2>Oops, RubyMine</h2> <p><a href="http://www.jetbrains.com/ruby">RubyMine</a> on the other hand doesn&#8217;t and therefore I&#8217;ve derived a slightly bigger <tt>Inconsolata XL</tt> font which includes a rough bold variant. Just download, unpack and then move the two font files into your <tt>~/Library/Fonts</tt>.</p> <h2>Downloads</h2> <ul> <li><a href="http://www.levien.com/type/myfonts/inconsolata.html">Inconsolata</a></li> <li><a href="/page_attachments/0000/0023/InconsolataXL.zip">Inconsolata XL</a></li> </ul> Fri, 09 Oct 2009 16:32:23 GMT http://www.bitcetera.com/en/techblog/2009/10/09/inconsolata-xl-font/ http://www.bitcetera.com/en/techblog/2009/10/09/inconsolata-xl-font/ Batch Update TextMate Bundles <p>Most bundles for <a href="http://macromates.com">TextMate</a> are served by some form of version control system. Macromates uses Subversion for it&#8217;s official bundle repository whereas the Ruby herd relies more on Git.</p> <p>Some bundles contain an update menu item and there are a few attempts out there to manage bundles altogether. However, with just a little console-fu, you can update all bundles at once:</p> <pre>find ~/"Library/Application Support/TextMate/Pristine Copy/Bundles" -name .git -execdir git pull --quiet \; find ~/"Library/Application Support/TextMate/Pristine Copy/Bundles" -maxdepth 2 -name .svn -execdir svn up --quiet \;</pre> <p>To mimick the missing &#8220;auto-update all TextMate bundles&#8221; functionality, just put these lines in a cronjob.</p> Tue, 08 Sep 2009 11:10:57 GMT http://www.bitcetera.com/en/techblog/2009/09/08/batch-update-textmate-bundles/ http://www.bitcetera.com/en/techblog/2009/09/08/batch-update-textmate-bundles/ Mock it Real Good <p>A few weeks ago I came across a blog post mentioning <a href="http://www.balsamiq.com/products/mockups">Balsamiq Mockups</a>, an application to put together screen sketches, and as always my first thought was: &#8220;Do I really need a toy like that?&#8221; Now, several sketches and one presentation later, the answer is more &#8220;oh, yes&#8221; than I anticipated at first.</p> <h2>Paper and Pencil</h2> <p>Like many, I have outlined screens with some paper and a pencil until now. And I won&#8217;t mothball that pencil quite yet because it still has one huge advantage: It works in my favorite environment: on the beach. However, things tend to get messy as sketches become more numerous, complex and mature.</p> <p>Therefore after the initial brainstorming, it&#8217;s a good idea to fire up an editor of sorts and morph the sketches into a state worthy of presentation. This is where <a href="http://www.balsamiq.com/products/mockups">Balsamiq Mockups</a> comes into play.</p> <p>It&#8217;s a graphics editor specially designed for screen sketches and comes with a set of UI elements which represent most of what you will need for an average (web) application. Additional UI elements can be downloaded and future versions might bring a larger UI library to start with. Once placed these UI elements can be tweaked, however, the variations are limited to what makes sense for that specific element. This streamlines the number of menus and buttons compared to more generic tools such as OmniGraffle or Adobe Illustrator and thus speeds up the sketching a big deal.</p> <h2>No False Hopes</h2> <p>Mock UI elements are not perfectly styled and don&#8217;t carry the look of any specific environment but resemble more what the good old pencil would have produced. This intentional lack of perfection makes it utterly useless to be pedantic and the resulting sketches don&#8217;t pretend to be anywhere close to a final product yet.</p> <p>The impact of this last sentence only becomes clear once you present the sketches to non-techies such as that notorious guy from marketing or a potential user like I did a few days ago: You run next to zero risk of raising false hopes such as &#8220;wow, look at that beautiful screen, these guys are almost done with my app&#8221;. And at the same time you make it crystal clear that the sketches are just that &#8211; and most likely will see adjustments during implementation.</p> <h2>Need Some <span class="caps">AIR</span></h2> <p>Only downside so far: <a href="http://www.balsamiq.com/products/mockups">Balsamiq Mockups</a> runs on <a href="http://www.adobe.com/products/air"><span class="caps">AIR</span></a> which means you have to install Adobe stuff on your computer. This may hurt, after all, it felt so good when my Mac became an Adobe free zone many years ago. (Not entirely true after Adobe acquired Macromedia, but that&#8217;s another story.) However, after using the online trial for a while, the fun working with it outweighed my adobephobia. And <span class="caps">AIR</span> runs stable and does a pretty good job mimicking a native Mac OS X application.</p> <p>The best way to testdrive <a href="http://www.balsamiq.com/products/mockups">Balsamiq Mockups</a> is the <a href="http://www.balsamiq.com/demos/mockups/Mockups.html">free online version</a> which also comes in handy if you want to send screen outlines to someone who doesn&#8217;t own the software and still would like to fiddle about your sketches. The <a href="http://www.balsamiq.com/products/mockups/desktop#download">downloadable <span class="caps">AIR</span> application</a> runs on all major platforms.</p> Tue, 11 Aug 2009 21:25:37 GMT http://www.bitcetera.com/en/techblog/2009/08/11/mock-it-real-good/ http://www.bitcetera.com/en/techblog/2009/08/11/mock-it-real-good/ Heredoc with Indent in Ruby <p>Heredocs come in handy when you have to deal with larger multi-line strings in the source code itself. However, it usually breaks the indents:</p> <pre> class Poem def initialize @text = &lt;&lt;END "Faith" is a fine invention When Gentlemen can see But Microscopes are prudent In an Emergency. (Emily Dickinson 1830-1886) END end def recite puts @text end end </pre> <p>But it wouldn&#8217;t be Ruby if there were no way to make this pretty. The minus in <code>-END</code> makes sure any whitespace before the end marker is ignored and the first six spaces of every line are cut when the string collected by heredoc is post processed with <code>gsub</code>:</p> <pre> class Poem def initialize @text = &lt;&lt;-END.gsub(/^ {6}/, '') "Faith" is a fine invention When Gentlemen can see But Microscopes are prudent In an Emergency. (Emily Dickinson 1830-1886) END end def recite puts @text end end </pre> <p>The result for both snippets is exactly the same &#8211; provided you stick to the recommended 2 spaces indent for Ruby source code:</p> <pre> &gt;&gt; Poem.new.recite "Faith" is a fine invention When Gentlemen can see But Microscopes are prudent In an Emergency. (Emily Dickinson 1830-1886) </pre> Thu, 02 Jul 2009 19:54:30 GMT http://www.bitcetera.com/en/techblog/2009/07/02/heredoc-with-indent-in-ruby/ http://www.bitcetera.com/en/techblog/2009/07/02/heredoc-with-indent-in-ruby/ Mac-friendly Autotest <h2>autotest</h2> <p>ZenTest&#8217;s autotest is great, but it has one drawback: In order to detect whether you have modified a file, it relies on filesystem polling. In other words it constantly traverses the filesystem and thus causes a lot of <span class="caps">CPU</span> and harddrive load. Check this out:</p> <pre> $ autotest &amp; [1] 664 $ ps ax 664 664 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest -- WAIT 1 MINUTE -- $ ps ax 664 664 s000 S+ 0:01.27 /usr/bin/ruby -ws /usr/bin/autotest ^^^^^^^ </pre> <p>Eventhough you don&#8217;t do anything, the <span class="caps">CPU</span> clock for the autotest process keeps counting up. If you are working on a portable computer, you will notice that your battery runs out in no time. And that&#8217;s not even the worst part yet. Permanent filesystem cruising are poison for the harddrive will have an impact on it&#8217;s life expectancy on the long run.</p> <h2>autotest-fsevent</h2> <p>Enter the autotest-fsevent gem. It teaches autotest to use FSEvent instead of filesystem polling. Here&#8217;s the same test with autotest-fsevent installed:</p> <pre> $ autotest &amp; [1] 698 $ ps ax 698 698 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest -- WAIT 1 MINUTE -- $ ps ax 698 698 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest ^^^^^^^ </pre> <p>As you see the <span class="caps">CPU</span> clock is not counting while autotest waits for file alterations. Instead of monitoring the files itself, autotest-fsevent delegates this job to the FSEvent core service which Apple has introduced with Mac OS X 10.5. Think of FSEvent as a radio station which constantly broadcasts file alterations. It comes at no extra cost as it&#8217;s sitting right on the kernel.</p> <h3>Installation</h3> <p>First install the gem:</p> <pre>sudo gem install autotest-fsevent</pre> <p>Then add the following line <strong>after all other requires</strong> in your <tt>&#126;/.autotest</tt>:</p> <pre>require 'autotest/fsevent'</pre> <p><span class="warning">Please submit feature requests and bug reports on <a href="https://forge.bitcetera.com/projects/show/autotest-fsevent">BitForge</a> rather than adding a comment here.</span></p> <h3>Resources</h3> <ul> <li><a href="/en/products/autotest-fsevent">Homepage</a></li> <li><a href="https://forge.bitcetera.com/projects/show/autotest-fsevent">BitForge</a> (Bugtracker, Forum etc)</li> <li><a href="http://github.com/svoop/autotest-fsevent/tree/master">Github</a></li> </ul> <h2>autotest-growl</h2> <p>ZenTest-4.0.0 comes with bundled Growl support which, however, will vanish very soon in favor of the autotest-growl gem which displays Growl notifications for RSpec, Unit::Test and Cucumber. And it comes with a cute set of colored Ruby icons which can easily be overridden by your preferred icon set.</p> <h3>Installation</h3> <p>Read the <a href="http://github.com/svoop/autotest-growl/tree/master"><span class="caps">README</span></a> for installation instructions as they differ whether your&#8217;re on ZenTest-4.0.0 or an upcoming version without bundled Growl support.</p> <p><span class="warning">Please submit feature requests and bug reports on <a href="https://forge.bitcetera.com/projects/show/autotest-growl">BitForge</a> rather than adding a comment here.</span></p> <h3>References</h3> <ul> <li><a href="/en/products/autotest-growl">Homepage</a></li> <li><a href="https://forge.bitcetera.com/projects/show/autotest-growl">BitForge</a> (Bugtracker, Forum etc)</li> <li><a href="http://github.com/svoop/autotest-growl/tree/master">Github</a></li> </ul> <h2>Exceptions</h2> <p>The only feature which hasn&#8217;t made it from the now deprecated autotest-mac gem into neither autotest-fsevent nor autotest-growl is the exception of certain paths. It&#8217;s in fact better if you set them yourself and according to your needs in <tt>&#126;/.autotest</tt>. Here is an example:</p> <pre> Autotest.add_hook :initialize do |autotest| %w{.git .svn .hg .DS_Store ._* vendor}.each {|exception| autotest.add_exception(exception) } false end </pre> <p>(<a href="/en/services/sven-schwyn">Sven Schwyn</a>)</p> Wed, 27 May 2009 09:20:51 GMT http://www.bitcetera.com/en/techblog/2009/05/27/mac-friendly-autotest/ http://www.bitcetera.com/en/techblog/2009/05/27/mac-friendly-autotest/ Pimp Your .autotest <p><span class="warning">This blog article is out of date, check out <a href="/en/techblog/2009/05/27/mac-friendly-autotest/">Mac-friendly Autotest</a> instead.</span></p> <h2><span class="caps">BDD</span> is Fun</h2> <p>Besides the positive impact on code quality, <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"><span class="caps">BDD</span></a> has a fun factor of it&#8217;s own. It adds some immediate and colorful feedback to the work cycles and makes me feel like being the pilot of my code.</p> <p>Setting things up is quite easy nowadays, but as many howtos out there have come to a certain age, here&#8217;s one for <a href="http://rspec.info">RSpec</a> 1.2 and <a href="http://cukes.info">Cucumber</a> 0.3. Test::Unit is supported as well. (This is work in progress, so please feel free to post your comments and check back as I&#8217;m going to update this post for a while.)</p> <h2>Requirements</h2> <p>This howto assumes that you are working on a Rails application and that your workstation is running Mac OS X with the latest and greatest version of <a href="http://growl.info">Growl</a> installed.</p> <h2>Installation</h2> <p>First install the gems necessary to work with Ruby on Rails applications:</p> <pre>gem install rspec rspec-rails cucumber webrat ZenTest</pre> <p><a href="http://github.com/brynary/webrat/tree/master">Webrat</a> is optional, but you don&#8217;t want to miss it. Now define some environment variables:</p> <pre> echo "export AUTOFEATURE=true" &gt;&gt;~/.profile echo "export RSPEC=true" &gt;&gt;~/.profile source .profile </pre> <p>If you prefer to set these in your application, add the following lines to the top of <tt>config/environments/test.rb</tt> instead:</p> <pre class="sh_ruby"> ENV['AUTOFEATURE'] = 'true' ENV['RSPEC'] = 'true' </pre> <p>Next are the images which will be displayed in Growl notifications:</p> <p><img src="/page_attachments/0000/0001/ruby_red_icon.png" size="icon" /><br /> <img src="/page_attachments/0000/0003/ruby_yellow_icon.png" size="icon" /><br /> <img src="/page_attachments/0000/0005/ruby_green_icon.png" size="icon" /><br /> <img src="/page_attachments/0000/0007/ruby_grey_icon.png" size="icon" /></p> <pre> wget http://www.bitcetera.com/page_attachments/0000/0009/autotest_images.zip unzip autotest_images.zip mv autotest_images ~/.autotest_images </pre> <p>And finally create the configuration file <tt>~/.autotest</tt>:</p> <pre class="sh_ruby"> module Autotest::Growl def self.growl title, msg, img, pri=0, stick="" system "growlnotify -H localhost -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{stick}" end Autotest.add_hook :run_command do @label = File.basename(Dir.pwd).upcase @run_scenarios = false print "\n"*2 + '-'*80 + "\n"*2 print "\e[2J\e[f" # clear the terminal end Autotest.add_hook :ran_command do |autotest| gist = autotest.results.grep(/\d+\s+(example|test)s?/).map {|s| s.gsub(/(\e.*?m|\n)/, '') }.join(" / ") if gist == '' growl "#{@label} cannot run tests", '', "~/.autotest_images/ruby_grey.png" else if gist.match /[1-9]\d*\s+(failure|error)/ growl "#{@label} fails some tests", "#{gist}", "~/.autotest_images/ruby_red.png" elsif gist.match /pending/ growl "#{@label} has pending tests", "#{gist}", "~/.autotest_images/ruby_yellow.png" @run_scenarios = true else growl "#{@label} passes all tests", "#{gist}", "~/.autotest_images/ruby_green.png" @run_scenarios = true end end end # FIXME: This is a temporary workaround until Cucumber is properly integrated! Autotest.add_hook :waiting do |autotest| if @run_scenarios gist = autotest.results.grep(/\d+\s+(scenario|step)s?/).map {|s| s.gsub(/(\e.*?m|\n)/, '') }.join(" / ") if gist == '' growl "#{@label} cannot run scenarios", '', "~/.autotest_images/ruby_grey.png" else if gist.match /failed/ growl "#{@label} fails some scenarios", "#{gist}", "~/.autotest_images/ruby_red.png" elsif gist.match /undefined/ growl "#{@label} has undefined scenarios", "#{gist}", "~/.autotest_images/ruby_yellow.png" else growl "#{@label} passes all scenarios", "#{gist}", "~/.autotest_images/ruby_green.png" end end end end end Autotest.add_hook :initialize do |autotest| %w{.svn .hg .git vendor}.each {|exception| autotest.add_exception(exception) } end </pre> <p>A few things to note here:</p> <ul> <li>ZenTest does not yet really support Cucumber. However, this workaround does the trick if you use RSpec or Test::Unit as well.</li> <li>The Growl message titles may be too long for some display styles, a good choice is &#8220;Music Video&#8221;.</li> <li>The <tt>run_command</tt> hook clears the terminal every time before tests are ran, however, you can still scroll up to previous output. Every test run is separated with a line of dashes.</li> <li>The &#8220;cannot run tests/scenarios&#8221; message is shown e.g. when you have a serious syntax error in your specs like do-end nesting typos.</li> <li>The <tt>-H localhost</tt> argument is a workaround for a glitch which lets Growl 1.1.4 on Mac OS X 10.5 randomly ignore some notifications. However, it will only work if you check &#8220;System Preferences -&gt; Growl -&gt; Network -&gt; Listen for incoming notifications&#8221;. (You&#8217;ll get a <tt>NSPortTimeoutException</tt> from <tt>growlnotify</tt> if you don&#8217;t do this.) Furthermore, when using this setup for the first time, you have to check &#8220;System Preferenes &#8594; Growl &#8594; Network &#8594; Allow remote application registration&#8221; as well. Once <tt>autotest</tt> is in the list of Growl applications, you can uncheck this again.</li> </ul> <h2>Usage</h2> <p>Just change into the RAILS_ROOT directory and fire up autotest:</p> <pre>autotest</pre> <p>Whenever you save a file of your Rails project, all relevant tests will be ran and you get both a Growl feedback and detailed test results in the terminal.</p> <p>(<a href="/en/services/sven-schwyn">Sven Schwyn</a>)</p> Thu, 09 Apr 2009 14:24:20 GMT http://www.bitcetera.com/en/techblog/2009/04/09/pimp-your-autotest/ http://www.bitcetera.com/en/techblog/2009/04/09/pimp-your-autotest/ 10 Reasons why PHP is Still Better than Ruby ;-) <h2>1. Safety</h2> <p>Remember Gregg and Jason in their <a href="http://www.youtube.com/watch?v=Ld919lziKgE">Ruby on Rails vs <span class="caps">PHP</span></a> clips? The Rails guy goes to the beach while the <span class="caps">PHP</span> guy still tries to switch databases. Turns out hundreds of people die every year on beaches whereas the risk of dropping dead on your desk is next to nil. In fact, driving to work and most things you do during your spare time are far more life threatening than working on code and therefore the longer it takes, the better for your own personal safety.</p> <h2>2. Semicolon</h2> <p>Programming languages without a semicolon at the end of each line are like a fish without a bicycle. Nuff said.</p> <h2>3. <span class="caps">DRY</span> won&#8217;t Pay your Bills</h2> <p>Unless you&#8217;re workin on a project of your own, producing as little and maintainable code as possible will mainly <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself"><span class="caps">DRY</span></a> up your paycheck. You spend less hours copying and pasting, less hours fixing the same bug on ten different lines and less time finding bugs in the first place. But remember: Time equals cash when you&#8217;re contracted by the hour. So we should be grateful for <span class="caps">PHP</span> and frameworks like Zend which make it so ridiculously easy to write the most cumbersome code full of duplications.</p> <h2>4. Namespaces</h2> <p>Colliding classes which happen to have the same name can indeed become a problem, however, Ruby-style namespaces with <code>module MyNamespace</code> are by no means the only solution. The makers of <span class="caps">PHP</span> chose not to overload it&#8217;s lean syntax with such unneccessary keywords and urge coders to prefix the class name like <code>class MyNamespace_MyClass</code> instead.</p> <p>Nevertheless, in order to satisfy those who still long for namespaces, <span class="caps">PHP</span> will support <a href="http://www.php.net/manual/en/language.namespaces.rationale.php">the <code>namespace</code> keyword</a> as of the yet to be released version 5.3.</p> <h2>5. Goto</h2> <p>The presence of a <code>goto</code> language construct has been considered evil for decades now, yet not the keyword itself is evil but what a tiny minority of coders would use it for. In other words: Messy software developers are used as an excuse to discriminate the Methuselah of keywords.</p> <p>Discrimination is fundamentally wrong! The makers of <span class="caps">PHP</span> have realized that and will <a href="http://www.php.net/manual/en/control-structures.goto.php">will support <code>goto</code></a> as of the upcoming version 5.3 whereas for Rubyists the <a href="http://raa.ruby-lang.org/project/ruby-goto">ruby-goto library</a> (categorized Library/Evil) is not even available as a gem.</p> <h2>6. Elseif</h2> <p>Cascading <code>if</code> clauses contain at least one &#8220;else if&#8221; case, so the natural way to name this keyword is <code>elseif</code> &#8211; as does <span class="caps">PHP</span>. Ruby on the other hand uses <code>elsif</code> which is so much harder to remember.</p> <h2>7. Solid and Static Foundation</h2> <p>Ruby is a highly dynamic programming language which allows you to twist and tweak almost every aspect of it. Therefore all it takes is for someone to accidentially monkey patch the <code>+</code> method of Float and your application goes kaboom. <span class="caps">PHP</span> on the other hand has a rock static foundation which means <code>array_uintersect_uassoc()</code> does exactly what it sais, which is&#8230; well, <a href="http://www.php.net/manual/en/function.array-uintersect-uassoc.php">check the documentation</a> for that. And if you absolutely must change it&#8217;s behaviour, you can always write your own <code>my_array_uintersect_uassoc()</code>.</p> <h2>8. Elegance versus Expertise</h2> <p>Andy Jeffries compares the following snippets in his blog post <a href="http://andyjeffries.co.uk/articles/4-reasons-why-ruby-syntax-is-better-than-phps%2D">4 Reasons why Ruby Syntax is Better than PHPs</a>.</p> <p><span class="caps">PHP</span>:</p> <pre class="sh_php"> $foo = array("zulu" =&gt; "1", "alpha" =&gt; "4", "golf" =&gt; "8", "bravo" =&gt; "3"); $keys = array_keys($foo); sort($keys); $bar = array_slice($keys, 0, 3); </pre> <p>Ruby:</p> <pre class="sh_ruby"> foo = {"zulu" =&gt; "1", "alpha" =&gt; "4", "golf" =&gt; "8", "bravo" =&gt; "3"} bar = foo.keys.sort.slice(0,3) </pre> <p>Admittedly, the Ruby syntax is more elegant and easier to read. However, if elegance is your aim in life, you&#8217;d better become a poet. Fact is that my granma could read and understand this piece of Ruby code whereas it takes a lot more expertise to figure what the <span class="caps">PHP</span> snippet is doing. Software developers should face the fact that they are paid for expertise, so making things hard to read &#8211; best coupled with poor documentation &#8211; will make you less disposable on the long run.</p> <h2>9. Less is More</h2> <p>The statistics of available extensions as of 2009-06-04:</p> <table class="wikitable"> <tr> <th>Language </th> <th>Appearance </th> <th>Extensions </th> <th>Ext per Year </th> <th>Sources </th> </tr> <tr> <td> <a href="http://en.wikipedia.org/wiki/Perl">Perl</a> </td> <td> 1987 </td> <td> 15461 distros </td> <td> 703 distros </td> <td> <a href="http://www.cpan.org/modules/01modules.index.html"><span class="caps">CPAN</span></a> </td> </tr> <tr> <td> <a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29">Ruby</a> </td> <td> 1995 </td> <td> 7326 gems </td> <td> 523 gems </td> <td> <a href="http://gems.rubyforge.org/gems">Rubyforge</a> and <a href="http://gems.github.com/list.html">Github</a> (forks not counted) </td> </tr> <tr> <td> <a href="http://en.wikipedia.org/wiki/Php"><span class="caps">PHP</span></a> </td> <td> 1995 </td> <td> 749 packages </td> <td> 54 packages </td> <td> <a href="http://pear.php.net/packages.php"><span class="caps">PEAR</span></a> and <a href="http://pecl.php.net/packages.php"><span class="caps">PECL</span></a> </td> </tr> </table> <p>At first sight this seems to be bad news for <span class="caps">PHP</span> as it falls way behind the others with Ruby closing in on Perl. Then again in the real world with real customers it&#8217;s much easier to get a fair price for your software project if you can sell bits and pieces with: &#8220;There is no solution available out there, we&#8217;ll have to do it ourselves.&#8221;</p> <h2>10. Bugs are your Friends</h2> <p>You just have to learn how to sell them, too. Don&#8217;t believe the &#8220;half a product, not a half-ass product&#8221; stanza by the nice yet overly idealistic folks at 37signals (<a href="http://gettingreal.37signals.com">Getting Real</a>, <a href="http://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php">chapter 5</a>). The real buck starts flowing once you force your customers to constantly upgrade or even contract your consulting services.</p> <p>This said, <span class="caps">PHP</span> is the ideal choice. There are testing frameworks out there, even <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"><span class="caps">BDD</span></a> has made it to the <span class="caps">PHP</span> world, but fortunately the <span class="caps">PHP</span> syntax is twisted enough to make the descriptions quite illegible. Compare the code samples from the two project webpages:</p> <p><a href="http://www.rspec.info">RSpec</a>:</p> <pre class="sh_ruby"> require 'bowling' describe Bowling do before(:each) do @bowling = Bowling.new end it "should score 0 for gutter game" do 20.times { @bowling.hit(0) } @bowling.score.should == 0 end end </pre> <p><a href="http://www.phpspec.org">PHPSpec</a>:</p> <pre class="sh_php"> require_once 'Bowling.php'; class DescribeNewBowlingGame extends PHPSpec_Context { private $_bowling = null; public function before() { $this-&gt;_bowling = new Bowling; } public function itShouldScore0ForGutterGame() { // allow 20 throws for ($i=1; $i&lt;=20; $i++) { $this-&gt;_bowling-&gt;hit(0); } $this-&gt;spec($this-&gt;_bowling-&gt;score)-&gt;should-&gt;equal(0); } } </pre> <p>By working with <span class="caps">PHP</span> you can rest assured that 99.9% of the lines of code out there won&#8217;t come with tests and given the syntactical challanges that&#8217;s not going to change. Therefore, <span class="caps">PHP</span> is the perfect ecosystem for bugs to grow and continue to play an important role in selling bugfixing to customers.</p> <p>(<a href="/en/services/sven-schwyn">Sven Schwyn</a>)</p> Tue, 07 Apr 2009 09:53:20 GMT http://www.bitcetera.com/en/techblog/2009/04/07/10-reasons-why-php-is-still-better-than-ruby--/ http://www.bitcetera.com/en/techblog/2009/04/07/10-reasons-why-php-is-still-better-than-ruby--/ Easy Screencast Creation <p>If you&#8217;re tired of explaining the same things over and over again, then you might find this little application for Mac OS X and Windows very helpful: <a href="http://www.jingproject.com">Jing</a>. It allows you to create screenshots and screencasts from any area of your screen and add annotations or voice-over to it.</p> <p>Once done, you can upload your image or movie either to the default provider <a href="http://www.screencast.com">Screencast</a> (free within some bandwidth and diskspace boundraries), send them to a <span class="caps">FTP</span> server of your choice or save it locally.</p> <p>Jing uses a simple interface and an original, but maybe not overly practical &#8220;sun&#8221; hotspot for invocation. However, on Mac OS X a setting exists which replaces the &#8220;sun&#8221; hotspot with a normal menu bar item.</p> <p>(<a href="/en/services/sven-schwyn">Sven Schwyn</a>)</p> Wed, 18 Feb 2009 13:18:30 GMT http://www.bitcetera.com/en/techblog/2009/02/18/easy-screencast-creation/ http://www.bitcetera.com/en/techblog/2009/02/18/easy-screencast-creation/