Agile Business Analysis

After some time working in an Agile environment I have had the privilege to get involved with the generation of the new Agile Business Analysis qualification accredited by APMGroup International. Initially the scheme is released with a Foundation level exam but a practitioner level qualification will be released in the upcoming months.

The qualification is designed to outline the role and responsibilities of a Business Analyst working on an agile project. There are many different flavours of Agile but the only one that gives any real definition to the roles in the project is the DSDM Agile Project Framework. The Agile BA Qualification is built around this framework.

I have completed the training with a fantastic training organisation, TCC. They are based in Cheshire but run training all over the country both publicly and in-house with organisations. For more details about the qualification take a look at the Agile Business Analysis Training Course page.

NEVER BUY A RENAULT AGAIN

I have had a Renault Megane for about 6 years in total now. In that time I’ve had two cars. The first one had a few issues with the alarm not being grounded properly so would randomly go off while driving the car around the streets. This coupled with a few other issues with the car made it a bit of a headache. That said I did like the look of the car and the way it drove.

That car unfortunately got written off by no fault of my own. I replaced that car with a like for like because I wanted to stay with what I knew… unfortunately that hasn’t worked out for me. Since having the replacement car I’ve been plagued by the Renault weak spot of electrical problems. It started with the Push button locks on the side of the car not working. I had to get the push buttons replaced.

My next problem was with the window regulator. A known problem with Renault Meganes I might point out. It’s recognised by Renault as a problem and they offer to pay 76% of the charge of the replacement cost. That’s not all that great though as it still left me with a cost of £100 to replace the faulty part. That was just over 18 months ago… guess what has stopped working again… you guessed it the same window. Exactly the same problem again.

I contacted Renault Customer Services to enquire if they would cover the entire cost of replacement… because I’m not prepared to pay another £100 to fix their mistakes for a second time. They flatly refused and made it clear that they would only cover 76% of the cost leaving me with a £100 bill to foot for a SECOND time to repair the SAME problem I’ve already paid £100 to have fixed.

My advice to the world would be NEVER BUY A RENAULT AGAIN. THEY ARE COMPLETELY UNRELIABLE AND THE CUSTOMER SERVICE LEAVES LOTS TO BE DESIRED.

Windows Firewall for Remote Access

I’ve come across this multiple times now and finally thought it was about time to post about it because I end up spending time googling each time I need it…

We have two hyper-v server at work which we manage using our own PCs. This works well but we’ve recently upgraded them and have to set everything up again. This involves allowing remote access. A lot of this is taken care of by the hyper-v admin. The bit that this doesn’t do is allow event viewer admin. To allow this you need to run a few commands. First lets get the info that we need laid out…

MMC Snapin Rule Group
Event Viewer Remote Event Log Management
Services Remote Services Management
Shared Folders File and Printer Sharing
Task Scheduler Remte Scheduled Tasks Management
Reliability and Performance “Performance Logs and Alerts” and “File and Printer Sharing”
Disk Management Remote Volume Management
Windows Firewall with Advanced Security Windows Firewall Remote Management

Using the above table as a key use the command below:

 

newsh advfirewall fireall set rule group="" new enable=yes

Using the above on the server should give access to the relevant MMC snapins.

Office 2010 and Windows 8

I’ve been having some problems with my laptop since upgrading to Windows 8. The problem has revolved around my Office installation and Windows Updates. It turns out that it was a problem with the Office installation hanging up the Windows Installer. To fix it I though the best bet was to remove office and re-install it. That didn’t turn out to be as easy though. To begin with the Windows Installer was hanging so using it to remove Office was a no go. To remove it I had to follow the manual removal steps form this KB article.

http://support.microsoft.com/kb/290301#Method4

Once the office install had started I tried to install office again but again it hang half way through. After about 2 hours of googl’ing I stumbled upon a post talking about restarting and then stopping the Print Spooler service. As the installation was half way through I decided to just stop the Print Spooler service and that did the trick.

