Friday, 4 June 2010

Perforce and Subversion - a short story of a new-found love

Before my previous project I used CVS and SVN and obviously preferred SVN. In my eyes it wasn't maybe the best thing ever, but I was reasonably confident user, knew how to merge and, more importantly, I knew how to force it to cooperate when I screwed my local .svn folders. I liked it.


First few weeks after joining, working with Perforce was a major pain. Ideas of client specs, changelists, "opening for edit", creating branches etc. - all that was new, and not exactly friendly for ex-svn user. I simply didn't know how to use it. I complained a lot, I was completely confused (and rather complicated build process around it specific to the project didn't help at all).

However, recently I switched jobs, and after first shock of learning that we're still using CVS, I realized that the migration I'd love to see is not to SVN. It's to perforce.


What has changed? I have become much more comfortable with P4 and I realized that it really supports productivity and is more powerful than SVN. Bear in mind that last time I used SVN was not this recently and some of the things I'll mention here may be in SVN - but I don't think they were there when I was using it.


  • The first great strength of P4, especially when working in a really big team and not much of code ownership (i.e. everybody touches everything) is merging. The fact that P4 can track exactly which changes were already integrated (merged) and which not makes it sooo easy to work on branch/trunk and only merge as and when necessary. And unless there are conflicts the merge task of quite big branch can be literally 2 mins. And - again - because P4 tracks what you already merged and what not, you could merge every day and barely notice you're working on a branch. you can bring changes between branch and trunk back and forth and unless you're (rather stupidly) trying to manually merge files - it's absolutely unbeatable. Of course working on branches will always give some overhead - but I feel that managing this with P4 is way easier than with SVN.

  • I also loved 3-way diffs (and even though I'm sure that could be done on every version control system, somehow I first saw it when using P4).

  • I loved changelists. I now can barely imagine living without them in SVN. Perhaps it's because I sometimes have some "side-work" that is of very low priority, but being able to keep it on a seperate changelist until I'm (finally) able to commit is really nice. I don't have to check with each commit what files I want to submit now and which ones later - or not at all. BTW latest P4 has idea of "shelving changes" so there isn't even a worry that if the machine dies, you lose your work.

  • I absolutely love the fact that it doesn't store any additional information in my code folders and that it's so easy to revert if I accidentally remove a directory.

  • Despite my initial reservations about "open for edit" sometimes it actually was really useful - for example before doing a major refactoring and deleting/renaming some classes I could check if by any chance someone else is working on them and talk to them, maybe postpone my refactoring a bit so that we don't have to merge. It's not a lock, multiple people can have a file open for edit - it's just a marker. The only drawback is that the first time you start editing a file Eclipse would hang for a fraction of second while opening the file for edit - but you can really live with that.

  • Absolutely fantastic support for viewing history, with my favourite "time line view" which is basically "blame on steroids". You can see whole history (or selected range) of the file with deleted lines stroked out, additions and modifications clearly marked, with author names alongside, and easy access to details of the commit (when, comment etc.).


What I didn't like?



  • That you need to remember to explicitly add files for add - in theory you have to do that in svn as well but somehow SVN clients are always much better in detecting new files. The solution here is to make Eclipse always open for Add when you create a file

  • Eclipse plugin for P4 is nowhere near SVN plugin - but to be honest, it didn't take me very long to get used to having P4Win constantly open on second screen and I didn't miss direct Eclipse integration this much. It would have been much worse if I only had something like Tortoise.

  • Creating of labels and branches could be easier. Once you grasp the concept and understand how it works - the procedure is not this bad, still I think it could be a bit more user-friendly (perhaps all it needs is a nicer wizard in P4Win!).



Overall, I'd say that yes, perforce has a learning curve (in my case from "omg, wtf is that?!" to "it's actually kind of nice" it was about 2 months), but now given choice I'd go for Perforce without a second of hesitation. Unfortunately the fact that is not free (or perhaps should say: is very expensive) doesn't help - but I just found out that you can get Perforce for free for 2 devs - so you can always try it.


I hope that in near future I'll get a chance to try out Git which gets a lot of praise - however, I'm slightly worried by the lack of something in the class of P4Win/TortoiseSVN. Perhaps it's just a matter of time.

Sunday, 2 May 2010

Useful Eclipse plugins (1) - Grep console

I hope this is just the first in series of posts regarding useful Eclipse plugins - there are so many of them. Quite a lot are widely known - here I want to concentrate on the ones that I wasn't aware of for quite a long time.

Grep Console is one of them - a very useful plugin as, like in my current project, the amount of log output is enormous. It's easy to miss what you're looking for... well, not any more.

Here are my settings for this plugin (unfortunately the line with settings cannot be split!):

#Fri Jan 22 16:46:53 GMT 2010
eclipse.preferences.version=1
settings=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><expressions><expression grepExpression\="^(.*Exception\:|.*Caused by\:|\\s*at).*$" name\="EXCEPTION"><style background\="ff80c0" foreground\="000000"/><style/></expression><expression grepExpression\=".*ERROR.*" name\="ERROR"><style background\="ff0000"/></expression><expression grepExpression\=".*WARN.*" name\="WARNING"><style background\="ff8040"/></expression><expression enabled\="false" grepExpression\="^.*INFO .*$" name\="INFO"><style foreground\="808080"/></expression><expression grepExpression\="^.*DEBUG.*$" name\="DEBUG"><style foreground\="c0c0c0"/></expression><expression enabled\="false" grepExpression\="^[^\\d].*$" name\="NONLOG"><style foreground\="c0c0c0"/></expression><expression grepExpression\="^\\t.*$" name\="TAB"><style foreground\="000000"/></expression><expression grepExpression\="^Hibernate.*$" name\="HIBERNATE"><style foreground\="c0c0c0"/></expression></expressions>

It needs to be placed in %ECLIPSE_WORKSPACE%\.metadata\.plugins\org.eclipse.core.runtime\com.musgit.eclipse.grepconsole.prefs file

Saturday, 20 February 2010

Google collections ordering and filtering

Recently on my project I faced a task that could be simplified to a following problem:
I have a list of objects of class Foo, which has a field bar which is a String. I get a list of Strings X and the task is:
a) from the set of objects Foo I need to filter out anything for which the bar field is not equal to one of the Strings on the list X
b) the order of objects Foo according to their bar value must match the order of Strings on the list X

