VSoft Technologies Blogs

rss

VSoft Technologies Blogs - posts about our products and software development.


Hybrid Version Control

Distributed verison control systems are gaining in usage and popularity, but many organisations still use traditional centralised VCSs like Subversion and Visual Source Safe. Recently I've been using a hybrid setup and getting many of the benefits of a DVCS without needing to move the whole team to a new VCS platform.
 
When I started with VSoft a few months back my first chunk of work was to create Mercurial actions for the upcoming FinalBuilder 7. It was the first time I'd used a DVCS and after the initial shock I became quite fond of it.
 
Internally we use a CVCS - Surround SCM. If you've never used Surround you can think of it as VSS done right. It uses similar concepts and abstractions but without all the pain and frustration. We're considering moving to a DVCS but haven't yet worked out if the increased flexibility is worth the extra overhead for our relatively small dev team.
 
After getting to know Mercurial though, I knew what I was missing out on. Primarily for me that was version control of my local changes. This is becoming more important as FinalBulder 7 gets closer to completion and breaking the build becomes a bigger deal. I also like being able to easily clone and sync my repositories locally as a basic backup strategy.
 
The setup I've come up with couldn't be simpler. If I'm going to work on a VS.NET solution I will:
  • check out the solution from Surround
  • hg init the solution directory to create a repository
  • hg commit -A which adds/removes all file changes to the repository
  • work locally, committing whenever I feel like it
  • when the solution is in a state where it won't break the build, check it in to Surround
 
To make things easier I've set up this alias in my Mercurial.ini:
[alias]
cam = commit -A -m
 
So to commit I just hg cam "commit message".
 
Recently I started checking my .hg directory into Surround as well. That allows me to maintain the history of all my local commits, without cluttering up the Surround check-in logs.
 

Caveats

There's some things to be aware of when using a hyrbid system like this. While you could still use Mercurial for merging work from different developers it is much more complex than in a pure DVCS setup. I'll leave it to you to work out the details: it's not something I plan on ever doing. 
 
If you're checking your .hg folder in to your CVCS you need to be careful that it doesn't become corrupted through concurrent updates/merging. Of course if it does become corrupted you don't lose much by deleting and recreating it, because the check-in history for your major changes is in the CVCS's check-in logs.
 

Other uses for Mercurial

Because Mercurial repositories are so easy to create I've started using them for all sorts of things. For example, at home I have a perl script that runs nightly and exports the contents of my Wordpress blogs to XML. Previously I included the date in the filename and ended up with (literally) hundreds of files in my backup directory. 
 
Now I've set up a Mercurial repository, removed the date component from the filename and have my backup script commit after it downloads the latest version. The directory is now a lot cleaner as well as being smaller, because Mercurial only stores the changes between each night's backup.
 

Further reading

While running a hybrid system doesn't give you all the advantages of a pure DVCS it is a major improvement over a plain CVCS. It also allows you and your team to get comfortable with the DVCS methodology before moving away from CVCS completely.
 
For more information on Mercurial, see:

  


Using interfaces and reference counting in Delphi works great for the most part. Its a feature I use a lot, I'm a big fan of using interfaces to tightly control what parts of a class a consumer has access to. But, there is one big achillies heel with reference counting in Delphi, you cannot keep circular references, at least not easily, without causing memory leaks.

Consider this trivial example :

 
IChild = interface;
IParent = interface
['{62DC70E1-8D82-4012-BF01-452EB0F7F45A}']
  procedure AddChild(const AChild : IChild);
end;

IChild = interface
['{E1DB1DA0-55D6-408E-8143-072CA433412D}']
end;

TParent = class( TInterfacedObject, IParent )
private
  FChild : IChild;
  procedure AddChild(const AChild : IChild);
public
  destructor Destroy; override;
end;

TChild = class( TInterfacedObject, IChild )
private
  FParent : IParent;
public
  constructor Create( AParent : IParent );
  destructor Destroy; override;
end;

implementation
	
constructor TChild.Create(AParent: IParent);
begin
  inherited Create;
  FParent := AParent;
  AParent.AddChild(Self);
