<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CE4FQHg_eCp7ImA9WxBUEk0.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120</id><updated>2010-02-26T08:48:31.640-08:00</updated><title>Chris Moyer</title><subtitle type="html">Run With The Cloud</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.coredumped.org/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.coredumped.org/" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ChrisMoyer" /><feedburner:info uri="chrismoyer" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEUEQHcyeyp7ImA9WxBUEUk.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-8224572533853407203</id><published>2010-02-25T15:56:00.000-08:00</published><updated>2010-02-25T15:56:41.993-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-25T15:56:41.993-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="boto" /><category scheme="http://www.blogger.com/atom/ns#" term="sdb" /><category scheme="http://www.blogger.com/atom/ns#" term="amazon web services" /><category scheme="http://www.blogger.com/atom/ns#" term="aws" /><title>Creating Sequences using SDB</title><content type="html">Thanks to &lt;a href="http://aws.amazon.com/simpledb/#consistent"&gt;the new functionality in Amazon's SimpleDB&lt;/a&gt;&amp;nbsp;we can now choose to have consistent DBs instead of highly scalable ones. Previously if we wanted to have a database that was&amp;nbsp;guaranteed&amp;nbsp;to be consistent right away, our only choice was to use our own SQL database, or use &lt;a href="http://aws.amazon.com/rds/"&gt;RDS&lt;/a&gt;.&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;But why would you want to trade in performance and availability for consistency? It's quite simple, if you've ever tried to generate sequential numbers for any reason (typically because people don't like using random UUIDs), then you know the ONLY way to do this is by using a locking mechanism. Since SDB was previously only eventually consistent, this made it impossible to use such a database for that purpose.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Thanks largely to&lt;a href="http://www.elastician.com/2010/02/stupid-boto-tricks-2-reliable-counters.html"&gt; Mitch Garnaat's post about how to create Counters&lt;/a&gt;, I've been able to create a "Sequence" object for boto that will allow you to persist a SequenceGenerator into SDB, and use it reliably across multiple locations, threads, and processes. This new functionality is now in boto.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Using this new sequence object is relatively simple. First, if you have a [DB] section already in your boto.cfg, it's easy to set up a default domain for your sequences. The Sequence object will look first for a key "sequence_db", and if that doesn't exist it will fall back to "db_name" which is used by the rest of the boto.sdb.db module as well. A sample config section would look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;code&gt;&lt;br /&gt;
[DB]&lt;br /&gt;
db_name = default&lt;br /&gt;
sequence_db = sequences&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
Next it's time to launch up python and start playing around.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from boto.sdb.db.sequence import Sequence&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s = Sequence() # Note that we can pass in an optional name&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.id #&amp;nbsp;but if we don't it just uses a UUID&lt;br /&gt;
'1ce3eb7b-3fdd-4c60-b243-ec33019090bd'&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.val # The value is set to the first value in our set&lt;br /&gt;
0&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next() # Lets get the next value in this set&lt;br /&gt;
1&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s2 = Sequence(s.id) # Lets load up this set in another object&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s2.val # The value should be the same, even if this was somewhere else&lt;br /&gt;
1&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next() # We increment our first object&lt;br /&gt;
2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s2.val # And when we look at the second object it's also incremented&lt;br /&gt;
2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.delete()&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;So that's all fine and dandy if we're just using a simple sequence, but what if we want to do something more complicated like a fibonacci sequence? Lucky for us this is built into our sequence module:&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; from boto.sdb.db.sequence import fib&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s = Sequence(fnc=fib)&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.val&lt;br /&gt;
1&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next()&lt;br /&gt;
1&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next()&lt;br /&gt;
2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next()&lt;br /&gt;
3&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next()&lt;br /&gt;
5&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.next()&lt;br /&gt;
8&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; s.delete()&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;But what is this "fnc" argument you ask? Quite simply the sequence object allows you to pass in a custom function that determines how to get the next value in the sequence. This function is passed in both the current value, and the previous value in the sequence. The fibonacci function, which you could have made yourself, simply looks like this:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;def fib(cv=1, lv=0):&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;"""The fibonacci sequence, this incrementer uses the&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;last value"""&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if cv == None:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cv = 1&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if lv == None:&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;lv = 0&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;return cv + lv&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;The important things here to remember is that the first value in the sequence must be returned if both the first and second values passed into the function are "None". The first value passed into this function is the "current" value of the sequence, and the second value passed in is the "last" or "previous" value that was in the sequence just before our current value.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;So this is great if you're dealing with integers, but what if I want to increment a string, or a double, or for that matter any random sequence? Lucky for us the cast type is determined automatically, so whatever types you have in your sequence will be the types that come back out of it. So, for example, if you have a string sequence that you want to increment easily, you can use the "increment_string" function:&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; from boto.sdb.db.sequence import increment_string&lt;br /&gt;
&lt;div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s = Sequence(fnc=increment_string)&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.val&lt;/div&gt;&lt;div&gt;'A'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'B'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'C'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.val = "Z"&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'AA'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.delete()&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;So what's the magic of this "increment_string" function? Let's take a look:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;increment_string = SequenceGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ")&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;What's this SequenceGenerator stuff? Quite simply you can pass in either a string or a list and it'll use that to determine what the next value in the sequence should be. You can also pass in an optional value called "rollover" which will prevent the sequence from "rolling over" and instead just make it return back to the initial value, so instead of going from "Z" to "AA", it would go back to "A":&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; from boto.sdb.db.sequence import SequenceGenerator&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s = Sequence(fnc=SequenceGenerator("ABC", True))&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.val&lt;/div&gt;&lt;div&gt;'A'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'B'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'C'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.next()&lt;/div&gt;&lt;div&gt;'A'&lt;/div&gt;&lt;div&gt;&amp;gt;&amp;gt;&amp;gt; s.delete()&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: Times;"&gt;With this new SequenceGenerator, and the Sequence object now available in boto.sdb.db, you should now be able to generate any sort of sequence kept in SDB that you could think of.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-8224572533853407203?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tZtKfNCoL3nhfEjETsGrCqhWz9s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tZtKfNCoL3nhfEjETsGrCqhWz9s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tZtKfNCoL3nhfEjETsGrCqhWz9s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tZtKfNCoL3nhfEjETsGrCqhWz9s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/lxDJa8bid0A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/8224572533853407203/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=8224572533853407203" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/8224572533853407203?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/8224572533853407203?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/lxDJa8bid0A/creating-sequences-using-sdb.html" title="Creating Sequences using SDB" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2010/02/creating-sequences-using-sdb.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cGRXw7fSp7ImA9WxBRF04.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-508612439692666303</id><published>2010-01-05T14:37:00.000-08:00</published><updated>2010-01-05T14:37:04.205-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-05T14:37:04.205-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="pyflakes" /><category scheme="http://www.blogger.com/atom/ns#" term="OSX" /><category scheme="http://www.blogger.com/atom/ns#" term="vim" /><category scheme="http://www.blogger.com/atom/ns#" term="developers" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>OSX, Vim, and Python</title><content type="html">I've been using python and vim for the past few years as my sole development environment since I hate GUIs, and I love how simple and powerful vim really is. I started off with &lt;a href="http://blog.dispatched.ch/2009/05/24/vim-as-python-ide/"&gt;a simple tutorial&lt;/a&gt;, and then expanded from there to develop my own custom IDE. I recently discovered that vim7 has support for running python commands inline. This only further's my love of vim.&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;I also recently discovered a nice little checker for vim called &lt;a href="http://divmod.org/trac/wiki/DivmodPyflakes"&gt;pyflakes&lt;/a&gt;. This program allows you to check python scripts for simple errors that are detected at compile time in languages that support that sort of thing. It includes being able to check for un-imported modules, typos, and even things that you imported that you didn't use within that module.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The problem is that I'm using Mac OSX, which comes with vim that isn't compiled with "--enable-pythoninterp", so the &lt;a href="http://www.vim.org/scripts/script.php?script_id=2441"&gt;pyflakes vim plugin&lt;/a&gt; doesn't work. A simple workaround is on the tutorial page I found, by simply installing MacVim though you only get it compiled against python2.5, not 2.6 which is standard now in Snow Leopard. Additionally, the syntax highlighting in MacVim is horrible for python compared to the built in one that ships with OSX, and I still prefer to run vim in the console.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Solving this issue involves a few steps:&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;1) Build MacVim from source. Of course you'll need the 10.6 XCode to do this, but after that it's pretty straight forward. The only thing to watch is that you have to run "./configure&amp;nbsp;--enable-pythoninterp --with-macsdk=10.6" instead of just "./configure". Other then that you can follow the &lt;a href="http://code.google.com/p/macvim/wiki/Building"&gt;instructions from the MacVim site&lt;/a&gt; for compiling your own version.&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;2) Copy the MacVim.app folder into your /Applications folder&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;3) add &lt;code&gt;[ -x "/Applications/MacVim.app/Contents/MacOS/Vim" ] &amp;amp;&amp;amp; alias vim=/Applications/MacVim.app/Contents/MacOS/Vim&lt;/code&gt; To your shell rc (for me it's .zshrc but for most people it's probably .tcshrc). I noticed that simply copying the Vim binary to your PATH, or sym linking it doesn't work, not quite sure why but this works well enough for me.&lt;br /&gt;
&lt;br /&gt;
4) Copy the python syntax file from &lt;code&gt;/usr/share/vim/vim72/syntax/python.vim&lt;/code&gt; to &lt;code&gt;~/.vim/syntax/python.vim&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
5) Download and install &lt;a href="http://www.vim.org/scripts/script.php?script_id=2441"&gt;the pyflakes.vim plugin&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
6) Open up a new terminal and edit an already created python source file.&lt;br /&gt;
&lt;br /&gt;
After you've done all of that you should see that anything that would normally show up in an error while running pyflakes now automatically get's highlighted as an error.&lt;br /&gt;
&lt;br /&gt;
I've also been using the pyflakes binary included with the pyflakes.vim plugin to check everything in my modules before building and uploading them to our servers. The only issue I've noticed is that sometimes you need to import a module even though you don't need to use it (for example with boto this is used in the sdb.db module to enable reverse-references). I'm still not quite sure how to ignore those or get around that.&lt;br /&gt;
&lt;br /&gt;
One other thing that doesn't work is doing conditional imports, for example to get JSON support the manuals tell you to do:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
try:&lt;br /&gt;
&amp;nbsp;&amp;nbsp; import json&lt;br /&gt;
except ImportError:&lt;br /&gt;
&amp;nbsp;&amp;nbsp; import simplejson as json&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;&lt;br /&gt;
&lt;/code&gt;&lt;br /&gt;
But in pyflakes, this will result in an error.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-508612439692666303?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z71XkcvHvJXMMlyudaiDB-o0tPw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z71XkcvHvJXMMlyudaiDB-o0tPw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z71XkcvHvJXMMlyudaiDB-o0tPw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z71XkcvHvJXMMlyudaiDB-o0tPw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/mXPk2LXc3yI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/508612439692666303/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=508612439692666303" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/508612439692666303?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/508612439692666303?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/mXPk2LXc3yI/osx-vim-and-python.html" title="OSX, Vim, and Python" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2010/01/osx-vim-and-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8ESX4zeyp7ImA9WxBSEUs.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-2284852270290488103</id><published>2009-12-18T11:16:00.000-08:00</published><updated>2009-12-18T11:16:48.083-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-18T11:16:48.083-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="newstex" /><category scheme="http://www.blogger.com/atom/ns#" term="amazon web services" /><title>Aeron Chairs</title><content type="html">&lt;a href="http://newstex.com/"&gt;Newstex&lt;/a&gt; has a tradition of giving all of it's employee's something related to the business we do (Authoritative Content Aggrigation) every christmas. One year it was a&amp;nbsp;&lt;a href="http://www.amazon.com/Kindle-Wireless-Reading-Display-Generation/dp/B0015T963C?ie=UTF8&amp;amp;tag=blogcoredumpe-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Kindle&lt;/a&gt;,&amp;nbsp;&amp;nbsp;once an &lt;a href="http://www.amazon.com/Apple-TV-160GB-Hard-Drive/dp/B000RQHAUA?ie=UTF8&amp;amp;tag=blogcoredumpe-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Apple TV&lt;/a&gt;, and once an iPhone. This year, however, Newstex bought &lt;a href="http://www.amazon.com/Aeron-Chair-Posture-Medium-Size/dp/B0006NUB5U?ie=UTF8&amp;amp;tag=blogcoredumpe-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;the most expensive desk chairs&amp;nbsp;ever produced&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=blogcoredumpe-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=B0006NUB5U" style="border: none !important; margin: 0px !important;" width="1" /&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=blogcoredumpe-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=B0006NUB5U" style="border: none !important; margin: 0px !important;" width="1" /&gt;.&lt;br /&gt;
&lt;br /&gt;
It took a while to adjust this chair, about 400 different settings to change, it can be relatively comfortable, but it's one of those things that we all look at yet never want to buy (who spends $850 on a chair?). In any event, this is the exact same chair as we use to have at the old RIT DataCenter when we had to stay up late running scripts which should have been handeld by a good crontab.&lt;br /&gt;
&lt;br /&gt;
I've realized today that I've moved quite a bit away from that original job in the DCO. Back then I was running scripts by hand that should have easily been automated, and today I work for a company automating processes that most people would consider far to complex for a computer to handle. Now that we've migrated our entire operations into &lt;a href="http://aws.amazon.com/"&gt;Amazon Web Services&lt;/a&gt;, we have the scalability and availability of the largest companies, without any big investments in hardware, or having to worry about hardware upgrades at all. Just today I performed a live upgrade on our websites without a single second of downtime.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-2284852270290488103?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZmmOXzroSsDuAcYLpZYoAOeEKqs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZmmOXzroSsDuAcYLpZYoAOeEKqs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZmmOXzroSsDuAcYLpZYoAOeEKqs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZmmOXzroSsDuAcYLpZYoAOeEKqs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/x0Bdb32Wi0I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/2284852270290488103/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=2284852270290488103" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/2284852270290488103?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/2284852270290488103?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/x0Bdb32Wi0I/aeron-chairs.html" title="Aeron Chairs" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/12/aeron-chairs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QGQH86fSp7ImA9WxBTFko.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-8209897561346503169</id><published>2009-12-12T18:05:00.001-08:00</published><updated>2009-12-12T18:28:41.115-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-12T18:28:41.115-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="boto" /><category scheme="http://www.blogger.com/atom/ns#" term="sdb" /><category scheme="http://www.blogger.com/atom/ns#" term="amazon web services" /><title>Paging SDB results in boto</title><content type="html">&lt;div&gt;Boto can be a great tool if you're querying against SDB, and it helps you out by managing paging automatically for you so you don't have to keep querying it for the next set of results. If you're dealing with a web-based application, however, you have to deal with your own paging and simply iterating forever over a large result set will eventually time out your connections. To solve this, you can use the built-in paging system provided by boto.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;Everytime you query using "db.select" in boto, you get back a result set. Most people probably just think of this as an iterator, since it does all the magic behind-the scenes and only queries when you start iterating. It also stores that magical "next_token" within itself so it can query for the next page of results from SDB. Normally, you wouldn't even notice this attribute, but if you're dealing with a service that needs to return in a short amount of time, it can be quite useful.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Additionally, there are two important keyword arguments you can specify to the "select" command on any domain. These are &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;max_items&lt;/span&gt;, and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;next_token&lt;/span&gt;. The &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;max_items&lt;/span&gt; keyword tells boto to return after it has yielded that number of results, instead of simply handling the paging automatically for you. It's also quite important to add the &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;limit&lt;/span&gt; SDB command to your query or boto will return in the middle of the result set and you will lose those middle results!&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;Ok, now to the code:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style=" ;font-family:Georgia, serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;div&gt;&gt;&gt;&gt; import boto&lt;/div&gt;&lt;div&gt;&gt;&gt;&gt; sdb = boto.connect_sdb()&lt;/div&gt;&lt;div&gt;&gt;&gt;&gt; db = sdb.get_domain("default")&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; rs = db.select("SELECT * FROM `default` LIMIT 10", max_items=10)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Notice that we set "LIMIT" and "max_items" both to 10.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Also note that "rs" is the result set of your select query, but only runs after you start iterating, rs.next_token should be blank now&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; rs.next_token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; for i in rs:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;...     print i&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Your first 10 results will print out, now rs.next_token is set:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; rs.next_token&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;u'r........'&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Now you can pass that next_token back to the SAME select, it must be the EXACT same query for next_token to work:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; rs2 = db.select("SELECT * FROM `default` LIMIT 10", max_items=10, next_token=rs.next_token)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&gt;&gt;&gt; for i in rs2:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;...     print i&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:georgia;"&gt;Your next 10 results will print out&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After you get to this point, it's a simple process to rinse-repeat. Once you run out of results, rs.next_token will be empty.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-8209897561346503169?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0i0dDBLZj30_8eC-CMiMuGxM0CY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0i0dDBLZj30_8eC-CMiMuGxM0CY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0i0dDBLZj30_8eC-CMiMuGxM0CY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0i0dDBLZj30_8eC-CMiMuGxM0CY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/kvLRyvfMaEI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/8209897561346503169/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=8209897561346503169" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/8209897561346503169?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/8209897561346503169?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/kvLRyvfMaEI/boto-can-be-great-tool-if-youre.html" title="Paging SDB results in boto" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/12/boto-can-be-great-tool-if-youre.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUCR307fyp7ImA9WxNRE0s.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-2962084550951053875</id><published>2009-09-07T14:39:00.000-07:00</published><updated>2009-09-07T14:51:06.307-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-07T14:51:06.307-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="10.6" /><category scheme="http://www.blogger.com/atom/ns#" term="python2.6" /><category scheme="http://www.blogger.com/atom/ns#" term="gcc" /><category scheme="http://www.blogger.com/atom/ns#" term="lxml" /><category scheme="http://www.blogger.com/atom/ns#" term="xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="snow leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="pysvn" /><title>Snow Leopard and lxml</title><content type="html">As many of you might already know, I've been dealing a lot with XML and python recently. I also recently upgraded to Mac OS 10.6 Snow Leopard. To my surprise, after the upgrade I noticed that I was now being pushed from python 2.5 to python 2.6. At first I was a little concerned since everything I had been doing was in 2.5, and all of our servers are running 2.5, but I soon found that I could continue to build for 2.5 and upload my eggs, so I welcomed the change.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After a while, I became aware that subversion was also upgraded. Building pysvn again proved to be a difficult task. I upgraded from python 2.5.1 to python 2.5.2 in order to try to also install the development libraries required to build pysvn from source. I had many issues there and then decided to move on and just install subversion 1.6.1 and the python 2.6 egg from the pysvn website.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I then discovered that lxml wasn't installed properly, and every time I tried to install the egg it told me that lxml was a pre-requisite of lxml... a bit of a confusing error message, but basically the change came about because 10.6 builds for 64 bit by default. Eventually, after attempting to build lxml for quite a while, I discovered the issue was that it wasn't working with gcc-4.2, the default compiler.  If you get an error like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;/Developer/SDKs/MacOSX10.4u.sdk/usr/include/stdarg.h:4:25: error: stdarg.h: No such file or directory&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;lipo: can't figure out the architecture type of: /var/folders/....&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;Then you have to do two things.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First of all, make sure you install the new XCode including the XCode 10.4 SDK (an optional install that is unchecked by default). For some reason most of the python modules I've found seem to rely on the 10.4 SDK and they even back-port the install for 10.3.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Secondly, you have to change your default compiler from gcc 4.2 to gcc 4.0.  This can be done by removing the symlink file in /usr/bin/gcc and re-linking that to gcc-4.0. This can be done by doing:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;/div&gt;&lt;div&gt;sudo rm /usr/bin/gcc&lt;/div&gt;&lt;div&gt;sudo ln -s /usr/bin/gcc-4.0 /usr/bin/gcc&lt;/div&gt;&lt;div&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After all that is done, you should be able to download lxml and build it using the standard Mac build command:&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;/div&gt;&lt;div&gt;python setup.py install --static-deps&lt;/div&gt;&lt;div&gt;&lt;/code&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-2962084550951053875?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wRxHRve1dS8jiEeE088CDnHpuv0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wRxHRve1dS8jiEeE088CDnHpuv0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wRxHRve1dS8jiEeE088CDnHpuv0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wRxHRve1dS8jiEeE088CDnHpuv0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/mb7cTuK1yDQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/2962084550951053875/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=2962084550951053875" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/2962084550951053875?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/2962084550951053875?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/mb7cTuK1yDQ/snow-leopard-and-lxml.html" title="Snow Leopard and lxml" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/09/snow-leopard-and-lxml.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IDSX47eSp7ImA9WxJUGEk.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-9179900027239777426</id><published>2009-07-17T08:25:00.001-07:00</published><updated>2009-07-17T08:46:18.001-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-17T08:46:18.001-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="RPC" /><category scheme="http://www.blogger.com/atom/ns#" term="HTTP" /><category scheme="http://www.blogger.com/atom/ns#" term="REST" /><category scheme="http://www.blogger.com/atom/ns#" term="amazon web services" /><category scheme="http://www.blogger.com/atom/ns#" term="aws" /><title>REST Method calling</title><content type="html">For a few years now, I've been strongly encouraging usage of REST interfaces when building any sort of application. Providing a simple REST interface on top of your application means that you can provide a service and have someone else deal with creating the interfaces. This allows you to have a simple JavaScript client, a Dashboard widget, an iPhone client, and even a Command line client all operating on the same back-end.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The one problem I've found with REST interfaces is that they only allow you to operate on resources with 4 methods, GET, POST, PUT, and DELETE. These methods as stated by most, allow you to Read, Create, Update, and Delete objects ONLY. In working with my applications, I often find the need to let the client perform other operations directly on the object. One possible solution to this problem is to overload the POST method with an optional "ACTION" parameter associated with it. This, however, always seemed hack-ish to me and more of something you'd see in SOAP then REST.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My proposed solution was to use HTTP to it's fullest and allow arbitrary HTTP verbs to be used on objects and collections. For example, if you had a user object at:&lt;/div&gt;&lt;div&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;&lt;span class="Apple-style-span"  style="color:#000099;"&gt;/users/moyer&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;REST says you can do:&lt;/div&gt;&lt;div&gt;&lt;code&gt;    &lt;span class="Apple-style-span"  style="color:#000099;"&gt;GET /users/moyer&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;To perform a "GET" (which would read the object) operation on the object, or&lt;/div&gt;&lt;div&gt;  &lt;code&gt;    &lt;span class="Apple-style-span"  style="color:#000099;"&gt;DELETE /users/moyer&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;To perform a "DELETE" operation on the object, so why not&lt;/div&gt;&lt;div&gt; &lt;code&gt;    &lt;span class="Apple-style-span"  style="color:#000099;"&gt;RESETPW /users/moyer&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;div&gt;To perform a "RESETPW" operation on the object? This turns a simple REST interface into a fully developed remote procedure calling system built directly off of the HTTP specifications.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have tested this usage using the python httplib standard library, proxying through apache and hitting a CherryPy and Paste backend server. All of my tests suggest that the client libraries and server libraries all will support arbitrary extensions of the HTTP specification.  This is the natural flow of progression to extend REST to support more methods on an individual object.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-9179900027239777426?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QpfC3aSoUdYtiXT4cxHK4vLrceY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QpfC3aSoUdYtiXT4cxHK4vLrceY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QpfC3aSoUdYtiXT4cxHK4vLrceY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QpfC3aSoUdYtiXT4cxHK4vLrceY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/nH8fXbyMbD0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/9179900027239777426/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=9179900027239777426" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/9179900027239777426?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/9179900027239777426?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/nH8fXbyMbD0/rest-method-calling.html" title="REST Method calling" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/07/rest-method-calling.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04ARn4yeSp7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-7277068227645853507</id><published>2009-07-07T15:23:00.000-07:00</published><updated>2009-07-07T15:32:27.091-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T15:32:27.091-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="OSX" /><category scheme="http://www.blogger.com/atom/ns#" term="WebDav" /><category scheme="http://www.blogger.com/atom/ns#" term="Apache" /><title>OSX WebDav Client</title><content type="html">In working on my custom WebDAV server, I discovered an interesting note about the OSX built-in WebDAV client. First of all, if you use finder to copy files (instead of cp in terminal), it sends all files over in chunked transfer-encoding. This is entirely allowed within the WebDAV specification, but it doesn't help that they also send it using the WRONG header. They send the encoding method as "Chunked" instead of "chunked".&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While working with Python Paste, I found that chunked encoding wasn't supported at all, so I switched over to using CherryPy. After testing locally and getting everything to work (CherryPy apparently ignores case), I deployed this system to production behind an apache server to add in SSL support (Yes, I plan to use Nginx in the future, but we have apache set up here already). After setting up the proxy, I noticed that I could no longer send files to my WebDAV server and a strange message was appearing in the apache error.log:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;[error] proxy: Chunked Transfer-Encoding is not supported&lt;/div&gt;&lt;div&gt;[error] [client xxx.xxx.xxx.xxx] Handler for proxy-server returned invalid result code 22&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After a lot of googling, I found a single page (written in german), which describes the issue:&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.stresser.de/blog/category/server/&amp;amp;ei=0clTSsHICYO0NvnDtewI&amp;amp;sa=X&amp;amp;oi=translate&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;prev=/search%3Fq%3D%2522Handler%2Bfor%2Bproxy-server%2Breturned%2Binvalid%2Bresult%2Bcode%2B22%2522%26hl%3Den%26client%3Dsafari%26rls%3Den-us"&gt;http://www.stresser.de/blog/category/server/&amp;amp;ei=0clTSsHICYO0NvnDtewI&amp;amp;sa=X&amp;amp;oi=translate&amp;amp;resnum=1&amp;amp;ct=result&amp;amp;prev=/search%3Fq%3D%2522Handler%2Bfor%2Bproxy-server%2Breturned%2Binvalid%2Bresult%2Bcode%2B22%2522%26hl%3Den%26client%3Dsafari%26rls%3Den-us&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The end result was that I had to enable mod_headers, and place this line in my apache config under the virtual host:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   RequestHeader edit Transfer-Encoding Chunked chunked early&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This fixes the header before mod_proxy gets to it and changes the "Chunked" to "chunked" which tells apache how to handle the request body. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-7277068227645853507?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qvDFqq1UTKeHAi17pFUOvx1d7BM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qvDFqq1UTKeHAi17pFUOvx1d7BM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qvDFqq1UTKeHAi17pFUOvx1d7BM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qvDFqq1UTKeHAi17pFUOvx1d7BM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/Z1Z9lwPTx30" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/7277068227645853507/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=7277068227645853507" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/7277068227645853507?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/7277068227645853507?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/Z1Z9lwPTx30/osx-webdav-client.html" title="OSX WebDav Client" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/07/osx-webdav-client.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MARXw4eCp7ImA9WxVUGEk.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-9107058665267822175</id><published>2009-03-23T15:43:00.000-07:00</published><updated>2009-03-23T16:04:04.230-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-23T16:04:04.230-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="service" /><category scheme="http://www.blogger.com/atom/ns#" term="macpro" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><category scheme="http://www.blogger.com/atom/ns#" term="apple" /><title>Now that's service</title><content type="html">After fighting with my mac pro all week, I finally took it in on Friday to get the graphics card replaced. I had deduced this was the problem, but still I expected to get some heat from the apple store. After bringing the computer up to the store, an apple rep quickly came out to meet me and carry the beast the rest of the way to the table. He pushed up my appointment by half an hour, and then I even got them to look at it even earlier because someone hadn't shown up yet. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not only did they not ask me a dozen questions, they didn't even plug the thing in. I said "The graphics card is dead" and they said "Ok, we'll get you a new one".... Thank you apple for not treating me like an idiot.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;They had to order it, which took a total of a day, less then 24 hours later I got a phone call saying I could pick it up. They even took it out to my car for me... and all of this was under warranty so I didn't pay anything. Now that's what I call service.  Yes, apple's may be more expensive, but this is what you're paying for and it's WELL worth it.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-9107058665267822175?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ak_tpi_XaJ0C-GhGuQS_E24akjg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ak_tpi_XaJ0C-GhGuQS_E24akjg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ak_tpi_XaJ0C-GhGuQS_E24akjg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ak_tpi_XaJ0C-GhGuQS_E24akjg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/KM_RH4QcZgg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/9107058665267822175/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=9107058665267822175" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/9107058665267822175?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/9107058665267822175?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/KM_RH4QcZgg/now-thats-service.html" title="Now that's service" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/03/now-thats-service.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEHSHw9cCp7ImA9WxVUEEU.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-5428414190988196474</id><published>2009-03-14T19:54:00.000-07:00</published><updated>2009-03-14T20:10:39.268-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-14T20:10:39.268-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="college" /><category scheme="http://www.blogger.com/atom/ns#" term="rit" /><category scheme="http://www.blogger.com/atom/ns#" term="amazon web services" /><category scheme="http://www.blogger.com/atom/ns#" term="user group" /><category scheme="http://www.blogger.com/atom/ns#" term="aws" /><title>RAWSUG Meeting</title><content type="html">This tuesday at 6:00 pm will be our next Rochester Amazon Web Services User Group (RAWSUG) meeting. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We will be going over some of the basics of cloud infrastructure, and discussing the interesting solutions we have each come up with to develop high-demand and highly-scalable/reliable applications. If you've ever had any desire to learn about AWS or Cloud Computing in general, I highly suggest you come check it out. Most of the meeting will be a forum-based discussion with a few presentations in the beginning.  If you have any specific requests please email me beforehand and I'll try to get it lined up. All presentation notes will be posted on &lt;a href="http://rawsug.org"&gt;http://rawsug.org&lt;/a&gt; after the meeting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It will be hosted at RIT in the IT conference room on the second floor of GCCIS. For more information visit &lt;a href="http://rawsug.org"&gt;http://rawsug.org&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-5428414190988196474?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z73ZJAV60cCiiSKITEPquV6TMwc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z73ZJAV60cCiiSKITEPquV6TMwc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z73ZJAV60cCiiSKITEPquV6TMwc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z73ZJAV60cCiiSKITEPquV6TMwc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/t9tqtGaFYsI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/5428414190988196474/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=5428414190988196474" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/5428414190988196474?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/5428414190988196474?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/t9tqtGaFYsI/rawsug-meeting.html" title="RAWSUG Meeting" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/03/rawsug-meeting.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEMRX85fCp7ImA9WxVUEEU.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-3045488248087950184</id><published>2009-01-05T07:32:00.001-08:00</published><updated>2009-03-14T20:11:24.124-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-14T20:11:24.124-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rules of life" /><category scheme="http://www.blogger.com/atom/ns#" term="Theories" /><title>Life lessons</title><content type="html">Over the years I've developed a few theories about people that I thought I'd share with everyone. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold; "&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;People are idiots&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;In general, people are idiots. Even if you're not an idiot, you'll have idiotic moments. Everyone does something stupid at least once a day that someone else sees. The only difference between idiots and intelligent people is that the idiots don't notice it.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold; "&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;Stereotypes exist for a reason&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Stereotypes came from somewhere, we really can't make this crap up. No, not everyone fits them, but there's at least 80% that do. Have you ever met a straight white person that can dance?&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold; "&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;In the end, everything comes down to greed&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;Every single thing that anyone does is for selfish reasons. Even if you're helping someone else out of what you would think of as pure reasons, you'll expect some sort of self-gratification, either from a thank you or something else. Nothing is ever done out of pure selflessness. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-3045488248087950184?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/19dd-Oy0zkKZ8OnPPIzTj7uoyfU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/19dd-Oy0zkKZ8OnPPIzTj7uoyfU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/19dd-Oy0zkKZ8OnPPIzTj7uoyfU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/19dd-Oy0zkKZ8OnPPIzTj7uoyfU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/niR1iaHrr1o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/3045488248087950184/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=3045488248087950184" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/3045488248087950184?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/3045488248087950184?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/niR1iaHrr1o/over-years-ive-developed-few-theories.html" title="Life lessons" /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.coredumped.org/2009/01/over-years-ive-developed-few-theories.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYNRXw8fip7ImA9WxRaEEk.&quot;"><id>tag:blogger.com,1999:blog-301169258518998120.post-4483724333396530431</id><published>2008-12-11T16:42:00.000-08:00</published><updated>2008-12-11T16:53:14.276-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-11T16:53:14.276-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="senior project" /><category scheme="http://www.blogger.com/atom/ns#" term="fail" /><category scheme="http://www.blogger.com/atom/ns#" term="rit" /><category scheme="http://www.blogger.com/atom/ns#" term="software" /><category scheme="http://www.blogger.com/atom/ns#" term="design" /><title>How RIT reverses your education.</title><content type="html">So, I'm finally a Senior at RIT, doing my last year, which basically consists of one class that spans two quarters, known as Senior Project. On the first day we were shown a pretty powerpoint that discussed how we're suppose to use all of our knowledge and training over the past 4 years (yes, it's a 5 year program), and incorporate everything into one big project. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sounds great right? Well not so much. For this class we're giving a real-world customer and a product they want us to create. We start out by gathering requirements from the customer, then we have to design, architect, build, and, finally, deploy the product. It all starts off great, we meet the customer, start gathering requirements, and respond back with some decent offers for what we can do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next, we start talking about how we can actually go about doing this, and what type of software we can build in the next 22 weeks. Since we're only a team of 5, and we have 22 weeks to build the entire system from scratch, scope is very important. We limit down what we're going to do and present a counter-proposal to the customer for what we think we can get done given our time constraints. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;During the meeting, the client keeps talking about how he wants a nice user interface, we explain that we're focused on the core system, but we can help his people develop a decent one, and provide a very simple interface. We discuss our plans to architect the system in such a way that it will be expandable later on and should easily scale and be able to run on multiple systems. We're designing the system to be a proper 3-tier Presentation, Application, Data, system (web service). After the meeting, our faculty advisor turns to us and says "You don't need to worry about architecting the system like that, just give him a nice GUI and he'll be happy, we don't care if it's scalable".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As it turns out, RIT is really only interested in making the customer happy for the time-being, and not really producing decent software. I once again show my distain for RIT's policies. Instead of actually teaching us things and then testing us on them as they said, they want to throw us into the world and tell us "Just forget about your training and try to make the other guy happy."&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Good job RIT.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/301169258518998120-4483724333396530431?l=blog.coredumped.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lt2kfIS9j4hxShVtwenqgX4CQ_0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lt2kfIS9j4hxShVtwenqgX4CQ_0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lt2kfIS9j4hxShVtwenqgX4CQ_0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lt2kfIS9j4hxShVtwenqgX4CQ_0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/ChrisMoyer/~4/P6G1HG-EKTo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.coredumped.org/feeds/4483724333396530431/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=301169258518998120&amp;postID=4483724333396530431" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/4483724333396530431?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/301169258518998120/posts/default/4483724333396530431?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ChrisMoyer/~3/P6G1HG-EKTo/how-rit-reverses-your-education.html" title="How RIT reverses your education." /><author><name>Chris Moyer</name><uri>http://www.blogger.com/profile/04068315333804202241</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05808470980156084500" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.coredumped.org/2008/12/how-rit-reverses-your-education.html</feedburner:origLink></entry></feed>
