<?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-2538137900778784501</id><updated>2012-01-24T02:03:40.531-05:00</updated><category term='Python'/><category term='plans'/><category term='MVC'/><category term='book recommendations'/><category term='plea for sanity'/><category term='XML'/><category term='MySpace'/><category term='Zend'/><category term='self-promotion'/><category term='SOAP'/><category term='PHP'/><category term='job search'/><category term='Project McLuhan'/><category term='DB'/><category term='software engineering'/><category term='discoveries'/><category term='Symfony'/><category term='old ideas'/><category term='architecture'/><category term='laws'/><category term='RAD'/><category term='Facebook'/><category term='shameless pride'/><category term='Project Alchemy'/><category term='CakePHP'/><title type='text'>Quoth the runtime, "Segmentation Fault"</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mgpcoe.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8383903675998355483</id><published>2012-01-24T02:03:00.000-05:00</published><updated>2012-01-24T02:03:40.541-05:00</updated><title type='text'>The sleep-deprived ramblings of a developer in transition...</title><content type='html'>&lt;p&gt;Late-night software deployments are no fun. No fun whatsoever, particularly when you feel compelled (out of a little niggling paranoia that you&amp;rsquo;ve done something just a hair&amp;rsquo;s-breadth away from perfect) to stay up to watch the automated jobs pick up and start running the new code.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m going to be very happy when this project can be put to bed, so that I can get back to doing things that I&amp;rsquo;m a little more emotionally invested in. I have a great opportunity to do some systems architecture coming up; we&amp;rsquo;re rewriting my core projects into Java and JSF, which is allowing for some much-needed central refactoring, so that things can be decoupled and streamlined. I might not have the technical knowledge that the other developers on the project have (I&amp;rsquo;m terrifically out-of-date on Java), but I do have solid domain knowledge, so I&amp;rsquo;ll be able to establish the game plan&amp;mdash;write up most of the user stories and make sure that that&amp;rsquo;s all coherent, make sure that all the systems that need to be redesign get done correctly, &amp;amp;c, &amp;amp;c.&lt;/p&gt;&lt;p&gt;Of course, the worst thing of staying up late to work on code is when you forget that there&amp;rsquo;s a time zone difference between you and the server it&amp;rsquo;s running on&amp;hellip; and that when it runs at &amp;ldquo;2:00 am&amp;rdquo;, it&amp;rsquo;s actually referring to Mountain Standard Time. Bah!&lt;/p&gt;&lt;p&gt;Time for bed.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8383903675998355483?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2012/01/sleep-deprived-ramblings-of-developer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8383903675998355483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8383903675998355483'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2012/01/sleep-deprived-ramblings-of-developer.html' title='The sleep-deprived ramblings of a developer in transition...'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-2964721373298863160</id><published>2012-01-02T13:30:00.000-05:00</published><updated>2012-01-02T13:30:47.182-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>In which documentation leads to rearchitecture</title><content type='html'>&lt;p&gt;All year&amp;mdash;well, mainly just the second half of 2011&amp;mdash;I&amp;rsquo;ve been intending to write some XML Schema documents to formalise the input and output of an XML API I wrote a year and change ago. Is it really Important to do this? Yes and no. Mostly no (which explains why it hasn&amp;rsquo;t been done yet), since there are only three applications that use the API so far and I wrote all of them (and the PHP and JS libraries that handle it). From the functional perspective, it&amp;rsquo;s not critical that these schemata get written. However, I&amp;rsquo;m also trying to finish off some formal documentation of the tool that the API serves, which includes these schemata. Why would it need to include the schemata? Hopefully, we&amp;rsquo;re going to get some more developers working on this project, so having a formal document that describes the input and output would be good; it would give these developers something to refer to, that could be used for validation, and improve the testability of the whole system.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been trying finally finish these schemata, and I&amp;rsquo;ve found two things about how I implemented it:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The output has a small logic flaw, I think&amp;mdash;I use a &lt;tt&gt;&amp;lt;message/&amp;gt;&lt;/tt&gt; element both inside and outside the element that indicates what objects have been affected, depending (primarily) on the context of the action being performed.&lt;/li&gt;
&lt;li&gt;In order to be able to validate against these schemata, I&amp;rsquo;d have to make some obnoxiously redundant changes to the libraries that generate the input. The XML is somewhat polymorphic&amp;mdash;depending on the value of the &lt;tt&gt;command&lt;/tt&gt; attribute on an &lt;tt&gt;&amp;lt;action/&amp;gt;&lt;/tt&gt; element, the legal child elements change. I&amp;rsquo;d love to be able to handle that without having to use the &lt;tt&gt;xsi:type&lt;/tt&gt; attribute to indicate that the delete action is an instance of type ActionDelete, but it&amp;rsquo;s becoming apparent that XML parsers just don&amp;rsquo;t work that way.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So, the decision to make the XML polymorphic based on an &lt;tt&gt;&amp;lt;action/&amp;gt;&lt;/tt&gt; element may have been shortsighted. Probably was, in fact. The question is, though, do I rewrite the API entirely to allow this business logic to be expressed in the schema, or do I write a more generalised pair of schemata now, then clean up the API in a v2.0 so that it can be more rigourously and specifically validated against the business? The output definitely needs to be revisited (especially since it's currently sending both XML and JSON, depending on the action), but what to do about the input? Probably simpler to do the minimal amount of redesign now, then when the applications get refactored later this year, look into the more comprehensive enhancements.&lt;/p&gt;&lt;p&gt;We shall see, we shall see&amp;hellip;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-2964721373298863160?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2012/01/in-which-documentation-leads-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/2964721373298863160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/2964721373298863160'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2012/01/in-which-documentation-leads-to.html' title='In which documentation leads to rearchitecture'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-7621906898677454285</id><published>2011-06-27T23:29:00.000-04:00</published><updated>2011-06-27T23:29:52.036-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='laws'/><title type='text'>On Coe’s First Law of Software Development</title><content type='html'>&lt;p&gt;Last week, I discussed my &lt;a href="http://mgpcoe.blogspot.com/2011/06/coes-first-law-of-code-documentation.html"&gt;Second Law of Software Development&lt;/a&gt; (&lt;em&gt;self-documenting code isn&amp;rsquo;t&lt;/em&gt;), in reference to why proper, discrete documentation is a Good Thing. I didn&amp;rsquo;t get into what I think is the best time to write documentation (before you write code), because that&amp;rsquo;s a whole other rant in and of itself, but I did briefly mention my First Law of Software Development:&lt;/p&gt;&lt;p&gt;&lt;em&gt;When it happens, you&amp;rsquo;ll know.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not ashamed to admit that I&amp;rsquo;ve borrowed the phrasing from &lt;i&gt;The Simpsons&lt;/i&gt;, but it&amp;rsquo;s a really good line. The First Law originally applied to baking in security when you&amp;rsquo;re developing &lt;abbr title="Software as a Service" style="border-bottom: 1px dashed #000;"&gt;SaaS&lt;/abbr&gt;, but other things keep coming up, wherein if I&amp;rsquo;d kept in mind that &lt;em&gt;when it happens, you&amp;rsquo;ll know&lt;/em&gt;, I could have avoided a whole lot of hassle.&lt;/p&gt;&lt;p&gt;Simply put, the First Law is all about trying to see things coming, and being prepared for them. I could have borrowed from Scouts and gone with &lt;em&gt;be prepared&lt;/em&gt;, but it doesn&amp;rsquo;t quite appeal to my sense of humour. The fact is, something will eventually go wrong, and when it finally happens, you&amp;rsquo;ll know. And when you look at the block of code that&amp;rsquo;s to blame, you&amp;rsquo;ll ask yourself why you didn&amp;rsquo;t code defensively for it in the first place.&lt;/p&gt;&lt;p&gt;It originally came to me when I was writing a CRM tool for the company I worked for in 2007. Inspired by a software engineering professor at my university, I wanted to code against bad input. At first, it was about malicious input, but as time has gone on, it really is about just generally bad input. The original motivation was about accepting the fact that at some point in time, someone, somewhere, is going to discover and exploit a weakness in your software. You don&amp;rsquo;t want to assume that all of your users will be nefarious little pissants, but in the interest of your good users, you ought to assume that your average long-term number of less-than-trustworthy users is nonzero.&lt;/p&gt;&lt;p&gt;So, eventually, someone will try to misuse your software. But does it stop there? The correct answer is no, no it doesn&amp;rsquo;t. While you&amp;rsquo;re validating your input against inappropriate behaviour, you can just as easily, if not more easily, validate for correct behaviour&amp;mdash;that your users haven&amp;rsquo;t accidentally done something wrong. Type checking falls under this umbrella, and it&amp;rsquo;s useful both in the functions that are retrieving user input and the functions that are processing it. This is particularly important in weakly typed languages, because you can&amp;rsquo;t reliably just cast your input into a variable of type &lt;i&gt;x&lt;/i&gt; (particularly in JavaScript, where concatenation and mathematic addition use the same operator). When users provide improper input that isn&amp;rsquo;t what it should be (but they still have honourable intentions), then you have a problem (maybe it&amp;rsquo;s in your documentation&amp;hellip; but that&amp;rsquo;s another post). Maybe the input is well-formed, but has unexpected side-effects. &lt;em&gt;When it happens, you&amp;rsquo;ll know.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Now that you&amp;rsquo;re validating your user input for validity and intent, are you done? Probably not. In this day and age, software doesn&amp;rsquo;t exist in a vacuum (apart from the little noddy programs you write to prove that you can handle the concept you were just taught). There are external subsystems that you rely on. In an ideal world, you&amp;rsquo;ll get perfect data from them, but this isn&amp;rsquo;t an ideal world. Databases get overloaded and refuse connections. Servers get restarted and services don&amp;rsquo;t always come up correctly, if at all. Connections time out, or you forget whether or not this request has to go through a proxy. When it happens, you&amp;rsquo;ll know, because all of a sudden, your software breaks. Hard. You need to figure out what subsystem failed, and more importantly, why, so that you can prevent it from happening that way in the future.&lt;/p&gt;&lt;p&gt;However, that isn&amp;rsquo;t enough. You should have been ready for that failure. You can&amp;rsquo;t assume that all the other subsystems will be there 100% of the time. Assume that your caching layer will disappear at an inconvenient moment. Know that your database won&amp;rsquo;t always give you a result set. If you have to call out to a separately managed web service, do not rely on it being there, or having the same API forever. Code defensively for the fact that eventually, something will go wrong, and you won&amp;rsquo;t be watching when it happens.&lt;/p&gt;&lt;p&gt;So there&amp;rsquo;s a very good reason why the First Law of Software Development is &lt;em&gt;when it happens, you&amp;rsquo;ll know&lt;/em&gt;. Eventually, &amp;ldquo;it&amp;rdquo; will happen, and when you figure out what &amp;ldquo;it&amp;rdquo; was, and where it caused you problems, it&amp;rsquo;ll seem so obvious that there was a point of failure, or a weakness, that you&amp;rsquo;ll ask yourself why this problem wasn&amp;rsquo;t coded against in the first place.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-7621906898677454285?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2011/06/on-coe-first-law-of-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/7621906898677454285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/7621906898677454285'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2011/06/on-coe-first-law-of-software.html' title='On &lt;i&gt;Coe&amp;rsquo;s First Law of Software Development&lt;/i&gt;'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8711984437410520361</id><published>2011-06-15T19:33:00.003-04:00</published><updated>2011-06-15T20:52:18.504-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='laws'/><title type='text'>Coe's Second Law Of Software Development</title><content type='html'>&lt;p&gt;Before I begin, let me just put it out there that I really like the Zend Framework. I know, I know, laying down your cards about your favourite editor/framework/OS/whatever is liable to set off holy wars, but I really like ZF. It&amp;rsquo;s clean, and I like the mix-and-match properties of it that allow me to use only as much of the framework as I need. It&amp;rsquo;s this very property that I&amp;rsquo;ve used to great advantage in Project Alchemy and Portico. But I&amp;rsquo;ve always had one complaint about it.&lt;/p&gt;&lt;p&gt;The documentation in the reference guide, and to a roughly equal extent, in the PHPDoc navigator, is really flaky. The full functionality isn&amp;rsquo;t properly described in the reference guide, and the PHPDoc doesn&amp;rsquo;t provide enough information about the API. I&amp;rsquo;ve found, on several occasions, that I have to dig into the code simply in order to figure out how to use some methods.&lt;/p&gt;&lt;p&gt;Anthony Wlodarski, of PHPDeveloper.org, sees this as a positive of Zend Framework; that when ZF community wonks tell you to &lt;abbr title="Read The Fine Source"&gt;RTFS&lt;/abbr&gt;, it really is for your own good; that ZF really is that self-documenting. He says,&lt;/p&gt;&lt;blockquote&gt;One thing I learned early on with ZF was that the curators and associates in the ZF ecosystem always fall back to the root of &amp;ldquo;read the code/api/documentation&amp;rdquo;. With good reason too! It is not the volunteers simply shrugging you off but it is for your own good&lt;/blockquote&gt;&lt;p&gt;Unfortunately, it&amp;rsquo;s been my experience that &lt;em&gt;self-documenting code isn&amp;rsquo;t&lt;/em&gt;. Let&amp;rsquo;s call that &amp;ldquo;Coe&amp;rsquo;s Second Law Of Software Development&amp;rdquo; (the First being &lt;em&gt;when it happens, you&amp;rsquo;ll know&lt;/em&gt;). This is how strongly I feel about the issue. Far and away, the code itself is always the last place you want to look to figure out how it works, and only ever if you have a fair amount of time on your hands, because deciphering another developer&amp;rsquo;s idiosyncrasies is harder than writing new code. And if you have to look through that code to figure out what the correct usage of the tool is, then someone isn&amp;rsquo;t doing their job properly, particularly when Zend Framework has the backing of Zend.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been working for $EMPLOYER$ for more than a year now, and I&amp;rsquo;ve worked with a number of our internal tools, and across the board, I keep getting bit by the fact that our self-documenting code isn&amp;rsquo;t. Self-documenting code means that there&amp;rsquo;s no easily-accessible, central repository of information about how the tools are supposed to work, or about what inputs to provide and outputs to expect. Self-documenting code means that when something goes wrong, and the person who originally wrote the code, the poor sap who has to correct the problem now has to figure out what the code is supposed to do. Self-documenting code means that when your prototypes (or even production tools!) fail without a clear error code, you have to either start shotgun debugging, trying to figure out what you&amp;rsquo;re doing wrong (or what changed); or you have to ask the project manager, who will ask a developer to dig through the code. This increases the turnaround time on all problems.&lt;/p&gt;&lt;p&gt;Self-documenting code is fine when you&amp;rsquo;re writing little noddy programs for first-, second-, and even some third-year classes, where the functionality is defined in the assignment description, and the problems straightforward enough that what you&amp;rsquo;re doing is actually clear at a quick glance. When you&amp;rsquo;re writing tools for distribution to parties outside of the small group of people who are developing it, you owe it to yourself, to your QA team, to your present and future colleagues, and more importantly to your users, to write good, clear documentation, and to do so ahead of time, because then you only have to update the documentation to reflect what changed about your plan.&lt;/p&gt;&lt;p&gt;But remember, when someone tells you excitedly that their code is self-documenting, remember: &lt;em&gt;self-documenting code isn&amp;rsquo;t.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8711984437410520361?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2011/06/coes-first-law-of-code-documentation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8711984437410520361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8711984437410520361'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2011/06/coes-first-law-of-code-documentation.html' title='Coe&apos;s Second Law Of Software Development'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-6075908424677225749</id><published>2010-10-18T23:20:00.002-04:00</published><updated>2010-10-18T23:51:15.371-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='plans'/><title type='text'>In which there is a first time for everything</title><content type='html'>&lt;p&gt;So, this Thursday is the Toronto Facebook Developer Garage&amp;hellip; This is actually going to be the first industry event I&amp;rsquo;ll have ever attended, and hopefully not the last. Should be interesting&amp;mdash;I&amp;rsquo;m going with the development team from work (all three of us), and I know that a few of the guys from my first Facebook-related job will be there (naturally; that company is one of the hosts). I haven&amp;rsquo;t so much as touched the Facebook API since I left that job, so it&amp;rsquo;s certainly going to be interesting to see what cool stuff people are doing with the platform, and how it&amp;rsquo;s changed in the last two years.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m also, admittedly, really curious to see just what goes on at one of these events. Apparently it grew from a bunch of grassroots, community-organised gatherings of just developers who wanted to show off some cool stuff, but this one&amp;rsquo;s got a proper agenda, with keynote speeches and whatnot. I know that the Garage in NYC involved getting some swag (saw pictures, said former employer co-hosted that one too), so obviously it&amp;rsquo;s much more&amp;hellip; regimented than just an informal gathering.&lt;/p&gt;&lt;p&gt;Should be fun, though. The biggest issue of getting deeper integration of Facebook into what my company does is the monetisation issue, and unless I&amp;rsquo;m much mistaken, you can&amp;rsquo;t post your own ads inside of a Facebook app canvas (probably because it takes eyeballs away from the ads on the side of the page), so the issue becomes, how would we get Facebook users to buy the paid parts of the service? Or at least how do we get Facebook users to come to our site (because we&amp;rsquo;re already one of the most popular sites in Canada; can&amp;rsquo;t go wrong with getting some more eyes), so that they&amp;rsquo;ll&amp;hellip;&lt;/p&gt;&lt;ol style="list-style-type: lower-alpha;"&gt;&lt;li&gt;see the ads that &lt;em&gt;our&lt;/em&gt; advertisers are paying for, and&lt;/li&gt;&lt;li&gt;continue through the regular flow and maybe buy the paid parts of the service?&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Therein lies the challenge&amp;hellip; and maybe there will be answers at this Garage. At the very least, there should be ideas on what can be done with the API that&amp;rsquo;s been introduced since 2008!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-6075908424677225749?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/10/in-which-there-is-first-time-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6075908424677225749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6075908424677225749'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/10/in-which-there-is-first-time-for.html' title='In which there is a first time for everything'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-4271578073434950792</id><published>2010-07-23T22:51:00.007-04:00</published><updated>2010-07-26T19:18:42.129-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='SOAP'/><category scheme='http://www.blogger.com/atom/ns#' term='discoveries'/><title type='text'>In which work ethics are considered</title><content type='html'>&lt;p&gt;Over the past couple of weeks, I&amp;rsquo;ve had two very clear indicators&amp;mdash;to myself&amp;mdash;of just how much I&amp;rsquo;m enjoying my current job. I say that because there&amp;rsquo;s a subtle, but important, difference between saying &amp;ldquo;I love my job because I love doing &lt;i&gt;x&lt;/i&gt;&amp;rdquo; and observing your own behaviours and thought patterns, and noticing that the way that you do your job, and approach your job, demonstrates how much you enjoy it.&lt;/p&gt;&lt;p&gt;The first way is something I realised about two weeks ago, when I met with the general manager (my boss&amp;rsquo;s boss, and an all-around good guy) for a quick catch-up chat. I&amp;rsquo;ve been working at this job for eleven weeks, and it feels like I&amp;rsquo;ve been there a lot longer, and more importantly, the environment, and the nature of the work is just naturally enjoyable, and it&amp;rsquo;s something I&amp;rsquo;m keenly interested in, so I like going to work on general principle. But when I was talking to him, it dawned on me that I like my work so much that, for the first time in years (at least two, if not four) have I been able to get so wrapped up in my work that I lose track of the time. Almost every other job I&amp;rsquo;ve had, with possibly one exception, since I moved to Toronto, I&amp;rsquo;ve tended to kind of check out around 4:30 or 4:45; I&amp;rsquo;d start trying to find something to do that would be productive work, but wouldn&amp;rsquo;t take too long to do, because I wanted to get out the door. Where I am now, as often as not, it&amp;rsquo;ll be almost 5:30 when I look at the clock and realise that I should probably go home.&lt;/p&gt;&lt;p&gt;The second, even clearer indication came this past Friday. I&amp;rsquo;ve been working on coming up with a way to better integrate two of the projects I&amp;rsquo;ve been working on, and particularly a way to do it across a subdomain divide (the products need to communicate on both the server and client sides; I managed to hack it on the pure client side by spawning some IFrames, but getting a particular server-side action in Project A to trigger an action in Project B has been a little less clear-cut. So, I decided that a simple XML interface into Project B was needed, with a wrapper for Project A (and Project C, which another developer is working on was necessary). So, I spent Thursday and Friday afternoons working on this API.&lt;/p&gt;&lt;p&gt;Two very cool things came from this.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Apart from a few minor syntax errors (missing a parenthesis, putting a colon where a semicolon should&amp;rsquo;ve been, &amp;c.), the stripped down API worked perfectly right off the bat. A few hundred lines of code, and it Just Worked. I haven&amp;rsquo;t been that successful in a while.&lt;/li&gt;&lt;li&gt;I ran the first test at about 4:40. I had other things that needed to be done that evening which necessitated my leaving as close to 5:00 as possible, but I had a thought I haven&amp;rsquo;t had in a long time: &lt;i&gt;I wish I didn&amp;rsquo;t have to leave right away&lt;/i&gt;. I wanted to take my work home with me.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This hasn&amp;rsquo;t happened in ages, and I didn&amp;rsquo;t realise how much I missed that feeling until this past Friday. I&amp;rsquo;ve been telling people how much I like my job based on its perks: catered lunches on Fridays, stocked kitchen, and an amazing sense of community with my co-workers. But being able to say, &amp;ldquo;there are days that I don&amp;rsquo;t want to stop working&amp;rdquo;&amp;hellip; that might be the surest sign that you&amp;rsquo;ve got a great job.&lt;/p&gt;&lt;p&gt;It&amp;rsquo;s kind of funny, because I normally try to fight against that really, typically Protestant work ethic of, when you boil it down, &amp;ldquo;living to work&amp;rdquo;. I can leave my work at the office; most days, it&amp;rsquo;s a case of losing track of the time because I&amp;rsquo;m so wrapped up in what I&amp;rsquo;m doing, so when I realise what time it is, I clean up what I was doing, get it to a state where I can leave, and I go home. And I think that&amp;rsquo;s what this is an extension of&amp;mdash;I got so wrapped up in what I was doing that, had I not had other things to do, I almost certainly would have stuck around, ignoring the clock.&lt;/p&gt;&lt;p&gt;I think that might be the difference. Most days, I don&amp;rsquo;t care what time it is; it&amp;rsquo;s irrelevant to me how many hours I spend at the office, as long as I get done what I want to get done. When I compare that against the Toronto workaholics who not only work to live, but take it as a point of some perverse kind of pride that they work sixty- or eighty-hour weeks, I can see much better what the difference is. I&amp;rsquo;m doing what I love, and I take pride in the result of my work, whereas some people take pride in the amount of work that they do.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-4271578073434950792?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/07/in-which-work-ethics-are-considered.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/4271578073434950792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/4271578073434950792'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/07/in-which-work-ethics-are-considered.html' title='In which work ethics are considered'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-3766787820210061803</id><published>2010-06-03T12:15:00.004-04:00</published><updated>2010-06-03T12:26:16.526-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shameless pride'/><category scheme='http://www.blogger.com/atom/ns#' term='self-promotion'/><category scheme='http://www.blogger.com/atom/ns#' term='discoveries'/><title type='text'>That thing you use? I made that.</title><content type='html'>&lt;p&gt;Monday night (technically Tuesday morning, but who&amp;rsquo;s counting? Other than Blogger, that is) I mentioned that being able to say to somebody, &amp;ldquo;you know that thing that you use? I made that&amp;rdquo; is a great feeling. I just ran into a former colleague from my previous contract, who let me know just on what scale my stuff is operating.&lt;/p&gt;&lt;p&gt;One of the projects I worked on&amp;mdash;made, really; the requirements were small enough&amp;mdash;was a carbon and cost savings calculator for Sears Canada&amp;rsquo;s website, so that people looking to replace one of their appliances could see about how much money they&amp;rsquo;d save by switching. Fairly simple to do; the worst of it was extracting the formulas from the Big Ugly Interactive Spreadsheet that Sears provided. I worked hard to provide the best little jQuery applet I could, complete with pretty transitions and everything. Fully translated into French, too, and I made sure it&amp;rsquo;d work acceptably well in IE6. It was kind of a focus of their recent/current Green promotion, but how many people, really, were going to wind up using it?&lt;/p&gt;&lt;p&gt;As it turns out, a lot. In the linked article, you can see that last Friday, they opened a six-kiosk booth in the Vancouver Robson store that runs that &amp;ldquo;little jQuery applet&amp;rdquo; in a touchscreen interface! I&amp;rsquo;m&amp;hellip; speechless. To the best of my knowledge, nothing I&amp;rsquo;ve ever made has seen such a wide userbase. They&amp;rsquo;re adding more booths to more stores, too. I kind of hope that one will show up in Toronto so I can play with it and show people.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-3766787820210061803?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://ca.news.finance.yahoo.com/s/28052010/30/link-f-cnw-sears-canada-unveils-cost-carbon-savings-calculator-vancouver.html' title='That thing you use? I made that.'/><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/06/that-thing-you-use-i-made-that.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/3766787820210061803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/3766787820210061803'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/06/that-thing-you-use-i-made-that.html' title='That thing you use? I made that.'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8379235130414093548</id><published>2010-06-01T00:55:00.003-04:00</published><updated>2010-06-01T01:15:00.272-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='book recommendations'/><category scheme='http://www.blogger.com/atom/ns#' term='plea for sanity'/><title type='text'>In which a scale is found tipping</title><content type='html'>&lt;p&gt;There&amp;rsquo;s a certain aphorism that I&amp;rsquo;ve been thinking about lately: &amp;ldquo;there are twenty-four useful hours in every day&amp;rdquo; I don&amp;rsquo;t recall where I heard it first&amp;mdash;as I recall, the version I heard growing up was &amp;ldquo;you&amp;rsquo;ve got the same amount of time in the day as the rest of us&amp;rdquo;&amp;mdash;but I&amp;rsquo;ve realised two things about that first saying:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;There are decidedly &lt;strong&gt;not&lt;/strong&gt; twenty-four useful hours in every day. Depending on your particularly sleep needs, there are eighteen and, say, fifteen waking hours in every day. Then when you factor in time spent in transit between work/school and home, and mealtimes, along with basic hygiene needs, your time-per-day number drops considerably. I&amp;rdquo;d estimate around twelve. Your mileage may vary, depending on, well, the mileage between home and what you do to make a living.&lt;/li&gt;&lt;li&gt;I need more. I think this is why I&amp;rsquo;m reminded if my father&amp;rsquo;s different, truer version of the saying.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;There are people in this industry, in this city, who love the freelancing life; people who love seeking out the Next Big Contract, and who get off on working late into the night to make a higher paycheque than the next guy. I&amp;rsquo;m not one of those people, as I&amp;rsquo;ve been discovering this year.&lt;/p&gt;&lt;p&gt;Don&amp;rsquo;t get me wrong. I like networking, and I like making things happens, and I like being able to say, &amp;ldquo;you know that thing that you use? I made that.&amp;rdquo; It&amp;rsquo;s a great feeling. But for the past few months, I&amp;rsquo;ve really felt like I&amp;rsquo;ve had at least twenty-four hours of &lt;em&gt;work&lt;/em&gt; to do, every single day. So I perpetually feel like I&amp;rsquo;m behind. And that&amp;rsquo;s a pretty crappy feeling.&lt;/p&gt;&lt;p&gt;I read a book a few years back called &lt;i&gt;The Hacker Ethic&lt;/i&gt;. It discusses the Protestant work ethic, which I think is a huge influence, in this city, of why people will willingly put in ten- or twelve-hour working days, five or six days a week. I don&amp;rsquo;t get that. I&amp;rsquo;ve been doing that for months, and it&amp;rsquo;s awful. All you&amp;rsquo;re thinking about is what you have to do. Your main focus is making more money. But why? So you can buy more things?&lt;/p&gt;&lt;p&gt;Seriously, everybody should read that book. I got into computers professionally because I love using them, and bending them to my will. But I also love my wife, and it&amp;rsquo;s important to find that work/life balance that keeps you sane and healthy.&lt;/p&gt;&lt;p&gt;This is becoming a bit of a rant, so I think I&amp;rsquo;d best cut it off. Too much work to do, anyway.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8379235130414093548?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/06/in-which-scale-is-found-tipping.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8379235130414093548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8379235130414093548'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/06/in-which-scale-is-found-tipping.html' title='In which a scale is found tipping'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-7128820273137115206</id><published>2010-03-12T20:14:00.003-05:00</published><updated>2010-03-12T20:30:37.986-05:00</updated><title type='text'>In which an error is realised</title><content type='html'>&lt;p&gt;I&amp;rsquo;ve been giving some deeper thought to the multiple-has table I described in my last post, and I&amp;rsquo;ve figured out where the problem is. All the usual actions can be performed in constant time for any specific table, as usual&amp;hellip; the issue is what &lt;em&gt;kind&lt;/em&gt; of time they require. For &lt;i&gt;n&lt;/i&gt;-dimensional tables, the number of operations for &lt;code&gt;find&lt;/code&gt; increases linearly with &lt;i&gt;n&lt;/i&gt;, but the operations required for &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; increases &lt;strong&gt;factorially&lt;/strong&gt;. For &lt;i&gt;n&lt;/i&gt;=2, &lt;code&gt;add&lt;/code&gt; requires three actions, but for &lt;i&gt;n&lt;/i&gt;=3, &lt;code&gt;add&lt;/code&gt; takes seven. &lt;i&gt;n&lt;/i&gt;=4 causes &lt;code&gt;add&lt;/code&gt; to take twenty-five, unless I&amp;rsquo;ve mucked up my math.&lt;/p&gt;&lt;p&gt;This is, of course, bad. Unless you can magically prepopulate the hashtable, and you never have to modify it&amp;hellip; and that&amp;rsquo;s exceedingly unlikely. I think I need to find a better way of storing the indices. I think the problem that&amp;rsquo;s causing the factorial growth is the fact that I was originally thinking of storing the sub-hashtables (say, where &lt;i&gt;n&lt;/i&gt;=2, the tables one dimension deep) as independent of each other, and relying on encapsulation. Didn&amp;rsquo;t I specifically mention that the annoying part about classic multidimensional arrays is that they&amp;rsquo;re based on encapsulation?!&lt;/p&gt;&lt;p&gt;Back to the drawing board.&lt;/p&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-7128820273137115206?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/03/in-which-error-is-realised.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/7128820273137115206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/7128820273137115206'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/03/in-which-error-is-realised.html' title='In which an error is realised'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-6449932035491093566</id><published>2010-03-07T23:46:00.004-05:00</published><updated>2010-03-08T00:43:41.484-05:00</updated><title type='text'>In which an algorithm is partially puzzled out</title><content type='html'>&lt;p&gt;This past week, I was working on a small project at work that seemed, at first glance, to need a unique type of multidimensional array—I needed to be able to store a collection of data that had a composite key, where the values of each component of the key were bounded sets. I realised after an hour or so of trying to figure it out that I was overthinking the problem (a regular multidimensional array would suffice, because as the programmer I can fully control which key component would be the primary axis of the array), but it left me with an interesting idea in my head that, after a brief bit of research, I've realised nobody's really approached... and while I thought of the idea at work, I also tossed it out as being unnecessary, so I don't think they can really lay claim to the intellectual property, because I'm not doing any development of the idea on their dime! Only part of what I'm going to get into was something done at the office, so the vast bulk of this is my own work, for my own amusement.&lt;/p&gt;&lt;p&gt;That idea is, in essence, an &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;-dimensional multi-hash table (which I'll just refer to as an MHT, for brevity's sake). The problem that I thought I had was that I would need to allow the user to specify either of the components, then update the available choices from the other component appropriately, or retrieve a subset of the data that had that key (like I said, it turned out to not be the case), but I've realised since then, what if, someday, I really need to do that, and I want to be able to do it quickly? My approach to the problem follows, but this is fairly off-the-cuff, and hasn't been implemented. I'm really just trying to think this out, and I want to make sure that if this turns out to be Important, that there's a published record of when I came up with it.&lt;/p&gt;&lt;p&gt;Let &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; be a set of data. Each item &lt;span style="font-style: italic;"&gt;s&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; contains (for the purpose of this example) a binary composite key, made of values &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;k&lt;/span&gt;, where &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;k&lt;/span&gt; are members of sets &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;K&lt;/span&gt;. &lt;span style="font-style: italic;"&gt;s&lt;/span&gt; has a unique key value &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; that may or may not be exposed to the user, but is available to the software. Instead, the user wishes to access &lt;span style="font-style: italic;"&gt;s&lt;/span&gt; by specifying &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;k&lt;/span&gt;, but may need to obtain a list of all items in &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; with a specific value of either &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; or &lt;span style="font-style: italic;"&gt;k&lt;/span&gt;. Since &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; may be of arbitrary size, maintaining a low order for the algorithm is important. Hash tables are particularly well-suited to this, as they can typically maintain O(1) performance for most access functions.&lt;/p&gt;&lt;p&gt;In order to accomplish this, multiple hash tables must be maintained (it's actually quite similar to maintaining hash indices in a DBMS; perhaps I should look into the specific algorithms used there). A hash table of all &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; values must be maintained, and each item in the &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; hashtable must point to a hash table with  values as its key. These relationships must in turn be transposed, so that the user can access all the &lt;span style="font-style: italic;"&gt;s&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; with a particular &lt;span style="font-style: italic;"&gt;k&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;The issue, of course, becomes one of implementation. We also want to maintain a low storage requirement, so each item in the &lt;span style="font-style: italic;"&gt;J&lt;/span&gt;-to-&lt;span style="font-style: italic;"&gt;K&lt;/span&gt; hash table should simply be a pointer into &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;; this is why I mentioned that each &lt;span style="font-style: italic;"&gt;s&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; has a unique key that is programmatically available, but not necessarily exposed to the user.&lt;/p&gt;&lt;p&gt;So, what's the best approach to doing this? It seems to me that &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;+1 hash tables are required, where &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; is the number of dimensions that the user needs to use to access a given &lt;span style="font-style: italic;"&gt;s&lt;/span&gt;. A master &lt;span style="font-style: italic;"&gt;S&lt;/span&gt; hash table will exist with all the items. Then each dimension will have its own hash table. For dimension&lt;span style="font-style: italic;"&gt; &lt;span style="font-style: italic;"&gt;J&lt;/span&gt;&lt;/span&gt;, each record would be a key-value pair with the key &lt;span style="font-style: italic;"&gt;j&lt;/span&gt;, and the value being a hash table where the keys are values from &lt;span style="font-style: italic;"&gt;K&lt;/span&gt;, and the values are pointers into &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;. Dimension &lt;span style="font-style: italic;"&gt;K&lt;/span&gt; would exist similarly. When adding an item &lt;span style="font-style: italic;"&gt;x&lt;/span&gt; to &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;, after calculating its unique key value, the add function would need to add &lt;span style="font-style: italic;"&gt;x&lt;sub&gt;k&lt;/sub&gt;&lt;/span&gt; to &lt;i&gt;J&lt;/i&gt; and &lt;i&gt;x&lt;sub&gt;j&lt;/sub&gt;&lt;/i&gt; to &lt;i&gt;K&lt;/i&gt;. The reverse would be necessary for deletions. So, f&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;or a 2&lt;span style="font-style: italic;"&gt;&lt;/span&gt;-dimensional MHT, it seems that adds and deletes could be performed in 3 O(1) steps. It's not perfect, but it's better than O(&lt;span style="font-style: italic;"&gt;n&lt;/span&gt;). Fortunately, the data storage requirements for the two-dimensional are &lt;span style="font-style: italic;"&gt;3n&lt;/span&gt; (so still O(&lt;span style="font-style: italic;"&gt;n&lt;/span&gt;))—each record would exist one time in each of the &lt;span style="font-style: italic;"&gt;S&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;J&lt;/span&gt;, and &lt;span style="font-style: italic;"&gt;K&lt;/span&gt; hash tables.&lt;/p&gt;&lt;p&gt;The difficulty that I'm realising, as I write this, could very easily come up, is what do you do when you need to create an &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;-dimensional multihash table where &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;&gt;2? The mechanism I've described above works fine where each &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; refers to a simple hash table, but what happens when you have keys &lt;span style="font-style: italic;"&gt;J&lt;/span&gt;, &lt;span style="font-style: italic;"&gt;K&lt;/span&gt;, and &lt;span style="font-style: italic;"&gt;L&lt;/span&gt;? What would each &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; refer to? A multidimensional array? Then updating &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; may necessitate updating multiple tables with the same data (which is something I'd like to &lt;span style="font-style: italic;"&gt;&lt;/span&gt;avoid). I think the answer lies in what each &lt;span style="font-style: italic;"&gt;j&lt;/span&gt; in &lt;span style="font-style: italic;"&gt;J&lt;/span&gt; points to, but I haven't worked out how that's going to work, and I tend to do my best figuring out of this type of thing when I can see the problem—and being 12:30 in the morning, at home, I don't exactly have access to a gigantic whiteboard on which to work, or the opportunity to try hacking on the problem to see what works best.&lt;/p&gt;&lt;p&gt;But there's my approach to a 2-dimensional hash table. This is definitely something I want to try implementing, and that I want to continue working with in a bid to make an &lt;span style="font-style: italic;"&gt;n&lt;/span&gt;-dimensional, any-addressable, MHT. I don't know if it will give any kind of accolades, but I think it'll be a fun problem to solve... and considering the fact that I can't find any evidence of anyone else trying to approach it this way on The Google, I'm starting to think that it might even be patentable.. so I think this would qualify as prior art!&lt;/p&gt;&lt;p&gt;Now I'm even more excited.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-6449932035491093566?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/03/in-which-algorithm-is-partially-puzzled.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6449932035491093566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6449932035491093566'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/03/in-which-algorithm-is-partially-puzzled.html' title='In which an algorithm is partially puzzled out'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-441484670001151833</id><published>2010-02-10T00:34:00.004-05:00</published><updated>2010-02-10T00:57:51.162-05:00</updated><title type='text'>In which the author retraces his steps… slowly.</title><content type='html'>&lt;p&gt;I don&amp;rsquo;t think I&amp;rsquo;ve ever really truly been ambivalent about anything before. In high school and university I garnered a reputation for being almost unflappable; that I could let anything slide. Something went wrong, and it wasn&amp;rsquo;t a big deal. Never really experienced ambivalence, as it&amp;rsquo;s properly described&amp;mdash;that the subject feels strongly about the object, but in opposite directions at once. Not until now, not until tonight.&lt;/p&gt;&lt;p&gt;I have never been simultaneously so happy to have largely abandoned Microsoft&amp;rsquo;s operating systems and Web browser for my daily use and first-line development testing, and so spectacularly frustrated. I&amp;rsquo;ve been having some difficulty with the Windows XP partition on my main computer at home for a while now, mainly because I was using a particularly poorly-designed firewall (Comodo Personal Firewall, for those keeping score&amp;mdash;I&amp;rsquo;d advise you to never install it)&amp;hellip; I&amp;rsquo;d attempted to upgrade the software, but the previous version refused to be removed first. Deleting it didn&amp;rsquo;t help; there were still innumerable system hooks that actually wound up making it impossible to use the Internet! I thought perhaps the firewall had rewritten the network stack, and hypothesised that upgrading the operating system to Service Pack 3 would help. Needless to say, it didn&amp;rsquo;t, but I eventually managed to excise the demonspawn firewall. Somewhere in here, I also upgraded to Internet Explorer 8&amp;mdash;after even Microsoft started actively encouraging the switch, for safety reasons, I knew its time had finally come and I could stop supporting it.&lt;/p&gt;&lt;p&gt;Unwisely, I tried the new version of the firewall, and now explorer.exe has become quite possibly the least-responsive piece of software on the computer. I can&amp;rsquo;t be 100% certain that these are causally related, because I can&amp;rsquo;t find any trace of the firewall on the system, and I&amp;rsquo;ve followed the same removal steps as the last time, and Windows Explorer hasn&amp;rsquo;t improved any.&lt;/p&gt;&lt;p&gt;This is all just context&amp;hellip; a secondary source of frustration, because it means my computer is running far slower than it ever normally did prior to all these changes. The real frustration is that I&amp;rsquo;m jumping through all these hoops (all the while trying to install Subversion, Apache and MySQL on a FreeBSD 6.0 server with a 500 MHz Celeron processor in PuTTY) so that I can track down an IE-specific rendering bug in my new contract. Unfortunately the bug is so specific that it&amp;rsquo;s only appearing in Internet Explorer &lt;strong&gt;&lt;em&gt;7&lt;/em&gt;&lt;/strong&gt;! At this point, anyone who&amp;rsquo;s intimiately familiar with how deeply-tied Microsoft&amp;rsquo;s browser and operating system are knows exactly what&amp;rsquo;s become necessary: In order to install IE7, I have to first uninstall IE8. However, in order to uninstall IE8, I have to revert the SP3 upgrade. This is a large and significant problem, because the upgrade itself cost me more than two hours! That process is currently running in the background as I write this (and checkout the current branch of the project to the small Celeron machine, dubbed &lt;em&gt;&lt;code&gt;mouse&lt;/code&gt;&lt;/em&gt;). I am, nonetheless, quite distinctly far from amused by Microsoft&amp;rsquo;s decision to make IE8 and SP3 so deeply integrated that, if IE8 is installed prior to SP3 (which I&amp;rsquo;m fairly sure is what happened; while Comodo had disable the majority of my connectivity, Windows Update continued to operate), then removing the former requires removing the latter &lt;em&gt;by design&lt;/em&gt;. It&amp;rsquo;s certainly further motivation to move to Europe!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-441484670001151833?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/02/in-which-author-retraces-his-steps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/441484670001151833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/441484670001151833'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/02/in-which-author-retraces-his-steps.html' title='In which the author retraces his steps&amp;hellip; slowly.'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-634187633787554008</id><published>2010-02-01T01:14:00.004-05:00</published><updated>2010-02-01T01:40:28.590-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='job search'/><category scheme='http://www.blogger.com/atom/ns#' term='Symfony'/><title type='text'>In which good news is announced</title><content type='html'>&lt;p&gt;The past&amp;hellip; roughly sixty-six hours have been pretty exciting in my neck of the woods, for a number of reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;I met a recruiter downtown regarding a twelve-month contract situated (if memory serves) very near to my home, for a major classifieds website you&amp;rsquo;ve probably heard of. I was told that my resum&amp;eacute; will be submitted, so hopefully I&amp;rsquo;ll be contacted for a phone interview.&lt;/li&gt;&lt;li&gt;I heard from another recruiter, this one with disappointing, but not altogether surprising, news: the client that had been given my resum&amp;eacute;, regarding a front-end position, said they&amp;rsquo;ll not be seeking an interview with me. Disappointing because it means no job there, but not surprising because the bulk of my skill set lies in back end development (as you&amp;rsquo;ve probably discovered, if you&amp;rsquo;ve been following my writing), with less emphasis on front end technologies. My Flash is rusty and creaky; I have no Flex or Air; I could keep going, but I&amp;rsquo;d rather not, because&amp;hellip;&lt;/li&gt;&lt;li&gt;Yet another recruiter got in touch with me about a brief, lucrative contract, working out of my home, picking up where another developer has had to bow out due to time pressures. He wanted to know how I&amp;rsquo;d feel about picking up a mostly-there project built on Symfony, with jQuery as the JavaScript framework: an MVC framework to which I have minimal (but positive) exposure, and the whipping-boy JS framework of comp.lang.javascript that I&amp;rsquo;ve never touched (I use Prototype in Project Alchemy and Project McLuhan). Recruiter knew this, passed on what I am familiar with and mentioned that I tested well in his company&amp;rsquo;s PHP skills test, and the client wanted to get in touch with me anyway. After a couple of hours to look at the source code, I was confident I&amp;rsquo;d be able to get myself up to speed with Symfony over the course of the weekend. I met with the client on Saturday over coffee, met with the previous developer on Sunday, and, well&amp;hellip; I&amp;rsquo;ve already nailed down two of the end user&amp;rsquo;s major &lt;em&gt;we-want-this-fixed-by-the-beginning-of-business-Wednesday&lt;/em&gt; bugs!&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;So yes, dear readers, I am (or rather, will be, once I&amp;rsquo;ve signed the contract) gainfully employed&amp;mdash;at least for the month of February! I feel good; I feel energised&amp;hellip; and I feel that by the middle of February I&amp;rsquo;ll have two new things I&amp;rsquo;ll be able to add to resum&amp;eacute;! I think my lack of previous jQuery has been a bit of a sticking point&amp;mdash;everybody uses it! So now, I&amp;rsquo;ll be able to say I can use jQuery.&lt;/p&gt;&lt;p&gt;This gig is going to be a great stretch of my skills. I&amp;rsquo;ve already hit the ground running (thank God that Symfony&amp;rsquo;s interpretation of MVC is fairly similar to Zend&amp;rsquo;s!), so as long as I hit this Wednesday&amp;rsquo;s deadline, everything should be great&amp;hellip; and I don&amp;rsquo;t see any reason why I won&amp;rsquo;t be able to hit it.&lt;/p&gt;&lt;p&gt;This was a good weekend, and one that I&amp;rsquo;ve been waiting for for quite a while now. With any luck, this contract will turn into further opportunities with this client, which will mean (fairly) regular work and more opportunities to expand what I do!&lt;/p&gt;&lt;p&gt;One closing note: Looking at Symfony, I have to say that I&amp;rsquo;m already pretty much in love with it. It&amp;rsquo;s got a very similar logic to Zend (and, near as I can tell, is similarly modular, which I like), but it&amp;rsquo;s got a lot of back-office automation, kind of like Cake and Rails, that unburdens the developers, and it doesn&amp;rsquo;t appear to be doing so in an ugly an inefficient way! I&amp;rsquo;m almost mad that I hadn&amp;rsquo;t found it in the summer of 2008&amp;mdash;so many things would probably be different! Project Alchemy would probably be much farther along than it is (I&amp;rsquo;ve been having trouble with the ORM layer and articulating join logic as associative arrays). Also, it&amp;rsquo;s kind of a pity that I&amp;rsquo;ve found it now, rather than long before, because I&amp;rsquo;m also about to start learning Python, which I&amp;rsquo;ve been meaning to do, in order to move away from the Failboat that will be PHP 6.&lt;/p&gt;&lt;p&gt;Ahh well, can&amp;rsquo;t always do everything right the first time you do it, right? Otherwise, you&amp;rsquo;d never learn anything!&lt;/p&gt;&lt;p&gt;Wish me luck this month; I&amp;rsquo;m going to be awfully busy!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-634187633787554008?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/02/in-which-good-news-is-announced.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/634187633787554008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/634187633787554008'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/02/in-which-good-news-is-announced.html' title='In which good news is announced'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8252740484154827644</id><published>2010-01-24T14:23:00.007-05:00</published><updated>2010-02-01T01:48:09.485-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='plea for sanity'/><title type='text'>In which software that wasn't properly engineered is shown to have killed people... again.</title><content type='html'>&lt;p&gt;My wife showed me an &lt;a href="http://www.nytimes.com/2010/01/24/health/24radiation.html"&gt;article in today&amp;rsquo;s online &lt;i&gt;New York Times&lt;/i&gt;&lt;/a&gt; (yesterday&amp;rsquo;s print edition) that got my blood boiling&amp;mdash;a radiation therapy machine manufactured and programmed by Varian Medical Systems wound up massively overdosing and killing two patients in 2005, just like Therac-25 did back in the eighties. The bad part is that Therac-25 is a standard case study for CS students throughout the continent (and probably worldwide), so this shouldn&amp;rsquo;t have happened in the first place. The worst is that Varian Medical Systems said it was pilot error. Now, as a software developer and a computer scientist, incidents like these are particularly poignant, as they demonstrate the urgent need for a cultural sea change within the industry.&lt;/p&gt;&lt;p&gt;A quick backgrounder: Therac-25 was involved in six known massive overdoses of radiation, at various sites, that killed two patients. A careful study of the machines and their operating circumstances was conducted and it was ultimately revealed that the control software was designed so poorly that it allowed almost precisely the same problem outlined in the Times&amp;rsquo; article. In Therac-25&amp;rsquo;s case, a higher-powered beam was able to be activated without a beam spreader in place to disperse the radiation, much like how the Varian Medical Systems machine allowed the collimator to be left wide open during therapy. Furthermore, the Therac-25 user interface, like the Varian interface, was found to occasionally show a different configuration to the operator than was active in the machine, as the article mentions: &amp;ldquo;when the computer kept crashing, &amp;hellip;the medical physicist did not realize that her instructions for the collimator had not been saved.&amp;rdquo; The same issue occurred with Therac-25, where operator instructions never arrived at the therapy machine. Finally, both interfaces failed to prevent potentially lethal configurations without some kind of unmistakable warning of the danger to the operator.&lt;/p&gt;&lt;p&gt;The Therac-25 incident quickly became a standard case study in computer science and software engineering programs throughout Canadian and American universities, so the fact that this problem was able to happen again is shocking, as is the fact that Varian Medical Systems and the hospitals in question deflected the blame onto the operators. The fact of the matter is that Varian&amp;rsquo;s machine is one that, when it fails to operate correctly, can maim or even kill people. In such a system, there is simply no room for operator error and it must be safeguarded against. Unfortunately, in shifting the blame, Varian Medical Systems has denied their responsibility in untold more tragedies.&lt;/p&gt;&lt;p&gt;Had a professional engineer been overseeing the machine&amp;rsquo;s design, these deaths could have been prevented. Unfortunately, most professional engineering societies do not yet recognise the discipline of software engineering, primarily because it is exceedingly difficult to define exactly what software engineering entails. For decades, software systems have been in positions where life and death are held in the balance of their proper operation, and it is critical, in these cases, that professional engineers be involved in their design. These tragedies underscore the need for engineering societies to begin licensing and regulating the proper engineering of such software. By comparison, an aerospace engineer certifies that an airplane&amp;rsquo;s design is sound, and when an airframe fails, those certified plans typically reveal that the construction of (or more often, later repairs to) the plane did not adhere to the design. Correspondingly, in computer-controlled systems that can fail catastrophically, as Varian&amp;rsquo;s has, it is imperative that a professional engineer certify that the design&amp;mdash;and in a computer program&amp;rsquo;s case, the implementation&amp;mdash;is sound.&lt;/p&gt;&lt;p&gt;Varian Medical Systems&amp;rsquo; response&amp;mdash;to merely send warning letters reminding &amp;ldquo;users to be especially careful when using their equipment&amp;rdquo;&amp;mdash;is appallingly insufficient. Varian Medical Systems is responsible for these injuries and deaths, due to their software&amp;rsquo;s faulty design and implementation, and I urge them to admit their fault. I recognise that it would be bad for their business, but it is their business practices that have cost lives and livelihoods. I think the least they could do is offer a &lt;em&gt;mea culpa&lt;/em&gt; with a clear plan for how they will redesign their systems to prevent these incidents in the future.&lt;/p&gt;&lt;p&gt;The IEEE, the ACM, and professional engineering societies need to sit up and take notice of incidents such as this. That they are still happening, even with the careful studies that have been performed of similar tragedies, is undeniable proof that software engineers are necessary in our ever more technologically dependent society, and that software companies must, without exception, be willing to accept the blame when their poor designs cause such incidents. Medical therapy technology must be properly engineered, or we will certainly see history continue to repeat itself.&lt;/p&gt;&lt;p style="font-size: 0.8em;"&gt;If this reads like a submission to the Op-Ed page, there&amp;rsquo;s a very good reason for that! It was, but they decided not to publish it. Oh well.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8252740484154827644?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.nytimes.com/2010/01/24/health/24radiation.html' title='In which software that wasn&apos;t properly engineered is shown to have killed people... again.'/><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-software-that-wasnt-properly.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8252740484154827644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8252740484154827644'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-software-that-wasnt-properly.html' title='In which software that wasn&apos;t properly engineered is shown to have killed people... again.'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8316224182936457267</id><published>2010-01-22T16:13:00.002-05:00</published><updated>2010-01-24T15:20:41.267-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='CakePHP'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='Project McLuhan'/><title type='text'>In which the author reflects on his career</title><content type='html'>&lt;p&gt;Without trying to sound like a couple of cartoon nine-year-olds, I realised something today—I’ve done a lot of pretty cool stuff in this industry. I might be young, but there’s something to be said for starting early, and always trying to challenge yourself. Let’s see what I can remember&amp;hellip; but I warn you, this is a long, long post.
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Portico/Project McLuhan CMS&lt;br/&gt;
Late last year, I delivered, to a freelance client, an early build of an original CMS that I called &lt;i&gt;Portico&lt;/i&gt;. I refer to it as &lt;i&gt;Project McLuhan&lt;/i&gt; when I’m coming up with new features, but it’s certainly not just a random exercise—it’s currently being used to serve up &lt;a href="http://www.bellabalm.com/" target="_new"&gt;bellabalm.com&lt;/a&gt;, the website of one of my wife’s colleagues. Since delivery, I’ve been working on enhancements to the user interface (lots of use of AJAX) as well as the core functionality, to make it a little more usable, but it was pretty complete on delivery. It links to PayPal for purchase completion, and Canada Post for shipping cost calculation, and honestly, the shipping calculator was probably the hardest to write, because it's all XML, and I hadn't used XSLT for about six months before I started into it.&lt;/li&gt;&lt;li&gt;Project Alchemy toolkit&lt;br/&gt;
In 2008 I worked for a company I describe as “social advertising agency”. At the time, I was one of two developers, and we jointly decided to standardise the company on Zend Framework, based primarily (if my memory serves me) on the fact that ZF was created by the same group of programmers who wrote PHP, so we good reason to believe that it would be the most effective for the job. A few months later, a couple of other developers were brought who knew Ruby on Rails, and with it, CakePHP. I’ll say this for Cake: it certainly enhances developer time for developers familiar with its API, and it seems to be a bit more clearly documented than Zend. However, from my work with it, it’s not as efficient in terms of database usage, so I can't really say I’m a fan (also, hearing one of these Ruby guys say, on about a weekly basis, “I HATE CAKE!” amused me). However, I did find really quickly that the Zend API is somewhat lacking. Project Alchemy was born out of my desire to merge the two&amp;mdash;to take everything I liked about Cake, and make it available in a Zend context, along with some other features that I’ve long thought were important. Of particular note is a full audit trail of all database changes (and optionally, queries), which is easier than you might think to write, and will benefit you in the long run in case Something Bad happens. I'm also trying to decide on the best approach to implement model caching; a course in operating system design late last year brought the notion of shared memory into my mind, so now it’s just a matter of actually putting it together. Project Alchemy’s by no means complete, in terms of everything I want to do with it, but the essentials are all there, and it’s been an amazing learning process.&lt;/li&gt;&lt;li&gt;Innumerable changes to CIBC.com, including a core role in the October 2009 redesign&lt;br/&gt;
I was on contract at CIBC for quite a while, but in a purely front-end role. Nevertheless, I got exposed to some fun technologies while I was there&amp;mdash;XSLT, XPath, XForms&amp;mdash;that I’ve been meaning to investigate but otherwise haven’t had the time to properly study. When the project to update the website’s layout and accessibility came up, I was glad to be involved in the project, because I got a chance to really stretch and refresh my front-end skills, including some neat CSS and JavaScript techniques. I refamiliarised myself with basic AJAX, and I’ve been using it a lot in Alchemy and McLuhan.&lt;/li&gt;&lt;li&gt;The back-end image manager for the “Radio Perez” mobile podcast site and iPhone app.&lt;br/&gt;
While I was working at that ad agency, I was asked to write a pretty bare-bones CMS to serve up images and ads to an iPhone app, as well as mobile-ready pages. Two cool things I got to do with this were using the GPS data from the iPhone to provide geographically-relevant data (specifically, serving up a particular button graphic depending on your proximity to one of the client's radio transmitters), and I used the scaffolding technique on this project to get the required functionality going early, before worrying about making it look right. I first saw this technique in use by the Cake developers at that agency, thought it was a good idea, and tried it out. Turns out that it’s a great idea, and I've been using it ever since. It helped me deliver bellabalm.com in time without worrying too much about making the back end look exactly perfect. It did what it needed to do well before launch, it just wasn’t too pretty.&lt;/li&gt;&lt;li&gt;An inter-social-network photo album (ad agency)&lt;br/&gt;
This one was only partially completed before the Radio Perez thing came up, so it got shelved (there were only a few developers in the company at the time), but it was going to be a pretty cool photo album, that users could get at from Facebook, MySpace, iGoogle&amp;hellip; wherever, really. I did my best to make it work like Facebook’s photo albums, but I couldn’t figure out how to make photos draggable to reorder them (might have been because I hadn’t properly researched JavaScript frameworks at the time), so instead I implemented a priority queue in JS to update the sequence numbers correctly in real time. As I said, it never got completed while I was there.&lt;/li&gt;&lt;li&gt;An inter-social-network discusson board (ad agency)&lt;br/&gt;
This was the first project the company did with the technique of opening up a social app to multiple social networks simultaneously. I think it’s gone on to become one of their flagship products, so I have to laugh that I came up with the original design, and figured out all the potential problems and issues in doing this kind of thing, and now they’re making a mint&amp;hellip; and then I get sad, because I remember that I’m still bound to a noncompetition agreement and I probably can’t do anything with that knowledge for a while yet. RIM used it, MTV used it, and I think Astral Media used it before it got refactored from Zend to Cake. It doesn’t seem to be running its original form anywhere anymore, so it looks like it’s been pretty thoroughly rewritten.&lt;/li&gt;&lt;li&gt;&lt;i&gt;RMAtic&lt;/i&gt; Return Merchandise Authorisation tracker&lt;br/&gt;
My first attempt at writing an issue tracker, and if I do say so myself, a successful one! This is where I first got the chance to write the audit trail I mentioned above with Project Alchemy, because if anything needs that kind of tracking, it’s an issue tracker. Some weird bit rot has set in that won't let me update the RMAs in the database that I haven’t been able to isolate, but if I ever want to do an issue tracker again, I’d be rewriting it from scratch--this was done before I had a chance to use Zend, so all the links between things are procedural. It’s not super-pretty code, when you get down to it. But then, I honestly didn’t expect to ever have to see it again, so I wasn’t concerned with code re-use. I’m told it takes three times as much effort to write reusable code than it does to write a one-off, and that’s exactly what this became! If you’re curious, though, &lt;a href="http://torch.cs.dal.ca%7e/coe/prophecy/rmatic"&gt;check it out&lt;/a&gt;. The username and password are both “admin”. It's still branded with the client’s livery.
&lt;/li&gt;&lt;li&gt;A client relationship and project manager&lt;br/&gt;
This was the last project I worked on at a custom software company north of the city. Based in equal parts the existing in-house CRM, their in-house CMS, and Basecamp, the notion was that I’d rewrite the CRM to be something that could be resold. I very carefully wrote up a specification for everything it was going to do, how everything would interact, how the permissions model would operate, a huge E-R diagram for it, and got to work. I was easily 80-90% of the way through it&amp;mdash;and all the core stuff was there; I think I was down to making it easy to install add-ins, and maybe one or two other features that I can’t quite recall&amp;mdash;when the contract ended, for a variety of reasons. It was hugely ambitious, I was the only person on the project, and I think I did a great job of it. It was able to handle all the different clients the company had, with infinitely-overlappable user groups, all the various projects, work tasks (it had a built-in issue-tracker), notes, phone calls, anything billable&amp;hellip; invoicing. The whole shebang, with a two-dimensional access control scheme that depended on what permissions the user/user group had on individual items and their parent items. Hugely complex, and I’ve realised in retrospect that (a) role-based access control is a far better idea in terms of software complexity, database load, and usability, and (b) the database table that held the permissions really needed to be indexed and stored with a different storage engine. You live, you learn. I’ve been meaning to write myself a simple CRM for my freelance clients, and the little snippets of memory I’ve still got about that project should at least help me get started. It’ll be done in either Project Alchemy or even Django, if I’ve become familiar enough with Python by the time I get started.&lt;/li&gt;&lt;li&gt;A shopping cart for an existing CMS (custom software company)&lt;br/&gt;
The client wanted to add a store to their website, so I had to learn the old version of the company’s CMS in a hurry and add a new store module to it. It wasn’t easy, particularly when trying to put the shopping cart together, and make sure that all the right information appeared on the right pages, but I did it, and it worked, and allowed customers to select from a bunch of different customisable options, as well as customising certain products. I realised, in the last month, that the user experience certainly left something to be desired, but again&amp;hellip; you live, you learn. I think it was, more than anything, an issue of nomenclature. I used “option” to refer to, say, a specific T-shirt size, and “option group” to refer to offering size as an option. I just didn't make it very intuitive, and I think I know how I’d do it better in the future.&lt;/li&gt;&lt;li&gt;An inventory manager for a warehousing and shipping company (custom software company)&lt;br/&gt;
This client stored materials for their clients, and need a way to allow the clients to see how many boxes of each they had warehoused, order some to be shipped, and be alerted when the level was dropping low so that new items could be made. Fairly straightforward, and served as a basis for the issue tracker I built into the CRM later. Users could get things shipped to the address of their choice, and it would remember past addresses to make things easier. Got the opportunity to put together a PDF template that exactly matched their existing shipping labels, so that was fun. First project I did there.&lt;/li&gt;&lt;li&gt;A really elemental blogging tool for my own use.&lt;br/&gt;
This was bad, hacky code. I put in only what features I needed, and it also served up static content stored in HTML files within a specific directory structure. I just wanted to write my own blog without having to edit the HTML every time. There were comments, but I started getting spammed, so I had to disable them. The only feature I actually built was writing new blog posts. Couldn’t even edit after the fact. But it was also the first database-driven thing I tried writing&amp;hellip; back in first year. I wanted to learn what it took to do it. There may be a reason why I use Blogger for it now&amp;hellip; it’s a more complex problem than I wanted to get into at the time. Maybe later, though.
&lt;/li&gt;&lt;li&gt;While I was in high school, I came up with a way of handling a multi-page ticket-ordering process for a theatre that didn’t require sessions. I didn’t really have access to the server that hosted it, and I didn’t understand session cookies at the time anyway (not that I could use them without being to able get at the server), so I used a frameset, with an invisible frame full of hidden inputs. The hidden inputs were updated by JavaScript, and the last page email their contents to the box office. It was quite interesting, and it was superceded a while ago.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That’s about it for proper projects that really saw the light of day, that I did something interesting with. A few things I came up that either didn't go anywhere or just weren’t really a technical achievement follow:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;You know how Jillian Michaels, one of the coaches on The Biggest Loser, now has a website where you can track your weight-training goals online, and interact with other people trying to do the same thing? I had that same idea while taking a strength training class in high school. Many, many moons ago. Used it as a project idea. Shelved it because I didn’t have the money to start it up as a business and advertise it. Now I’m kicking myself.&lt;/li&gt;&lt;li&gt;In grade school, I had the opportunity to make the school’s website. I wanted to coordinate with the teachers to put lesson plans up online, so that parents could keep aware of what their children were learning. Nobody really wanted to go along with it. In my final year of high school, I tried designing and implementing the same solution, on a high school level, in a way that would empower the teachers to put up what content the wanted&amp;hellip; it was really more ambitious than I expected, and all I have left are a few design documents. Then I started university, and discovered that WebCT and Blackboard existed&amp;hellip; they do exactly what I was trying to make for my school. D'oh!&lt;/li&gt;&lt;li&gt;Also in my last year of high school, I had the “brilliant” idea of trying to create a bash-like shell for MS-DOS&amp;hellip; in Perl. Like the course management tool I just described, this was far more ambitious of an idea than I ever expected it to be, probably because at the time, I didn't have much experience with Unix, and didn’t understand the domain of the problem. But it serves as a good example of the level of idea I tend to come up with: BIG. Sometimes revolutionary, sometimes just complex, but I think big. I like big problems that require a lot of thought.&lt;/li&gt;&lt;li&gt;Back in the bad old days, just when DVDs had first came out, my cousin and I designed a website for a video store in our hometown. Not very revolutionary there, but we had an idea that no one else did--show the movie trailers on the website. It’s obvious now, sure, but it wasn’t in 1997; only a small fraction of movies even had websites to begin with!&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, yeah&amp;hellip; I’ve been around. I’ve seen quite a bit, now that I think of it, and there’s probably a lot of stuff that I can’t properly remember that’s getting left out, fairly or unfairly. I should remember this.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8316224182936457267?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-author-reflects-on-his-career.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8316224182936457267'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8316224182936457267'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-author-reflects-on-his-career.html' title='In which the author reflects on his career'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-1168848906805220224</id><published>2010-01-16T14:36:00.009-05:00</published><updated>2010-01-17T13:48:47.681-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Project McLuhan'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>In which opportunities are taken</title><content type='html'>&lt;p&gt;The coming of the new year, like everyone is always told, has shown itself to be a time of new opportunities. However, what&amp;rsquo;s unusual this time around is that I&amp;rsquo;ve also been in a wonderful position to take the opportunities with which I&amp;rsquo;ve been presented. The software I&amp;rsquo;ve been slowly writing over the past roughly six months (dubbed, depending on what specific functions I&amp;rsquo;m working on, either of Project Alchemy or Project McLuhan) has forced me into a position to really clean up some of the core things&amp;mdash;that is, Project Alchemy&amp;mdash;I originally put off implementing for the sake of getting it out the door, and an outside project has finally given me an opportunity to make good on &lt;a href="http://mgpcoe.blogspot.com/2008/11/so-many-job-profiles-to-choose-from.html"&gt;my threat to learn Python&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;First things last.&lt;/p&gt;&lt;p&gt;Given the nature of this blog so far, and the fact that I&amp;rsquo;ve been using it to talk about technical matters from a reasonably professional point of view, I kind of wish this opportunity to learn Python had a more professional set of circumstances. On the other hand, it&amp;rsquo;s not as though I&amp;rsquo;ve ever tried to hide this particular circumstance; I&amp;rsquo;ve even &lt;a href="http://mgpcoe.blogspot.com/2009/03/you-learn-something-new-every-day.html"&gt;discussed it in this very blog&lt;/a&gt;. In my continuing attempts to finish my BCSc, I&amp;rsquo;m required to take an introductory software engineering course, and I&amp;rsquo;m part of a development team that will be making a product virtually guaranteed to be delivered over the web. At first, I thought that I might be able to make an argument for integrating Project Alchemy into the codebase to speed up development, but then I discovered that I&amp;rsquo;m the only member of the team who has &lt;em&gt;no&lt;/em&gt; experience with Python, and no one else seems to know PHP. As a result, It&amp;rsquo;s kind of a given that we&amp;rsquo;ll be using Python, so I have a fairly steep learning curve ahead of me to get caught up. The University of Toronto&amp;rsquo;s Computer Science department uses Python as the language of choice for its first year classes, so everyone else has had at least a year of active (albeit toy) development with the language, and I have less than two-and-a-half months on this project, in which to provide real, tangible support. No time to lose!&lt;/p&gt;&lt;p&gt;On the other hand, I think I have more project planning experience than the rest of the team&amp;mdash;I remember how slapdash my programming practice was at Dalhousie, but this is a real-world product&amp;mdash;so I think I might be able to make up my gaps in language experience by taking care of more the behind-the-scenes things in the management of the project. I&amp;rsquo;ve been kind of spearheading that already, but it hasn&amp;rsquo;t really been particularly set it stone who&amp;rsquo;s doing it. I guess we&amp;rsquo;ll see how this works out. With any luck, our client will get a solid piece of code and I&amp;rsquo;ll get some realistic experience in project management, which can only ever serve to benefit me professionally, for reasons that seem fairly obvious.&lt;/p&gt;&lt;p&gt;In terms of Project Alchemy, like I said, I put off implementing Alchemy functions for the sake of getting Project McLuhan (and more specifically, my client&amp;rsquo;s website) out the door on schedule. As a result, fairly important architectural things like multi-model find calls were put on the back burner while I dealt with end-user issues like a shipping rate calculator. Now that it&amp;rsquo;s been delivered, I&amp;rsquo;m trying to clean up the McLuhan interface to improve its usability, and I&amp;rsquo;m realising just how critical that functionality is.&lt;/p&gt;&lt;p&gt;Admittedly, part of my initial hesitance in implementing it up-front was a certain degree of intimidation by the problem&amp;mdash;a large part of the design involved coming up with a way of compartmentalising WHERE clauses&amp;mdash;rather than simply requiring the find conditions to be input as a string, abstracting it out to better insulate against malformed data from the end user. As it turned out, it wasn&amp;rsquo;re exceedingly difficult (with two caveats: I still have yet to come up with a way of handling subqueries for the IN/NOT IN operators, and I&amp;rsquo;m not convinced that I&amp;rsquo;ve done it in a particularly efficient manner), but now I have to go back through all my controllers and models and rewrite the find calls to use the new schema. It&amp;rsquo;s a bit of a pain&amp;mdash;yet another example of why Doing It The Right Way First will invariably save you time in the long run&amp;mdash;but it&amp;rsquo;s ultimately worth it, because it&amp;rsquo;s also providing a good opportunity to review my own code and look for bad algorithms.&lt;/p&gt;&lt;p&gt;So, yeah, there have been a couple of great opportunities so far this year that I feel I&amp;rsquo;ve really been able to taken advantage of. One great opportunity to learn a language I&amp;rsquo;ve been meaning to learn for more than a year, and another to finish up something important and learn a good deal more about what really goes into writing an MVC framework. This can only possibly be good for me, so stay tuned to see what develops!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-1168848906805220224?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-opportunities-are-taken.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/1168848906805220224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/1168848906805220224'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2010/01/in-which-opportunities-are-taken.html' title='In which opportunities are taken'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-3955165709221955834</id><published>2009-12-11T09:00:00.000-05:00</published><updated>2009-12-11T09:01:04.819-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><category scheme='http://www.blogger.com/atom/ns#' term='old ideas'/><category scheme='http://www.blogger.com/atom/ns#' term='plans'/><title type='text'>A question of prudence</title><content type='html'>&lt;p&gt;Some time ago (and by &amp;ldquo;some time&amp;rdquo;, I mean &amp;ldquo;roughly eleven years&amp;rdquo;), I came up with an idea for a strategy game that would be grander in scope than all other strategy games. I don’t recall if it was to be multiplayer (though I doubt it), but I recently realised that, using social platforms like Facebook, MySpace, OpenSocial, &amp;amp;c., it’s quite doable, and with a gentle nod to the strategy games of yesteryear.&lt;/p&gt;&lt;p&gt;Now, I’ve forgotten, in the intervening decade, a lot of the detail. I seem to recall that the original version was supposed to include a first-person mode, which I’m uncertain if I’d be able to create even now. I knew I couldn’t then, and I doubt, highly, that with a social platform, first- or third-person view would even be an option. I’m not exactly what you might call &amp;ldquo;proficient&amp;rdquo; with applications like Flash or Silverlight.&lt;/p&gt;&lt;p&gt;I’ve started to write some of the plans down about how the game mechanics might work. I’ve found that, with the proper planning, it could allow players to control not only vast empires, but even small parcels of land, or even just groups of AIs. Players could govern each other under the right circumstances, and a player whose empire was governed by another could feasibly rise up against his former master.&lt;/p&gt;&lt;p&gt;It almost wouldn’t be a game, as much as it would be a simulation, on a grand scale, of the development of intelligent civilization (and yes, I know, there’s already a popular franchise of strategy games with that name&amp;hellip; this game would be, in general, a step removed from the necessary micromanagement that I find Mr Meier’s game espouses). The difficulty that I have is that I want to talk about it, but I don’t want to have my ideas stolen by a programmer with more time, or (more likely) a team of subordinates to do the work. Any suggestions for how I could discuss this notion? I'm afraid that if I let my momentum flag, it’ll be another ten years before anything gets done on this!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-3955165709221955834?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2009/12/question-of-prudence.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/3955165709221955834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/3955165709221955834'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2009/12/question-of-prudence.html' title='A question of prudence'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-1892864305683726579</id><published>2009-11-05T15:08:00.004-05:00</published><updated>2010-01-24T15:21:55.977-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB'/><category scheme='http://www.blogger.com/atom/ns#' term='CakePHP'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='RAD'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><title type='text'>In which the author learns that any great Web application developer needs to be half DBA</title><content type='html'>&lt;p&gt;The latest section of study in my database tuning class has focused on transactions and crash recovery. As with table indices, I&amp;rsquo;ve been aware of transactions on, shall we say, a theoretical level: I knew what they were, and I knew that they were useful for grouping queries together for atomicity. However, it somehow didn&amp;rsquo;t occur to me how spectacularly important they are if you&amp;rsquo;re writing a web application that has relation constraints, in order to maintain database consistency.&lt;/p&gt;&lt;p&gt;Perhaps it was merely that my previous argument had been, &amp;ldquo;but each request will be executed in less than a second!&amp;rdquo; That doesn&amp;rsquo;t matter when you&amp;rsquo;re trying to serve content to, say, more than ten thousand requests in an hour. On average, that&amp;rsquo;s one request every 0.36 seconds. But we all know that it doesn&amp;rsquo;t work out like...&lt;/p&gt;&lt;ol&gt;&lt;li&gt;0:00.00: Request&lt;/li&gt;&lt;li&gt;0:00.36: Request&lt;/li&gt;&lt;li&gt;0:00.72: Request&lt;/li&gt;&lt;li&gt;0:01.04: Request&lt;/li&gt;&lt;li&gt;0:01.40: Request&lt;/li&gt;&lt;li&gt;&amp;amp;c&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;That just doesn&amp;rsquo;t happen. At ten thousand requests per hour, you will almost certainly see overlap in your requests. This means, of course, that if you have an application that involves relational constraints, foreign keys, and really, anything where you have to reflect a change in table A in table B in such a way that every request is consistent, that change has to be applied to both tables before another request is allowed to query either. &lt;em&gt;This&lt;/em&gt; is why you need transactions.&lt;/p&gt;&lt;p&gt;I never really thought about it in terms of even modest usage patterns like that. The textbook went over it in more depth, more in a context of what considerations a DBMS programmer has to be aware of, but it was a great reminder. Just two concurrent transactions, one writing two tables, and another reading those two, can display errors in the data if the read transaction reads table A after it&amp;rsquo;s been changed, but reads table B before its change has been applied.&lt;/p&gt;&lt;p&gt;It retrospect, it&amp;rsquo;s so obvious. Unfortunately, I haven&amp;rsquo;t ever&amp;mdash;and I mean ever, in my entire professional career&amp;mdash;met a web application programmer who actually used transactions, and didn&amp;rsquo;t just blithely let their database autocommit every update as soon as the query was completed. Nobody does this, and why? At a guess, because it takes extra programmer time. Only one PHP framework I know of forces transactions by default (hint: It&amp;rsquo;s not Zend&amp;hellip; something else I need to add in to my Still Unnamed Project), but what about developers making their own frameworks? Not using frameworks? Using a framework that relies on the programmer to specifically start transactions? It won&amp;rsquo;t happen, because so much emphasis is put on reducing programmer time that no one really, properly, considers taking the extra hour, or day, or even, at worst, week, to plan things ahead and properly insulate against failure from step one.&lt;/p&gt;&lt;p&gt;But it does go to show how important proper planning is to being able to do this kind of work properly. Proper analysis of your tools and knowledge on the programmer&amp;rsquo;s part of what needs to go in to the software is what makes for better software in the long run. Seriously, take the little bit of extra time to do it right, and improve your product&amp;rsquo;s performance. How much does a day or two cost&amp;mdash;once&amp;mdash;relative to how much an extra server costs every month to compensate for inefficient code?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-1892864305683726579?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2009/11/in-which-author-learns-that-any-great.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/1892864305683726579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/1892864305683726579'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2009/11/in-which-author-learns-that-any-great.html' title='In which the author learns that any great Web application developer needs to be half DBA'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-658023306728042931</id><published>2009-03-19T23:36:00.004-04:00</published><updated>2010-01-24T15:22:49.270-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><title type='text'>You learn something new every day</title><content type='html'>&lt;p&gt;I&amp;rsquo;m willing to admit when I&amp;rsquo;ve been wrong, mistaken, or just poorly informed about something. I&amp;rsquo;m always happy to learn new tricks, and useful ways to improve my productivity, and my code&amp;rsquo;s efficiency&amp;hellip; but a lesson I just learned last night takes the cake for things I wish I&amp;rsquo;d known years ago.&lt;/p&gt;&lt;p&gt;After more than two years spent outside of studying, I&amp;rsquo;ve finally started to get things back in gear to complete my B.C.Sc. degree (Brief explanatory digression: I had to suspend my studies a year before they were finished due to lack of funds, and then a series of layoffs after moving to Toronto has consistently interrupted my ability to resume). I&amp;rsquo;m currently taking two courses by correspondence: Small Business Management and Distributed Database Systems and Database Tuning. The first topic in the DB Tuning course is a brief analysis of difference database indexing methods, in terms of how the DBMS manages the pages and records under certain structures. I&amp;rsquo;ve been seeing indexing options for years now, fiddling with phpMySQLAdmin, but I&amp;rsquo;ve never really been clear on how the indexing worked, from an internal point of view. Never looked into it, just as I never looked into JOINing tables instead of relying on the WHERE clause&amp;hellip; and when the light went on, reading the textbook, it nearly blinded me.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m not going to get into the details of it here, primarily because I don&amp;rsquo;t feel 100% confident in my correct understanding of the mechanisms used, but I realise now that I&amp;rsquo;ve been treating my databases as magical blackboxes a little bit too much. It&amp;rsquo;s a pretty rich statement, coming from the guy who says he does his work better when he has a more thorough understand of the whole system, from top to bottom. This kind of thing certainly demonstrates how true that is, though. For, literally, years, I&amp;rsquo;ve been treating DBMSes as though they just magically know how to organise my data to be able to get at the records I need quickly. I&amp;rsquo;ve strongly espoused letting the database do the hard work of returning a specific set of tuples, instead of pulling back a huge range of candidate tuples, and letting the host language (PHP, in my case) decided yea or nay about each record, on the grounds that the DBMS has been designed to do that kind of thing, and really well. And I&amp;rsquo;d like to think that&amp;rsquo;s still true, but man alive, it&amp;rsquo;s clearer than ever that I still have a lot to learn about writing database driven applications.&lt;/p&gt;&lt;p&gt;On that note, I unfortunately have to admit that my Zend enhancement/application template has stalled. But don&amp;rsquo;t worry, I already have an excuse lined up and ready to go: between my new job, going back to school and a play that&amp;rsquo;s been in rehearsal since the beginning of the year, I&amp;rsquo;ve had precious little time to work on my own, personal projects, which is unfortunately what that project is. Educational, certainly. Valuable to the wider community? Possibly. An interesting problem to work, most certainly. But also something that is simply not my highest priority, and my time feels pretty stretched most days. Besides, I&amp;rsquo;m still stuck at the logging functionality and integrating it better as a Model, and in turn, redesigning my Model superclass. I've been debating whether or not I should create an Object superclass as well, for better adherence to MVC, or whether that would just be unnecessarily reinventing the wheel (unlike the project, which I feel is a fairly necessary reinvention of the wheel).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-658023306728042931?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2009/03/you-learn-something-new-every-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/658023306728042931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/658023306728042931'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2009/03/you-learn-something-new-every-day.html' title='You learn something new every day'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-389806890111189682</id><published>2009-01-14T21:21:00.004-05:00</published><updated>2010-01-24T15:23:23.718-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Sometimes, reinventing the wheel becomes necessary.</title><content type='html'>&lt;p&gt;I believe I&amp;rsquo;ve found that a previous entry, &lt;a href="http://mgpcoe.blogspot.com/2008/11/model-model-my-kingdom-for-model.html"&gt;&lt;span style="font-style: italic;"&gt;A Model! A Model! My kingdom for a Model!&lt;/span&gt;&lt;/a&gt;, was written, perhaps, a little hastily. Some further analysis, and review of another Zend-based project, has revealed that the Zend_Db functions do provide some Model functionality, with the Zend_Db_Table and Zend_Db_Tablerow classes.&lt;/p&gt;&lt;p&gt;However, I maintain that they&amp;rsquo;re ineffective as a Model, if for no other reason than it restricts to user to thinking of Models as extensions of the database. This is simply not true. The Model should just exist as an abstract, and if the application requires for the majority of the Models to be stored in a database, then by all means, it should put them there. But the framework shouldn't necessarily require it.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve come to that opinion while working on my own ZF application template. I realised over the Christmas holidays that my own Model class is somewhat restrictive&amp;hellip; because it requires the database! I've since forgotten how I came up with the idea&amp;mdash;I think it had something to do with storing uploaded images in the filesystem, rather than as binary blobs in a database, that I realised that a Model should really be more like an interface, with find(), set(), write(), &amp;amp;c. methods that need to be implemented by, say, a triad of DatabaseModel, FileModel and MemoryModel classes. Perhaps even a SessionModel or CookieModel, but I think that might be pushing it.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been giving this same notion a little bit of thought over my recent hacking runs as a solution to a problem I&amp;rsquo;ve been running into. What's happening is that I want to implement a combination flash messenger and logger. Why? Well, it&amp;rsquo;s (I hope) fairly simple.&lt;/p&gt;&lt;p&gt;During a given execution of the application, any number of messages may need to be delivered to the user. Say, for example, a user wants to upload five images to the application. Four of them work, and we want to tell the user this, but one of them failed, and we want to tell the user this, as well. ZF&amp;rsquo;s FlashMessenger can kind of do that, but either all the messages have to appear in the same context, or the messages have to be rendered on the way &lt;em&gt;into&lt;/em&gt; the messenger. This isn&amp;rsquo;t ideal, for the simple reason that it&amp;rsquo;s putting View logic into a Model. Thanks, but no.&lt;/p&gt;&lt;p&gt;So, I thought that, since I&amp;rsquo;m already using Zend_Log to capture runtime information that I might want displayed in a debugging situation, maybe I could pull the logged information out of that in the layout. No such luck; Zend_Log doesn&amp;rsquo;t let me access its writers. After that, maybe I can write my own Zend_Log to write to a Zend_View&amp;rsquo;s placeholder, right?&lt;/p&gt;&lt;p&gt;If only it were actually that simple. I don&amp;rsquo;t really want to think about how much extra effort that&amp;rsquo;s going to involve, wading through the verbose, but less-than-useful ZF Reference Guide, the less-verbose, sometimes-useful ZF APIs, and just digging through the actual code to figure out how all this stuff fits together.&lt;/p&gt;&lt;p&gt;Or, I could just go the route I&amp;rsquo;ve already been going with my Model and Database classes, and roll my own functionality that does what I need it to do. Part of the point of this project was to identify the parts of ZF that fall short of what I, and possibly other programmers, need, and fill in what&amp;rsquo;s missing. To have a skeleton of an application pre-built that offers a lot of highly-useful, rarely-requested features.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m starting to think that as time goes on, I might wind up having to replace some more core elements of any MVC framework so that things in my own stuff work together more smoothly. God knows, I might even wind up building my own framework out of this!&lt;/p&gt;&lt;p&gt;How that affects my desire to move away from PHP and towards Python is, as yet, unknown, but it might help. It&amp;rsquo;ll certainly provide a hell of a groundwork for a first project in a new language!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-389806890111189682?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2009/01/sometimes-reinventing-wheel-becomes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/389806890111189682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/389806890111189682'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2009/01/sometimes-reinventing-wheel-becomes.html' title='Sometimes, reinventing the wheel becomes necessary.'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8517070302047110365</id><published>2008-11-25T08:17:00.001-05:00</published><updated>2009-11-05T15:41:31.952-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySpace'/><category scheme='http://www.blogger.com/atom/ns#' term='Facebook'/><title type='text'>Why it makes sense to give your money to Facebook</title><content type='html'>&lt;p&gt;I recognise I&amp;rsquo;m a little late coming to the table on this one, so anyone who reads this post probably already knows: Facebook is considering charging application developers to have their applications listed in the app directory. And there&amp;rsquo;s a pretty big backlash&amp;hellip; and I think MySpace feels pretty damn smug about the whole thing.&lt;/p&gt;&lt;p&gt;Here&amp;rsquo;s the neat thing: The amount of money that&amp;rsquo;s being spent, which is fairly considerable for solo developers, but a drop in the bucket for larger companies (about $400 to get it listed, then $100 a year to keep it there), is providing you with added value. Or in business-speak, it&amp;rsquo;s a value-add! Your $400 isn&amp;rsquo;t requred to let people use your application, it goes to have your application certified by Facebook, and listed in the directory. You get increased visibility in user news feeds and a little stamp on your application info page that assures that the application is safe. Your money goes somewhere. You benefit from spending it.&lt;/p&gt;&lt;p&gt;But remember, kids: anyone can develop an application for Facebook, make it publicly available, and advertise it. Absolutely anyone. There&amp;rsquo;s no barrier to entry. If you&amp;rsquo;re quick enough, this entire process can happen in one day, and you don't have to give a red cent to Facebook. With MySpace, you have to apply to be a developer, providing MySpace with your phone number so they can verify your identity (there&amp;rsquo;s at least one day lost, sometimes two), and then every application you develop has to be authorised by a member of the MySpace staff before anyone else can use it.&lt;/p&gt;&lt;p&gt;MySpace laughs, because they certify every application for free. But it can take as much as a week to hear back from MySpace, sometimes more, and if this is the first time you&amp;rsquo;ve made an application, you&amp;rsquo;ll probably have to resubmit it several times. Developing a MySpace application involves a great deal of waiting on them before anyone other than yourself can do anything. Everything&amp;rsquo;s &amp;ldquo;certified&amp;rdquo;, and that&amp;rsquo;s all well and good, but it takes a lot longer, and working with MySpace&amp;rsquo;s application verification team is an exercise in frustration.&lt;/p&gt;&lt;p&gt;Facebook is providing an optional service which, yes, improves their revenue stream, but gives application developers a tangible benefit over the usual model. As I said, increased visibility, publication in the application directory and a badge for your application, assuring your users that your application is safe to use. All this for $400 up front and $100 a year. Less than $0.30 a day. If you have a need for those benefits, you probably have financial backing for your app. You have an incoming revenue stream that outpaces what Facebook is asking by a long shot.&lt;/p&gt;&lt;p&gt;And if you&amp;rsquo;re a software company who write applications for other companies, you can always build it into your price and say &amp;ldquo;every application we write is certified by Facebook.&amp;rdquo;&lt;/p&gt;&lt;p&gt;It&amp;rsquo;s a great option. If you want it, it&amp;rsquo;s there. If you don't&amp;hellip; don't worry about it! As the ING Direct guy says, save your money!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8517070302047110365?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/i-recognise-im-little-late-coming-to.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8517070302047110365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8517070302047110365'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/i-recognise-im-little-late-coming-to.html' title='Why it makes sense to give your money to Facebook'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-6525407673776452071</id><published>2008-11-07T17:36:00.001-05:00</published><updated>2010-01-24T15:21:04.594-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Project Alchemy'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><title type='text'>A model! A model! My kingdom, for a model!</title><content type='html'>&lt;p&gt;At my last position, I was introduced to the formal concept of the Model-View-Controller architecture, specifically by way of &lt;a href="http://framework.zend.com/"&gt;Zend Framework&lt;/a&gt;. It&amp;rsquo;s a good framework. I enjoy using it a great deal, if for no other reason than the fact that it isn&amp;rsquo;t a &lt;a href="http://catb.org/jargon/html/B/bondage-and-discipline-language.html"&gt;bondage-and-discipline&lt;/a&gt; framework; I don&amp;rsquo;t have to use ZF&amp;rsquo;s functionality if I don&amp;rsquo;t want to.&lt;/p&gt;&lt;p&gt;But, it bears saying that the one function that ZF needs, that it doesn&amp;rsquo;t have, is a Model class. It has a Controller. It has a View. It has Layouts and Helpers, even a Paginator, for crying out loud, but it has no model. I feel this is a key component to the Model-View-Controller architecture. It&amp;rsquo;s even mentioned in the name. But ZF has no Model.&lt;/p&gt;&lt;p&gt;This leads, if you&amp;rsquo;re not careful, or ZF is your introduction to MVC, to a fairly significant error in design. The purpose of the Controller is to direct traffic between the user, the model and the view. Make sure the user should be able to do what they&amp;rsquo;re trying to do, see if there was a transmission failure in the case of user uploads, but really, your controller needs to small. Skinny controller, fat model, is what an old co-worker of mine advised the team. And I happen to agree with him.&lt;/p&gt;&lt;p&gt;The model is where all the heavy lifting involving your data goes. Controller tells the model, &amp;ldquo;I want a set of your objects that satisfy these conditions,&amp;rdquo; and the model goes and gets it. Controller tells the model, &amp;ldquo;Make an instance of yourself from this data, then store it,&amp;rdquo; and the model does it. Controller Actions should be tiny. You should be able to see an average of three on a screen.&lt;/p&gt;&lt;p&gt;But if you use ZF and you&amp;rsquo;re not fantastically careful about it, you&amp;rsquo;ll end up with a Controller that does all your work. That&amp;rsquo;s the one advantage I&amp;rsquo;ve seen about other frameworks like CakePHP. While you pretty much have to use Cake&amp;rsquo;s functionality, you use MVC correctly.&lt;/p&gt;&lt;p&gt;And that&amp;rsquo;s why I'm making a ZF application template that, by God, has a basic Model class to be extended.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-6525407673776452071?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/model-model-my-kingdom-for-model.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6525407673776452071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/6525407673776452071'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/model-model-my-kingdom-for-model.html' title='A model! A model! My kingdom, for a model!'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2538137900778784501.post-8679539683824954695</id><published>2008-11-04T11:55:00.001-05:00</published><updated>2010-01-24T15:21:11.783-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='job search'/><title type='text'>So many job profiles to choose from..!</title><content type='html'>&lt;p&gt;It&amp;rsquo;s really spooky, looking through jobs on Monster.ca, and noticing that every job in their &amp;ldquo;Featured Jobs&amp;rdquo; skyscraper box is listed in Ft. Meade. More so when you pick one at random and see that security clearance is a job requirement. As inexorably cool as it would be to work for the NSA, albeit indirectly, that would also be pretty stressful.&lt;/p&gt;&lt;p&gt;Besides, I&amp;rsquo;m Canadian. If I wanted to work for the spooks, I&amp;rsquo;d be applying at CSIS and CSE. I guess they&amp;rsquo;re not hiring.&lt;/p&gt;&lt;p&gt;What I am looking for, as of this point in time, is something in PHP development or system administration. While I can say pretty certainly that my days of writing PHP code are numbered, ever since I read about what the &lt;a href="http://loveandtheft.org/2008/10/26/set-sail-for-fail-php-namespaces/"&gt;new namespace token&lt;/a&gt; is going to be, it&amp;rsquo;s also what I have the most expertise in, and frankly, it's what&amp;rsquo;s going to get me working. I&amp;rsquo;ll experiment with Python once I&amp;rsquo;m getting a steady paycheque again. If you happen to need a PHP guy, &lt;a href="http://www.linkedin.com/in/matthewgpcoe"&gt;I&amp;rsquo;m your man&lt;/a&gt;. I like Zend as a framework; I'm not entirely sure that&amp;rsquo;s mentioned on my LinkedIn profile.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2538137900778784501-8679539683824954695?l=mgpcoe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/so-many-job-profiles-to-choose-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8679539683824954695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2538137900778784501/posts/default/8679539683824954695'/><link rel='alternate' type='text/html' href='http://mgpcoe.blogspot.com/2008/11/so-many-job-profiles-to-choose-from.html' title='So many job profiles to choose from..!'/><author><name>Matthew G P Coe</name><uri>http://www.blogger.com/profile/10109016763634756319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://lh5.ggpht.com/_xtyp_45owOg/SZc29pevPAI/AAAAAAAAADA/9zg8ElFx5cg/n94801579_32304082_1438.jpg'/></author><thr:total>0</thr:total></entry></feed>
