Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.
You searched this site for "matt". 1,142 entries found.

You can also try this same search on Google.

Great Weekend in Montana

After the Software Summit last week, I sped down I-70 towards Denver. I made it to DIA with no time to spare. I had to run from the train to the gate, where the lady told me she'd been calling my name for the last 5 minutes. The fact I made the flight was a nice beginning to a wonderful weekend with my Dad in Montana.

It's been awhile since I've been to The Cabin in the fall. The Tamarack's were dressed in yellow and the sun warmed the land the entire weekend. It was cold at night, but we had my Grandma's ol' wood cookstove to keep us warm.

Hunting was a blast.

I haven't done it since I was a kid and I have memories of boredom. This time was different. My Dad and I basically trounced around the woods at the ol' homestead (120 acres) for hours on end with guns in our hands. What's not to like about that? Anytime outside of hunting season, people would think you're crazy and you'd probably believe them! Besides hunting and target practice, I got to hear a lot of stories from my Dad, explore all 4 corners of our property, chop wood, haul water and create super-hot saunas.

On Sunday, my Dad spotted a doe on our front-road and got a shot off, but missed. 20 minutes later, I got a chance at the same deer when she poked her head out from behind a tree 30 feet away from me. Unfortunately, I had a .30-06 strapped to my shoulder and couldn't get in position fast enough. After she ran off, we hunted her for a couple hours. We saw her a few more times, but didn't have any success.

The best part is we still had a ton of fun. One thing's for sure: I'll be at The Cabin during hunting season from now on. :-)

Posted in General at Oct 28 2008, 11:45:01 PM MDT 7 Comments

RESTful Web Applications with Subbu Allamaraju

Subbu works at Yahoo! developing standards, patterns and practices for HTTP web languages. In the past, he was a web service and Java developer. He was also a standards contributor at BEA and an author of books on Java EE. His current passion is HTTP and REST. Subbu confesses that he's not a web developer, has no interest in the internals of programming models used for web frameworks and he's only interested in the visible aspects of the architecture.

"The Web is Mostly Restful"

Being RESTful in an abstract sense means:

  • Resources are named by URIs
  • Resources have representations (Atom, HTML, JSON, XML)
  • Resources contain contextual links to allow navigation of state
  • There's a Uniform Interface

In the web today, some resources and URIs are personalized, but most are not. Some depend on sessions, but most do not. The consequence of a personalized UI with a non-unique URI is you cannot rely on browser caching.

The web is full of different representations (HTML, XML, JS, PDF, CSS, Flash). The problem with HTML is you can't tell links that you want a particular representation based of a link. The links are hard-coded to be a particular content-type. However, some media types on responses are ignored. This is often a problem with browsers and whether the user has plugins installed.

The Uniform Interface for the web is HTML and primarily links and forms (GET and POST). There's still some misconceptions (e.g. POST is secure). However, it's not about security, it's about idempotency and safety. You need to make sure you only use POST when you're changing data. POSTs are not repeatable. GET URIs are not always refreshable, which is quite unfortunate. Users shouldn't have to fight the back button.

Caching is a fundamental aspect of the web. Even in a personalized site, most of the content can be cached. The web is read-only for the most part. However, many enterprise web applications don't take advantage of caching. This is fine when there's not that many users, but it's bad when you want to scale to thousands of users. There's several frameworks that use cache-busting and prefer backend caching over HTTP caching. These frameworks are not using the web like they should.

Backend caching (e.g. Memcached) uses a non-uniform interface and you need to explicitly program to it. Frontend/HTTP caching has a uniform interface that's pluggable. Backend caching is generally more expensive to develop and deploy. There are cases where data should be cached on the backend, but you shouldn't focus all on backend caching w/o doing some frontend caching.

With Ajax, you get more opportunities to be RESTful. XMLHttpRequest is another HTTP client that can be programmed to. It has full support for the uniform interface, which allows content negotiation, optimistic concurrency and caching. Cross-domain hacks can be done with <script> and <iframe> to tunnel requests over GET. The W3C has been working for the last two years on how to do cross-domain Ajax w/o using hacks. The problem with current cross-domain implementations is they often use GET for everything, which isn't very RESTful. Subbu recommends using a proxy on the same domain if you do need to talk to other domains. This will allow your Ajax code to remain RESTful.