Google Collections came to the rescue allowing me to write a nice and concise (and bug-free!) code in a matter of minutes. Here is how it looked like:


import java.util.Collection;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Ordering;

public class Bazz {

private final static class Foo {
private String bar;

public String getBar() {
return bar;
}
}

/**
* @param bars
* Reference bar List to define filter and sorting
* @param foos
* List of object that needs to be filtered and sorted
* @return Filtered and sorted Foos
*/
public List filterAndSort(final List bars, final List foos) {

Collection filtered = Collections2.filter(foos, new Predicate() {
public boolean apply(Foo foo) {
return bars.contains(foo.getBar());
}
});
Ordering fooOrdering = Ordering.explicit(bars).onResultOf(new Function() {
public String apply(Foo foo) {
return foo.getBar();
}
});
return fooOrdering.sortedCopy(filtered);
}
}



The only thing I'm currently wondering about is how would it look in a functional language like Scala for which the book is already in the reading queue...

Saturday, 23 January 2010

Attached properties in Silverlight

I'm pleasantly surprised by the existence of attached properties in Silverlight. They provide a neat point of extension for properties in child-parent relation between components. It may have been better if they called it "metadata properties" or similar (it would certainly bring my mind into correct direction) though. The example in the book I'm reading is not actually very impressive (namely Grid.Row, for which probably a couple of other options exist) but I can see how the mechanism behind this may be useful when desiging my own app.


The idea is simple - when placing an element in XAML you can place an attribute, say Grid.Row="value". Internally, it's going to get translated into a static call to Grid.SetRow(caller, value), and in this particular case in turn will call caller.SetValue(Grid.RowProperty, value). Parent object then can call getValue on the child to get the value. Nice decoupling and no need to implement any special methods on the classes that are going to be contained in the parent. The child doesn't even have to be aware of what properties are set and how are they going to be used.