To stop the Print Spooler press start and type services.msc and press Ctrl + Shift + Enter to run it as administrator. Scroll down the list of services and find the Print Spooler service and stop it (right click and select stop). As soon as I stopped the service the install completed. Once the install has completed remember to restart the Print Spooler service again and you should be all installed and running.

Raspberry Pi USB Reset Code

I’ve recently got a Raspberry Pi with the intention of using it to create a little helper for photography and camera controlling. I have fallen foul though of the issue that has caused issues for many users and that is the USB ports needing resetting after each call with gphoto2 to the camera.

A developer wrote a piece of C code to reset the ports and I wanted to re-post it here because I was having problems with it. Please not the following code is a direct copy of that at http://marc.info/?l=linux-usb&m=121459435621262&w=2 and is in no way my work.

/* usbreset -- send a USB port reset to a USB device */

#include 
#include 
#include 
#include 
#include 

#include 

int main(int argc, char **argv)
{
	const char *filename;
	int fd;
	int rc;

	if (argc != 2) {
		fprintf(stderr, "Usage: usbreset device-filename\n");
		return 1;
	}
	filename = argv[1];

	fd = open(filename, O_WRONLY);
	if (fd < 0) {
		perror("Error opening output file");
		return 1;
	}

	printf("Resetting USB device %s\n", filename);
	rc = ioctl(fd, USBDEVFS_RESET, 0);
	if (rc < 0) {
		perror("Error in ioctl");
		return 1;
	}
	printf("Reset successful\n");

	close(fd);
	return 0;
}

Just compile this with

gcc usbreset.c -o usbreset

This should then allow you to make a call to the program after each call to the camera to reset the usb port.

Another piece of code from http://www.rezamahmood.net/raspberrypi-gphoto-web-api/ gives a script which will allow you to pass commands straight through to gphoto2 and do the resets as required.

#!/bin/bash
#
dev=`gphoto2 --auto-detect | grep usb | cut -b 36-42 | sed 's/,/\//'`
if [ -z ${dev} ]
then
 echo "Error: Camera not found"
 exit
fi
resetusb /dev/bus/usb/${dev}
gphoto2 $@
resetusb /dev/bus/usb/${dev}

UPDATE:
I’ve improved on the above a little… the second script posted which passes through the commands to gphoto2 I have saved as a script called camera.sh. I also edited all files to remove any output when in normal operation (mainly in the C code above). I also edited the call out to gphoto2 in my new camera.sh script to be /usr/bin/gphoto2 and created an alias as: alias gphoto2=//camera.sh. All calls to gphoto2 then go via my script which resets the USB ports automatically and I don’t even have to think about it!

XpsRollup Including Adding Blank Pages

XpxRollup is an example program from MSDN for combining multiple xps files. We use this at work for creating files that we can use to print runs of course materials. To use the XpsRollup file you’d do something like this.

xpsrollup.exe outputfile.xps file1.xps file2.xps file3.xps ...

The problem with this was that we wanted to each xps file to start on a new page when printed double sided. To overcome this we had to insert a blank.xps file between each section that required it. the difficulty was identifying where the blank files were required. This usually meant crating an xps file and then checking if the page breaks were correct.

To overcome this I decided to modify the XpsRollup source code. I simply introduced a page counter into the code and at the end of each document insertion I used the page count to find out if I needed to add a blank page in. If it was odd I needed a new blank page if it was even I didn’t.

I’ve attached the new file to this post with a blank.xps file to insert between pages. Xps Rollup Add Blank. Enjoy!

Business Analysis – RACI Matrices

An Introduction to Tools and  Techniques

I’ve recently been working as a Business Analysis trainer and in this position have had the opportunity to use and teach many interesting techniques. I though I’d share some of my thoughts on some of the techniques as they come to me!

The first technique/tool I wanted to talk about is RACI Matrices. These are becoming the way of working with stakeholders and allow you to identify how a stakeholder is involved with a specific activity or process.

