<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Grabbing Hanuman's Long Tail</title>
	<atom:link href="http://pajamadesign.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://pajamadesign.com</link>
	<description>Jacob Singh</description>
	<pubDate>Thu, 03 Jul 2008 05:58:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>Helpers_user: The user API that never was</title>
		<link>http://pajamadesign.com/2008/07/03/helpers_user-the-user-api-that-never-was/</link>
		<comments>http://pajamadesign.com/2008/07/03/helpers_user-the-user-api-that-never-was/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 05:58:49 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Drupal]]></category>

		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[api]]></category>

		<category><![CDATA[helpers]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=17</guid>
		<description><![CDATA[I was writing an install profile for a out-of-the-box workflow install profile to be used by media organizations today, when I ran into the rote task of adding roles and permissions.
(for reference, see my last article on workflow configuration in drupal)
So being the programmer who will write something in a day which takes an hour [...]]]></description>
			<content:encoded><![CDATA[<p>I was writing an install profile for a out-of-the-box workflow install profile to be used by media organizations today, when I ran into the rote task of adding roles and permissions.</p>
<p>(for reference, see my last article on <a href="http://pajamadesign.com/2008/04/24/advanced-workflow-configuration-for-drupal/">workflow configuration in drupal</a>)</p>
<p>So being the programmer who will write something in a day which takes an hour to run to save 5 minutes, I decided to scratch a long standing itch:</p>
<p>The Drupal User System API.</p>
<p>I love the simplicity of the drupal user system, but like many things in drupal, it wants you to use forms to admin it, and the DB model is inherently tied to the controller (not good).</p>
<p>So I decided to contribute this to the <a href="http://drupal.org/project/helpers">helpers</a> module.  It provides some simple functions like:</p>
<p>helpers_user_help($section)<br />
permissions_get(unknown_type $rid)<br />
permissions_set(unknown_type $rid, unknown_type $perms = array)<br />
role_add(string $name)<br />
role_get(int $rid = 0, string $name = &#8220;&#8221;)<br />
user_add_roles($uid, $roles = array)<br />
user_delete_roles($uid, $roles = array)</p>
<p>Simple stuff, but AFAIK, lacking in drupal.</p>
<p>In addition, I also wrote a full set of simplete tests for it which can be found in the tests directory.</p>
<p>The patch can be found at:<br />
http://drupal.org/node/252058<br />
Hope others find this helpful!</p>
<p>-Jacob</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/07/03/helpers_user-the-user-api-that-never-was/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Solving bad IA using enterprise search (Reverse Advanced Search)</title>
		<link>http://pajamadesign.com/2008/07/01/solving-bad-ia-using-enterprise-search-reverse-advanced-search/</link>
		<comments>http://pajamadesign.com/2008/07/01/solving-bad-ia-using-enterprise-search-reverse-advanced-search/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 05:32:41 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Drupal]]></category>

		<category><![CDATA[Solr]]></category>

		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[faceted search]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=30</guid>
		<description><![CDATA[Since I started working with Apache Solr in Drupal, I&#8217;ve realized how much client money has been wasted making ill advised advanced searches.  We&#8217;ve all gotten the requests for &#8220;advanced&#8221; searches and it makes any IA-god fearing developer cringe.  For the 1% of users who use them, you blow tons of budget, and [...]]]></description>
			<content:encoded><![CDATA[<p>Since I started working with Apache Solr in Drupal, I&#8217;ve realized how much client money has been wasted making ill advised advanced searches.  We&#8217;ve all gotten the requests for &#8220;advanced&#8221; searches and it makes any IA-god fearing developer cringe.  For the 1% of users who use them, you blow tons of budget, and the result is often quite poor because the client doesn&#8217;t really know their data or their users that well.</p>
<p>For those of you who are unfamiliar with faceted search compare the following:</p>
<p>I did a search for WSXGA because I&#8217;m looking for a laptop with decent resolution on two sites.</p>
<p><a href="http://www.laptopsdirect.co.uk/asp/searchSite.asp?mode=2&#038;keywords=WSXGA&#038;submit=">Laptops Direct</a></p>
<p>vs.</p>
<p><a href="http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&#038;DEPA=0&#038;Description=WSXGA&#038;x=0&#038;y=0"> New Egg </a></p>
<p>(click to enlarge image in new window)<br />
<a href='http://pajamadesign.com/wp-content/uploads/2008/06/newegg_ld_compare.jpeg' target="_blank"><img src="http://pajamadesign.com/wp-content/uploads/2008/06/newegg_ld_compare.jpeg" alt="" title="newegg_ld_compare"  width="300px" class="aligncenter wp-image-31" /></a></p>
<p>The New Egg search lets me filter, so I know that I&#8217;m looking for a laptop between $750 -> $1000, I&#8217;ll get 5 results.  After that filter, I&#8217;ll know what&#8217;s available, and the # per manufacturer etc.</p>
<p>Contrast that with an advanced search form where I have to put in all my criteria, and hope I get a result.  I might also miss certain results if my vocabulary is bad, or I don&#8217;t understand that the website says &#8220;high resolution&#8221; instead of WSXGA, so I don&#8217;t select it.</p>
<p>I think it&#8217;s obvious to anyone why faceted search is a good thing.  In my next post, I&#8217;ll be exploring why is hasn&#8217;t gotten widespread adoption, particularly in the small business / NGO sector, and how I plan to help change that.</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/07/01/solving-bad-ia-using-enterprise-search-reverse-advanced-search/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Similar Nodes Module Released!</title>
		<link>http://pajamadesign.com/2008/06/30/similar-nodes-module-released/</link>
		<comments>http://pajamadesign.com/2008/06/30/similar-nodes-module-released/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 14:55:59 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Drupal]]></category>

		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=21</guid>
		<description><![CDATA[I&#8217;ve just released a new module which I hope will fill a general need in the Drupal community.
This module allows you to show nodes in a view which have the same taxonomy as a node which you pass in as an argument.  BUT it goes a step beyond this.  By using a weighting [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released a new module which I hope will fill a general need in the Drupal community.</p>
<p>This module allows you to show nodes in a view which have the same taxonomy as a node which you pass in as an argument.  BUT it goes a step beyond this.  By using a weighting table, one can specify the weight of each vocabulary in making the comparison.</p>
<blockquote><p>Say you have two vocabularies on a movie site &#8220;Genre&#8221; and &#8220;Community Tags&#8221;, the latter being a free tagging taxonomy. With this module, you can give Genre a weight of 10 and Community tags a weight of 1. Which means that if I&#8217;m looking at &#8220;Meet the Parents&#8221;, I&#8217;m most likely to see a list of similar Romantic Comedies like &#8220;Sleepless in Seattle&#8221; and &#8220;French Kiss&#8221; with something like &#8220;Taxi&#8221; or &#8220;The Godfather II&#8221; coming lower in the list, because someone tagged both &#8220;Robert De niro&#8221;</p></blockquote>
<p>See the <a href="http://drupal.org/project/similarnodes"> Module Page </a> for more information and how to use.</p>
<p>I&#8217;m going to be cleaning up the code a bit and providing a sample view soon, but any brave souls out there who would like to test / suggest, please go ahead!</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/30/similar-nodes-module-released/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Solving bad IA using enterprise search (Vocabulary)</title>
		<link>http://pajamadesign.com/2008/06/30/apache-solr-based-cms-vocabulary/</link>
		<comments>http://pajamadesign.com/2008/06/30/apache-solr-based-cms-vocabulary/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 04:21:55 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Solr]]></category>

		<category><![CDATA[information architechture]]></category>

		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=28</guid>
		<description><![CDATA[Long time no blog&#8230;
I had a bit of a realization (or rather a resurgence of a recurring realization) that I enjoy writing.  It happened this weekend as I was &#8220;getting away from  it  all&#8221;.  
I&#8217;ve been interested in enterprise search for small and medium enterprises for a while now.  Having [...]]]></description>
			<content:encoded><![CDATA[<p>Long time no blog&#8230;</p>
<p>I had a bit of a realization (or rather a resurgence of a recurring realization) that I enjoy writing.  It happened this weekend as I was &#8220;getting away from <em> it </em> all&#8221;.  </p>
<p>I&#8217;ve been interested in enterprise search for small and medium enterprises for a while now.  Having implemented the Google Mini and the GSA, I&#8217;ve seen how a good search can really turn your information architecture on its head in a good way.  Like any conversation between two entities be they two people or a person and a website, communication is difficult, and many of the same rules apply:</p>
<h2> Vocabulary </h2>
<p>You have to speak the same language.   This doesn&#8217;t mean an Thai can&#8217;t talk to a Nigerian, but it does mean that when you are communicating, if the same word doesn&#8217;t mean the same thing (which it never does), your intentions, delivery and content is worthless.  That is why non-verbal communication and communication over phones is so ineffective compared to face to face meetings.  The words may be the same, but the interpretation never is.</p>
<p>So what does this have to do with enterprise search?  When a user wants something from your website, they are looking for a keyword.  Many computer scientists have tried to make linguistic aware search engines which correctly interpret sentences and question.  Some of these results are useful, but generally, I believe people don&#8217;t come to a site thinking &#8220;Do you have any
<ul>red Toyota Corolla</ul>
<p>.&#8221;  Internally, they are simply thinking &#8220;Corolla&#8221; and &#8220;Red&#8221;.  For instance, I could speak only two words of English, Red and Corolla, and chances are, I could walk into any American City and rent a red Toyota Corolla.  </p>
<p>When one plans information architecture for a site, they usually start with Persona or stereotypes of users, which have goals.  And then you define actions they take to meet those goals, and try to use the same vocabulary and thought process of these users to make an interface which is organized like their brain.  But when you have 10 different Persona, how is this possible?  And within your 10 stereotypes, there can be huge variation and outside of your assumptions, there may be other users you never thought about.  By having an good search engine, even if you have one page about red Mustangs which is buried in your site, people might find it.  By having an excellent search engine which has synonyms, facets, spell checking, related results, etc you may be able to help the user not only find what they thought they were looking for, but contextual information about it.  What if there is a mechanic looking for parts who types in
<ul>1988 Corolla Fuel Pump</ul>
<p> into a search, shouldn&#8217;t the search engine know what years the fuel pumps for Corollas available are the same and available, and allow him to filter?  Shouldn&#8217;t it know that in the late eighties the Chevy Nova was a clone of the Corolla, and had the same parts cheaper?</p>
<p>This is the type of high value information which comes from dealing with a real human, and no amount of brilliant forethought in information architecture can pre-assume what the person is actually looking for.  If I were doing IA for a parts website sans search, I&#8217;d have to have categories by model, by year, etc Even in a straightforward example like that, value is lost.  That&#8217;s why search engines need to ask the extra question, and today&#8217;s search engines that most sites use are not.</p>
<h2> Faceted Search </h2>
<p>Next whenever, I&#8217;ll write something about faceted search (fancy name for search with fields and filters) and how I think the combination of Apache Solr and open source CMSs like Drupal, Typo3 and Joomla, are going to pave the way to an entirely new concept of information architecture and where we spend out usability testing money. </p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/30/apache-solr-based-cms-vocabulary/feed/</wfw:commentRss>
		</item>
		<item>
		<title>the t() that took down a webserver</title>
		<link>http://pajamadesign.com/2008/06/29/the-t-that-took-down-a-webserver/</link>
		<comments>http://pajamadesign.com/2008/06/29/the-t-that-took-down-a-webserver/#comments</comments>
		<pubDate>Sun, 29 Jun 2008 06:54:25 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Drupal]]></category>

		<category><![CDATA[high performance]]></category>

		<category><![CDATA[i18n]]></category>

		<category><![CDATA[locale]]></category>

		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=20</guid>
		<description><![CDATA[Hey folks,
I feel compelled to announce this.  Please Please Please read this post if you have done any multilingual drupal development.
Do not use t() outside of a hook or before locale gets to build its cache
I was asked to do some profiling on a colleague&#8217;s site, and I found this little doozy in the [...]]]></description>
			<content:encoded><![CDATA[<p>Hey folks,</p>
<p>I feel compelled to announce this.  Please Please Please read this post if you have done any multilingual drupal development.</p>
<blockquote><p><strong>Do not</strong> use t() outside of a hook or before locale gets to build its cache</p></blockquote>
<p>I was asked to do some profiling on a colleague&#8217;s site, and I found this little doozy in the location_views module:</p>
<p>http://drupal.org/node/253813</p>
<p>The offending line is:</p>
<pre><code> define('LOCATION_VIEWS_UNKNOWN', t('unknown')); </code></pre>
<p>Okay, so what is the problem?  When drupal starts up, it runs through many &#8220;bootstrappping states&#8221;:</p>
<h3> Booting Drupal&#8217;s locale module </h3>
<p>The last one is:</p>
<pre>
<code>

 case DRUPAL_BOOTSTRAP_FULL:
      require_once './includes/common.inc';
      _drupal_bootstrap_full();
      break;
  }
</code>
</pre>
<p>Now let&#8217;s look at the end of _drupal_bootstap_full:</p>
<pre>
<code>
// Load all enabled modules
  module_load_all();
  // Initialize the localization system.  Depends on i18n.module being loaded already.
  $locale = locale_initialize();
</code></pre>
<p>So the modules are getting loaded - module_load_all (they are included) before the locale module is initialized.  In location_views, the offending statement is just interpreted upon inclusion because it isn&#8217;t wrapped in any hook.  So it gets called before the locale_initialize() function.  </p>
<p>This last call $locale = locale_initialize() sets to the global $locale variable to the iso language code the user is looking at the site in.  If it is not set, see what happens when someone calls t():</p>
<pre>
<code>
function t($string, $args = 0) {
  global $locale;
  if (function_exists('locale') &#038;&#038; $locale != 'en') {
    $string = locale($string);
  }

.......
</code>
</pre>
<p>Okay, so look at the first conditional.  This will obviously return true every time, because locale is == to null when a module uses t() before locale is initialized.  So if we dig into locale, what do we see:</p>
<pre>
<code>

function locale($string) {
  global $locale;
  static $locale_t;

  // Store database cached translations in a static var.
  if (!isset($locale_t)) {
    $cache = cache_get("locale:$locale", 'cache');

    if (!$cache) {
      locale_refresh_cache();
      $cache = cache_get("locale:$locale", 'cache');
    }
    $locale_t = unserialize($cache->data);
  }

</code>
</pre>
<p>So what happens?</p>
<p>We get here, because locale_t doesn&#8217;t exist yet: </p>
<pre><code>$cache = cache_get("locale:$locale", 'cache');</code></pre>
<p>We are trying to get a cache for &#8220;locale:&#8221;.  Obviously, this does not exist.  Because of this, locale says, okay, let&#8217;s refresh the cache.</p>
<h3> The locale cache </h3>
<p>The locale cache is a massive serialized array of strings and their matches from locales_source and locales_target.  Let&#8217;s see how it is formed:</p>
<pre>
<code>
function locale_refresh_cache() {
  $languages = locale_supported_languages();

  foreach (array_keys($languages['name']) as $locale) {
    $result = db_query("SELECT s.source, t.translation, t.locale FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid WHERE t.locale = '%s' AND LENGTH(s.source) < 75", $locale);
    $t = array();
    while ($data = db_fetch_object($result)) {
      $t[$data->source] = (empty($data->translation) ? TRUE : $data->translation);
    }
    cache_set(&#8221;locale:$locale&#8221;, &#8216;cache&#8217;, serialize($t));
  }
}
</code>
</pre>
<p><strong>OUCH!</strong></p>
<p>This loops through each available language, and does a join selecting every string from locales source and locales target.  It then builds a massive array (the bigger the translated site, the bigger the array) which eats up a huge amount of RAM - For reference, on http://www.amnesty.org, we&#8217;ve got over 10k translated strings, so we&#8217;re talking a few MB.</p>
<p>Then it serializes the whole thing - which uses a good amount of CPU, and then cache_set writes it to the cache table.</p>
<p>That&#8217;s where it gets really bad.  When cache_set makes a write to the cache table.  It first runs<br />
LOCK TABLES cache;<br />
then INSERT INTO cache&#8230;</p>
<p>So the cache table is effectively frozen up for anyone who wants to get data or put data into it.  So think about this.  If you have a 3MB locale cache array you are inserting into cache, and it takes 200ms to make that insert, any other user trying to access the site who wants to make queries to cache for variables is in line.  </p>
<p>This creates a cascading effect where other processes which could have finished quickly are now holding up RAM in apache, waiting for access to the DB.  If your server isn&#8217;t fast enough, this basically runs mysql&#8217;s process limit up to it&#8217;s max, and people start being unable to connect, the DB server gets partial inserts, deadlocks, all kinds of ugly stuff.</p>
<p>What&#8217;s worse, if t() is used outside of a hook, it will fire on EVERY page load.  So on the site I was doing the profiling for, it uses a lot of AJAX.  So every AJAX request was actually running this massive insert as well!</p>
<p>In xdebug, running on my sandbox, I was able to bring the avg page load time down from about 3-4seconds to 300-500ms by the simple patch referenced above.</p>
<h3> Conclusion </h3>
<ul>
<li>Don&#8217;t ever run t() outside of a hook</li>
<li> Don&#8217;t ever run t() on non-static strings (if you have enough of them, this same thing will happen every time a new one appears in the system </li>
<li> Watch out for cache_sets in your application.  They can be a real silent killer.  Everything will work fine, but you are killing yourself performance wise.  I suggest using xdebug, and if nothing else, go into cache_set, and add debug_print_backtrace(); to just see everyone who is using it.
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/29/the-t-that-took-down-a-webserver/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Media Mover Workflow needs</title>
		<link>http://pajamadesign.com/2008/06/28/media-mover-workflow-needs/</link>
		<comments>http://pajamadesign.com/2008/06/28/media-mover-workflow-needs/#comments</comments>
		<pubDate>Sat, 28 Jun 2008 04:33:24 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Drupal]]></category>

		<category><![CDATA[asset]]></category>

		<category><![CDATA[media mover]]></category>

		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=12</guid>
		<description><![CDATA[I&#8217;ve been playing around with Media Mover this week for Arthur with the goal of improving the general use cases for the community and giving some code review.
For those who don&#8217;t know, here is an excerpt from the project page of media mover:
Media Mover is a set of modules which allows website administrators to easily [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing around with <a href="http://drupal.org/project/media_mover">Media Mover</a> this week for <a href="http://www.24b6.net/">Arthur</a> with the goal of improving the general use cases for the community and giving some code review.</p>
<p>For those who don&#8217;t know, here is an excerpt from the project page of media mover:</p>
<blockquote><p>Media Mover is a set of modules which allows website administrators to easily create complex file conversion processes. The core of Media Mover is the media_mover_api module which creates a set of rules allowing multiple modules to interact with a file. Media Mover can take a file emailed to an email account, turn a file attachment into an FLV file, create a new node with the file data, and then save the file on an external file storage like Amazon&#8217;s S3 all at once. And that&#8217;s just the start.</p></blockquote>
<p>Wow!  So does mm live up the hype?  Of course.  Arthur wrote it. <img src='http://pajamadesign.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>What I&#8217;ve been looking into the integration of Media Mover with <a href="http://drupal.org/project/workflow_ng">workflow-ng</a> and <a href="http://drupal.org/project/asset">asset</a>.  Media Mover&#8217;s strengths right now are harvesting from multiple sources like ftp servers, email accounts, local stores, etc&#8230; and processing the video / audio / image via ffmpeg.</p>
<p>I&#8217;d say the main weakness it has is a drupal waekness, and that is how do files exist in the drupal node paradigm?  Where is their meta-data stored?</p>
<p>There are so many different ways people do this task, generally with modules like image or video (which is basically file as a node).  Or with modules like videofield, imagefield, etc which is file in files table, and a reference from a CCK field.</p>
<p>This kinda works, but asset provides a much more robust media integration framework, wherein an asset has metadata, it has formatting options and it can be embeded in the text body, or attached as a cck value.</p>
<p>The first goal of the integration is use the store hook in media mover to store the incoming media as an asset.  Secondly, we&#8217;re going to build a store function to create a new node, and place the asset in a CCK field for that node.</p>
<p>The ultimate scenario is to create multiple assets for multiple processing instructions, so we have a folder of low res videos and a folder of high res videos, and we are automagically somehow adding the created assets to CCK fields (think I have a store selling video, and I have a &#8220;preview&#8221; CCK asset field and a &#8220;full version&#8221; CCK asset field).</p>
<p>There is inherent data model problems here both with asset and MM, but let&#8217;s see what we can do.</p>
<p>More next week when I&#8217;ve written the module, but if any Media Mover users are reading this, how is your experience with MM?  What do you perceive as its lackings (if any) and what can be done to make it simpler / more intuitive for you?</p>
<p>-J</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/28/media-mover-workflow-needs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Good Bye Appendix, Hello Google App Engine</title>
		<link>http://pajamadesign.com/2008/06/27/good-bye-appendix-hello-google-app-engine/</link>
		<comments>http://pajamadesign.com/2008/06/27/good-bye-appendix-hello-google-app-engine/#comments</comments>
		<pubDate>Fri, 27 Jun 2008 04:00:37 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[business]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[google app engine]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=22</guid>
		<description><![CDATA[While an appendicitis is a painful, uncomfortable and ultimately debilitating condition - one which I have suffered with for over a year, its remedy (Laproscopic surgery, way too much money to an evil hospital, a shitton of painkillers and a week of bedrest) is fairly tame as far as surgical procedures go.
PHPitis is another condition [...]]]></description>
			<content:encoded><![CDATA[<p>While an appendicitis is a painful, uncomfortable and ultimately debilitating condition - one which I have suffered with for over a year, its remedy (Laproscopic surgery, way too much money to an evil hospital, a shitton of painkillers and a week of bedrest) is fairly tame as far as surgical procedures go.</p>
<p>PHPitis is another condition I have been suffering from.  It&#8217;s not early as painful and has provided me with a decent income and professional growth.  It is also not a pussy inflamed organ with no apparent value pressing up against all the nicely formed and functioning organs around it.  However, the feeling that there is something not right &#8220;down there&#8221; remains.</p>
<p>I&#8217;ve always known that python is the best language out there.  I don&#8217;t mean to start yet another stupid language fight, because every language is fine and dandy.  But honestly, every programmer I respect has told me the same thing, they wish they could just write python.  The only knocks against python are:</p>
<ul>
<li> Lack of hosting options</li>
<li> Lack of Jobs / Skilled personnel</li>
</ul>
<p>The first one, is obviously stupid, because it is as easy to run as PHP, but is totally chicken and egg.  The second is pretty much the same.  You have to be a better programmer to write python, and so there are less people who can, so there are less CTOs wanting to risk a language with less people available.</p>
<p>Anyway, for what it&#8217;s worth, I love python, and I&#8217;m not that good at it yet, because I never get jobs in it, and it&#8217;s hard to get clients signed up for something that isn&#8217;t hosted anywhere&#8230;. Until now.</p>
<p>A day before I went to the hospital for an examination into yet another bout of my awful stomach pains which turned into the aforementioned surgery, I got my <a href="http://appengine.google.com">App Engine</a> key in the mail. </p>
<p>I am affraid of the big G as much as anyone, and this offering is too new to judge.  I won&#8217;t bore everyone with the questions everyone is asking about if your code can be moved or not, what is the guarantee they will keep it around, etc.  I just want to say that the data api and the security of knowing that such terse syntax with so much power will scale till the end of the googleverse is exciting.</p>
<p>I highly recommend everyone give it a whirl, and discover / rediscover beautiful code.  I was thinking of &#8220;killer apps&#8221; to build on it.  My first inclination is that the &#8220;killer app&#8221; for the gapjinn (as I have now started calling it) is something with the following characteristics:</p>
<h2> Uses Google Apps data apis </h2>
<p>As much as possible, the application should store it&#8217;s data in google sites, google docs, google calendar, etc.  This is because google will always have a commitment to making these two platforms work together AND you will not be made irrelevant because you can&#8217;t integrate.</p>
<h2> Uses Google Apps provisioning APIs </h2>
<p>Because SaaS is in, and you will want to make setup super easy.</p>
<h2> Uses Google for authentication </h2>
<p>Because you will not survive in the enterprise if you can&#8217;t take advantage of single sign-on services.  As long as you are using all the google apps stuff, you should authenticate the same way.</p>
<h2> Is niche enough that it does something better / easier / more focused than native google apps <br />
OR<br />
<br />
Provides an integration between different google apps and a 3rd party service<br />
</h2>
<p>On the first count, it&#8217;s about creating a wrapper, basically a new interface layer to an existing google apps platform.  Sometimes simple is too simple.  For instance, using a series of tags and and a small amount of data store in the Google BigTable, I bet you create a really quick and dirty CRM using google contacts + gmail + google sites + google calendar.</p>
<p>On the second, I think the potential to provide bridge functionality between more mature best of breed apps like <a href="http://37signals.com">basecamp</a>, <a href="http://unfuddled.com">unfuddled<a />, salesforce, will make quick enterprise dashboards possible.  Something like a dashboard / middleware layer between this stuff.</p>
<p>Let&#8217;s see&#8230;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/27/good-bye-appendix-hello-google-app-engine/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Awesome SVN training materials under CC</title>
		<link>http://pajamadesign.com/2008/06/02/awesome-svn-training-materials-under-cc/</link>
		<comments>http://pajamadesign.com/2008/06/02/awesome-svn-training-materials-under-cc/#comments</comments>
		<pubDate>Mon, 02 Jun 2008 06:15:39 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[training]]></category>

		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=27</guid>
		<description><![CDATA[I&#8217;m doing a training for Srijan this week with their developers on good version control and change management practices, and while googling around I ran into this:
http://www.polarion.org/index.php?page=overview&#038;project=subtrain
It is a fantastic set of training materials generously provided under CC 2.5 by Polarion.org.
it features ppts for admins as well as users, evaluation and feedback materials, as well [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m doing a training for <a href="http://srijan.in">Srijan</a> this week with their developers on good version control and change management practices, and while googling around I ran into this:</p>
<p><a href="http://www.polarion.org/index.php?page=overview&#038;project=subtrain">http://www.polarion.org/index.php?page=overview&#038;project=subtrain</a></p>
<p>It is a fantastic set of training materials generously provided under CC 2.5 by Polarion.org.</p>
<p>it features ppts for admins as well as users, evaluation and feedback materials, as well as sets of exercises to simulate normal working environments.  I can&#8217;t say enough about these materials, they are really top notch.</p>
<p>Major cred goes to the good folks providing them.  Please check them out!</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/06/02/awesome-svn-training-materials-under-cc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Drupal Training Curriculum</title>
		<link>http://pajamadesign.com/2008/05/20/drupal-curriculum/</link>
		<comments>http://pajamadesign.com/2008/05/20/drupal-curriculum/#comments</comments>
		<pubDate>Mon, 19 May 2008 18:37:29 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/2008/05/20/26/</guid>
		<description><![CDATA[ 
Getting Started
Who are we and what are we doing here? Backgrounds and goals (personal and technical).


Get to know 	everyone&#8217;s development background and professional history


Where do we come 	from as programmers?  How does that influence our current approach 	and approach to learning drupal?


What do we want to 	learn and specialize in?


General goals of this [...]]]></description>
			<content:encoded><![CDATA[<p id="h4se0" class="western" style="margin-bottom: 0in;"><br id="h4se1"/> </p>
<h2 id="h4se2" class="western">Getting Started</h2>
<h3 id="h4se3" class="western">Who are we and what are we doing here? Backgrounds and goals (personal and technical).</h3>
<ul id="h4se4">
<li id="h4se5">
<p id="h4se6" class="western">Get to know 	everyone&#8217;s development background and professional history</p>
</li>
<li id="h4se7">
<p id="h4se8" class="western">Where do we come 	from as programmers?  How does that influence our current approach 	and approach to learning drupal?</p>
</li>
<li id="h4se9">
<p id="h4se10" class="western">What do we want to 	learn and specialize in?</p>
</li>
</ul>
<h3 id="h4se11" class="western">General goals of this training</h3>
<ul id="h4se12">
<li id="h4se13">
<p id="h4se14" class="western">Make developing in Drupal fun</p>
</li>
<li id="h4se15">
<p id="h4se16" class="western">Increase the speed at which you can develop 	solutions</p>
</li>
<li id="h4se17">
<p id="h4se18" class="western">Decrease the amount of time you have to spend 	on donkey work</p>
</li>
<li id="h4se19">
<p id="h4se20" class="western">Introduce you to the Drupal community and how 	to leverage / participate in it</p>
</li>
<li id="h4se21">
<p id="h4se22" class="western">Make the connections between requirements and 	stock solutions</p>
</li>
<li id="h4se23">
<p id="h4se24" class="western">Know how and when to hack it</p>
</li>
</ul>
<p id="h4se25" class="western"><br id="h4se26"/> <br id="h4se27"/> </p>
<h3 id="h4se28" class="western">Specific Objectives for today</h3>
<ul id="h4se29">
<li id="h4se30">
<p id="h4se31" class="western">Know how to set up drupal sites using 	multisite deployment</p>
</li>
<li id="h4se32">
<p id="h4se33" class="western">Understand how to use update status, CVS and 	drush</p>
</li>
<li id="h4se34">
<p id="h4se35" class="western"><a id="h4se36" name="DDE_LINK1"></a>Learn the devel 	module, masquerade module, and other development tools</p>
</li>
<li id="h4se37">
<p id="h4se38" class="western">Understand the drupal architecture:</p>
<ul id="h4se39">
<li id="h4se40">
<p id="h4se41" class="western">What IOC is</p>
</li>
<li id="h4se42">
<p id="h4se43" class="western">Why is successful</p>
</li>
<li id="h4se44">
<p id="h4se45" class="western">Why is it annoying</p>
</li>
</ul>
</li>
</ul>
<h3 id="h4se46" class="western">Planned Format</h3>
<ul id="h4se47">
<li id="h4se48">
<p id="h4se49" class="western">Devs spend as much time in front of computers 	practicing as possible</p>
</li>
<li id="h4se50">
<p id="h4se51" class="western">Topics are discussed, examples are shown in 	existing modules, and practice on a custom module</p>
</li>
<li id="h4se52">
<p id="h4se53" class="western">Every days ends with ½hr of Q&amp;A</p>
</li>
</ul>
<h2 id="h4se54" class="western">Tools of the trade</h2>
<ul id="h4se55">
<li id="h4se56">
<p id="h4se57" class="western">Devel Module</p>
</li>
<li id="h4se58">
<p id="h4se59" class="western">Coder</p>
</li>
<li id="h4se60">
<p id="h4se61" class="western">Masquerade</p>
</li>
<li id="h4se62">
<p id="h4se63" class="western">Project Set-Up and sandbox creation</p>
</li>
<li id="h4se64">
<p id="h4se65" class="western">admin_menu</p>
</li>
<li id="h4se66">
<p id="h4se67" class="western">Drush, CVS and update_status</p>
</li>
</ul>
<h2 id="h4se68" class="western">The Drupal Community</h2>
<ul id="h4se69">
<li id="h4se70">
<p id="h4se71" class="western">IRC</p>
</li>
<li id="h4se72">
<p id="h4se73" class="western">Issue Trackers</p>
</li>
<li id="h4se74">
<p id="h4se75" class="western">groups.drupal.org</p>
</li>
<li id="h4se76">
<p id="h4se77" class="western">Forums</p>
</li>
<li id="h4se78">
<p id="h4se79" class="western">drupalmodules.com</p>
</li>
<li id="h4se80">
<p id="h4se81" class="western">drupal.org/planet</p>
</li>
</ul>
<h2 id="h4se82" class="western">Drupal Architecture</h2>
<ul id="h4se83">
<li id="h4se84">
<p id="h4se85" class="western">IOC (Inversion of control model)</p>
</li>
<li id="h4se86">
<p id="h4se87" class="western">The Hook system</p>
</li>
<li id="h4se88">
<p id="h4se89" class="western">Drupal Bootsrap process</p>
</li>
<li id="h4se90">
<p id="h4se91" class="western">Theming Engines and themes</p>
</li>
</ul>
<p id="h4se92" class="western"><br id="h4se93"/> <br id="h4se94"/> </p>
<h2 id="h4se95" class="western">Tea Party</h2>
<ul id="h4se96">
<li id="h4se97">
<p id="h4se98" class="western">Learning the hook system via the drink module</p>
</li>
</ul>
<h2 id="h4se99" class="western">Main Core Hooks and their usage</h2>
<p id="h4se100" class="western"><font id="h4se101" color="#000080"><u id="h4se102"><a id="h4se103" href="http://api.drupal.org/api/group/hooks/5">http://api.drupal.org/api/group/hooks/5</a></u></font></p>
<h3 id="h4se104" class="western">hook_menu</h3>
<p id="h4se105" class="western">Example: contact</p>
<h3 id="h4se106" class="western">hook_nodeapi</h3>
<p id="h4se107" class="western">Example: path module</p>
<h3 id="h4se108" class="western">hook_help</h3>
<p id="h4se109" class="western">Example: contact module</p>
<h3 id="h4se110" class="western">hook_user</h3>
<p id="h4se111" class="western">Example: contact module</p>
<h2 id="h4se112" class="western"></h2>
<h2 id="h4se113" class="western" style="page-break-before: always;">To Hack or Not to Hack, that is the question</h2>
<h2 id="h4se114" class="western">Form API</h2>
<h3 id="h4se115" class="western">Building an admin settings form</h3>
<ul id="h4se116">
<li id="h4se117">
<p id="h4se118" class="western">callback to drupal_get_form</p>
</li>
<li id="h4se119">
<p id="h4se120" class="western">validate hook</p>
</li>
<li id="h4se121">
<p id="h4se122" class="western">submit hook</p>
</li>
</ul>
<h3 id="h4se123" class="western">Implementing form_alter</h3>
<h3 id="h4se124" class="western">Implementing a custom submit hook on a form_alter</h3>
<h2 id="h4se125" class="western">Real site planning and development in Drupal</h2>
<h3 id="h4se126" class="western">Modules you can&#8217;t live without</h3>
<ul id="h4se127">
<li id="h4se128">
<p id="h4se129" class="western">CCK</p>
</li>
<li id="h4se130">
<p id="h4se131" class="western">Views</p>
</li>
<li id="h4se132">
<p id="h4se133" class="western">Panels 2</p>
</li>
<li id="h4se134">
<p id="h4se135" class="western">nodequeue</p>
</li>
<li id="h4se136">
<p id="h4se137" class="western">adminrole</p>
</li>
<li id="h4se138">
<p id="h4se139" class="western">pathauto</p>
</li>
<li id="h4se140">
<p id="h4se141" class="western">nodereference</p>
</li>
<li id="h4se142">
<p id="h4se143" class="western">imagecache</p>
</li>
<li id="h4se144">
<p id="h4se145" class="western">asset or image + imagefield</p>
</li>
<li id="h4se146">
<p id="h4se147" class="western">tinymce</p>
</li>
</ul>
<h3 id="h4se148" class="western">How do you build this page:</h3>
<ul id="h4se149">
<li id="h4se150">
<p id="h4se151" class="western">List of Nodes w/ RSS &amp; Pager</p>
<ul id="h4se152">
<li id="h4se153">
<p id="h4se154" class="western">Views</p>
</li>
</ul>
</li>
<li id="h4se155">
<p id="h4se156" class="western">Custom content type which has related nodes 	in a heirarchy</p>
<ul id="h4se157">
<li id="h4se158">
<p id="h4se159" class="western">CCK + nodereference</p>
</li>
</ul>
</li>
<li id="h4se160">
<p id="h4se161" class="western">Thumbnails in node listing</p>
<ul id="h4se162">
<li id="h4se163">
<p id="h4se164" class="western">Asset + imagecache</p>
</li>
</ul>
</li>
<li id="h4se165">
<p id="h4se166" class="western">Cultivated (admin chosen) list of nodes</p>
<ul id="h4se167">
<li id="h4se168">
<p id="h4se169" class="western">nodequeue</p>
</li>
<li id="h4se170">
<p id="h4se171" class="western">views</p>
</li>
</ul>
</li>
<li id="h4se172">
<p id="h4se173" class="western">Sortable table of nodes and their values</p>
<ul id="h4se174">
<li id="h4se175">
<p id="h4se176" class="western">Views + Table style plugin</p>
</li>
</ul>
</li>
<li id="h4se177">
<p id="h4se178" class="western">Complex front page containing any of the 	above</p>
<ul id="h4se179">
<li id="h4se180">
<p id="h4se181" class="western">Panels 2</p>
</li>
</ul>
</li>
</ul>
<p id="h4se182" class="western"><br id="h4se183"/> <br id="h4se184"/> </p>
<table id="h4se185" border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="693"><col id="h4se186" width="222"></col><col id="h4se187" width="223"></col><col id="h4se188" width="222"><br />
<tbody id="h4se189">
<tr id="h4se190" valign="top">
<th id="h4se191" width="222">
<p id="h4se192" class="western"><br id="h4se193"/> </p>
</th>
<th id="h4se194" width="223">
<p id="h4se195" class="western"><br id="h4se196"/> </p>
</th>
<th id="h4se197" width="222">
<p id="h4se198" class="western"><br id="h4se199"/> </p>
</th>
</tr>
<tr id="h4se200" valign="top">
<td id="h4se201" width="222">
<p id="h4se202" class="western"><br id="h4se203"/> </p>
</td>
<td id="h4se204" width="223">
<p id="h4se205" class="western"><br id="h4se206"/> </p>
</td>
<td id="h4se207" width="222">
<p id="h4se208" class="western"><br id="h4se209"/> </p>
</td>
</tr>
</tbody>
<p></col></table>
<p id="h4se210" class="western" style="margin-bottom: 0in;"><br id="h4se211"/> </p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/05/20/drupal-curriculum/feed/</wfw:commentRss>
		</item>
		<item>
		<title>6 premises for killer apps on the Google App Engine or Good bye Appendix, Hello Google Apps</title>
		<link>http://pajamadesign.com/2008/05/11/6-premises-for-killer-apps-on-the-google-app-engine-or-good-bye-appendix-hello-google-apps/</link>
		<comments>http://pajamadesign.com/2008/05/11/6-premises-for-killer-apps-on-the-google-app-engine-or-good-bye-appendix-hello-google-apps/#comments</comments>
		<pubDate>Sun, 11 May 2008 06:04:34 +0000</pubDate>
		<dc:creator>Jacob Singh</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[business]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[google app engine]]></category>

		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://pajamadesign.com/?p=23</guid>
		<description><![CDATA[An appendicitis is a painful, uncomfortable and ultimately debilitating condition one which I have suffered with for over a year. However, its remedy (Laproscopic surgery) is fairly tame as far as surgical procedures go - way too much money to an evil hospital, a shitton of painkillers and a week of bedrest
PHPitis is another condition [...]]]></description>
			<content:encoded><![CDATA[<p>An appendicitis is a painful, uncomfortable and ultimately debilitating condition one which I have suffered with for over a year. However, its remedy (Laproscopic surgery) is fairly tame as far as surgical procedures go - way too much money to an evil hospital, a shitton of painkillers and a week of bedrest</p>
<p>PHPitis is another condition I have been suffering from.  It&#8217;s not early as painful and has provided me with a decent income and professional growth.  It is also not a pussy inflamed organ with no apparent value pressing up against all the nicely formed and functioning organs around it.  However, the feeling that there is something not right &#8220;down there&#8221; remains.<br />
<span id="more-23"></span></p>
<p>I&#8217;ve always known that python is the best language out there.  I don&#8217;t mean to start yet another stupid language fight, because every language is fine and dandy.  But honestly, every programmer I respect has told me the same thing, they wish they could just write python.  The only knocks against python are:</p>
<ul>
<li> Lack of hosting options</li>
<li> Lack of Jobs / Skilled personnel</li>
</ul>
<p>The first one, is obviously stupid, because it is as easy to run as PHP, but is totally chicken and egg.  The second is pretty much the same.  You have to be a better programmer to write python, and so there are less people who can, so there are less CTOs wanting to risk a language with less people available, so they go with PHP, and get speghetti code, because 90% of PHP developers aren&#8217;t that good.</p>
<p>Anyway, for what it&#8217;s worth, I love python, and I&#8217;m not that good at it yet, because I never get jobs in it, and it&#8217;s hard to get clients signed up for something that isn&#8217;t hosted anywhere&#8230;. Until now.</p>
<p>A day before I went to the hospital for an examination into yet another bout of my awful stomach pains which turned into the aforementioned surgery, I got my <a href="http://appengine.google.com"> App Engine </a> key.  During my few days of bed rest without net, I took it for a spin.</p>
<p>I&#8217;m as afraid of the big G as everyone else, and I hate the idea of locking my code up in a proprietary platform too.  But suspend those doubts for a minute and let me just tell you, that this thing is pretty cool.  Being able to write really elegant code while being able to scale to the end of the googleverse is pretty exciting.</p>
<p>I&#8217;m not going to repeat the questions everyone is asking about portability, sustainability, etc.  I&#8217;m looking at what would be a &#8220;killer app&#8221; that could be developed and deployed in 6 months and that would be successful on this platform.  Here are the attributes I would expect it to have:</p>
<h3> Uses Google Apps data apis </h3>
<p>If you&#8217;ve got the power of google calendar behind you, why spend forever building the database schema to support a calendaring application, it will never be as good. If you need a wiki, use sites.  It&#8217;s all there, and google will always provide more and more support for integration.  Plus, you reap all the benefits of your data being interoperable with other formats these services export to.  No brainer.</p>
<h3> Uses Google Apps Provisioing apis </h3>
<p>SaaS is in forever.  This means setup must be really simple for users.  They shouldn&#8217;t have to do a run around to setup google apps before using your service.</p>
<h3> Uses Google Authentication </h3>
<p>To survive in the enterprise, you need the single signon stuff.  Plus, they need it already if you want to do the first two.</p>
<h3> Provides a better / enhanced interface to existing google apps<br />
<br />
OR<br />
<br />
Provides a 3rd party middleware / conversion layer to other software<br />
</h3>
<p>On the first count, I think that you could provide something which makes it easier to use google apps, or provided some value added service there.  For instance, a simple CRM system which is a mashup of Contacts, gmail, sites and calendar would probably not be too much of a stretch.</p>
<p>On the second, there are lots of opportunities here, to be the glue, which makes you an attractive meal for both google, and the 3rd party you are integrating with.  good for short term wins.</p>
<h3> Makes Real Money (is not ad supported)</h3>
<p>I feel that the architecture of google apps is not for making content rich sites.  It&#8217;s really more for building tools which do something.  Ad supported sites which ACTUALLY make any money (as in profit, as in real money) are so rare.  All of them are either content producers or content organizers.  If you want to do something like that, go for a CMS like <a href="http://drupal.org"> Drupal</a> or something, and make your .02 per click on viagra ads.  I don&#8217;t think it&#8217;s a very exiting place to be.</p>
<h3> The Sew-up </h3>
<p>What is this blasphemy? I thought you were a linux free software guy?  You are encouraging me to place all my data in google and make my app <strong>totally</strong> dependent on google? Yeah, but I&#8217;m also a husband, and a son and I have rent + huge medical bills.  I think there is a golden opportunity here, and the tech is fun to play with.  There is no point doing this IMO, if you don&#8217;t want to marry google for this app.  It won&#8217;t make sense for everything you build, but if you&#8217;re going to do it, go whole hog and get bought.  Of course, there are millions thinking the same thing, but this platform has the potential to have lots of really small apps which get in, get a pain point solved and get out - bought - or at least with a low recovery time.</p>
]]></content:encoded>
			<wfw:commentRss>http://pajamadesign.com/2008/05/11/6-premises-for-killer-apps-on-the-google-app-engine-or-good-bye-appendix-hello-google-apps/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