Web Frameworks
Web development is hard because of all the moving pieces that exist. Because of this, many web frameworks have been created to solve the various problems. In 1997, there were servlets. They provided basic plumbing and closely reflected HTTP/1.1. Servlets provided a poor programming model, but it allowed a lot of frameworks to be built on top of it. We don't use servlets to write applications, only to write application frameworks. The second era came about in 2001 when Action-oriented frameworks became popular. In 2004, JSF and friends came to play. JSF is a component-based framework with known limitations (complex, slow, uses POST for almost everything, Ajax is difficult). These limitations have resulted in a number of third-party patches being developed to solve these issues.

JSF was designed to use the request to create a component tree that maintains state. Unfortunately, the state is not something the developer has control over. It's not the state of the application, it's the state of the components. The client's knowledge of the state is mentioned with a cookie and the server keeps the state in the session. The problem with JSF is you don't have a choice of state in your application - you can't write stateless applications like you can with servlets.

JSF uses overloaded URIs for its resources. When you have one URI with multiple representations, there's no way to tell how a representation was chosen. JSF's compromise is to allow client-side state saving. However, they do this by putting hidden field in the form and requiring POST for navigation.

JSF vs. REST
Basically, these two are at opposite extremes. JSF is focused heavily on a UI component model. The people that developed it misinterpreted how the web works and made some fundamental questionable choices. You can patch it, but you can not fix it.

Web 2.0 Frameworks
GWT is a cross-compilation based framework. You write Java to generate JavaScript (b/c everyone hates writing JavaScript). It mashes client and server code into a single source. These layers communicate using GWT-RPC. Typical RPC concerns do not apply since code generation handles coupling and the client is downloaded from the same application. GWT-PRC does POSTs to the server and uses HTTP like a transport layer. To be fair, GWT does allow you to use a RequestBuilder to use the web like it should be used. This class allows more control over HTTP requests, it supports GET and POST and it allows so-called RESTful layers (GWT-REST and GET-Restlet). GWT is focused heavily on ease-of-use, which is good. It's modeled after RPC and breaks the uniform interface and focuses on backend caching. Unlike JSF, GWT is fixable, but the community tends to use RPC instead of RequestBuilder.

SOFEA has a central promise of SOA. Business logic is a reusable service that changes less often. The presentation application calls those services and changes more often. The nice thing about this type of architecture is it allows a separation of concerns and loose coupling. However, it doesn't embrace REST like it should. Appcelerator is an implementation of SOFEA that has a Ruby on Rails-like usability. However, it uses a SOAP/HTTP style with messaging and POSTs to a single URI. Appcelerator is interesting, but it introduces a different style of coupling. It breaks URI opacity and client deals with POX instead of links.

Conclusion
Don't fight the architecture of the web. Innovate and enhance instead of breaking. If nothing else, break judiciously. As developers, we should demand more from our frameworks and make sure they use the web and HTTP like it should be used.

Posted in Java at Oct 24 2008, 09:52:02 AM MDT 16 Comments

What's Coming in Spring 3.0

This morning, I delivered my What's Coming in Spring 3.0 talk for the 2nd time at Colorado Software Summit. Since there is no Spring 3.0 source code to speak of, I was unable to do the "Choose Your Own Adventure" demo at the end. :(

The good news is I was able to easily upgrade the Spring Kickstart application from Spring 2.0 to Spring 2.5.5 (using annotations). When 3.0 is released, I hope to update this project to use 3.0 as well as show what I needed to change. If I get ambitious, I might even change the UI to use Flex or Ext JS to show a RESTful client. Below is my presentation - hope you enjoy.

Posted in Java at Oct 22 2008, 11:51:12 AM MDT 12 Comments

Appcelerator with Matt Quinlan

This evening I attended the Denver Open Source User Group meeting where the Basic Concepts talk was on Appcelerator. Matt Quinlan (Twitter, Blog, LinkedIn) was the presenter. I arrived 10 minutes late, so I didn't hear any of the intro stuff. Below are my notes from the event.

The Appcelerator developers liked the "onclick" syntax, but found it was too limited to do everything they wanted. Rather than onclick, they use an on attribute. For example:

<div on="click then l:show.box">
Click me
<div>

"DOM Manipulation is JavaScript cruft."

