Thursday, December 28, 2006

Coding with the correct Property

Be sure to use the right property when writing your code. I was looking back at one of my programs today trying to debug a process and found a bug.

My code
TimeSpan diff = DateTime.Now - System.IO.File.GetLastWriteTime(FileIn);
if( diff.Seconds < 3 )
{
Thread.Sleep(3000);
}

The quirk here is that if the file was last written 5 days, 4 hours 10 minutes and 1 second ago then this will wait 3 seconds before trying to process the file again.

I should instead have used TotalSeconds.
TimeSpan diff = DateTime.Now - System.IO.File.GetLastWriteTime(FileIn);
if( diff.TotalSeconds < 3 )
{
Thread.Sleep(3000);
}

This will return the total time in seconds. In my situation this wasn't a problem because it would only pause the process for 3 seconds and work correctly. If I had chosen to make the program wait 1 minute though, then everytime the timer fired it would have been less than 3 seconds. Also if I was checking minutes instead. I could have seriously slowed an automated process due simply to a failure to use the correct property.

Wednesday, December 27, 2006

Christmas Geek toys

I had a better Geek toy Christmas this year than I have in the recent past. This year I got a Digital Voice Recorder, a 2 GB USB Drive, and a 1 GB Memory stick for my digital camera.

Also, my kids got a VSmile video game system. It's the first video game system in my house in the past 5 years. I have a somewhat addictive gaming habit and have some pretty bad tendinitis in my right thumb from way too many hours of Nintendo. I played a little today and I started to get that itch. I wonder if there's a cheap Xbox 360 anywhere nearby.

Thursday, December 21, 2006

A Disillusioned Pragmatic Prgrammer

