Jake Scruggs

writes ruby/wears crazy shirts

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Friday 7-30-04

IntelliJ IDEA 4.5 just came out and there's a been a flurry of emails about how it lets you analyze your code. The Martins (Micah and Bob) are trading barbs about whose code is more redundant. Paul looked some 10 year old code he was working on and it had hundreds of repetitions. I've only just installed 4.5, so I haven't had time to try the new features. Dare I analyze my old projects?

The pawn is killing me. My chess program takes the pretty obvious tact of having a ChessPiece interface from which all the pieces inherit. Bishops, Knights, Rooks, don't really need to know about the ChessBoard. You can just give them their move and they'll tell you if it's legal. The ChessBoard will do a check to see if any pieces are in the way of a move. But the Pawn -- What a jerk! Pawns can move two spaces on their first move but not on their second. That's not too bad -- I'm using a state pattern to take care of that. But they attack on a diagonal if and only if there is an opposing piece for them to take upon that diagonal square. Also they can do this weird en passan thing if another pawn passes them by making a two square move, but only on the next turn. It's crazy insane. So now I'm faced with the possibility of passing in not only a ChessBoard, but a LastMove to all the ChessPieces even though only pawn really needs it. Well, actually, the King also needs to know about the board for castling, but I'm trying to fight one war at a time. I've been thinking about creating a special moves class which would check for pawn diagonal attacking and en passan and other things. But that's pretty ugly too as the pawn logic is going to be in a number of places. Hmm.

Of course all this is a little silly because the rules of chess haven't changed in over 200 years are aren't likely to change any time soon. I could, in theory, couple the code as tightly as I want. But the whole point of this exercise (for me) is to learn something about managing dependencies so I'm going to pretend that the rules may change.

Some sort of program that analyses the quality of your code? Is this the birthplace of metric_fu? Not really, just the beginning of a thought that really didn't mature until much later.

I love that I'm trying to keep knowledge of the board away from the pieces. I really spent a bunch of time drawing UML diagrams and thinking about dependencies before writing any code. If nothing else, it was good practice thinking about design.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Thursday 7-29-04

So I was doing one last re-install of Word Press, just to make sure I understood everything that could go wrong -- But apparently there was one more thing. I just couldn't sign in from my laptop when I pointed it's browser at the Linux box. I know I had the right login and password because it worked on the other machine. After spending too much time messing around in the Linux terminal, I went back to my laptop, deleted the cookies associated with that website, and everything was fine.

Cookies are a problem.

The chess program is proving to be an interesting problem. Everything wants to know about everything else. Must... Manage... Dependencies...


"Everything wants to know about everything else" I fight this battle every day. And I continue to fight cookies and other browser state tricks. State is the enemy.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Wednesday 7-28-04

Not a whole lot going on today. I messed around with Word Press. Paul continues to remove the html from FitNesse. Which is more like storing the html inside methods so that the chance of a typo is reduced -- if you have to constantly add in a bunch of cryptic strings then you probably will mistype somewhere which can cause hard to find problems. However, if you make a method that adds in a html tag, then either every instance of that tag works or fails. The IDE will tell you if you've entered the method correctly, thereby reducing the chance of a typo causing a troublesome error.

Susan and Ellen are pretty swamped under the pressure of getting XPAU up and running. David's having a good time with his class, but they're working him like a red headed stepchild.

I got to meet Micah's wife Angelique and their cute-as-a-button son today. Luka responds to French, because Angelique was born in France. We all had a good time watching him toddle around OM. 'Don't put that in your mouth' seems way cuter in French.

My Earthlink DSL is down at home. I sent the Earthlink crew a long email detailing all the things I tried. They sent me back a standard response that asks if I've tried shutting down the computer and modem and then restarting. Of course, I mentioned that I had already done this in the initial email. Sigh.

Earthlink? I forgot that I had DSL for awhile -- it was terrible. Now I have RCN and it's terrible. For awhile I had Comcast and it was terrible. There's a theme here... Is moderately fast and reliable so hard to figure out? This morning I spent 10 minutes waiting for a 10 meg podcast to download. It still had '25 minutes' to go when I had leave for my train.

I saw Luka a few months ago -- He's still very cute. And he has an iPod touch.

I want an iPod touch. Luka has a portable game machine/music player 10 times better than all the audio/video equipment I owned before the age of 25. Oh to be the child of a nerd with money.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Tuesday 7-27-04

Today I worked on cleaning up Word Press so that it looked nicer and behaved better. Alex King was nice enough to hold a contest for the best Word Press skins and publish the results here:

www.alexking.org/index.php?content=software/wordpress/styles.php

For now, 'But Uncle Bob,' is using the 'Dark Fire' skin. I also spent a fair amount of the day figuring out the various features of the program so that I can teach Micah when he comes back. Once you get it working (and, if the server has already been set up for you, that is not too hard) WP is a nifty little program. Tomorrow I think I'm going to wipe the Linux box, reinstall the OS, and put WP back up because the first install was so crazy that I'm not completely sure I can repeat it without wasting a whole bunch of Micah's time (Micah's off in Philadelphia this week coaching some company called Primavera) .

Somewhere in the middle of all this, it has occurred to me that there is a fair amount of irony involved in blogging about trying to set up blogging software. But the bigger question is: now that I know how to get WP up and running will this blog become a Word Press blog?

Probably not.

