News just in: Team Foundation Server sucks. More at 11.
Submitted by craiga on Wed, 04/09/2008 - 09:50.
One of the banes of my current working life is the heaping mound of crud known as Team Foundation Server. I know I've ranted about it before, and I'm sure I'll rant again. Such is the heinous evil that is TFS.
This time, I'm going to list 4 things that TFS does (or doesn't) that means it's completely unsuited to modern development practice. I'll be comparing the functionality with that of Subversion, currently a very popular open source VCS that I like a great deal.
So, on with the rant ...
Checking stuff out
First let's get rid of a bit of a nomenclature conflict. In Subversion, the act of 'checking out' a working copy means simply copying it to your local drive. In TFS, it means notifying that server that you are intending to work on that file. This is actually an important difference because it underlines the issue here.
If I want to change a file in TFS while in the Visual Studio IDE, all is well. I simply start editing and the file is silently 'checked out' behind the scenes. This means that other people browsing the repository can see that I'm making edits to the file. All well and good, I suppose, except I can't think of a single reason for notifying the server that I intend to change a file (note that I might not have actually changed it). Surely that's nothing to do with the server, and everything to do with your working copy?
Anyway, as I said, this is all well and good except when it isn't. Suppose you edit an image in an external program, or a source file or document in an external editor? Suppose you're just far too 1337 for the Microsoft types and actually automate parts of your workflow? How are these external tools supposed to know that they should 'check out' the file? They can't, which means you have to do it manually. Every. Single. Time.
Tiresome.
The Subversion method, then, is somewhat easier. If a file has changed on the disk, then it's different. That's, well, it. If you do a check in, it will only check in files that are different. You don't need to tell any server anywhere that the file is different. It knows because it keeps metadata about the file locally and can tell when it's not the same. What becomes a monumental pain in the arse in TFS isn't even an issue in Subversion.
So how do you know when you've changed a file if there's no little 'checked out' tick on it!? I can almost hear the TFS weenies getting out their tiny fists in frustration as I type this. Well, funnily enough, that's easy too. It brings me on to point two.
Status of files
How do you check what files are different, then? Well, this is one key area in which TFS falls completely flat. In TFS, so check diffs, you have to:
- Click check in at some top level point
- Click the refresh button, because God knows updating a cache automatically is too hard ...
- See list of files
So far so good. Except then you realise the awful truth; it's not showing you a list of changes at all. It's just showing you a list of things you've remembered to tell the server about. If you've changed a file with an automated tool and forgotten to tell the server, or if you've created a new icon and forgotten to add it to the repository, it simply doesn't appear.
So how can you be sure that what you're about to commit is what you've actually changed? In short, you can't. At all.
Let's compare that to Subversion. Issue a simply command, 'svn status', in a suitable directory and a list of files will appear. These will be prefixed by a status character to tell you what has happened. It might be M for 'modified', A for 'added', D for 'deleted' or C for 'conflicts'. If its status is ?, that simply means that the file does not exist in the repository. If you've got a ? on a file that's important to commit, it's a handy reminder to issue an 'svn add' before you commit.
There are other statuses that I won't go into right now, because I've already proved my point. In TFS there is simply NO WAY to determine what the actual current state of your working version is. In Subversion, its so simple that you don't even have to think about it.
OK, remember I mentioned a status of C for conflicted? That's very useful. It means that you can't commit until you resolve it. This is my next section.
Resolution of conflicts
Resolution of conflicts in Subversion is quite comprehensive. If a file has differences when updating that cannot be automatically resolved, it is put into a conflicted state and a variety of things happen.
- The file as it exists in the repository will be created as filename.newrevision, where newrevision is the revision that is being retrieved.
- The file as it exists in your working copy will be renamed to filename.mine
- The file as it existed before you started making changes will be created as filename.oldrevision, where oldrevision is the revision that you updated to last time you performed an update.
- The file itself is updated with conflict markers to show you where the problems lie. These follow a formatting convention that is easy to search for.
Armed with that lot, you can use diff tools, patches, text editors or whatever you see fit to figure out what you want to do. You could just copy filename.mine to filename to wipe out the remote changes, or copy filename.newrevision to filename to wipe out your own changes. Most commonly, you just edit the file itself and fix the conflicts that Subversion has marked for you.
When you've done that and the output of 'svn diff' is satisfactory, just run 'svn resolve' on the file and the version files will be removed and the file will simply appeared as modified.
Sure, it sounds complex, but there are two important points that make it work:
- Changes that can be automatically merged are merged for you, meaning less work for you
- Changes that cannot be automatically merged are left for you to do in your own time, without forcing your hand
Comparing that with TFS is like comparing eggs with space probes. You can fire both of them up in the air, but only the space probe will send back pictures of Mars. The egg will just hit you in the face and make a mess.
So in what ways is TFS so terrible? Let me list them:
- Changes that could be automatically merged are marked as conflicts, requiring a manual operation to click the 'automatically resolve' button. Yes, well ...
- Conflicts are presented in a small, hard to read dialog and you must act on them
- The merge tool is the only apparent way to merge the files, and it's much harder to use than simply marked up lines of code
- Once you've 'finished' a manual conflict resolution, you can't check it with diff and resume later easiler (although it is possible, if you know where to look)
- Once you've finished updating your repository, there is no way to see what it has done. Which files were updated? Which ones conflicted? Which ones are new? Who knows.
Conflict resolution, and indeed the whole process of updating files, is shockingly bad. Having worked with a vast array of source control systems in my life, the only one that handles conflicts worse than TFS is SourceSafe, and that's only because it's not a concurrent versioning system and so doesn't support parallel development.
Annotation
One particularly useful feature of Subversion that carried over from its CVS roots is the 'annotate' command. It provides a specially annotated version of the file, with each line prefixed by the revision in which that line last changed, and who changed it. The annotate command has two synonyms, 'blame' and 'praise', depending on your mood when calling it.
This means that if you want to find out who applied a specific change for any reason, be it for conflict resolution, for correction of API use, or just because the code is that damned impressive you want to buy them a pint, you can do so. Contrast that with TFS, in which such a thing is impossible, and you're forced to check the diff for every single revision of the file until you find the point the line in question last changed. Best of luck with that.
Summary
The thing about TFS is that it's not that bad for a document storage system (think SharePoint). However, it's woefully lacking just about every useful feature used in software development. My only real conclusion is that TFS is unsuited to any practical software development role you may think up for it, simply because it requires far too much hard work doing the simple things, and the hard things are just unfathomable. This means that, as a developer, you spend more time faffing about with source control than actually writing the software.
Source control systems like CVS, Subversion, and even the newer, distributed ones like Mercurial and Git, step out of the way. They let you do what you need to do, and then provide the tools and status reports required to make sure it's all properly managed. TFS takes the opposite approach. Its heavy handed focus on making sure that every action of every user is explicit and recorded means that it completely fails at the job it was intended for. I'm now convinced more than ever that it is as bad as SourceSafe was, simply because the additions to make it a concurrent versioning system are so bad as to be unusable.
