Showing posts with label Tips. Show all posts
Showing posts with label Tips. Show all posts

Friday, 18 January 2008

Tools for the Development Team - JIRA

  

imageCrikey, where did the time go?

This has been a very busy time for the team with a large number of projects and small alterations coming through as well as RFIs and RFPs (Request For Information / Proposal) to answer. It is at these times when a good issue management tool proves its worth and certainly ours did.

I've talked a lot about the different tools that we've looked at here, but we did finally make a decision, the winner was JIRA from Atlassian (http://www.atlassian.com/software/jira/).

So what was it about JIRA that made it stand out against the, sometimes free, competition? It does what it does well.

Many of the other programs that I looked at tried to do many things, and in my opinion, sometimes meant that it did none of those very well. JIRA doesn't suffer from that. It knows what its supposed to do and it does it well. That's where the final decision lay as far as the team were concerned.

Getting to know JIRA.

I had used JIRA in the past so it was second nature to me, but not yet to the team. There were a couple of language constraints that we had to get past before some of the team could understand the concept. Everything you place in JIRA is an "Issue". It doesn't matter if its a suggestion, a bug, a task, whatever it is, if its in JIRA, then its an "Issue". This is one of the very few things that I could not change in JIRA.

The other area that new users will enjoy getting used to is that nearly everything in JIRA is configurable. At times it seems that everything that is asked for is there within the configuration available to the JRIA Administrator. You will get to understand how such things as Notification Schemes and Permission Schemes work, and you can assign different schemes to different projects.

Projects

ProjectUsers or Administrators (depending on what rights the Administrator gives each user or user group) can set up Projects in JIRA and create Issues to the projects. A Project can be either a standard project with a beginning and an end (e.g. a software development project), or an area we can place tasks for normal things needing to be done (e.g. an application or "IT Admin").

I have set up the Notification Scheme so that users will get an email when they area assigned to an issue or when someone has added a comment to an issue that is assigned to them. You can set up notifications as you wish. Users can also "watch" particular issues and be emailed whenever anything changes. You can even email JIRA to open a new issue or add a comment and email attachment to an issue.

Issue numbers are related directly to the project via a 3-4 letter prefix. For example, you might have a project called "IT Administration" and a project called "Worldwide Enterprises Project", which will have a prefix of IT and WWE respectively. Issues in IT will start IT-1, IT-2 etc. and issues in WWE will start WWE-1, WWE-2 etc. so it's easy to know what project an issue relates to. You will find the team with a new vocabulary of words like WWE-193 and IT-22 arising in every sentence.

Users can log work against issues and time tracked.

Workflow

image The Enterprise version has a number of tools that allow you to create and change the workflow, however we opted for the standard which uses a good workflow.

With the standard, an issue is Open when it is created. Once a developer starts work on it, they can change it to In Progress, unless its a small issue that is completed in less than 30 minutes - they can then just go straight to Resolve.

I have set it so that only myself and QA can Close an issue, but anyone can Reopen it for any reason.

Issues are never deleted, only closed.

Issues can be Resolved in a number of ways and the user is presented with the following in the Standard JIRA, the other JIRA versions allow you to add to or change these :

  • Fixed (default) : A fix for this issue has been completed to the satisfaction of the user
  • Won’t Fix : The problem described is an issue which will never be fixed (e.g. the issue relates to a previous version and the workaround its to upgrade)
  • Duplicate : The problem is a duplicate of an existing issue (user can link the issue to another)
  • Incomplete : The problem is not completely described. Used only if the creator of the issue cannot supply any further information (i.e. the creator is no longer available or all attempts to contacted have failed).
    Normally, if the problem is not described correctly, it is up to the user to reassign the issue back to the creator with more questions as comments
  • Cannot Reproduce : All attempts at reproducing this issue failed, or not enough information was available to reproduce the issue. Reading the code produces no clues as to why this behaviour would occur. If more information appears later, the issue may be reopened.

Searching

Users have two ways that they can search for an issue or comment.

"Quick Search" is a seemingly insignificant little search box up the top right of the screen that is extremely powerful. Type anything into there (like "VPN Connection") and JIRA will do a very fast search of all its issues and give you a list of all issues contain that word or phrase. If you know the JIRA number, just type it in and you'll be taken directly to the issue.

"Find Issues" is a menu item that allows you to find issues by creating a Filter. Filters can be created on the fly, saved to a name (e.g. "All Unresolved Development Issues"). JIRA will automatically add a Filter to show you all issues currently assigned to you.

Setting up these Filters is a simple idea of selecting from the list of selections for the fields to search, for example, selecting 1 or more projects to search. Other areas in this search is the Query on the Summary, Description and Comments fields. Query is a reasonably powerful search facility explained Here. Date and time fields have the ability to enter either specific dates, or relative dates (within the last x hours/days, in range from/to). This allows me to, for example, set up a filter to report on all JIRA issues created last month (don't tell my boss that my monthly management reporting is that easy).

When you activate or view a Filter, it shows in a list that you can scroll through and export to Excel or Word, and

Filters can be set up to appear on your JIRA Portal.

The JIRA Portal

The front screen in JIRA can be set up differently by each user. You can add, delete, and move items around the screen to suit yourself. You can add Filters that you created yourself and add pre-set Portlets. These include such things as Project Stats; Admin functions; Filter Stats; My Watched Issues; and Issues in Progress. These can be arranged as you like with the most used Portlets showing at the top of the screen.

My own Portlet shows some details about projects; lists all my save Filters; Overdue Issues; Issues update within the last 8 hours; Resolved issues awaiting me to Close; Issues I'm watching; My assigned issues; and a few of the available graphs that I got from a free JIRA Plugin available from the Atlassian website.

Using JIRA

After using JIRA now for a few months I can honestly say that I have resolved a number of team issues here. I know what is happening; what the team is working on; issues are tracked and comments are added as new information comes in or things are done; the developers and BA can fully understand issues with a place to keep documents, screenshots and comments; work can be prioritised; and everyone can see what work lies ahead of them.

Nothing gets forgotten; work is logged against issues; issues are assigned to others where necessary within the workflow; and management reporting is completed.

The Down Side

image Of course there's a downside -  it costs real money. JIRA comes in Standard, Professional and Enterprise editions costing US$1,200, US$2,400 and US$4,800 respectively. While I would have loved the Enterprise edition, we are getting by quite nicely on the Standard edition.

You will have to keep on top of it when you first install it as there is a mind-set that says "I've assigned this issue to someone else, it's no longer my problem". It's also easy to simply ignore issues assigned to you and then get upset when you have hundreds of issues in front of you.

Summary

As I said, "JIRA works". Sometimes it comes down to that. As a Development Manager I can trust it, the developers trust it, and everyone in the company trusts it.

Try it out for free on your server for a month or two. They'll extend the free trial if you ask them nicely, but I don't think you'll need it. It's so nice to find nice people who actually support and use their product themselves.

 

Just a quick note: I have no affiliation with JIRA\Atlassian . I don't know anyone there and I don't get anything free from them .. although a tee-shirt wouldn't go astray (HINT HINT Atlassian - Grin).

Wednesday, 17 October 2007

Tools for the Development Team - SourceForge

SourceForge

SourceForgeSourceForge (http://sf.net/powerbar/sfee/) was the real contender against Jira and we took a good hard look at it, putting it through its paces. The price (free for less than 15 users) was a compelling argument, as was its document storage and version control of those documents. We installed it on a server here and the team had a play. The following are our findings.

Initially we found SourceForge (SF) very slow. This was perhaps related to the fact it was set up as a virtual machine. This also meant that it was many gigs to download.

There was a small learning curve, same as any new product I suppose. The one thing that threw me immediately was that Tasks is not the area you place issues. Within a project, you can "create" new Trackers, and its in that new tracker area off the Main Menu where you can now track issues, or "Artifacts" as SF calls them. I'm not sure that I like the term 'artifact' as I don't want issues buried for centuries for some scientist to dig up to find out how we performed our work.

You create fields or use the defaults, you can categorise tracker items and the items are also colour coded to show their priority. You can even ask tracker to auto assign different categories to different people. While the auto assignments worked very well, I wanted to auto assign depending on the development process - e.g. auto assign to me all new issues and I can then distribute them to the available team member, then auto assign to QA when the issue is resolved. However, this is another system and what it offers is good.

SourceForge has several areas of concentration:

  • Tracker - an issues register
  • Documents - a document control system where company and technical documents can be stored, and a sort of version control is applied (more about that shortly)
  • Tasks - These are project tasks as opposed to software issues.
  • Source Code - links to Subversion or other source/version control systems
  • Discussion - a nice discussion forum with threaded messages
  • Reports
  • Release Packages
  • Wiki
  • Project Admin

foldersDocuments

The document control was a really nice feature that we gave high marks to. I can add folders and sub folders and place documents in them, just like Windows. The main difference here is that when I go back and add updated files into the same folders, instead of overwriting the files as Windows does, SF treats the newer files as new versions of the older files. I can then review previous versions, almost like I was in a Version Control program.

Discussions

The SF discussion forums were a nice touch. You can associate a discussion with a tracker artifact, people can reply to discussions and you

can select to "watch" a particular discussion to get an email when someone adds to the discussion. You can also have it automatically sending out to a mailing list.

There were a couple of downsides to the discussions. When replying to a comment, you can not see the discussion you are replying to. This will surely cause a lot of mis-quoting. Also, it seems that the user is unable to edit their own discussion after posting so even if they find they have misquoted, they can't edit that to change it. While I can understand not being able to change a comment if another has replied, surely you can edit to change that spelling mistake or typo you noticed in that frozen moment after you press save and before it was redisplayed.

File Releases

It is a convenient tool to package files in a patch set. You could upload all the files needed for a patch and when pressing the downloading release button, it saves all files into a zip file. Good for patches but I'm uncertain for major releases.

Reports

Reports can be defined to report on any searchable criteria. A standard report of a graphical summary and the report detail will then be generated. Reports can be on Tasks (project) or Tracker Artifacts.

Wiki

The Wiki was a disappointment. It was a simple and very basic Wiki without even the ability to add graphics other than as a URL. It has a different command set than I was used to but as it was so limiting, it wouldn't take long to learn.

General

It had a nice interface and some nice additions when compared with Jira, however when even after 2 weeks the company still could not reply to even a standard sales enquiry (sent by two of us separately), we were left wondering about the likelihood of any response to a real support query. That was the real clincher as far as we were concerned. Sadly, we dropped SourceForge from our list.

Thursday, 23 August 2007

Have an iif() function in Delphi

There are many advantages to learning other programming languages, but there are also some problems as well. The "Immediate If" (iif) function is one of those. In most, if not all, the other languages there is an immediate if function that makes programming just a little easier and allows you to say things in much less lines. Consider the following...

    if Str = 'Top' then
s := 'Woohoo!'
else
s := 'Climb some more';


While in Delphi we can effectively write this on one line as...

    if Str = 'Top' then s := 'Woohoo!' else s := 'Climb some more';


This looks untidy. If we were using another language with immediate if, that would look like this...

    s := iif(Str='Top', 'Woohoo!', 'Climb some more');


Now I realise to some Delphi programmers that are not multiple programming language experienced, all that seems a little esoteric but it is standard use in even Excel. Here's how it works...

iif(condition, TrueResult, FalseResult) : String;


The iif() function first looks at the boolean condition. If that condition is true, then it return the TrueResult, and if it is false, then it returns the FalseResult. Here's the declaration

function iif(Test: boolean; TrueR, FalseR: string): string;


The 1st parameter is the Test condition, this can be anything (e.g.: x > y).
The 2nd parameter is the string to return if the test condition is True.
The 3rd parameter is the string to return if the test condition is False.

Here's the full function...

function iif(Test: boolean; TrueR, FalseR: string): string;
begin
if Test then
Result := TrueR
else
Result := FalseR;
end;


but in other languages, the 'type' we return can vary. For example we may want to return 99 if true or 0 of false. How do we do that in Delphi? By using the 'overload' directive.

function iif(Test: boolean; TrueR, FalseR: string): string; overload;
function iif(Test: boolean; TrueR, FalseR: integer): integer; overload;
function iif(Test: boolean; TrueR, FalseR: extended): extended; overload;

Implementation

function iif(Test: boolean; TrueR, FalseR: string): string;
begin
if Test then
Result := TrueR
else
Result := FalseR;
end;

function iif(Test: boolean; TrueR, FalseR: integer): integer;
begin
if Test then
Result := TrueR
else
Result := FalseR;
end;

function iif(Test: boolean; TrueR, FalseR: extended): extended;
begin
if Test then
Result := TrueR
else
Result := FalseR;
end;


We can even extend these to bytes or even TObject if we want to. The only thing we can't do is have the same parameter types and return a different type, e.g...

function iif(Test: boolean; TrueR, FalseR: string): string; overload;
function iif(Test: boolean; TrueR, FalseR: string): integer; overload;


This is a no-no. Why? Delphi will decide which function to run based on the parameter types. If all the parameter types are the same, Delphi will not compile as it will see this as an error.

As already stated, Delphi decides which function it will used based on the types used in the parameters. It will always use the least type for the job. For example, if you have iif()'s set up for both integer and byte, and then use iif(x=y,5,10), then Delphi will use the byte function and return a byte. In most cases this will still work ok even if you are expecting an integer returned.

Friday, 10 August 2007

Use of Try/Except/Finally

[Steve: I have altered the example to a more suitable one - that should teach me to quickly post then leave for the weekend without reading it].

I have seen a number of discussions recently showing that some developers can be confused over try/except and try/finally blocks. I can give an example in the kind of work that I was doing this morning.

I often read or write to an external device (let's just call it "the device" as it could be any external device). That device can sometimes send back confusing errors that I try to trap. However because those errors are confusing, I must let the user know all the various issues and ways around them.

Here's a simplified version of my code (the procedures can raise their own exception with the error message returned from the device).

var
curSave : TCursor;
begin
try
curSave := Screen.Cursor;
Screen.Cursor := crHourGlass; // Show hourglass cursor
try
OpenDeviceConnection; // each will raise an exception if error
DoStuffWithDevice;
ObtainReadings;
CalculateNewFigures;
UpdateDevice;
If not CloseConnection then // raise my own error
raise exception.create('Cant Close Connection');
finally
// return the cursor to what it was
Screen.Cursor := curSave;
end;
except
// the original exception is now being handled
// we can re-raise it, but in this case we'll
// raise a new exception with additions
on e:exception do
raise exception.create(e.message + #13+#10
+ 'Please check that the device is switched on' +#13+#10
+ 'and that the cables are properly connected.');
end;
end;



Exceptions created by any of the procedure calls will now result in an error message something like the following...



Note that I have also placed a try/finally block inside the try/except. This is to ensure that we get the cursor back.

I can raise an exception myself with "raise exception.create", the process then heads immediately to the except block, but before doing that, it must complete the finally block.

The order that finally and except will be executed depends on the order that you give it. In the above sequence, finally will be completed before the except. Usually you will see them the other way around where the exception is processed before the finally block.