Saturday, August 21, 2010

Off-line Wiki - using TWiki with Subversion

As part of my personal productivity setup I use a wiki, and for a while now I've wanted to be able to use it off-line as well - on a laptop without Internet connection.

I finally took the plunge, and converted my previous on-line-only TWiki into an on-line/off-line setup based on FosWiki. It was remarkably easy. At least, after I finally decided not to use any of the fancy alternatives.

There is a surprisingly large number of experimental wikis in this area, but most do not look very usable or stable. For example I looked at Ikiwiki and Gitit, two Git-based wikis. Both looked interesting but it turned out that neither supports Windows. One of my requirements is to run it off-line on a Windows laptop. I also looked at various extensions for TWiki and FosWiki that are supposed to support off-line work, such as MercurialContrib, Subversive and SubversionStoreContrib. In the end I decided to focus on Subversion (instead of Git and Mercurial) because subversion is simpler. When I tried out SubversionStoreContrib for FosWiki it turned out to be incomplete and didn't work. 

In the end I selected the following straightforward setup:
  • First I migrated my on-line TWiki to FosWiki, because FosWiki is easy to install on Windows and more up to date than my aging TWiki setup, while still 100% compatible with the TWiki page format. This will allow me to create off-line copies on various Windows environments easily.
  • I imported the pages from the Main web into Subversion, but only the ones I'd written myself. All system pages (such as WebPreferences.txt) were added to the ignore list, as well as all files ending in ,v and .lease. I did the same for the attachments in pub/Main. 
  • Next I created two simple shell scripts to update and commit the local svn workspace from/to the repository. These scripts add new files to the repository where needed. They can be called from links on the main WebHome page.
  • For the off-line setup I installed FosWiki to my laptop and used TortoiseSVN to check out the page and attachment parts of the repository into the right FosWiki directories. 
  • The main trick here is to leave the normal TWiki/FosWiki RCS-based store unchanged, but simply add *,v to the SVN ignore list.
  • The result is that most use cases are covered both on-line and off-line; editing, updating, committing and adding new files. I haven't covered deleting and renaming files yet in the on-line scripts because those are pretty rarely used, and can be done easily off-line using TortoiseSVN.
  • Another result that is not very elegant is that because the RCS ,v files are not in SVN they are basically worthless and the history view in the wiki itself will be incorrect. I simply chose to ignore this, and when I want to see the page history (pretty rare again) I can do so using the SVN tools.
All in all I'm very satisfied with this setup, it does what I wanted it to, and is suitable for use by one or more users with technical / Subversion experience. It seems less suitable for very large user groups and non-technical users.

If you're interested let me know in the comments and I can supply more details (scripts, ignore lists etc.)

Monday, May 31, 2010

Lean architect

These are lean times. I'm probably not the only architect who's starving, forced to unsatisfying gnawing on TOGAF books, hoping for better times. Some say this is the perfect time to invest, expand, learn, grow and prepare. I say no. I'm a lean and mean architecture machine already. Bring 'em on, those challenging cutting edge projects. Yeah!

Anyway, I've renamed my blog from Time Investment to Lean Architect, and also moved it to a new URL. Could be that the old URL on my reiz.nl domain wasn't indexed very well because Google understands country TLDs to contain content in local languages only. Could also be that I'll be writing a bit about Lean Architecture. Could be.

Saturday, August 8, 2009

Grails and Groovy - too dynamic for the real world

After using Groovy and Grails on some bigger projects for months I've come to reconsider some of the advantages of this platform. In particular the fact that it's a dynamically typed language.

If you come from a statically typed Java background like I did, it might not even be very obvious in the beginning what dynamic typing implies here. In particular because Groovy is mostly a super-set of Java. In Groovy you can still type "Map map=new HashMap();" and it will work. A bit later you will get lazy and start typing "def map=[:]", which means the same, works the same and is a bit shorter to type. At that point I simply thought "score one for Groovy against Java" and continued.