Not that I hate the program, but I'm not interested in its advantages. Right now I type my post in MS Word, then do a little cutting and pasting via TextPad, and upload with an FTP or Web-based file manager. Upgrading to Word Press would allow people to post comments, or let me set up a list of users who are allowed to post, but I don't much care about that. If somebody wants to comment they can email me. Also, I'm not sure about how long this blog will last after August 18th (the last day of XPAU and my last official day with OM). After that I'll either have found a new job in software development (Interested in hiring me? Send an email and we'll talk.) or I'll be back teaching physics to teenagers.

David's Advanced Object Oriented Design class is going well this week -- one of his students speaks Portuguese and so does David! What are the odds? It's a worldly class, other class members are from Italy and India. There was a little trouble the first day when they turned up their noses at the complementary Crispy Cream donuts. One student even when so far as to pejoratively call Crispy Cream's 'So very American.' Look, you can take shots at our foreign policy, but insulting our donuts is asking for trouble.

Hostilities, thankfully, were avoided.

What? Still talking about WordPress? Boring.

It's funny that I'm talking about entering the blogging world while a fair amount of my colleges have abandoned serious blogging for Twitter. In my quest to be continually 2 years behind the times I'll be announcing my Twitter mash-up website soon. Via stone tablet.

But seriously folks, I am indeed on the Twitter where I am known as jakescruggs. I recently spent a bunch of time tweeting about the movie 'Bolt.' Seemed like a good idea at the time.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Monday 7-26-04

Word Press is up and running! I had a bunch of ideas when I arrived, but before I got too far I said to my self: 'Self, maybe you outta try starting Apache, MySQL, and run install.php from Mozilla just one more time' Well, I wouldn't be telling ya about it if it hadn't worked. Of course when I say it worked, I mean that the install actually started but not that everything was fine from the get go. First I gave it the path that the wordpress folder was in, but not where the files were. So everything failed, but did so is a way that I could see that every place it was looking was missing a '/wordpress' so I fixed that. Then I tried to look at it on another computer but I was getting a screwed up version of the site. What wordpress really wants when it asks for the location is something like this: "181.783.13.1/wordpress" Eventually that'll be something a wee bit more user-friendly, but it'll do for now. Finally the install went smooth. Excellent.

So why did this take forever? Here's the Reader's Digest version: Red Hat Linux automatically installs MySQL, PHP, and Apache so when I attempted to install XAMPP (which is a bundle of the three) things got a little nutty. Same problem when I tried to install MySQL, PHP, and Apache separately. But all this might have been fine if I had known that the way you're really supposed to run install.php is not from the command line but by typing in install.php in a browser pointed at your sever (which, for me, would be http://localhost/wordpress/wp-admin/install.php). Over a week went by with me trying everything I could think of but it didn't matter because every time I typed in 'php install.php' I got the same error telling me that: maybe MySQL isn't running, maybe your server isn't running, maybe you set up the password/username are wrong, or maybe PHP is configured wrong. Not one of those things actually turned out to be the problem, but I did learn lots about Linux, MySQL, PHP, and Apache in the process.

In response to my request for a side-project, Micah has suggested that I join the club and write a chess program. This may keep me busy for awhile.

The weekend in Michigan was fantastic. My former boss gave me 'a bicycle built for two' (are you thinking of the HAL 9000? I am) and it's been rusting in my backyard for 9 months. On Friday, I took 'er apart and crammed it into my Saturn (no easy feat, mind you. but nothing some WD-40, the wrong tools, and a whole bunch of swearing couldn't fix). Father and son were able to put the tandem back together in Michigan and it's a whole busload of fun! The brakes are a little dicey and the tires might be leaking, but everyone's your friend on a tandem. Cars slow down to look, kids laugh and point, people wave and say nice, friendly things. Riding along the lakeshore with my wife was quite the time. Here's a picture:

Bike for Two

So I started the 5 minute install back on July 8th and now, a mere 17 days later, it is complete. By the way ButUncleBob.com (the blog I was trying to set up) had a good run from 2004 through 2006 but has since been retired/mothballed.

Recently my team needed to find out if a point was inside a given polygon and, as usual, we found some code on the internet that did what we wanted. And, as usual, there wasn't much explanation as to what it was doing. Here's the code (after we converted it to Ruby):




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def contains_point?(point)
c = false
i = -1
j = self.size - 1
while (i += 1) < self.size
if ((self[i].y <= point.y && point.y < self[j].y) ||
(self[j].y <= point.y && point.y < self[i].y))
if (point.x < (self[j].x - self[i].x) * (point.y - self[i].y) /
(self[j].y - self[i].y) + self[i].x)
c = !c
end
end
j = i
end
return c
end
end


So, you know, it works and I'm grateful to somebody for posting it but we had no idea how it works. So we wrapped 2 tests around it (one where the point is not in the polygon and another where it is). But that one method had a Flog score of 80 -- it was killing me. Also 2 tests where nowhere near exercising all the possible paths through this code and since it was completely un-obvious as to what was going on this was just a bug waiting to happen.

I decided to refactor this method so that it made a wee bit more sense. I did a little bit of reading on the internet about the ray casting algorithm, got out a pen and paper, and figured out what the hell was going on. Before I go on to explain how I changed the code, I should probably explain that we are using GeoRuby to give us a bunch of geometric classes and we added the contains_point? method to GeoRuby::SimpleFeatures::LinearRing. Inside a LinearRing instance self[0] is the first point in the polygon, self[1] is the second, and so on. Also, point.x gives you the x value of the point. Oh, and self.size returns the number of points in the polygon

Here's the refactored code:




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def contains_point?(point)
contains_point = false
i = -1
j = self.size - 1
while (i += 1) < self.size
a_point_on_polygon = self[i]
trailing_point_on_polygon = self[j]
if point_is_between_the_ys_of_the_line_segment?(point, a_point_on_polygon, trailing_point_on_polygon)
if ray_crosses_through_line_segment?(point, a_point_on_polygon, trailing_point_on_polygon)
contains_point = !contains_point
end
end
j = i
end
return contains_point
end

private

def point_is_between_the_ys_of_the_line_segment?(point, a_point_on_polygon, trailing_point_on_polygon)
(a_point_on_polygon.y <= point.y && point.y < trailing_point_on_polygon.y) ||
(trailing_point_on_polygon.y <= point.y && point.y < a_point_on_polygon.y)
end

def ray_crosses_through_line_segment?(point, a_point_on_polygon, trailing_point_on_polygon)
(point.x < (trailing_point_on_polygon.x - a_point_on_polygon.x) * (point.y - a_point_on_polygon.y) /
(trailing_point_on_polygon.y - a_point_on_polygon.y) + a_point_on_polygon.x)
end


And here's what I think this algorithm is doing: If you take any point and draw a ray from it, in any direction, and that ray crosses through the sides of a polygon 0 or and even number of times then the point is outside the polygon. If the ray crosses the sides of a polygon an odd number of times then it is inside said polygon. If you don't believe me get out a pen and paper and draw it or look at this wikipedia article.

So the contains_point? method starts out by assuming the point is outside the polygon since its ray has yet to cross any of the borders. Then it needs to look at each line segment of the polygon (otherwise known as a border or edge) so, if you look at the i and j iterators, they are working their way around the polygon and are used to define a point on the polygon and the point immediately preceding it. Now the algorithm looks to see if the point in question is between the max and min y values for a given line segment using the appropriately named point_is_between_the_ys_of_the_line_segment? method. If that's true then a horizontal ray could travel through the current line segment. But it might not, depending on which way it is traveling. So the next method 'ray_crosses_through_line_segment?,' checks to make sure. Now if the ray has crossed through the line segment, or edge, of the polygon you set contains_point to the opposite of whatever it was. Why? Well if it had crossed 0 times contains_point would be false and one more crossing would bring it to a total of 1 (an odd number) and so contains_point should now be true. Every time you find another crossing you flip from odd to even or vice-versa and so you must flip the variable also.

Not too hard, huh? But if there are many sides to your polygon (and we sometimes have lots of sides) then this can be quite a slow operation to do en masse (and we are planning to do it very en masse) so while doing some research for the refactor I found an optimization:




1
2
3
4
5
6
7
8
9
def outside_bounding_box?(point)
bb_point_1, bb_point_2 = bounding_box
max_x = [bb_point_1.x, bb_point_2.x].max
max_y = [bb_point_1.y, bb_point_2.y].max
min_x = [bb_point_1.x, bb_point_2.x].min
min_y = [bb_point_1.y, bb_point_2.y].min

point.x < min_x || point.x > max_x || point.y < min_y || point.y > max_y
end


A bounding box is the smallest possible box that can completely contain a polygon. If you draw a bounding box around the polygon, check to see if the point is outside the bounding box, and it is then you're done. You fail fast because if the point is outside the bounding box there is no way it is inside the polygon. GeoRuby gives you a bounding_box method for free (but it's not too hard to find the max and min x's and y's of a polygon) so I was able to create the above method and insert it into the original pretty easily:




1
2
3
4
def contains_point?(point)
return false if outside_bounding_box?(point)
# rest of method as shown above
end


Now contains_point? will give up early if there's no chance.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Thursday 7-22-04

Finished up the patterns class today and I have to say that David did a pretty good job. With new material, not much teaching experience, and Paul and I firing questions at him he was able to get through the class rather easily. Sure there were some confusing slides and weird-ball patterns, but the cool thing about OM giving him this week to flesh out the course is that he can make note of the problems and then talk to Micah or Bob to straighten things out. Next week he does it for real with paying customers and I think he'll do fine. I, however, need to write more code. This Word Press/Linux/MySQL/Apache/PHP adventure I've been on has been very informative but sorely lacking in full-on coding. I need to remember to ask Micah (or Bob, or David, or Paul) for some advice on a side project to make me a better programmer. If any of you are reading this and feel like emailing me an idea, feel free. Life without cool little software projects is less fun.

Tomorrow I'll be heading up to Michigan to see my folks and hang out at the cottage. There are some pictures of my last trip here.

The cool little side project from Micah will turn out to be not so little.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Wednesday 7-21-04

Our payroll UML diagram (from yesterday) had some needless complexity but, other than that, it was fine. Well, mostly fine.

Lots more patterns today. Many of the patterns boil down to the server-client relationship. Let's say you have a laser scanner object that can scan a bar code and identify a product. There's also going to be a sale object which gets a message from the scanner and then does some sort of sale stuff. Well now the scanner has to have code that knows about the sale and the sale might even have code that depends on the scanner. This system is now tightly coupled. But if you stick and interface between them, you can have them both know about the interface and not each other. Therefore swapping out the scanner for another one doesn't affect the sale code. And changes to the sale don't affect the scanner object. Patterns can be way oversimplified as the proper placement of interfaces. Too many and you've got needless complexity. Too few and the code is tightly coupled and hard to maintain. All these patterns have trade-offs so the big deal is not just knowing how to use them, but being able to figure out if they're necessary/will help your project.

My project for the afternoon was, of course, banging my head against the Linux box. Apache keeps insisting that I don't have permission to run the install.php program, but everybody has permission to use it. Hmm. At least Micah had some trouble when he tried to figure it out. I'm always a wee bit worried that the thing that's been bugging me for days is only 30 seconds worth of work for a pro. So I went back to prowling through the httpd.conf file (a set-up file for the apache file server) for things to change or adjust. The day ended with Micah and me pretty stumped.

The big message I took away from Object Mentor that summer was that although patterns are cool and can help a lot, they add complexity. It's a complexity/coupling trade-off. A message that has stayed with me. Just today I was looking at some code that could have been refactored to be more DRY, but way less intentional and I had to make a call as to wether the project would be better served by adhering to one principle or another. That's the thing about writing code that is meant to be understood by humans: The hard part is not learning the language, patterns, or principles, but knowing when to use them and where.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Tuesday 7-20-04

Second day of A.O.O.D. and I'm getting pretty good with UML. Today we discussed the various principles of software development: Single responsibility, Open/closed, Liskov, Interface segregation, and Dependency inversion (Which, all together, spells S.O.L.I.D. - you can learn things from XPAU mouse pads).

Paul an I spent an hour or so trying to design an system that could take in information about a bunch of different types of employees. Then, after we designed a system with enough interfaces and uses of inheritance to avoid violation of the principles, more user stories were added and we had to refactor. It was an initially frustrating, but ultimately fun project to take a system and make it do something new without, hopefully, coupling the classes together too much. I think we got it, but we'll find out tomorrow morning if we did.

Bob said he liked my blog, especially the bit where Micah came back after a week, looked at out project and asked us what we thought we were supposed to do. Apparently this is a pretty common experience in software -- after a few weeks the customer looks at what you've produced and either realizes that what you did isn't what s/he asked, or what they asked for isn't what they really want. One of the big points of XP is trying to make this conflict between intent and execution happen earlier rather than later. There's always going to be changes to the system, but big ones need to happen early (changing the look and feel of the GUI -- not so bad, changing a 2-D side scroller into a 3-D first person shooter? Little bit more difficult).

I still have one of those 'S.O.L.I.D.' mouse pads - I don't really need it for my optical mouse but I have it. Also nice to have an Uncle Bob (Martin) sighting. People often ask me about all the Object Mentor employees I must know, but most of them were off teaching classes at the client site or doing agile/xp coaching during the summer of 2004. I mostly hung around with David, Paul, and Micah that summer and had shorter interactions with the rest. The same thing happened at ThoughtWorks were people would assume I knew this, that, or the other person who worked there while I did. But often person 'X' was in Texas while I was in New Jersey and our interaction was limited to possible bumping into each other at a company function.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Monday 7-19-04

Today was the first day of my Advanced Object Oriented Design (AOOD) class. David's teaching Paul and I in order to make sure he's familiar with the material and can teach paying customers next week. After covering the usual X.P. verses Waterfall stuff and briefly touching on how good OO design can keep your code loosely coupled (in a tightly coupled design each class depends on several other classes, which in-turn depend on a few other classes and so on. The bad news is that changing one class means that you have to change every other class that depends on it. And since everybody is holding hands with everybody else, that could mean hundreds of changes for each modification. No me gusta. Loosely coupled code has objects that, through interfaces and clever structure, can be changed without having to track down bunches of dependencies) we moved on to some UML (Unified Modeling Language -- a way to get a global view of the code you are about to write). Which is cool because although I've been looking at and trying to draw UML for a month or so now, I could really use some formal training. We used UML to design a state machine that strips code of its comments. In a few languages (mostly C derived) two slashes mean that the rest of the line is a comment and should not be read by the compiler. Or anything between a slash and a star and then another star and a slash is a comment. For example:

Not a comment // comment all the way 'till the end 'o the line

Not a comment /* comment */ not a comment

So we wrote out a bunch of UML and it was pretty interesting. I like all the cases where the object loops back to itself -- I don't know why I find that cool, I just do. After working on that SMC for a week or so I had a pretty good foundation in State Machines but it was fun to try out my ideas on something new. Later we had to make a UML diagram for a cash register. There were a number of user stories which we had to accommodate. Knowing something about teaching, it didn't come as a great surprise that this exercise was supposed to be a bit of a failure. The were multiple dependencies and inversion violations and single responsibility problems as far as the eye could see. And this was after an hour's work. But the point of the class is to get us to be able to use design patterns to eliminate (or at least minimize) these problems. It's basically a patterns class. Patterns are the idea that many programming problems boil down to the same idea and that there are well thought out ways to deal with these common problems.

Oh, and I've got a potential solution to the Word Press problem. The install.php file needs to be run by the server. In other words, I need to request the file from Apache which knows to execute .php files. Interesting. This was nowhere in the installation notes, but I guess they probably assumed that anyone trying to set up a server would know how things are done with servers. I didn't have much time today to try out this idea (which Micah came up with) but maybe tomorrow. Although, with the class this week I won't have a lot of extra time.

Weird that I just had dinner with David (Chelimsky) and his lovely lady friend Flor and now I'm writing about him teaching me a class. David and I actually live in the same condo complex in Rogers Park. This happened more or less by accident. David currently works for Articulated Man and I for Obtiva -- we've never worked together professionally but have remained friends.

Did you see that part about how you're not supposed to run the install.php file through the command line but by hitting it through a web-browser? I didn't know at the time that Apache would just figure the rest out and the people who wrote the instruction manual probably didn't think they had to point out something so basic. A common problem when I was getting into software was that no explanation was basic enough for the likes of me.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Friday 7-16-04

Today I rode my bike into the city in search of a passport. City Hall: Big, confusing, lots of stairways leading to locked doors. First goal: Get a birth certificate. Long line, filled out misleading paperwork wrong, but accomplished. Second goal: Get passport. Not so fast, Mr. man, this office is closed inexplicably for an hour starting... Now. Kill time, eat pizza, come on back. I was waiting at the wrong place! Even thought the sign above the door clearly said 'U.S. Passports.' But the real passport place is upstairs in the same room where you apply for city jobs.

Silly of me.

For all those of you who like to complain about yer passport photo, I'd like to point out that you probably didn't wear a bike helmet in rain and let your hair dry in a pizza parlor before you got your photo taken. Did ya? That taken care of, I paid the nice lady $160 ($85 for city and federal fees, $60 because I want the passport sometime this year, and $15 for the photo) and peddled my soggy self home.

I remember being pretty worked up about asking Object Mentor for a day off so I could get my passport. They were very cool about it. On the other hand I was working for free that summer. And by working I mean floundering. They were probably excited to have a day where they didn't have to listen to me complain about a '5 minute install' all day long.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Thursday 7-15-04

So I downloaded and installed Apache -- which wasn't too much trouble. But MySQL was a different story. When typing in the bizarre list of commands to install it, I made a slight typo which took a little while to track down. But, even worse, I ran into the same problem as before -- MySQL would run but Word Press couldn't find it. After a lot of messing about I finally figured out that Linux had installed MySQL automatically and that was causing conflicts. Which I couldn't figure out how to resolve. Before I installed PHP I decided to look and see if it was on the hard drive. I found the documentation, and when I typed in PHP at the command line something happened. But I couldn't find where the files where installed. If this were windows I would have some idea how to go about looking for things. Add/Remove programs can tell you what's installed. The find function in Linux doesn't seem to work as well as windows. This is all part of the big problem here: I don't know Linux yet and so all my usual tricks do not apply. Thursday ended with Word Press' 'five minute install' as yet to be completed. It'll have to wait 'till Monday because tomorrow I'm heading downtown to get a passport. In theory, you only need a birth certificate and a driver's license to travel to Canada, but I have these visions of my flight taking off as I try to convince some large man that I really am a U.S. citizen. Best to be sure.
Turns out most Linux installs come with Apache, PHP, and MySQL -- this supporting of common developer tools was weird to me coming from Windows where if it's remotely useful it must have a heinous install and cost a lot of money.

Why was I going to Canada? Because that year's XPAU (Extreme Programing Agile Universe (Now just called Agile as in 'Agile 2009' - have I mentioned that I'm speaking at it?)) was in Calgary that year. Object Mentor used to organize XPAU, so it was a pretty big deal for them. And me. I think this might have been the last year Object Mentor was running the show.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Wednesday 7-14-04