I finished reading The Pragmatic Programmer a few days ago. There were a lot of good ideas in the book, but mostly it can be summed up with continue learning, do things on purpose, and follow good standards. The good standards of course are object oriented programming, decoupling systems as much as possible, using test driven development, the DRY (don't repeat yourself) principle, etc. All of the good standards already existed outside this book, it just points out that a Pragmatic Programmer will do these. Some other tips that are made are as simple as "learn your editor really well". That makes sense. Anyone who wants to be as efficient as possible should take the time to learn the all the options available in their editing tool and the shortcut keys to be able to get more done at crunch time. It's worth the initial investment for the repeated payoff while using your tools.

However, after having completed the book, I was a bit disappointed in the continued support. There is a website http://www.pragmaticprogrammer.com/ the book says to go here for the code samples and up to date links. There are no code samples or up to date links. There are some bloggers listed, but only 2 of them have even written a post within the past month. The main authors of the book have not posted anything in several months. The website is only copyrighted through 2005. All in all the pragmatic programmer support seems to have dissolved. This is very disappointing. There are several good suggestions from the book that I was hoping to have some kind of follow up with. The book give a list of Knowledge Goals

  • Learn at least one new language every year. Different languages solve the same problems in different ways. By learning several different approaches, you can help broaden your thinking and avoid getting stuck in a rut. Additionally, learning many languages is far easier now, thanks to the wealth of freely available software on the Internet.
  • Read a technical book each quarter. Bookstores are full of technical books on interesting topics related to your current project. Once you're in the habit, read a book a month. After you've mastered the technologies you're currently using, branch out and study some that don't relate to your project.
  • Read nontechnical books too. It is important to remember that computers are used by people--people whose needs you are trying to satisfy. Don't forget the human side of the equation.
  • Take classes. Look for interesting courses at your local community college or university, or perhaps at the next trade show that comes to town.
  • Participate in local user groups. Don't just go and listen, but actively participate. Isolation can be deadly to your career, find out what people are working on outside of your company.
  • Experiment with different environments. If you've worked only in Windows, play with Unix at home (the freely available Linux is perfect for this). If you've used only make files and an editor, try an IDE, and vice versa.
  • Stay current. Subscribe to trade magazines and other journals. Choose some that cover technology different from that of your current project.
  • Get wired. Want to know the ins and outs of a new language or other technology? Newsgroups are a great way to find out what experiences other people are having with it, the particular jargon they use, and so on. Surf the Web for papers, commercial sites, and any other sources of information you can find.
I thought that list was awesome. So what are the up to date suggestions for new languages with reasons to learn them? Which books are good? Is there anyone out there that's a windows user talking about his own struggles to do these same things? Nope. That is all completely left out of the website. They also link to a wiki, but the wiki too is in poor shape. I'm not up to fixing the Pragmatic Programmer community. I will however continue to do the things that I have, which are most of the suggestions made in the book. I will continue to document my own struggles.

Now to start my next book and start learning a new language. Tcl anyone? Nah, maybe LISP. Oops, I'm busy learning Java as a new language right now, I guess that will have to do and I'll continue to plug along with it.

Tuesday, December 19, 2006

Backup script

I have been using the TiddlyWiki for a while now for keeping track of my notes, todo tasks, and other items. I am slowly migrating most items from here to MonkeyGTD to more closely use the GTD system. However, there is a built-in backup option that will save a copy of the file for every change. It's typical of wiki's to be able to have a per change rollback process and that's awesome, but my needs are different. I want a once a day option. I'm ok if I lose all of my changes for a day, as long as I can get back to where I was at the end of yesterday I'll feel comfortable. However, there is no option for that.

Instead what I did was turn off the backup option in tiddly wiki. It's my biggest annoyance saving the entire html file everytime I make a 1 character change. My file is currently 205 KB, but 160 KB are the javascript that is embedded to make the wiki work, so a majority of each of my backup files were the javascript. I wanted either only the data that I had, or a once a day copy. The javascript is way over my head, and at over 50,000 lines of it, I didn't have the time to learn it all and tweak the backup process. Instead what I did was build my own archive process.

I keep my wiki on a USB drive and when I plug it into my computer it is always drive E. So I built myself a startup.cmd file with the commands.

start backupwiki.vbs
c:
cd \Program Files\Mozilla Firefox
start firefox.exe "e:\my wiki\MyTiddlyWiki.html"

And I build the backupwiki.vbs that creates my backup copy daily of my file, only if I need it.

Dim filename
filename = "MyTiddlyWiki.html"

Dim dtPart
Dim filesys
set filesys=CreateObject("Scripting.FileSystemObject")
If filesys.FileExists(filename) Then
Set mainfile = filesys.GetFile(filename)
modifiedDate = mainfile.DateLastModified
dtPart = FormatDate(mainfile.DateLastModified)

If modifiedDate < Date() Then
If Not filesys.FileExists("MyTiddlyWiki." & dtPart & ".html") Then
filesys.CopyFile filename, "MyTiddlyWiki." & dtPart & ".html"
End If
End If

End If

Function FormatDate(dateToFormat)
FormatDate = Year(dateToFormat) & Pd(Month(dateToFormat),2) & Pd(Day(dateToFormat),2)
End Function

Function pd(n, totalDigits)
if totalDigits > len(n) then
pd = String(totalDigits-len(n),"0") & n
else
pd = n
end if
End Function


Now when I am ready, I open my folder and just double click the startup.cmd file and it will open in Firefox for me and create the backup when needed. In about 30 minutes I wrote the scripts that will save me from some annoyances, but more importantly hold me to my daily backup. If I don't use it for a few days, the backup will still be before I make any new changes and won't hurt anything. It's great!

Do you have any repetitive tasks you do that could be automated somehow?

Monday, December 18, 2006

Solve your customer's problems.

It's important when designing a solution that you understand the environment that your users work in. If you don't, then you may use an assumption that causes a problem. This is a true story, not something made up or something that happened years ago, this happened last week.


To reduce the chance of theft gas stations have to drop money into a drop safe frequently. That way if any theft occurs they can only get a max of about $100. To solve this problem the cash registers were programmed to force the cashier to drop money into the safe at $100. However, the starting cash in a drawer is $100. That's what is used to make change. Thus every purchase puts the register over $100 and the only way to take another order is to pull some money out and punch in the amount being dropped into the cash register so it can continue to track it.

The problem is that the developers didn't realize that the cash register started with $100, they expected the register to be empty and when it hit $100 to force a drop. They didn't realize the users neeed to be able to make change to help the customer.

This is not a joke, the problem occurred at a major gas station last week and was not solved yet over the weekend. So if you are in a major gas station and the cashier is cursing and asking you to wait while dropping some more money into the safe, remember, it's because the IT department didn't understand the problem that they were trying to solve.

Wednesday, December 06, 2006

Coming soon.

I have not forgotten my geek posts. I'm extra swamped at work right now with people quitting, and learning a new technology (Java, JSF, Websphere all at once). I haven't had time to write up anything interesting. I do have notes on a few things that I want to post, so be patient and I'll have something soon.

Tuesday, November 28, 2006

App.Config

I've been guilty of using the AppSettings tag in the app.config file to hold my custom settings. I haven't seen a single person that has used custom tags. I had read about them once, a long, long, long, time ago, but I never looked into them because it was just too easy to use the AppSettings tag. Last week I read a great post taking you step by step through the process of setting up a custom tag. This is great!!! I wish more posts were as concise.

Undelete Plus

For anyone who wants gone to actually mean gone you will want to read this post on Undelete Plus. This software scans the hard drive for deleted files that haven't been overwritten. Yikes!!! This is almost a must have for anyone quitting a job. You'll want to make sure that anything that you wanted gone is actually gone. It's also a must for anyone about to sell a computer.

Tuesday, November 21, 2006

Java Growing pains

I've been busy lately trying to pick up Java. I'm finally on a project at work where I get to use Java and it's been very painful. My first project is a Websphere portlet that I'm going to use Java Server Faces for. I've never done anything Java, which makes me completely overwhelmed. A co-worker is helping me get started by pointing me in the right direction with example projects to look at, and I've gotten what I think is a lot of the backend code written. Now I want to have some kind of test for it, so I was trying to use JUnit. That wasn't bad at all, my experience with NUnit and about 10 minutes reading on the web and I had it up and running.

However, I cannot get a simple date object to work, and that is what I want to write my first test against. I have read 20 examples online and they all are getting now, I want to be able to test against a specific time other than now. I'll just have to keep looking. Expect more posts as I learn how to do more things in Java.

Tuesday, November 14, 2006

ARG!!!

Or to borrow a quote from Dilbert "GAH!!"

I've been trying to get Rational Application Developer and Websphere Portal setup on my work computer now for over a week. Every day, all day, I just install and wait. This is the most painful installation process that I've ever been through.... Oh wait, I did try to setup a version of RedHat linux before that was more painful.

When are companies going to learn that the most pain in the ass introduction to their product is the installation. Even if the product itself is only so-so, at least it should have a super simple, error free installation process. Put the CD in, run it. There should be no other pains. I don't even like having to reboot in the middle, that's only an issue when the install is trying to touch shared functionality that is already installed. Why can't they just check for an existing version if it's new enough, then leave it alone.

I'm sure that using Java is not going to be nearly as bad as installing it. However, for just over a week, my computer has been practically crap. I haven't been able to do anything, because the install just kills it. This has got to be the most expensive install ever.

Thursday, November 09, 2006

Personal development

Isn't it amazing how a book can affect a person very differently depending on where he is in his own personal development? A person just starting out can read a book and think that it's total hogwash and crap, while somone several years into their career can read the same book and think it's a godsend. On the other hand, there are some books that are absolutely awesome, if they are the first one that you've read, but they aren't very good if you have read similar types of books.

Pretty much no matter what the first agile book I read was going to be awesome. It was introducing me into new ways of doing things that I was desperately ready for. But if I had been reading about agile in blogs and magazine articles for the previous year, then the first book would have just felt like a rehash of the ideas.

I notice this a lot when I read books. I'm always conscious of the fact that if I hadn't already read 10 other books on this topic, that this one would be really good. It's written well, I enjoy it, and the information is good. But I got part of it from book 1 and part of it from book 2 and most of the rest of it from book 3, but this one chapter was really interesting.

The other day I was discussing "The pragmatic programmer" with a friend and he was talking about how it completely changed his life, and I was a tad shocked. I'm reading it right now and there's only been one thing in it so far that I don't think I'm already doing. Then he told me, "Well, it was one of the first books of that kind that I read when I was just getting started programming". That made sense. A lot of books are that way. The book itself is timeless, but the timliness of it to the reader is very important. Jonas used to love for me to read him "Goodnight Moon", Then for a long time Ady wanted it everynight too. Now, neither of them want it, and I could probably recite it from memory, but before long, Jaden will love hearing goodnight moon. You get the point.

Here are a few books that I have read that I think are excellent, and really affected me, but it may have just been the timliness of reading them.
"Atlas Shrugged" - this is probably still by far my most favorite book. I've read the monstrous text 3 times. My favorite is probably still the 70 page chapter that John Galt takes over the radio. If you have read it, you know what I'm talking about.

"How to Win Friends and Influence People" Dale Carnegie wrote a masterpiece. I've read this twice in the past year, and I'm looking to try and go to some of his training on this topic. I've almost completely changed my attitude on several key areas in my life and they have not only made me more positive and happy, the changes have caused me less problems with others.

"Raving fans" This book made me want to do more customer service. For a time I seriously considered getting into some kind of sales role to be able to get the satisfaction that this book made me feel.

"Driving Growth through Innovation". This book is about idea generation and corporate creativity. Both of these topics are still very dear to me. A lot of the things that I do are done with creativity and idea generation in mind. I was so inspired when I read this book that I proposed an idea generation plan at my company and even volunteered to work on off hours to completely manage it. Yes I was probably crazy and wouldn't go that far anymore, but the desire to benefit from the awesome intelligence and creativity of all of the employees at a company still makes me giddy.

"Weaving the Web" a historical book about the origins of the internet by it's creator, Tim-Berner's Lee. I got a new perspective on what the internet could be and became a huge fan of blogs and wiki's which are Mr. Lee's original view of the internet.

"Keys to Success" by Napolean Hill. Dale Carnegie is the master of getting along with others, Napolean Hill is the master of self mastery. This book elevated my already strong dedication to continued learning.

"Getting things done". Ok, this one is a tentative entry. I'm only half through the book. I love it. I already feel better about my own organization and my stress level on a ton of things has drastically changed. On the flip side, I'm just starting to incorporate the process into my life and I don't know if it will stick long term. But I think that it will, mostly because I want it to and will dedicate myself to following through on it.

I could rant for days and days about the books that I've read that I hate, but I'll leave it with the ones that are most important to me.

True Geeks spin pens

That's right! True geeks can spin their pens and do all kinds of neat tricks with them, because we have notihing better to do. While others talk about relationships and watch daytime tv, we learn new things and practice our pen spinning.

If you are a beginning geek and you haven't mastered your own pen spinning yet, then I suggest checking out Pentrix. This is a site for geeks of all ages. Remember, you are what you do.

Wednesday, November 08, 2006

Posting Code

I've had some issues with posting my code samples. Blogger does not have a nice way for me to just copy my code into the post and have it show up nicely. Until I find something better I'm converting all of my source code to html and then pasting it into my post. This is not a simple process.. I have to copy my code into a converter, run the conversion, view the html code as source, copy it, and then paste it into my post. It would be nice if there were an easier way to do this. But for now, I'm using the longer conversion process. If you are interested, I use txt2html on the web to convert my code to html. It's a good free application.

Show and hide a div based on a dropdown list

I've been playing with some javascript. I've seen more and more web pages that show and hide pieces based on values in the page without reloading the page, so I wanted to see what it took. I searched and had to find answers at several different sites, so I thought I'd put my research into a single place. If nothing else, I can refer back to this later.

First, I placed the Javascript code to show and hide the DIV immediately after my BODY tag.

<script type="text/javascript">

<!--

function showmessage(id, id2) {

        if(document.getElementById(id2).value == 'MAC')
show_div(id);
else
hide_div(id);

}

function hide_div(id) {

        var e = document.getElementById(id);
e.style.display = 'none';

}

function show_div(id) {

        var e = document.getElementById(id);
e.style.display = 'block';

}

//-->

</script>



Then in my code where I want the message to go, I have a DIV tag.
<div id="sometimes" style="display:none;"><br>You really should select something else.</div>

I have the default set to hidden, because I only want it to show when a value is selected.

Finally, in order to show an hide it, there has to be a change that causes it. I have a select value determining whether or not the message is shown, but the examples I saw all showed it from an Anchor tag. Anytime a form event could fire though, the function could be called to show or hide the div.

<select ID="FavoritComputer" NAME="FavoritComputer" onChange="showmessage('sometimes', 'FavoritComputer');">

Tuesday, November 07, 2006

Synthetic Photosynthesis?

Scientists have discovered the structure of the catalyst for photosynthesis.

This is awesome. Photosynthesis is a very efficient way to split water and could be used to make Hyrogen cheaply. This is awesome. Making hydrogen cheaply is one of the biggest problems with going to a Hydrogen economy. Even if Hydrogen is healthier for the atmosphere and more efficient, it's very cost prohibitive at the moment.

Personally I'm a proponent of using renewable clean energy sources such as wind, solar, wave, and hydroelectic methods to generate the hydrogen to at least make it cleanly. However, all of these are fairly inefficient methods of generating electricity. There have been some great strides in both solar and wind efficiency over the past 2 or 3 years. Wave and Tidal energy are just in their infancy and nobody is benefiting from these at all right now, over the next 10 years while these kinds of energy plants roll onto the grid we'll at least get a little boost in clean energy. I haven't read anything about any kinds of improvements in hydroelectic plants to make them more efficient. We already have a lot of these, if they could be refitted with new hardware inside the plants that are more efficient, that would be another big benefit.

Tuesday, October 31, 2006

Another RSS Reader

Attensa has a free RSS Reader plugin for Outlook. There are some good and bad things about this tool. First, this is an awesome plugin for free. It does everything that I would want any RSS Feeder that plugs into outlook to do. Attensa is integrated very well into Outlook. When new posts arrive the information window pops up and lets you know, just like emails, and even MSN Messenger do. Most I like that intranet RSS feeds show up nicely in it. These feeds I only want to check when I'm at my work computer, at work.

I do have a few complaints. Personally, I would like an RSS feeder that integrates into outlook to make reading my feeds easy while I'm at work and that keeps in sync with a web version that let's me check on feeds from home. I really like how Google Reader is working for me right now. I am tagging and saving more posts than I had ever saved before. While using my previous RSS Readers, I would just read things and learn the new information, but I wouldn't save it for reference.

Generally my thinking is I read a ton of posts because if I know about something, then when a situation arises that I will need something like that, I'll remember having read it and can find it more easily. Otherwise, I fear that I'll spend too much time re-inventing the wheel to solve problems that someone else has solved, usually better than me.

Anyway, I really like Attensa for one reason. It integrates to outlook and can see my intranet RSS feeds. Currently there aren't a lot of these, but over the next year I expect the list of these to start growing. And I dont' want my intranet feeds on a reader that can't get to them, so Attensa is very nice to fill in this gap for me.

Monday, October 30, 2006

A beautiful thing.

There's a simple beauty to a pencil, especially mechanical pencils. Here's of why I love the pencil.
  1. I always know if it's about to run out on me.
  2. A pencil does not skip on paper over a spot that may have been touched by your finger.
  3. A pencil will write on an angle unlike a pen.
  4. I always know what color a pencil will write.
  5. I can buy lead refills and use the same pencil for years, which I have done. I even wrote the draft for this in a pencil that I've had for 3 years.
Ok, so it's geeky, but I love to write in pencil. Since I think everything should be stored electonically anyway, there's no point in having something writen in ink, so I can keep the paper forever. I don't want to keep paper forever, paper is temporary.

Friday, October 27, 2006

But they aren't agile.

Agile is sweeping the developing world. But it is not going without it's growing pains. I've not heard of anyplace that was able to switch to an agile process smoothly. We started switching almost a year ago, and we are still going through growing pains. However, Agile is designed to continually improve the process as well. The people who came up with agile just came up with a manifesto. What it means, is that there is no single way to be agile. Whatever works for you that fits with the idea in the manifesto, is agile. There are many processes that have become fairly common with agile, but none of them have to be used, because the Agile process stresses people not processes. Personally, many of my earliest complaints about agile were more that our Agile process is not Extreme Programming. Extreme programming is often viewed as Agile, and it's philosophies are very much the same, but it does stress certain processes. Anyway, the point I'm making is that Agile is an idea, not a process.

Recently, I heard a co-worker complaining that she needed help from another department by saying, "But they aren't on agile, I can't get them to do things as fast as we want." This caught me off guard. I fully support Agile. And being agile also means being flexible and communicating a lot. This incident felt a lot more like someone complaining about another group not dropping everything and jumping into action at the last minute. It's something that the complainer also would not have done if the situation was reversed, even though she's "agile". If you know that you will need help from someone, don't wait until the last minute to ask him for help. As soon as you have something that you know will need help, send an email with a heads up, "Hey in 5-10 days I have this thing that I'm going to need your help with". Then as you get closer and have a better defined list of what will need to be done send another email. "Hey in 3-5 days I need this thing done, it includes, X, Y, and Z. Please let me know if you will be able to get that done and when, so I can let my boss know." For a total of 3 sentences you no longer have a last minute issue. The person you need help from knows that something was coming and can make sure that their workload has some room for it. If they won't have room for it, they are able to tell you immediately. Finally, just because something is your number 1 priority, it doesn't mean that it's the other person's number 1 priority. Use this early and often communication both with the person you need help with and your boss/client to let them know what's going on and what issues may occur. And finally remain flexible. If the person who's helping you is not available, then let it push back. It's always better to get it right than to have to do it twice.

Getting Things Done

It appears that I'm a Johny-come-lately to this whole Getting things done following. Over the past month or two I have had glimpses of different things with GTD popping up. Then a conversation with a friend of mine who has read the book and believes wholly in the system prompted me to find out more information.

If you haven't heard, in short, GTD is a system to organize your entire life to help you accomplish more things. I've started reading the book, and it's a good book so far (not yet 1/4 the way through it), the only problem that I have is that I keep having things that my mind thinks of that I need to do. It's almost as if reading a book about being organized has gotten my mind thinking of all sorts of tasks that have been buried in it for a long time. The good thing is that GTD says you need to get these all out of your head and into a system to organize them. I've been making sure I write them all down and I've been using the Tiddly Wiki, which I blogged about previously, to keep my notes in. Just this week I have also seen that there is an enhanced version of the Tiddly Wiki that is organized around GTD, and today I read that there is a Firefox plugin that can be used to help organize your GMail to work better with GTD. If you are a tech person and haven't heard about it before now, then you will, it will be gaining popularity.

If you are even more interested, here is a good posted about getting started with GTD.

Thursday, October 26, 2006

VB6 Example

Private Sub SetFormCaption(ByVal strcaption As String)
'**********************************************************************************************************
' PURPOSE:
' Sets the Child Form's caption property when this control is loaded.
'**********************************************************************************************************
On Error Resume Next

UserControl.Parent.Caption = strcaption

End Sub


I am working on an application currently, and one of the functions is the function above. With my great and wonderful refactoring skills I have been able to cut out 6 lines from this function. Please see the wonderfully updated version below.

Private Sub SetFormCaption(ByVal strcaption As String)
On Error Resume Next
UserControl.Parent.Caption = strcaption
End Sub

Monday, October 23, 2006

Something not to do in C# Part 2 My Code

Here is my C# code for this. I am no longer writing that the file opened in 0 minutes, and I am using built in tracing functionality. I am also loading more information from the config file than the application was previously. there is even more that could be moved, but I have let myself live with a few things.

using System;
using System.Xml;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Data;

namespace AfniRemovalArchive
{
class Removal
{

private const string ConfigFile = "Archive.xml";
private TraceSwitch deleteTrace = new TraceSwitch("deleteTrace", "Trace deleted file information");

[STAThread]
static void Main(string[] args)
{
Removal rmv = new Removal();
try
{
ArrayList localDepartments = rmv.GetConfigurationSettings();
rmv.CheckDepartments(localDepartments);
}
catch(Exception ex)
{
Trace.WriteLine( ex.ToString() );
}
}



private ArrayList GetConfigurationSettings()
{
ArrayList localDepartments;
Trace.WriteLine("Get configuration settings Begin: " + DateTime.Now.ToString());
string configpath = Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location.ToString()), ConfigFile);
DataSet configds = new DataSet("config");
try
{
configds.ReadXml(configpath);
}
catch(System.Exception ex)
{
Trace.WriteLine("Get configuration settings: " + ex.ToString());
throw new Exception("Error reading configuration information", ex);
}
Trace.WriteLine("Configuration file loaded from: " + configpath );
localDepartments = new ArrayList();
// Create a list of Department configuration objects.
foreach(DataRow currentRow in configds.Tables["localdepartment"].Rows)
{
Department currentDepartment = CreateDepartment(currentRow);
localDepartments.Add(currentDepartment);
}
Trace.WriteLine( "Get configuration settings End: " + System.DateTime.Now.ToString() );
return localDepartments;
}
private Department CreateDepartment(DataRow currentDepartmentRow)
{
Department currentDepartment = new Department();
currentDepartment.departmentName = currentDepartmentRow["ldepartment"].ToString();
currentDepartment.localLocation = currentDepartmentRow["locallocation"].ToString();
currentDepartment.numberOfDays = Int32.Parse(currentDepartmentRow["numberofdays"].ToString());
return currentDepartment;
}
private void CheckDepartments(ArrayList localDepartments)
{
try
{
foreach(Department currentDepartment in localDepartments)
{
Trace.WriteLine("RemoveArchive for department " + currentDepartment.departmentName);
RemoveArchive(currentDepartment);
}
}
catch( Exception ex )
{
// something bad happened, log it, there is no recovery until we can see these errors.
Trace.WriteLine( "Error in CheckDepartments\n" + ex.ToString() );
}
}



private void RemoveArchive(Department currentLocalDepartment)
{
string[] archiveDirecotries = Directory.GetDirectories(currentLocalDepartment.localLocation);

DateTime cutOffDate = new DateTime(DateTime.Today.Ticks);
cutOffDate = cutOffDate.AddDays(-currentLocalDepartment.numberOfDays);
Trace.WriteLine("CutOffDate is " + cutOffDate);
int batchCount = 0;
for( int barcodeDir = 0; barcodeDir < archiveDirecotries.Length; barcodeDir++ )
{
string[] dirLocalBatch = Directory.GetDirectories(archiveDirecotries[barcodeDir], "*.ARCHIVE");
for( int batchDir = 0; batchDir<dirLocalBatch.Length; batchDir++ )
{
// check to see if i need to delete this directory.
DateTime createTime = Directory.GetCreationTime(dirLocalBatch[batchDir]);
if( createTime < cutOffDate )
{
Trace.WriteLineIf(deleteTrace.TraceError, "Deleting batch " + dirLocalBatch[batchDir] + " created at " + createTime );
Directory.Delete(dirLocalBatch[batchDir], true);
batchCount++;
}
else
{
Trace.WriteLineIf(deleteTrace.TraceVerbose, "Keeping batch " + dirLocalBatch[batchDir] + " created " + createTime );
}
}
}
Trace.WriteLine("Deleted " + batchCount + " batches.");
}

}

}