Tuesday, 22 December 2009

Logger template for Eclipse

As always, my blog dies rather quickly with lack of posts. Main reason for that is lack of time to write a nice, long blog entry. I was recently advised by a colleague that a good place to start is to jot down things that are easily forgotten and require googling later on.
So here comes the first one: how to create a template that will save me a bit of typing every time I need to add a logger to a class.

Preferences -> java -> editor -> templates, "new...".

name: log
description: Logger definition
context: java
automatically insert: yes
pattern:
private static final ${typeLogger:newType(org.slf4j.Logger)}
${name:newName(log)} =
${typeFactory:newType(org.slf4j.LoggerFactory)}.getLogger(${enclosing_type}.class);


All that you need to type in your code afterwards is "log" & ctrl+space. Of course it will work just as nicely with any other log library.

Sunday, 6 September 2009

Simplest HTTPService connection on Flex4

I tried to follow one of the examples in "Getting Started with Flex 3" (create Flickr browser) and faced a couple of issues. This is a working solution, however instead of Flickr RSS it is using Picasa and is using some Flex 4-specific stuff (mainly for data-access). Flickr at the moment is sending an RSS with one of the tags invalid for Flex 4 XML parser (or to be more precise: you cannot generate AS classes from it).


The mxml starts as in the original example (except for colour values, that is):



<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
minWidth="1024" minHeight="768"
xmlns:photoservice="services.photoservice.*"
backgroundGradientColors="[#BB78D7, #75637C]">

The next part is a bit simpler than in the original example, since we have nice service generation in Flex 4 (more about this later).



<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.controls.Alert;

import services.photoservice.PhotoService;
import mx.rpc.AsyncToken;
import mx.rpc.CallResponder;
import services.photoservice.PicasaPhotos;

private var callResponder:CallResponder;

protected function search():void
{
fetchResult.token = photoService.fetch("rss","photo","en_US");
}

protected function tileList_creationCompleteHandler(event:FlexEvent):void
{
fetchResult.token = photoService.fetch("rss","photo","en_US");
}

]]>
</fx:Script>

Last part is the actual design part, which also is mostly as in original example, except for the service-related part:



<mx:HBox>
<mx:Label text="Picasa tags or search terms:"/>
<mx:Text id="searchTerms" width="150"/>
<s:Button label="Search" click="search()"/>
</mx:HBox>

<mx:TileList width="100%" height="100%" id="tileList"
creationComplete="tileList_creationCompleteHandler(event)"
dataProvider="{fetchResult.lastResult.item}" labelField="title"
itemRenderer="PicasaThumbnail">
</mx:TileList>

<fx:Declarations>
<s:CallResponder id="fetchResult"/>
<photoservice:PhotoService id="photoService" fault="Alert.show(event.fault.faultString)" showBusyCursor="true" />
</fx:Declarations>
</mx:Application>

The PicasaThumbnail.mxml class looks as follows:



<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
width="250" height="250"
paddingBottom="10" paddingLeft="15" paddingRight="15" paddingTop="10"
alpha="1"
>

<mx:Image width="200" height="200" source="{data.enclosure.url}" alpha="1"/>
<mx:Text text="{data.title}"/>

</mx:VBox>


The main reason all this works is a very nice addition coming in Flash Builder 4 - Data/Services wizard. It's enough to select menu Data -> Connect to HTTP... and on presented wizard provide a few details (URL, required parameters, service name - and that's it). This will generate a service class. After this is done you can "Configure return type" - the tool will connect to your service, parse example XML and try to prepare a set of classes representing it nicely. Works very well and allows all the nice tools of Eclipse (autocompletion) to be much more helpful.


Overall I am very pleasantly surprised how easy the whole task was and I can see great potential to simplify my work with the data wizard tool.

Flex4, here I come

It's time to resurrect this blog since I've started learning Flex4 and I hope my journey from-Java-to-Flex4 may be helpful for all those other lost souls out there.
My first impression is that I may actually like it - but Flash Builder system requirements are even worse than those of Eclipse 3.5, meaning I probably should get a new laptop. Oh dear...