The problem with a 'five minute install' is that if you go beyond 5 minutes, you are screwed. A five minute install is doing a lot of things behind the scenes. If those hidden processes fail, then you don't have anything to look at. The configuration file for Word Press is very simple: You tell it the database's name, the user's name, the user's password, and where to look for the server. Once you've verified that the database does exist (by messing around in MySQL), the user has access, and the password is correct then only the server is left. Which is quickly crossed out by accessing the database through the server (which is running on the localhost). Now what? There's really nothing else to change.

After banging my head against this all day (Well not actually all day. When I arrived this morning the power was out and so I had no access to the Linux box. When the power came on, there was no internet until a number of things were restarted. Most of the mess got sorted out by 11am.) I have come to the conclusion, with Paul's help, that this Appache/PHP/MySQL bundle I've been using (which is called Xampp) may not be working correctly. There's also the issue of MySQL being installed in two places on the machine (I didn't know it was already there) so Word Press may be trying to access the wrong place. Or there's the fact that .php files aren't being recognized as PHP files unless I specifically run them by typing, for example: php install.php All this leads me to believe that I probably am going to have to uninstall Xampp and set up Apache, MySQL, and PHP the old fashioned way.

I better not have to re-re-re-install Linux.

Here's a bit of weirdness: Last night I woke up at 3:43 in the morning. As I blearily stared at the clock I thought "3:43, that should be public static."