A Case Study

As I go through this article I will be using an example business system to show how the tool fits in. The example I will use will be for a library. A traditional library that lends books (you know… these places that lend dead trees to people by scanning a card, stamping a book and getting them to return the item when they’ve finished with it).

What does RACI Stand for?

RACI is an acronym which stands for “Responsible”, “Accountable”, “Consulted” and “Informed”.  There are several variations to this but this is the most commonly used set so I will use this for the purpose of this article.

Now we know what the letters stand for lets consider what the categories mean and which stakeholders may fall into each within our library example.

Responsible

The stakeholders in this category are the ones who operate/run the area under investigation. In our library lets consider the function of “Lend Books”. The stakeholders we would consider responsible for the “Lend Books” function would be the librarians at the desk who take people’s library cards, scan the books and issue the loans to lenders.

Accountable

Accountable stakeholders are those at which “the buck stops”. The person with overall responsibility for the task at hand. Often a managerial role falls into the accountable area. In our library example it would be someone like the head of the librarians at the desk. This person is responsible for the accurate and complete completion of the “Lend Books” function.

Consulted

These stakeholders are people who need to be liaised with about the completion of the task. This implies a two way communication. In the library example if our lender has outstanding fines to pay for late return of items, an account administrator may be consulted as to the account status before a loan is permitted.

Informed

Informed stakeholders are those who are “kept in the loop” about goings on but do not have any input to the operation of the function. Due to the non-input nature of this relationship a single direction of communication is inferred here. In out library example, the overall library manager may wish for management information about the number of loans or other performance metrics of the process and would therefore be informed about the process.

RACI Roles

Now we have an idea of what each element of the RACI are lets lay out some rules for using a RACI Matrix (We’ll see soon why it’s called a matrix).

  • Responsible and Accountable positions are only assigned to one stakeholder role.
  • Often the role that is accountable for a task is also responsible for it. In this case only the Accountable role is added and the Responsible is assumed to be the same person
  • Except for the Responsible and Accountable roles, all other roles are mutually exclusive. For example, a stakeholder can not be both Responsible for a task as well as Informed about the task.
  • The role that is Responsible for a task obtains information required to complete the task from the Consulted role. This implies a two-way communication.
  • The Responsible role updates the Informed role about the task. This implies a one way channel of communication.
  • The Responsible role may delegate responsibilities to others in their team.

Why a Matrix?

Lets get an idea of why it’s called a RACI Matrix. Usually the roles/tasks/stakeholders are presented in tabular form. Let’s build a table for the library example presented in this article.

Librarian Lender Library Manager Finance Clerk County Council
Lend Book R C A C I
Return Book R C A C I
Set Targets I A I C
Register New Borrowers R C A I I

Based on the above lets look at the matrix. We have a county council linked with the library who oversee the operation of the library and want information about the number of items leant, the number of returns, late loans etc. They are not involved in the operation of the library but need information from it.

There are multiple roles that are consulted to complete certain tasks. For example, the lend books function relies on both the lender and the finance clerk to provide information to allow the function to be completed. Similarly with “Register New Borrowers” updates both the County Council and Finance Clerk about the output of registering new borrowers.

The “Set Targets” function does not have a Responsible task specified directly and therefore this falls under the Accountable task to complete, i.e. the Library Manager.

Summary

This technique is a very useful tool for business analysts and project managers to aid with stakeholder management. It provides useful information about the functions and processes being investigated and which stakeholders may be affected by any proposed changes.

Zend Framework Smarty Integration

I’ve been working with zend framework for some time and have been using the Smarty template engine for the views. Initially we were working well with the smarty integration but have just come across a problem. I’ve been using partials for Zend Navigation elements so I can create custom layouts.

