Wednesday 30 December 2009

A sad day...at least for me

On Sunday I decided to boot up my two-and-a-half year old Philips X58, which came originally with Windows Vista, but now dual-boots the trial version of Windows 7 and Ubuntu 9.10. It had just booted Windows up when, all of a sudden, it died. At first I thought maybe the power had gone, as the power supply was pretty worn out, but it had the battery in and as far as a I knew it had some charge in it. I tried pressing the power button, which did nothing, and that's when I started worrying because even if power wasn't reaching it from the power supply and the battery was discharged, there would be enough power left to get the battery warning light to flash, but nothing whatsoever was happening.

I noticed that the light on the power supply was flickering, rather than being steady, so I googled it, and apparently that normally means power is reaching the adapter, but can't be passed on to the computer. A bit more research led me to believe there were several possibilities:
  1. The power supply was broken.
  2. The connection from the power socked on the computer to the motherboard was broken.
  3. The fuse in the power supply had blown.
  4. The motherboard had been fried by a power surge.
Ominously, there was a faint whiff of burning from inside the computer. I took the back off to have a look and couldn't see anything obviously wrong with it, so I figured I had to eliminate the power supply as an option. So I ordered a new power supply for it.

This came yesterday, so I tried it with the laptop, but it was the same story - flickering green. So it looks like the motherboard on this machine is gone. Humph, just the Christmas present I want...

This is frustrating because the machine isn't actually that old (half as old as my Dell Inspiron). I have also noticed one of the hinges has a crack in it. I'm looking into how much it might cost to repair it, but it's a rather awkwardly-designed laptop and I'm really not convinced it's going to be a worthwhile proposition repairing it. So it's likely I'm going to have to replace it.

I was actually considering the possibility of buying a new one with Windows 7 anyway (even though I last bought one only in October, a Dell Mini Inspiron with Windows XP), so this does at least come as a valid excuse to buy a new machine. Despite my preference for Unix-like OS's, I do still like having the option of using Windows around.