end;

destructor TChild.Destroy;
begin
  FParent := nil;
  inherited;
end;
	
procedure TParent.AddChild(const AChild: IChild);
begin
  FChild := AChild;
end;

destructor TParent.Destroy;
begin
  if Assigned( FChild ) then
    FChild := nil;
  inherited;
end;

procedure Test;
var 
  MyParent : IParent;
  MyChild : IChild;
begin
  MyParent := TParent.Create;
  MyChild := TChild.Create(MyParent);
  MyChild := nil;
  MyParent := nil;
end;

Both parent and child are now orphaned and we have no reference to them and no way to free them! Ideally, the parent would control the life of the child, but the child would not control the life parent.

So how can we get around this? Well a technique that I have used a lot in the past is to not hold a reference to the parent in the child, but rather just a pointer to the parent.

 
TChild = class(TInterfacedObject,IChild) 
private 
  FParent : Pointer; 
  ... 
end;

constructor TChild.Create(AParent : IParent); 
begin 
	FParent := Pointer(AParent); 
end; 
function TChild.GetParent : IParent; 
begin 
  result := IParent(FParent); // if the parent has been released the we are passing out a bad reference! 
                              // a nil reference would be preferable as it's easy to check. 
end; 

This works well for the most part, but it does have the potential for access voilations if you do not understand or at least know how the child is referencing the parent.

For example :

 
var child : IChild; 
parent : IParent 
begin 
  parent := TParent.Create; 
  child := TChild.Create(parent): 
  parent := nil; //parent will now be freed, since nothing has a reference to it.
  ....... 
  parent := child.GetParent; //kaboom 
end; 

One of my collegues kindly pointed out that C# doesn't suffer from this problem and he uses circular references all the time without even thinking about it. While discussing this, he mentioned the WeakReference class in .NET. It basically allows you to hold a reference to a object without affecting it's lifecycle (ie, not influencing when it will be garbage collected). I figured there must be a way to do this in Delphi, and so set about creating a WeakReference class for Delphi.

I wasn't able to find a reliable way to do this with any old TInterfacedObject descendant, however by creating a TWeakReferencedObject class and the use of generics on Delphi 2010 I did manage to implement something that works well and is not too cumbersome. Lets take a look at our Child/Parent example using a weak reference.

The important part in this is the use of the WeakReference to the parent in the Child class. So instead of declaring

FParent : IParent;

we have

FParent : IWeakReference<IParent>;

We create it using

FParent := TWeakReference<IParent>.Create(parent); //value is an IParent instance

This is how our TChild.GetParent /SetParent methods look now :

 
function TChild.GetParent: IParent; 
begin 
  if FParent <> nil then 
    result := FParent.Data as IParent 
  else 
    result := nil; 
end; 

procedure TChild.SetParent(const value: IParent); 
begin 
  if (FParent <> nil) and FParent.IsAlive then 
    FParent.Data.RemoveChild(Self); 
  FParent := nil; 
  if value <> nil then 
    FParent := TWeakReference<IParent>.Create(value); 
end; 

Note the use of the IsAlive property on our weak reference, this tells us whether the referenced object is still available, and provides a safe way to get a concrete reference to the parent.

I still think this is something that could be solved in a better way by the delphi compiler/vcl guys n girls.

Hopefully someone will find this useful, the code is available for download here - Updated Sunday 28/3/2010

Feedback welcolme, I'm about to start making extensive use of this code, so if you see any holes then please do let me know!


No more flash ads, ever.


Yesterday, I stopped all of our flash based ad campaigns... forever.

In late 2008, we started a large campaign which introduced our first flash ads. We had some fun making these and received mixed responses - some outrage, some love. But overall, I feel that just by using flash ads to communicate, we were becoming a little too closely affiliated with the many scam like flash ads. You know the ones, those before-and-after-weight-loss-body-shots.

Advertising was once a powerful method of communicating, but no more. Thanks to the lowest common denominators in advertising, everyone suffers. Ad blockers are the proof. When the web is filled with before-and-after-weight-loss-body-shots, we block every ad. The 1% of useful information from advertising is not worth the 99% of junk!