Appcelerator allows you to implement the Observer pattern in the browser. In addition to allowing DOM elements to subscribe to messages, server-side objects (in any language) can subscribe as well. In Appcelerator syntax "l:" means local and "r:" means remote. The messages that are passed to the server are JSON and have payloads. JSON is more popular than XML because you can eval() it and create JavaScript objects from it. Appcelerator allows you to do Declarative Ajax. On the server-side, you can annotation Java and C# classes with @Service to subscribe to messages. In other languages (i.e. PHP), Javadoc-style comments are used.

Tagline: The seamless fusion of RIA and SOA.

Web Expression Language
Goal is to eliminate 90% of the JavaScript you write. Example syntax:

on="[condition] then [action]"

Conditions include DOM events (click, focus, blur, change, mouse events), key events (up, down, press), other (history, drag/drop, selected, resize, iPhone orient, sortXYZ), subscribe to custom message. Actions include Scriptaculous effects (show/hide, fade, move, drop, grow), set element value (static, dynamic, bind), set CSS class or attribute, execute custom JavaScript, publish custom message.

Now Matt is doing a demo on http://try.appcelerator.org. This site consists of a form that allows you to type in Appcelerator code and run it. 3 attributes can be added to any tag: draggable, droppable and resizeable.

Client-Side
Add simple tags to your HTML to inject RIA widgets. Add single property to existing HTML elements for dynamic behavior. Eclipse Plugin built on Aptana, but is generally targeted towards web developers moreso than business analysts (no drag and drop of widgets).

Server-Side
Server-side development done with your IDE of choices. Based on your server-side tehchnology platform. Easily create services using annotations.

App Command
The app command is similar to Rails' GEM command. Allows you to build scaffolding and deploy to cloud (AppEngine, Amazon S3). It also allows you to pulldown components from the main server and auto-updating.

Examples:

Appcelerator allows you to create prototypes easily by using a JavaScript file with mocks for the server-side objects. In the next version, you can "annotate" the UI and allow end-users to Ctrl+Click on elements and add feedback. For an example of this, see http://dev.appcelerator.com/pearson.

When starting with Appcelerator, you can start by crawling (including appcelerator.js for widgets) then move to walking (decouple server-side and client-side) and finally running (developing working prototypes with mocks for server-side).

"Let's face it, ASP, JSP, PHP and Ruby are just lipstick on CGI."

Posted in Open Source at Oct 07 2008, 07:08:19 PM MDT 5 Comments

Ajaxified Body

I've often wondered if it was possible to use Ajax to reload the main content of a web application without reloading the header, menu and footer. SiteMesh allows you to move these common elements to a decorator that gets wrapped around each page. Below is a diagram of how SiteMesh works.

SiteMesh

You can read the Introduction to SiteMesh article if you're interested in learning more about SiteMesh's basic features. By default, SiteMesh decorates text/html responses and ignores any other content type (e.g. image/gif). It also contains an <excludes> configuration element that allows you to turn off decoration when a URL matches a certain pattern. For example, the following allows you to disable decoration when "ajax=true" is passed in the URL.

<excludes>
    <pattern>**ajax=true</pattern>
</excludes>

To optimize the loading of an application so the common elements aren't loaded for each page, it should be possible to create an Ajaxified Body where the primary content area (PCA) of the site is loaded via Ajax rather than refreshing the whole page. The header, footer and navigation bar often stays the same from page-to-page, so it doesn't seem to make a whole lot of sense to load them each time the page loads. The image below shows the PCA (of an AppFuse Light application) as a grey square with a red border.

Ajaxified Body - AppFuse Light