The problem I was experiencing was that all my assigned variables were being cleared after the navigation partial has been called. The cause of this problem is that when partials are rendered the view object gets cloned to make sure that the partial is rendered in it’s own address space. With my previous integration the view object was not being cloned correctly and the current view object was being returned and then all the variables in the object was being cleared.

To fix this I found a new smarty integration on the internet based on the currently used view integration and adopted this into my object… I’ve included it below!

/**
* Smarty template engine integration into Zend Framework
* Some ideas borrowed from http://devzone.zend.com/article/120
*/
class ZendExt_View_Smarty extends Zend_View_Abstract
{
	/**
	 * Instance of Smarty
	 * @var Smarty
	 */
	protected $_smarty = null;
 
	/**
	 * Template explicitly set to render in this view
	 * @var string
	 */
	protected $_customTemplate = '';
 
	/**
	 * Smarty config
	 * @var array
	 */
	private $_config = null;
 
	/**
	 * Class definition and constructor
	 *
	 * Let's start with the class definition and the constructor part. My class Travello_View_Smarty is extending the Zend_View_Abstract class. In the constructor the parent constructor from Zend_View_Abstract is called first. After that a Smarty object is instantiated, configured and stored in a private attribute.
	 * Please note that I use a configuration object from the object store to get the configuration data for Smarty.
	 *
	 * @param array $smartyConfig
	 * @param array $config
	 */
	public function __construct($smartyConfig, $config = array())
	{
		$this->_config = $smartyConfig;
		parent::__construct($config);
		$this->_loadSmarty();
	}
 
	/**
	 * Return the template engine object
	 *
	 * @return Smarty
	 */
	public function getEngine()
	{
		return $this->_smarty;
	}
 
	/**
	 * Implement _run() method
	 *
	 * The method _run() is the only method that needs to be implemented in any subclass of Zend_View_Abstract. It is called automatically within the render() method. My implementation just uses the display() method from Smarty to generate and output the template.
	 *
	 * @param string $template
	 */
	protected function _run()
	{
		$file = func_num_args() > 0 && file_exists(func_get_arg(0)) ? func_get_arg(0) : '';
		if ($this->_customTemplate || $file) {
			$template = $this->_customTemplate;
			if (!$template) {
				$template = $file;
			}
 
			$this->_smarty->display($template);
		} else {
			throw new Zend_View_Exception('Cannot render view without any template being assigned or file does not exist');
		}
	}
 
	/**
	 * Overwrite assign() method
	 *
	 * The next part is an overwrite of the assign() method from Zend_View_Abstract, which works in a similar way. The big difference is that the values are assigned to the Smarty object and not to the $this->_vars variables array of Zend_View_Abstract.
	 *
	 * @param string|array $var
	 * @return Ext_View_Smarty
	 */
	public function assign($var, $value = null)
	{
		if (is_string($var)) {
			$this->_smarty->assign($var, $value);
		} elseif (is_array($var)) {
			foreach ($var as $key => $value) {
				$this->assign($key, $value);
			}
		} else {
			throw new Zend_View_Exception('assign() expects a string or array, got '.gettype($var));
		}
	}
 
	/**
	 * Overwrite escape() method
	 *
	 * The next part is an overwrite of the escape() method from Zend_View_Abstract. It works both for string and array values and also uses the escape() method from the Zend_View_Abstract. The advantage of this is that I don't have to care about each value of an array to get properly escaped.
	 *
	 * @param mixed $var
	 * @return mixed
	 */
	public function escape($var)
	{
		if (is_string($var)) {
			return parent::escape($var);
		} elseif (is_array($var)) {
			foreach ($var as $key => $val) {
				$var[$key] = $this->escape($val);
			}
		}
		return $var;
	}
 
	/**
	 * Print the output
	 *
	 * The next method output() is a wrapper on the render() method from Zend_View_Abstract. It just sets some headers before printing the output.
	 *
	 * @param <type> $name
	 */
	public function output($name)
	{
		header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
		header("Cache-Control: no-cache");
		header("Pragma: no-cache");
		header("Cache-Control: post-check=0, pre-check=0", false);
 
		print parent::render($name);
	}
 
