VMWare Machines : How to Make the Hard Disk Bigger

Here’s an easy commandline way to make the size of a virtual disk (virtual hard disk) larger.

Article

Note that this still requires getting the additional space added to the partition in Windows – which will require a repartitioning tool.

Fortunately, Vista's disk manager allows you to extend existing partitions into the unpartitioned space. All you have to do is click on the drive and hit extend.

Posted on 5/7/2009 7:53:00 PM by Jason Nadal

Permalink | Comments |

Categories: hardware | system | vmware

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Upgrade Vista Enterprise to 7 RC

I attempted to update my home development virtual machine running in VMWare workstation to Windows 7 this evening. I cloned it first – don’t want to get stuck with a no-upgrade path from Windows 7 RC to Windows 7 RTM when it comes out!

I ran across this unfortunate message:

Vista Enterprise cannot be upgraded to Windows 7 Ultimate

This was not a pleasant discovery – figured I was dead in the water unless I upgraded needlessly to Ultimate. When I found out how to upgrade from Enterprise to Ultimate, I realized I can just avoid ultimate altogether and change from Enterprise to Business (sort of a side-grade), and from there to Windows 7 Ultimate.

Here’s the appropriate registry changes:

  • Go to, Start, Run: and type: regedit.exe
  • Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
  • Change the key : ProductName from "Windows Vista ™ Enterprise” to “Windows Vista ™ Business”
  • Change the key: EditionID from "Enterprise" to “Business
  • Do not restart (not sure what this will do, but the original instructions made sure to mention this!

Posted on 5/7/2009 7:39:01 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

An Exercise in Refactoring: Part 7

This post is a continuation of our previous article, a response to this smelly code.

When last we left off, a majority of our duplicate code was refactored away to the GetKeyFor method. Here’s where our method currently stands.

private int MarkConnectingCellsRecursive(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    //set the current location to be clicked.
    grid.Columns[location.Column][location.Row].CellState = CellStates.Down;

    //we seed the count at one here, because at least the current cell is to be
    //marked.
    int countOfMarkedCells = 1; 

    //look all around our current cell for other cells of the same value.
    string rightKey = GetKeyFor(grid, location.MoveRight(), clickedValue);
    string leftKey = GetKeyFor(grid, location.MoveLeft(), clickedValue);
    string downKey = GetKeyFor(grid, location.MoveDown(), clickedValue);
    string upKey = GetKeyFor(grid, location.MoveUp(), clickedValue);

    //if the keys ARE the same value, look around them for the same value, mark them, and add them
    //to the count
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, location.MoveRight(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, location.MoveLeft(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, location.MoveDown(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, location.MoveUp(), clickedValue);

    return countOfMarkedCells;
}

Note there are essentially two blocks of logic repeated four times.  We can reorganize the lines of code, and then the method extraction should be obvious:

private int MarkConnectingCellsRecursive6(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    //set the current location to be clicked.
    grid.GetCell(location).CellState = CellStates.Down;

    //we seed the count at one here, because at least the current cell is to be
    //marked.
    int countOfMarkedCells = 1; 

    //look all around our current cell for other cells of the same value.
    string rightKey = GetKeyFor(grid, location.MoveRight(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, location.MoveRight(), clickedValue);
    string leftKey = GetKeyFor(grid, location.MoveLeft(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(leftKey, grid, location.MoveLeft(), clickedValue);
    string downKey = GetKeyFor(grid, location.MoveDown(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(downKey, grid, location.MoveDown(), clickedValue);
    string upKey = GetKeyFor(grid, location.MoveUp(), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(upKey, grid, location.MoveUp(), clickedValue);

    return countOfMarkedCells;
}

See the repetition? Pull it out into a method, and you have the code below. This is a VAST improvement over where we started out at the beginning of this series.

private int MarkAndCountCellsWithValueFrom(IGrid grid, CellValues clickedValue, GridCoordinate potentialLocation)
{
    string key = GetKeyFor(grid, potentialLocation, clickedValue);
    return IfContainsClickedValueThenMark(key, grid, potentialLocation, clickedValue);
}

private int MarkConnectingCellsRecursive(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    //set the current location to be clicked.
    grid.GetCell(location).CellState = CellStates.Down;
    
    int countOfMarkedCells = 1;
    
    //look all around our current cell for other cells of the same value.
    countOfMarkedCells += MarkAndCountCellsWithValueFrom(grid, clickedValue, location.MoveRight());
    countOfMarkedCells += MarkAndCountCellsWithValueFrom(grid, clickedValue, location.MoveLeft());
    countOfMarkedCells += MarkAndCountCellsWithValueFrom(grid, clickedValue, location.MoveUp());
    countOfMarkedCells += MarkAndCountCellsWithValueFrom(grid, clickedValue, location.MoveDown());

    return countOfMarkedCells;
}

There’s still an issue with this code – is it obvious? Look at the name of the method it’s calling. “MarkAndCountCells….:” This violates a fundamental principle methods should do one thing, and do it well – be a Unit of code. The method may be doing two things well, but is still doing two things. More on this to come.

Posted on 5/7/2009 7:25:43 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

An Exercise in Refactoring: Part 6

This post is a continuation of our previous article, a response to this smelly code.

When we left off yesterday, I mentioned that the rest of the day’s work on this refactoring (I do have a day job as well, please keep in mind!) I’d spend replacing the Grid.Columns[column][row]:Cell. Well in order to do that, I’ve introduced a new method in the IGrid interface:

public Cell GetCell(GridCoordinate coordinate)
{
    return Columns[coordinate.Column]
        [coordinate.Row];
}

This allows us to do some interesting things in the long term. But really it just makes parameter lists that are passed into methods cleaner.

Now we can get to the fun part – all those GetXKey methods… one for each direction. There’s so much duplication there! See if you can find the similarities in purpose and form between two of the four methods.

private static string GetRightKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{

    string rightKey = String.Empty;
    bool columnIsNotLastColumn = location.Column < grid.Width - 1; ;
    if (columnIsNotLastColumn
        && grid.Columns[location.Column + 1][location.Row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column + 1][location.Row]))
    {
        rightKey = location.MoveRight().CreateCellKey();
    }
    return rightKey;
}

private static string GetLeftKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    string leftKey = String.Empty;
    bool columnIsNotFirstColumn = location.Column > 0;
    if (columnIsNotFirstColumn
        && grid.Columns[location.Column - 1][location.Row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column - 1][location.Row]))
    {
        leftKey = location.MoveLeft().CreateCellKey();
    }
    return leftKey;
}

Any ideas? The problem is that there’s a lot of different code there. They’re looking at different criteria in that first boolean expression, but that logic is clear – is the cell (location) that’s being passed in outside the bounds of the Grid. If the cells a legitimate location, and meets the other criteria, then create the cell key.

So what we can introduce is a GridCoordinateBoundary class, representing the measurable borders (boundaries) of our Grid object.

public class GridCoordinateBoundary
{
    public int MinimumRow { get; set; }
    public int MaximumRow { get; set; }
    public int MinimumColumn { get; set; }
    public int MaximumColumn { get; set; }

    private GridCoordinateBoundary(int minimumRow, int maximumRow, int minimumColumn, int maximumColumn)
    {
        MinimumRow = minimumRow;
        MaximumRow = maximumRow;
        MinimumColumn = minimumColumn;
        MaximumColumn = maximumColumn;
    }

    public static GridCoordinateBoundary CreateFrom(int minimumRow, int maximumRow, int minimumColumn, int maximumColumn)
    {
        return new GridCoordinateBoundary(minimumRow, maximumRow, minimumColumn, maximumColumn);
    }
    
    public bool IsWithinBoundary(GridCoordinate location)
    {
        return (location.Row >= MinimumRow)
               && (location.Row < MaximumRow)
               && (location.Column >= MinimumColumn)
               && (location.Column < MaximumColumn);
    }
}

Now we can start pulling the logic together. We don’t need the 4 unique GetDownKey, GetUpKey, etc.

private static string GetKeyFor1(IGrid grid, GridCoordinate nextLocation, CellValues clickedValue)
{
    string key = String.Empty;
    if (grid.GetBoundary().
            IsWithinBoundary(nextLocation)
        && grid.GetCell(nextLocation).CellValue 
            == clickedValue
        && IsCellInMarkableState(
            grid.GetCell(nextLocation)))
    {
        key = nextLocation.CreateCellKey();
    }
    return key;
}

Note that the logic is right in the if block. Based on literature I’m currently reading (I’d highly recommend Robert C. Martin’s Clean Code so far), pulling the boolean expressions out for variable names is cleaner. This gives us the following result at the end of a short day’s work. I will spend the rest of the day getting the GetCell() method propagated to replace the Column[][] syntax that’s pervasive in the solution.

private static string GetKeyFor(IGrid grid, GridCoordinate nextLocation, CellValues clickedValue)
{
    string key = String.Empty;
    bool locationIsWithinGridBoundary = grid.GetBoundary().IsWithinBoundary(nextLocation);
    bool cellValueIsSameAsClicked = grid.GetCell(nextLocation).CellValue == clickedValue;

    if (locationIsWithinGridBoundary
        && cellValueIsSameAsClicked
        && IsCellInMarkableState(grid.GetCell(nextLocation)))
    {
        key = nextLocation.CreateCellKey();
    }
    return key;
}

Posted on 5/6/2009 7:00:35 AM by Jason Nadal

Permalink | Comments |

Categories: development | codeQuality | refactoring

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

An Exercise in Refactoring: Part 5

This post is a continuation of our previous article, a response to this smelly code.

Remember those columns and rows everywhere, and how tough it was to swap them everywhere? Well this is a prime time to fix that. How else can we reduce parameter count, while still passing in the same information? Enter complex object.

In this case, we can gain:

  • Reduction of column / row parameters to just location
  • Give the CreateCellKey(x,y) method a home (really, it gives a key for a particular coordinate.

So our first step is to create the new object and move in the CreateCellKey method; note this is also implementing a static create method:

public class GridCoordinate
{
    public int Column { get; set;}
    public int Row { get; set; }

    public static string CreateCellKey(GridCoordinate location)
    {
        return location.Column + "," + location.Row;
    }

    public static GridCoordinate Create(int column, int row)
    {
        return new GridCoordinate {Column = column, Row = row};
    }
}

And then we have to fix the calls that just deal with columns and rows. Note the code is longer for now, but we’ll address this with reusability in the near future!

Our resulting changed code is as follows:

private static string GetRightKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{

    string rightKey = String.Empty;
    bool columnIsNotLastColumn = location.Column < grid.Width - 1; ;
    if (columnIsNotLastColumn
        && grid.Columns[location.Column + 1][location.Row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column + 1][location.Row]))
    {
        rightKey = GridCoordinate.CreateCellKey(GridCoordinate.Create(location.Column + 1, location.Row));
    }
    return rightKey;
}

private static string GetLeftKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    string leftKey = String.Empty;
    bool columnIsNotFirstColumn = location.Column > 0;
    if (columnIsNotFirstColumn
        && grid.Columns[location.Column - 1][location.Row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column - 1][location.Row]))
    {
        leftKey = GridCoordinate.CreateCellKey(GridCoordinate.Create(location.Column - 1, location.Row));
    }
    return leftKey;
}

private static string GetDownKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    string downKey = String.Empty;
    bool rowIsNotLastRow = location.Row < grid.Height - 1;
    if (rowIsNotLastRow
        && grid.Columns[location.Column][location.Row + 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column][location.Row + 1]))
    {
        downKey = GridCoordinate.CreateCellKey(GridCoordinate.Create(location.Column, location.Row + 1));
    }
    return downKey;
}

private static string GetUpKey(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    string upKey = String.Empty;
    bool rowIsNotFirstRow = location.Row > 0;
    if (rowIsNotFirstRow
        && grid.Columns[location.Column][location.Row- 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[location.Column][location.Row - 1]))
    {
        upKey = GridCoordinate.CreateCellKey(GridCoordinate.Create(location.Column, location.Row - 1));
    }
    return upKey;
}

private int IfContainsClickedValueThenMark(string key, IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    int countOfMarkedCells = 0;
    if (key != String.Empty && !_searchedCells.Contains(key))
    {
        _searchedCells.Add(key, String.Empty);
        countOfMarkedCells += MarkConnectingCellsRecursive(grid, location, clickedValue);
    }
    return countOfMarkedCells;
}

private int MarkConnectingCellsRecursive(IGrid grid, GridCoordinate location, CellValues clickedValue)
{
    //set the current location to be clicked.
    grid.Columns[location.Column][location.Row].CellState = CellStates.Down;

    //we seed the count at one here, because at least the current cell is to be
    //marked.
    int countOfMarkedCells = 1; 

    //look all around our current cell for other cells of the same value.
    string rightKey = GetRightKey(grid, location, clickedValue);
    string leftKey = GetLeftKey(grid, location, clickedValue);
    string downKey = GetDownKey(grid, location, clickedValue);
    string upKey = GetUpKey(grid, location, clickedValue);

    //if the keys ARE the same value, look around them for the same value, mark them, and add them
    //to the count
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, GridCoordinate.Create(location.Column + 1, location.Row), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(leftKey, grid, GridCoordinate.Create(location.Column - 1, location.Row), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(downKey, grid, GridCoordinate.Create(location.Column, location.Row + 1), clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(upKey, grid, GridCoordinate.Create(location.Column, location.Row- 1), clickedValue);

    return countOfMarkedCells;
}

Now that we’ve done that, we can really do some cool things. Since we have a reference to a distinct location as an object, that object knows where it is. You can treat it like a plotter. Given a location, move up, down, left, right.(Note, we’ll probably want to rename this object to something like GridPlotter, so it makes more sense… this would have a GridCoordinate object, but for now, we’ll place the methods right in the GridCoordinate object:

public GridCoordinate MoveUp()
{
    return Create(Column, Row - 1);
}

public GridCoordinate MoveDown()
{
    return Create(Column, Row + 1);
}

public GridCoordinate MoveLeft()
{
    return Create(Column - 1, Row);
}

public GridCoordinate MoveRight()
{
    return Create(Column + 1, Row);
}

public string CreateCellKey()
{
    return CreateCellKey(this);
}

This lets you refactor code like follows. Instead of the +1 and –1 everywhere:

countOfMarkedCells += 
    IfContainsClickedValueThenMark(
    rightKey, grid, 
    GridCoordinate.Create(location.Column + 1, 
        location.Row), 
    clickedValue);

You can just put:

countOfMarkedCells += IfContainsClickedValueThenMark(
    rightKey, grid, 
    location.MoveRight(), 
    clickedValue);

At this point, unit tests all still pass, and app feels pretty good still, so this is a pretty successful refactoring process thus far. For the time until the next post, I’ll be making sure all areas of code referencing this class (the GridController class) no longer use pure “int column, int row” values, but rather use the more robust GridCoordinate class.

After this is complete, the GridCoordinate class will be renamed, and co-located near the Grid itself. Right now, this is only referenced by the GridController, but in reality, the GridCoordinate should serve as the base of all Grid cell lookups. (Rather than always using the Grid.Columns[column][row]:Cell).

Posted on 5/5/2009 6:42:40 AM by Jason Nadal

Permalink | Comments |

Categories: development | patterns | refactoring | codeQuality

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

An Exercise in Refactoring: Part 4

This post is a continuation of our previous article, a response to this smelly code.

When we last left off, the method was much smaller; we had extracted methods for the entire first half of the method. This article focuses on the bottom half. Note that the if blocks in the bottom half check to see that:

  1. The key is not empty.
  2. The cell corresponding to the key has not already been checked
  3. If 1&2 are fine, then check around THAT cell for matching cells (from the originally clicked cell)
  4. If there are any new connecting cells, add them to the scoring tally.

So, we can pull out a method and pass in the next one to check. Here’s our new method:

private int IfContainsClickedValueThenMark(string key, IGrid grid, int column, int row, CellValues clickedValue)
{
    int countOfMarkedCells = 0;
    if (key != String.Empty && !_searchedCells.Contains(key))
    {
        _searchedCells.Add(key, String.Empty);
        countOfMarkedCells += MarkConnectingCellsRecursive(grid, column, row, clickedValue);
    }
    return countOfMarkedCells;
}

Note that this is the first time in this series that we’ve actually reduced the number of lines of code. Most of the time, this will wind up happening, however in some cases (like this method), it takes some work to get the code to where you can actually see the similarities in logic. Duplicate code does not always look like duplicate code at first glance! Here’s the resulting code in the method we’re focusing on for the refactoring. We’ve also made the following changes:

  1. Changed “count” to something more meaningful: it’s actually the count of connected (marked) cells.
  2. We’ve added some descriptive comments. Note that this can mean that our code has room for further optimization. If our code needs the comments, how well is it written?
private int MarkConnectingCellsRecursive(IGrid grid, int column, int row, CellValues clickedValue)
{
    //set the current location to be clicked.
    grid.Columns[column][row].CellState = CellStates.Down;

    //we seed the count at one here, because at least the current cell is to be
    //marked.
    int countOfMarkedCells = 1; 

    //look all around our current cell for other cells of the same value.
    string rightKey = GetRightKey(grid, column, row, clickedValue);
    string leftKey = GetLeftKey(grid, column, row, clickedValue);
    string downKey = GetDownKey(grid, column, row, clickedValue);
    string upKey = GetUpKey(grid, column, row, clickedValue);

    //if the keys ARE the same value, look around them for the same value, mark them, and add them
    //to the count
    countOfMarkedCells += IfContainsClickedValueThenMark(rightKey, grid, column + 1, row, clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(leftKey, grid, column - 1, row, clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(downKey, grid, column, row + 1, clickedValue);
    countOfMarkedCells += IfContainsClickedValueThenMark(upKey, grid, column, row - 1, clickedValue);

    return countOfMarkedCells;
}

Posted on 5/4/2009 7:51:52 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

An Exercise in Refactoring: Part 3

This post is a continuation to our previous article, a response to this smelly code.

When we last left off, we replaced the boolean expressions in the first if blocks with meaningful boolean logic.

Now that we have that, we can re-replace the boolean logic with variables that make sense. The first step to making more concise code is to make more readable code.

private int MarkConnectingCellsRecursive2(IGrid grid, int column, int row, CellValues clickedValue)
{

    //set the current location to be clicked.
    grid.Columns[column][row].CellState = CellStates.Down;

    int count = 1;

    string rightKey = String.Empty;
    string leftKey = String.Empty;
    string downKey = String.Empty;
    string upKey = String.Empty;

    bool columnIsNotFirstColumn = column > 0;
    bool columnIsNotLastColumn = column < grid.Width - 1;
    bool rowIsNotFirstRow = row > 0;
    bool rowIsNotLastRow = row < grid.Height - 1;

    if (columnIsNotLastColumn
        && grid.Columns[column + 1][row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column + 1][row]))
    {
        rightKey = CreateCellKey(column + 1, row);
    }
    if (columnIsNotFirstColumn
        && grid.Columns[column - 1][row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column - 1][row]))
    {
        leftKey = CreateCellKey(column - 1, row);
    }
    if (rowIsNotLastRow
        && grid.Columns[column][row + 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column][row + 1]))
    {
        downKey = CreateCellKey(column, row + 1);
    }
    if (rowIsNotFirstRow
        && grid.Columns[column][row - 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column][row - 1]))
    {
        upKey = CreateCellKey(column, row - 1);
    }


    if (rightKey != String.Empty && !_searchedCells.Contains(rightKey))
    {
        //if the one to the right is a match and we haven't looked around it yet,                                
        _searchedCells.Add(rightKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column + 1, row, clickedValue);
    }
    if (leftKey != String.Empty && !_searchedCells.Contains(leftKey))
    {
        //if the one to the left is a match                
        _searchedCells.Add(leftKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column - 1, row, clickedValue);
    }
    if (downKey != String.Empty && !_searchedCells.Contains(downKey))
    {
        //if the one below is a match                
        _searchedCells.Add(downKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row + 1, clickedValue);
    }
    if (upKey != String.Empty && !_searchedCells.Contains(upKey))
    {
        //if the one above is a match                
        _searchedCells.Add(upKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row - 1, clickedValue);
    }
    return count;
}

As you can see here, we now are checking to see of the row is not the last row, something that makes considerably more sense.

From here, we can actually start to do real refactoring. Let’s take the first if blocks, they’ve got much repeated logic, but there are four distinct checks here… the first step is to extract them out to methods. The result is below:

private static string GetRightKey(IGrid grid, int column, int row, CellValues clickedValue)
{

    string rightKey = String.Empty;
    bool columnIsNotLastColumn = column < grid.Width - 1; ;
    if (columnIsNotLastColumn
        && grid.Columns[column + 1][row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column + 1][row]))
    {
        rightKey = CreateCellKey(column + 1, row);
    }
    return rightKey;
}

private static string GetLeftKey(IGrid grid, int column, int row, CellValues clickedValue)
{
    string leftKey = String.Empty;
    bool columnIsNotFirstColumn = column > 0;
    if (columnIsNotFirstColumn
        && grid.Columns[column - 1][row].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column - 1][row]))
    {
        leftKey = CreateCellKey(column - 1, row);
    }
    return leftKey;
}