Paul mentioned that he isn't allowed to use most of what he knows in his college programming classes. If he writes tests, he has to strip them out. And if he were to use a Visitor pattern and his professors didn't understand it he would be marked down. So he spends 9 months out of the year having to ignore what he learned in the other 3. That's not cool. Speaking of the Visitor pattern, it looks like I'm going to get to take a class at Object Mentor in advanced object programming and patterns. David is scheduled to teach this class, but since he's only taken it once, he wants to teach Paul and I first so that he can get his moves down and spot potential questions. Good for him and me because, although I've heard people talking about patterns in the office, I've only used the state machine pattern and not much else.

I wonder how test-friendly colleges have gotten in the past 5 years and if you make students write tests will they learn to hate them? I know a lot of students would ask me to teach them something about Quantum Physics because they had read a cool article or seen a 'Nova.' However, when they actually had to study about quarks and weak forces they were decidedly less enthusiastic.

So which one of the potential problems I outlined with the 5 minute install do you think is really the cause of its failure? The 2 databases? Xamp? The .php files not being recognized? An unsuccessful install of Linux? And how many more days before the 5 minute install draws to a close?

"public static" -- funny.

So there have been a bunch of metric_fu releases since I announced 1.0.0 on this here blog. It's now up to version 1.1.4 and we've added:

  • Flog, Flay, Reek, Roodi, and Rcov now have graphs over time (thanks Édouard Brière).
  • Cool, dare we say 'Awesome,' templates for the metrics (thanks Nick Quaranto and Edouard Brière).
  • Flog report now tracks average Flog score per method and the average of the worst 5% of your methods.
  • MetricFu now works with Ruby 1.9.1 (thanks to Robert E. Rouse for his help).
