<?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-14251888</id><updated>2012-01-23T19:35:15.855-08:00</updated><category term='JavaFX Tutorial Simple'/><title type='text'>Dave Ford's  Programming Blog</title><subtitle type='html'>Random thoughts about software development</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-14251888.post-4831903670374306483</id><published>2010-11-10T12:51:00.000-08:00</published><updated>2010-11-10T13:19:36.213-08:00</updated><title type='text'>GWT 2.1: data-binding and client-side JPA</title><content type='html'>GWT 2.1 was finally released. And as usual, it's brilliant. I am generally annoyed by technology fan-boys, but each time they do a release i am amazed by how smart these guys are. There is an amazing amount of new and useful stuff. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of things i particularly admire is that they tend to focus on the GWT &lt;i&gt;core, &lt;/i&gt; that is, the kind of things that would be difficult for 3rd parties or developers to do themselves. Everything that is added to GWT is extremely well thought out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two productivity enhancements that I miss from the days of server-side MVC (i.e. Struts, Grails, JSF, Wicket, etc.) are:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Data binding (i.e. bound controls)&lt;/li&gt;&lt;li&gt;JPA's EntityManager. A client-side entity manager would really be useful. Much of Hibernates beauty (like lazy loading) is lost in client-heavy GWT apps. You sometime end up having a PersonEntity (for JPA) and a PersonDto (for sending to GWT client) - yuck!&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;GWT 2.1 addresses both of these. Data Binding is addressed with the new &lt;a href="http://code.google.com/webtoolkit/doc/latest/ReleaseNotes.html#Editors"&gt;Editor Framework&lt;/a&gt;. And the client-side JPA-like thing is addressed with their new &lt;a href="http://code.google.com/webtoolkit/doc/latest/ReleaseNotes.html#RequestFactory"&gt;Request Factory&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-4831903670374306483?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/4831903670374306483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=4831903670374306483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4831903670374306483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4831903670374306483'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2010/11/gwt-21-looks-really-nice.html' title='GWT 2.1: data-binding and client-side JPA'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-7970624189363565125</id><published>2009-06-11T16:36:00.000-07:00</published><updated>2009-06-11T16:38:04.501-07:00</updated><title type='text'>Google Wave is written in GWT</title><content type='html'>In case you haven't checked out Google Wave yet, it's a cool communications application that demonstrates what is possible in browser based applications. It's by the same guys who wrote Google Maps. And it's written in GWT.&lt;br /&gt;&lt;br /&gt;Here is a link to Google Wave:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wave.google.com/"&gt;http://wave.google.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-7970624189363565125?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/7970624189363565125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=7970624189363565125' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7970624189363565125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7970624189363565125'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/06/google-wave-is-written-in-gwt.html' title='Google Wave is written in GWT'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-5524786384094396722</id><published>2009-05-25T08:51:00.000-07:00</published><updated>2009-05-25T08:57:49.894-07:00</updated><title type='text'>SBT: Simple Build Tool</title><content type='html'>I have been complaining about Ant and Maven for years. I don't use these tools because I like them. I use them because there haven't been many alternatives. But that is changing with a new tool called Simple Build Tool: SBT.&lt;br /&gt;&lt;br /&gt;SBT is written in Scala (my favorite language of the week). But it can build Scala apps or Java apps. I don't have time to go into all that I like about it. But here are a few highlights:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The language used for build scripts is the same as the language being built: Scala&lt;/li&gt;&lt;li&gt;It is completely and easily extensible - using Scala. The key here is the &lt;span style="font-style: italic;"&gt;easy&lt;/span&gt; part. &lt;/li&gt;&lt;li&gt;Great docs! The project is fairly new, but already the documentation is better than that from Ant or Maven&lt;/li&gt;&lt;li&gt;It is compatible with Maven repositories and POM files&lt;/li&gt;&lt;li&gt;It is compatible with Ivy&lt;/li&gt;&lt;li&gt;SBT eliminates most of the unnecessary boilerplate and &lt;span style="font-style: italic;"&gt;noise&lt;/span&gt; code required with Ant and Maven&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The project owner, Mark Harrah, is very talented and committed to this project &lt;/li&gt;&lt;li&gt;Support is excellent. Mark personally replies to all messages on Google Groups&lt;/li&gt;&lt;li&gt;Bugs and feature requests are addressed quickly&lt;/li&gt;&lt;li&gt;It's fast. Building my project in SBT is much faster then Maven - I'm not sure why, but it is.&lt;/li&gt;&lt;/ol&gt;For more info:&lt;br /&gt;&lt;br /&gt;Project Home: &lt;a href="http://code.google.com/p/simple-build-tool/"&gt;http://code.google.com/p/simple-build-tool/&lt;/a&gt;&lt;br /&gt;Google Groups: &lt;a href="http://groups.google.com/group/simple-build-tool"&gt;http://groups.google.com/group/simple-build-tool&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-5524786384094396722?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/5524786384094396722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=5524786384094396722' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5524786384094396722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5524786384094396722'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/05/sbt-simple-build-tool.html' title='SBT: Simple Build Tool'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-1779565171941114579</id><published>2009-04-30T11:33:00.000-07:00</published><updated>2009-04-30T12:23:02.273-07:00</updated><title type='text'>Leaky Web Abstractions</title><content type='html'>As a consultant and trainer, I have worked with web developers of every variety. Two things that I observe over and over again are:&lt;br /&gt;&lt;br /&gt;1.    Many web developers are so entrenched in the stacks upon stacks of frameworks needed (or not needed) to build web apps that (to their detriment) they loose track of the fundamental concepts that underlie all web apps.&lt;br /&gt;&lt;br /&gt;2.    The frameworks we use to build web apps are not good enough to allow us to learn &lt;span style="font-style: italic;"&gt;only&lt;/span&gt; the abstractions provided by the framework while remaining blissfully ignorant of the web underpinnings. I believe this is called a leaky abstraction. This is not the case in more mature technologies. For example, I have been coding in Java for 10 years and not once have I needed to drop down to the &lt;span style="font-style: italic;"&gt;byte-code&lt;/span&gt; level to solve a problem. I have been using Oracle for years and not once have I needed to know what goes on inside of Oracle once it receives my SQL. Nor have I ever needed to know the file format that Oracle uses behind the scenes.&lt;br /&gt;&lt;br /&gt;But the abstractions we use to build web apps are much more leaky than Java and SQL. It's a very small set of problems that can be solved without understanding the web. True, I have seen successful apps created using slick .NET tools by people who know nothing about HTTP or client/server architecture. But just as often I see million dollar disasters that could have been prevented had the architects understood the web at a more fundamental level.&lt;br /&gt;&lt;br /&gt;Summary:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;As of 2009, you still need to understand the foundational technologies (HTTP, client-server, HTML, CSS, JavaScript, etc) of the web if you want to effectively architect web applications.&lt;/li&gt;&lt;li&gt;Our Web frameworks must, by necessity, &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; obscure what is going on under the covers too greatly.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Our Web frameworks must allow us to, on occasion, drop-down to the lower levels simply and elegantly. And then go back up to the high-level abstraction without missing a beat.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;An example of number #3 is GWT. In GWT you can drop (from Java) down to the underlying JavaScript using GWT's JSNI (JavaScript Native Interface) mechanism. But unlike JNI (after which JSNI was probably named), JSNI is freakishly easy.  So easy, that I now effortlessly blend Java and JavaScript in a single app all the time.&lt;br /&gt;&lt;br /&gt;As a side note, this GWT feature has altered my perspective on the whole Static versus Dynamic language debate. If GWT can do it, I am convinced that the inventor of the NBL (Next Big Language) will able to seamlessly blend static and dynamic typing in single language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-1779565171941114579?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/1779565171941114579/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=1779565171941114579' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/1779565171941114579'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/1779565171941114579'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/04/leaky-web-abstractions.html' title='Leaky Web Abstractions'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-5908023776816330506</id><published>2009-04-15T09:07:00.000-07:00</published><updated>2009-04-27T08:27:10.973-07:00</updated><title type='text'>Member Literals</title><content type='html'>&lt;div&gt;I am aware of the pro and cons of static and dynamic languages. I lean toward static because of my error-prone typing, IntelliJ addiction, identifier indecisiveness and unit-test laziness. All things being equal, I would rather have the compiler find my errors than write more tests (which will probably have errors and then I'll need to write a test for the test).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is why I was excited about Scala. What I was hoping for from Scala's type system:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#1. Less intrusive than Java's type system (Scala succeeds here)&lt;/div&gt;&lt;div&gt;#2.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Find more of my errors than Java does &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For #2, Scala let me down in one area that is important to me (and i think many others). Can you find the typo in the code snippet below? If you can, then you are smarter than scala.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;class Person{&lt;/span&gt;&lt;/div&gt;&lt;div&gt; &lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var firstName:String;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var lastName:String;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;//etc.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;val rs = statement.executeQuery(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  "select firstName,lastName from Person")&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;p.firstName = rs.getString("firstName")&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;p.lastName = rs.getString("lastName")&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;p.doSomeStuff();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;val e = new XmlElement()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;e.addTextElement("firtName",p.firstName)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;e.addTextElement("lastName",p.lastName)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;p.addPropertyChangeListener("firstName"){&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;txtFirstName.setText(p.firstName)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;p.addPropertyChangeListener("lastName"){&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;txtLastName.setText(p.lastName)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I probably made 7 typos, but the one i was referring to was the "firtName" typo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Q: Have you ever been burned by this type of error?&lt;/div&gt;&lt;div&gt;Q: Have you ever had the feeling that the compiler should be able help?&lt;/div&gt;&lt;div&gt;Q: Is it *that* hard for a compiler vendor to give a "member literal" syntax? Perhaps something like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;e.addTextElement(Person#lastName,p.lastName)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I would actually pay money for a compiler that did that. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The only reasons i can think of that this feature does not seem to exist in Java and Scala:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;I am the only one who wants the feature&lt;/div&gt;&lt;div&gt;2.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Compiler writers include features that are very useful for compiler writers (Scala has a parser combinator). Kind of like the waiter who sets the thermostat for him, and doesn't notice that his customers are freezing.&lt;/div&gt;&lt;div&gt;3.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;It must be really hard to implement&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By the way, I am aware that Hibernate, JAXB, Rails/Grails can address some the these issues. Also, I am aware of constants (static final), but it seems a bit silly to have code like this:&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;class Person{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;String firstName;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;public static final String FIRST_NAME = "firstName";&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;String lastName;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;public static final String LAST_NAME = "lastName";&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-5908023776816330506?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/5908023776816330506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=5908023776816330506' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5908023776816330506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5908023776816330506'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/04/member-literals.html' title='Member Literals'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-7316448996216485138</id><published>2009-04-13T14:45:00.000-07:00</published><updated>2009-04-15T09:02:57.272-07:00</updated><title type='text'>The Right Tool for the Job at Hand</title><content type='html'>There is a recurring theme that i see in forums and mailing lists. Some guy posts a message like: "what's better, Flex or AJAX?" or "What's the best tool for making a pdf: iText, Jasper or FOP?" or "What language is more productive, Groovy or Scala?". A number of people chime in with their favorites. Then some bozo chimes in: "Dude, its really a dumb question, you are comparing apples to oranges. You just need to choose the *right tool for the job* at hand."&lt;br /&gt;&lt;br /&gt;Let me tell you why i think this is mostly crap. This "best tool for the job" logic works great for some things, like a *shovel*. I can reasonably afford a snow shovel for my driveway and a different shovel (a spade) for my yard. Shovels are cheap and the learning curve is low. But compare that with cars. I want horsepower. I want planet-friendly. I want safety. I need to tote the kids around. But I can't afford a Porshe, a Prius, a Volvo and a mini-van. I need one vehicle that (comes close) to meeting all my needs. And then i will live with the decision for the next 5 years.&lt;br /&gt;&lt;br /&gt;I view software tools (like frameworks, IDE's or languages) more like cars. Some of these tools take years to learn. The cost of learning a new language, migrating your old code, ditching your favorite IDE, etc. can be huge.&lt;br /&gt;&lt;br /&gt;I once knew a guy who used MS Excel as his spreadsheet, database, word processor, desktop publishing and html tool. I tried to convince him to stick with Excel for number crunching but use more specialized tools for those other functions. But he was happy with his universal tool.&lt;br /&gt;&lt;br /&gt;I kind of feel that way with programming languages. The other night, at our Java user group meeting we were trying to "position" Groovy versus Java or Groovy versus Scala. Some suggested that Groovy was good for web/database programming. While Scala was good for systems programming. Or some said Scala was suited towards mission critical tasks, where errors are too costly. But here is why I think this is mostly horse shit: &lt;b&gt;Java, Groovy and Scala are all &lt;i&gt;general purpose programing languages&lt;/i&gt;&lt;/b&gt;. &lt;b&gt;90% of their target use-cases is overlap&lt;/b&gt;. There might be a few things one is more suited to than the other. But all are powerful, advanced, general purpose programming languages - with steep learning curves.&lt;br /&gt;&lt;br /&gt;I don't really want to know which of these tools is right for which job. I want to know which is best for most jobs. Having a different tool for every project (or sub-project) is really not appropriate when the tool takes 5 years to learn. Here are 2 extreme examples:&lt;br /&gt;&lt;br /&gt;1.     XSLT. XSLT is a special purpose language for transforming one XML document into another, usually a raw-data xml into a presentation (i.e. HTML) xml. The problem is this. The book I learned XSLT from is &lt;b&gt;&lt;i&gt;1000&lt;/i&gt;&lt;/b&gt; &lt;b&gt;&lt;i&gt;pages&lt;/i&gt;&lt;/b&gt; long. XSLT is HUGE! It's an interesting and powerful language. And I learned a lot about functional programming and pattern-matching thru XSLT, so I have no regrets. But 90% of XSLT has nothing specifically to do with transforming XML. 90% of XSLT's constructs would be (and are) useful in any application, xml-transforming or not. And transforming XML is a pretty small part of what I need to do on any given day. Anything you can do with XSLT, you can do (not quite as elegantly) using a general purpose language plus a library. For most application developers who need to transform XML, I think a general purpose language plus a library is the smartest approach.&lt;br /&gt;&lt;br /&gt;2.    Another example is JavaFX. JavaFX is a really cool new language for the JVM. It is marketed as a special-purpose programming language (aka external DSL) for rich clients (anything you would have used Swing for in the past, you could now use JavaFX). But here is the rub. JavaFX is *very* feature-rich. In many ways JavaFX is a *superset* of Java. So if it takes you two years to master Java, it might take 4 years to master JavaFX. And like XSLT, 90% of the new programming constructs you will learn in JavaFX are *not specific to creating Swing apps*. Most of the cool, new features introduced in JavaFX would be useful for *any* application.&lt;br /&gt;&lt;br /&gt;I don't think the world needs any more languages or tools with the surface area of a general purpose language but only 5% of the applicability. At least not today - with so many general purpose languages offering rich internal DSL capabilities. If you are a person who is really pigeon-holed, and all you do is xml transforms all-day-every-day and you don't already know a general purpose language like Java, then perhaps things like XSLT (or JavaFX) have a place. Or if you can somehow organize your team into super specialized niches, then maybe this will work.&lt;br /&gt;&lt;br /&gt;But I am a general purpose programmer. I might code a mobile app one week, a Web/Database app the next week and a parser the next. JavaScript, ActionScript, Java, Ruby, Python, Groovy, Scala and C# are all *general purpose* languages. 90% of the constructs provided by these languages apply to systems programming, transforms, web apps and database apps. I have never had a client that choses a new programming language for every job. It just isn't feasible. Even Google has standardized on only 4.  And I don't really care that Groovy is a few hairs better for scripting. And Scala is a few hairs better for system programming (although, if Scala was 10 times faster for system's programming I might want to know that).&lt;br /&gt;&lt;br /&gt;I have been searching for a Java replacement (as my default, general purpose language) for some time, watching new languages like Ruby, JavaFX, Boo, C# 4, Groovy, etc.&lt;span style="font-weight: bold;"&gt; I am trying to learn which language is most productive for the 90% crap that *all* programming languages do - and doesn't screw me over completely if I need something from the other 10%.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I think with the "internal DSL" functionality of most newer general purpose languages, it is perfectly reasonable to ask the question, "which is the best general purpose programming language?".&lt;br /&gt;&lt;br /&gt;So if I start posting questions comparing various languages or frameworks please don't respond with the "right tool for the right job" lecture. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I *do* want to know the strengths and weaknesses of the various languages and platforms. But I have no intention of using a different general purpose programming language for every project or sub project I do. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also, please don't get offended if I ask questions that may put your favorite tool in a bad light. It is nothing personal against you. I am just trying to learn.&lt;br /&gt;&lt;br /&gt;Side note: One huge limiting factor in all of this is &lt;i&gt;runtime environment&lt;/i&gt;. At present, there is no powerful, general purpose language that runs on &lt;i&gt;every&lt;/i&gt; runtime platform. In fact, I was just about to jump head first into Python, in spite of the fact that it is 90% redundant (I am guessing) with languages I already know. Why? Because it runs on the Google App Engine. Luckily I procrastinated long enough, and the Google App Engine now runs Java.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-7316448996216485138?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/7316448996216485138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=7316448996216485138' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7316448996216485138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7316448996216485138'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/04/right-tool-for-job-at-hand.html' title='The Right Tool for the Job at Hand'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-8282648964084407061</id><published>2009-04-11T18:00:00.000-07:00</published><updated>2009-04-11T18:07:24.649-07:00</updated><title type='text'>Fail Fast Fail Nice</title><content type='html'>You may be familiar with the term "fail fast" as it applies to software development. It basically states that errors should be reported sooner rather than later. So, for example, suppose an error occurs on line 30 (x has a null value when it shouldn't) but the error doesn't rear its head until line 246. This kind of thing can take hours to debug. A solution would be to place an assertion on line 31 like this:&lt;br /&gt;&lt;br /&gt;if(x == null) throw new IllegalStateException("x should not be null");&lt;br /&gt;&lt;br /&gt;A few corollaries to the fail-fast rule might be that compile errors are preferable to runtime errors. And errors caught in unit tests are better than errors caught in customer tests.&lt;br /&gt;&lt;br /&gt;I would like to take the fail fast principal and expand it to "fail fast, fail nice" (FFFN). By &lt;span style="font-style: italic;"&gt;nice&lt;/span&gt;, I mean this: the system has to give me a nice error message with enough information to quickly pinpoint and correct the problem. To me, FFFN is important. And not just in the code &lt;span style="font-style: italic;"&gt;we&lt;/span&gt; write. But in the code we *use*: languages, libraries, frameworks, compilers, runtimes, IDE's, etc.&lt;br /&gt;&lt;br /&gt;Let me give a few examples. A year or so ago, I decided to learn JavaFX. Being new, I made lots of mistakes. Every time I screwed up, JavaFX gave me the exact line number and column number of the error. And it gave a nice message telling me what i did wrong. In other words, right out of the gate, JavaFX seemed to succeed at FFFN. It was surprising to me because at this time JavaFX was brand new, not released yet, and mostly the brainchild of a single guy named Chris.&lt;br /&gt;&lt;br /&gt;Consider JSF as another example. I had been using and teaching JSF for 3 years. In class, a student makes a mistake on his lab exercise. His app does not work. He just gets a blank screen. No stack trace. No error message. We turn up logging to its most verbose setting. Still nothing. In other words,  the JSF implementation did not give us a *bad* error message. It gave us *no* error message. No clue. This kind of thing can takes hours to fix.&lt;br /&gt;&lt;br /&gt;An other example would be GWT. If you make a mistake, GWT almost always tells you the exact line number with a friendly description. Compare this to JavaScript programming (without GWT). You often get the wrong line number. And a completely unhelpful error message (although Firebug can help a little).&lt;br /&gt;&lt;br /&gt;Another example is Groovy. Every 6 months or so I get excited about Groovy. The clean, elegant syntax. Less need to repeat stuff (the DRY principal), closures, etc. I love Groovy. But then I loose my enthusiasm after a few mistakes take me into java stack trace hell. As of my last go around, Groovy scores high in most areas that are important to me. But it stills scores low in FFFN.&lt;br /&gt;&lt;br /&gt;When developing with a low-FFFN tool (like JavaScript) you must drastically decrease your mean-time-between-testing.&lt;br /&gt;&lt;br /&gt;What are your experiences? What technologies (languages, libraries, frameworks, compilers, runtimes, IDE's, etc) have you used that are particularly high-FFFN? Which tools have you used that are particularly low-FFFN? Is FFFN an important factor for you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-8282648964084407061?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/8282648964084407061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=8282648964084407061' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8282648964084407061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8282648964084407061'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/04/fail-fast-fail-nice.html' title='Fail Fast Fail Nice'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-6195899376742847137</id><published>2009-04-03T08:38:00.000-07:00</published><updated>2009-05-01T08:30:33.429-07:00</updated><title type='text'>Is Spring Useful?</title><content type='html'>I friend recently asked my take on Spring.  I thought others might benefit from my response.&lt;br /&gt;&lt;br /&gt;&gt; What's your take on the pros and cons of Spring?&lt;br /&gt;You know me, i always seem to have non-standard opinions on things. I can't help it :) I have been using Spring and IOC for a long time. I actually wrote my own (crappy) dependency injection framework before i knew about spring. I have also used used Pico. And lately Guice.&lt;br /&gt;&lt;br /&gt;Regarding spring, I use it a lot (it's in the classpath of most projects i do). This is because there are a number of little gems in there. The jdbc stuff, the reflection/bean-util stuff, etc. But, on the whole, i think the *core* of what Spring does is useless (for me). Here is what i have learned that led me to this conclusion:&lt;br /&gt;&lt;br /&gt;1.  I realized that the IOC pattern is a great pattern, but its a *pattern*, more than a framework. You don't need a framework to do ioc. If you really think of it, the core premise of ioc (or dependeny injection as its also called) is this: Don't lookup dependencies from some kind of global scope. Instead, pass them in as parameters. By "global scope" what i really mean is: (registry | jndi | serviceHashMap | global-variable/singleton). If you really think of it, the ioc pattern is just a re-phrasing of what we have always been taught: prefer explicit argument passing over globals.&lt;br /&gt;&lt;br /&gt;Also, in good oo design, one should think about things like "object life cycle" and things like: some objects are *users* of a service (aka object) while other objects (or object) is in charge of *creating* the service (or object). By the way, the *creator* is also the *injector*. This stuff needs to be planned out thoughtfully as part of a good oo design.&lt;br /&gt;&lt;br /&gt;So my point here is that 80% of the ioc value comes from the ioc *pattern* (which is really just good oo practices) and *not* the ioc framework.&lt;br /&gt;&lt;br /&gt;2. We learned that "autowire" has issues. The one area where an ioc framework can actually clean up your code is the "autowire" feature. But, the autowire feature, as it turns out, kills the dave &lt;a href="http://dave-ford.blogspot.com/2009/04/fail-fast-fail-nice.html"&gt;fail-fast/fail-nice&lt;/a&gt; principle. In fact, the spring docs caution against the autowire feature.&lt;br /&gt;&lt;br /&gt;3. You already know i am against random creation of crappy, unneeded "external" DSL's (http://www.martinfowler.com/bliki/DomainSpecificLanguage.html) (i.e. spring's xml file). There are a million reasons for this. The one good thing about java (the strong type checking) you loose. They now have an equivalent "internal" DSL (java based). But still, there has to be some real benefits (not imagined benefits) before one adds a disruptive framework to their project.&lt;br /&gt;&lt;br /&gt;I kind of view the Spring/Java combo as the absolute worst of all worlds. You *don't* get all of the great benefits of a dynamic language like Ruby. And you *don't* get the benefits of type safety.&lt;br /&gt;&lt;br /&gt;4. For most things that people use Spring for, I can show them cleaner better ways. Things like transactions, hibernate, dev/staging/production config, swappable impls, factories, etc.&lt;br /&gt;&lt;br /&gt;So to summarize, Spring has a place in my toolset, but these days, it is more in the role of an apache commons type of thing. The core idea of what spring is, is mostly useless to me. There are very few use-cases that (for me) warrant the use of Spring (in its central role of ioc/aop container). One use-case would be if i needed a transaction layer that worked seamlessly with JTA (i.e. 2 phase commit) and non-jta environments. But i can't imaging needing that. You either need 2-phase commit or you don't.&lt;br /&gt;&lt;br /&gt;If I ever decide to take up ioc frameworks again, it will probably be juice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-6195899376742847137?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/6195899376742847137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=6195899376742847137' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/6195899376742847137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/6195899376742847137'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/04/is-spring-useful.html' title='Is Spring Useful?'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-7948358962296768082</id><published>2009-01-20T06:11:00.001-08:00</published><updated>2009-02-22T15:01:09.539-08:00</updated><title type='text'>Form over Function on the Web</title><content type='html'>In a perfect world, all web sites (and web apps) would look great and be easy to use. But web developers tend to &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; have unlimited resources. Thus we must prioritize. If you take 3 metrics:&lt;br /&gt;&lt;br /&gt;1.    Functionality/Content: What does the site or app do (or allow the user to do)&lt;br /&gt;2.     Usability: how easy and intuitive is it to use (for the target audience) without reading a bunch of docs&lt;br /&gt;3.     Visually appealing: how good does it look&lt;br /&gt;&lt;br /&gt;Here are my observations on this subject:&lt;br /&gt;&lt;br /&gt;1. There are many web sites and web apps that are ugly but freakishly popular because they offer functionality or content that people really want (craigs list, e-bay). I don't know of any freakishly popular web sites where the reverse is true.&lt;br /&gt;&lt;br /&gt;2. As a user, I have often put up with ugly, counter-intuitive web sites because I really wanted the functionality or content.&lt;br /&gt;&lt;br /&gt;3. All three of these metrics are fairly subjective&lt;br /&gt;&lt;br /&gt;4. Many organizations that create web sites or web apps tend to lump metric #2 and #3 together. But they are really different skills. I don't think it is a valid assumption that someone who is good at making things look pretty is also good at making an application easy to use.&lt;br /&gt;&lt;br /&gt;5. I have seen web sites that have spent extreme and disproportionate amounts of development effort on a feature that adds no functionality or usability gain. But it looks cool. This is fine in a world with unlimited resources. But in the real world it may be less appropriate. &lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thus my preference (both as a user and developer) for prioritizing these 3 metrics is:&lt;br /&gt;&lt;br /&gt;1.     Functionality/Content&lt;br /&gt;2.     Usability&lt;br /&gt;3.     Visually appealing&lt;br /&gt;&lt;br /&gt;There are always exceptions. For example, a web site for a graphic art company or a web site trying to promote their product's image/brand may prioritize differently.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-7948358962296768082?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/7948358962296768082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=7948358962296768082' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7948358962296768082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/7948358962296768082'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2009/01/form-over-function-on-web.html' title='Form over Function on the Web'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-2537612105791611856</id><published>2008-12-24T13:27:00.000-08:00</published><updated>2009-04-30T15:03:25.771-07:00</updated><title type='text'>Mac Usability Overrated</title><content type='html'>A few years ago, I switched back to a Mac after a 15 year hiatus. Overall, it was a positive experience. And overall, I prefer the Mac OS X Leopard to Windows XP. I have no experience with Vista, so I can't comment on that. But given my general tendency of complaining and my annoyance of religiously fervent Mac fans, I feel I should share a few things that, in my opinion, represent poor usability design in the Mac.&lt;br /&gt;&lt;br /&gt;Now there is no way to gauge how skewed my opinions are by the fifteen years of Windows experience. Sometimes people judge something as crappy just because it is &lt;i&gt;new&lt;/i&gt; to them. As a teacher, I see this in my students. Most people taking my class are moving from an old technology to a new technology. And many of my students complain that the "new way" of doing things sucks and that their "old way" (in Cobalt, Fortran, PowerBuilder, etc) was much better. Sometimes, they are right. But sometimes, they just haven't gotten used to the "new way". Its probably impossible to separate "poor design" from "I'm just not used to it", but none-the-less, I'll try.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;#1 Context &lt;span style="color: rgb(255, 0, 0);"&gt;In&lt;/span&gt;sensitive Menus&lt;/span&gt;&lt;br /&gt;Most Mac applications have a global menu bar. And this is how you access most of the app's functionality. What's more, the menu is anchored to the top of the screen. Not the top of the document. Not the top of the panel - the top of the computer screen. This, in my opinion, isn't just &lt;i&gt;different&lt;/i&gt; from what I am used to. It's a poor design. It violates the UI design &lt;a href="http://www.sylvantech.com/%7Etalin/projects/ui_design.html"&gt;Principal of Context&lt;/a&gt;. Most user actions apply to a specific context (i.e. object): a paragraph, the selected cells, the current document, etc. This is the fundamental concept of OO (an object is really just a context). Imagine you have a dual monitor setup. You have a graphics application running on the right screen. And you want to modify a rectangle. Where do look for a list of possible actions? The rectangle? No. The document? No. You look to a menu bar at the top of your &lt;i&gt;left&lt;/i&gt; monitor. The only argument, in favor of this design is that it saves a bit of screen real estate. And old Mac people are used to it. But, overall, in my opinion it is just poor usability design.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;#2 No Maximize Button&lt;/span&gt;&lt;br /&gt;Mac windows do not have a maximize button. They have something kind-of (but not really) comparable: the Zoom Button. It is one of the 3 tiny circle buttons in the upper left corn of every Mac window. The zoom button attempts a "size to fit". Most UI programming toolkits have a function like this built-in. In Java Swing, it's called the pack() function. Basically, the window attempts to find the &lt;i&gt;optimal&lt;/i&gt; size (not too big, not too small) based on the window's contents. The problem with this approach is that the algorithm is wrong most of the time. And it takes control away from the user. Often, when browsing with Safari, I just want the whole screen. Obviously, it's not a deal breaker. I can just drag the window bigger if needed. It's just a pain in the butt. By the way, many (non apple) vendors simply have their zoom buttons &lt;i&gt;do&lt;/i&gt; a maximize. But Safari, Finder and iTunes do not.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;#3 The Window Button&lt;/span&gt;s&lt;br /&gt;Most windows on my Mac have 3 buttons in the upper left corner (one of them is the Zoom button mentioned above). These buttons are just circles. There is no indication of what they do. If you hover your mouse over the button, then an image appears. But you get no tool tip telling you (in words) what the button does. This, in my opinion, is not just &lt;i&gt;different&lt;/i&gt; from what I am used to. It's just poor usability design. Why not just have the image visible all the time? Why not have a tool tip? Perhaps some designer thought it looked prettier this way. I don't know.&lt;br /&gt;&lt;br /&gt;I think Apple is great at creating interfaces that &lt;i&gt;look&lt;/i&gt; great. But as far, as usability goes, I think they are probably good. Above average. But not great. At least not based on my Mac experience.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-2537612105791611856?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/2537612105791611856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=2537612105791611856' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/2537612105791611856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/2537612105791611856'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/mac-usability-overrated.html' title='Mac Usability Overrated'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-3955368892016390624</id><published>2008-12-23T07:53:00.001-08:00</published><updated>2009-02-22T15:02:41.795-08:00</updated><title type='text'>Composite Widgets and Blur Events</title><content type='html'>It is a common need in web applications to create a single logical widget (aka UI component) that internally is composed of multiple native html elements. A few examples:&lt;ul&gt;&lt;li&gt;A DateWidget composed of 3 html SELECT elements (month, day and year)&lt;/li&gt;&lt;li&gt;A custom combobox composed of a textbox, a button (placed to the right of the textbox) and a popup (or more accurately a drop-down) div that contains a pick list and appears when the button is clicked or a letter is typed.&lt;/li&gt;&lt;li&gt;A DatePicker (same as custom combobox mentioned above, except the drop down is a calendar instead of a pick list)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Below is a problem with this kind of widget that i have not been able to easily solve:&lt;/div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Problem Definition&lt;/span&gt;&lt;br /&gt;It is often desirable to have a &lt;i&gt;single&lt;/i&gt; blur event that applies to the composite as a whole. Using the blur event for the internal html elements may be the wrong granularity for validation or change notifications. For example, suppose that for the above mentioned combobox, we chose to use the textbox's blur event (because the combobox as a whole has no blur event) for validation. Then imagine this scenario:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The user types 1 letter into the textbox&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The popup appears&lt;br /&gt;&lt;/li&gt;&lt;li&gt;User clicks on the popup - perhaps to scroll the pick list or (in the case of the DatePicker) to scroll the month&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Boom! The TextBox's change and blur events fire.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Our app, in response to the blur event, attempts to validate&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Our validation function reads the value in the textbox and, detecting that it is only 1 character long, displays an error message.&lt;/li&gt;&lt;/ol&gt;This is clearly not the desired behavior.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Desired Behavior&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Test #1:&lt;/span&gt;&lt;br /&gt;Does the composite widget have its own blur event as distinct from those of its child widgets? And (more to the point) is there an obvious way to add a blur listener to the composite (again, as distinct from its child elements)?&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Test #2:&lt;/span&gt; &lt;div&gt;Assuming we passed test #1, does the composite's blur event fire in a way that is logical for the composite as a whole:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Test  2a (comboBox with down-arrow trigger button):&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Click into the textbox portion of the combobox&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Type a few letters&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Click the down-arrow-button (to reveal the drop down list). This should &lt;i&gt;not&lt;/i&gt; fire the &lt;i&gt;composite's&lt;/i&gt; blur event.&lt;/li&gt;&lt;/ol&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;Test 2b (date picker with no trigger button):&lt;/span&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The user types 1 letter into the textbox&lt;br /&gt;&lt;/li&gt;&lt;li&gt;This causes the popup calendar to appear&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The popup contains a "Scroll Next Month" button. Click on that. This should &lt;i&gt;not&lt;/i&gt; fire the &lt;i&gt;composite's&lt;/i&gt; blur event.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Workarounds&lt;/span&gt;&lt;br /&gt;This isn't a deal breaker issue for most applications. We can just hold off on validation until later, when the entire form is submitted. But none-the-less, many customers prefer field-level errors to appear sooner rather than later. This is, after all, one of reasons we have blur and change events.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Other Widget Libraries&lt;/span&gt;&lt;br /&gt;I did a quick survey of composite widgets from various web widget libraries, to see if they handled blur events as desired (see "desired behavior" above). Here is what I found:&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt; &lt;tr&gt;  &lt;th&gt;Library&lt;/th&gt;  &lt;th&gt;Widget&lt;/th&gt;  &lt;th&gt;Composite blur/change events&lt;/th&gt;  &lt;th&gt;Demo Link&lt;/th&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;DOJO&lt;/td&gt;  &lt;td&gt;dijit.form.FilteringSelect&lt;/td&gt;  &lt;td&gt;Yes&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;jQuery&lt;/td&gt;  &lt;td&gt;ui.datepicker&lt;/td&gt;  &lt;td&gt;No&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;Spry&lt;/td&gt;  &lt;td&gt;SuggestText ??&lt;/td&gt;  &lt;td&gt;No&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;GWT 1.5&lt;/td&gt;  &lt;td&gt;SuggestBox&lt;/td&gt;  &lt;td&gt;No&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;GWT 1.6&lt;/td&gt;  &lt;td&gt;SuggestBox&lt;/td&gt;  &lt;td&gt;Maybe&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;  &lt;td&gt;GWT Incubator&lt;/td&gt;  &lt;td&gt;DateBox&lt;/td&gt;  &lt;td&gt;No&lt;/td&gt;  &lt;td&gt;TODO&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Possible Solutions&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Timer solutions. TODO: elaborate&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Global focus tracker. TODO: elaborate&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Try to figure out what DOJO did (their solution was not easy for me to follow)&lt;/li&gt;&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Event Bubbling&lt;/span&gt;&lt;br /&gt;Note that what we are describing here is not the same as bubbling. Event bubbling refers to the fact that if a child element does not handle an event (or more specifically &lt;i&gt;cancel&lt;/i&gt; the event) then that event bubbles up to the parent element. But a div containing 3 select elements (as in the date selector described above) would still fire 3 change events in either case:&lt;br /&gt;&lt;br /&gt;Case #1: three select#changeListeners&lt;br /&gt;Case #2: one div#changeListener.&lt;br /&gt;&lt;br /&gt;This is not to say, that bubbling might not be used in the solution. But bubbling, in and of itself, is not the solution.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Objective&lt;/span&gt;&lt;br /&gt;Come up with a solution that:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Provides the desired behavior described above&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Is general enough to componentize (for example, in GWT, a generic parent class called BlurableComposite). Note: GWT has a class called FocusPanel, but I can't figure what it's purpose is and if it is designed to address the problem I am describing here.&lt;/li&gt;&lt;li&gt;If the solution is not general enough to express as a reusable class, then a solution general enough to express in the form of a design pattern/solution&lt;/li&gt;&lt;li&gt;Perhaps tie in the solution with GWT's new HasValue/HasValueChangeHandler (in 1.6 trunk)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-3955368892016390624?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/3955368892016390624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=3955368892016390624' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/3955368892016390624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/3955368892016390624'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/composite-widgets-and-blur-events.html' title='Composite Widgets and Blur Events'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-1723049708027952214</id><published>2008-12-19T14:57:00.000-08:00</published><updated>2008-12-19T18:51:12.864-08:00</updated><title type='text'>JavaScript Virtual Properties</title><content type='html'>Some programming languages have a particular feature that I find &lt;i&gt;very&lt;/i&gt; useful. This feature allows a setter method to disguise itself as a variable assignment. For example, instead of:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;person1.setAge(42);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You would do this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;person.age = 42;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Under the covers, it's actually not setting a variable (as it appears) but rather it's calling a setter method.&lt;br /&gt;&lt;br /&gt;The same language feature allows a getter method to disguise itself as a variable read. For example, instead of:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;print( person1.getAge() );&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;You would do this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;print( person1.age );&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Again, under the covers, we are actually &lt;i&gt;not&lt;/i&gt; setting a variable (as it appears) but rather we are calling a getter method.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Virtual Properties&lt;/h3&gt;&lt;br /&gt;The above described language feature does &lt;i&gt;not&lt;/i&gt; have an industry standard name (that I know of). The old VB used to call it "property procedure". I've heard it called "getters and setters", but that is a confusing term because languages like Java have "getters and setters" but they do NOT have the above mentioned language feature. C# calls them properties. But this is also a confusing term. JavaScript and Java both use the term property to mean something different. Also, many people use the term property interchangeably with "field" or "instance variable". Ruby uses the term "attr_accessor".&lt;br /&gt;&lt;br /&gt;But JavaScript (as of ECMAScript 4th edition) will soon be supporting this feature. And they use the term "Virtual Property" which makes the most sense to me. So that is what I will use. To be more specific, ECMAScript 4 defines three terms:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Value Property&lt;/b&gt;: A value property is the new name for what used to be called "property" (without the "value" prefix). Value properties are just plain old instance variables (aka fields). The reason for the new term is to distinguish a value property from a "virtual property".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Virtual Property&lt;/b&gt;: A virtual property is really a getter and/or setter method that (to the caller) appears to be an instance variable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Property&lt;/b&gt;: The term "property" is now inclusive of both value properties and virtual properties. Thus, clients of the object just see "properties" there is no way they can tell whether they are accessing a virtual property (i.e. calling a setter or getter method) or accessing value property (i.e. a variable). The fact that the caller is hidden from these details is really the whole point of virtual properties.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why Use Virtual Properties&lt;/h3&gt;&lt;br /&gt;You may be asking yourself, "why would I want to use this feature?" Well let me explain by reviewing setter/getter methods in general.&lt;br /&gt;&lt;br /&gt;Most of the time, setter methods (the old kind of setters and the new "virtual property" style setters which I will show shortly) don't do much that is interesting. They usually, just turn around and set a variable:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function setAge(newValue){&lt;br /&gt;    this._age = newValue;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;But sometimes, the setter adds a bit of value beyond merely setting an instance variable. For example, validation:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function setAge(newValue){&lt;br /&gt;    if(newValue) &gt; 150) throw new Error("Too Old");&lt;br /&gt;    this._age = newValue;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Or perhaps the setter may trigger some other action (or side effect):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function setAge(newValue){&lt;br /&gt;    this._age = newValue;&lt;br /&gt; recalculateDateOfBirth();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;And sometimes the setter has no corresponding underlying instance variable at all. For example, storing age &lt;i&gt;and&lt;/i&gt; dateOfBirth is redundant. So you may have:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function setAge(newValue){&lt;br /&gt;    this.dateOfBirth =  computeDateOfBirthFromAge(newValue);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;But the vast majority of the time, setters &lt;i&gt;just&lt;/i&gt; set a variable:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function setAge(newValue){&lt;br /&gt;    this._age = newValue;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This results in a whole ton of boiler plate code for setter methods. The same is true of getter methods, some times they do something interesting like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function getArea(){&lt;br /&gt; return this._length * this._width;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;But most of time they just do the same old boring thing, return the value of a variable:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;function getLength(){&lt;br /&gt; return this._length;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Again, this results in a ton of boring, noisy, boiler plate code. In fact, most modern IDE's have a shortcut called "generate getters and setters". &lt;br /&gt;&lt;br /&gt;So now, with virtual properties, any time you have a setter or getter that does nothing but set or get the value of an instance variable, just get rid of it.  Instead allow direct access to the instance variable. &lt;br /&gt;&lt;br /&gt;The payoff: all those boilerplate do-nothing getters and setters just go away!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to Create a JavaScript Virtual Property&lt;/h3&gt;&lt;br /&gt;So now in JavaScript you have two new keywords: get and set. These are placed write after the word &lt;code&gt;function&lt;/code&gt; like this: &lt;br /&gt;&lt;code&gt;&lt;br /&gt;function get age() { &lt;br /&gt; return this._age &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;function set length(newValue) { &lt;br /&gt; if(newValue &gt; 150) throw new Error("Too Old"); &lt;br /&gt; this._age = newValue&lt;br /&gt;} &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Browser Support&lt;/h3&gt;&lt;br /&gt;As it turns out Safari, FireFox and Opera all support virtual properties. And now (from what I have read), virtual properties will be supported in IE8.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;More Info&lt;/h3&gt;&lt;br /&gt;&lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Creating_New_Objects/Defining_Getters_and_Setters"&gt;Mozilla: Defining Getters and Setters&lt;/a&gt;&lt;br /&gt;&lt;a href="http://beust.com/weblog/archives/000083.html"&gt;Cedric on gettersand setters&lt;/a&gt;&lt;br /&gt;&lt;a href="http://wiki.ecmascript.org/lib/exe/fetch.php?id=spec%3Aspec&amp;cache=cache&amp;media=spec:core-language-d2.html"&gt;ECMAScript 4&lt;/a&gt; Look for section titled: Property States&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-1723049708027952214?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/1723049708027952214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=1723049708027952214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/1723049708027952214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/1723049708027952214'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/virtual-properties-soon-to-be-supported.html' title='JavaScript Virtual Properties'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-2389741367028735176</id><published>2008-12-17T16:59:00.000-08:00</published><updated>2008-12-17T17:01:50.672-08:00</updated><title type='text'>Safari DevelopMenu</title><content type='html'>Just discovered something cool in Safari. Under Safari -&gt; Preferences -&gt; Advanced, there is a checkbox: "Show Develop Menu in Menu Bar". This adds a new menu item called "Develop" with all sorts of web developer tools.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-2389741367028735176?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/2389741367028735176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=2389741367028735176' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/2389741367028735176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/2389741367028735176'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/safari-developmenu.html' title='Safari DevelopMenu'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-5610296182699765228</id><published>2008-12-17T11:49:00.000-08:00</published><updated>2009-04-12T19:35:45.359-07:00</updated><title type='text'>One Language for Client and Server</title><content type='html'>Some web developers categorize themselves as a "front-end" developer or a "back-end" developer. For large teams, this specialization is a nice luxury. But more often than not (I think) most developers end up playing both roles. I'm glad that I play both roles, because often it takes an intimate understanding of both, to create the best overall architecture. Often the most important part of an architecture is deciding what should be part of the the front-end and what should be part of the back-end and the communication protocol between the two. Thus, I proudly categorize myself as an end-to-end developer (or a front-back developer?).&lt;br /&gt;&lt;br /&gt;Side-note #1: The terms front-end and back-end is not necessarily the same thing as client-side and server-side. But for this post, this is how I am using them.&lt;br /&gt;&lt;br /&gt;So here is the problem with being an end-to-end developer. The predominate programming languages for front-ends are JavaScript and ActionScript. The predominant language for back-ends are: Java, C#, VB.NET, PHP, Ruby and Python. This means developers must learn at least two languages to do their job (lets ignore CSS, HTML and SQL for the moment). This is good for me personally, because I enjoy learning new languages and (as luck would have it) I already know most of the server-side and client-side languages. But most of my clients (corporate IT developers) must also spend time learning their own problem domain (insurance, medical, banking, or whatever). These people are not as geeky as me and don't enjoy learning new programming languages for sport. Many come from backgrounds where they used to create entire applications using only one language like VB, PowerBuilder or Oracle Forms. Thus, I ask the question, how much more productive can we be if we can use the same language end-to-end? I personally would like this.&lt;br /&gt;&lt;br /&gt;Side-note #2: Sometimes additional, more special-purpose languages are a good thing. There is even a acronym to represent the concept: DSL - &lt;a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html"&gt; (Domain Specific Language&lt;/a&gt;). Examples of DSLs include things like HTML, CSS, SQL, XSLT and regular expressions. But when I speak of a single programming language for front-end and back-end, I am talking about general purpose languages. The predominant front-end and back-end languages mentioned above are &lt;i&gt;general purpose&lt;/i&gt; programming languages.&lt;br /&gt;&lt;br /&gt;So, if you would like a single end-to-end language for web development. Here are your options:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Compile your favorite server-side language-to-JavaScript&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Find an Application Server that supports JavaScript&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use a server-side framework that generates all the JavaScript&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;Below are a few examples from each of these categories.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GWT: Google Web Toolkit&lt;/h3&gt;&lt;br /&gt;GWT compiles Java into JavaScript. Thus, you can use Java for the front-end and Java for the back-end. Think of JavaScript as the new byte-code. In both cases the Java part is really an illusion; at runtime the Java is gone and all that's left is JVM byte-code (server-side) or JavaScript (client-side). But once you are coding in Java on both sides, network (i.e. AJAX) programming becomes much easier; you can now send Java objects back and forth RPC-style.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Pyjamas&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/pyjamas/"&gt;Pyjamas&lt;/a&gt; is similar to GWT except it compiles Python to JavaScript.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Other X-to-JavaScript Compilers&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://j2s.sourceforge.net/"&gt;Java2Script&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rb2js.rubyforge.org/"&gt;Ruby to JavaScript&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.harmony-framework.com//"&gt;Harmony Framework - PHP to JavaScript&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;ASP.NET and JScript&lt;/h3&gt;&lt;br /&gt;One can create ASP.NET pages using JavaScript. Thus, in principal, one can use JavaScript for both front-end and back-end development. The only problem is that JScript is a more modern version of JavaScript (more like ActionScript 3) thus client and server languages are not technically the same.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;JSF AJAX&lt;/h3&gt;&lt;br /&gt;JSF (JavaServer Faces) when coupled with an AJAX JSF tag library like &lt;a href="http://www.icefaces.org/"&gt;ICEFaces&lt;/a&gt;, allows one to create an entire AJAX application and not see a lick of JavaScript.  Just as traditional server-side tags are expanded into HTML before being served to the browser, AJAX aware JSF tags are expanded to HTML + JavaScript. Thus you get most of the benefits of a rich JavaScript client, but you are only coding in one language: Java. The only problem with this is that, in reality, you are coding in all sorts of languages: JSP, JSF tags, EL (the Java Expression Language). Plus large chunks of the application ends up in JSF specific XML files (faces-config). This model is the least flexible of the solutions mentioned in this article.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Sun's Phobos&lt;/h3&gt;&lt;br /&gt;&lt;a&gt;Phobos&lt;/a&gt;, like Jaxer, is a server-side JavaScript web application server. However, Phobos is based on the rhino JavaScript engine. Rhino itself is a pure Java application. This means it will be slower than C based JavaScript engines (like SpiderMonkey, TraceMonkey used in Jaxer). But it also means its very easy to make use of existing java code and libraries - a potentially huge benefit. Plus, Phobos takes the form of a standard Java WAR file. Meaning it can run on top of any Web Container that supports the Java Servlet 2.4 spec such as Tomcat, Jetty, IBM WebSphere, etc.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Jaxer&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://aptana.com/jaxer"&gt;Jaxer&lt;/a&gt; is a server-side JavaScript application server. Technically speaking Jaxer takes the form of a web server plug-in. It currently runs on Apache 2.0 and Jetty (with plans to support IIS). It uses the SpiderMonkey JavaScript engine, the same one used by Firefox. They claim that "Jaxer performance is comparable to PHP and Rails". However, they will soon be switching to Firefox's newest JavaScript engine (TraceMonkey) which should prove much faster. One interesting point about Jaxer is that it's server-side programming model is essentially the same as the client-side programming model, namely DOM. Thus client and server not only use the same language, they also use the same API.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;10Gen&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://www.10gen.com/"&gt;10Gen&lt;/a&gt; (like Jaxer and Phobos) is a server-side, application server that supports JavaScript, Ruby and Python. There whole schtick is that the platform is "cloud-aware" from the get-go. In that since it's a bit like Google's app engine. You can use their platform as a "service" or you can run their software in your own cloud (i.e. on your own servers).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Own Experience&lt;/h3&gt;&lt;br /&gt;I have dabbled with all of these technologies. But the ones I have the most experience with are GWT and JSF/ICEFaces. Presently, my favorite tool for web development is GWT. It doesn't have the most feature-rich widget library in the world. But that is because they focus their efforts on making the "core" as good as it can be, then leave some of the widgets to third party vendors (of which there are dozens). If you work with GWT you will become a better web developer. There is some serious "smarts" contained in GWT. And it will rub off on you. Things that took days in JSF take minutes in GWT (creating your own component, for example). GWT is a thin layer on top of DHTML. It doesn't try to hide anything and generally doesn't create a whole new abstraction layer. But I could go on all day about GWT, but that would be a subject for a different post. Here are a few links about the general philosophies behind GWT:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/webtoolkit/makinggwtbetter.html#introduction"&gt;GWT Mission Statement&lt;/a&gt;&lt;br /&gt;&lt;a href="http://code.google.com/webtoolkit/makinggwtbetter.html#designaxioms"&gt;GWT Design Axioms&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-5610296182699765228?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/5610296182699765228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=5610296182699765228' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5610296182699765228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/5610296182699765228'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/one-language-for-client-and-server.html' title='One Language for Client and Server'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-6423828856455556694</id><published>2008-12-16T19:25:00.000-08:00</published><updated>2008-12-16T19:26:04.375-08:00</updated><title type='text'>User Experience (UX)</title><content type='html'>I am a developer. But I am also an avid &lt;i&gt;user&lt;/i&gt; of web sites and web applications. And as a user, I happen to really like the applications put out by Google. In particular, I like how they keep things simple, clean and uncluttered. And they don't get side tracked adding features and frills that impress everyone except the actual user of the application.&lt;br /&gt;&lt;br /&gt;Then I found this on Google's web site, &lt;a href="http://www.google.com/corporate/ux.html"&gt;Ten principles that contribute to a Googley user experience&lt;/a&gt;, that summarizes their design philosophies.&lt;br /&gt;&lt;br /&gt;I also like the apps by 37signals, specifically: BaseCamp and Highrise. As luck would have it, 37signals also has a web site explaining their UX and development philosophies called &lt;a href="http://gettingreal.37signals.com/toc.php"&gt;Getting Real&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-6423828856455556694?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/6423828856455556694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=6423828856455556694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/6423828856455556694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/6423828856455556694'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/user-experience-ux.html' title='User Experience (UX)'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-8754575062578877333</id><published>2008-12-04T11:19:00.000-08:00</published><updated>2008-12-04T11:26:38.736-08:00</updated><title type='text'>GWT apps are Small!</title><content type='html'>I just wrote a small DOJO page that has nothing on it but a combobox with 10 hard coded entires. I ran it thru firebug and the total download size was:   268 kb. Then I ran the gwt app i am working on thru firebug ( a full app with multiple screens, dozens of widgets). The entire download size of the gwt app was 98 kb. To summarize:&lt;br /&gt;&lt;br /&gt;268kb: DOJO app with one combobox&lt;br /&gt;98kb: a complete gwt application&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-8754575062578877333?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/8754575062578877333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=8754575062578877333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8754575062578877333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8754575062578877333'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/12/gwt-apps-are-small.html' title='GWT apps are Small!'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-8269599007072742069</id><published>2008-01-31T07:27:00.000-08:00</published><updated>2008-01-31T07:42:57.730-08:00</updated><title type='text'>Google's 4 Approved Programming Languages</title><content type='html'>I just learned today that within Google there are only 4 approved programming languages:&lt;div&gt;&lt;ul&gt;&lt;li&gt;C++&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Java&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Python&lt;br /&gt;&lt;/li&gt;&lt;li&gt;JavaScript&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Noticeably missing are C# and Ruby. Perhaps they figure that Ruby and C# occupy the same niche as Python and Java and are thus redundant and unnecessary. &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/14251888-8269599007072742069?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/8269599007072742069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=8269599007072742069' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8269599007072742069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/8269599007072742069'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2008/01/googles-4-approved-programming.html' title='Google&apos;s 4 Approved Programming Languages'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-4753670590916069473</id><published>2007-07-03T16:54:00.001-07:00</published><updated>2009-04-30T16:32:15.963-07:00</updated><title type='text'>Herding and Branding</title><content type='html'>Marketing people have a concept they use known as "branding". As a capitalist and entrepreneur, I love the idea of branding. I'm impressed by anyone who can get otherwise intelligent people to pay $50 for a five dollar white underwear t-shirt by putting the name of their brand. That is really cool. I wish I could do that!&lt;br /&gt;&lt;br /&gt;But with that said, as a consumer I find branding kind of insulting.&lt;br /&gt;&lt;br /&gt;I suspect that Lexus, Toyota and Scion (all Toyota brands) do not represent 3 categories of &lt;span style="font-style: italic;"&gt;car&lt;/span&gt; as much as they represent categories of &lt;span style="font-style: italic;"&gt;marketing strategy&lt;/span&gt;. In other words, different people respond differently to different sales gimmicks. By creating 3 virtual car companies, Toyota can ensure that each person receives the exact sales message that works on them.&lt;br /&gt;&lt;br /&gt;There is nothing inherently wrong with this kind of thing. Obviously it works on some people - maybe all people. But none the less, it's annoying to me - just as it's annoying when the used car salesman uses a cheap sales line on me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;IBM WebSphere&lt;/span&gt;&lt;br /&gt;At one point WebSphere was a &lt;em&gt;product&lt;/em&gt; (an app server). Then the marketing people at IBM thought: "How can we leverage the success of that product?" Their answer: &lt;span class="Apple-style-span" style="font-style: italic;"&gt;Rename every other product to WebSphere&lt;/span&gt;. So IBM's IDE was renamed to WebSphere, IBM's messaging product was renamed to WebSphere, and so on. Yes. IBM really does think we are that stupid. Or perhaps their sales pitch isn't geared to the cats, but rather the cat herders. But in the end the word WebSphere, with so &lt;em&gt;many&lt;/em&gt; meanings has no meaning at all. The whole WebSphere craziness just serves to confuse.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;J2EE&lt;/span&gt;&lt;br /&gt;I think the biggest culprit of branding craziness has to be Sun. I am a Java specialist. It's all I do. Yet, I have no idea what the current version of Java is. We started with 1.0, then 1.1, then 1.2, then 1.3, 1.4,1.5 and 1.6. But then there is also Java 5 and Java 6. And what the hell is Java 2 (as in J2SE and J2EE)?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;JavaFX&lt;/span&gt;&lt;br /&gt;So now Sun is at it again. JavaFX (Sun's cool new programming language) is not a language - &lt;em&gt;it's a brand&lt;/em&gt;. That means JavaFX could refer to a programming language or a mobile phone but it could also refer to a banana.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-4753670590916069473?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/4753670590916069473/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=4753670590916069473' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4753670590916069473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4753670590916069473'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2007/07/herding-and-branding.html' title='Herding and Branding'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-4093832080667764220</id><published>2007-06-27T22:58:00.000-07:00</published><updated>2009-04-30T15:17:19.558-07:00</updated><title type='text'>JavaFX</title><content type='html'>So JavaFX is my new favorite programming language. Thats right - JavaFX is a new programming language.&lt;br /&gt;&lt;br /&gt;I think a lot of people might be getting the wrong idea about JavaFX because of the marketing hype. When I first heard about JavaFX, it was positioned as an alternative to Flash (or Flex). As a way to create (and deliver) Rich Internet Applications. But upon further inspection one realizes that, at its core, JavaFX is &lt;i&gt;&lt;b&gt;really a new language that runs on the JVM&lt;/b&gt;&lt;/i&gt;. I would say that comparing JavaFX to Groovy (or even Spring) would be more appropriate than comparing it to Flash.&lt;br /&gt;&lt;br /&gt;[Correction: Technically speaking &lt;i&gt;JavaFX&lt;/i&gt; is a brand - &lt;i&gt;JavaFX &lt;b&gt;Script&lt;/b&gt;&lt;/i&gt; is the name of the programming language.]&lt;br /&gt;&lt;br /&gt;I'm low on time right now and can't go into many details, but let me say this: JavaFX is not just another language that runs on the JVM, its a very &lt;i&gt;&lt;b&gt;cool&lt;/b&gt;&lt;/i&gt; language. By cool, I mean that JavaFX has a number of innovative features that produce immediate and pronounced payoffs. For example:&lt;br /&gt;&lt;br /&gt;1. Type-safe JSON&lt;br /&gt;Any one who has used languages like Ruby or Groovy or even JavaScript knows that those languages don't need all those damn XML files that are part and parcel to modern Java frameworks.&lt;br /&gt;&lt;br /&gt;Essentially, any language that has syntax for array literals PLUS map literals has built-in support for declarative, XML-ish constructs:&lt;br /&gt;&lt;br /&gt;For example in JavaScript:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var company = {&lt;br /&gt;  name: "Smart Soft",&lt;br /&gt;  url: "www.smart-soft.com",&lt;br /&gt;  people:[&lt;br /&gt;    {firstName:"Dave",lastName: "Ford"},&lt;br /&gt;    {firstName:"Michelle",lastName: "Goldstein"}]&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now JavaFX has this same feature - but with one distinct advantage: the map literals are not maps - they are &lt;i&gt;typed&lt;/i&gt; Java objects. Here is how this would look in JavaFX:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var company = &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Company&lt;/span&gt;{&lt;br /&gt;  name: "Smart Soft"&lt;br /&gt;  url: "www.smart-soft.com"&lt;br /&gt;  people:[&lt;br /&gt;     &lt;span style="font-weight: bold;"&gt;Person&lt;/span&gt;{&lt;br /&gt;         firstName:"Dave"&lt;br /&gt;         lastName: "Ford"&lt;br /&gt;     },&lt;br /&gt;     &lt;span style="font-weight: bold;"&gt;Person&lt;/span&gt;{&lt;br /&gt;         firstName:"Michelle"&lt;br /&gt;         lastName: "Goldstein"}&lt;br /&gt;  ]&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This "typed" feature means that the IDE can give you auto-completion and find your errors &lt;i&gt;sooner&lt;/i&gt; rather than later. Bottom line: integrated declarative-style programming + type-safe IDE auto-completion and early error detection = big productivity gains.&lt;br /&gt;&lt;br /&gt;2. Language level support for bi-directional data binding. This is analogous to JSF's "value binding expressions" or Microsoft's "bound controls". The data binding feature supports MVC architectures in the most elegant manner I have seen yet. You simply &lt;i&gt;declare&lt;/i&gt; that a particular UI text field is &lt;i&gt;bound&lt;/i&gt; to some field in your model object. And then JavaFX keeps the model and view in synch automatically.&lt;br /&gt;&lt;br /&gt;There is much more to JavaFX than I have mentioned, but this should give a you a basic feel.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-4093832080667764220?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/4093832080667764220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=4093832080667764220' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4093832080667764220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4093832080667764220'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2007/06/javafx.html' title='JavaFX'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-9221866617329440682</id><published>2007-06-27T11:28:00.001-07:00</published><updated>2007-07-03T17:31:04.036-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaFX Tutorial Simple'/><title type='text'>Minimal JavaFX Demo</title><content type='html'>Here are the absolute simplest steps to get a demo of JavaFX up an running: &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Download the 3 JavaFX jar files:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;javafxrt.jar&lt;br /&gt;Filters.jar&lt;br /&gt;swing-layout.jar&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;You can get them from here:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://openjfx.dev.java.net/source/browse/openjfx/trunk/lib/"&gt;https://openjfx.dev.java.net/source/browse/openjfx/trunk/lib/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a text file called &lt;code&gt;Hello.fx&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import javafx.ui.*;&lt;br /&gt;&lt;br /&gt;Frame {&lt;br /&gt;    content: Label {&lt;br /&gt;        text: "Hello JavaFX"&lt;br /&gt;    }&lt;br /&gt;    visible: true&lt;br /&gt;}&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Add the 3 jars &lt;i&gt;&lt;b&gt;and Hello.fx&lt;/b&gt;&lt;/i&gt; to your classpath&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Run the script like so:&lt;br /&gt; &lt;br /&gt;&lt;code&gt;java net.java.javafx.FXShell Hello&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Note: The name &lt;code&gt;Hello&lt;/code&gt; is resolved via the classpath (not the file system).&lt;br /&gt;&lt;br /&gt;Here is how my folders looked:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;~/DavesJavafxDemo/classes/Hello.fx&lt;br /&gt;~/DavesJavafxDemo/lib/javafxrt.jar&lt;br /&gt;~/DavesJavafxDemo/lib/Filters.jar&lt;br /&gt;~/DavesJavafxDemo/lib/swing-layout.jar&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Thus, my classpath must include the &lt;i&gt;&lt;b&gt;classes folder&lt;/b&gt;&lt;/i&gt; plus the 3 jar files:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;~/DavesJavafxDemo/classes&lt;br /&gt;~/DavesJavafxDemo/lib/javafxrt.jar&lt;br /&gt;~/DavesJavafxDemo/lib/Filters.jar&lt;br /&gt;~/DavesJavafxDemo/lib/swing-layout.jar&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Here is the shell script I used:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cp=./lib/swing-layout.jar:./lib/Filter.jar:./lib/javafxrt.jar:./classes&lt;br /&gt;java -classpath $cp net.java.javafx.FXShell Hello&lt;br /&gt;&lt;/pre &gt;&lt;br /&gt;Note: The way I have the paths specified, you must run this script from within DavesJavafxDemo folder.&lt;br /&gt;&lt;br /&gt;On Windows, the shell script (runDemo.bat) would look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;set cp=.\lib\swing-layout.jar;.\lib\Filter.jar;.\lib\javafxrt.jar;.\classes&lt;br /&gt;java -classpath %cp% net.java.javafx.FXShell Hello&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-9221866617329440682?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/9221866617329440682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=9221866617329440682' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/9221866617329440682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/9221866617329440682'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2007/06/minimal-javafx-demo.html' title='Minimal JavaFX Demo'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-4881143558846757663</id><published>2007-04-07T08:15:00.000-07:00</published><updated>2007-06-27T21:35:12.908-07:00</updated><title type='text'>Dynamic Language Benefits</title><content type='html'>Here is a specific, concrete example demonstrating one of the benefits of a dynamic language (like JavaScript and Ruby) as compared to a static language like Java. &lt;br /&gt;&lt;br /&gt;Suppose you want to do some ad hoc profiling (and you don't have a profiling tool handy). Here would be one way to do it in Java:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;long t1 = System.currentTimeMillis();&lt;br /&gt;slowMethod();&lt;br /&gt;long t2 = System.currentTimeMillis();&lt;br /&gt;long delta = t2 - t1;&lt;br /&gt;System.out.println("slowMethod: " + delta);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And here would be the same thing in JavaScript:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;executeAndTime(slowMethod);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This works because JavaScript treats functions as just-another-object. As such, the function can be passed around like any other object. In this example, slowMethod (an object of type function) is passed as an argument to the executeAndTime() function. Here is what &lt;code&gt;executeAndTime&lt;/code&gt; looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function executeAndTime(f){&lt;br /&gt;    var t1 = new Date();&lt;br /&gt;    f();&lt;br /&gt;    var t2 = new Date();&lt;br /&gt;    var delta = t2 - t1;&lt;br /&gt;    document.write("Delta for [" + f.name + "]: " + delta + " millis");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-4881143558846757663?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4881143558846757663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/4881143558846757663'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2007/04/dynamic-language-benefit.html' title='Dynamic Language Benefits'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-116974014716612070</id><published>2007-01-25T07:48:00.000-08:00</published><updated>2007-07-03T10:46:47.615-07:00</updated><title type='text'>What to Hide?</title><content type='html'>In the world of computer programming, a lot of thought goes into deciding "what to hide" - in particular, what to hide from the computer programmer.&lt;br /&gt;&lt;br /&gt;For example, at some point in history people wrote applications in &lt;i&gt;machine language&lt;/i&gt;. Today machine language is hidden from the developer and we see something more human-friendly, like C or Java. The stuff that gets hidden is usually closer to the way machines communicate. The stuff that remains visible is closer to the way humans communicate. At least that's the idea.&lt;br /&gt;&lt;br /&gt;The terms high-level and low-level are used to convey this concept. Low-level technologies are more machine-ish and ripe for hiding. High-level technologies are more human-friendly. The high-level technologies are often referred to as &lt;i&gt;abstractions&lt;/i&gt; that &lt;i&gt;encapsulate&lt;/i&gt; or hide the low-level technologies. Today's high-level technology often becomes tomorrow's low-level technology. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Char and Array&lt;/h3&gt;&lt;br /&gt;Two language constructs that I once used daily are the &lt;i&gt;char&lt;/i&gt; and the &lt;i&gt;array&lt;/i&gt;. Today, I use them only indirectly, preferring higher-level constructs like String and Collection. In other words, the char and the array are going the way of machine language: mostly hidden.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;SQL&lt;/h3&gt;&lt;br /&gt;Sometimes it's not alway clear what should be hidden and what shouldn't. For example, many years ago a high-level language called SQL was invented for working with data. SQL is an abstraction designed for humans. SQL is, in no way, a reflection of how machines or hardware work. It was designed for humans. Yet still, SQL is gradually crossing over to the world of the hidden, joining the ranks of machine language, chars and arrays. If you have ever used JDO, EJB Entity Beans or Hibernate, then you know what I'm talking about.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;JavaScript&lt;/h3&gt;&lt;br /&gt;The blogs are filled with developers singing the praises of dynamic languages (formerly known as scripting languages). The two most popular dynamic languages that I use are JavaScript and Ruby. Dynamic languages are often more terse, flexible and feature-rich than static languages.  Static languages, like Java, do have their advantages though. They are typically more IDE'able and optimizable. The thing to note here is that both Java and JavaScript are pure abstractions. Both were invented to be human-friendly ways of programming computers. But if I had to pick one as being "lower-level", it would be Java. &lt;br /&gt;&lt;br /&gt;So which is the preferred abstraction? Java or JavaScript? Not everyone agrees. But if you look at frameworks like the Google Web Toolkit (GWT) or ICEfaces you will see that JavaScript may be crossing over into the land of the hidden. With GWT, the human codes in &lt;i&gt;Java&lt;/i&gt;, then the GWT compiler translates your Java into JavaScript. No human ever sees the JavaScript. Only the machine sees it. In this case the &lt;i&gt;machine&lt;/i&gt; is the JavaScript enabled web browser.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Hiding Gone Wrong&lt;/h3&gt;&lt;br /&gt;The key point here is to &lt;i&gt;&lt;b&gt;choose your abstractions wisely&lt;/b&gt;&lt;/i&gt;. The stuff that's &lt;i&gt;not&lt;/i&gt; hidden ultimately becomes a dependency. The goal is to encapsulate things that are &lt;i&gt;complicated or volatile&lt;/i&gt; behind abstractions that are &lt;i&gt;simple and stable&lt;/i&gt;. Here are a few examples where, in my opinion, the choice of "what to hide" is sometimes wrong:&lt;br /&gt;&lt;br /&gt;Web Service Toolkits.&lt;br /&gt;XML is simple and stable. HTTP is simple and stable. Web service toolkits (like Axis) that &lt;i&gt;hide&lt;/i&gt; the XML are not simple or stable. They add unnecessary layers and complexity. For most developers that need to produce or consume web services, it makes more sense to work directly with XML. Tools like Axis have their place, but in my opinion, that place is a fairly small niche*.&lt;br /&gt;&lt;br /&gt;O/R Mappers (like Hibernate)&lt;br /&gt;SQL is simple, stable and extremely versatile. I can teach anyone SQL in a half day. Hibernate is not so simple. Contrary to what anyone tells you, it's a very sophisticated tool. If you don't know what your doing, it can easily cause more trouble than it saves you. Again, Hibernate does have its niche*. In fact, I love Hibernate. But do keep in mind that with Hibernate (and O/R mappers in general) you are encapsulating something really simple with something really complicated. So be sure you are clear on the benefits and drawbacks before moving forward.&lt;br /&gt;&lt;br /&gt;* Note: if you take our Hibernate or Web Services workshop, we do cover these decision making criteria. That is: when does it make since to forgo Hibernate or Axis and work directly with the underlying technology (like SQL or XML)?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-116974014716612070?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/116974014716612070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=116974014716612070' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116974014716612070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116974014716612070'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2007/01/what-to-hide.html' title='What to Hide?'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-116344065699517516</id><published>2006-11-13T09:54:00.000-08:00</published><updated>2009-05-01T12:37:20.920-07:00</updated><title type='text'>Amazon and Google use Table-Based Layouts</title><content type='html'>This is my addition to the already over-blogged "table-based vs. CSS-based layout" debate. The older, tried-and-true technique for laying out web pages is to use HTML tables. A newer way is to use CSS Floats. Neither floats nor tables were ever intended to be used for page layout. I won't restate what's been stated but here are my 2 cents on the issue:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;The benefits of float-based layouts are overstated.&lt;/li&gt;&lt;li&gt;The difficulty in using float based layouts are understated.&lt;/li&gt;&lt;li&gt;One of the benefits of float-based layouts is separation of content from layout. This benefit can be achieved in other ways, for example on the server-side, by using XSLT, sitemesh or portal technologies.&lt;/li&gt;&lt;li&gt;Amazon and Google use table-based layouts. That has to count for something.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;[Update: 5/1/2009] : Today, amazon and Google's Blogger.com both use CSS based layouts&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-116344065699517516?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/116344065699517516/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=116344065699517516' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116344065699517516'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116344065699517516'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2006/11/amazon-and-google-use-table-based.html' title='Amazon and Google use Table-Based Layouts'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-116318128815701240</id><published>2006-11-10T08:42:00.000-08:00</published><updated>2007-01-31T20:24:12.240-08:00</updated><title type='text'>10 IDE Shortcuts Everyone Should Know</title><content type='html'>Below are 10 IDE shortcuts that everyone should know but many don't. These are tricks that save me lots of time. I use them so often they are hard-wired into my brain. They work in IntelliJ and Eclipse and probably others.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;1. Introduce Variable&lt;/h3&gt;&lt;br /&gt;IntelliJ calls it "Introduce Variable" (Ctrl Alt V)&lt;br /&gt;Eclipse calls it "Extract Local Variable" (Alt Shift L)&lt;br /&gt;&lt;br /&gt;Here is how it works. You type this:&lt;br /&gt;&lt;br /&gt;new FooBanger();&lt;br /&gt;&lt;br /&gt;Then, with your cursor positioned at the end of the line, press Ctrl Alt V. IntelliJ prompts for a variable name and then changes the code to this:&lt;br /&gt;&lt;br /&gt;FooBanger fooBanger = new FooBanger();&lt;br /&gt;&lt;br /&gt;Alternately, if you have a long expression like this:&lt;br /&gt;&lt;br /&gt;x.getPerson().getCompany().getCEO().getLastName();&lt;br /&gt;&lt;br /&gt;You can highlight an expression within the expression, for example:&lt;br /&gt;&lt;img src="http://photos1.blogger.com/blogger/8068/1283/1600/g1.gif" /&gt;&lt;br /&gt;&lt;br /&gt;Then press Ctrl Alt V. IntelliJ prompts for a variable name and changes your code to this:&lt;br /&gt;&lt;br /&gt;Company c = x.getPerson().getCompany() &lt;br /&gt;c.getCEO().getLastName();&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;2. Goto File&lt;/h3&gt;&lt;br /&gt;IntelliJ calls it "Goto File or Goto Class" (Ctrl Shift N or Ctrl N)&lt;br /&gt;Eclipse calls it "Open Resource" (Alt Shift L)&lt;br /&gt;&lt;br /&gt;A large part of what modern IDE's do falls under the heading of "Project Navigation", i.e. making it easy to quickly move from file to file within a large project. This and the next two tips deal with project navigation.&lt;br /&gt;&lt;br /&gt;If you remember the name of a file but don't feel like navigating 8 folders deep to get to it, then use this trick. Press Ctrl N. Then type the first few letters of a file name. The IDE then takes you to that file. You don't have to remember what folder the file is in.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;3. Hyperlink (Jump to File)&lt;/h3&gt;&lt;br /&gt;This works the same in IntelliJ and Eclipse. Hold down the control key, then hover your mouse over a class name. As your mouse moves over the class name, it turns into a hyperlink. Click the hyperlink to goto the highlighted file.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;4. The Back Button&lt;/h3&gt;&lt;br /&gt;IntelliJ and Eclipse both have a browser style Back button which takes you to the previous file you were working on. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;5. Delete Current Line&lt;/h3&gt;&lt;br /&gt;Eclipse: Ctrl D (D for delete)&lt;br /&gt;IntelliJ: Ctrl Y (Y for yank)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;6. Duplicate Current Line&lt;/h3&gt;&lt;br /&gt;Eclipse: Ctrl Alt Down&lt;br /&gt;IntelliJ: Ctrl D (D for duplicate)&lt;br /&gt;&lt;br /&gt;-----------&lt;br /&gt;OK, so I stopped at 6. This blogging business is tiring.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-116318128815701240?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/116318128815701240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=116318128815701240' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116318128815701240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/116318128815701240'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2006/11/10-ide-shortcuts-everyone-should-know.html' title='10 IDE Shortcuts Everyone Should Know'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-14251888.post-112069539756785218</id><published>2005-07-06T17:15:00.000-07:00</published><updated>2006-10-04T08:38:59.463-07:00</updated><title type='text'>Welcome</title><content type='html'>Welcome to my new Blog. I have nothing to say at the moment. Actually, I have lots to say, but just too busy right now. But at least I've taken the first step: setting up the blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14251888-112069539756785218?l=dave-ford.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dave-ford.blogspot.com/feeds/112069539756785218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=14251888&amp;postID=112069539756785218' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/112069539756785218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/14251888/posts/default/112069539756785218'/><link rel='alternate' type='text/html' href='http://dave-ford.blogspot.com/2005/07/welcome.html' title='Welcome'/><author><name>Dave Ford</name><uri>http://www.blogger.com/profile/03132728962355936253</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://www.smart-soft.com/images/dave-ford-headshot.jpg'/></author><thr:total>0</thr:total></entry></feed>