private static string GetDownKey(IGrid grid, int column, int row, CellValues clickedValue)
{
    string downKey = String.Empty;
    bool rowIsNotLastRow = row < grid.Height - 1;
    if (rowIsNotLastRow
        && grid.Columns[column][row + 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column][row + 1]))
    {
        downKey = CreateCellKey(column, row + 1);
    }
    return downKey;
}

private static string GetUpKey(IGrid grid, int column, int row, CellValues clickedValue)
{
    string upKey = String.Empty;
    bool rowIsNotFirstRow = row > 0;
    if (rowIsNotFirstRow
        && grid.Columns[column][row - 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[column][row - 1]))
    {
        upKey = CreateCellKey(column, row - 1);
    }
    return upKey;
}

Now that we have these, adjust the calls to point to our newly extracted methods. Note that if you see duplication above, you’re on the right track; we’ll get back to consolidating these in a future article in this series. Below is the resulting refactored method. Note how much shorter it is now!

private int MarkConnectingCellsRecursive3(IGrid grid, int column, int row, CellValues clickedValue)
{

    //set the current location to be clicked.
    grid.Columns[column][row].CellState = CellStates.Down;

    int count = 1;

    string rightKey = GetRightKey(grid, column, row, clickedValue);
    string leftKey = GetLeftKey(grid, column, row, clickedValue);
    string downKey = GetDownKey(grid, column, row, clickedValue);
    string upKey = GetUpKey(grid, column, row, clickedValue);

    if (rightKey != String.Empty && !_searchedCells.Contains(rightKey))
    {
        //if the one to the right is a match and we haven't looked around it yet,                                
        _searchedCells.Add(rightKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column + 1, row, clickedValue);
    }
    if (leftKey != String.Empty && !_searchedCells.Contains(leftKey))
    {
        //if the one to the left is a match                
        _searchedCells.Add(leftKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column - 1, row, clickedValue);
    }
    if (downKey != String.Empty && !_searchedCells.Contains(downKey))
    {
        //if the one below is a match                
        _searchedCells.Add(downKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row + 1, clickedValue);
    }
    if (upKey != String.Empty && !_searchedCells.Contains(upKey))
    {
        //if the one above is a match                
        _searchedCells.Add(upKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row - 1, clickedValue);
    }
    return count;
}