Implementing an Ajaxified Body consists of the following steps:

  1. Adding SiteMesh and moving common elements to a decorator.
  2. Remove common elements from each individual page (if you're using includes).
  3. Configure SiteMesh so decoration is disabled when the requested URL contains "ajax=true".
  4. Write JavaScript that modifies all <a href=""> links (and buttons with onclick='location.href') in the PCA to have an onclick handler.
  5. The onclick handler should call a JavaScript function that loads the link's URL + ajax=true using XMLHttpRequest (XHR).
  6. Add XHR success handling to replace the PCA with the loaded content.
  7. Add XHR error handling to go to the URL normally when response.status != 200.
  8. Inspect the response HTML for <title> element and replace document.title if exists.
  9. Inspect the response HTML for <head> element and append to current if exists.
  10. Inspect the response HTML for <script> and <link> elements (JavaScript and CSS) and evaluate them if they exist.

As a proof of concept, I created a prototype using AppFuse Light (Prototype/Scriptaculous for Ajax). You can see a demo at the following URL. You can also download a patch or the source for this project.

http://demo.raibledesigns.com/ajaxifiedbody

Below are a number of things I discovered while writing this prototype:

  • The hardest part of implementing this seems to be coding the exceptions. It's possible you'll have some links with existing onclick handlers and you may have to disable "ajaxifying links" for those links.
  • A progress indicator is important or the page might load so fast that the user doesn't visually detect it changed. This can lead to a worse user experience because they don't see the flash of the blank page they're used to when a page load occurs.
  • While forms can be submitted via Ajax, there's no harm in leaving existing form behavior in place where the full site is reloaded after submitting a form.
  • If a particular page needs to change the common elements (header, menu, footer), it should be possible to do that with JavaScript after the PCA content loads.
  • If the success/error indicator is outside the PCA, it may need to be populated and displayed/hidden with JavaScript after the PCA loads.

I'm sure my implementation can be improved, but I'm also curious to see what you think of this idea. I know it's not revolutionary, but it's something I'm considering adding by default to AppFuse and AppFuse Light. Do any Ajax frameworks do something like this out-of-the-box?

Update: Thanks to everyone for the great feedback - keep it coming. I agree that adding history support is a must. I'll try to do that in the next day or two. This post has also been featured on Javalobby and Ajaxian.

Update 2: Added history support.

Posted in Java at Oct 03 2008, 02:33:09 PM MDT 19 Comments

Oktoberfest: Best. Vacation. Ever.

As mentioned earlier, a good friend (Miller) and I took a vacation to Oktoberfest last week. The flight over was brutal: Denver -> Newark (4 hour layover) -> Paris (2 hour layover) -> Munich. I was pretty disappointed to see "No Service" on my iPhone when we landed in France. This continued in Munich and I quickly decided connectivity wasn't necessary. After a 80 € cab ride from the airport, we arrived at our hotel around 1PM on Monday. We both woke up at 4AM on Sunday to start the journey, so we were pretty beat.

It didn't take us long to decide we had to suck it up and head to "The Tents" at Oktoberfest. We walked the 4 blocks in the rain and quickly ended up in the Armbrustschutzenzelt tent. The crowd was small and we found a table and enjoyed our first Liter.

Weather on Arrival in Munich Day 1 - First Tent

I won't go into details about how much fun we had during the week, except for these simple stats:

  • Made it into The Tents 5 days in a row
  • Mostly slept in until 2 or 4PM each day
  • No Hangovers (for me at least)

I've uploaded most of the pictures I took to an Oktoberfest 2008 set on Flickr. I would like to thank Peter and friends for being fabulous hosts and showing us a great time on Thursday night. Below is a video I took of what the festivities were like (yes, that is Bon Jovi):

If you ever get a chance to attend Oktoberfest, I highly recommend it.

Posted in General at Oct 01 2008, 10:37:49 PM MDT 5 Comments

My Oktoberfest Adventure Begins

A few months ago, a friend called me up and asked if I wanted to go to Oktoberfest. He said he had enough miles to cover both our tickets. I couldn't pass up the opportunity and hence we're leaving at the crack of dawn tomorrow for a week in Munich, Germany. We're not taking laptops and we don't plan on doing a whole lot more than having a great time.

Summerview @ Neuhausen/Munich

If you'd like to see what we're doing on our adventure, you can follow me on Twitter.

Posted in General at Sep 20 2008, 10:19:28 PM MDT 13 Comments

RE: How Open Source is Spring?

Peter Mularien has a very well written post titled How Open Source is Spring?: An Analytical Investigation:

This post is to expand on some of the thoughts I posted on the SpringSource Blog in response to Rod Johnson's excellent description of the SpringSource business model and its commitment to development of open source software.

Now that SpringSource has shown an ability to crank out new product releases on a seemingly weekly basis, I wanted to reflect on where Spring is positioned in the Java open source community, and how open the Spring Core project is to work done by the public.

The hypothesis of my experiment occurred to me when I happened to be reviewing Spring JIRA assignments one day. I was curious whether, following the bug assignments, the majority of development on the "Spring Core" projects (including Spring MVC and what we would consider "classic Spring") is performed solely by SpringSource employees.

Peter's post is near and dear to me because I'm doing a What's coming in Spring 3.0 talk at the Colorado Software Summit in October. The only information I was able to find on Spring 3.0 is from random blog posts and Juergen's presentation. When I give talks about technologies, I prefer to dig in and try them before talking about it. With Spring 3.0's source code nowhere to be found, this is very difficult to do.

I really hope Spring 3.0 becomes available in early October. If it does, I hope to upgrade AppFuse, AppFuse Light and Spring Kickstart. If it doesn't, my talk will most likely be a regurgitation of what Juergen's slides have and that's just not right.

Posted in Java at Sep 19 2008, 09:54:48 AM MDT 14 Comments

Upgrading Hibernate to 3.4.0 and AppFuse for Tapestry 5

Last night I spent an hour upgrading AppFuse to Hibernate 3.4.0.GA. I tried the same thing a week ago, but failed miserably. When Hibernate Core Modules (3.3) (a Maven dependency howto) showed up on the Hibernate blog, I was re-inspired. I discovered some interesting things along the way (at least in my setup).

You need to use JBoss's Maven Repository
The latest Hibernate releases aren't in the central Maven repo yet. If they're not in there two weeks after the release, I doubt they'll be there anytime soon. Best to plan on adding http://repository.jboss.com/maven2 as a permanent repository. As a bonus, you can remove http://download.java.net/maven/2 since JTA is in JBoss's repo.

Javassist is not an optional dependency
If I remove the Javassist dependency, here's the error I get:

java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter

Seems reasonable right? What if I add in the dependency on Hibernate's cglib instead?

java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter

OK, so apparently you can't switch between Javassist and hibernate-cglib-repack as stated in Hibernate's Maven dependency howto. Of course, I do believe their instructions are correct, they just don't work in my setup. Versions I'm using: hibernate-core-3.3.1.GA and hibernate-annotations-3.4.0.GA.

Not including SLF4J is a bad idea
If you don't include a dependency on SLF4J (and you're using Spring), you get a nice cryptic error message.

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class 
[org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean]: 
Constructor threw exception; nested exception is java.lang.NoClassDefFoundError
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:115)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:61)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:877)
        ... 48 more