I'll also include my App.exe.config information. I leave a standard comment in my config files to make it easier for others to maintain later. I like to use Autoflush = true on the logging, this forces every write to actually write to the file. If you don't do this, you have to be particularly careful in your code to flush before ending due to an error, or you could lose the valuable tracing information that you need. I've never been comfortable with that, and always choose to set autoflush to true.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

<system.diagnostics>

<!-- Note that all listeners are used all of the time. When logging
at an information level you may want to turn off email, or you will get overwhelmed. -->
<switches>
<!-- value = 0 = Logging off. -->
<!-- value = 1 = Log Errors. -->
<!-- value = 2 = Log Errors and Warnings. -->

<!-- value = 3 = Log Errors and Warnings and Information. -->
<!-- value = 4 = Log Errors and Warnings and Information and Verbose. -->
<!-- value > 4 is assumed to be 4. value < 0 is assumed to be 0 -->
<add name="deleteTrace" value="1" />
</switches>

<trace autoflush="true" indentsize="0">
<listeners>
<add name="TextListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="\archiveTracing.txt" />
</listeners>
</trace>

</system.diagnostics>


</configuration>

Something not to do in C# Part 2 Bad Code

After I posted the other day, I got into looking at the rest of that class. The entire applicaiton was a single class, but there were things all over that were just annoying to me. Rather than rant too much about the code, I'll let it stand on it's own merits.