Posted on 5/4/2009 7:43:54 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

The Refactoring: Step 2

This post is a continuation to our last article, a response to this smelly code.

 

So after the last step, we start to see some real problems. Let’s take a look at a chunk of code – the first real logic block:

if (
    rowIsNotLastColumn 
    && columnIsNotFirstColumn
    && columnIsUpToLastRow
    && grid.Columns[row + 1][column].CellValue == clickedValue
    && IsCellInMarkableState(grid.Columns[row + 1][column])
    )
{
    downKey = CreateCellKey(row + 1, column);
}

What you see here is that something’s seriously wrong. Unless we are doing something crazy, why on earth would we be checking for something like “row is not last column”. Can you think of a scenario that this ever makes sense?

In the context of this method, the answer is a resounding “no”. So what’s actually going on here? Well, one thing we can do is to fix things to what you think they should be.

This block of code attempts to check to see if you have a cell that:

  1. Can have a cell below it
  2. Has a cell below it with the same cell value as the value that the user originally clicked.

So, the resulting code that you expect to be correct is:

if  (
rowIsNotLastRow
&& columnIsNotFirstColumn //why? more smell?
&& columnIsUpToLastRow //munster cheese? more smell...
&& grid.Columns[row + 1][column].CellValue == clickedValue
&& IsCellInMarkableState(grid.Columns[row + 1][column])
)
...