Caused by: java.lang.NoClassDefFoundError
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:164)
        at org.springframework.orm.hibernate3.LocalSessionFactoryBean.class$(LocalSessionFactoryBean.java:174)
        at org.springframework.orm.hibernate3.LocalSessionFactoryBean.(LocalSessionFactoryBean.java:174)
        at org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean.(AnnotationSessionFactoryBean.java:64)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:100)

Hibernate's JPA now uses PersistenceException instead of EntityExistsException
In previous releases, Hibernate's ConstraintViolationException was wrapped in a javax.persistence.EntityExistsException. In Hibernate's EntityManager 3.4.0.GA, it's wrapped in a javax.persistence.PersistenceException.

Of course, these errors could be caused by Spring or Maven, but my hunch is they're more related to Hibernate and it's new more modular dependencies. You can view the full changeset for upgrading Hibernate 3.2.6.ga to 3.3.1.GA via FishEye.

Tapestry 5 version of AppFuse
In other AppFuse-related news, Serge Eby has created a Tapestry 5 version of AppFuse. You can see his alpha-level work in Google Code's tapestry5-appfuse project. I haven't had a chance to take a look at Serge's work yet, but I'm eager to do so. Hopefully we can get it back into the main project sooner than later. As far as Wicket and Stripes support, I haven't forgot about those - just having trouble finding the time and motivation to do the work.

Posted in Java at Sep 17 2008, 09:35:45 AM MDT 12 Comments

[DJUG] Ship it! and Distributed Teams by Jared Richardson

Jared's first book is called Ship it! and it's been wildly successful (translated into several different languages). During the first hour, Jared talked about his book and practices defined in it.

Ship it! is an attempt to talk about the holistic process of software development: techniques, infrastructure and process. For Techniques, there's a Technical Lead, The List, Code Reviews, Code Change Notifier and Daily Meetings. Infrastructure involves Version Control, Script Builds, Continuous Builds, Track Issues, Track Features and Writing/Running Tests. Process is Propose System Objects -> Propose Interfaces -> Connect Interfaces -> Add Functions -> Refactor, Refine, Repeat.