I will however point out a few of the things I found the most annoying.
1. The WriteTraceLine function writes elapsed time. The way that is called everywhere writes the number of minutes that it takes t oopen the tracing file. Even a slow process takes less than a minute so this writes a zero on every line.
2. DateTime.Now is passed in to WriteTraceLine everywhere, but not before being assigned to another variable the line before it.
3. Although this code reads a config file, the location of the trace file is hard coded. This is a problem when the application is deployed to a server and runs on the C drive, while the log should be written to the larger partition of the D drive.
4. CheckDepartments has a catch and finally that do nothing.

using System;
using System.Xml;
using System.IO;
using System.Collections;

namespace AfniRemovalArchive
{

class Removal
{
Department currentLocalDepartment;
string tracing;
ArrayList localDepartments;
StreamWriter traceFile;

[STAThread]
static void Main(string[] args)
{
Removal rmv = new Removal();
rmv.GetXmlSettings();
rmv.CheckDepartments();
}

private void GetXmlSettings()
{
DateTime begintime = DateTime.Now;
WriteTraceLine("Get xml settings Begin: ", begintime);

string path;
XmlDocument doc;
XmlNode root;

//the path of the MailWatcher xml will be the location
//of the service EXE itself.
path = Path.GetDirectoryName(this.GetType().Assembly.Location.ToString());
path += @"\Archive.xml";
doc = new XmlDocument();

try
{
doc.Load(path);
}
catch(System.Exception ex)
{
begintime = DateTime.Now;
WriteTraceLine("Get xml settings: " + ex.ToString(), begintime);
}
begintime = DateTime.Now;
WriteTraceLine("Get xml settings path: " + path, begintime);

root = doc.SelectSingleNode("/Archive/localdepartments");
localDepartments = new ArrayList();
Department departmentObject;


foreach(XmlNode department in root.ChildNodes)
{
departmentObject = new Department();
foreach(XmlNode depart in department.ChildNodes)
{
if(depart.Name == "ldepartment")
{
departmentObject.departmentName = depart.InnerText;
}

if(depart.Name == "locallocation")
{
departmentObject.localLocation = depart.InnerText;
}
}
localDepartments.Add(departmentObject);

}


try
{
root = doc.SelectSingleNode("/Archive");
}
catch(Exception ex)
{
begintime = DateTime.Now;
WriteTraceLine("Get xml settings: " + ex.ToString(), begintime);
}
tracing = root.Attributes["Tracing"].Value;

begintime = DateTime.Now;
WriteTraceLine("Get xml settings End: ", begintime);

}

private void WriteTraceLine(string txt, DateTime btime)
{
if(tracing == "On")
{

try
{
traceFile = new StreamWriter(@"c:\archiveTracing.txt", true);
}
catch
{
traceFile = new StreamWriter(@"c:\archiveTracing1.txt", true);
}
DateTime endtime = DateTime.Now;
TimeSpan elaspedtime = endtime - btime;
traceFile.WriteLine(txt + elaspedtime.Minutes.ToString() + " seconds: " + elaspedtime.Seconds.ToString() + " Date: " + DateTime.Now.ToString());
traceFile.Close();
}
else
{
if(traceFile != null)
{
traceFile.Close();
}
}
}



private void CheckDepartments()
{
try
{
foreach(Department department in localDepartments)
{
currentLocalDepartment = department;
RemoveArchive();
}
}
catch
{
}
finally
{
}

}


private void RemoveArchive()
{

string localPath = currentLocalDepartment.localLocation;

DirectoryInfo objLocalDirectory = new DirectoryInfo(localPath);
DirectoryInfo[] objLocalDirectories = objLocalDirectory.GetDirectories();

for(int a=0; a < objLocalDirectories.Length; a++)
{
DirectoryInfo[] objLocalBatches = objLocalDirectories[a].GetDirectories("*.ARCHIVE");
for(int l=0; l < objLocalBatches.Length; l++)
{
Directory.Delete(objLocalBatches[l].FullName,true);
}
}
}
}
}

Thursday, October 19, 2006

Something not to do in C#

private void WriteTraceLine(string txt, DateTime btime)
{
if(tracing == "On")
{
try
{
traceFile = new StreamWriter(@"c:\archiveTracing.txt", true);
}
catch
{
traceFile = new StreamWriter(@"c:\archiveTracing1.txt", true);
}
DateTime endtime = DateTime.Now;
TimeSpan elaspedtime = endtime - btime;
traceFile.WriteLine(txt + elaspedtime.Minutes.ToString() + " seconds: " + elaspedtime.Seconds.ToString() + " Date: " + DateTime.Now.ToString());
traceFile.Close();
}
else
{
if(traceFile != null)
{
traceFile.Close();
}
}
}


Don't do the same thing in a catch that you do in the try. The chances that it works the second time are slim. Besides, if there was enough of a chance for the first one to fail, this should at the least be in another try catch block. I know the two are opening different files, but that's not enough of an issue. It does cause problems of it's own when trying to track down issues. Even when logging is on I have to have both files open and go back and forth looking for specific issues.

Furthermore the function WriteTraceLine that this is in, is the only place that the variable traceFile is used, but it is declared to be at the class level. Finally, this ignores all built in tracing functionality in C# and relies solely on tracing off or on.

The filenames are not configurable, even though the application is using a custom config file. At the least that would allow us to relocate the files to a folder that could be shared out on the server, without having to recompile code.

Finally the Elapsed time that is being logged, is how long the function took to open the trace file. This is not an important issue, and is something completely separate from the actual informatoin that was sent to be logged in the first place.

Monday, October 16, 2006

Goals and Metrics.

I think a lot about goals and measuring them. For myself either I complete something or I don't.
Company goals and department goals are also different than personal goals.

For example, if I'm in charge of a department I have a department goal of x units to produce per day. What's being produced won't matter, widgits, phone calls, sales made, it's irrelevant. At my company I know specifically what it is that my goal is and making x of it is what I want. If I want to ensure that I make x, then I have to set up goals that each person needs to do their part to reach that goal, so each person needs to do x/person. Pretty simple math. If each person reaches 100% of their individual goal, then I meet my department goal and everyone is happy. If the group averages 100% then we are also all happy.

I know of a situation where this is not how it's being done. Instead the supervisors are watching their employees and figuring out how many each can do a day and then coming up with the goal in reverse. In essence, with total disregard for the amount of work that may be profitable for the department we are finding out how much work our users are actually showing us they can get done. We've done this in the past, but amazingly after coming up with how much can be accomplished on average, the department always exceeds 120%. An average day should be around 100%.

I have several major philosophical issues with this. First the average amount of work a day is the amount that we get when we are currently hitting 120%. Our numbers should be shifted to make this amount the 100% amount. Second, the amount of work that we are doing is not tied in any way to the amount of work that we need to be doing. I don't know what those numbers are, but it's conceivable that even 200% is not enough. If we are getting w amount of work done and it's only 50% of what we need to be getting done it should be reported as only 50%. Currently we are rewarding our employees for getting more work done on a normal work day than they did when they were being timed and knew it. Of course they all worked slower during the timing phase because they knew it would make it easier for them to acheive their goals. By reward I mean we are actually paying out bonuses for people who are able to meet more than 100% of the easy goals that they set for themselves. This is wrong.

Goals are simple and straightforward. Getting x done earns us money, our goal is x. Getting more than x done earns us more money and we offer bonuses. I sometimes wish I could just slap the manager that came up with this way of measuring performance.

Tuesday, October 10, 2006

Commenting Code

I was recently asked my opinion on commenting code and if there were any standards that I follow. I have been a big believer in commenting code as long as I've been programming. I used to add comments to my own Basic code that I wrote on the Commodore 64 even. It's always been strange to me to go into a very complex piece of code and not see any comments. I would pick it apart and come out with a dialog that commonly goes like this.