The downside is that there is almost no compile-time checking in Groovy. This follows directly from some of its features:
  • Methods and fields can be added to objects at run time
  • The type of variables can change at run time
  • Groovy is very forgiving of null values and exceptions, in many cases continuing silently instead of aborting
This means that many of the compile-time checks of statically typed languages are impossible, but also that IDEs like Eclipse cannot provide many of the context-sensitive completion features that we're used to, and that many errors are flagged only at run-time when that particular line of code is reached.

For small single-developer projects with a prototyping/scripting nature this is likely not an issue, in particular when the developer has a lot of experience with Groovy and/or other scripting languages. For larger multi-developer projects the picture changes, even more so when developer experience level varies. In longer-running multi-developer projects maintainability can become a huge issue. Unit tests can help, but are notoriously difficult and time-consuming to create for web applications and applications that interact with many external systems.

When unit tests are lacking and compile-time checks are absent, the result can be trial-and-error programming and a very fragile code base. One example is refactoring, an important part of agile programming. In Java it's normal to refactor constantly, e.g. moving and renaming classes. The IDE will do all the grunt work of renaming corresponding references, and the compiler will help catch any resulting bugs. In Groovy this is not possible; the IDE cannot do the grunt work, so refactoring will be a manual process. Any missed references will not be found at that time, but only when that particular line of code is reached at run-time. I recently started realizing that Groovy offers a very bad trade-off for larger projects.

That you can type "def map=[:]" instead of "Map map=new HashMap();" is nice, and saves maybe 10 seconds at code-writing time. But if that means that hours are lost hunting bugs that would simply not occur in statically typed languages, hours lost searching for what are basically syntactic errors, then the downside becomes obvious in a very painful way.

Luckily this sad tale has a happy ending. For the particular projects that we're running we will simply continue using Grails - its advantages still stand. We will also still use Groovy for simple code snippets and scripting. For anything more complicated we will create Java classes and call them from Groovy. This is fully supported by Grails, and offers a best-of-both worlds escape.

Friday, June 5, 2009

Grails script runner featuring dependency on other projects

One of my favorite uses for Grails is scripting, as I've stated before. However, I stumbled over re-using code from other Grails projects in Eclipse.

With Java projects I'm used to interdependencies - for example larger projects are split up into sub-projects. All external libraries are put into the 'Lib' sub-project and can be used from the others, which makes the other projects look cleaner in Eclipse. To do this you simply use the Eclipse build path for the Eclipse compiler, and build.xml for Ant-driven build and deployment.

With Grails this isn't so straight-forward. In particular because running scripts does not go through build.xml at all. To influence the Eclipse compiler you can still use the build path, and include other Eclipse projects there. To influence what happens when you run a script from the command line you have to use a custom script runner. This isn't so bad because for some other features (enabling GORM) you have to use a custom script runner anyway.

An example is available here: ScriptRunner.groovy. Put it in your project scripts folder together with the scripts you want to run, and invoke it as grails [env] script-runner OtherScript [parameters..]

The magic for this particular purpose is in overrideCompilerPaths, which is mostly copied from _GrailsCompile.groovy in the Grails distribution but has the added line:

src(path: "${basedir}/../OtherProject/src/groovy") // added path

You'll have to add a line for each folder of each project you want to use code from. It isn't very elegant, so please let me know if you've found a better way to do this.

NB If you also use the Grails web app in this project, you'll also have to create a script like this: RunXApp.groovy, and instead of grails run-app use grails run-x-app.

It's a bit of a hassle, but once it's smoothed out you have a scripting environment where:
  • You can map domain classes to the database using only a few lines of code (using GORM and the data source provided by Grails you only have to add domain classes yourself).
  • You can use all the power of Grails, Groovy, Hibernate and Java from your scripts with zero extra setup.
  • You have a dynamically generated web app to view and edit your domain classes at virtually zero extra cost (you only have to run create-controller for each domain class and replace the controller body with def scaffold = default).
Neat.