<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6655636091625157671</id><updated>2011-11-22T00:08:57.614-05:00</updated><category term='yapc 2010 modern perl 5'/><category term='performance correctness'/><category term='DBM::Deep 1.0020 release'/><category term='CDBI Class DBI DBIx DBIC conversion convert similarities differences'/><category term='perlish code conciseness'/><category term='perl debugger useless'/><category term='YAPC 2010 social media'/><category term='perlish code conciseness list manipulations'/><category term='CDBI DBIC components multiple inheritance MI'/><category term='class dbi dbix converting'/><category term='CDBI DBIC CDBICompat'/><category term='DBIC CDBI conversion result_class resultset_class'/><category term='YAPC 2010 CFP'/><category term='Perl Java enterprise jobs'/><category term='complexity management'/><category term='DBIC CDBI conversion'/><category term='ironman blogging'/><category term='perl 6 perl6 rakudo'/><category term='Perl Java enterprise'/><category term='software complexity change risk management coupling'/><title type='text'>robkinyon on Perl</title><subtitle type='html'>I've been babbling about Perl and programming in general on Perlmonks and IRC for years. mst finally got me to start blogging as part of the Ironman blogging push.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-4416617178843214481</id><published>2010-03-02T19:01:00.003-05:00</published><updated>2010-03-02T19:17:09.603-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DBM::Deep 1.0020 release'/><title type='text'>DBM::Deep 1.0020 released</title><content type='html'>&lt;div&gt;1.0020 Feb 16 22:00:00 2010 EST&lt;/div&gt;&lt;div&gt;    (This version is compatible with 1.0016)&lt;/div&gt;&lt;div&gt;    - Fixed t/43_transaction_maximum.t so that it doesn't error out on systems&lt;/div&gt;&lt;div&gt;      which cannot fork &gt; 255 children at one time.&lt;/div&gt;&lt;div&gt;    - Improved code coverage&lt;/div&gt;&lt;div&gt;        - Added t/96_virtual_functions.t which helps describe what actually&lt;/div&gt;&lt;div&gt;          needs to be overridden in a new plugin.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, the major change between 1.0020 and 1.0016 is the support for different backends. This was one of the biggest changes I've made, even considering adding support for transactions. While transactions were a big change mentally, adding backends required a lot more physical work. There was moving all sorts of code around and actually making proper APIs between the various subsystems. This exposed a ton of coupling that had to be teased apart very gently.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I also learned a ton about just how &lt;b&gt;UN&lt;/b&gt;-transactional the various "transactional" datastores really are. SQLite does full DB-locks to implement transactions. InnoDB (MySQL's transactional engine) takes locks on AUTO_INCREMENT keys. So, in both cases, concurrent transactions just don't work. DBM::Deep's transaction support wins. Huh.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But, unlike DBM::Deep's native file backend, using MySQL as a backend allows you to use DBM::Deep across different servers. So, DBM::Deep can start to scale horizontally where, before, it couldn't because of problems with flock over NFS. And, for obvious reasons, running DBM::Deep using MySQL as a backend is faster - much faster.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have an idea for how to improve transactions over InnoDB to avoid AUTO_INCREMENT keys by using UUIDs. But, until I see someone actually using this in prod, it'll remain just an idea.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-4416617178843214481?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/4416617178843214481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/03/dbmdeep-10020-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4416617178843214481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4416617178843214481'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/03/dbmdeep-10020-released.html' title='DBM::Deep 1.0020 released'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-7056685318513127265</id><published>2010-02-20T16:54:00.003-05:00</published><updated>2010-02-20T19:25:47.529-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software complexity change risk management coupling'/><title type='text'>Software as complexity management (part 2)</title><content type='html'>(q.v. &lt;a href="http://robonperl.blogspot.com/2010/02/software-as-complexity-management-part.html"&gt;part 1&lt;/a&gt;)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All pieces of software have one thing in common - they change over time. Whether it's a new feature, a bug report, or a feature that's implemented over 3 releases, these changes affect our baby in so many ways. Managing those changes is probably the most important thing a developer does.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Change is a problem because it introduces risk - risk of a bug. We all know what a bug is, but every change could introduce one. So, managing change is best done by reducing the risk of every change.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The only way to reduce risk is to reduce the scope of the risk. The biggest risk any change has is in how many workflows the change can potentially affect. So, you want to keep the scope of every line of code as tight as possible. Any change to any line in a scope (block, function, etc) has the same area of effect as every other line in the same scope. So, if one line of code in a function reference a global variable, then any change to any line in that function have the potential to affect that global variable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is sometimes called coupling, but I think that coupling isn't a strong enough concept. The best analogy is taint. Let's say we have global variable %BAD_IDEA. It's referenced in functions bad_foo() and bad_bar(). If any line in bad_foo() is changed, then every workflow that uses bad_foo() must be tested (duh!). But, every workflow that uses bad_bar() must &lt;b&gt;also &lt;/b&gt;be tested. And, if bad_bar() uses another global variable, then every workflow that uses&lt;b&gt; &lt;/b&gt;any function that uses that second global variable must also be tested. All from changing a line in bad_foo().&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It becomes pretty obvious pretty quickly that global variables end up tainting whole swathes of code (and why global variables should be avoided at all costs). Next part is about objects and how they encourage the use of global variables.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-7056685318513127265?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/7056685318513127265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/software-as-complexity-management-part_20.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7056685318513127265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7056685318513127265'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/software-as-complexity-management-part_20.html' title='Software as complexity management (part 2)'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-3841985802007261880</id><published>2010-02-18T22:29:00.004-05:00</published><updated>2010-02-18T23:06:23.343-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='complexity management'/><title type='text'>Software as complexity management (part 1)</title><content type='html'>Software exists to solve problems, primarily problems in business. Solutions to those problems pay for the people who write the software who solve them. Even free software runs on corporate money. Especially free software.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we want to write better software, we need to have a solid understanding of what a problem is. Instead of problems, it's useful to talk about the &lt;i&gt;problemspace&lt;/i&gt;. I often find it useful to imagine a problem as a surface in N-dimensional space, each dimension representing a competing concern. For me, the surface describes the &lt;i&gt;complexity floor&lt;/i&gt;&lt;i&gt; of the solutionspace. &lt;/i&gt;It's the theoretically ideal solution - the absolute zero of software perfection.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, the ideal software is the implementation that is closest to the complexity floor. Can we describe the complexity axes? Can we describe some rules for how to minimize them? What do you think?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-3841985802007261880?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/3841985802007261880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/software-as-complexity-management-part.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3841985802007261880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3841985802007261880'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/software-as-complexity-management-part.html' title='Software as complexity management (part 1)'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-4758558314182609499</id><published>2010-02-16T19:06:00.004-05:00</published><updated>2010-02-16T19:21:32.861-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl debugger useless'/><title type='text'>How useful is a debugger, really?</title><content type='html'>&lt;div&gt;(Inspired by &lt;a href="http://stackoverflow.com/questions/602138/is-a-debugger-the-mother-of-all-evil"&gt;this&lt;/a&gt; and &lt;a href="http://www.reddit.com/r/programming/comments/b2u8v/the_dumbest_thing_ive_read_all_day/"&gt;this&lt;/a&gt; and informed by &lt;a href="http://linuxmafia.com/faq/Kernel/linus-im-a-bastard-speech.html"&gt;Linus&lt;/a&gt;.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;From the get-go, there's been a Perl debugger and lots of people think that it's a "Good Thing"™. Me, I've never seen the point. Yeah, I've used it. I know how to set breakpoints and step into functions and all that. I've used perl -d, gdb, the VB debugger, and the debuggers in both Firefox and IE (version 5-8). And I hate them all.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, &lt;i&gt;hate&lt;/i&gt; is a strong word. Frankly, I don't see the point. There has never been a programming problem I've faced where using the debugger helped me. At all. In any language. Ever.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In 2000, I was lucky to be mentored by &lt;a href="http://www.blogger.com/profile/17711708636792771116"&gt;Ted Vessenes&lt;/a&gt; when we were working at Motorola. Ted is one of the most phenomenal programmers I've ever met and I know a bunch of brilliant people. Just to give you an idea of how freaking awesome he is, this is the guy that played so much Unreal Tournament that he got pissed at the AI and built a new one. Not a perfect player, but a perfect &lt;i&gt;human&lt;/i&gt; player. His AI ended up being so good that he had to mess up his algorithms so that other people knew they were playing an AI. He literally passed the UT3 Turing Test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ted once told me "the most powerful debugging tool is print." (He actually told me this a bunch of times.) Or, restated - "If you need anything more than the print statement to debug a problem, then you don't understand the problem enough to solve it."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That means you, Mr. debugger. If I have to reach for you, that means I don't have enough context, knowledge, or whatever else I might need to solve the problem. In fact, I use my desire for a debugger as a litmus test. Anytime I want a debugger, I know I'm too stupid to fix it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(Frankly, this goes for IDEs, too. If I need anything but vim to manage my project, then my project isn't organized properly.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-4758558314182609499?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/4758558314182609499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/how-useful-is-debugger-really.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4758558314182609499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4758558314182609499'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/how-useful-is-debugger-really.html' title='How useful is a debugger, really?'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-8797430669425975578</id><published>2010-02-15T20:34:00.003-05:00</published><updated>2010-02-15T21:11:36.705-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl Java enterprise'/><title type='text'>Why choose Java over Perl?</title><content type='html'>I was talking about about &lt;a href="http://robonperl.blogspot.com/2010/02/perl-and-java-in-enterprise.html"&gt;Perl and Java in the Enterprise&lt;/a&gt; with frew on IRC tonight. We never actually discussed the topic at hand. Instead, we ended up talking about &lt;a href="http://robonperl.blogspot.com/2010/02/perl-and-java-in-enterprise.html?showComment=1266214751087#c3593954782438590736"&gt;szabgab's comment&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think the primary reason is that Perl is too individualizable, by far. Yes, I said &lt;i&gt;too individualizable&lt;/i&gt;. That strength of Perl - TMTOWTDI - is its biggest weakness when it comes to working in groups.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When it comes to programming applications, the key feature of a good workflow is managing change. Every application will have change come down the pike. A new feature, an overeager salesman, a bug found, or an idiotic CTO - these all bring about changes. A good workflow will build an application that manages these changes without compromising the application's ability to manage subsequent changes. A team of decent Perl developers will easily be able to build an application that does this. But, how long is the ramp-up for a new developer? What happens when one of the initial developers leaves?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Java, on the other hand, does not give you all that freedom in how you build your application. There is no TMTOWTDI Ave. in Java City. This inability to express yourself is a strength when it comes to managing turnover. Every Java application in existence looks a lot like every other Java application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Furthermore, Java offers a set of guarantees that Perl simply cannot do because of the design tradeoffs inherent in the language. For example, there is absolutely no way to declare something invariant in Perl. In Java, invariants are a normal part of the language. Perl also has no way of guaranteeing the type of a given variable. Java and Haskell both have this feature. You cannot turn off monkey-patching or any of the other runtime poking that is one of Perl's greatest strengths, not even lexically.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And, to top it all off, there's such a huge variety in feature strengths that a Perl novice simply cannot comprehend a Perl master's code, let alone a guru's. Every Java developer can read every other Java developer's code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Given that some programming teams turn over a developer every week, which language should they choose?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-8797430669425975578?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/8797430669425975578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/why-choose-java-over-perl.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/8797430669425975578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/8797430669425975578'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/why-choose-java-over-perl.html' title='Why choose Java over Perl?'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-7939545764367654366</id><published>2010-02-14T17:49:00.002-05:00</published><updated>2010-02-14T20:19:52.232-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl Java enterprise jobs'/><title type='text'>Perl and Java in the Enterprise</title><content type='html'>(&lt;a href="http://www.google.com/buzz/perigrin/EJPsuEUCQQv/PHP-and-Perl-crashing-the-enterprise-party-The"&gt;Via Google Buzz&lt;/a&gt;)&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm glad that Perl job openings in the enterprise are trending upwards. But, what does the number of openings really tell us about the comparative penetration of each language? Well, a lot less than you might think.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The big difference is how many developers of language X are needed to support a given set of features. And, as every good Perl developer knows, Perl requires a lot less developers than Java.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;A LOT LESS.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the past, I was a Perl contractor for some of the largest Fortune 500 companies in the world. Every one of these companies had significant investment in both Perl and Java. A few times, I saw a given application developed in Perl, then reimplemented in Java. I distinctly remember two specific cases where this happened.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Both cases followed the same pattern. First, the Perl app was developed part-time by 2-3 developers over a couple weeks and supported by them in their "spare time" - in addition to their fulltime responsibilities. Management found out about the app and, in both cases, ordered it reimplemented in Java. Six months later, the group 20+ developers and 2-3 project managers released their first version. Unusably buggy, it had less than half the features than the prototype app in Perl. After another year (roughly 40 man-years sunk), the users in both cases got the original app up and running via back-channels and went about their work. In one case, management supported the Perl app. In the other, I think the Java app is still up and running. Maybe (6+ years later), it's finally where the original prototype was. Probably not.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The point is that a team of 3-5 Perl developers can do more than 30 Java developers. 10:1 sounds about right. Perl has &lt;b&gt;already &lt;/b&gt;penetrated the enterprise. Frankly, the enterprise cannot exist without Perl. The enterprise just doesn't need as many Perl developers to do the same work. Think about that. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-7939545764367654366?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/7939545764367654366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/perl-and-java-in-enterprise.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7939545764367654366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7939545764367654366'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/perl-and-java-in-enterprise.html' title='Perl and Java in the Enterprise'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-6493609904843232864</id><published>2010-02-10T19:45:00.005-05:00</published><updated>2010-02-10T20:45:15.903-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='yapc 2010 modern perl 5'/><title type='text'>What is "Modern Perl 5"?</title><content type='html'>So, the theme for &lt;a href="http://yapc2010.com/"&gt;YAPC::NA::2010&lt;/a&gt; is going to be "Modern Perl 5". Other than a cool marketing buzzword, what exactly does that mean?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sometimes, it's easier to start with what this &lt;b&gt;doesn't&lt;/b&gt; mean.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There's a quasi-truism that says something like "You can always recognize someone's original language in Perl." C programmers write C in Perl. Java programmers do the same thing. (And, wow can you tell a sysadmin who's only ever used awk and sed!) It's easy to recognize "good Perl," but can we describe it?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Perl is also oft-maligned as "a bunch of line-noise." While it's easy to dismiss those complaints as from "sigil haters" or "regex newbies," there is definitely some truth that Perl tends to be much &lt;i&gt;denser&lt;/i&gt; than other languages. And, that's a strength of our language - one we get from our FP roots. It's quite common to translate a program from C to Perl and get LOC ratios of 20-1 or higher. I once saw higher than 100-1 and it was well-written C.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lastly, one of the great promises of Perl 6 is that it will allow sane grammar modification. We don't have that yet. But, &lt;a href="http://search.cpan.org/~flora/Devel-Declare-0.005011/lib/Devel/Declare.pm"&gt;Devel::Declare&lt;/a&gt; does get us quite close. Syntactic sugar isn't about less keystrokes - it's about being clear about the &lt;i&gt;intent&lt;/i&gt; of the code. In my opinion, C's typedef is one of its most powerful features.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Putting it all together, this is what Modern Perl 5 is all about:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;A Perl "style"&lt;/li&gt;&lt;li&gt;Readably dense code&lt;/li&gt;&lt;li&gt;Literate code&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;The best example of this is &lt;a href="http://search.cpan.org/~drolsky/Moose-0.98/lib/Moose.pm"&gt;Moose&lt;/a&gt;. Everything in Moose can be implemented in pure Perl. (Some is in XS for performance, but it doesn't &lt;i&gt;have&lt;/i&gt; to be.) Code written using Moose is unarguably in a Perl style. The code is very dense (easily 20-1 to C or Java), but it's clear at the same time. There are several kinds of subroutine declarations, each making it clear what its intention is.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moose will have at least one track devoted to it and there's going to be at least one class on Moose during the after-YAPC. What else is there that epitomizes those "Modern Perl 5" features? How did you bring those features to your pre-modern codebases? What advice can you give someone on how to make their code modern? Did I even get all the features of "Modern Perl 5" correct?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Why am I asking all these questions? Because I want your talk submissions!&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-6493609904843232864?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/6493609904843232864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/what-is-modern-perl-5.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/6493609904843232864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/6493609904843232864'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/what-is-modern-perl-5.html' title='What is &quot;Modern Perl 5&quot;?'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-4520321405684358807</id><published>2010-02-10T07:34:00.003-05:00</published><updated>2010-02-10T07:38:55.997-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='YAPC 2010 social media'/><title type='text'>Social media setup</title><content type='html'>We have setup the various social media connections you want to get your YAPC::NA::2010 on.&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://twitter.com/yapc2010"&gt;Twitter - http://twitter.com/yapc2010&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.facebook.com/group.php?gid=300769505669"&gt;Facebook - http://www.facebook.com/group.php?gid=300769505669&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;And we're still on the ones you already know and love:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;#yapc on irc.perl.org&lt;/li&gt;&lt;li&gt;&lt;a href="http://mail.pm.org/mailman/listinfo/yapc"&gt;Mailing list - http://mail.pm.org/mailman/listinfo/yapc&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-4520321405684358807?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/4520321405684358807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/social-media-setup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4520321405684358807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4520321405684358807'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/social-media-setup.html' title='Social media setup'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-6871838257881457984</id><published>2010-02-09T18:36:00.006-05:00</published><updated>2010-02-10T20:49:29.168-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='YAPC 2010 CFP'/><title type='text'>Call for Presentations for YAPC::NA::2010</title><content type='html'>&lt;a href="http://conferences.mongueurs.net/yn2010/"&gt;YAPC::NA::2010&lt;/a&gt; is just around the corner. (Well, inasumuch as something 18 weeks away is "around the corner.") Last week, I met with Heath Bairh and the other organizers and took the position of speaker liaison. So, I should probably talk some about what we're looking for.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;YAPC::NA::2010 is going to be about "Modern Perl 5". We believe that Perl 5 is a vibrant and living language with many uncharted places it can go. Perl 6 is going to be great, but we can't wait until &lt;a href="http://dave.whipp.name/sw/perl6/perl6_xmas_2008.html"&gt;Christmas for Perl 6&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, we're looking for presentations about Perl 5 in all of its modern glory. Whatcha got?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You'll need to register (or login) to the&lt;a href="http://yapc2010.com/"&gt; YAPC::NA::2010&lt;/a&gt; website, then after registering for the conference, you can submit your CFP. The window closes March 31, 2010 at midnight GMT.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-6871838257881457984?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/6871838257881457984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2010/02/call-for-presentations-for-yapcna2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/6871838257881457984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/6871838257881457984'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2010/02/call-for-presentations-for-yapcna2010.html' title='Call for Presentations for YAPC::NA::2010'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-7900958962188580464</id><published>2009-08-17T09:34:00.005-04:00</published><updated>2009-08-17T09:44:00.339-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ironman blogging'/><title type='text'>Falling off the Ironman wagon</title><content type='html'>*sighs* I've fallen off the wagon. I knew I should have posted last week, but I didn't. Blogging is much harder than I thought. If you know me at all, you know that I have at least one opinion about nearly every topic in the word. I love discussing pretty much every topic, particularly if there are more than two options and it's impossible to determine which is better in any given situation. Those kinds of indeterminate discussions are absolutely fun.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Yet, here we are - I have people actually reading this blog and I can't actually write something every 8 days. I think it's because people aren't telling me how wrong I am on a regular basis. :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-7900958962188580464?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/7900958962188580464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/08/falling-off-ironman-wagon.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7900958962188580464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7900958962188580464'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/08/falling-off-ironman-wagon.html' title='Falling off the Ironman wagon'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-3793257411774586276</id><published>2009-08-06T17:07:00.004-04:00</published><updated>2009-08-06T18:06:41.426-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl 6 perl6 rakudo'/><title type='text'>The first "usable" release of P6</title><content type='html'>Patrick Michaud just &lt;a href="http://use.perl.org/~pmichaud/journal/39411"&gt;discussed the idea&lt;/a&gt; of releasing Rakudo, the Perl6 implementation bootstrapped in Perl6 targeting Parrot. He makes a very interesting point that language development doesn't go for a static target. Instead, it's very evolutionary. And, so, his goal is to have a "usable" and "useful" release of Perl 6 by Spring 2010 (April-ish).&lt;br /&gt;&lt;br /&gt;So, what does this mean? Well, in my mind, it means a few things.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first is that we, as a community, have been thinking we're going to get the most amazing thing in the world &lt;i&gt;from the get-go&lt;/i&gt;. And, in retrospect, it's rather obvious that this just isn't reasonable. The whole point of agile development (and, believe me, P6 development is nothing if not agile!) is that you "release early, release often".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second is that, frankly, a well-supported feature-light Perl 6 now is much better than a well-supported feature-complete Perl 6 released right before Duke Nuke'em Forever. I want to have some frozen API in my grubby hands before I spend my evenings away from my family and hacking on CP6AN stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And, lastly, we need to remember our history. Perl had been around for &lt;b&gt;10 years&lt;/b&gt; before objects and sane packaging were supported at all. Threads? Unicode? Both became stable with 5.8.0 - that's barely five years ago. Moose is less than three years old. DBIx::Class and Catalyst aren't much older. And, frankly, we drove the development of every one of those features. As a dev, I want users to tell me what they want to use. The P6 devs aren't any different.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, instead of griping that a feature-light P6 will be available, start thinking about how you can (ab)use those P6 features that &lt;i&gt;will&lt;/i&gt; be available (and we should have that list in the next month or two). Maybe we should start voting for our favorite features and see what we can do to help get them into the first production-ready Rakudo release. Go Team!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-3793257411774586276?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/3793257411774586276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/08/first-usable-release-of-p6.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3793257411774586276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3793257411774586276'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/08/first-usable-release-of-p6.html' title='The first &quot;usable&quot; release of P6'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-7682721787024913171</id><published>2009-07-29T21:59:00.009-04:00</published><updated>2009-07-30T21:21:16.423-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perlish code conciseness list manipulations'/><title type='text'>Perlish code part deux</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;Wow. Lots of good comments on my &lt;a href="http://robonperl.blogspot.com/2009/07/what-makes-code-perlish.html"&gt;last post&lt;/a&gt;. (well, lots of comments by this novice's standards, at any rate.) And, while I'm pretty sure some were tongue-in-cheek, it's obvious that my rather sparse discussion of conciseness was a bit too concise. So, maybe a longer example is in order.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Most programmers (perlers or not) will easily understand the following:&lt;/div&gt;&lt;pre&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;my @data = (&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        id =&gt; 1,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        first_name =&gt; 'Barney',&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        last_name =&gt; 'Rubble',&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        age =&gt; 33,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        gender =&gt; 'male',&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    # more of the same&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;# Create a string of "first last, first last, ...", sorted by name, for just males&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;my $names = join ", ", map {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        "$_-&gt;{first_name} $_-&gt;{last_name}"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    } sort {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        $a-&gt;{last_name} cmp $b-&gt;{last_name}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;     || $a-&gt;{first_name} cmp $b-&gt;{first_name}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    } grep {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;        $_-&gt;{gender} eq 'male'&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;    } @data;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm not going to even attempt how to do that in C. Needless to say, I'm betting it's going to be significantly longer than 8&lt;b&gt; lines&lt;/b&gt;. In fact, I'm betting it'll be closer to 10x that. The Java version is likely to be 5x that and likely more if you add in the building and maintenance of the initial data structure.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That is concise Perl. It takes advantage of the native high-level data structures (hashes and arrays) and the operators built for them (sort, map, and grep) to create very easy-to-understand complex code. And, we're not even touching string manipulation, supposedly Perl's greatest strength.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-7682721787024913171?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/7682721787024913171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/perlish-code-part-deux.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7682721787024913171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/7682721787024913171'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/perlish-code-part-deux.html' title='Perlish code part deux'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-419231139348360203</id><published>2009-07-28T22:56:00.006-04:00</published><updated>2009-07-28T23:07:42.551-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perlish code conciseness'/><title type='text'>What makes code Perlish?</title><content type='html'>There is a lot of discussion in lots of places about "perlish" code. What perlish code is. What it isn't. But, not a lot about how you can tell the difference.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first metric to look for is conciseness. How many lines of code does it take to express a concept? For example, swapping a two variables. In most languages, you have to use an explicit temp variable, such as in the following C code:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial, -webkit-fantasy; "&gt;temp = i;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, -webkit-fantasy;"&gt;i = j;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, -webkit-fantasy;"&gt;j = temp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's three lines to express a single concept. Most imperative languages require the same thing. Perl (and similar languages like Python and Ruby) does it in one.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial, fantasy;"&gt;( $i, $j ) = ( $j, $i );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Two lines doesn't sound like much. But, think about it as a 3-to-1 reduction. That means 300 lines is now 100. Ohhhh.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-419231139348360203?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/419231139348360203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/what-makes-code-perlish.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/419231139348360203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/419231139348360203'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/what-makes-code-perlish.html' title='What makes code Perlish?'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-2881323094169942211</id><published>2009-07-20T16:48:00.003-04:00</published><updated>2009-07-20T17:56:40.479-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DBIC CDBI conversion result_class resultset_class'/><title type='text'>Converting CDBI to DBIC (part 6): Phase 1</title><content type='html'>In &lt;a href="http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-5-plan.html"&gt;part 5&lt;/a&gt; of this series, the plan for how we're going to do this conversion was laid out. Now, for some actual working code.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The plan for our migration is going to leverage &lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: medium; color: rgb(0, 102, 153); "&gt;DBIx::Class::ResultSource&lt;/span&gt;'s &lt;i&gt;result_class &lt;/i&gt;attribute. First, some explanation. Unlike every other ORM I know about, DBIC decouples the operations on a group of rows from inflating those rows. This is the whole resultset thing. So, it only makes sense that you would be able to specify how you want to actually go about inflating the rows returned from a search. And DBIC does exactly that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, we have a set of CDBI classes. Let's work with one of them called App::CDBI::Foo. In order to make this work, we're going to want to have a corresponding DBIx::Class::ResultSource object. That resultsource object will be registered with our schema object (q.v. DBIC for more info) as handling stuff for the &lt;i&gt;foo&lt;/i&gt; table that App::CDBI::Foo used to manage.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In order to get everything to work, we're going to need to tell that resultsource everything that the CDBI class knows. We're also going to have to inject an &lt;i&gt;inflate_result()&lt;/i&gt; method into the CDBI class.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;my $source = DBIx::Class::ResultSource::Table-&gt;new({});&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;$source-&gt;add_columns( $cdbi-&gt;columns );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;$source-&gt;set_primary_key( $cdbi-&gt;primary_columns );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;*{ $cdbi . '::inflate_result' } = sub {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;    my $self = shift;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;    my ($source, $data, $prefetch) = @_;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;    return $cdbi-&gt;construct( $data );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;$source-&gt;result_class( $cdbi );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;$schema-&gt;register_source( $tablename =&gt; $source );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Georgia, fantasy; "&gt;And, that's the basic structure. Unfortunately, there are issues. Some of which I'll deal with in later posts, some of which I can't (because they're &lt;i&gt;your&lt;/i&gt; problems).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;One of the biggest reasons to migrate to DBIC is prefetch. You'll notice that our inflate_result doesn't actually do anything with $prefetch. I'll post a better one later.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;&lt;i&gt;add_columns()&lt;/i&gt; can take a lot more information than CDBI ever stored. You'll want to populate that information somehow.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;&lt;i&gt;$tablename &lt;/i&gt;and other variables appeared out of mid-air. You'll want to fix that. :)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;This code doesn't actually do anything for things like unique constraints, defining relationships, and the like. You'll want to fix that, too. :)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;Unless your code is amazingly clean, you probably have snippets like &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$obj-&gt;search(...);&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt; &lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;You may need an AUTOLOAD to catch those (for now).&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:Georgia, -webkit-fantasy;"&gt;And, later on, I'll show you how to migrate your actual objects to DBIx::Class::Row objects from CDBI.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-2881323094169942211?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/2881323094169942211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-6-phase-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/2881323094169942211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/2881323094169942211'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-6-phase-1.html' title='Converting CDBI to DBIC (part 6): Phase 1'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-61554036856037675</id><published>2009-07-15T20:49:00.002-04:00</published><updated>2009-07-15T21:26:33.278-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DBIC CDBI conversion'/><title type='text'>Converting CDBI to DBIC (part 5): The plan- requirements</title><content type='html'>So, in &lt;a href="http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-4-why-not.html"&gt;part 4&lt;/a&gt; of this series, I discussed why CDBICompat just wasn't going to cut it. What I didn't explain in great detail is just &lt;i&gt;why&lt;/i&gt; CDBICompat needs to use tied variables (thus causing a nasty slowdown). It goes something like this:&lt;div&gt;&lt;ol&gt;&lt;li&gt;CDBI has pretty poor searching capabilities&lt;/li&gt;&lt;li&gt;CDBI doesn't have prefetch&lt;/li&gt;&lt;li&gt;CDBI doesn't cache very smartly&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;So, most heavy users of CDBI tend to write their own caching mechanisms. Given that CDBI is a row-centric ORM, these caches are almost always in the row. Given that most of these developers are smart, but under serious time constraints, these caches break encapsulation. So, something like&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  my @rows = CDBI::Class-&gt;search( ... );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', fantasy;"&gt;  foreach my $row ( @rows ) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;      $row-&gt;{_cache} = $row-&gt;expensive_method();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new', -webkit-fantasy;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;is very normal to see. And very expensive to convert away from. Any changeset that converts over every single one of these encapsulation breakages is going to be too huge to test with any confidence. As the applications we're looking at are large (&gt; 100kLOC) and big moneymakers (often $M's per year), having confidence in the next push to production is key.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, the conversion plan has to meet the following requirements:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;allows us to use DBIC's big features - resultsets, prefetch, and SQLA searching.&lt;/li&gt;&lt;li&gt;allows us to phase our conversion so that we don't have massive changesets which are impossible to test.&lt;/li&gt;&lt;li&gt;doesn't impose any noticeable slowdowns, at least not noticeable by the users&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;With any other distribution, that would be a tall order. DBIx::Class, however, already has the single feature we need to make this happen. More on this in part 6.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For those who can't wait, I'll give you a hint. Go look at &lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: medium; "&gt;&lt;h2 class="sr" style="font-size: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "&gt;&lt;b&gt;&lt;a href="http://search.cpan.org/~ribasushi/DBIx-Class-0.08108/lib/DBIx/Class/ResultClass/HashRefInflator.pm" style="background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: transparent; color: rgb(0, 102, 153); background-position: initial initial; "&gt;DBIx::Class::ResultClass::HashRefInflator&lt;/a&gt;.&lt;/b&gt;&lt;/h2&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-61554036856037675?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/61554036856037675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-5-plan.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/61554036856037675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/61554036856037675'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-5-plan.html' title='Converting CDBI to DBIC (part 5): The plan- requirements'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-5121138612494323174</id><published>2009-07-13T21:20:00.003-04:00</published><updated>2009-07-13T22:28:13.172-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CDBI DBIC CDBICompat'/><title type='text'>Converting CDBI to DBIC (part 4): Why not CDBICompat?</title><content type='html'>This isn't the first time someone has tried to convert from one ORM to another. In fact, DBIC grew out of working with CDBI and needing something better. In the past, ORMs have usually been similar enough in their inner workings that a compatibility layer was enough. The userland could be migrated at some later date, if ever. The cost of the indirection would be nearly nothing. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;DBIC, though, is different. So different that a compatibility layer obscures the whole purpose of converting from CDBI to DBIC. The very concept of resultsets breaks the mold. Like, shatters it, stomps all over it, and melts it in a vat of molten iron. The whole point of switching to DBIC is to get access to resultsets. CDBI's API has absolutely no facility to provide access to these features.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Second, you're stuck with CDBI's searching facilities. SQL::Abstract is extremely powerful. So powerful that several CDBI plugins were created to mimic its power. SQL::Abstract v2 will be even more powerful yet. But, CDBICompat cannot expose any of it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And, worse yet, in order to accommodate the numerous abuses of CDBI that most people did in order to make it usable in larger applications, the compat layer ends up being about 20% slower than either raw DBIC or raw CDBI. In fact, the row object provided by CDBICompat is tied just to make sure things work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's the worst of both worlds - you're stuck with CDBI's API (the bad thing you're trying to escape) and a slowdown of your application's code. Given that you're usually trying to &lt;i&gt;speed up&lt;/i&gt; your application and improve the ease of writing new features, this doesn't sound like a win.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next up - the actual solution.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-5121138612494323174?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/5121138612494323174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-4-why-not.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/5121138612494323174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/5121138612494323174'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/converting-cdbi-to-dbic-part-4-why-not.html' title='Converting CDBI to DBIC (part 4): Why not CDBICompat?'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-3831671099260708694</id><published>2009-07-07T21:24:00.002-04:00</published><updated>2009-07-07T21:37:04.357-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='performance correctness'/><title type='text'>Performance vs. Correctness</title><content type='html'>This would seem to be a truism, but it bears repeating. Bertrand Meyer once said &lt;span style="font-style: italic;"&gt;"Correctness is clearly the prime quality.  If a system does not do what it is supposed to do, then everything else about it matters little."&lt;/span&gt; A lot of people seem to forget that if you get the wrong answer very quickly, it's still the wrong answer. And, a lot of those people are in the OSS and Perl communities. A corollary to that could be "Try and do it right. If you can't guarantee the right answer, then fail very quickly and and even louder."&lt;br /&gt;&lt;br /&gt;Why bring this up now? Well, in Perl, performance concerns seem to crop up every so often, and in places where it makes no sense to bring them up. For example, when dealing with crazy date manipulations. DateTime is the de-facto standard for date manipulations in Perl, and for good reason. It is correct and, in most cases, fast. But, its interface is very low level. There is another module that provides different interfaces to dates - Date::Manip. But, even the author acknowledges in the POD that "It's the most powerful of the date modules. It's also the biggest and slowest." And, whenever it's brought up, inevitably someone will say "Yeah, it's pretty heavy."&lt;br /&gt;&lt;br /&gt;My answer to that is "So what?" The &lt;span style="font-weight: bold;"&gt;very first&lt;/span&gt; criterion for a computer program is "Does it work?" And, by that I mean "Is it correct?" Once it's correct (and you have a regression suite to validate that), then you measure its performance. If its overall performance is acceptable, &lt;span style="font-weight: bold;"&gt;then you leave it alone.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let me repeat - &lt;span style="font-weight: bold;"&gt;if overall performance is acceptable, then you leave it alone.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If overall performance needs improved, then you profile it. Chances are, the module you think is heavy isn't your bottleneck. Even if it is, it's very likely that a small change to one method will net you 80% (or more!) of your potential speed improvements.&lt;br /&gt;&lt;br /&gt;Pick modules based on features. Then, if you need it, optimize after profiling. And, module authors, don't refuse to fix a bug because it would hurt performance. If your module is wrong, then it needs to be fixed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-3831671099260708694?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/3831671099260708694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/07/performance-vs-correctness.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3831671099260708694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/3831671099260708694'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/07/performance-vs-correctness.html' title='Performance vs. Correctness'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-4027403113242383088</id><published>2009-06-28T11:48:00.002-04:00</published><updated>2009-07-06T12:39:55.096-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CDBI DBIC components multiple inheritance MI'/><title type='text'>Converting CDBI to DBIC (part 3): Why C3 is important</title><content type='html'>If you want to override any of the methods in CDBI, you have to inherit from CDBI, then override using standard OO methods. With any large application, you end up with the explosion of classes in your hierarchy. More than any other hierarchy, the ORM hierarchy really cries out for roles (or traits). Enough of your tables need to be treated the same in some places, but different in others, that you want to be able to say "for classes A, B, and C, their create() is overrided as &lt;span style="font-style: italic;"&gt;so&lt;/span&gt;, but A and B have their update() overrided as &lt;span style="font-style: italic;"&gt;so&lt;/span&gt;, but B and C have their delete() overrided as &lt;span style="font-style: italic;"&gt;so". &lt;/span&gt;With standard inheritance, it's almost impossible to do that and make it comprehensible for the next developer.&lt;br /&gt;&lt;br /&gt;DBIC, on the other hand, allows you to define capabilities using components. By providing a traits-like solution, you can easily extend the behavior of your Rows and ResultSets in ways that can cross class hierarchy lines. In other words, it's sane multiple-inheritance-like behavior for a very common use-case of multiple inheritance. In our CDBI example above, you would have three components - one each for the create, update, and delete overrides. A, B, and C would all use the create override, A and B use the update override, and B and C use the delete override. Given that each one is likely to be independent (not related to each other), the code becomes more self-documenting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-4027403113242383088?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/4027403113242383088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-3-why-c3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4027403113242383088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/4027403113242383088'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-3-why-c3.html' title='Converting CDBI to DBIC (part 3): Why C3 is important'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-200166446674931335</id><published>2009-06-27T20:46:00.000-04:00</published><updated>2009-06-28T11:49:54.393-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CDBI Class DBI DBIx DBIC conversion convert similarities differences'/><title type='text'>Converting CDBI to DBIC (part 2): The supposed similarities</title><content type='html'>(You can catch &lt;a href="http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-1-context.html"&gt;Part 1&lt;/a&gt; for the context)&lt;br /&gt;&lt;br /&gt;The first thing you notice when comparing CDBI and DBIC is that the APIs look really really similar. They both have the same method names for almost everything most people use them for. So, you'd think that it's as easy as swapping out use statements, adding a few lines to the table definitions, and calling it a day.&lt;br /&gt;&lt;br /&gt;And, unless your application is so exceedingly simple that you were able to keep to the officially published CDBI API, not a single test will pass. (You do have tests, right?) Every problem arises out of the need to have abused CDBI in order to get work done.&lt;br /&gt;&lt;br /&gt;Class::DBI is built upon &lt;a href="http://search.cpan.org/%7Eperrin/Ima-DBI-0.35/lib/Ima/DBI.pm"&gt;Ima::DBI&lt;/a&gt;, a connection caching and SQL management distribution. Every method provided by CDBI is built using Ima::DBI's set_sql() and transform_sql() methods. These methods, while pretty neat, are very hard to extend because they use string transformation.&lt;br /&gt;&lt;br /&gt;DBIx::Class, on the other hand, is built on three major concepts that CDBI doesn't have:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;everything is componentized using C3 method resolution&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SQL::Abstract to generate the SQL&lt;/li&gt;&lt;li&gt;first-class distinction between ResultSets and Rows&lt;/li&gt;&lt;/ul&gt;These three differences mean that what should, in theory, be a simple conversion between two modules that expose similar APIs becomes a much more difficult thing to do. Over the next few posts, I'll examine why each of these differences is important and how each one complicates the conversion process.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-200166446674931335?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/200166446674931335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-2-supposed.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/200166446674931335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/200166446674931335'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-2-supposed.html' title='Converting CDBI to DBIC (part 2): The supposed similarities'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6655636091625157671.post-1838991080005689544</id><published>2009-06-26T22:35:00.001-04:00</published><updated>2009-06-28T11:50:47.663-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='class dbi dbix converting'/><title type='text'>Converting CDBI to DBIC (part 1): The context</title><content type='html'>For years, &lt;a href="http://search.cpan.org/%7Etmtm/Class-DBI-v3.0.17/lib/Class/DBI.pm"&gt;Class::DBI&lt;/a&gt; was the gold standard ORM in the Perl community, and for good reason. It was simple to deploy, easy to use, and, for the most part, dwim'ed. Oh, we Perlers love our dwimmery. If it doesn't dwim, then we get pissy.&lt;br /&gt;&lt;br /&gt;Now, CDBI wasn't designed like Perl. Perl has always been built to make the hard things easy and the impossible merely hard. CDBI, on the other hand, was designed with the 80/20 rule in mind - make as many of the things most people do every day extremely easy. And, for everything else, there's always an easy way to get to use raw SQL. And this was, for most people, good enough. It easily supported rapid prototyping and small applications and, while slighly annoying on the edges, it worked.&lt;br /&gt;&lt;br /&gt;But, as applications are wont to do, some of those applications grew up. They didn't stay small or fade away. The schemas grew from 5 or 10 tables to monstrosities of 250 tables or more, many having dozens of columns. The codebases weighed in at well over hundreds of thousands of lines of code. And, instead of building the code, the focus became maintenance. And, those things that were rare in the past became more common. Not relatively more common, but appeared more often. Instead of 3 or 4 dips into raw SQL, there were 90 or 100. And, wow, was scaling an issue.&lt;br /&gt;&lt;br /&gt;Many ORMs were built to try and take its place. Lots of good work was done, but the gold standard has seemed to settle around to &lt;a href="http://search.cpan.org/%7Eribasushi/DBIx-Class-0.08107/lib/DBIx/Class.pm"&gt;DBIx::Class&lt;/a&gt;, and for good reason. DBIC maintains that 80/20 design philosophy, but manages to marry it to the Perl philosophy of making hard things easy.&lt;br /&gt;&lt;br /&gt;Unlike CDBI, DBIC uses &lt;a href="http://search.cpan.org/%7Eribasushi/SQL-Abstract-1.56/lib/SQL/Abstract.pm"&gt;SQL::Abstract&lt;/a&gt; for its SQL generation, meaning less dips into raw SQL. Scaling is saner because lessons were learned. Yet, all the really easy things are still really easy. Rapid prototyping is still rapid.&lt;br /&gt;&lt;br /&gt;And, this is why we want to convert.&lt;br /&gt;&lt;br /&gt;(Follow on in &lt;a href="http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-2-supposed.html"&gt;Part 2&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6655636091625157671-1838991080005689544?l=robonperl.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://robonperl.blogspot.com/feeds/1838991080005689544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-1-context.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/1838991080005689544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6655636091625157671/posts/default/1838991080005689544'/><link rel='alternate' type='text/html' href='http://robonperl.blogspot.com/2009/06/converting-cdbi-to-dbic-part-1-context.html' title='Converting CDBI to DBIC (part 1): The context'/><author><name>Rob</name><uri>http://www.blogger.com/profile/07966252008096453177</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://4.bp.blogspot.com/__in5Y8EvERI/S3Nmcci5yAI/AAAAAAAAAAM/q1ugcKlvBPQ/S220/RobKinyon.png'/></author><thr:total>0</thr:total></entry></feed>