Now when I try to run this, unit tests start failing, and running the program results in random cells being marked all over the grid. So the extent of this problem reaches quite far.

I’ll skip to the chase here… because of gridX and gridY’s pervasiveness, coupled with the seemingly random placement of ordering those items as parameters within method signatures, these values are getting swapped all over the place… it’s only due to the seemingly lucky smelly code above that this happens to work.

The fix here is to go up and down and make sure that the parameters are in the same order throughout the chain (more on this in a later article in this series!), as well as making sure everything uses the more descriptive “row” and “column” variable names.

So, we wind up with the code below. Note the lack of use of descriptive variables to replace the inline boolean logic, but at least the code makes sense!

private int MarkConnectingCellsRecursive1(IGrid grid, int column, int row, CellValues clickedValue)
{

    //set the current location to be clicked.
    grid.Columns[column][row].CellState = CellStates.Down;

    int count = 1;

    string rightKey = String.Empty;
    string leftKey = String.Empty;
    string downKey = String.Empty;
    string upKey = String.Empty;
    
    if (column < grid.Width - 1 && row >= 0 && row <= grid.Height - 1 && grid.Columns[column + 1][row].CellValue == clickedValue
        && (grid.Columns[column + 1][row].CellState == CellStates.Normal || grid.Columns[column + 1][row].CellState == CellStates.Down))
    {
        rightKey = CreateCellKey(column + 1, row);
    }
    if (column > 0 && row >= 0 && row <= grid.Height - 1 && grid.Columns[column - 1][row].CellValue == clickedValue
        && (grid.Columns[column - 1][row].CellState == CellStates.Normal || grid.Columns[column - 1][row].CellState == CellStates.Down))
    {
        leftKey = CreateCellKey(column - 1, row);
    }
    if (column >= 0 && column <= grid.Width - 1 && row < grid.Height - 1 && grid.Columns[column][row + 1].CellValue == clickedValue
        && (grid.Columns[column][row + 1].CellState == CellStates.Normal || grid.Columns[column][row + 1].CellState == CellStates.Down))
    {
        downKey = CreateCellKey(column, row + 1);
    }
    if (column >= 0 && column <= grid.Width - 1 && row > 0 && grid.Columns[column][row - 1].CellValue == clickedValue
        && (grid.Columns[column][row - 1].CellState == CellStates.Normal || grid.Columns[column][row - 1].CellState == CellStates.Down))
    {
        upKey = CreateCellKey(column, row - 1);
    }


    if (rightKey != String.Empty && !_searchedCells.Contains(rightKey))
    {
        //if the one to the right is a match and we haven't looked around it yet,                                
        _searchedCells.Add(rightKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column + 1, row, clickedValue);
    }
    if (leftKey != String.Empty && !_searchedCells.Contains(leftKey))
    {
        //if the one to the left is a match                
        _searchedCells.Add(leftKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column - 1, row, clickedValue);
    }
    if (downKey != String.Empty && !_searchedCells.Contains(downKey))
    {
        //if the one below is a match                
        _searchedCells.Add(downKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row + 1, clickedValue);
    }
    if (upKey != String.Empty && !_searchedCells.Contains(upKey))
    {
        //if the one above is a match                
        _searchedCells.Add(upKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, column, row - 1, clickedValue);
    }
    return count;
}