So what to do? How can we communicate with those who might want what we've got, without the medium implying we're offering cruft?

Two ways: education and community involvement.

From now on, these two methods will form the pillars of our overall marketing. A reply to a question on stackoverflow. A response to a customer on twitter. It's how FinalBuilder got it's start, before we could afford ad space, and now we're coming back to it because it's authentic and meaningful.

Oh, and we have a few other, more exciting plans to get involved in the community. Watch this space.

FinalBuilder Roadmap for 2010

We don't usually have a published roadmap. I generally don't like to talk too much about the next version until I have something to show (ie when we are close to beta), however it's been a while since we release FB6 and some customers have asked what our plans are.

I will say that FinalBuilder and FinalBuilder Server are being actively worked on. Below is just a general outline of what we are up to :

FinalBuilder 7.0:

1) Full Unicode support. This is something that we have been working on for the last year. It meant finding replacements for many libraries and components we use, the biggest of which was the Active Scripting support. We ended up having to write our own active scripting library as the old one was impossible to move forward with (the vendor has long since disappeared). This work is mostly completed.

2) A new IDE - with the ability to open multiple projects, and hopefully be able to step into included projects. This required some major re-architecting of the core and the IDE and that is something we are still working on.

3) General enhancements to existing actions and some new actions. As usual, we have a long todo list to keep us busy.

FinalBuilder Server 7.0

FinalBuilder Server 7.0 will be a revision of the FBServer 6.0 code base. (Note that this has changed from my forum post in Nov. due to resourcing issues).

1) Support for more version control triggers. MKS, Clearcase and possibly Git have been identified as popular targets.

2) Enhancements to the user interface.. cleaning up html, more use of client side script to reduce postbacks.

3) Performance enhancements where possible.

We will also be looking at feature requests to see what else we can implement, but many will be implemented in a future product (see below).

FinalBuilder Server vNext + 1

Along side the developement of FinalBuilder, we have had another project running over the last year that was intended to be FinalBuilder Server 7. Due to a lack of resources (or more to the point, a lack of success in recruiting) we had to rethink our plans for this product. It's a large project, and it became clear over the last few weeks that it was not going to be ready to release alongside FinalBuilder 7. This project was born out of the feature requests and feedback from users, and an in depth look at what people were really asking for and why, as well as our own future needs (we are our own best customer!). It was clear quite early on that the architecture of FinalBuilder Server was not capable of supporting some of the features, and neither was ASP.NET.

So we started fresh. FB Server vNext (actual product name yet to be decided) was designed from outset to support work flow, build agents (possibly also on other platforms), tight integration with bug tracking systems and version control. We are also focusing more on the release management side of things.. management of build artifacts, release notes, tracking which issues are related to which builds, which checkins are related to which builds etc.

When???

Now what you are probably wanting to hear is when will the next versions be released. I'm not going to make any promises here, but we are aiming for FinalBuilder 7 and FBServer 7 at the end of Q1 next year. FinalBuilder Server vNext will come later in the year.

The biggest blocking issue for us at the moment is a lack of manpower (or woman power!). We are finding it hard to recruit suitable people. Canberra is a difficult place to run a software business, we have to compete with the many (both federal and ACT) government departments for people... and despite the election promises the government has only gotten larger over the last 2 years. We will continue our recruitment drive in the new year (but feel free to submit your resume - if you have the right to work and live in Australia).

 


Nelson Wolf recently published a blog post to introduce the new FinalBuilder action he'd developed. The action checks that all required variables for a project are available at run-time. Quite a handy action if your projects include a lot of subprojects. You can download it from launchpad.net.

He's also created and made available example projects and a 'unit testing' project for the action.

I have to comment on one other comment in the post that gave me a good laugh.

"Initially I had resisted [FinalBuilder] because I thought it might be too easy."

We've previously heard from devs who are hesitant to try a visual tool because of fears that it may restrict what you can automate, but I've never heard of someone avoiding FB because it might make automating builds too easy!