On to the pics:

flog

main metric_fu

stats

saikuro

roodi

reek

rcov

flay

churn

Homepage
Google Group
Github Repo

Enjoy!

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Tuesday 7-13-04

What was supposed to take a half hour yesterday actually did take 30 minutes today (after we got yesterday sorted out). Email problems turned out to be mostly a matter of restarting Outlook a few times. With the SMCCSharp compiler taken care of, I could go back to my other project: getting Word Press, MySQL, and PHP running on the Linux box.

Although Micah and I had downloaded, installed, and successfully used Mozilla (a web browser -- like Internet Explorer) I couldn't find it today. Paul came over and he couldn't find it. And he's been using Linux for years! It was somewhere on the hard drive, but after wasting about an hour looking for it I decided to stop throwing good time after bad and just re-install Linux (for a third time) and this time make sure I installed almost everything. While that was chugging away, I used my laptop to look up Word Press, MySQL, and PHP. Word Press claims you can set it up in five minutes. The hidden assumption is that you know how to use MySQL and PHP. Here's what I knew about MySQL as of this morning: It's a database. Here's what I know about PHP: it's a scripting language. I did, despite my ignorance, manage to get an local Apache server up and running using MySQL and PHP. I even got to look at some sample databases using the local host (what all this means is that I set up the computer to be a server and then I had another part of that same computer start talking to that server using Mozilla -- kinda weird but real useful when you want to get all the bugs out prior to opening your server up to the world wide web). After digging around on the internet for awhile I still wasn't sure how to get a basic database up and running. I'm pretty hopeful about tomorrow because David found a book in the OM library entitled 'MySQL and PHP for Web Development. Which sounds more than a little helpful.