	/**
	 * Use Smarty caching
	 *
	 * The last two methods were created to simply integrate the Smarty caching mechanism in the View class. With the first one you can check for cached template and with the second one you can set the caching on or of.
	 *
	 * @param string $template
	 * @return bool
	 */
	public function isCached($template)
	{
		return $this->_smarty->is_cached($template);
	}
 
	/**
	 * Enable/disable caching
	 *
	 * @param bool $caching
	 * @return Ext_View_Smarty
	 */
	public function setCaching($caching)
	{
		$this->_smarty->caching = $caching;
		return $this;
	}
 
	/**
	 * Template getter (return file path)
	 * @return string
	 */
	public function getTemplate()
	{
		return $this->_customTemplate;
	}
 
	/**
	 * Template filename setter
	 * @param string
	 * @return Ext_View_Smarty
	 */
	public function setTemplate($tpl)
	{
		$this->_customTemplate = $tpl;
		return $this;
	}
 
	/**
	 * Magic setter for Zend_View compatibility. Performs assign()
	 *
	 * @param string $key
	 * @param mixed $val
	 */
	public function __set($key, $val)
	{
		$this->assign($key, $val);
	}
 
 
	/**
	 * Magic getter for Zend_View compatibility. Retrieves template var
	 *
	 * @param string $key
	 * @return mixed
	 */
	public function __get($key)
	{
		return $this->_smarty->getTemplateVars($key);
	}
 
	/**
	 * Magic getter for Zend_View compatibility. Removes template var
	 *
	 * @see View/Zend_View_Abstract::__unset()
	 * @param string $key
	 */
	public function __unset($key)
	{
		$this->_smarty->clearAssign($key);
	}
 
	/**
	 * Allows testing with empty() and isset() to work
	 * Zend_View compatibility. Checks template var for existance
	 *
	 * @param string $key
	 * @return boolean
	 */
	public function __isset($key)
	{
		return (null !== $this->_smarty->getTemplateVars($key));
	}
 
	/**
	 * Zend_View compatibility. Retrieves all template vars
	 *
	 * @see Zend_View_Abstract::getVars()
	 * @return array
	 */
	public function getVars()
	{
		return $this->_smarty->getTemplateVars();
	}
 
	/**
	 * Updates Smarty's template_dir field with new value
	 *
	 * @param string $dir
	 * @return Ext_View_Smarty
	 */
	public function setTemplateDir($dir)
	{
		$this->_smarty->setTemplateDir($dir);
		return $this;
	}
 
	/**
	 * Adds another Smarty template_dir to scan for templates
	 *
	 * @param string $dir
	 * @return Ext_View_Smarty
	 */
	public function addTemplateDir($dir)
	{
		$this->_smarty->addTemplateDir($dir);
		return $this;
	}
 
	/**
	 * Adds another Smarty plugin directory to scan for plugins
	 *
	 * @param string $dir
	 * @return Ext_View_Smarty
	 */
	public function addPluginDir($dir)
	{
		$this->_smarty->addPluginsDir($dir);
		return $this;
	}
 
	/**
	 * Zend_View compatibility. Removes all template vars
	 *
	 * @see View/Zend_View_Abstract::clearVars()
	 * @return Ext_View_Smarty
	 */
	public function clearVars()
	{
		$this->_smarty->clearAllAssign();
		$this->assign('this', $this);
		return $this;
	}
 
	/**
	 * Zend_View compatibility. Add the templates dir
	 *
	 * @see View/Zend_View_Abstract::addBasePath()
	 * @return Ext_View_Smarty
	 */	public function addBasePath($path, $classPrefix = 'Zend_View')
	{
		parent::addBasePath($path, $classPrefix);
		$this->addScriptPath($path . '/templates');
		$this->addTemplateDir($path . '/templates/static');
		return $this;
	}
 