Me: "This code is doing thing A exactly.
Other: That code is supposed to be doing A and B.
Me: Ok, but I didn't know that. I can only tell you what the code tells me. It does thing A.
Other: Why wasn't this caught sooner.

When things like this happen it's always the same. Even if I've been working on a piece of code for a long time, I cannot notice and change the problem in a function like this. I can possibly refactor the code to make it do A more efficiently or easier, but I can't make it do both A and B because there are no comments.

I believe that there should be a comment stating what the purpose of something is. Especially in the agile process where the requirements are small pieces that generally do not generate much in the way of design. Having a comment in the code that says what the process is supposed to do, is a good way to help other developers with understanding the code.

Unit testing is a good "What the code does" documentation, but it's not used everywhere. Having good unit tests could prevent the need for needing the documentation, however, unit tests are not written in clear English. When I write unit tests, I like to document the "What" in my unit test class. However, I'm not consistent enough with my unit testing.

Ultimately, having documented what is supposed to happen somewhere is very important. It allows others later to come in and see if the code is working properly.

Wednesday, October 04, 2006

Podcasting

Podcasting is easier now than it has been in the past. There are a lot of people out there that do it, and even more that listen. My friend Joel using podcasting as his method of delivering the piano music he plays. Many others just talk about things going on in their life. I remember growing up when I would receive a cassette tape in the mail from a friend who had recorded herself talking to me instead of writing me. That was the coolest thing ever. I thought at the time, "It will be so awesome if someday this can be done faster than using the mail". Obviously even then telephones were an option, but long distance was not as cheap as it is now. Now I can talk forever on my phone and it will only cost me 30$ a month. I can't even imagine what my life would have been like if I had that option when I was in high school. I could have easily paid for our phone and talked almost my entire life away. Looking back I'm glad that was not an option for me. Really, with as much dead time as there is on the phone, I sometimes wouldn't mind if people would just record their thoughts and send them to me all at once, then I don't have to worry about them getting off topic because of a question I ask. I can just hear what they want me to hear and move on.

Anyway, podcasting is big. There's lots of good reasons to do it, and just as many good reasons to listen. I compiled a few small lists of reasons of what I think about podcasts. In general. Specifically, I think there is a lot of potential in podcasting, and I think that a very small group will be able to fully take advantage of it for what it can be used for. I also feel the same way about the TV. I'll leave that for another time though.

3 Reasons Why I don't podcast.
1. I don't like to hear my own voice.
2. I like being able to proof what I'm doing and organize and coordinate it.
3. I don't have a good quiet place that I could record my voice other than my car ride to and from work, at which point my focus is driving.

3 Reasons you should podcast.
1. It's faster to talk than it is to type.
2. Posting a podcast is as easy posting a blog (link to podcast posting instructions)
3. A podcast can be listened to from the computer without having to look at it. Busy people only need the time to start the podcast, then they can continue taking care of their kids or making dinner while listening.

3 Reasons I don't listen to podcasts
1. Podcasts are generally too long. I can tolerate a 20 minute podcast, but some of the technology sites I go to have 1 hour plus podcasts.
2. I hate commercials. Some of the podcasts I've heard have a 5 minute commercial introduction, I understand your have a need to earn money from advertisers, but this is annoying.
3. I hate rambling. Some of the podcasts I have heard are from people who have never had a public speaking course in their life. I understand being nervous in front of an audience, but this is in the privacy of your own home. It's like singing in the shower, you just do it and don't care if anyone is listening.

3 Things that would make me listen to podcasts.
1. If a podcast is short and downloadable, then I can listen on my short 30 minute car ride home.
2. Don't ramble. Try to organize your thoughts before you start talking, think about public speaking, please don't say "um" 600 times.
3. Be dynamic and excited. Some podcasts are just people talking, very monotone, "Buehler, Buehler" C'mon, you wanted to say this, so say it.

Tuesday, October 03, 2006

Google reader

There is a new RSS Reader available. I'm sure a new one is released practically daily, however, this one has been released from the behemoth Google.

Check out more information about it at the Google Reader Blog.

I have not decided yet if I like it better than NewsGator or not. I have imported all of my feeds, which was an easy task.

From NewsGator I had to select My Settings, then view the Edit Locations tab. The OPML link was at the top. I was able to open it and save it to my PC. Then I could upload it into Google. This is fine for me, but it's a bit more complicated for anyone not as technical.

There are some things that I like with the Google reader.
1. I like the ListView. It lets me read just the heading. For my sports feeds, that is all that they have anyway, so being able to get them all in a smaller space is nice. I can pick the ones that I want to go to the site and read, and which to ignore a lot faster.
2. I like the folder organization. It is a nice clean look.
3. I like being able to select veiw all and get back to something that I've marked as read.
4. I think I will like being able to star the articles that I find particularly interesting, especially the technical articles. I haven't used this yet, but I am guessing that it will work similar to Clippings in Newsgator.
5. Keyboard shortcuts. I hate the mouse, and wish every website that existed would spend a ton of time creating keyboard shortcuts.

Even Google is not perfect. There are some things that I do not like.
1. Google still does not use Ajax style functionality. The important toolbar type of links at the top of the page scroll off when I am looking down the page.
2. I cannot drag a feed into a folder. Sometimes I'm lazy when I add a feed. I'll add it in my general aread because I don't know if I want to keep it or not. Then after I've been reading it for a while I like to move it to a folder that it's related to to keep things organized. As it is now I cannot drag the feed to a folder. This functionality does exist for me in NewsGator. Google's solution involves opening the "Manage Subscriptions" page, selecting which folder to put it into and then going back to Google Reader to see the updated structure.
3. Google Reader does not refresh as rapidly as NewsGator. I have dug around and cannot find a setting that would affect this. Basically, during the writing of this post NewsGator found 5 new articles, Google Reader didn't find any of them. How much longer am I going to have to wait with Google to be able to read what is already available?

Monday, October 02, 2006

Change slow in coming.

It sometimes seems as if change only happens when a major crisis occurs. However, I think more often a mental attitude adjustment which coincidentally corresponds to a major crisis, is the actual cause of the change.

For example. I've been trying for quite some time to get people that I work with to use a Wiki to document things. I am in love with the Wiki. It's so open and honest. If I make a mistake in my documentation, it can quickly be corrected by someone who knows better, or learns better. I've been using is for over a year. That's about the time at which I realized that everything should be documented, everywhere. I started blogging about a month after I started using the wiki at work. It's taken over a year to get my fellow employees to start documenting also. The thing that held them back was twofold. First, all people resist change. Second, telling that resisting change makes them suck will not help them change.

Ok, on the second one I didn't specifically ever say it like that, but the meaning can often come across when not intended. I would tell people that they could make it so much easier on someone else if they would just add some documentation out there. For the cost of a few minutes or an hour one time, you can say something that's out there and able to be accessed by everyone forever. This is the greatest thing EVER!!!! This did not work. Granted, maybe the change didn't come solely from my own change in encouragement. There was a policy change at work that all of the sudden helped people see the same thing that I had been saying.

It started with me saying. If someone else spends a few minutes documenting, it can help you out dramatically when you need to do that. This was not enough. It was good, it was the right kind of change in phrasing, but it was not enough. At the same time, work changed their policy. Whomever was on production support had to do everything possible to resolve the problem before involving someone that is working on new development. At first, almost nobody knew about any other system. So when person A had a problem come in, a lot of research had to be done to find a resolution. It was not documented anywhere, it was in person Cs head. Finally person A would ask person C and get the answer. The real bonus came when I was person A. I documented a bunch of solutions on the wiki. The next person A saw the documentation and was amazed (a little self flattery here). Suddenly the other people were able to see the real benefit to themselves. It was no longer an imaginary possible future benefit, but something that was tangible and could be used right now.

I am still standing here shouting from the cube-tops. Use the wiki. Document anything that you had to learn to do this, it will be something that someone else has to learn in the future. If you are each doing it then you will each benefit. The full support for the additional documentation is not there yet. Maybe it will require another change in department policy. Maybe I'll be able to win over just one or two more people and then it will snowball. A leader is only a leader if others follow. It doesn't even make him a leader to be doing the right thing. If nobody is following, he's just doing the right thing alone.

Through most of my life I've thought that change only happened in a "Change or Die" type of situation. After a heart attack a previously lazy lifestyle is thrown away and replaced with a healthy active lifestyle type of thing. That's wrong. Over the past several years I've seen too many instances where a wake-up call and slap in the face came, and yet the receiver didn't do anything. Alcoholics who hurt themselves and others, but refuse to go to AA. People who have bipass surgery and contniue to behave exactly as they have before. Diabetics who are told that they will not only have a shortened life, but could have body parts amputated; they still do nothing. I'm not sure why this would be. Are we just so convinced we are invincible that we choose not to change? Are we just stuck in the mindset that, "If I'm a live I'm going to live like I want"? Why don't these people see that changing their habits does not mean that they are living less of a life, in many cases they could be livin more of a life if they changed. I don't know any of the answers to my questions. I have asked a lot and now sit and wonder how it is that we as a race can become more open to change. Is there a teacher that can lead us into an open-minded lifestyle?