Somewhere in the middle of the day, Paul said that he thought our SMCCSharp compiler might have some bad dependencies. Hmm.

I remember, during one of my first days at Object Mentor, being flabbergasted that David had a server running on his laptop. Weren't servers huge things that hosted cnn.com? How could he possibly have one on that little laptop? I'm pretty sure I kinda didn't believe him when he mentioned it in passing. Now here I was a few weeks later setting up a server my own self. Crazy talk.

4 days since distant-past-jake started the 5 minute WordPress install -- how long will it take? Stay tuned.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Monday 7-12-04

Today was a day of unintentional diversions. Paul and I came up with an idea of how to test an area of our state map compiler that had been eluding us. We would build up an input file, in the tests, and then send that input file into the SMC which would create an output file that we could read and check to make sure it works. If we had been designing this SMC thing from scratch using TDD, we could have made it easier to test, but since large parts of the program are a legacy, we had to resort to the building/writing/reading file method. But the parser in the SMC program doesn't like to be called twice, so a fair amount of the day was spent figuring out how to get around that for multiple tests. The other part of the day was spent writing a bunch of tests that had to be thrown out because there's a quirk of the program that given the same input, you may get different output. Everything will be there, but the order is not guaranteed. This is one of the problems with using a list, things may not come out in the order they were added. So our tests, which assumed a certain order, would randomly fail. Great. Luckily, there was only one test that really needed our new method of building/writing/reading so we could move all the old tests back to the old way (we called the program directly to set variables) and, in the one straggler, we re-wrote the test so that order was unimportant.

Pretty much the same thing was going on in the office. The email wasn't functioning and everybody who knew about the mail server was either out of town or teaching a class. Then Quickbooks started malfunctioning and things typed in by one person were not available to someone else in the system Nobody was sure if data might be getting lost -- this had the effect of chilling productivity in the office.

In short, everybody's 9am plans never even got started.


"If we had been designing this SMC thing from scratch using TDD, we could have made it easier to test..." How many times over the last five years have I run into this exact same problem? Too many to count -- lack of test leads to untestable code which is very often unmaintainable code.

Oh distant-past-jake, why didn't you just loop over the list you were trying to test and see if the things you wanted were in there? Ah well, a testing technique I would soon learn the hard way
.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Friday 7-9-04

Revision: the State Map Compiler C Sharp version isn't done. It doesn't actually work, as Micah showed us. I feel pretty bad about it because we should have tried the things he tried before showing it to him. The SMCC# produces code that's meant to be part of a larger program. We really should have written the larger program to make sure it works. Bad apprentices. Bad!

On the positive side, I'm becoming a lot more familiar with how this SMC thing functions as we plow through it again (and again, and again). After looking at some UML with Micah we decided to re-design how the C# version of the SMC is written to avoid using inner classes. Which is good because they were confusing me.

David and Paul have suggested that they start writing an 'Anti-Jake' blog. Treachery! We shall speak of them no more.

Tonight I'm going to a ChAD meeting (Chicago area Agile Developers). It's starting at 6:30 at the Loop-area DePaul campus, but my train doesn't arrive until 6:25. So I've got 5 minutes to get off the train, unfold my bike, and peddle my ass on over to Jackson and Wabash.