Posted on 5/4/2009 7:22:45 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

The Refactoring: Step 1

In our last code showing, we explored the code in question, marking it as a very suitable candidate for refactoring.

First things first, we have to be able to know what on earth is going on in this method – and that means descriptive variable names. When this refactoring session is complete, I’ll show the original code this was created from. Since my first source code (Java) was lost to the ages, I decompiled the class file – this resulted in the worst-of-the-worst as far as refactoring goes. Labels, and variable names like “l0” abound (that’s L-Zero for those of you using sans-serif fonts).

The most key renaming below is:

  • Changing parameter names. No more “gridX” and “gridY”, but rather “column” and “row”
  • Creating variables to represent boolean logic.
  • What does “row < grid.Width - 1” actually mean? (the row is not the last column == rowIsNotLastColumn – does this make sense? More on this later!)
  • Extraction of a method. IsCellInAMarkableState() encapulates the logic of checking to see if a given cell is in the Down or Normal states.

And here’s the first run at the refactoring:

private static bool IsCellInMarkableState(Cell c)
{
    return c.CellState == CellStates.Normal || c.CellState == CellStates.Down;
}


private int MarkConnectingCellsRecursiveRefactor1(IGrid grid, int row, int column, CellValues clickedValue)
{

    //set the current location to be clicked.
    grid.Columns[row][column].CellState = CellStates.Down;

    int count = 1;

    string rightKey = String.Empty;
    string leftKey = String.Empty;
    string downKey = String.Empty;
    string upKey = String.Empty;

    bool rowIsNotFirstRow = row > 0;
    bool rowIsNotLastColumn = row < grid.Width - 1;
    bool rowIsUpToLastColumn = row <= grid.Width - 1;

    bool columnIsNotFirstColumn = column > 0;
    bool columnIsNotLastRow = column < grid.Height - 1;
    bool columnIsUpToLastRow = column <= grid.Height - 1;
    

    if (
        rowIsNotLastColumn 
        && columnIsNotFirstColumn
        && columnIsUpToLastRow
        && grid.Columns[row + 1][column].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[row + 1][column])
        )
    {
        downKey = CreateCellKey(row + 1, column);
    }
    if (
        rowIsNotFirstRow
        && columnIsUpToLastRow 
        && grid.Columns[row - 1][column].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[row - 1][column])
        )
    {
        upKey = CreateCellKey(row - 1, column);
    }
    if (
        rowIsNotLastColumn
        && columnIsNotLastRow 
        && grid.Columns[row][column + 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[row][column + 1])
        )
    {
        rightKey = CreateCellKey(row, column + 1);
    }
    if (
        rowIsUpToLastColumn 
        && columnIsNotFirstColumn
        && grid.Columns[row][column - 1].CellValue == clickedValue
        && IsCellInMarkableState(grid.Columns[row][column - 1])
        )
    {
        leftKey = CreateCellKey(row, column - 1);
    }


    if (downKey != String.Empty && !_searchedCells.Contains(downKey))
    {
        //if the one to the down is a match and we haven't looked around it yet,                                
        _searchedCells.Add(downKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, row + 1, column, clickedValue);
    }
    if (upKey != String.Empty && !_searchedCells.Contains(upKey))
    {
        //if the one to the up is a match                
        _searchedCells.Add(upKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, row - 1, column, clickedValue);
    }
    if (rightKey != String.Empty && !_searchedCells.Contains(rightKey))
    {
        //if the one right is a match                
        _searchedCells.Add(rightKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, row, column + 1, clickedValue);
    }
    if (leftKey != String.Empty && !_searchedCells.Contains(leftKey))
    {
        //if the one left is a match                
        _searchedCells.Add(leftKey, String.Empty);
        count += MarkConnectingCellsRecursive(grid, row, column - 1, clickedValue);
    }

    return count;
}