	/**
	 * Zend_View compatibility. Set the templates dir instead of scripts
	 *
	 * @see View/Zend_View_Abstract::setBasePath()
	 * @return Ext_View_Smarty
	 */
	public function setBasePath($path, $classPrefix = 'Zend_View')
	{
		parent::setBasePath($path, $classPrefix);
		$this->setScriptPath($path . '/templates');
		$this->addTemplateDir($path . '/templates/static');
		return $this;
	}
 
	/**
	 * Magic clone method, on clone create diferent smarty object
	 */
	public function __clone() {
		$this->_loadSmarty();
	}
 
	/**
	 * Initializes the smarty and populates config params
	 *
	 * @throws Zend_View_Exception
	 * @return void
	 */
	private function _loadSmarty()
	{
		if (!class_exists('Smarty', true)) {
			require_once 'Smarty/Smarty.class.php';
		}
 
		$this->_smarty = new Smarty();
 
		if ($this->_config === null) {
			throw new Zend_View_Exception("Could not locate Smarty config - node 'smarty' not found");
		}
 
		$this->_smarty->caching = $this->_config['smarty']['caching'];
		$this->_smarty->cache_lifetime = $this->_config['smarty']['cache_lifetime'];
		$this->_smarty->template_dir = $this->_config['smarty']['template_dir'];
		$this->_smarty->compile_dir = $this->_config['smarty']['compile_dir'];
		$this->_smarty->config_dir = $this->_config['smarty']['config_dir'];
		$this->_smarty->cache_dir = $this->_config['smarty']['cache_dir'];
		$this->_smarty->left_delimiter = $this->_config['smarty']['left_delimiter'];
		$this->_smarty->right_delimiter = $this->_config['smarty']['right_delimiter'];
 
		if(isset($this->_config['smarty']['plugins_dir']))
		{
			foreach($this->_config['smarty']['plugins_dir'] as $pluginDir)
			{
				$this->addPluginDir($pluginDir);
			}
		}
 
		$this->assign('this', $this);
	}
 
 
 
	public function addScriptPath($path)
	{
		if(!isset($this->_smarty->template_dir))
		{
			$this->_smarty->template_dir = $path;
		}
		else
		{
			if(!$this->checkScriptPathExists($path))
			{
				if(!is_array($this->_smarty->template_dir))
				{
					$this->_smarty->template_dir = array($this->_smarty->template_dir);
				}
 
				array_unshift($this->_smarty->template_dir, $path);
			}
		}
 
		parent::addScriptPath($path);
	}
 
	private function checkScriptPathExists($path)
	{
		$dirs = $this->_smarty->template_dir;
 
		if(is_array($dirs))
		{
			foreach($dirs as $dir)
			{
				if($dir == $path)
				{
					return true;
				}
			}
		}
		else
		{
			if($dirs == $path)
			{
				return true;
			}
		}
		return false;
	}
}

Zend Navigation’s isActive method

Again another Zend Framework issue. I’ve been trying to work out how to detect if a current page is active when using zend navigation. I have setup an XML document with the navigation structure I am after but was having problems detecting if a higher level node in the structure was the currently active branch.

Example:

Page 1
   Sub Page 1
   Sub Page 2 - Currently active page
   Sub Page 3
Page 2
Page 3

I was wanting to know when looking at the top level pages which one of Page 1, Page 2 or Page 3 was the current branch. I know the isActive() method exists for the current page but what I didn’t realise (and is not advertised on the send manual pages) is that passing the parameter “true” to the method makes is recursive.

By calling isActive(true) on the current node I was able to determine if the current branch I was looking at is the actual branch I require.

Comment Spam

I’m sorry to say that I’ve had to require registration before people are able to leave comments on this blog now. I’ve been getting a lot of comment spam so I’ve temporarily activated the requirement for registration before comments are allowed until I’ve managed to put some form of protection in place.