Last night I bought my airplane tickets to XPAU (eXtreme Programming Agile Universe) which is being held in Calgary this year. I'm pretty excited about going ' should be a great chance to learn a bunch and maybe meet somebody who will offer me a job. (stop laughing -- it could happen). The crazy part is that I have to be back to start my teaching gig the morning after the conference ends. At 8:30pm Calgary time, I get on a flight to Las Vegas, NV. Somewhere around midnight I get on another plane which takes me to Chicago. Arriving at 4:30am. Yipes! I guess I'll sleep a few hours at the airport and take a cab to school. The alternative is taking the 'El back to my home in Chicago, and then getting in my car almost immediately (gotta beat that traffic) to go back to school. That first day is gonna be a little bit crazy. Luckily, it's only a day of meetings -- no teaching required.

Yeah, you should probably run the code before you declare it done. "But all the tests pass" is not an excuse. In fact, it's an insult to your test suite.

XPAU is now just called 'Agile.' I'm speaking at Agile 2009 in August in Chicago, it's going to be weird going back there after all these years as a presenter.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Thursday 7-8-04

Today Paul and I set up the conference room for next week's class by making sure IntelliJ, FitNesse, and M.S. Visual Studio were installed and current on the mini computers. It's gonna be a full house for the TDD (test driven design) class -- six computers with 2 people at each.

Then Micah gave us a choice: one of us could try to track down a mysterious file on a computer about to be re-formatted and the other was to figure out Word Press and install it. I chose Word Press -- it's a program that can be installed on a server so that blogging (weB LOGging) is quick and easy. We are setting up a blog so we can start the site www.butunclebob.com where individuals can object to Uncle Bob's (Bob Martin, founder of Object Mentor is often referred to as 'Uncle Bob.' I don't know why either) frequent declarations (like: 'Debuggers are bad' or 'Comments should not be used' ) and then Bob can respond. But the servers are Linux based, so I needed to install Linux on an old computer they had lying around. Linux is an operating system( like Windows, or Mac OS) favored by nerds. Long have I wanted to get my hands on this O.S. ' it's in all the great nerd literature like Crytomonicon or, uh' hmm. Maybe something by Coupland? Anyway, the nerds favor this O.S. because, although it's not the most user-friendly of file systems, it is very stable and secure. Linux servers don't crash as often as windows servers but even when they do, it's not too hard to get them back up and running.

So I installed Red Hat Linux, and then I installed it again because I did it wrong the first time. Yargh. After that I downloaded My SQL and PHP. These are programs that Word Press needs to run on a server. What they actually do, I'm not sure, but I'll have to look into that later because, by that time, I had to go.

Wow, first day using linux. These days it's easy to forget that I wasn't alway in love with the *nix based operating systems, but there was a time when I was a windows developer. I remember getting placed on a Rails project and trying to get it up and running on my windows laptop -- I think it took about a week. Eventually I gave up and dual booted Ubuntu. After that I made the switch to OSX.

I love the part where I explain that Linux is more reliable than Windows and what a 'blog' is. Who did I think was reading this? As if me explaining every 20th technical term was going to make this blog any easier to read. Actually I didn't even think of those original posts as a blog -- It was just sort of an extension of the little stories I'd been telling for years on my crappy website.

Also, take note of today's date and keep track of how many days it takes me to install WordPress. At the time their website boasted a "5 minute install." I might have gone a little over that estimate.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Wednesday 7-7-04

Most of today was the State Map Compiler. We got it to work, but almost all the work was being done in a 600+ line class. Armed with a bunch of passing tests, we proceeded to brake just about all of them in the refactoring process. But, and this is important, we only broke one test at a time. The goal was to offload a whole mess of functionality into a bunch of other classes. By the time we got back to a refactored green, we had about 100 lines in the controlling method and much more readable code. Whoo!

Then it was time to do a real conversion of the OMwiki to FitNesse. Previously Paul and I had used a copy of the OMwiki files for practicing purposes. Today we shut down the OMwiki and ran our program on the wiki pages. Due to an unfortunate use of a backslash in a program designed to deal with Unix, our conversion program created a few thousand extra files. Sigh. You see, the Unix system uses forward slashes to denote directories so it sees backslashes as just another character. All those directories we thought were being created became strangely named files. And all the real files got dumped in the main directory. Too many files to delete, oddly enough. The 'rm' command stands for remove in Unix-speak. But apparently it has a limit as to how many files it can address. We actually had to write a program in Python just to delete the files. Then, on our second try we saw the resurgence of the strike-through (double dash) problem. Apparently there had been some changes after I left yesterday, but we went back to an earlier solution and that worked. As I had to dash out the door to make my train, everything was working on the new OMwiki site except for an unfortunate spelling of refactor (as 'refacator'). I'm sure they'll be able to fix that one without me.

Anyway, I'm putting today in the win column.

I'm not really sure why we couldn't have just copied the files, ran the program, got it up and working on the new wiki, and then shut down the old wiki. That would have involved too little stress I suppose.

As to the State Map (Machine?) Compiler, I think that may have been the first time I was able to see the power of having a comprehensive test suite so you can refactor at will. More and more I work with developers who've had testing forced on them and see it as a necessary, or perhaps unnecessary, burden. I really don't get that -- I find a well tested application very satisfying.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Tuesday 7-6-04

Fun things you learn when Micah returns: Your tests? -- don't really test what they should. The regex expression you labored over? -- can be done a lot better. All the time it takes to run your program? -- is because your program is doing 20 more operations per file than it needs to. All that polymorphism stuff you vaguely grasp? -- you don't know at all.

All part of the learning process.

Other than that it was a pretty good day. I got back from Vegas last night and was pretty tired (Cirque de Soile's 'O' and 'Mystere' are amazing. Stop reading this blog and go see them now). Before Micah knocked some sense into our heads, Paul and I spent most of the day working on the State Map Compiler. Writing tests for this thing sucks. The output is basically one long string (which is what a program is) so the tests are mostly comparing lots of strings. All the excitement of: missed spaces, absent newline characters ('\n'), and improper capitalization.

A recurring theme in any apprenticeship program: The mentor checks in with the apprentices and points out all their mistakes. Since I was writing this blog in hopes of getting a job I edited out a lot of these revelations so I didn't look like quite such a dumb-ass but, in truth, this probably happened every few days (if not daily).

Fun side note: Laura (my wife) and I went to Vegas that time because she had successfully completed a sticker program. After having our millionth conversation about how she needs to clean up her study, car, office, etc she suggested a sticker program (You know the thing where every week, if you complete the task, you get a sticker in a cell on a table?). I thought she was kidding, but it turns out she wasn't. So we created the "Super Fun Sticker Program for Increased Cleanliness" which lasted 6 weeks if I remember correctly. If she got all the stickers then we went to Vegas and saw some shows. After I tell this story people either tend to think I'm a terrible husband for subjecting her to some sort of behavioral experiment or a very nice husband for encouraging her quirkiness.

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Friday 7-2-04

We did use my code in the wiki conversion program. And while it was good to finish up that project, this meant we had to start working on the State Map Compiler. A program first written in 1993 in C++, then later re-written in Java in '98. No tests, very long methods, and the documentation gives lots of examples in C++ (which I don't know much about -- it seems like Java, but it most definitely is not.) The point of the program is to take in a simple statement of a 'state machine' and output source code that implements the state machine in either Java or C++. We are going to be adding a C# output option to this program.

Now, at this point, you might be wondering: 'What is a state machine?' Well, let me attempt to regurgitate the turnstile example. A turnstile has two states: Locked and Unlocked. If you try to pass through a turnstile when it's locked, you'll get quite a different response than when it is unlocked. A coin will cause a locked turnstile to become unlocked, but won't do much to an unlocked turnstile. A lot of software engineering problems can be thought of a nothing more than a dressed up turnstile with a few more states. So it's handy to have a program that takes in some information about a finite state machine and then outputs the basic code that you can build your implementation around.

Also, it's pretty interesting to be working on a compiler. Software that writes other software (that, ultimately, will be translated into byte code, and then the byte code will be translated by the virtual machine so that the real machine will know what to do -- quite a process).

Not a bad explanation of a state machine for guy who just learned about them that day: Good job distant-past-jake. I think ended up using a state machine pattern in my code submission to ThoughtWorks later that year.

I later worked on a huge java project that would generate something like 15 classes for every one written class. I soon got very tired of generated code ("Hey, why did my changes go away? Oh, it's a generated class... (next line said forlornly) Guess I better go dig through the xml pit for what to change.")

This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.

Thursday 7-1-04

There's just one problem with our conversion program: the Double Dash (cue the dramatic music). In FitNesse, two dashes in a row (--) mean strikethrough. But in the old OMwiki, two dashes had no meaning. A fair amount of people use two dashes to separate their thoughts ' as you might expect. So our pages were getting translated with lots of text 'struck out.' Okay, so all we had to do was write a program that looks through all the wiki pages and replaces two dashes with one. Which, it turns out, is not as easy as we thought. The proper way to do this is with regular expressions (mentioned in the previous post), but neither Paul nor I understand them too well. So we looked around for the regex (regular expression) book at OM, but somebody had probably taken it home for some light reading. With that option crossed out we started to build a series of nested if statements. After getting about 5 if's in, Paul turned to me and said 'If Micah sees this code, we're telling him that YOU wrote it.' Fair enough. Well, the problem with nested ifs, as you might know, is that it's hard to keep all those conditionals straight (if this, but not that, and this, that, and the other, wait! No, not the other. Or, uh, let's start again.) so we quickly got lost. Then we gave up. It was just too messy to keep track of how long the string of dashes were. We wanted to change two dashes in a row, but no other length was to be affected. So we started looking up regexs on the web. An hour or so later, it was time to go.