I I found this great article on the psychology of change, I hope you enjoy it. I found it strange that after I started this post I searched for articles, and potentially a solution., that this article seemed in tune with some of my own thinking. This was by far the best article I found. There doesn't appear to be enough solutions in this area.

Wednesday, September 27, 2006

Thoughts on Tiddly Wiki

I mentioned last week that I was trying out Tiddly Wiki.

Pros:
Thns is a really neat application and implementation. It turns out that there are several variations on the theme on the web. I like that it's easy to save two copies, one for a daily journal, and one for a simple notes and todo list. I like keeping the two separate, it's easier for me to find my todo items itf I don't have to search through any journal entries that I'm making. I like that I can modify the source code. I haven't, but I like that control. I can look at it to learn as well as use it to play with new things that I learn. The entire application is a single .html file, making it portable, it can reside easily on even the smallest thumb drives. The editing is pretty standard, using the "standar" wiki editing format, that is used by many other wiki tools, including Media Wiki. Finally, there are a few keyboard shortcuts to prevent me from having to use my mouse.


Cons:
There aren't enough keyboard shortcuts. I like to be able to do as much as possible without having to use my mouse. It's a local wiki, which is great for my own todo lists, but I can't share it with anyone, at least without some additional effort. It may be possible to host the .html file on a service that allows me to share documents and have multiple people using it, but I think we are more often going to be overwriting what the other person does, if that's the case. Mostly though I just want to be able to share a read-only version of things. Being able to send the html for the visible tiddlers to the clipboard would be interesting, then I could just paste that into another application, it wouldn't be ideal, but it would make sharing my list easier. The default behavior is to make a backup copy of each change (just like a normal wiki), but to do that, the entire .html document is saved with a date-time stamp. Not an issue at first with a 160KB file, but what happens a year from now when I have a 5 MB document that is being backed up 3-4 times a day. I don't like the prospects of space that it can use. Too bad there is no built-in keep archive for 10 days type of function. Maybe I can write it.

My view:
There are more things that I like about this than I dislike. I'm planning to keep using it for a while longer to see if it continues to satisfy my needs. I haven't done much with JavaScript in the past, so I'm interested in looking at the source to learn new things, but It starts as a 51,000+ line file with nothing in it. I'd like the backups to only be the backups of html and not the entire javascript, but that will require some work on my part to understand how the code is curerntly working and to learn how to change it. The original site also mentioned several "plugins" for this application. I'm not sure what a plugin for an html file is, but I will look at them to see how they enhance the existing wiki structure. One of my biggest positives with this is that I can take just my thumb drive with me and be able to keep my notes no matter where I go. All new computers have a USB drive that I can plug into. There are a few places that I go that have old enough computers that they don't have a USB drive, but I'll just have to know that and take my laptop with me to those.

Thursday, September 21, 2006

Personal wiki

I have been looking at trying to find different options for journalling. I downloaded PowerJournal recently and was not happy with it. PowerJournal and the Desktop Sidebar that I like to use.

When I type in PowerJournal it makes the entire sidebar flicker.

Since I'm not excited about what I was using, I've started to look for new things. I use a wiki for a lot of documentation at work, and I figured there is probably a good wiki I can use on my own.

I know there are a lot of them out there, but the first one that I've run across and am trying is Tiddlywiki. So far this is about the coolest concept that I have ever seen. This wiki is an html file. That's it. There is no database, no php install, no web server. Open the Html file in a browser with javascript enabled and wow. There some plugins that can be downloaded with it as well, but for now I'll play with this for a few days and then post an update. I really like the idea of it just being an .html file. I have the entire source code, in the one file. I opened it and glanced through the code. I didn't dig into it though. With almost 52,000 lines in the file, it will be a while before I decide to dedicate that much time to understanding how it works. I wonder if something similar can be done with web pages through servers. A way for this wiki to reside on a server and be shared by others. Hrm.. Maybe that's something I'll have to research.

At least take the time to look at the page. Notice when you click on a lick it expands out into a new section that wasn't there before. It's a cool way to nest and group comments and have them all reside in the same page.

Wednesday, September 20, 2006

Java Training

I haven't crossed over to the other side yet. I'm in Dallas at Java training this week. I've been here all week. My trip here was a nightmare.

Monday I was in a fog and practically falling asleep in class. It's not the insructors fault, nor is it a dislike for Java. It's just that I didn't have enough sleep. We covered some of the basics of the Model View Controller pattern and where to use Servlets, JSPs and EJBs. The entire class is spent building up the same application. We start it from scratch and every lab continually adds to it. We setup a database using Cloudscape. This is a free database which is included with RAD.

RAD as it turns out is just a bunch of purchased plug-ins for Eclipse. The development is all done in Eclipse using the plugins to enhance the environment. I've never used Eclipse before, so I have no idea what the base functionality provides. The instructor mentioned that there are a lot of free plugins that would provide you with a very usable development environment.

Tuesday and Wednesday are both kind of a blur to me. I've had so much new information thrown at me that I'm not sure which way is which. I've learned about Java Beans and tags. I've learned about script funcitonality so I can use ${item.id} instead. I've also started working ahead on the labs and am currently working on custom tags.

Every little click I do in the IDE, I learn something new. "Oooh, I didn't know you can do that" is running through my head all the time. I would be lost if I wasn't following step by step instructions though. I'm learning a lot, but I also still don't understand practically anything. At least I understand the code (mostly). Now if I can just figure out why everything has to go where it does in the project.

File Modified time

I had a problem recently where a program provided to me exported 60,000 files. Only some of these files were exported with the modified time was set to the year 1617.

I wrote myself a little utility to set the last write time to now for any file that was not set correctly. this is a simple utility writen in C# VS 2002. Why 2002 insteady of 2005? Honestly, 2005 was taking too long to program in. There are some bugs with it that anytime it starts to show intellisense my PC freezes for the next 20 seconds to 4 minutes. Yes, I would type and wait 4 minutes for the next character to appear. Anyway, I went back to using what I knew would work better.

My original issues were that I was trying to verify that File.GetLastWriteTime actually showed me the 1617 date, but I had mistakenly put GetLastAccessTime. This caused me a lot of pain as I paced and cursed. But when I found my own small simple bug, I fixed it.

Here is the entire code showing the count of files that are updated. I did play with the formatting a little to reduce a few lines of code.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace SetDateOfFiles
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtFolder;
private System.Windows.Forms.TextBox txtResults;
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;

public Form1(){
InitializeComponent();
}

protected override void Dispose( bool disposing ){
if( disposing ){
if (components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
private void InitializeComponent(){
this.label1 = new System.Windows.Forms.Label();
this.txtFolder = new System.Windows.Forms.TextBox();
this.txtResults = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();

this.label1.Location = new System.Drawing.Point(24, 8);
this.label1.Name = "label1";
this.label1.TabIndex = 0;
this.label1.Text = "Folder:";

this.txtFolder.Location = new System.Drawing.Point(144, 8);
this.txtFolder.Name = "txtFolder";
this.txtFolder.Size = new System.Drawing.Size(200, 20);
this.txtFolder.TabIndex = 1;
this.txtFolder.Text = "C:\\MyFiles";

this.txtResults.Location = new System.Drawing.Point(24, 88);
this.txtResults.Multiline = true;
this.txtResults.Name = "txtResults";
this.txtResults.Size = new System.Drawing.Size(480, 160);
this.txtResults.TabIndex = 2;
this.txtResults.Text = "textBox2";

this.button1.Location = new System.Drawing.Point(152, 48);
this.button1.Name = "button1";
this.button1.TabIndex = 3;
this.button1.Text = "run";
this.button1.Click += new System.EventHandler(this.button1_Click);

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(528, 269);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.button1,
this.txtResults,
this.txtFolder,
this.label1});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main() {
Application.Run(new Form1());
}

private void button1_Click(object sender, System.EventArgs e){
txtResults.Text = "";
string[] files = Directory.GetFiles(txtFolder.Text);
int changeCounter = 0;
int filesChecked = 0;
int totalFiles = files.Length;
foreach( String f in files ){
filesChecked++;
if( File.GetLastWriteTime(f) < new DateTime(2000, 1, 1) ){
changeCounter++;
File.SetLastWriteTime(f, System.DateTime.Now );
}

if( filesChecked % 10 == 0 ){
txtResults.Text = String.Format("{0} of {1} files checked\r\n{2} files changed.",
filesChecked, totalFiles, changeCounter);
txtResults.Refresh();
}
}
txtResults.Text = String.Format("{0} of {1} files checked\r\n{2} files changed.",
filesChecked, totalFiles, changeCounter);
}
}
}

Thursday, September 07, 2006

Book Review: Why leaders can't lead

Why leaders can't lead

The Unconscious Conspiracy Continues by Warren Bennis.

