<?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-3965682379736830499</id><updated>2011-12-11T10:19:41.379-05:00</updated><title type='text'>Development Adventures</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8118522729263644879</id><published>2011-12-11T10:16:00.002-05:00</published><updated>2011-12-11T10:19:41.388-05:00</updated><title type='text'>Running Clojure</title><content type='html'>I ran across a(nother) article today about jumping into clojure.  It was full of misconceptions and half truths, but if it gets people into running and playing with clojure that otherwise would not, then I guess I can overlook them.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One thing that I *always* see though, is how to run the REPL.  It's always:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;    &lt;span class="Apple-style-span" &gt;java -cp clojure-1.3.0.jar clojure.main&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which works just fine.  What I don't understand is why no one seems to know this easier way:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span" &gt; java -jar clojure-1.3.0.jar&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Which also works, and is shorter, and somewhat more idiomatic, IMO.   It even works on, &lt;shudder&gt;, Windows.&lt;/shudder&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;c:\clojure-1.3.0&amp;gt;java -jar clojure-1.3.0.jar &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;Clojure 1.3.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;user=&amp;gt; (+ 1 2)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;3&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&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;&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/3965682379736830499-8118522729263644879?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8118522729263644879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8118522729263644879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8118522729263644879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8118522729263644879'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2011/12/running-clojure.html' title='Running Clojure'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-464645088882819564</id><published>2011-11-19T21:23:00.004-05:00</published><updated>2011-11-19T23:10:09.394-05:00</updated><title type='text'>Project Euler #4</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Did problem #4 today.  Find the largest product of 2 three digits that is a palindrome.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This one wasn't too hard (given that I don't know clojure well enough to not have to scour docs for the order of arguments and such).  First made a function that just returns all the products of 100...999, (actually 101; no product of 100 * anything can be a palindrome) as a list of 2 item vectors of the product and its palindrome, as strings.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then ran it through a filter which removed all the non-palindromes.  Then a map to get one of the elements of the vector.  Then mapped it to an integer.  Then applied max to that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, I hated that solution. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, I improved upon it slightly by reversing the range to start from the high point and counting down, thinking that I could generate the palindromes in pre-sorted order, and I could just take the first one.  Unfortunately, my plan did not work.  But, I did realize how to better use the for comprehension to do the filtering for me, rather than after the fact, so I didn't bother doing as many int -&amp;gt; string -&amp;gt; int conversions, which did make it faster.  I also eliminated the function wrapping the for, and just stuck it inline.  So what I ended up with is here:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;(apply max (for [a (range 1000 101 -1) b (range 1000 a -1) &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;  :when (=&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;          (.toString (* a b))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;          (apply str (reverse (.toString (* a b)))))] (* a b)))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&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/3965682379736830499-464645088882819564?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/464645088882819564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=464645088882819564' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/464645088882819564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/464645088882819564'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2011/11/project-euler-4.html' title='Project Euler #4'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-250134494613941625</id><published>2011-11-16T21:56:00.002-05:00</published><updated>2011-11-16T22:04:32.332-05:00</updated><title type='text'>Project Euler in Clojure</title><content type='html'>Problem 3; what's the biggest prime factor of some big #?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I went a lot of ways here, but finally ended up with the following.  First, I made a function which would factor a number.  I poked at this a lot of times before I ended up on the for comprehension, which I'm not sure is the best way by far, but I wanted to play with it.   It runs up a counter from 2 to the sqrt(target), and if the target MOD the number is 0,  returns the number and the "other" factor in a list, then flattens the list of lists when done.  (Ideas welcome for removing the flatten... something with cons/conj?)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then I wrote a "prime" method which tells me if a number is prime.  It does this by just factoring the number using my factor func, then counts the factors.  If it's 2, it's prime (1 and the # itself).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then it was a simple matter of calling factor on my big #, filtering the factors returned through the prime method, and calling max on the result.  Ah, but max doesn't take a seq... so I had to 'apply' max to the result.  Lots of lessons learned here, and looking for advice on how this could be more clojurific.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;&lt;/span&gt;&lt;pre&gt;&lt;span class="Apple-style-span" &gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;(defn factor [m] (flatten (for [a (range 1 (Math/sqrt m)) :when (zero? (mod m a))] (list a (/ m a)))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;(defn prime [n] (= 2 (count (factor n))))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;(apply max (filter prime (factor 600851475143)))&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" &gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3965682379736830499-250134494613941625?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/250134494613941625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=250134494613941625' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/250134494613941625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/250134494613941625'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2011/11/project-euler-in-clojure.html' title='Project Euler in Clojure'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8192155720344377063</id><published>2011-11-16T20:23:00.004-05:00</published><updated>2011-11-16T20:51:03.605-05:00</updated><title type='text'>Learning Clojure</title><content type='html'>&lt;div&gt;I've started my journey down clojure land. 4clojure and Project Euler are my first goals. Started with project Euler. Here are my first couple solutions. Critiques on clojure idioms, style, optimizations welcome.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#1. http://projecteuler.net/problem=1&lt;/div&gt;&lt;div&gt;Find the sum of all the multiples of 3 or 5 below 1000.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(reduce + (filter #(or (zero? (mod % 3)) (zero? (mod % 5))) (range 1 1000)))&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;br /&gt;&lt;/div&gt;&lt;div&gt;#2. http://projecteuler.net/problem=2&lt;/div&gt;&lt;div&gt;Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:&lt;/div&gt;&lt;div&gt;1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My solution:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(defn fib [x]&lt;/div&gt;&lt;div&gt;        (cond &lt;/div&gt;&lt;div&gt;          (&amp;lt;= x 3) x&lt;/div&gt;&lt;div&gt;          :else (+ (fib (- x 2)) (fib (- x 1)))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;(reduce + (filter even? (take-while #(&amp;lt; % 4000000) (map fib (iterate inc 1)))))&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The unusual form of fibonacci is due to the requirement; the sequence starts with 1 and 2 instead of 0 and 1, so the first 3 terms are 1,2,3 so that is a teensy teensy point of optimization.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I actually started with a range, but that starts with 0 which isn't quite right, and if you have a starting point (say... 1), on a range, you need an ending point. And while I could have used an obviously too high end point (which is actually what I started with), it didn't feel right, so I dug around for the function I knew existed, but couldn't locate.... until I found iterate.&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3965682379736830499-8192155720344377063?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8192155720344377063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8192155720344377063' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8192155720344377063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8192155720344377063'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2011/11/learning-clojure.html' title='Learning Clojure'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-2853390689217478801</id><published>2008-10-19T14:32:00.001-04:00</published><updated>2008-10-19T14:32:47.310-04:00</updated><title type='text'>Where are all the women?</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I've seen a lot of articles lately about women in IT, computer science classes, technical industries, etc.  The lack of them, the declining numbers, the declining %'s, how to get more of them, how to pander to their tastes, etc.&lt;br/&gt;&lt;br/&gt;My question is, why?  Why all the extra energy for just women?   Are they magical in some way that I'm not aware of?  More deserving of special treatment?  Somehow "better" than any other group that ISN'T getting all this love?  Do the people writing these articles have some sort of ulterior motive of their ultimate porn fantasy?  Why not "Where are all the [insert demographic here]"?&lt;br/&gt;&lt;br/&gt;I don't THINK I'm sexist*, but all I want from coworkers and people in the IT (or ANY) industry is people I can get along with and can do the job.  Women, men, Antareans, amoebas, fungi; I don't care.  Do your job, don't keep me from doing mine, help me when you can and I'll do the same.   &lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;* Before you comment, me being sexist would be me saying I want fewer women or to somehow make it harder for them, which I'm not.  What I'm saying here is... I don't care if there are more, OR fewer.  All I want is qualified people.&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/3965682379736830499-2853390689217478801?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/2853390689217478801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=2853390689217478801' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/2853390689217478801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/2853390689217478801'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/10/where-are-all-women.html' title='Where are all the women?'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-5464603583765562026</id><published>2008-10-13T19:30:00.001-04:00</published><updated>2008-10-13T19:30:58.098-04:00</updated><title type='text'>Stuff I Did Today</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;It was officially a holiday for me, so I didn't get any real work done.  That's unusual; if I'm home, I usually work.  Mostly off the books.&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;li&gt;I can't seem to be able to ask a question without people thinking I have an ulterior motive, thinking I'm complaining about something, or something else negative.  I guess I only have myself to blame, but I'm honestly generally just asking.   I think I've figured out a way to try and not trigger everyone's eye-rolling reaction to me; we'll see if it works.  I often wonder if I'm slightly autistic because I appear to be very, very bad at reading social cues.  I thought working from home would help; it pretty much hasn't, but possibly made it worse.&lt;/li&gt;&lt;li&gt;I learned (or rather, read), that diesel engines don't have a throttle.  They adjust power by varying fuel/air ratios.  My next car will probably be a diesel.&lt;/li&gt;&lt;li&gt;Downloaded a free FPS and played that.  Fun, no subscription, and satisfies my gaming urge.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3965682379736830499-5464603583765562026?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/5464603583765562026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=5464603583765562026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/5464603583765562026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/5464603583765562026'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/10/stuff-i-did-today_13.html' title='Stuff I Did Today'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8694688263373997470</id><published>2008-10-08T19:51:00.001-04:00</published><updated>2008-10-08T19:51:52.354-04:00</updated><title type='text'>Stuff I Did Today</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;ul&gt;&lt;li&gt;Was completely misunderstood.  By 2 people.  On 2 different circumstances.  Sometimes working from home sucks.&lt;/li&gt;&lt;li&gt;Did unnatural things to our QA box with gobs of data it'd never seen before.  CPU was at 100% and load averages hovered above 10 a good bit of the day.&lt;/li&gt;&lt;/ul&gt;That's about it.  BigDataLoadTesting took my whole day.&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/3965682379736830499-8694688263373997470?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8694688263373997470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8694688263373997470' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8694688263373997470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8694688263373997470'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/10/stuff-i-did-today_08.html' title='Stuff I Did Today'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-1514551686297372395</id><published>2008-10-07T19:50:00.001-04:00</published><updated>2008-10-07T19:50:09.276-04:00</updated><title type='text'>Stuff I did today</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;ul&gt;&lt;li&gt;Installed ruby on our QA box.  Finally.&lt;/li&gt;&lt;li&gt;Navigated treacherous object dependencies and got a bulk data generation script running well enough to not puke out internally inconsistent data.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Learned about Oracle's bulk loader.&lt;/li&gt;&lt;li&gt;Sicced a new employee on an irksome bug report like a dog on a pork chop.&lt;/li&gt;&lt;/ul&gt;A good day.  Even managed to squeak out a few "good dad" moments.&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/3965682379736830499-1514551686297372395?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/1514551686297372395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=1514551686297372395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1514551686297372395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1514551686297372395'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/10/stuff-i-did-today.html' title='Stuff I did today'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-6960615517905907312</id><published>2008-07-06T20:48:00.001-04:00</published><updated>2008-07-06T20:48:56.107-04:00</updated><title type='text'>What is the singular of...</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;As I was reading this BBC story, "How to solve the British maths problem?"[1] I was reminded of my numerous British friends and colleagues always ribbing me (a United States citizen) how bad my English was.  That was, of course, in the context of their British English since I think my American English is at least in the top quartile in terms of correctness[2].&lt;br/&gt;&lt;br/&gt;As I read the story I was left with one question.  In the UK, how much, or big, or many, is one "math"?&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;[1]http://news.bbc.co.uk/2/hi/uk_news/magazine/7435023.stm&lt;br/&gt;[2] Yes, I fully expect to have errors in this post pointed out.  Thanks.&lt;br/&gt;&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/3965682379736830499-6960615517905907312?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/6960615517905907312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=6960615517905907312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/6960615517905907312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/6960615517905907312'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/07/what-is-singular-of.html' title='What is the singular of...'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8066824518659142865</id><published>2008-05-22T17:26:00.006-04:00</published><updated>2008-05-22T17:42:35.443-04:00</updated><title type='text'>Full Text Justification is Abysmal</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div style='text-align: left;'&gt;&lt;br/&gt;I hate full text justification.  It works ok for newspapers since their columns are not wide, and they typically do not use "big words".  So, the difference from line to line between letters and words aren't noticeable.  Also TeX and LaTeX seem to get it right, but that's because TeX and family obey typesetting rules that have been carefully tweaked, honed, and perfected over the past 500 years.&lt;br/&gt;&lt;br/&gt;But then came WYSIWYG, and everyone from "HTML Programmer" (snort) through administrative assitant through CEO thinks they suddenly have insight into what looks better.  And just add insult to injury, we get 1680x1050 resolution monitors with ClearType font smoothing and...&lt;br/&gt;&lt;br/&gt;it&amp;nbsp;&amp;nbsp;&amp;nbsp;looks&amp;nbsp;&amp;nbsp;&amp;nbsp;like&amp;nbsp;&amp;nbsp;&amp;nbsp;I&amp;nbsp;&amp;nbsp;&amp;nbsp;printed   &amp;nbsp;&amp;nbsp;&amp;nbsp;it &amp;nbsp;&amp;nbsp;&amp;nbsp;  on &amp;nbsp;&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp;  my  &amp;nbsp;&amp;nbsp;&amp;nbsp; 9 &amp;nbsp;&amp;nbsp;&amp;nbsp; pin &amp;nbsp;&amp;nbsp;&amp;nbsp;  Epson &amp;nbsp;&amp;nbsp;&amp;nbsp;  dot &amp;nbsp;&amp;nbsp;&amp;nbsp;  matrix &amp;nbsp;&amp;nbsp;&amp;nbsp;  from &amp;nbsp;&amp;nbsp;&amp;nbsp;  20 &amp;nbsp;&amp;nbsp;&amp;nbsp;  years &amp;nbsp;&amp;nbsp;&amp;nbsp;  ago.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;The problem is especially bad on technical blogs and Wikis since we techies DO use really big words; not because we're that smart (although some are, just not me), but because we tend to talk in code, and our code uses big words, or directories, or class names, or, or or...    The result is certainly not unreadable, but very sophomoric in impression.&lt;br/&gt;&lt;br/&gt;If you have a blog or run a wiki and can control these things, don't use full text justification.  Yeah, it was cool in 8'th grade with Scripsit to see the blinkenlights magically put text to paper and spread it out to the edge, but these days it just looks like an 8'th grader wrote it. Using Scripsit.&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(I'm not a Luddite, really.)&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3965682379736830499-8066824518659142865?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8066824518659142865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8066824518659142865' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8066824518659142865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8066824518659142865'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/05/full-text-justification-is-abysmal.html' title='Full Text Justification is Abysmal'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-6273633962377684142</id><published>2008-05-21T19:56:00.002-04:00</published><updated>2008-05-21T20:00:33.790-04:00</updated><title type='text'>Lift Diary, Day 1</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div style=''&gt;I'm trying to learn Scala, and /lift/.  The ultimate goal really IS to learn something, but as a way to accomplish that, I'm going to use a website that I maintain (currently java, webwork, and ibatis) as a template.  Rewrite that (or significant, not-necessarily-production-quality parts of it), and I'll consider it a success.&lt;br /&gt;&lt;br /&gt;As I do various things along this journey, I plan on jotting them down here, so please forgive the inevitable sentence fragments, missing links, misconceptions, etc.  This is more a jot pad of what I'm doing, as I do it, not a finalized tutorial for anyone following me.&lt;br /&gt;&lt;br /&gt;So, on to it then.&lt;br /&gt;&lt;br /&gt;* Download and install the latest Scala (2.7.1 final) at http://www.scala-lang.org/downloads/.  I'm using Windows for this.  Yeah, I   know.  &lt;br /&gt;&lt;br /&gt;* Setup the path, etc.&lt;br /&gt;&lt;br /&gt;* Try it out.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;c:\tmp&amp;gt;scala&lt;br /&gt;Welcome to Scala version 2.7.1.final (Java HotSpot(TM) Client VM, Java 1.6.0_05).&lt;br /&gt;Type in expressions to have them evaluated.&lt;br /&gt;Type :help for more information.&lt;br /&gt;&lt;br /&gt;scala&amp;gt; object HelloWorld {&lt;br /&gt;     | def main(args: Array[String]) { &lt;br /&gt;     | println("hello, world")&lt;br /&gt;     | }&lt;br /&gt;     | }&lt;br /&gt;defined module HelloWorld&lt;br /&gt;&lt;br /&gt;scala&amp;gt; HelloWorld.main(null)&lt;br /&gt;hello, world&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Success, but I expected that.&lt;br /&gt;&lt;br /&gt;* Download /lift/. What the deuce? You don't download lift, you let maven do it.   (http://liftweb.net/index.php/HowTo_start_a_new_liftwebapp) Ok, no problem, I   use maven roughly daily for my 'real work', so I'm ok with that.  &lt;br /&gt;&lt;br /&gt;  I've used the command line below, all on one line, indents are simply for   looks.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  mvn archetype:generate -U &lt;br /&gt;   -DarchetypeGroupId=net.liftweb &lt;br /&gt;   -DarchetypeArtifactId=lift-archetype-basic &lt;br /&gt;   -DarchetypeVersion=0.8 &lt;br /&gt;   -DremoteRepositories=http://scala-tools.org/repo-releases &lt;br /&gt;   -DgroupId=net.liftweb.hello &lt;br /&gt;   -DartifactId=liftdiary&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;  Not mentioned on the wiki, it asks for a version, then asks for confirmation for some properties its set,  then completes.&lt;br /&gt;&lt;br /&gt;(I've asked permission (since I'm kind and polite) to edit the wiki, so I can just set things right as I find them, rather than gripe about them here. Also, I've asked David if he wants me to just wiki-ize this whole experience somewhere ON the lift wiki.  We'll see how that goes.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;* mvn install jetty:run&lt;br /&gt;&lt;br /&gt;Works fine.  Now to figure out how to make my OWN web app, and not blindly follow the "do this, do this, do this" pages.&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/3965682379736830499-6273633962377684142?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/6273633962377684142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=6273633962377684142' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/6273633962377684142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/6273633962377684142'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/05/lift-diary-day-1.html' title='Lift Diary, Day 1'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-1308729795649027453</id><published>2008-05-18T15:02:00.003-04:00</published><updated>2008-05-18T15:07:12.235-04:00</updated><title type='text'>Culture Clash with Python</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div style=''&gt;I first looked at Python around 1997, for reasons lost to my ever failing memory, but already being a rather big perl-head by then, I didn't go much past the "Hrm, neat" stage.&lt;br/&gt;&lt;br/&gt;I've since decided to give it a real go and am studying a bit from online sources.   On one hand there are aspects I really like (large extensive library, big support, stable; and even some aspects of the Python "way", since sometimes, but not always, TMTOWTDI is a PITA.&lt;br/&gt;&lt;br/&gt;There is one aspect though that just really clashes with me; the community is VERY quick to point out how you're wrong.  It doesn't matter about what, it's just you're wrong.  I've found that most of the time, I am, but there's this absoluteist tone that I sense that makes me  completely understand why the community has the "Pythonista" term applied.&lt;br/&gt;&lt;br/&gt;For example, if you want to join a list with a delimeter, the way to do that is like so:  string_delimeter.join(&amp;lt;list, tuple, etc.&amp;gt;) # i.e. ", ".join([1, 3, 4, 7, 10])&lt;br/&gt;&lt;br/&gt;Ok, that's just a bit backwards from what I'm used to.  I want to join THE LIST with the delimeter.  It's a small cognitive dissonance, but it's there.  When looking at the FAQ about this, it says ... I'm wrong.  No, that's not what I want to do.  The exact quote is:  &lt;br/&gt;&lt;br/&gt;&lt;i&gt;The second objection is typically cast as: “I am really telling a sequence to join its members together with a string constant”.  Sadly, you aren’t. &lt;/i&gt;&lt;br/&gt;&lt;br/&gt;Well, yes, yes I am.   Like I said, a small nit, but it could have been phrased in less absolutist verbiage, (and the counter example of "split" is inconsistent with what it's saying, but I digress).  Ok, so I get past that.  (And there is another less odd looking, but less "OOish" way of doing that if I find I can't stand it.  So Python ISN'T just 1 way to do it for everything after all!)&lt;br/&gt;&lt;br/&gt;So, playing around, I wonder what happens when I try to join a list, err, sorry, "telling my delimeter to iterate my list and insert itself" (rolls eyes), when it contains the equavalent of a null, namely Python's "None".&lt;br/&gt;&lt;br/&gt;", ".join(['a', None, 'b']) # =&amp;gt; a,,b?  &lt;br/&gt;&lt;br/&gt;Nope.  Exception.    Ok, I can accept that None has no default conversion to a string, and I can accept that there's no easy way to do it (Is there?  If there is, IRC folk didn't know, and told me I was wrong for even deigning to ask), but I find this behavior a bit irritating.   What was the result when I mentioned this?  Not that I'm expecting the wrong thing (I am), or even that I was quick to jump the gun to find this irritating (I was), but rather, I don't find it irritating.  Excuse me?  I'm pretty sure that I do.  "Nope, you don't."&lt;br/&gt;&lt;br/&gt;Then there's the PEP standard that calls for no more than 80 character lines.  I've been programming professionally awhile, and 132 was all the rage almost 30 years ago.   There does seem to be some debate about this, and going over my latest java project my line length averages 37 chars (over some 100k lines of code) so I doubt this would really affect me in any meaningful way, and too, I doubt I'm going to be putting any code into Python's already outstanding standard library, but the discussion around it was just what I've come to find out as typical.  &lt;br/&gt;&lt;br/&gt;I happened to come into IRC when this debate was going on, and although it was mostly good natured, one of the reasons for 80 is that anything over 80 is unreadable.  Not, "*I* find it hard to read over 80 character lines.", or even "GUIDO hates it", but &amp;gt;80 is just absolutely unreadable, for anyone.  Questioning that, or even mentioning that YOU can do fine with 132, 150, 180, 250 character lines just about has you burned at the stake since you obviously do not, and cannot float like a small stone.&lt;br/&gt;&lt;br/&gt;Lastly, and this is probably confirmation bias, but whenever I come across a blog post comparing, contrasting, teaching, explaining, or anything with a programming language, there is almost inevitably the "Why don't you try it in Python?", "X sucks, you should do this in Python", "Python does this all better, see?" set of bleats and whines.  It is the same tenor as the nice young men in their white shirts and black ties coming to my door trying to push their version of God on me.  Actually, now that I write that I DO realize that what I'm feeling with some of this community has strong similarities to fundamentalist religious methods of conversion.  Hrm, interesting.&lt;br/&gt;&lt;br/&gt;So, I'll continue learning as I do find the language very interesting, although I haven't really found it to do things in any sort of way other languages cannot with as much or more expressiveness.&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/3965682379736830499-1308729795649027453?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/1308729795649027453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=1308729795649027453' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1308729795649027453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1308729795649027453'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/05/culture-clash-with-python.html' title='Culture Clash with Python'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-1839292853404737920</id><published>2008-05-16T17:13:00.001-04:00</published><updated>2008-05-16T17:13:28.467-04:00</updated><title type='text'>Absurd</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;div style=''&gt;Some time ago, a company I've recently (1.75 years ago) left was bought by another.  This all happened after I left, so it didn't affect me other than it directly affects friends that are still there.  One of the acquiring company's MO's is to do an immediate 30%-40% headcount reduction (or so I am told).  &lt;br/&gt;&lt;br/&gt;True to form, they announced the RIF in the department I was in, and soon after noted who will stay (very few) and who will go (very many) and who will be doing the jobs of the people they let go (outsourced).&lt;br/&gt;&lt;br/&gt;The other day, someone realized that the company's business is financial in nature, and it was against [the law, company policy, a regulation] to allow this personal financial data to leave the US borders.  The solution?  NOT fire the people that were going to do those jobs?  Oh, but no!  They instead decided to bring ONshore the OFFshore employees to do these jobs, and pay them about the same as the people who already knew how to do it.&lt;br/&gt;&lt;br/&gt;Cost savings, indeed.&lt;br/&gt;&lt;br/&gt;Discuss.&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/3965682379736830499-1839292853404737920?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/1839292853404737920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=1839292853404737920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1839292853404737920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/1839292853404737920'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/05/absurd.html' title='Absurd'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8649738173053660041</id><published>2008-04-23T13:20:00.001-04:00</published><updated>2008-04-23T13:20:44.775-04:00</updated><title type='text'>Curious Design Choice</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;In eclipse, in the java editor, Ctrl-S (save) is RIGHT NEXT to Ctrl-D (delete line).&lt;br/&gt;&lt;br/&gt;I understand WHY they are, but it's a bad design all the same.  Often, if you're not accurate, or you're using the typical crap laptop keyboard, one can hit both; in the wrong order this can be rather irritating at best, disastrous at worst.&lt;br/&gt;&lt;br/&gt;Any other examples of this?&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/3965682379736830499-8649738173053660041?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8649738173053660041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8649738173053660041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8649738173053660041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8649738173053660041'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/04/curious-design-choice.html' title='Curious Design Choice'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-200962780358685530</id><published>2008-04-18T13:27:00.001-04:00</published><updated>2008-04-18T13:47:41.776-04:00</updated><title type='text'>Creative Employment Agreements</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I was chatting with a coworker today about some company issues, and I had offhandedly mentioned a thought I've had over the past few years; that being, putting something in your employment contract/offer letter/acceptance/etc. that wasn't already there.&lt;br /&gt;&lt;br /&gt;In my case, had I remembered it when I joined this company; this is an old, old thought that I've never followed through on; I would have specified:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Any "team building" exercise FOR the sake of team building, I would be free to opt-out of.&lt;/li&gt;&lt;li&gt;I am not required to attend weekly status meetings.&lt;/li&gt;&lt;li&gt;I am not required to submit weekly status reports.  I would of course couch both of these in terms of being perfectly happy to provide &lt;span style='font-weight: bold;'&gt;relevant &lt;/span&gt;status updates to my manager, just not in the "Management 101", Andersen Consulting style TPS reports and meetings.&lt;/li&gt;&lt;li&gt;Probably something about meetings.  This is a little easier; one can just not accept invitations if it's not convenient, which I often do already.&lt;/li&gt;&lt;/ul&gt;Naturally the company would be perfectly within their rights to NOT hire me with these riders on the contract and I accept that.  It just seems like these types of things would be as much or more easily negotiated than the standard pay or vacation time items.&lt;br /&gt;&lt;br /&gt;Has anyone done anything like this?  How'd it work out?&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/3965682379736830499-200962780358685530?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/200962780358685530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=200962780358685530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/200962780358685530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/200962780358685530'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/04/creative-employment-agreements.html' title='Creative Employment Agreements'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3965682379736830499.post-8632947314253457206</id><published>2008-04-17T21:39:00.001-04:00</published><updated>2008-04-17T21:53:06.134-04:00</updated><title type='text'>What's A Good Error Message?</title><content type='html'>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;What makes a good error message?  As developers, we certainly see a lot of them, and they are almost always the first indication that Something Bad (tm) has happened.   So what makes a good one?&lt;br /&gt;&lt;br /&gt;In order to answer that, it's probably best to illustrate what they are FOR.  There are generally 2 classes of error message:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Messages intended for users.  These messages indicate that the USER has done something wrong.  Typically bad input.&lt;/li&gt;&lt;li&gt;Messages intended for the developers.  These are TYPICALLY cries, bleats, or yelps for help to tell the programmer that something unexpected has happened.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Since this isn't "Adventures in Usering", I'll focus mainly on the latter.&lt;br /&gt;&lt;br /&gt;So what makes a good error message?  I've given this a bit of thought lately, and I think that a really good error message has the following 4 qualities:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It tells what was expected.&lt;/li&gt;&lt;li&gt;It tells what it actually got, and how or why that is different than what was expected.&lt;/li&gt;&lt;li&gt;It tells how or why this might have happened.&lt;/li&gt;&lt;li&gt;It gives some direction on how to fix the problem.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;As an example of a good error message, let's look at some pro and counter examples.&lt;br /&gt;&lt;br /&gt;The ultimate counter example of all 4 qualities can be seen here&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Awesome.  It tells me, as a developer, absolutely nothing useful to find out what the heck happened, what was SUPPOSED to happen, &lt;span style="font-style: italic;"&gt;where&lt;/span&gt; it happened, or what I'm supposed to do about it.  This particular nugget occured while starting up an application server.  Since it is java code, I was able to see the stack trace that led to it, so I had a &lt;span style="font-weight: bold;"&gt;very small&lt;/span&gt; clue as to where to start looking. &lt;br /&gt;&lt;br /&gt;This is an example of a very common type of error message; the "I'm an error message" message.  We've all seen these; they provide no useful information other than the fact an error occurred.  A message announcing that an error occurred is obviated by the fact the message is there at all.  I used to joke in college that I was going to write a compiler and to save message space, it would have one error message that said simply, "No".  I didn't think so many developers would steal and stylize my idea, but apparently they have.&lt;br /&gt;&lt;br /&gt;So what would have been better?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tell me what was expected&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this case, this error was the result of a missing file that was needed during some startup code.  So, tell me that.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler.  &lt;span style="font-weight: bold; text-decoration: underline;"&gt;Expected to read from file: /opt/apps/config/i18n.xml&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;NOW we're getting somewhere.  Even with THIS bit of info, I might have an idea by putting together that there IS an error message, and that it's saying that it's expecting to read from a given file, that maybe something is wrong with that file.  My years of experience might lead me to see if that  file exists, its permissions are such that it can be read by the app, it looks "ok" (not zero length, the format matches what it probably should (xml), etc.)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tell me what &lt;span style="font-style: italic;"&gt;actually &lt;/span&gt;occurred&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that we know what the app wanted, an indication of what differed from this expectation would be nice.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler. Expected to read from file: /opt/apps/config/i18n.xml&lt;span style="font-weight: bold;"&gt;&lt;span style="text-decoration: underline;"&gt;, but file was not found&lt;/span&gt;&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Hey now, this looks promising.  And spares me the checks I would have had to make if this tidbit were missing, as before.  Too, it disambiguates from something like...&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler. Expected to read from file: /opt/apps/config/i18n.xml&lt;span style="font-weight: bold;"&gt;&lt;span style="text-decoration: underline;"&gt;, but file is not readable&lt;/span&gt;&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tell me how this happened&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately, this isn't always possible, and sometimes the first 2 bits of information are more than enough to get started.  But when writing error messages, if you have any idea of how the error could have occurred, put it in the message.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler.  Expected to read from file: /opt/apps/config/i18n.xml, but file is not readable.  &lt;span style="font-weight: bold; text-decoration: underline;"&gt;This can occur if permissions are set incorrectly on the file or its directory.  This happens often during an initial setup of the application, since this file is deployed separately from the application itself.&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Be careful here, this &lt;span style="font-style: italic;"&gt;might&lt;/span&gt; lead a developer or tester to the wrong conclusion.  When writing error messages, if there are a litany of reasons an error might occur, I will often leave this step out since it would be too much to list them, and just listing some might cause one to not check the others.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Tell me how to fix it&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This one can also be tricky, since it's often not known how to fix the problem, especially when the error message is first being coded.  However, I've found that over time developers will tend to see a certain error and know what causes it.  If possible, that's the time to go back and fix the message (if possible, and it often isn't).  Or of course, sometimes an error can only be fixed in a limited number of ways.  So, list them.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;Exception data: com.stuff.SystemException: Failed to initialise or configure service: config class com.stuff.ConfigurationImpl, prefix DefaultHandler, serviceClassName com.stuff.DefaultServiceExceptionHandler. Expected to read from file: /opt/apps/config/i18n.xml, but file is not readable.  This can occur if permissions are set incorrectly on the file or its directory.  This happens often during an initial setup of the application, since this file is deployed separately from the application itself.  &lt;span style="font-weight: bold; text-decoration: underline;"&gt;Check the permissions on /opt/apps/config/i18n.xml to ensure they are readable by the application.&lt;/span&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Although I've gone a bit off the deep end on this particular example, if I'd had this information on this very real  message (but somewhat obfuscated to protect the perpetrators of such heinousosity), it would have saved a lot of debugging time.  In this particular case, the application reads a file that lists what OTHER files it should read, and it was one of those second level files that was missing.  Because the error message was so vague, I had to step-debug into the code at that point, and check EACH LOOP ITERATION until I found the offending iteration and fix the file it couldn't find.  This took the better part of a half hour, and it wasn't the first time, so I knew where to start.   Two minutes by the original programmer would have saved me and coworkers of mine hours of debugging time.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3965682379736830499-8632947314253457206?l=developmentadventures.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://developmentadventures.blogspot.com/feeds/8632947314253457206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3965682379736830499&amp;postID=8632947314253457206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8632947314253457206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3965682379736830499/posts/default/8632947314253457206'/><link rel='alternate' type='text/html' href='http://developmentadventures.blogspot.com/2008/04/what-good-error-message.html' title='What&amp;#39;s A Good Error Message?'/><author><name>Michael Campbell</name><uri>http://www.blogger.com/profile/15025907481819573844</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