Incidentally, I made my train with only a minute to spare. Really, really, big wind today.

Here's the weird part: I just figured it out while on the train. Using Java's API (a guide to all the classes and methods in the Java library) and some tutorials I downloaded off the web, I talked the 'matcher' into finding dash strings of any length. If the length of that string was two, I replaced it with one dash. If not, I kept the string the same. Nice.

Gotta say, I feel pretty good about being able to contribute something to this project.

So mark down July 1st, 2004 as the day I felt like I really might be able to become a programmer. Since starting at Object Mentor I had contributed almost exactly nothing except for the occasional "You spelled that wrong." But on that hallowed day I actually figured something out before Paul. Maybe I wouldn't have to go back to teaching high school remedial physics and hating Sunday nights because of what Monday promised. Heady thoughts.

Interestingly enough Jay Fields wrote a blog post about the "Spellchecking Pair" a few years later. He makes some good points about matching the levels of programmers but:
A. That's not always possible.
B. I'd feel pretty bad if I was a junior guy on his team when he wrote that post.
C. Inexperienced devs already feel like they are worthless -- try not to make them feel worse.

Still it's important to talk about the problem -- you want to bring developers along but sometimes the impedance mis-match can really frustrate both developers. I generally err on the side of "pairing increases the long term health of the project," but of course their are exceptions. It's just that the exceptions have a nasty way of becoming the rule.