From the Odyssey:
…but gave them to eat of the lotus, which was so delicious that those who ate of it left off caring about home
I believe that the Sazerac may be my ‘lotus’ - what is yours?
I read GOOS severals years ago but I have decided to reread it as I felt I didn’t think it really got into my head the first time. Definitely I did become more comfortable with mocking in tests - but I felt there was probably more that I missed. So I am rereading it - and more importantly - taking a few notes. It is those notes that I will be writing about, every chapter or two - hopefully not a project that will end in a whimper.
“Software is a learning process.” I am not sure why I didn’t catch this last time. It is something that makes absolute sense to me now; and moreover I don’t know a time when it would not have made sense to me over the last decade. If software is a learning process, getting feedback on that learning is of utmost importance.
The boxed-text about ‘nothing to lose but your bugs’ strikes me as ‘sales pitch’. Having believed, then being bitten by this catch phrase I don’t buy it. TDD will not help the developers write the right feature - just help ensure that what they write is what they intended. It is not a silver bullet; and I’d think that Pryce and Freeman had not intended that; so I hope that I’ll see something that backs up this claim from them.
(However I do feel that implementing via TDD helps drive out cases that might get missed until later exploratory testing. By finding them earlier in the process we have a big win.)
After finishing the rest of the chapter I see their claim is that all the levels of TDD practices: end-to-end; integration and unit; could reduce the chance of writing the wrong code.
Pryce and Freeman say that refactoring is a local change. This made me immediately realize that easily fall into large refactorings. This is something I want to keep an eye on. Not just for refactorings - but for any work - I should work in small chunks.
It annoys me that there are so many terms for different levels of tests. I personally use ‘Integration’ test for any test that integrates two or more components (except for those sets of components which I consider a Unit - then of course that would be a Unit test…). They keep talking about ‘Acceptance Tests’ which to me are ‘User Tests’ - and given I just got back from some training from Jim Shore I am currently at least moderately against automated user tests. I do like End-to-End tests - that they call Acceptance test - but need to keep them under control since they have the drawback of slowness and brittleness.
I really like to have clear terms for things - terms that are understood generally by people. I think it eases communication. That being said I see in myself a lacking of clarity when I discuss topics. Reading this book is bringing this up to me; perhaps it is something I need to work on for myself.
I think the important idea presented in this chapter is the idea the domain concepts are not embodied by a particular classes in your code but by the connections of those classes embodied by the messages that they pass each other. This is an idea I remember having trouble with when I first read this book and I am again having a little trouble making it concrete in my head. Hopefully this second read will help solidify it.
The authors present a nice terminology for two types of collections of data and functionality found in code. Simply: Values are immutable without distinct identity; Objects have changing state and have distinct identity.
Here again is a reminder to me to have a clear, consistent terminology to aid in communication.
While I am familiar with the “Law of Demeter”, it is one of those things that seems to quickly fall by the wayside as I code. Another thing to add to my list of things to improve.
There seems to be a lot of good discussion about this on the internet - one discussion and explanation of it I like is that from Avdi Grimm in his blog post Demeter: It’s not a good idea. It’s the law. In it he points to method chaining and points out:
>Look again at the definition of the Law: it never says anything about the >number of methods called, or the number of objects a method uses. It is >strictly concerned with the number of /types/ a method deals with.
So it is OK to chain a set of method calls together that all do different things to collections of objects, or Strings for example; but not when there are multiple different types of objects.
I am looking forward to continuing my rereading of this book. I think I will gain from this review of important topics (Object Oriented Design and TDD). I may not end up agreeing with it - but I hope to solidify my thoughts and practices in this area through it.
Along the way I plan on continuing to take notes and then making blog posts about it. I think through this process I will do an even better job of understanding what I have read. I hope you all don’t mind too much.
Chapter 3 was a discussion about using JMock. Nothing really to note or report. I have no yet decided what language(s) I will be using while doing the exercises. I think I may just do it in Java with JMock so that I can easily follow along with their examples. However another part of me wants to do them in Ruby or Groovy or Clojure to help me compare and contrast.
In any case, any code written will of course be published to my Github.
The training turned out to be review for me given that most of my coworkers are Cyrus Innovations employees and they all attended this training in October of 2011. They came back and implemented some of the ideas from the training - so in a way I’ve been living this stuff since then. Even before that we were a pretty well functioning agile team.
Even though it was a review I still thought it was very beneficial to me. There are always opportunities to improve; and details/reasonings that had been forgotten. Old ideas can become new again through re-iteration.
The training was split into two parts. The first two days covered Agile Planning and the last three Agile Delivery. The latter was what I was most interested in - but I think I may have gotten just as much out of the first section.
It was in the second half of the class that we got to “experience” Agile Delivery for ourselves. In our groups we delivered working software four times in four iterations; each iteration was 90 minutes long. It seemed crazy and a few times it felt crazy - but we did deliver running software (a cheesy text based ‘game’) in 90 minute iterations. During these 90 minutes we did everything from release planning, to coding (TDD’d naturally), exploratory testing, and releasing.
Crazy as it may seem - it is a brilliant exercise. By making us so focused we needed to organize ourselves, help each other out and really work to remove all roadblocks. Also it forced us to make, quickly, decisions about what was going to be in and what was not. We couldn’t let ego get in the way and argue too much about anything; we could always pivot and change our minds later.
Even as a well functioning agile team I have to say that there were some things related to stories that I now think I/We were doing wrong or not so well. Firstly, I was reminded that Stories are not requirements. Stories are conversations about the requirements and they are negotiable. It is really important that they are small and independent. A story on its own is not likely to be a complete feature (MMF) - they ought to be much smaller than that.
Another point about stories that Jim makes a point of is that they should not be re-estimated. This seemed odd to me so I made a point to discuss it further. It seemed to me that one should re-estimate a story if more information is known. For example we may come to know that the implementation needed for a story is harder than first thought, or easier (perhaps it is becoming routine).
Jim’s point is that estimates are always wrong, but they should be consistent. So if something was estimated as a ‘1’; then anything like it should also be a ‘1’; even if find out that it was easier/harder. The reason is because if we change our estimations then our velocity becomes less meaningful. It is our velocity that should be changing to reflect our capability for doing N 1-point stories. That N will go up and down as 1 point stories are harder/easier.
Instead of simply doing Yesterday’s Weather, Jim
suggests letting velocity ‘settle’. The way he put it was:
Decrease velocity easily. Increase velocity pessimistically.
The idea is that if you always use Yesterday’s Weather that your velocity may tend to to be erratic, and more importantly that it prevents the team from having consistent time for Slack. While I can understand this intellectually I find it hard to grok. Perhaps that is because of long standing bad habits from previous work environments. It is something I’d like to experiment with.
Duh. I just needed to be reminded of this.
Diana and Jim presented an idea of ‘Fluency’ in Agile Practices. Each level is useful, none of them are ‘bad’. They are:
The idea is that you are ‘fluent’ at a level, as with a language, when you can easily work at that level, even under pressure. I think our current team, and myself, is largely fluent at the level of delivering business value and day-to-day we do some work at the level of optimizing that value.
Diana mentioned a good quote: The First thing to build is Trust. The idea is that the first thing the team needs to get good at is delivering on its commitments - consistently.
This is an interesting idea that I need to think more about. The idea is that because Iteration Planning involves choices about what will be built; that it affect design.
I always find interacting with people who are interested in or driven to learning very energizing. A change in this time I realized what that now I was the person who was answering questions of and encouraging people who were new to Agile. I am starting to realize that I know this stuff and have something to offer. It was also great to see a coworker doing the same, and doing a better job than I did.
There are some things I want to try for myself and for my team.
Right now on my current project we do not have Customer Demos. I said a few times during the training that my project does not yet have a Customer, but what it really doesn’t have is a User. I think we could start demoing it now to whoever wanted to see it. At the least demoing to fellow team members may help us be focused and see a bigger picture.
Currently our features are not quite Minimum Marketable Features. They tend to be larger than that. Furthermore it seems our Product Manager (the Customer Proxy) doesn’t care much about anything smaller than that. However that is leaving us with only a story or two per iteration - which is not helping us achieve a more stable velocity.
I need to do some brainstorming on how we can (or if we should) shrink our features. Then figure out ways to split stories into smaller chunks so we can have several per iteration (at least 4). The important thing here is to keep business value in each story. While I do not think this will magically cause my Product Manager to care about the smaller stories; but I hope it will help engage them more if we can show business value progress with each one.
Related to this is the problem that it seems there may be some expectations about when the current release will be shippable. My current projections are much further out from those expectations. I need to use tools like Velocity, Release Planning with Risk calculations (ala Rabu which I currently use) to bring data to the table in my discussions with the Product and Project Managers.
Now that I’ve had this review I feel that I and my team have not been doing a good job of doing root cause analysis on the issues in our process which we discuss in our Retrospectives. Furthermore we are not doing a good job of root cause analysis on any bugs that come up.
(On the topic of bugs I want to more seriously have the “Bugs don’t happen here” attitude.)
In conclusion the training was fantastic - even for someone who is not new to Agile methodologies. I am bringing back some good ideas which may help me and my team achieve even better fluency in our work. It also solidified for me some existing ideas that I thought I/we already did pretty well.
After I posted my last blog post it was reported to me that my code blocks
were no displaying properly. The readers were seeing an error like:
error: Could not open library ‘/usr/local/lib/libpython2.7.a’: ...".
Some googling informed me that the problem seemed to be somewhere in RubyPython. The instructions were relatively straightforward - but it wasn’t clear to me if I needed to do both of the directions.
The quick answer is yes. To fix this problem one must do the following:
gem 'rubypython', '= 0.5.1'
plugins/ruby_python_heroku_fix.rbwith the contents:
RubyPython.configure :python_exe => 'python2.6'(the filename is not actually important).
(And helpful it was… I see plenty of mistakes I made and summarize the lessons learned at the end).
First a quick background. (defdrink) will be/is a web application which will assist in the choosing of a cocktail based upon the contents of the users liquor cabinet. I am using this project as a means of learning Clojure. I have put all the source on github (as one does…) and in this post will refer to particular commits to illustrate different steps.
At the point where our story begins I had slapped together a quick (and ugly) prototype. The purpose of the prototype was to get a Clojure project which has a web page which allowed retrieving and saving data into a database; all served up on Heroku. Being a prototype - it had not tests (horrors). This moment in time is commit 0da77fbafc87634e94e0342e409e5b071b8d6c1f.
It took me two tries to get my first Midje test (and that first test merely
proved that Arithmetic worked:
(fact (+ 2 2) => 4)).
My first attempt was me doing what I thought was ‘obvious’ and what I thought
the Midje wiki was telling me I should be able to do: put a bit of magic in my
projects.clj file and then a test file with a
(fact ...) in it.
That attempt ending with frustration at the fact the only feedback I was getting was a bunch of Java stack traces.
My second attempt was simply making these same stumblings - I had wrongly assumed that I had I simply not quite understood the previous time.
After I realized that my second attempt was heading toward another failure I finally rolled back and tried to take the next smallest step. I wanted to run Midje (with Lazytest) and get it to report something like “0 tests”. With the help of the lein-midje plugin Readme I got this working in not too much time. If you look at that commit you will notice a glaring error - one that was not obvious to me as I tried to continue.
Ages ago when I started this project I ran
lein new defdrink and then, since
I didn’t have any tests, I removed the
test subdirectory. Now, a month
later, I couldn’t remember just how the test directory was supposed to be laid
out, and it was obvious to me that it needed to have some special directory
tree/naming to find the files etc. Mixed into that was a lack of understanding
Clojure namespaces and directory structures (this was just me being dense).
At this point I kept getting stack traces about not finding namespaces, which
all seemed right - but obviously lein, midje, clojure or all three didn’t
Finally I had just ran
lein new foo in a temp directory and saw the
structure needed. That was the clue I needed – the clue I couldn’t find
this little simple piece of information out on the web either for Midje or
Clojure’s own test framework. Now that I had the directory structure right,
the namespace in the file right it would work right? Right?
As I am sure all of you playing along at home can see - I never added a dependency on Midje itself in the previous step. That means at this point I started getting messages that said:
Could not locate midje/sweet__init.class or midje/sweet.clj on classpath
Let me tell you this was very confusing after all I knew that I already had Midje working. Now that I added a test it says it can’t find Midje?! Finally I saw my error and fixed it. Now at long last, I had a Midje test! Of course it was just a dummy test but it was actually running.
My next step was to get a real test. My premise for these tests was to remove
some hardcoded SQL code in my model class. I was going to push that code down
into a couple helper classes so that I could isolate myself from the database.
The first test was to show that my
defdrink/all method would delegate down
to my new
sql/select method with the
:drinks parameter (that is the
I once again had some odd and annoying problems with the only feedback being cryptic stack traces. I don’t remember all the details but they involved statements such as ‘provided not being defined in this context’ - which led me down wild chases to determine if I had all the right modules required etc. Fortunately/unfortunately the problems resolved themselves (I hate that) and I got my first real test running:
(I sort of like how it turned out… I like the metacontstants feature and am excited to try it out more.)
Now that the select statement was sequestered, I turned my attention to the insert statement. This is where I again ran into problems.
This new test, like the previous, was going to be a simple test of delegation.
Did the model layer properly call down to the database layer to query or
persist the data. The test I wanted to write was to say that the
defdrink/save method called the
sql/insert method with the correct
parameters. My first attempt at this ended… (wait for it…) in
In Ruby or Java/Groovy I’d simply have my test call my method and test the
expectation on my mock object that the
sql/insert method was called with the
correct parameters. Unfortunatly for me, I could not figure out how to do that
in Midje. I ended with the following unhappy test:
1 2 3
I’ll freely admit that while trying to write this test I began to have doubts (which I still hold) that perhaps I shouldn’t even by trying to right this test. It just seemed like a code smell to me. The way the test ended up seems to be telling me: “Mark, just what are you thinking?!”
In conclusion (finally) my problems were much of my own devising. Whether it was shooting myself in the foot, trying to do something quickly because “its easy right?”, not yet understanding this language/environment I am trying to work in, or simply because I am trying to write Clojure tests as I would Ruby or Java tests – I’ve had a hard time getting to this point.
Even admitting my own problems, I have to say, IMNSHO that it would have been nice to see a tutorial/cookbook out there of how to get started with Midje. What I’d have liked to have found would be something which stepped me through:
project.cljfile for midje, lazytest, and lien
In researching this blog post I see I did overlook some resources on the Midje wiki that would have helped, at least with the second two points.
So the moral is:
I do think I might try to contribute this sort of tutorial to the Midje project. Because I can’t be the only dope who thinks he knows what he’s doing, who will get frustrated because there is not a tutorial to hold his hand through the first steps.
We were going to see Kraftwerk at MoMA and the trip didn’t start well as we sat in stop-and-go traffic through Connecticut right into NYC. Luckily we were not driving ourselves, but I still worried this was an ill omen. We even had trouble finding some quick food before the show. Even with all these problems the show was fantastic.
Wendy and I staked our claim to a bench off to the side and at the back while the surprisingly young crowd filled in in front of the stage. The view was just fine from where we were.
The show began with the dropping of the curtain - showing the band at their podiums.
They started the album off by playing Man-Machine and with the 3d glasses the visuals were interesting… but when Spacelab started they were fantastic.
The images of Spacelab orbiting the earth was great. They even used a cheap 3d trick of having the orbiting ship head straight into the audience; cheap but still fun.
The huge looming buildings, and slow pans through them fit with the song Metropolis perfectly.
The visuals for The Model were all black-and-white fashion shots - not much more interesting in ‘3d’ than not, but the next song (Neon Lights) used the 3d effects better.
The album performance was capped off with We are the Robots. Everyone went wild over the robo-kraftwerk dancing and looming over the audience.
Now that the album was over I was not sure what to expect; I was not disappointed with their choice of Autobahn - the visuals being computer generated VW Beetle and other cars on a seemingly infinite Autobahn. The song ended with VW pulling off the highway.
Up next was Radioactivity followed by Trans Europe Express. Then ComputerWorld and Tour De France.
Then my phone battery died - so not more pictures. So you’ll have to take my word on it that the rest of the show, including Technopop was fantastic.
My full set of pictures is availble on my flickr stream
There is still a problem with some posts - the media they contained are not currently available. I think it was the posts where I had emailed a picture to Posterous (which would then bounced to Flickr and Twitter). But any post I composed as an email seems to be here.
The time it takes to generate the site has really dropped off unfortunately. Hopefully it will not just get linearly worse…
(Well not quite true I don’t have a desk at all… but effectively I don’t have one).
About a year ago I changed to a new job. In all previous jobs I’ve had I had a desk, in fact I had a office (sometimes shared) or at least a cube of my own. It was different at the new job; when I showed up on my first day at the new work there was a little bit of confusion about what cube I could be given and as a ‘temporary’ solution I was given a desk in the lab.
Given the way we work on the team, I spent very little time at my desk. It became simply a place where I put my bag & coat; a place for my coffee mug; a place for my notebook at the end of the day. I did use it to check my email first thing in the morning before everyone arrived (I’m an early person) - but other than that - unused. As the months went on I used it less and less everyday.
Then in January the new DBA consultant started sitting at it with his laptop so he could be with the team; thus I was partially evicted from my ‘desk’. I still kept my inbox there - but now I didn’t even use the desk to read my email in the morning.
At this same time there was a new coworker starting and with that a little angst about where they would sit (the cube situation was in fact no better; but actually worse). A cube was found for her; but I felt that by giving up my desk entirely I was making a personal statement about desks, cubes, offices.
I do have regrets periodically when I need to do some personal matters; but we have a shared office nearby the lab and a few cubes that can be used in a pinch for private work/calls.
In all - I have not really missed having a desk. I have found out that I don’t need much more than space for my inbox; maybe someday space for some filing. This conclusion is NOT what I would have expected from myself; I remember clearly wanting an office and bemoaning my fate of being in cubes. It seems I have accepted the team-room setting more than I had imagined I could have.
(I finally went to another Boston Ruby meetup. Only my second - hopefully it will be less than ~9 months before I go to my third.)
Chad Fowler gave a talk entitled “Measuring & Analyzing Things That Matter When You Have Too Many Things To Keep Track Of” at tonights Boston Ruby Meetup. It was the reason why I went to the meetup.(But I did enjoy the other two talks - but they are not the topic of this post)
His talk was, self-described, half-baked ideas. Which is fine by me. At @boston_sc we’ve started doing “half-baked” ideas talks and they have been great - I only wish that this talk was more discussion style like the ones we have at @boston_sc.
He talked about how even with a team of very good developers, good code is not guaranteed. The bad stuff builds up, even without people noticing, via bad habits and laziness. His person example of gaining a lot of weight hits very solidly with me and I am again working to drop my weight which keeps just sneaking back (due to bad habits and laziness on my part).
He mentioned several thoughts about how to fight the bad habits/laziness, but the one that got me thinking was about the Flesch-Kincaid Readability Scale.
Basically in a nutshell Rudolph Flesch devised a algorithm for English which let you compute a score which then equates to what level of English reader could easily read and understand your English. He suggested that perhaps some combination of metrics (e.g. flog, flag, roodi, churn, reek, (i.e. things from metric-fu)) might render a number which would equate to a level of developer (his scale topped out at Rich Hickey) that could understand your code.
The reason that this got me thinking especially was because it fits into a less-than-half-baked idea I’ve had. A few months ago I was working with a junior developer at my job and while she was away I had implemented a nice little bit of Groovy code to do something. It involved a chain of collection functions (e.g. map, inject, collect etc.). I thought it was great. When she came back and saw it she couldn’t understand it. I explained it to her and she started to understand. I explained again and she sort of understood. Then I said “ok, hold on…” and replaced it with 2 for loops. Totally dumb un-cool code that did the same thing. She immediately understood! So that is what we committed.
The problem was that I was at a higher level of understanding of that sort of pseudo-function collection function chaining. (and also it the code might have been a bit ‘clever’ shudder). By shifting to ordinary code it was easy to understand.
The thing I am interested in is if this scale of code comprehensibility is if it is absolute or relative. My first thought it is relative. If one can raise the base skill of a team then that team can understand more esoteric code.
There were other interesting points in there - obviously rather ruby specific:
These are also things that will keep me thinking for a bit. I can use these ideas both in my for-pay coding and my for-free/me coding.