Posted on 5/4/2009 7:12:13 PM by Jason Nadal

Permalink | Comments |

Categories:

Tags:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Corrupted Suspended VMWare VM How to discard suspended state

Oh boy is this one fun... so you like having your VMWare images (virtual machines) on a separate hard drive, so they run faster. You have your PC's OS hard drive on different physical hardware than the VMWare image. Here comes the fun part -- you love the portability of being able to move the hard drive from machine to machine, running the virtual machine on both VMWare Workstation and VMWare player. You suspend your VM when you're done for a while, and resume it later on, sometimes on a different PC. You always safely remove your hardware using the windows OS tools, until one fateful day.

You unplug the harddrive thinking you're done, when you get a windows error message: "Delayed Write Failed". Uh oh.

You've just corrupted your saved state. This is because even though vmware said it was done writing the ram out to disk, it really was still writing... this way you could still work in the background!

OK, you think -- as far as the VM is concerned, the RAM is corrupt (or rather the data stored in virtual RAM is corrupt). How can we get this back?

The easy way is to close your vm software of choice (vmware player or workstation), rename your *.vmem file (a file containing the contents of the virtual ram), and start up the virtual machine again.

It will die. You'll get a message saying the vmem file cannot be found, and there's something corrupt with the saved state... do you want to preserve or discard?

You should select "Discard", and then start up the VM again. This time it'll boot up, just like windows crashed (do you want to enter safe mode? no.). You should still have all of your data (assuming nothing was acting on the data in RAM as you were suspending, in which case you can add data loss to your list of accomplishments for the day.

Posted on 5/4/2009 6:47:00 PM by Jason Nadal

Permalink | Comments |

Categories: network | troubleshooting | windows | virtualization

Tags: , , , ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5