Peter Drucker is quoted on the cover as saying Warren Bennis' background "makes Why Leaders Can't Lead the best book on how leaders can lead." I disagree. This book is much more of cynical. All but the last two chapter do nothing but complain about the way things are and the way people have handled situations. It is dated and spends much of it's time in the Nixon and Reagan administrations. For a leadership book from a former President of a University it was surprising how there were no specific suggestions of how to make Universities better. This feels more like Mr. Bennis wanted to make a buck by reselling the same book that he wrote 20 years ago by having it reprinted. Even the two chapters of suggestions don't feel like anything of substance.


Had I read the reviews at Amazon first, I probably would not have read the book. It is just too much of a rant. And for a book that's ultimately supposed to be about showing how to lead, I completely disagree with his practice of complaining 90% of the time. That's not leading, it's bitching.

Wednesday, September 06, 2006

What is a Great Developer

I have taken this completely from Eric Wise.

A great developer is a person who:

  1. Understands that different tools and languages excel at different tasks. They do not engage in "zealotry" choosing only one pattern or paradigm and jamming it into every problem situation.
  2. Understands that the goal of development is to produce "Working Software". Anything that distracts from working software should be shunned.
  3. Realizes that they will not be the only or last person to experience the code. Avoids unecessary complexity and comments where appropriate.
  4. Gets along with other developers. Realizes there are many solutions that can viably solve a problem and that their way is not always right or best. Is able to be a leader and take direction equally well.
  5. Gets along with end users. Is able to explain technical concepts in "layman terms". Over time, builds a trusting relationship with end users and becomes an advisor, not a dictator, for software requests. Makes every effort to learn the domain from the user perspective.
  6. Is intellectually honest. Does not over or underestimate deadlines, provides software in a timely fashion.
  7. Is always watchful. Constantly looks for ways to improve the day to day productivity and end user experience.
I thought that there could be some other things added. Here are my additions
3b. Documents the process to make it easier for others to understand.
7b. Is constantly learning new skills and techniques to use when appropriate.
8. Is available to listen, and offer suggestions when approached by other developers.
9. Is always available to others.

I believe that the great develop has great skills, but is also available as a mentor. Relationships with clients take time, but are equally important, always take an opportunity to improve your relationships with your clients.

Scroll wheel working

Victories come in small packages.

I have been having to program in VB6 a lot lately and I've been very annoyed by the fact that my scroll wheel doesn't work here. This is the only application that I have that the scroll wheel doesn't work on. The funny thing, is that several years ago I didn't even want a scroll wheel. Now I want to beat someone with a rubber duck if they have a mouse without it.

Anyway, out of frustration, I downloaded and installed the Logitech drivers on my PC and viola!!! I can use my scroll wheel. I also stumbled across a Microsoft post regarding this problem. If you have it, try installing your drivers first, it's probably more reliable than depending on the drivers built-in to the OS. But if that doesn't work then install the VB6MouseWheel.exe.

Tuesday, September 05, 2006

NUnit Addin

I've been wondering why NUnit hadn't just been integrated with the IDE, now I don't have to wonder. It has been.

If you are using VS2005 and want to use the NUnit plugin with your IDE, then get it from Netlogics. I link to a site other than sourceforge, because the installation instructions are here.

Friday, September 01, 2006

Text Parsing

Oooh. I am going to get to take 1 file that's 120 MB and parse it into approximately 40,000 files.

We received a single text file that contains the 40,000 files together, so I will get to write the program to find the start of each bill, find the account number and all information for that file, parse it and write it out to it's own file, containing the entire record wanted.

I'll post if there are any interesting challenges from this. The file appears to be fairly straight forward. There may be 3 or 4 challenges because it contains information from 2 different companies and the other company appears to have 2 or 3 formats for their data. I'll have to make sure I can recognize the format, then pull the required information from the required location.

Monday, August 28, 2006

A simple logging function

I love to use the built in tracing functionality. However, sometimes I want logging for a sublevel .dll that I do not want to attach to the standard tracing files. Whenever I encounter this kind of a situation I fall back on a simple WriteToLogFile function that I wrote a long time ago. I usually have the .dll know about it's own log file and call this function from a helper .dll This has proven a very useful function when I need to log in .dlls without relying on a Tracing being turned on.

static public void WriteToLogFile(string filename, string output)
{

System.IO.FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read);
Byte[] OutputArray = new Byte[output.Length];
for ( int i=0; i < output.Length; i++)
{
OutputArray[i] = Convert.ToByte(output[i]);
}
fs.Write(OutputArray, 0, OutputArray.Length);
fs.Close();
}

Sunday, August 27, 2006

Standard Maintenance pages

I've been helping a friend out with websites recently, and I am constantly writing a fairly standard type of maintenance page. Almost every page has the same layout, and fields. It ties to a single table from a database and allows the user to edit all of the fields. Occasionally some of the fields are dropdowns or option buttons, but mostly they are simple text fields.

I'm thinking of writing a program to generate this standard maintenance page and all of it's code with all of the fields defaulted to text boxes. Then I can modify a mostly complete page to finish it.

I think it will be a fun program, now to find the time to do it.

T.V. a waste of time.

"T.V. is the great equalizer. The assasination of John Kennedy and David Letterman's stupid dog tricks are absolutely equal." -- Warren Bennis.

The book I'm reading has an entire chapter on how TV is wasting our times and how it is preventing leaders from emerging. I disagree. I think TV allows leaders to reach a large audience who otherwise would not have been able to. I believe the internet goes a step further. However, I do agree with one thing he says. TV is a great waste of time. The content that is on TV is terrible. The format of what we watch has gotten worse, and commercials are taking over more and more of the television. A typical 30 minute program has 5-10 minutes of commercials, with another 5-10 minutes of the show itself being used as a medium to show a companies wares; every 30 minutes we are bombarded with 10-20 minutes of advertising. While we sit on our butts and do nothing and learn nothing we absorb the advertising. I myself am guilty of it. I even blog about commercials that I think are clever. This is part of the reason that I only really like to watch sports on TV. I still don't grow, from the TV, but at least I get to watch a competition. Sport though, are even worse with advertising. Ads have been placed in the ballpark in such a way as to almost always be on the TV. The Nike swoosh on the clothes, the Rawlings insignia on the gloves. The backdrop behind home plate, even the world series had tv tricks last year to make advertisements look like they were on the field when they were only camera tricks.

I spent some time this weekend channel surfing looking for a program to help expand my mind. I found one. I think MythBusters could actually be considered a learning program. However, the rest of everything on TV. was solely entertainment. I have decided to reduce the amount of TV that I am watching. I will no longer watch these shows. When I go to bed, I will not turn the TV on to anything other than a sporting event. Erin can watch what she wants, I will close my eyes and sleep.

What will I be giving up when I give up TV? I'll be giving up my frustration. I'll be giving up my annoyance with commercials and programs.

What will I be gaining? I hope to be gaining more quality time with my children. I hope to not have TV distracting me from blogging, reading my newsletters, and reading books after the kids go to bed.

I will now take control back into my life and remove as much TV from it as I can. As I wrote this blog I turned off the Cubs vs. Cardinals game.

Friday, August 25, 2006

Comments available

Talking with someone who read this blog, I found out that he wanted comments available. I guess something I wrote was worth commenting on.

In any case, I have gone back through most of my old posts and turned comments back on. There are still some that I didn't think that anyone would need to comment on, so I left them disabled on those posts. On all of my posts going forward comments will be enabled. I hope you enjoy the topics that I cover. Feel free to comment and ask questions about the artidcles.

Thursday, August 24, 2006

Unit Testing Problem

I previously wrote about keeping Unit tests as stand-alone tests. This is the correct practice, However, doing so can sometimes cause a problem.

Problems occur when trying to test a boundary object, especially if it has complicated rules about how it works. The best thing to do in this instance is to replace the boundary object with a Mock Object that implements the expected results. If you don't plan for it, this can cause a shift in your design. For example:
puclib class ClassToTest
{
private boundaryClass myBoundary;
}

This is not good anymore. This code specifically ties ClassToTest to the boundary class. However, the boundary class could have the problems. Instead ClassToTest should have the boundary object passed to it, and code to an interface.

public class ClassToTest
{
private IboundaryClass myBoundary;
public ClassToTest(IboundaryClass boundaryClassItem)
{
myBoundary = boundaryClassItem;
}
}

This is a good chunk of code now, because boundaryClassItem can be either the actual boundary item (as it will in the deployed program), or it can be a mock object (which it will be in Unit Testing).

In my particular case, the login function being called by each test is a problem. However, for the purpose of testing each as a stand-alone item everything works fine.

The problem is that Login can only be called once nicely in on the boundary class and have the process work correctly. So NUnit itself is actually breaking my boundary class. However, a Mock class that allows that will allow NUNit to run successfully. I will at least have the confidence that everything except my boundary class works correctly, and then just try to fix bugs if they occur.

Tuesday, August 22, 2006

Unit Testing Do's and Dont's

Unit Testing is awesome and can be a huge help in validating that changes to code doesn't cause any problems anywhere else in the application. There are a few small guidelines to make sure you follow.

1. Unit Tests should be completely independent of each other. The order of tests is not gauranteed. Thus any setup code that happens all the time should be factored out into a function with the SetUp attribute. If the setup code happens on a lot of the tests, then create a private helper function that is called from each test to initialize values.

2. Unit Tests are good. Do them.