Martin Fowler's definition of Architecture: anything that is difficult to change later.

The majority of Jared's talk was about implementing TDD, continuous integration and many other things driven by audience questions. I didn't take notes because it was more of a conversation than a presentation. Jared's second talk was on Distributed Teams and my notes from this talk are below.

Agile is not XP or Scrum, those are implementations of Agile. The Manifesto for Agile Software Development is the interface for Agile Development. It contains the following principles:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Custom collaboration over contract negotiation
  • Responding to change over following a plan

To re-word these principles: Agility is...

  • People interacting
  • Software that runs
  • Fast Feedback
  • Frequent Change

Scrum principles are often not about developing software, they're about making people talk. The important thing is to get people in the habit of communicating. The best way to get people interacting is to do Daily meetings. One to two minutes per person. Same time. Three questions (what did you do yesterday, what today and any blockers?). Scrum style.

How do you do a daily meetings when you're remote? Conference calls are the most common, but don't let anyone local dial-in or they will get in the habit of doing it. Video is best, but it's often expensive to setup. One good strategy for daily meetings is IM. The beauty of this is that there's a transcript of the daily meeting that others can read. Conference calls are usually bad b/c you can only hear the guys that are close to the phone. It's even worse when the speaker phone is a cell phone. Whatever you do, you should never skip the daily meetings.

Peer Code Reviews are another good way to get people interacting. The first rule of code reviews is that anyone can refuse to do one. If you're not doing code reviews or pair programming, you'll end up with inefficiencies and broken windows. Address the behavior head-on. Peer Code Reviews remotely: e-mail, Skype headset, IM, VNC or SubEthaEdit (works awesome). NetBeans (collaboration module) and Eclipse (communication framework) have plugins that allow SubEthaEdit-style functionality.

How do you keep software running? Continuous integration and automated testing. Keep a list of atomic features. Prioritize. Don't let people work for 2 months. All tasks should be broken down into small chunks. Tests are a good way to communicate. Don't tell me you're done because you think you're done. Show me a test that proves you're done. Don't allow broken windows. Broken windows give the impression that no one cares and more bugs happen because of this. Continuous integration is essential for remote teams.

What's the best to get fast feedback? Fast compiles, fast tests, running CI 24/7. Another good strategy is the The List. Make sure and get feedback from your Tech Lead and from your Customers (they like to be involved). If you have a list that doesn't change after 6 weeks, you're working for a team who's list is dead.

There's nothing wrong with documentation and a plan, but its the things on the left that are more important. Offsite teams should have a single tech lead. Writing Tests might be better than writing requirements. When the tests pass, you'll get what you asked for. If you care about the design, write unit tests. If you don't care about how it looks, but want it to work, use integration/MCT for functional tests. Don't separate development and QA. To deal with time zones, make the tech lead stay up and rotate. For documentation, DRY out your Docs. Generate documentation instead of manually creating them.

"Docs are a cache ... flush often"

For Customer Feedback, have the tech lead translate.

I really enjoyed Jared's talks. The first one (on Ship it!) didn't provide much new information for me, but that's likely because I've worked on several open source projects and I've tried to bring those procedures and practices into any company I've worked at. I'm very grateful that LinkedIn does a good job with continuous integration (Hudson), bug tracking (JIRA) and documentation/planning (Confluence).

The 2nd talk on Distributed Teams was enjoyable because I'm in the heart of that - managing a remote team in Denver. We've experienced the awful conference calls where you can't hear anything or when we're on speaker on a cell phone. We do have all the video conferencing equipment purchased (10K worth) and sitting in our office, but haven't set it up because we're waiting on IT to setup a persistent VPN (which is a requirement to make it work). I've had some communications issues with my boss (mostly related to him not knowing what we're working on). We do daily stand-ups and use many of the practices recommended by Jared. One thing I think we can do to increase communication with headquarters is to start doing our daily meetings over IM and posting the transcript to a wiki page.

If you get a chance to hear Jared speak, I highly recommend it. He has a style that's very conversational and fun to listen to. You feel like you're a part of a self-help group rather than listening to someone preach about how you should be developing software.

Posted in Java at Sep 10 2008, 09:56:52 PM MDT 4 Comments