<?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-3240281421131142620</id><updated>2012-01-09T22:24:08.836-08:00</updated><category term='gtd'/><category term='meta'/><category term='android'/><category term='emacs'/><category term='scala'/><category term='java'/><category term='language'/><category term='social'/><category term='productivity'/><category term='sourcecontrol'/><category term='testing'/><category term='data'/><category term='org-mode'/><category term='ansi-term'/><title type='text'>Technical Dresese</title><subtitle type='html'>Thoughts on technical matters.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-1774675451414983345</id><published>2011-10-08T18:44:00.000-07:00</published><updated>2011-10-09T20:52:07.711-07:00</updated><title type='text'>code-imports</title><content type='html'>I finally put up the emacs based code import-management solution I've been using for a while.  I wrote a similar thing a few years ago at Google, but I rethought and rewrote this, plus added a bunch of ert tests.I've put it up as&amp;nbsp;&lt;a href="https://github.com/ahyatt/code-imports"&gt;code-imports&lt;/a&gt;&amp;nbsp;in github. &amp;nbsp;The module allows you to organize imports according to predefined rules, as well as grab other files as imports and add them as imports to a target file.&lt;br /&gt;&lt;br /&gt;As opposed to the earlier incarnation, I've extracted as much as the logic as possible into purely functional functions, which makes it easy to test. &amp;nbsp;In my experience, import management is complicated enough that manual testing is just not enough to ensure a stable product. &amp;nbsp;Testing the code thoroughly is one way to solve this problem. &amp;nbsp;I've also simplified the number of concepts in the code, and the number of variable to tweak to the bare minimum. &lt;br /&gt;&lt;br /&gt;I'm going to refine this a bit, then announce it more broadly shortly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-1774675451414983345?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/1774675451414983345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=1774675451414983345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1774675451414983345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1774675451414983345'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2011/10/code-imports.html' title='code-imports'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-6246695972139262500</id><published>2011-04-09T09:57:00.000-07:00</published><updated>2011-04-09T09:57:19.943-07:00</updated><title type='text'>A brief demonstration of emacs new lexical bindings</title><content type='html'>It wasn't a joke. &amp;nbsp;On April 1st, Stefan Monnier &lt;a href="http://lists.gnu.org/archive/html/emacs-devel/2011-04/msg00043.html"&gt;merged the lexical binding branch into the emacs trunk&lt;/a&gt;. &amp;nbsp;Unless it needs to be rolled back, emacs 24 should have lexical binding, which is a huge improvement for elisp. &amp;nbsp;If you want to try it out, &lt;a href="http://www.emacswiki.org/emacs/BzrForEmacsCasualDevs"&gt;get the latest emacs from source, and compile it yourself&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To enable it, you need to set &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;lexical-binding&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"&gt;&amp;nbsp;to &lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;t&lt;/b&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"&gt;. &amp;nbsp;This is buffer local, so you need to set it for every buffer that you want to have lexical binding in.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's a demonstration in an ielm session (M-x &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ielm&lt;/span&gt;&lt;/b&gt;).&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ELISP&amp;gt; (setq lexical-binding t)&lt;br /&gt;t&lt;br /&gt;ELISP&amp;gt; (defun make-adder (base) (lambda (num) (+ num base)))&lt;br /&gt;make-adder&lt;br /&gt;ELISP&amp;gt; (setq x 1)&lt;br /&gt;1&lt;br /&gt;ELISP&amp;gt; (setq 1-adder (make-adder x))&lt;br /&gt;(closure&lt;br /&gt;((base . 1)&lt;br /&gt;t)&lt;br /&gt;(num)&lt;br /&gt;(+ num base))&lt;br /&gt;ELISP&amp;gt; (funcall 1-adder 10)&lt;br /&gt;11&lt;br /&gt;ELISP&amp;gt; (funcall 1-adder 100)&lt;br /&gt;101&lt;br /&gt;ELISP&amp;gt; (setq x 100)&lt;br /&gt;100&lt;br /&gt;ELISP&amp;gt; (funcall 1-adder 100)&lt;br /&gt;101&lt;/span&gt;&lt;/blockquote&gt;Without lexical binding, the variable &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;x&lt;/b&gt;&lt;/span&gt; would be a dynamic variable, and so when we set it to 100 later in the session, the &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;1-adder&lt;/span&gt;&lt;/b&gt; would change to a 100-adder inadvertently. &amp;nbsp;In fact, if we try, we can't even get to that point. &amp;nbsp;Here's the same session without lexical binding:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ELISP&amp;gt; lexical-binding&lt;br /&gt;nil&lt;br /&gt;ELISP&amp;gt; (defun make-adder (base) (lambda (num) (+ num base)))&lt;br /&gt;make-adder&lt;br /&gt;ELISP&amp;gt; (setq x 1)&lt;br /&gt;1&lt;br /&gt;ELISP&amp;gt; (setq 1-adder (make-adder x))&lt;br /&gt;(lambda&lt;br /&gt;(num)&lt;br /&gt;(+ num base))&lt;br /&gt;ELISP&amp;gt; (funcall 1-adder 10)&lt;br /&gt;*** Eval error ***  Symbol's value as variable is void: base&lt;/span&gt;&lt;/blockquote&gt;What's going on here? &amp;nbsp;Notice that when we make the &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;1-adder&lt;/span&gt;&lt;/b&gt; without lexical binding, we don't get a closure. &amp;nbsp; Instead, we just get a function that references &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;num&lt;/span&gt;&lt;/b&gt; and &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base&lt;/span&gt;&lt;/b&gt;. &amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;num&lt;/span&gt;&lt;/b&gt; is passed into the function, but &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;b&gt;base&lt;/b&gt;&lt;/span&gt; is a dynamic variable, so it is interpreted in the emacs global context, as opposed to a context inside a closure. &amp;nbsp;The variable &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base&lt;/span&gt;&lt;/b&gt; is not bound to a value in the global context, and when we execute the lambda, which refers to &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base&lt;/span&gt;&lt;/b&gt;, emacs looks for the &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base&lt;/span&gt;&lt;/b&gt; variable, cannot find it, and throws an error. &lt;br /&gt;&lt;br /&gt;This doesn't happen with lexical binding. &amp;nbsp;In that case, we can actually see the closure itself being returned when there is lexical binding:&lt;br /&gt;&lt;blockquote&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;(closure&lt;br /&gt;((base . 1)&lt;br /&gt;t)&lt;br /&gt;(num)&lt;br /&gt;(+ num base))&lt;/span&gt;&lt;/blockquote&gt;The closure here shows a structure in which we can interpret to mean that&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base&lt;/span&gt;&lt;/b&gt; is being bound to 1. &amp;nbsp;You can also see&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;num&lt;/span&gt;&lt;/b&gt; is the argument (since it is not in the same s-expression as the binding of &lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;base)&lt;/span&gt;&lt;/b&gt;, and then it proceeds with the simple addition function.&lt;br /&gt;&lt;br /&gt;I haven't yet made use of closures in my emacs code. &amp;nbsp;I don't really need it in my initialization files, and if I writes modules that assume it then almost no one can yet use it. &amp;nbsp;So I'll give it time, but it's a huge step in making elisp a better lisp. &amp;nbsp;Read more about lexical bindings Paul Graham's wonderful free book &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Lexical bindings are not only a good feature in themselves, they are also is an important step on the way to multithreading. &amp;nbsp;Having nothing but global variables makes threading quite challenging, and lexical bindings in the standard elisp packages can help make multithreading easier.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-6246695972139262500?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/6246695972139262500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=6246695972139262500' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6246695972139262500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6246695972139262500'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2011/04/brief-demonstration-of-emacs-new.html' title='A brief demonstration of emacs new lexical bindings'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-5146172353213932971</id><published>2011-03-21T20:20:00.001-07:00</published><updated>2011-03-21T20:20:25.546-07:00</updated><title type='text'>Data</title><content type='html'>&lt;div&gt;&lt;p&gt;Humans are not very good at remembering event frequency statistics. We tend to only remember the unusual, and forget about the common case.&amp;nbsp; There are plenty of other cognitive errors we make, but this seems to me one of the most troublesome.&lt;/p&gt;&lt;p&gt;An example: Every day I take the subway from Forest Hills in Queens to Manhattan.&amp;#160; Either the E or F train will arrive first, and I need the E train. I was noticing, though, that it always seemed to be the F train arriving first, making me wait for an extra few minutes.&lt;/p&gt;&lt;p&gt;Why would that be? Could it be a situation like Feynman's girlfriend puzzle, where the E train closely follows the F?&amp;#160; I decided to keep some statistics to find out.&lt;/p&gt;&lt;p&gt;Every day, I'd record which train came first. After a few days, I noticed the E had been coming first lately. Surely a fluke. &lt;/p&gt;&lt;p&gt;I kept at it, and before long the trend was clear. The E comes first almost twice as often! I counted 18 E firsts, and only 10 F firsts. &lt;/p&gt;&lt;p&gt;Obviously, I was completely wrong about even the most basic statistics for my morning commute, and that's about something I experience every single workday morning. Think how wrong I can be about everything else!&lt;/p&gt;&lt;p&gt;I take this as a warning about not trusting experiences when making decisions. Get data instead. Even just some data will be better than opinion or memories. &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/3240281421131142620-5146172353213932971?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/5146172353213932971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=5146172353213932971' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5146172353213932971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5146172353213932971'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2011/03/data.html' title='Data'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-7996201071530020957</id><published>2011-01-05T09:14:00.001-08:00</published><updated>2011-01-05T09:14:25.419-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='social'/><title type='text'>Does everything have to be social?</title><content type='html'>&lt;div&gt;&lt;p&gt;All I wanted to do was to download a document. To do that, I had to sign up for Scribd via my Facebook account. Next thing I know, I am getting follower notifications emails from some of my Facebook friends.&lt;/p&gt;&lt;p&gt;I just wanted to download a document. Now I'm connected to all sorts of friends. What do they want from me? Did they even explicitly choose to friend me or was it automatically done by Scribd?&lt;/p&gt;&lt;p&gt;For the time being, I'm just going to ignore it all and hope it goes away.&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/3240281421131142620-7996201071530020957?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/7996201071530020957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=7996201071530020957' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/7996201071530020957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/7996201071530020957'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2011/01/does-everything-have-to-be-social.html' title='Does everything have to be social?'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-4013381546567903683</id><published>2010-11-05T20:48:00.000-07:00</published><updated>2010-11-05T20:48:42.567-07:00</updated><title type='text'>Macros and meta-macros</title><content type='html'>Life is repetition. &amp;nbsp;We do the same things, day after day. &amp;nbsp;Within each day at work, we find ourselves performing the same actions, more or less. &amp;nbsp; The great thing about computers is that tasks performed on computers can be automated. &amp;nbsp;So any time we find that we are repeated ourselves on the computer, we have an opportunity of creating a tool that will allow us to eliminate repetition.&lt;br /&gt;&lt;br /&gt;Macros are a great example of this, and one of the defining feature of lisp. &amp;nbsp;Sure, c++ has macros as well, and they share same of the same capabilities as lisp's macros, but in general the power of lisp macros make them better for everyday use. &amp;nbsp;Macros are great tools to reduce repetitive code to simple forms. &amp;nbsp;Code such as:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/665169.js?file=gistfile1.cl"&gt;&lt;/script&gt;&lt;br /&gt;Seems reasonable enough if you just are opening up one file. &amp;nbsp;But what if you do this all the time? &amp;nbsp;Even the simple boilerplate here starts to add up. &amp;nbsp;That's why common lisp created a macro of an easy way to do this:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/665174.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;What a breath of fresh air that is... there is absolutely nothing wasted here. &amp;nbsp;All repetitive and wasted code has been removed, leaving only the essence of the task. &amp;nbsp;That's the art of the macro. &amp;nbsp;It's one thing to be able to write macros, but to recognize patterns of repetition is a skill worth practicing.&lt;br /&gt;&lt;br /&gt;Meta-macros are a term I just made up for this post, which describes repetitive coding tasks we have to perform. &amp;nbsp;To take a simple example, perhaps you are always navigating to the same files. &amp;nbsp;Like macros, it is essential that we realize we are doing something repetitive, and that this task can be removed with automation. &amp;nbsp;In this case, emacs provides a solution: bookmarks. &amp;nbsp;Many times the solution isn't provided by emacs, though, or the patterns are more complicated. &amp;nbsp; Every time I change or add a new function in my .cc file, I have to edit my .h file as well. &amp;nbsp;This is just a natural part of editing C++ code, something so ingrained in us that it's hard to even imagine not going through the trouble of essentially adding function definitions twice. &amp;nbsp;It's a plainly repetitive task, which could certainly be automated with a meta-macro, by which I mean some elisp code. &lt;br /&gt;&lt;br /&gt;Sometimes these meta-macro's automation can increase complexity. &amp;nbsp;It works fine 98% of the time, but 2% of the time it screws you up and you stop using the meta-macro in frustration. &amp;nbsp;But macros can have the same trait. &amp;nbsp;Good macros are actually a bit hard to write, and can be very confusing when they fail. &amp;nbsp;Meta-macros can be even worse, due to the complexity of the meta level in which we operate. &amp;nbsp;It takes dedication to solve each new problem you encounter, making your meta-macro more and more robust. &amp;nbsp;But, with enough effort, you will have an elegant solution that makes you more productive, and able to focus on problem solving, not mere coding.&lt;br /&gt;&lt;br /&gt;When you do, please share it with the word. &amp;nbsp;We all need the help.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-4013381546567903683?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/4013381546567903683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=4013381546567903683' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/4013381546567903683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/4013381546567903683'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2010/11/macros-and-meta-macros.html' title='Macros and meta-macros'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-3439033435696804017</id><published>2010-10-31T18:52:00.000-07:00</published><updated>2010-10-31T18:52:37.770-07:00</updated><title type='text'>Breadcrumb mode for emacs</title><content type='html'>I found this useful mode via &lt;a href="http://reddit.com/"&gt;reddit&lt;/a&gt;: &lt;a href="http://breadcrumbemacs.sourceforge.net/"&gt;breadcrumb&lt;/a&gt;. &amp;nbsp;It allows you to define bookmarks with a keypress. &amp;nbsp;The bookmarks are unnamed, but you can jump between them, either between-buffer or within-buffer. &amp;nbsp;This should be really useful for working within a changelist.&lt;br /&gt;&lt;br /&gt;One thing that may be useful would be loading or saving breadcrumb state, as I switch between working on different projects. &amp;nbsp;So I may have to add this (it probably isn't that hard).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-3439033435696804017?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/3439033435696804017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=3439033435696804017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3439033435696804017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3439033435696804017'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2010/10/breadcrumb-mode-for-emacs.html' title='Breadcrumb mode for emacs'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-6459611292383029131</id><published>2010-02-23T20:26:00.000-08:00</published><updated>2012-01-09T20:27:10.043-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ansi-term'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Saner ansi-term in emacs</title><content type='html'>&lt;div&gt;I like ansi-term in emacs.  It is the closest to a "real" terminal, offering all the goodness that bash, zsh, or whatever your favorite shell can give you.  However, you definitely lose a few things in going to it.  The following emacs code restores at least the things I find most useful: dabbrev-completion, yanking, and correct colors.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you use this code, note that dabbrev-completion is C-c /, and yanking is C-c C-y.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;script src="https://gist.github.com/313104.js"&gt; &lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-6459611292383029131?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/6459611292383029131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=6459611292383029131' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6459611292383029131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6459611292383029131'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2010/02/saner-ansi-term-in-emacs.html' title='Saner ansi-term in emacs'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-2900221462154796773</id><published>2009-09-25T22:12:00.000-07:00</published><updated>2009-09-26T12:28:47.003-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='android'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Android, Scala, and java.rmi.RemoteException</title><content type='html'>For fun, I've been experimenting with writing an Android application using scala.  Now, being a conscientious developer, I'm following the principles of TDD, at least with the low-level database interface.&lt;br /&gt;&lt;br /&gt;This proved a bit hard to do.  I won't go into the details of integrating Scala and Android, since Christian Neukirchen did a good job of that with his article &lt;a href="http://chneukirchen.org/blog/archive/2009/04/programming-for-android-with%20scala.html"&gt;Programming for Android with Scala&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After following the advice in that class, you basically have to double it to compile, dex, and trim the test tree as well.&lt;br /&gt;&lt;br /&gt;The big issue I had was trying to use &lt;a href="http://www.artima.com/scalatest/"&gt;ScalaTest&lt;/a&gt; with Android testing. As far as I know, no one has tried to do this yet.&lt;br /&gt;&lt;br /&gt;First, Android testing is very particular.  You can't just run any old class on the phone, instead there is a particular runner called the &lt;code&gt;InstrumentationTestRunner&lt;/code&gt; to run tests.  So, you need either Android-specific test classes, or JUnit classes.  I therefore had to write a converter class:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;class ScalaUnitTestRunner extends TestCase {&lt;br /&gt;  def testExerciseList() = {&lt;br /&gt;    new ExerciseListDaoSpec().execute()&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simple and needs improvement, but it's the most basic thing that can work.  The &lt;code&gt;execute&lt;/code&gt; call runs the scalatests in that test class.&lt;br /&gt;&lt;br /&gt;The problem was that when running, I would get this error on running:&lt;br /&gt;&lt;br /&gt;&lt;pre class="example"&gt;[exec] android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests:&lt;br /&gt;[exec] Error in testSuiteConstructionFailed:&lt;br /&gt;[exec] java.lang.RuntimeException: Exception during suite construction&lt;br /&gt;[exec]     at android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteConstructionFailed(TestSuiteBuilder.java:239)&lt;br /&gt;[exec]     at java.lang.reflect.Method.invokeNative(Native Method)&lt;br /&gt;[exec]     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:164)&lt;br /&gt;[exec]     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:151)&lt;br /&gt;[exec]     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:418)&lt;br /&gt;[exec]     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1520)&lt;br /&gt;[exec] Caused by: java.lang.TypeNotPresentException: Type java.rmi.RemoteException not present&lt;br /&gt;[exec]     at java.lang.Class.getDeclaredMethods(Native Method)&lt;br /&gt;[exec]     at java.lang.ClassCache.getDeclaredPublicMethods(ClassCache.java&lt;br /&gt;[exec]     at java.lang.ClassCache.getDeclaredMethods(ClassCache.java:179)&lt;br /&gt;[exec]     at java.lang.ClassCache.findAllMethods(ClassCache.java:249)&lt;br /&gt;[exec]     at java.lang.ClassCache.getFullListOfMethods(ClassCache.java:223)&lt;br /&gt;[exec]     at java.lang.ClassCache.getAllPublicMethods(ClassCache.java:204)&lt;br /&gt;[exec]     at java.lang.Class.getMethods(Class.java:1038)&lt;br /&gt;[exec]     at android.test.suitebuilder.TestGrouping.getTestMethods(TestGrouping.java:79)&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The problem was that for some reason every Scala class contains a special method called &lt;code&gt;$tag&lt;/code&gt;.  If you used &lt;code&gt;javap&lt;/code&gt; to investigate, you'd find the class looks like:&lt;br /&gt;&lt;pre class="example"&gt;~/src/AshExercises $ javap -classpath testbin/classes com.ash.exercisetests.db.ScalaUnitTestRunner&lt;br /&gt;Compiled from "ScalaUnitTestRunner.scala"&lt;br /&gt;public class com.ash.exercisetests.db.ScalaUnitTestRunner extends junit.framework.TestCase implements scala.ScalaObject{&lt;br /&gt;public com.ash.exercisetests.db.ScalaUnitTestRunner();&lt;br /&gt;public void testExerciseList();&lt;br /&gt;public int $tag()       throws java.rmi.RemoteException;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Because Android's tester is using reflection here to find the test methods, it encounters this method with a class that Android doesn't know about.  I tried to define a fake java.rmi.RemoteException, but Android is smart and doesn't let you define core java classes.&lt;br /&gt;&lt;br /&gt;So, I had to change my tester to this:&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;class ScalaUnitTestRunner extends TestCase {&lt;br /&gt;  def testExerciseList() = {&lt;br /&gt;    new ExerciseListDaoSpec().execute()&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  override def $tag() : Int = {&lt;br /&gt;    try {&lt;br /&gt;      return super.$tag();&lt;br /&gt;    } catch {&lt;br /&gt;      case e: Exception =&gt; throw new RuntimeException(e);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That fixed that issue.&lt;br /&gt;&lt;br /&gt;The next issue it had was that Android was giving me &lt;code&gt;java.lang.VerifyError&lt;/code&gt; on running.  This turned out to be my fault, but what I had to figure out was that &lt;code&gt;java.lang.VerifyError&lt;/code&gt; really meant a ClassCastException.  I found this out by looking in the logcat.&lt;br /&gt;&lt;br /&gt;&lt;pre class="example"&gt;E/dalvikvm(  726): Could not find class 'com.ash.exercise.db.ExerciseDatabase', referenced from method com.ash.exercisetests.db.ExerciseListDaoSpec.&amp;lt;init&amp;gt;&lt;br /&gt;W/dalvikvm(  726): VFY: unable to resolve new-instance 13 (Lcom/ash/exercise/db/ExerciseDatabase;) in Lcom/ash/exercisetests/db/ExerciseListDaoSpec;&lt;br /&gt;W/dalvikvm(  726): VFY:  rejecting opcode 0x22 at 0x0019&lt;br /&gt;W/dalvikvm(  726): VFY:  rejected Lcom/ash/exercisetests/db/ExerciseListDaoSpec;.&amp;lt;init&amp;gt; ()V&lt;br /&gt;W/dalvikvm(  726): Verifier rejected class Lcom/ash/exercisetests/db/ExerciseListDaoSpec;&lt;br /&gt;I/TestRunner(  726): failed: testExerciseList(com.ash.exercisetests.db.ScalaUnit&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It turned out I was compiling against the non-test src, but wasn't including the non-test src in my proguard step, so that the classes never wound up in my apk.&lt;br /&gt;&lt;br /&gt;I hope these tidbits help someone who is exploring Android, Scala, and unit tests.  Good luck, and happy coding!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-2900221462154796773?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/2900221462154796773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=2900221462154796773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2900221462154796773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2900221462154796773'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2009/09/android-scala-and-javarmiremoteexceptio.html' title='Android, Scala, and java.rmi.RemoteException'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-3473764945034203441</id><published>2009-06-01T10:28:00.000-07:00</published><updated>2009-06-01T10:43:25.956-07:00</updated><title type='text'>Distractions</title><content type='html'>Distractions, or no distractions? For your normal coder, most would prefer no distractions.  A distraction at the wrong moment could lose a train of thought, wipe out working memory, and set the programmer back by half an hour of time.  Not good.  And it is common for programmers to feel overwhelmed with distractions.&lt;br /&gt;&lt;br /&gt;However, distractions are useful to the programmer as well.  Without distractions, a coder would never get important information.  They would never hear a conversation about a problem that they have unique insight into.  An interesting fact discussed by two colleagues would go unheard and unremembered.  Distractions are unplanned and often&lt;br /&gt;random, but that's often why they are beneficial.  The benefits of locality via distractions is dealt with in &lt;i&gt;The Social Life of Information&lt;/i&gt; by John Seely Brown and Paul Duguid.&lt;br /&gt;&lt;br /&gt;A theoretically distraction-free programmer may get a lot done, but they also deprive others of their insight, and they may miss out on random learning opportunities.  This is a problem, because the job of the programmer is not only to design, implement features, or fix bugs, but also to exchange information to help others, and to better themselves.  These are the valuable kind of distractions programmers need.&lt;br /&gt;&lt;br /&gt;Not only work-related distractions are helpful.  Taking a break from work entirely is helpful.  Standing up and moving around every once and a while is healthy.  Doing fun things with coworkers such as playing foosball promotes camaraderie and teamwork.&lt;br /&gt;&lt;br /&gt;We need distractions, although clearly too much is a problem.  So, the question is how to process distractions and keep our sanity at the same time.&lt;br /&gt;&lt;br /&gt;The first thing to realize is that a distraction creates stress because it causes a prioritization conflict.  A developer is supposed to be working on &lt;i&gt;x&lt;/i&gt;, but now is distracted and doing task &lt;i&gt;y&lt;/i&gt;.  Well, there are a few possibilities:&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;&lt;dt&gt;&lt;i&gt;x&lt;/i&gt; is more important than the distractor &lt;i&gt;y&lt;/i&gt;&lt;/dt&gt;&lt;dd&gt; A fairly normal case, that comes in a variety of flavors.  For example, you are programming very productively when you decide to check your mail. This was a mistake.  Now you are out of the mindset of &lt;i&gt;x&lt;/i&gt;, and are dealing with some mail &lt;i&gt;y&lt;/i&gt; that is not ultimately as important as getting your work done.  Or, you are programming and get distracted by an unimportant IM message.  Or, you are are programming and the loud conversation next to you is constantly pulling your attention away.  For all these things, working in a distraction-free environment for at least part of your time is useful to get rid of part of these distractions, and training your mind not to jump around and want to check mail and surf the web is a way to get rid of the other part.  Meditation and just plain practice in focusing is important here. &lt;br /&gt;&lt;br /&gt;Even though being distraction free for a while is useful, this shouldn't be an all-day activity, even during rush times.  Spend some time and open yourself up to distractions for part of your day.  You will learn unexpected things, engage in conversation and relaxation, help people, and get to do all the tiny tasks that accumulate throughout the day.&lt;br /&gt;&lt;/dd&gt;&lt;br /&gt;&lt;dt&gt;&lt;i&gt;x&lt;/i&gt; is less important than the distractor &lt;i&gt;y&lt;/i&gt;&lt;/dt&gt;&lt;dd&gt; For example, you are working on an important refactoring of your code.  All of the sudden, your coworker leans over and tells you that your last changelist broke the build.  Obviously, you have to drop what you are doing and fix the problem.  You lose context and time, but that's unavoidable.  Hopefully, this kind of thing is rare.  If it isn't, you may want to check that you have the proper processes in place.  &lt;br /&gt;&lt;br /&gt;If there are still too many urgent interruptions, then it would help to have one person process all the interrupts of the team. For example, for one week Jane Programmer handles all interrupts for the team, and does not attempt to do non-interrupt-based work at all.  This is actually psychology comforting, because she doesn't have to worry about her interrupts slowing her down on her main project.  She's already decided that the only work she gets done is what are normally distractions.  And if she finds herself distraction-free, she can always do little code cleanups and fixes that she always intended to do but never got around to.  She's happy and the rest of the team is more productive by not having to worry about distractions.  This should more than offset any productivity loss by Jane Programmer's not working on her project.&lt;br /&gt;&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;Hopefully, by following rules like these we can manage to use the opportunities distractions provide, as well as to minimize their impact.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-3473764945034203441?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/3473764945034203441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=3473764945034203441' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3473764945034203441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3473764945034203441'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2009/06/distractions.html' title='Distractions'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-2885444901333114143</id><published>2008-11-29T13:07:00.000-08:00</published><updated>2008-12-06T20:30:10.842-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Why I've abandoned Eclipse for Emacs</title><content type='html'>Maybe this isn't a big surprise.  I've always used emacs, even when using Eclipse.  I'm used to emacs, and I use it for absolutely everything: shell, mail, task planner and more. For a while, though I did not do most of my Java coding in it.  There I mostly used Eclipse, unless I was just doing something quick.  After all Eclipse has great tools for refactoring, automatic imports, quick detection and correction of errors, and more.  It's a really great product.  Not only that, but it's unsurpassed at quick unit test cycles, mostly requiring no complication.&lt;br /&gt;&lt;br /&gt;Emacs has none of that.  But it does have a number of things going for it, and because of these things, I've stopped using Eclipse entirely, and have continued to be productive over the last few months using only emacs.  Here's why:&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Editing&lt;/span&gt;.  Emacs is a great editor, unquestionably better at editing than Eclipse.  For example, I can do comment formatting extremely quickly in emacs (Meta-q).  It's possible to do this Eclipse as well, but it's less flexible and requires more interaction.  There are many similar minor things that make emacs a better code editor, as far as textual edits go.&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Lack of projects&lt;/span&gt;.  Emacs is unconstrained.  Editing a file for Project A, I can switch to a file in Project B as quickly as I can switch to another file in Project A.   Emacs does not care about projects, which means it can't give you all the goodies Eclipse can, but it also doesn't tie you down in the same way Eclipse does. &lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Speed.  &lt;/span&gt;This is probably the most important reasons I've been doing everything in emacs.  There are many different kinds of speed, and most of them are important.  Emacs, being lightweight in comparison to Eclipse, has greater speed of editing.  Eclipse has greater speed in the change/compile/test cycle, which is very important.  But the one that seems important to me is that Emacs has no large pauses, where Eclipse does.  I switch projects a lot, and every time I do it seems like Eclipse has to build itself for 10 minutes.  IntelliJ doesn't have this problem, but that's because it does less up-front work; everything else is slower.  When I go work with someone who uses Eclipse, we often spend the first 10 minutes just waiting for Eclipse to build the project.   It's very frustrating.  If we were using emacs, we would already be on our way.&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Reliability.  &lt;/span&gt;Eclipse is a large moving part, and it is one that seems prone to failure.  Once you get burned a couple of times by problems that only are in Eclipse, getting that bit of unpredictability out of the system is a time-saver.  Emacs can get that way too, especially if you use something like jdee-mode.  I like to keep it relatively simple in emacs, though. &lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;It's emacs&lt;/span&gt;. This is somewhat tautological, but the truth is that once emacs is handling several important tasks for you, you get more and more benefit by bringing activity into it.  This is why I can read a mail in gnus (using nnimap), store it in my to-do list in org-mode, and then find some relevant piece of code in emacs and link it to the task in org-mode.  It all fits together beautifully.  And whatever you need is there for you, somewhere.  Writing a javadoc and want to put a diagram in there?  Emacs can make it easy; use artist-mode.  There's so much stuff to discover here.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For programming in Java, I just use java-mode, but I've written a few things to make my life easier.  I use anything-mode to quickly go to any Java file, ffap so I can quickly open up include files, and use M-x compile so I can jump to errors.   I've also written a little import management system that I'll post on this blog shortly.  So I find that I'm reasonably efficient.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All in all, my startup time is much quicker for emacs, but I lose time on editing.  I'd recommend emacs over Eclipse if you tend to work on a variety of tasks and you use emacs now.  If you spend most of your day writing Java, Eclipse is probably going to be better suited to that.&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/3240281421131142620-2885444901333114143?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/2885444901333114143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=2885444901333114143' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2885444901333114143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2885444901333114143'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2008/11/why-ive-abandoned-eclipse-for-emacs.html' title='Why I&apos;ve abandoned Eclipse for Emacs'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-1896061720748173617</id><published>2008-09-27T10:58:00.000-07:00</published><updated>2008-10-21T18:26:00.543-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sourcecontrol'/><title type='text'>Git in the office</title><content type='html'>I've been using &lt;a href="http://git.or.cz/"&gt;git&lt;/a&gt; recently. Not just me, in fact, but lots of open-source projects have started using it.   Right now I use it on github, to keep track of my &lt;a href="http://github.com/ahyatt/ash-emacs-customization/tree/master"&gt;emacs customizations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Git is a very interesting source control system to use, mainly because it makes it extremely easy to do branches and patching.  Linus has a very interesting &lt;a href="http://www.youtube.com/watch?v=4XpnKHJAok8"&gt;video on the rationale behind creating git&lt;/a&gt;, but to sum up his point in a few sentences: distributed source control, by allowing local modifications and local patches that can be easiliy merged, avoids the problems of latency and namespace pollution you get using centralized source control systems.  Also, he says git is the best distributed one out there, because it is very fast.   I really can't comment on whether it is the best, I haven't used darcs or any of the other distributed source control systems that have become popular.&lt;br /&gt;&lt;br /&gt;Git can be useful for the corporate developer.  When you have the ability to do local commits and local branches, development becomes more efficient.  You can commit changes at notable points, so if you've spent the last few hours fruitlessly exploring an interesting idea, you can revert back to your last good commit and proceed without having to manually unwind your changes.  Or, if you need to make a quick bugfix, you can just branch off of the current head branch, make a fix, then check it in and return to your previous branch.  The ability to always stay in one directory tree can be an efficiency gain as well.  And you can work offline, doing commits and everything you can do with a centralized source control system.  When you get online and you are ready, you just push all those commits to some other git repository.&lt;br /&gt;&lt;br /&gt;So, how can software companies use git?  Companies have traditionally used centralized source control systems.  I've used CVS (ugh), Perforce (not bad), StarTeam (somewhat yucky, but tolerable), and Visual SourceSafe (flaky) at various companies.  It's easy to comprehend a centralized system like this; you have your code, it's in one place, and that's all.  Git can be like that too, in a way.  There could be one central git repository, and each developer would have their own local repository.  Developers could do their own commits on their machine, and when they have something worth checking into the main repository, they do a "git push" to push it there.  Or, instead someone in charge of the next release specifically pulls relevant changelists from developers machines to create a coherent release.   This is basically what open-source projects do. This would work for small companies, who don't need anything more complicated than that.&lt;br /&gt;&lt;br /&gt;If small companies could use git like a centralized repository system, large companies can use it in more interesting ways.&lt;br /&gt;&lt;br /&gt;Large companies often have distributed development offices where the pain of using a centralized source repository system is fairly large.  Also, large companies also have lots of source which they tend to put in one repository.   After a certain point, these repositories get slow.   Repository slowness plus network lag for remote offices create a real issue for distributed teams.  Git can help by allowing each team to have it's own local repository which they use.  Changes are aggregated from each developer's git repository to a local team repository.   When it's time to do a release, or at regular intervals, each team's repository is merged with the release repository.   Similarly, each team has to make sure their repository is in sync with the release repository, because that one has all relevant changes.&lt;br /&gt;&lt;br /&gt;There is a disadvantage to this: with distributed repositories, merges don't happen on every checkin.  Merges get put off, and when they happen they the conflicts are typically worse.  In such situations, it should be the responsibility of the individual teams to fix any merge problems, that happen when either pushing or pulling their changes.&lt;br /&gt;&lt;br /&gt;There would be some great advantages.  If you run a continuous build, you only see your own build breakages, not others.   The release branch can merge only repositories that are passing their tests, and therefore they always get changes that are good.  Of course, it should really run its own continuous build.  So you need more build machines, but you get more developer productivity, since any developer's local build is not affected by other developer's build breakages.&lt;br /&gt;&lt;br /&gt;From what I've been told, Microsoft has a similar tiered source control system for Windows.  For any sufficiently complicated project, such a system is in fact a necessity.&lt;br /&gt;&lt;br /&gt;Could this work?  I've never seen it happen, but git and distributed source control in general is relatively new.   The problem is that the benefits are greatest when the company is large, but the decision on what system to use is made when the company is small, where the benefits are less obvious.  It may be that some companies will adopt it for certain projects where it makes sense, but not universally.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-1896061720748173617?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/1896061720748173617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=1896061720748173617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1896061720748173617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1896061720748173617'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2008/09/git-in-office.html' title='Git in the office'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-4743240566891688377</id><published>2008-09-13T08:51:00.000-07:00</published><updated>2008-09-14T06:44:39.761-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Why emacs can survive without automated tests</title><content type='html'>Automated tests are an accepted best practice in software engineering, and it's hard to find a recently-formed, well-run software organization these days that doesn't have some form of automated series of small tests run against their codebase.&lt;br /&gt;&lt;br /&gt;The argument for automated tests is relatively simple: without them, there is no easy way to verify that a release of a project works.  Manual testing is slow and expensive, and all the work you put into it is lost when the next release comes out.   Furthermore, with frequently run automated tests, you can find out very quickly what changes caused which bugs, and so revert or fix those changes.&lt;br /&gt;&lt;br /&gt;Given all that, how does emacs survive, given that it has a huge codebase and no tests?&lt;br /&gt;&lt;br /&gt;The best thing it has going for it is that it's a desktop app.  That means that users have to upgrade from one version to the next, as opposed to web apps in which all users are upgraded when the server version changes.  Since users have to upgrade, and are in control of which version they get, user's versions range from very old to a build of yesterday's CVS head.  That means that a certain percentage of users are going to be on the bleeding edge.  Those users are either contributors on the project, or those that can tolerate increased bugginess.&lt;br /&gt;&lt;br /&gt;Another key is that emacs is a tool people use every day.  In fact, it's fair to say that everyone who is contributing to emacs is probably using emacs as their development environment.  So those contributing are using the CVS head, and are actively using the latest version.&lt;br /&gt;&lt;br /&gt;Let's assume that 1% of the emacs-using population is running off of a recent version of CVS head.  So, 1% is exposed to the latest code, and since these same people use it all the time, to do a diverse variety of things, they are testing it continuously, while getting their work done at the same time.  Not only are they testing it, but since these are power users, they know how to fix most problems they encounter.&lt;br /&gt;&lt;br /&gt;For example, imagine two developers, each working off of CVS head.  One checks in a change that breaks dired.  The second will get the latest changes, build it, run it, work on it, notice the error, know how to fix it, and can submit a fix immediately.  &lt;br /&gt;&lt;br /&gt;Eventually, at some time period after any particular changes is made, it can be assumed to be safe, because enough emacs users have been running systems with this change in, and have not had a problem.&lt;br /&gt;&lt;br /&gt;However, this implies that if emacs ever wants a stable version, it has to stop non-bugfix checkins, otherwise there will always be a change that hasn't been fully vetted yet.  And this is what emacs does - for a new release there is a long phase in which no new functionality is put in. &lt;br /&gt;It's worth noting that this phase is particularly long.  Emacs release cycles for major versions can last years.&lt;br /&gt;&lt;br /&gt;Let's imagine a world in which emacs did have automated tests of reasonable coverage.  What would change? &lt;br /&gt;&lt;br /&gt;First, the codebase would be more stable overall, so if you are an emacs contributor, you can expect a less buggy environment.  This certainly would make contributing more efficient, since you can concentrate on functionality, not fixing bugs.&lt;br /&gt;&lt;br /&gt;Secondly, the feature freeze stage could be significantly shortened.  If the unit tests were extremely comprehensive, one could imagine that no feature freeze would be necessary.&lt;br /&gt;&lt;br /&gt;All in all, then, in exchange for the considerable effort of developing unit tests for emacs, we can expect a codebase that can change must more rapidly and radically.  Whether this is a tradeoff that makes sense I can only guess.  Emacs is a mature product, not going through many radical changes anymore.  But, part of the reason that radical changes are not happening is not because they aren't needed, but because it is frankly just too hard.  It would take a very brave developer who would take on making emacs multithreaded, or switching to Scheme as a basis for elisp.  That could change with unit tests.  The tasks would still be hard, but it would not be so destabilizing anymore.  And automated tests wouldn't take much bravery to write, so I think automated tests may be a path to allow the more radical changes in emacs's future.&lt;br /&gt;&lt;br /&gt;What these tests would look like is a subject for another post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-4743240566891688377?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/4743240566891688377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=4743240566891688377' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/4743240566891688377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/4743240566891688377'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2008/09/why-emacs-can-survive-without-automated.html' title='Why emacs can survive without automated tests'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-2251954858898745939</id><published>2008-08-06T15:10:00.000-07:00</published><updated>2008-08-10T20:03:26.379-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data'/><title type='text'>Code is the easy part: Preventing data corruptions</title><content type='html'>Coding, coding, coding.  There's an awful lot of attention paid to coding in the software engineering world.  I read &lt;a href="http://www.reddit.com/r/programming/"&gt;redditt's programming category&lt;/a&gt; a lot these days, and most software engineering posts are about specifically code.  I think this is not because coding is the most important part of being a programmer, but because it is the most interesting and fun part.&amp;nbsp;&amp;nbsp; Code is easy to change.  If you have a bug, you reproduce it and fix it, and then it goes away.  Sometimes it's difficult, but even if it is, you fix it, make sure it doesn't happen again by writing test cases (preferably before you fix it), and then you forget about it. &lt;br /&gt;&lt;br /&gt;Let's contrast the fixing of bugs in code, with fixing corrupted data.  Corrupted data in any reasonable system is probably going to be caused by a software bug.   So, you first have to find out why the data is corrupted.&amp;nbsp; Of course, maybe the corruption is old, and the bug has been fixed.&amp;nbsp; Hard to say.&amp;nbsp; You have to investigate.&amp;nbsp; You could try and reproduce it, if you can figure out a likely scenario.&amp;nbsp; Most likely you will fail to reproduce it, and even more likely is that you know you will fail to reproduce it, so you don't try.&amp;nbsp; So instead you look at the code, seeing how it could happen.&amp;nbsp; This is a useful practice.&amp;nbsp; You can sometimes find the cause here.&amp;nbsp; Then you can write a test for it and fix it.&amp;nbsp;&amp;nbsp; After you fix it, your work isn't done, of course.&amp;nbsp; You have to actually fix the corruptions.&amp;nbsp; This could be a simple as running a SQL query, or as complicated as writing a script to patch things up using a code library to do the work.&amp;nbsp;&amp;nbsp; Of course, sometimes you never can find out why your data is corrupted, so you just have to fix it, if you can figure out how.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some amount of corrupted data is an inevitability, and in fact some may come from design decisions.&amp;nbsp; For example, some database systems cannot do two-phased commits, and if you need to hook into one, you may have to accept a certain amount of data corruption due to not having atomicity in your transactions.&amp;nbsp; If the error rate is very low, some corruption may be a fair price to pay for whatever benefits the second system is getting you.&amp;nbsp;&amp;nbsp; Even so, this is dangerous, and a low error rate today may be a severe error rate tomorrow, leaving you with a lot of angry customers with corrupted data, and a few dejected developers who have to clean it all up.&lt;br /&gt;&lt;br /&gt;There's a few best practices you can do to avoid data corruption&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Use one transactional system with &lt;a href="http://en.wikipedia.org/wiki/ACID"&gt;ACID&lt;/a&gt; properties, and use it correctly.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When using SQL, use foreign key references whenever possible.&amp;nbsp; &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Before saving data, assert its correctness as a precondition.&amp;nbsp; This includes both the values stored, and the relationship of the data to data that both links to it, and is linked to.&lt;/li&gt;&lt;li&gt;Create a data checker that will run a series of tests on your data.&amp;nbsp; This is basically like unit-tests for data, but you can run it not only after a series of tests, but in your production system too.&amp;nbsp; Run this program regularly, and pay attention to the output.&amp;nbsp; You want to be alerted of any changes in the sanity of your data.&amp;nbsp; Like unit tests, the more invariants you encode into this tool, the better you will be.&amp;nbsp; When changing or adding data,&amp;nbsp; modify the data checker code.&amp;nbsp; After each QA cycle, run the data checker.&amp;nbsp; Any errors should be entered as bugs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If your data can be repaired, have an automated data repairer.&amp;nbsp; This shouldn't be run regularly, because you don't want to get too complacent about your corruptions.&amp;nbsp; Instead, if you notice that the data checker has picked up some new errors, then you run this, modifying it first if the errors are of a new type.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Doing a good job on all these tips should prevent most data corruption, but not all.&amp;nbsp; Like bugs, even the best preventative measures will not guarantee success.&lt;br /&gt;&lt;br /&gt;Having clean data is extremely important.&amp;nbsp; This data is not yours, it is your customer's, and they trust you with it.&amp;nbsp; You need to protect it, and it isn't easy, but preventing data corruptions is always the right thing to do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-2251954858898745939?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/2251954858898745939/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=2251954858898745939' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2251954858898745939'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/2251954858898745939'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2008/08/code-is-easy-part-preventing-data.html' title='Code is the easy part: Preventing data corruptions'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-3270399274750474515</id><published>2008-08-06T14:35:00.000-07:00</published><updated>2008-08-07T07:36:42.130-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='org-mode'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='gtd'/><title type='text'>In org-mode, abandoning GTD</title><content type='html'>I've already mentioned &lt;a href="http://technical-dresese.blogspot.com/2007/08/problem-with-gtd.html"&gt;the problem with contexts&lt;/a&gt; in the GTD system.  In using &lt;a href="http://www.orgmode.org/"&gt;org-mode&lt;/a&gt;, I've come to realize that another important concept of GTD is either flawed or redundant: the next action.&lt;br /&gt;&lt;br /&gt;Next actions seem good at first.  Every project has a next action, the action that is a short-doable task that will advance the state of the project.  Of course, some projects have several actions you can do in parallel, so there are several next actions.  As the number of projects you have grow, you get more and more next actions.  At some point, the number of next actions becomes too much to keep track of.  Some people might say this goes away with proper contexts.  However, I've never found a good use for contexts, because in truth at any point I can do any of my next actions.  Another strategy for getting rid of excessive projects is to move some to a someday/maybe folder.  I think this is reasonable, but sometimes you know that in a particular week you are just going to work on a few different projects, perhaps because of deadlines or other prioritization.    What then?&lt;br /&gt;&lt;br /&gt;In org-mode, I solved this problem by using the agenda, and scheduling my next actions that I wanted to work on for the current day.  I would then see a list of the next actions I had to accomplish that day.  If I didn't get them done that day, the next day I'd move them up a day, to the current day.  It ended up being a daily-planner-like system a lot like Tom Limoncelli recommends in &lt;a href="http://www.amazon.com/Management-System-Administrators-Thomas-Limoncelli/dp/0596007833/ref=pd_bbs_sr_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1218058811&amp;amp;sr=8-2"&gt;Time Management for System Administrators&lt;/a&gt;.   But with next actions.&lt;br /&gt;&lt;br /&gt;Last week I had a revelation: scheduled items, for me, were the same as next actions!  So I removed all next actions, just having states &lt;span style="font-style: italic;"&gt;TODO, WAITING, &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;DONE.  &lt;/span&gt;&lt;span&gt;Like next actions, when I finish a scheduled item, the next item in the project becomes scheduled.  &lt;/span&gt;&lt;span&gt;I like my new system.  It combines the flexibility of Limoncelli's day-planner system with the project-planning of GTD.&lt;br /&gt;&lt;br /&gt;I spend my day as before, taking tasks from the day view of org-mode, and using a weekly review to schedule or de-schedule items from that view.   I also add notes to tasks all the time, which proves to be helpful.  I think I've benefitted from next-actions, since they force you to think of actions at level of granularity such that each task is specific, concrete, and immediately actionable.  I treat tasks the exact same way now, even without next actions themselves.&lt;br /&gt;&lt;br /&gt;For more info about org-mode, check out the &lt;a href="http://orgmode.org/GoogleTech.html"&gt;talk on org-mode&lt;/a&gt; which happened after I invited Carsten Dominik to give a talk at Google about his system.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-3270399274750474515?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/3270399274750474515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=3270399274750474515' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3270399274750474515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/3270399274750474515'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2008/08/in-org-mode-abandoning-gtd.html' title='In org-mode, abandoning GTD'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-8068913673553261705</id><published>2007-08-31T18:24:00.000-07:00</published><updated>2007-09-03T19:11:33.242-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='org-mode'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='gtd'/><title type='text'>org-mode</title><content type='html'>In my previous post on the &lt;a id="__CONK_66" href="http://technical-dresese.blogspot.com/2007/08/problem-with-gtd.html"&gt;problems with GTD&lt;/a&gt;, I mentioned a bit about using emacs' &lt;a id="__CONK_67" href="http://staff.science.uva.nl/%7Edominik/Tools/org/"&gt;org-mode&lt;/a&gt; to implement a GTD-like system.   I've been using it for a while now, with good success.&lt;br /&gt;&lt;br /&gt;I've previously used &lt;a id="__CONK_68" href="http://kinkless.com/kgtd"&gt;kGTD&lt;/a&gt;, as well as &lt;a id="__CONK_69" href="http://bargiel.home.pl/iGTD/"&gt;iGTD&lt;/a&gt;, but I like org-mode the best.  With any other application, you are quite limited in what you can do.  You can basically do what they want you to, maybe modulo a few scripts or preferences.  With org-mode, the basic functionality is extremely flexible, and since it's all just a bunch of lisp code, you can rewrite and alter it to your heart's content.&lt;p&gt;&lt;/p&gt;&lt;p&gt;org-mode, at it's simplest, presents an outline.  You can expand and collapse it.  Like other programs, you can put all sorts of stuff in the outline, in a very natural matter.  For example:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;* Fix bug 1919&lt;br /&gt;** Reproduce the bug&lt;br /&gt;This only breaks for very old users&lt;br /&gt;** Write test case for bug&lt;/blockquote&gt;The stars here represent the indentation level.  It's all just text, folks.  This is emacs, what else would you expect?  But notice that I can just add random text anywhere.  It will be collapsed along with the "Reproduce the bug" header.  This is very convenient place to put notes when you are working.   As other programs do, you can have links.  When I write "Fix bug 1919", the "1919" can link to my work's bug tracking system.   More impressively, this being emacs, I can link to a specific location in a buffer.  Opening it takes me right there, and off I go to do whatever work I need to.&lt;br /&gt;&lt;br /&gt;I also use TODO tags, which are states associated with each work item.  So, if this is an item that can become, in the GTD sense, a "next action", then it has a tag.  There are four tags I use:&lt;ol&gt;&lt;li&gt;&lt;em&gt;TODO&lt;/em&gt;: An item which is still to be done, but is not yet actionable.&lt;/li&gt;&lt;li&gt;&lt;em&gt;NEXT&lt;/em&gt;: A "next action", which should be done.&lt;/li&gt;&lt;li&gt;&lt;em&gt;WAITING&lt;/em&gt;: An action that is waiting on some outside signal to either go back to NEXT or DONE.&lt;/li&gt;&lt;li&gt;&lt;em&gt;DONE&lt;/em&gt;: Finished.  Hooray!&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;So, the above outline is more like:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;* Fix bug 1919&lt;br /&gt;** NEXT Reproduce the bug&lt;br /&gt;This only breaks for very old users&lt;br /&gt;** TODO Write test case for bug&lt;/blockquote&gt;&lt;p&gt;Here is some customization code to enable this, as well as to enable useful agenda commands:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;(setq org-todo-keywords '("TODO" "NEXT" "WAITING" "DONE"))               &lt;br /&gt;(setq org-agenda-custom-commands                                         &lt;br /&gt;  '(("w" todo "WAITING" nil)                                         &lt;br /&gt;     ("n" todo "NEXT" nil)))&lt;/blockquote&gt;&lt;p&gt;I like to, with one keystroke, mark an entry done and change the next one to NEXT.  I wrote the following lisp code to do it:&lt;/p&gt;&lt;blockquote&gt;(defun ash-org-todo-item-p ()                                            &lt;br /&gt;  (save-excursion                                                        &lt;br /&gt;    (beginning-of-line)                                                  &lt;br /&gt;      (looking-at "\\*+[ \t]+TODO\\&gt;")))                                   &lt;br /&gt;                                                                  &lt;br /&gt;(defun ash-org-mark-done ()                                              &lt;br /&gt;  (interactive)                                                           &lt;br /&gt;  (save-excursion                                                        &lt;br /&gt;       ;; org-entry-is-done-p has a bug where if you are at the first       &lt;br /&gt;       ;; char of a line it doesn't always work.  Let's work around it       &lt;br /&gt;    ;; here.                                                             &lt;br /&gt;       (end-of-line)                                                        &lt;br /&gt;    (when (not (org-entry-is-done-p))                                    &lt;br /&gt;             (org-todo 'done)                                                   &lt;br /&gt;       (outline-forward-same-level 1)                                     &lt;br /&gt;          (when (ash-org-todo-item-p)                                        &lt;br /&gt;          (org-todo "NEXT")))))         &lt;br /&gt;&lt;br /&gt;(define-key global-map "\C-c\C-x\C-c" 'ash-org-mark-done)                &lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The preceding code gives me a pretty nice, basic GTD system.  On top of this I've been adding my own tweaks.  One thing I like to do is to keep track of what I'm working on at the current time.  This helps me keep focused.   Org-mode has a way for keeping track of what you are doing at any one time, which is a clock which you can start or stop on any particular entry.  Using this as a basis,  I wrote the following nifty function for binding the F9 key to go back to the last current item.  I know an item is current if I use the clock-in feature.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;(defvar ash-org-current-task-loc nil                                     &lt;br /&gt;   "A cons of the buffer &amp; location of the current task")                 &lt;br /&gt;                                                                  &lt;br /&gt;(defadvice org-clock-in (after ash-org-mark-task activate)               &lt;br /&gt;   "When the user clocks in, bind F9 to go back to the worked on task."   &lt;br /&gt;                                                                  &lt;br /&gt;(setq ash-org-current-task-loc (cons (current-buffer)                  &lt;br /&gt;                                   (point)))                         &lt;br /&gt;(define-key global-map [f9] (lambda ()                                 &lt;br /&gt;                              (interactive)                           &lt;br /&gt;   (switch-to-buffer                       &lt;br /&gt;                                (car ash-org-current-task-loc))         &lt;br /&gt;       (goto-char                              &lt;br /&gt;                                      (cdr ash-org-current-task-loc)))))&lt;/blockquote&gt;&lt;br /&gt;This helps me mark a task as complete, I just hit F9, then C-c C-x C-c, which closes it out (stopping the clock and printing elapsed time), and marks the next item done.  Pretty nifty!&lt;br /&gt;&lt;br /&gt;This isn't enough, yet.  I'm still tweaking the system, trying to perfect it to suit the particular problems I have.  I may post more on this in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-8068913673553261705?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/8068913673553261705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=8068913673553261705' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/8068913673553261705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/8068913673553261705'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2007/08/org-mode.html' title='org-mode'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-5417754219637161879</id><published>2007-08-04T09:59:00.000-07:00</published><updated>2007-08-20T17:08:50.893-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='org-mode'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='gtd'/><title type='text'>The problem with GTD</title><content type='html'>&lt;p&gt;David Allen's productivity system, GTD (standing for Getting Things Done), continues to be more and more popular.  If you are all at interested in being more productive, than likely you've heard of this already.   I follow it myself, using emacs and &lt;a href="http://staff.science.uva.nl/~dominik/Tools/org/"&gt;org-mode&lt;/a&gt;.  Well, actually, when I say I follow it, I currently only follow part of it, because part of it is just not useful.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;There are a few key concepts in GTD, but the most often applied are &lt;span class="Apple-style-span" style="font-style: italic;"&gt;next actions&lt;/span&gt;, &lt;span class="Apple-style-span" style="font-style: italic;"&gt;contexts&lt;/span&gt;, and &lt;span class="Apple-style-span" style="font-style: italic;"&gt;weekly reviews&lt;/span&gt;.   I think that next actions are an important concept.  The general idea is that in your todo list you break down tasks to a level that each are simple and directly actionable with no planning or meta-level thinking required.  One of these is your next action, which is the very next thing you have to do to move your project forward.   This is a cool thing, because it forces your tasks to be of the correct granularity.  Also, most GTD software will show you all your next actions, so that you can see what you have to work on.  Once you complete one next action, the next todo item will become a next action.  For example, if your project is to fix a bug, then the next action here is to attempt to reproduce the problem locally.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Actually, this concept is slightly simplistic.  Sometimes your project can have several next actions.  If your project is to launch a new feature, then you might have several next actions, one to write the introduction and high level overview of a design document, the other is to send out a mail to your manager asking who could possibly be allocated to work on this feature.  A good GTD system should let you mark items as next actions arbitrarily.  org-mode does this, which is one of the reasons I like it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Another key concept of GTD is the weekly review, which means that you update your tasks and take time to plan new ones.  Good advice.  I have nothing to add to it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Finally, GTD has the notion of contexts, which are the bread-and-butter of most GTD apps.   Contexts represent some state in which your actions are performed.  One obvious place for contexts is for direct communication with someone.  You might have several projects that have an action that requires you to talk to your project manager.  You can associate those tasks with a context, and now you have a context that you look at to before you go speak to the project manager, to see all the appropriate tasks.  Then when you go talk with them, you have a list of things to ask them.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Sounds vaguely useful.  And that's the problem.  For software engineers and other types of knowledge workers, we just don't have a lot of context.   We are pretty well connected.  Usually things that can be done at work in front of our workstation can also be done at home, through VPN.   I find that most of my actions are to be done in front of my workstation, so the vast majority of my tasks have the context of the workstation.  What I find useful is to not use contexts for these tasks, since they all have a default obvious context.  I use it only for person-related contexts (such as the context for my project manager in my example).  And even then it's only somewhat useful.  It's possible that I could start doing work on my subway ride, in which case that is a useful context.  The problem would be that things done on the subway is a subset of things I can do at work.  Here again the concept of rigid contexts doesn't work.   So when I'm at my workstation, every task if fair game.  If I'm somewhere specialized, a specific context may come in handy.   But, ultimately, for most modern "knowledge-workers", contexts are not something we should be spending a lot of time thinking about.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;With contexts, org-mode again comes in handy.  It's not a real GTD app, so it doesn't insist on contexts.  It just lets you tag items, and those tags are your contexts.  So you can put things in multiple contexts, or none.  The tags inherit.  I think it's really perfect flexible solution for the modern GTD user.  Next post I'll detail exactly how I use it and give some customizations.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-5417754219637161879?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/5417754219637161879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=5417754219637161879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5417754219637161879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5417754219637161879'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2007/08/problem-with-gtd.html' title='The problem with GTD'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-7446021378117805931</id><published>2007-07-04T10:30:00.000-07:00</published><updated>2007-08-05T14:14:28.736-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='language'/><title type='text'>Generics</title><content type='html'>In my &lt;a href="http://technical-dresese.blogspot.com/2007/02/annotations.html"&gt;last post&lt;/a&gt;, I discussed annotations, and their contributions to the Java language.  The short version: they are pretty simple, and surprisingly useful.  Generics, also introduced with Java 1.5, is a much larger pill to swallow.  Not on the useful part, they are undeniably helpful.  They do something very important, which is to make run-time errors visible at compile time, while at the same time increasing the self-documentation of code.   This is a great thing.  However, there is no doubt that they add complexity.  To even document all cases of complexity would take a whole blog dedicated to just that subject.  I'll give one example:&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;blockquote&gt;&lt;code&gt;foo(List&amp;lt;B&amp;gt; list);&lt;br /&gt;bar(List&amp;lt;? extends B&amp;gt; list);&lt;br /&gt;tor(List&amp;lt;? super B&amp;gt; list);&lt;br /&gt;&lt;/code&gt;&lt;/blockquote&gt;So, what's the difference between these?  Well, suppose &lt;code&gt;B&lt;/code&gt; has a subtype &lt;code&gt;C&lt;/code&gt;, and a supertype &lt;code&gt;A&lt;/code&gt;.  So the inheritance hierarchy goes &lt;code&gt;A -&gt; B -&gt; C&lt;/code&gt;.  You can call &lt;code&gt;foo&lt;/code&gt; with a &lt;code&gt;List&amp;lt;B&amp;gt;&lt;/code&gt;, but not a &lt;code&gt;List&amp;lt;C&amp;gt;&lt;/code&gt;. But you can call &lt;code&gt;bar&lt;/code&gt; with a &lt;code&gt;List&amp;lt;C&gt;&lt;/code&gt;; as well as &lt;code&gt;List&amp;lt;B&amp;gt;&lt;/code&gt;. You can call &lt;code&gt;tor&lt;/code&gt; with a &lt;code&gt;List&amp;lt;A&amp;gt;&lt;/code&gt; and &lt;code&gt;List&amp;lt;B&amp;gt;&lt;/code&gt;.  Keep in mind that the contents of the list are not what I am talking about, just the compile-time type of the list.&lt;br /&gt;&lt;br /&gt;Generics are a bit more complicated than most people assume.  Almost anyone who has spent time with Generics has gotten into several puzzling situations that they can't explain, and where the solution isn't obvious.&lt;br /&gt;&lt;br /&gt;The question I wonder about is whether it has done more harm than good.  This is not a matter of opinion, I think.  If we could count up all the hours of lost productivity in wrestling with generics, and count the hours saved by catching bugs and improving the clarity of the code,  would the time saved exceed the time lost?  My anecdotal evidence is that it is a net benefit.  It has rescued the Java world from the perils of type-casting, and I do remember getting many &lt;code&gt;ClassCastExceptions&lt;/code&gt; in the past.  Nowadays they are rare, and I don't spend excessive time on the complexities.&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/3240281421131142620-7446021378117805931?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/7446021378117805931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=7446021378117805931' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/7446021378117805931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/7446021378117805931'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2007/07/generics.html' title='Generics'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-1889353164285819233</id><published>2007-02-13T20:05:00.000-08:00</published><updated>2007-07-04T14:10:27.600-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='language'/><title type='text'>Annotations</title><content type='html'>This post is a few years too late.  Annotations came out in Java 1.5, and we already are on Java 1.6.  But I'd like to make a few comments on them, because I think they are a great example of a low-cost but a high-use feature.&lt;br /&gt;&lt;br /&gt;Making improvements to a popular language is always difficult.  You want each addition in functionality to be well worth it.  Each addition should make things possible that were not possible before, and do so in a way that both fits with the spirit of the language, and results in the least possible disruption.&lt;br /&gt;&lt;br /&gt;Java annotations are a good example of a good change.  I find I use them more and more, and they enable things I now realize I in fact need.  Did I need them before annotations were around?  It didn't seem so, but now they are here I would find it difficult to live without them.&lt;br /&gt;&lt;br /&gt;I should illustrate how useful they are with a made-up example.  Let's say you want a simple webserver, one that took the path and used it to call into a dispatcher object.  So you would call &lt;span style="font-style:italic;"&gt;http://localhost/doSomething?foo=aaa&amp;bar=bbb&lt;/span&gt;.  This would use Java reflection to call  a method &lt;span style="font-style: italic;"&gt;Dispatcher.doSomething(String foo, String bar)&lt;/span&gt; .  But at reflection time you don't know the names of arguments, since those are all compiled away.  So, the first challenge is to figure out which argument is &lt;span style="font-style: italic;"&gt;foo&lt;/span&gt; and which is &lt;span style="font-style: italic;"&gt;bar&lt;/span&gt;.  How can we do this?  Before annotations, I would say you cannot do this.  You could do something such as populate a String to String map, and pass that in instead of arguments, but this is awkward for the non-reflection callers, and also doesn't enforce important invariants at compile-time.   Luckily for us, we do have annotations, and the annotations stick around at runtime (if you want them to).   So, we can make an annotation defined as:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;import java.lang.annotation.*;&lt;br /&gt;&lt;br /&gt;@Retention(RetentionPolicy.RUNTIME)&lt;br /&gt;@Target(ElementType.PARAMETER)&lt;br /&gt;public @interface ParameterName {&lt;br /&gt; String value();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;And we can use it like so:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;void doSomething(@ParameterName("foo") String foo,&lt;br /&gt;                @ParameterName("bar") String bar) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now reflection can match HTTP parameters up to the method arguments.&lt;br /&gt;&lt;br /&gt;But the fun doesn't stop there.  What if you wanted your delegator class to only have some methods accessible from the web?  You could try to separate into another class that is only web methods, but that overly constraining on the design.  Or, you could maintain a separate list of web-safe methods in a configuration file.  That solution seems prone to mistakes - developers will forget to update the configuration file, then wonder why their new method isn't accessible.  However, with annotations, you can simply tag methods with an annotation showing that they are web-safe.  We can create a runtime method-level annotation called &lt;code&gt;WebExecutable&lt;/code&gt; and use it like so:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;@WebExecutable&lt;br /&gt;void doSomething(@ParameterName("foo") String foo,&lt;br /&gt;                @ParameterName("bar") String bar) {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now, your dispatcher can check for the annotation before it executes.  Instant safety!  You can imagine further annotations that may classify whether methods needs authentication or not, or other such improvements.&lt;br /&gt;&lt;br /&gt;I've really been digging annotations.  They make things possible that never were possible before, and don't introduce much complexity or confusion.  There is some new syntax to learn, and some non-obvious things (such as "@interface"), but all in all, the part you have to look at the most is very easy and intuitive.  I think it's an ideal addition to the language.&lt;br /&gt;&lt;br /&gt;Next, I intend to look at generics, which has quite a different profile.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-1889353164285819233?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/1889353164285819233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=1889353164285819233' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1889353164285819233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/1889353164285819233'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2007/02/annotations.html' title='Annotations'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-5059734304335058313</id><published>2006-10-26T19:34:00.000-07:00</published><updated>2007-02-12T18:49:21.707-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='language'/><title type='text'>Language growth</title><content type='html'>To alter a quote from Annie Hall, programming languages are like sharks.  They have to keep moving or they will die.  Languages frequently don't succeed at this.  Thus a fine language like Common Lisp failed to include threads and networking in its spec, and by the time standards emerge, it is too late; the needs of users have long since passed by.&lt;br /&gt;&lt;br /&gt;Java has done a good job of this.  They have managed to keep incorporating the needs of users, while trying to stay true to the spirit of the language, and they have not proceeded so fast that they introduce unncessary complications. Some of their additions to the language spec have made things more complicated and confusing, but you always get something out of it.&lt;br /&gt;&lt;br /&gt;I'm interested in exploring this topic further in the next few posts.  I'd like to explore a few examples of Java language additions, and then examine some potential upcoming changes.   What are your opinions about changes in the Java language in recent years?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-5059734304335058313?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/5059734304335058313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=5059734304335058313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5059734304335058313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/5059734304335058313'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2006/10/language-growth.html' title='Language growth'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3240281421131142620.post-6413478617478362810</id><published>2006-10-19T16:33:00.000-07:00</published><updated>2006-10-21T05:44:25.996-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Introduction</title><content type='html'>Not only is this yet another blog, this is yet another in a series of blogs by me. I'm a believer in blogs that suit a specific topic, and therefore this is my blog for technical topics.  For a developer, having a technical blog is a way to both refine one's thoughts on particular topics, practice technical writing, and of course advertise &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;oneself&lt;/span&gt; as being a &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;knowledgeable&lt;/span&gt; dude.&lt;br /&gt;&lt;br /&gt;Every blog should know who its audience is.  This &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;blog's&lt;/span&gt; audience is other developers, mostly those who are searching for topics.    Although it would be nice to have people &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_3"&gt;subscribing&lt;/span&gt; to my atom feed,  I do not expect it.&lt;br /&gt;&lt;br /&gt;I program primarily in Java, with some Python, and some dabbling in lisp.  Expect posts relevant to those topics, as well as posts about development in general, productivity, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;IDEs&lt;/span&gt;, and similar issues.  Do not expect a flurry of posts.  I expect to be posting at least once every two weeks, but more if I happen to have a lot to say, or less if I am unusually busy.&lt;br /&gt;&lt;br /&gt;Oh, and I actually hope that this will be a good blog, and will actually contribute some knowledge or something of value to the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3240281421131142620-6413478617478362810?l=technical-dresese.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://technical-dresese.blogspot.com/feeds/6413478617478362810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3240281421131142620&amp;postID=6413478617478362810' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6413478617478362810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3240281421131142620/posts/default/6413478617478362810'/><link rel='alternate' type='text/html' href='http://technical-dresese.blogspot.com/2006/10/introduction.html' title='Introduction'/><author><name>Andrew Hyatt</name><uri>https://profiles.google.com/101505495157778834572</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-cked6JkcfmQ/AAAAAAAAAAI/AAAAAAAALlM/jdduo5hWovg/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