3. Name your unit test for what it is testing. Test1_GetFiles is not good. The test number is not important and can actually get confusing later when inserting new tests. TestGetFiles or Test_GetFiles is a good name. However, since only functions that have the Test attribute will show up in NUNit nameing it GetFiles is also useful.

4. Code that is in the function with the SetUp attribute should still be tested. If the SetUp is initializing a variable to an object or to a specific value, then have a test that just validates that the initialization worked. For Example:

int FilesExpected=0;
[SetUp]
private void Initialize()
{
FilesExpected = 10;
}

[Test]
public void TestNumberOfFilesExpected()
{
Assert.AreEqual(10, FilesExpected);
}

Strategy or Template Pattern

The training that I had last week was perfect. It put patterns into my mind and I have recognized that I have a problem to solve that requires either the Strategy Pattern or the Template pattern.

But how can I decide which one?

Problem description.
Iterate through a folder containing a list of files. Connect to a backend system. Process the files.

This itself does not lend itself to the pattern, it is not until I checked out the code from the repository that I see that we already have 2 other applications (they look like they were copy and pasted) that do the same basic logic. There is a slight difference in the processing of the file, but the logical flow of the application is exactly the same in all 3 instances.

Strategy Pattern according to James Cooper in C# Desing Patterns
"The strategy pattern consists of a number of related algorithms encapsulated in a driver class called the Context. Your client program can select one of these differing algorithms, or in some cases, the Context might select the best one for you. The intent is to make these algorithms interchangeable and provide a way to choose th emost appropriate one."

Template Pattern according to James Cooper in C# Desing Patterns
"The Template pattern formalizes the idea of defining an algorithm in a class but leaving some of the details to be implemented in subclasses."

I think they could both be made to work, but the Template pattern sounds better. So can build the base class, derive my class from it, and build a front end to use my new generic class. Then I need to refactor the other 2 implementations to make them also fit and I can have a single front end that can handle calling all implementations.

I like this whole patterns thing, I wish I had known it sooner.

Monday, August 21, 2006

Yes or No

I just finished reading Yes or No. This is a great short book by Spencer Johnson. You can read some of my other comments on it over on my non-geek blog.

This is a short book that could be read in 2 hours or less if you have time to dedicate to it. It took me 4 days of off and on reading. The program presented in the book to help make better decisions is a good thing. Basically any program to help make better decisions is a good thing if you use it. This book says that too. In order to facilitate better decisions you need to ask yourself 6 questions.

3 practical questions
1. Am I pursuing the real need?
2. Am I informed of my options?
3. Have I thought this through to a better result?

3 private questions
1. Am I really telling myself the truth?
2. Does this decision really feel right to me?
3. Do my actions show I believe I deserve better?

If you answer yes to everything then you do it, if not then rethink the process.
Spencer Johnson has once again written his book in the form of a parable, and there are times that the main character was frustrating either by stating the obvious, or by suddenly remembering a quote that fit perfect. For some reason the quotes were annoying because they were always stated by the guy who didn't know the system. The book was good though and it was definitely worth the time to read it. I would however suggest checking it out from a library vs. purchasing it. 20$ seems like a lot to spend on a pamphlet.

Wednesday, August 16, 2006

The more I know

I feel like a stupid kid sometimes when I get to the design portion of my work. I sometimes feel like I have trouble thinking in design.

I hope that as I continue to learn more and more about design patterns and Java I'll start thinking design more and be able to build better applications.

Tuesday, July 11, 2006

Problems with Agile

Ok, to start with I don't personally have problems with Agile. In fact Iove everything I've read about agile, however at my company we are having a lot of problems incorporating it into our department.

Issues.
  • SCRUMS (Daily Standups)
    • Our projects are not big enough to require multiple developers or iterations generally. Thus the developers almost never care about what the other developers are doing.
    • Our projects are not big enough to require multiple iterations, so our updates are really only to find out if there are any questions and if we will still be done during this 2 week iteration.
  • No gain in momentum
    • As much as I love working on a variety of projects I don't like the fact that if something hangs over, it just hangs over. I don't ever accomplish any more amount of work from iteration to iteration, because each iteration I'm starting over with having to understand a new process and start design again. This is not a problem in that it slows down everything, but it's dissapointing mentally to not be able to gain that momentum and make it look like I'm improving.
    • Management seems to want to push us to do more as if we are gaining momentum, but it's just not possible, in fact due to some recent turnover we not only are completing fewer stories (as would be expected with fewer developers), we are also taking longer on each one and having more hangover because we have lost a huge knowledge base and have to relearn things that we could easily ask someone in the past.
  • Deployment problems
    • It may be that the developers are now getting more things developed, but because of the additional layers of testing and sign-off added, we are not being able to deploy our solutions. Eithe we don't have enough BAs to handle the process, or we are not getting the buy-in from the client (our internal end users) that is required in an Agile world, to be able to move quickly.
    • After a story has sat in User Acceptance Testing for a while and is finally completed, the client feels that the application should be able to be deployed immediately. In another environment this may be the case. Where I work though, all of the deployments are to internal clients. At the same time our testing environment is not the exact same as our live environment. There is almost always some setting up and preparations that need to be made post UAT signoff and deployment. This adds to the time pressures that we have as well as to potential reduced client satisfaction.
  • Time pressures.
    • Yes time pressures always exist, but our time is booked pretty well with story card development and the standard meetings that we need to attend in order to continue the requirements gathering and estimation process for future story cards. This leaves very little time for bug fixes (thankfully this has not been much of an issue for me).
    • A deployment is not a hands off process here. We are involved in retesting the live deployment, verifying DB changes and any other setting changes are made correctly. We work with the clients to verify that the installs work correctly. None of this time is allocated for within our normal iteration.
  • Narratives
    • Our narratives never seem to be fully developed. We are constantly starting projects (with only a 2 week cycle) where we are still trying to gather requirements or understand what is being asked for.
    • Our narrative tells us exactly what to do and not why something is being requested. This has caused rework many times because the solution provided did not deliver what the client wanted.
    • There is a misunderstanding from our BA group in what they think the developers need and what the developrs think they need. I think this is due to the implementation process of Agile where I work. We took the group of people where were kind of good client contacts and put them into the roles of BA without giving them any training. Thus we have a group of BAs doing their best to get a job that they don't understand done.
  • Insufficient 'items' for developers
    • We did not get enough Agile training to start with. Bringing an Agile process into the department is a big process. It's not easy to implement and everyone has to understand what is required of them to make it work. Communication is a very big part of it and everyone needs to understand the high level of communication that they will need to be involved in.
    • We have application requests for technologies that not all of our developers are capable of accomplishing thus preventing some things from being played in the order that's actually most beneficial to the company. Having all of the developers able to do everything will prevent this, but we need to make sure that everyone knows all of the technologies.
    • Permissions. Not all of the developers have the same permissions. Thus when one person is no longer able to work on something, for being out sick or on vacation, not just anyone can pick up where he left off. We don't have the same permissions and must spend the next day or two getting permissions. Giving all the developers all the permissions that they need can make reduce this delay and prevent the frustration by all of the developers.
    • We do not have a test environment for some systems. That is just out of our control. However, most of the things that we do could have a test system. As a company more funds need to go into these test systems to allow a better testing and an easier transition from testing to deployment.
  • Lack of documentation
    • Not specifically an Agile problem, but a lack of documentation has been made more apparent with the agile process. One application may have 5 enhancments done by 5 different developers over 5 different iterations. The documentation for each of these enhancements is not being kept in a good central location for everyone to be able to understand what has been worked on in the past and what they may have to keep in mind with their own work.
    • A card is sometimes designed by one developer then developed by another. The desing of the card to the one who made the design makes sense because of the additional information that is gathered through conversation and stored in the mind. However the new developer picking up the card does not have any of this information and the design documentation becomes inadequate and leaves the same holes that have already had to be understood empty. Time is lost finding the same answer twice. Part of this could be reduced with better narratives, but even if the design documents were more accurate for everything that is known about the process then someone else could pick it up a lot easier.
    • Design reviews should catch this more often. If a design reviewer has to ask a single question, the question or the answer to the question should be added to the design documentation.
I have noticied a few positives that I would definitely like to point out.

  • SCRUMS
    • This is a place the a problem can be called out for everyone to know about.
    • This provides a place that help can easily be requested from fellow developers.
    • Personally I think these can be reduced. Questions should be emailed or called about immediately, we should not wait until the following day's stand up meeting.
  • Narratives
    • The narratives have been getting slightly better. A narrative coming from within IT instead of from Ops is a lot better, I hope the BAs can learn from all the additional amount of information that is given by an IT person that we need that amount of additional information from our clients.
    • Additional training for the BAs is still needed.
  • 'Items' for developers
    • Additional training is coming. It's hard to just up and train everyone at one time, so bringing everyone up to speed is a slow process that will probably take the next full year, which puts us a year and a half into our Agile expiriment. I think it will get better, but we have to weather the bad.
  • Documentation
    • We have a wiki and shared network drives that documentation can reside in. Both locations are accessible to all of the developers and can be uesd easily. Personally I prefer the wiki, because it's also more easily searchable and items can be cross linked easily.