I'm thinking probably another Dell - despite what so many people seem to say about Dell, all my Dell's have been great computers. My Inspiron I bought in 2004 is still going strong, and my Axim PDA works well too. The Mini Inspiron has also proven to be a good machine in the short time I've had it. My dad's Dell desktop was hit by a power surge last year which damaged the motherboard but would still power on (it just had regular BSOD's) so it was more resilient than my Philips, and it was easy to repair. I've found Dell's to be simple, reliable, efficient machines, and that suits me fine. The only issue I've had with them is the crapware they install, and even Apple do that (cough...iWeb...cough).

Maybe I should branch out into getting a desktop as I've always had laptops in the past?

Friday 18 December 2009

RATM for the Xmas number one!

Just wanted to voice my support for the campaign to get 'Killing In The Name' by Rage Against The Machine to the 2009 Christmas number one slot in the UK! I harbour no illusions about it changing the face of the music industry or getting The X Factor off our screens or anything like that, but it'll be worth it just to piss off Simon Cowell! I already have the album, but I bought a copy for precisely that purpose!

If you're in the UK and haven't bought it yet, here's a link to buy it on Amazon. At 29 pence, it's an absolute steal!

Thursday 17 December 2009

Validation

It can be quite hard to tell whether your programming skills are up to scratch if you're not doing so professionally or otherwise producing code that will be scrutinised by others, such as for an open-source project, or being taught in a classroom environment. You can't help but think "Am I doing a good job?", and it's difficult to get outside validation.

So today, when I came across a blog post referring to the FizzBuzz Test I thought I'd have a go. I decided to use Python as that's the language I know best, but I was a bit concerned about being a bit rusty as I haven't done much Python coding for a while due to concentrating on other things. As it turns out I needn't have worried. Here's the code I came up with:

def fizzBuzz():
for i in range(1,101):
if i % 3 == 0 and i % 5 == 0:
print "FizzBuzz"
else:
if i % 3 == 0:
print "Fizz"
elif i % 5 == 0:
print "Buzz"
else:
print i

fizzBuzz()

Not too shabby, and if this blog post is correct, it puts me ahead of a few people who are already working as full-time programmers! After doing that, I felt a bit better about my skills.

I wrote a Python script a few months back when at work we had to use one Excel spreadsheet among many, many people to update some details. If you've used Excel a lot, you may know that this can be a recipe for disaster - if you have sharing disabled, only one person can use it at once (and inevitably someone will go to lunch with it open), and if it's enabled you run the risk of someone overwriting what you've just entered. In frustration I wrote the following Python script to allow me to update the file without going into it. Please note that it requires the xlrd and xlwt modules:

# Spreadsheet Updater
# Written to allow an Excel spreadsheet to be updated automatically without opening it manually

from Tkinter import *
import xlrd, xlwt, datetime, tkMessageBox

class Application(Frame):
"""GUI application that takes data to be input into a spreadsheet. """
def __init__(self, master):
""" Initialize Frame. """
Frame.__init__(self, master)
self.grid()
self.create_widgets()

def create_widgets(self):
""" Create widgets to get information to enter into spreadsheet. """
# create instruction label
Label(self, text = "Enter details for a new entry in the current spreadsheet (saved as Current Month)").grid(row = 0, column = 0, columnspan = 4, sticky = W)

# Policy Number
Label(self, text = "Policy/Scheme Number").grid(row = 1, column = 0, sticky = W)
self.policy_no = Entry(self)
self.policy_no.grid(row = 1, column = 1, sticky = W)

# System
Label(self, text = "System Number").grid(row = 2, column = 0, sticky = W)
self.system = Entry(self)
self.system.grid(row = 2, column = 1, sticky = W)

# Log Ref
Label(self, text = "Log Number").grid(row = 3, column = 0, sticky = W)
self.log_ref = Entry(self)
self.log_ref.grid(row = 3, column = 1, sticky = W)

# Name
Label(self, text = "Name").grid(row = 4, column = 0, sticky = W)
self.ph_name = Entry(self)
self.ph_name.grid(row = 4, column = 1, sticky = W)

# Reason for Change
Label(self, text = "Justification for change").grid(row = 5, column = 0, sticky = W)
self.reason = Entry(self)
self.reason.grid(row = 5, column = 1, sticky = W)

# Incorrect Data
Label(self, text = "Incorrect Data").grid(row = 6, column = 0, sticky = W)
self.incorrect = Entry(self)
self.incorrect.grid(row = 6, column = 1, sticky = W)

# Correct Data
Label(self, text = "Correct Data").grid(row = 7, column = 0, sticky = W)
self.correct = Entry(self)
self.correct.grid(row = 7, column = 1, sticky = W)

# Spacer to separate Correct Data from Validated
Label(self, text = "").grid(row = 8, column = 0, sticky = W)

# Admin Validated
Label(self, text = "Have Admin validated change?").grid(row = 9, column = 0, sticky = W)
self.validated = StringVar()
admin_validate = ["Yes", "No"]
admin_column = 1
for entry in admin_validate:
Radiobutton(self, text = entry, variable = self.validated, value = entry).grid(row = 9, column = admin_column, sticky = W)
admin_column += 1

# Admin Informed
Label(self, text = "If not validated, Hand off to Admin method done?").grid(row = 10, column = 0, sticky = W)
self.informed = StringVar()
admin_inform = ["Yes", "No", "N/A"]
admin_inform_column = 1
for entry in admin_inform:
Radiobutton(self, text = entry, variable = self.informed, value = entry).grid(row = 10, column = admin_inform_column, sticky = W)
admin_inform_column += 1

# Admin details
Label(self, text = "Admin Details").grid(row = 11, column = 0, sticky = W)
self.admin_details = Entry(self)
self.admin_details.grid(row = 11, column = 1, sticky = W)

# Processor
Label(self, text = "Owner").grid(row = 12, column = 0, sticky = W)
self.processor = Entry(self)
self.processor.grid(row = 12, column = 1, sticky = W)

# Create a submit button
Button(self, text = "Click to submit", command = self.update_spreadsheet).grid(row = 13, column = 0, sticky = W)

def update_spreadsheet(self):
""" Create a Python list containing all the values from the application, plus the date, and append it to the spreadsheet. """
# get the date
raw_date = str(datetime.date.today())
year = raw_date[0:4]
month = raw_date[5:7]
day = raw_date[8:10]
date = str(day + "/" + month + "/" + year)

# get policy number
policy_no = self.policy_no.get()

# get system
system = self.system.get()

# get log ref
log_ref = self.log_ref.get()

# get name
ph_name = self.ph_name.get()

# get reason for change
reason = self.reason.get()

# get incorrect data
incorrect = self.incorrect.get()

# get correct data
correct = self.correct.get()

# get Admin Validated
validated = self.validated.get()

# get Admin Informed
informed = self.informed.get()

# get Admin details
admin_details = self.admin_details.get()

# get processor
processor = self.processor.get()

# create a Python list to hold the elements for adding to the form
new_entry = [date, policy_no, system, log_ref, ph_name, reason, incorrect, correct, validated, informed, admin_details, processor]

# If an element is empty, bring up a warning and break out
all_complete = True

for entry in new_entry:
if entry == "":
all_complete = False
break

if all_complete == True:
try:
self.write_to_spreadsheet(new_entry)
self.confirm_message()
except:
self.fail_message()
else:
self.incomplete_message()

def write_to_spreadsheet(self, new_entry):
""" Method to import the contents of the spreadsheet to memory, then save it again, overwriting the original. """
# Import the spreadsheet as a Python list with a nested list for each individual row
book = xlrd.open_workbook("Current_Month.xls")
sheet = book.sheet_by_name("Sheet1")

entries = []

for i in range(50000):
# if the first cell of the current row is empty, break out of the loop
try:
entry = []
for cell in sheet.row_values(i):
entry.append(cell)

entries.append(entry)

except(IndexError):
break

entries.append(new_entry) # Add the new entry to the spreadsheet

# Write the resulting list back to the spreadsheet
new_book = xlwt.Workbook(encoding="utf-8")
new_sheet = new_book.add_sheet("Sheet1", cell_overwrite_ok = True)
i = 0
for entry in entries:
j = 0
for item in entry:
new_sheet.write(i, j, item)
j += 1
i += 1

new_book.save("Current_Month.xls")

def confirm_message(self):
# Display a message confirming input processed
tkMessageBox.showinfo("Confirmed!", "New entry confirmed!")

def fail_message(self):
# Display a message warning input failed
tkMessageBox.showerror("Error!", "Error in writing to spreadsheet!")

def incomplete_message(self):
# Display a message if not all fields are completed
tkMessageBox.showwarning("Incomplete!", "Warning! Form not completed in full!")

# main
root = Tk()
root.title("Spreadsheet Updater")
app = Application(root)
root.mainloop()


Sadly, it doesn't show up well in Blogger - the ends of some lines are chopped off. I was quite proud of it - it does the job I wrote it for, which is all I can ask, and it looks fairly elegant to me. Sadly, I wasn't able to use it at work as it would have required everyone who needed to access the spreadsheet to have Python installed, and I was not able to get this (I won't go into why, but I do understand the reasons I was given, and they were pretty good, and potentially I could have done the same thing in VBA, if I knew it, without needing to install any software).

This put a damper on what I would like to have done next - written a second script to export the contents of the Excel spreadsheet to an SQLite database, then created an amended version of the updater to update the database instead of the spreadsheet, then finally written another script to export the contents of the database to another spreadsheet, thus enabling us to use a database to record the data in the first place (a much better solution!) while still retaining the option of getting it in spreadsheet form if necessary.

So I had this code just lying around, without a use. I've therefore submitted it to Useless Python - as at right now it hasn't been accepted yet, but hopefully it will be. I'm looking forward to people's feedback about it - for that matter, please feel free to comment here! I would welcome any constructive feedback.

In the last couple of years I've learned HTML, and a fair bit of Python. Earlier this year I finished my CIW Foundation course, and then spent a couple of months studying C. Even though I kind of got stuck on pointers, I learned quite a bit, and now any programming language whose syntax is based on C is a lot easier.

I'm also beginning to understand why so many experienced programmers say that they can learn a new language in a week or so. I'm now studying JavaScript and much of the syntax is almost identical to that of C, so it's very easy to pick up the core language itself. Also, a lot of concepts are common to virtually all programming languages - if/then statements, while and for loops are near-universal, for example, so you only have to learn them once.

I've now bought the books for the CIW Master Enterprise Developer certification, and it means I'm going to have to learn JavaScript, Perl, PHP and Java, as well as classic ASP and SQL. Assuming I complete it, I will have qualifications to validate my abilities, but for my money that's not what makes a great programmer.

A great programmer is someone who writes code that does the job efficiently, but is also elegant and easy to understand. Qualifications can't tell you how elegant or efficient your code is, nor how readable it is. And this is where it gets really hard to get validation - you can know your code works, but it's very difficult to know if it's good code if you don't have a wealth of experience.