Farewell to Pearson & Cedar Rapids

It has been almost ten years to the day since Sarah and I first arrived in Cedar Rapids to work with Pearson Education and it is with a mix of emotions that we say farewell.

My work with Pearson has been the most satisfying and stretching work experience I have had to date. I am grateful to have worked with professionals who strive for excellence in their daily work and who have taught me much about the craft of software development and continuous improvement—for which I am deeply grateful. With sadness I bid farewell to the many people who have made my experience at Pearson the joy it has been to me in these past ten years.

On October 24 I will assume a new role as Lead Developer with Urbancode of Cleveland, Ohio—a maker of build, release, and deployment management tools which has earned recognition from Gartner and others as a leader in the field. The challenge of creating products which improve the efficiency of software development teams and are offered for sale in the marketplace as well as the prospect of mentoring software developers in a small firm excites my entrepreneurial instincts. Despite the considerable disruption this move will be to the happiness my family and I have known in Cedar Rapids, the opportunity seems too perfect a fit to pass by.

In ten years we’ve put down deep roots in Iowa. Our church family, our Cedar Rapids friends and our home school co-op and assistance program have been a tremendous blessing to us. Thanks to all who have made this last decade one of joy and growth. You are dearly loved and will be sorely missed.

  • 7 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Declarative & Scalable XML Parsing

At ic-ruby on Thursday we talked about XML and JSON parsing and object mapping. I shared a little about how we are using ROXML at Pearson and Wesley Beary shared how Fog uses Nokogiri’s SAX support for performance but incurs maintenance overhead as a result. Perhaps we can have it all: Greg’s post shows how with sax-machine.

  • 8 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Angel vs Devil

  • light bulb comes on: Ah, now I understand what went wrong with my API and what I can do to make it much simpler.
  • voice1: MASSIVE DELETE? YEP. DO IT.
  • voice2: No. No. No. Refactor!
  • voice1: There is not much code here and you are fast. Go ahead. Don't waste time on those old tests and crappy code. They are all WRONG. Gut the two classes, scrap those tests that make bad assumptions about how the API should work and GET IT DONE. All of your valuable tests you can keep in place.
  • voice2: Don't you think that if you just stop to think for a few minutes you'll be able to find an incremental change?
  • voice1: You are using Git. Branch. No risk. Let's get started.
  • voice2: Okay, branch. But perhaps we just pause to think a minute before we start over.
  • voice1: This is really going to be a total waste of time. You move so slow when you take baby steps like that. Just get it DONE. Isn't that what Steve Yegge would do? He'd be DONE.
  • voice2: Why not give it a try? You can always delete if your idea doesn't work. And there might be more value in those tests than you think.
  • voice1: Look, you don't even know any refactorings that can handle this. All of your tests depend on that stupid constructor and your whole deserialization strategy is going to have to change. This is too big for a refactoring. Why refactor when the whole thing is going to have to change?
  • voice1: Trying to think. Think.
  • voice2: There are good reasons to start over on occasion. It might even be a pattern. You could blog about it. I'll bet Kent Beck would think you are smart for dealing with the nuances of the start over pattern.
  • voice2: Oh, come on. The first step is just introducing a factory method on the class. That's basic. This can't be that hard.
  • voice1: Damn that guy. He's going to make us waste all day polishing a terd.
  • 8 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Confessions of a Code-dependent

Gratuitous geek nostalgia, daring escapes, computers, love and romance, code, growing up and more computers—with a little about having babies, office jobs and more computers, including tips on learning to live with and without computers and how to retain one’s sanity (almost) in both conditions.

Part 1: The Darkness Descends 1981-1992

For the first seven or eight years of my life I was not a computer nerd, so far as I can remember. But when my Fern Drive Elementary second grade class shuffled into the computer lab to play Lemonade Stand on the Apple II computer called out to me. While I loved turning a fictitious profit its simulated economy, I immediately wanted to understand how it worked and eventually figured out how to get to some kind of command prompt which only amplified my curiosity.

I begged our principal—who took a personal interest in the computer lab—to let me join the school’s computer club but he was very firm in indicating that club was for strong readers and that I’d be old enough when I hit the sixth grade. THE SIXTH GRADE. Anything could happen by the sixth grade. I could be dead by then. Mount St. Helens is REAL. The Russians are REAL. Car Accidents. Kidnappers. Be serious for a moment. We don’t HAVE until THE SIXTH GRADE. Even this institution’s own esteemed standardized test scores support me here. But it was of all of no avail. YOU ARE TOO YOUNG.

Happily the Save On drug store just across Euclid Street had a shiny new TI-99 on display. I watched some kid write the first code I ever read.

  10 print "Billy Bugeye    ";
  20 goto 10

Once he left, I amused myself for what may have been hours by adding spaces after my own name to see the different patterns that would scroll by. As long as the number of characters in the string would not divide evenly into the 80 character column width, my name would appear to scroll at a diagonal angle influenced by the number of leading or terminating spaces. I visited often and would stand and work at the display unit until I just couldn’t take it anymore and would have to return home to use the restroom.

Some time in the next year or two a friendly neighbor couple, “Ruth and Will,” invited me over to “work” on their TSR-80. Will handed me the manual and said, “See what you can do with this.” I got far enough to write a little more interesting program than I had with the TI-99—expressions, variable assignments—but as it turns out my attention span with non-fiction wasn’t sufficiently developed to get me very far. As I left Ruth suggested that I could be a computer consultant when I grew up. Blank look. “People will pay for you to help them with computers.” That sounded magical but I could be pretty ornery at that age and indicated politely that it was a preposterous idea. “Whatever,” says Ruth who puts up with a lot of nonsense from this 2nd grader and will still have me back over the next day. Thanks Ruth and Will. Sorry I punctured your water bed.

By the end of my third grade year my mother and father had been separated for three and half years and I was spiraling out of control. Parents who think divorce is better for the kids than having to live through their parent’s troubled marriage should read The Unexpected Legacy of Divorce. My teachers, principle, school psycologists, etc. had run out of ideas—and they’d tried some pretty wacky ones. My Aunty, a pioneer in the home school movement, convinced my Mom that I should come to live with her (and my seven cousins) in Whittier, CA. Saying good bye to my home in Fullerton, to my brothers and my cat, Lisa, sucked but the year I spent with my aunt and uncle probably saved my life.

Among other good things that were happening with my aunt and uncle—like being continually made fun of by cousins David and Nathan, an antidote for self-pity that seemed to really work on me—my uncle one day brought home a Timex Sinclair 1000 ZX81, a full-sized replacement keyboard and a 16k RAM pack. My uncle was a software engineer and consultant with Telos and worked at the Hughes Aircraft campus in my hometown of Fullerton. I can remember watching him explain the BASIC language to my cousin David, three years my senior, as I watched from behind. When David was done with the computer, I’d rehearse the things I overhead and wrote a program in which the computer would select a number between 1 and 100 and then the user would try to guess the number given hints about whether guesses were too high or too low. My first program to include branches, loops, and input. Yeah!

The Timex Sincliar was a great computer for a kid learning to program because the BASIC keywords and functions were printed on they keyboard and available as extended funtions so that one didn’t need a manual or to be a good typist to start writing code. Happily, Uncle Ed did supply us with BASIC language books, magazines which printed example code and cassette tapes which had programs that could be loaded and read. I certainly didn’t master BASIC that year 4th grade year, but I implemented text adventure games, got a good start on a primitive PacMan clone and felt pretty smug having satisfied myself that the SIXTH GRADE ONLY computer club at Fern Drive Elementary couldn’t be nearly as far along.

In other news, I also discovered that coders could speak a language other than BASIC. My uncle brought home a book about machine language programming for the ZX81 and I read the first few chapters. Machine language seemed like quite a bit of work for relatively little payoff but I enjoyed learning more about how the computer worked and that one could program in languages other than dialects of BASIC was a revelation.

Thanksgiving 1984. Submit Christmas list to Grandma as part of annual ritual. Item #1: a computer.

Christmas 1984. No computer. I did get a robot arm that could be controlled by a couple of joy sticks. Unfortunately it wasn’t programmable.

After that fourth grade year and a number of other short-term transitions, I wound up with my father and new step-mother in Huntington Beach, CA. My dad was a counselor for juvenal delinquents with the Orange County justice system and worked the graveyard shift. That meant that during the summers while my step-mom was at work, my brothers and I (happily reunited) were to remain indoors and very, very, quiet. Shhhh! Dad will wake up! SHHHHH! We spent our time building space Lego cities, inventing economies for Lego men based on various translucent colored pieces, writing instruction manuals for games we invented and watching re-runs of Twilight Zone, Bonanza and Mission Impossible. I would read game instructions for style, structure and conciseness and would try to reproduce their sound in my own game instructions. When finished, I would inevitably be dissatisfied and start all over. I later realized that it was during that summer I learned to write and also developed a much greater capacity for studying detail in non-fiction.

Thanksgiving 1985. Submit Christmas list to Grandma as part of annual ritual. Item #1: a computer.

Christmas 1985. No computer.

Thanksgiving 1986. Submit Christmas list to Grandma as part of annual ritual. Item #1: a computer.

Christmas 1986. No computer.

But I did get a copy of the book Modula-2: Seafarer’s Guide and Shipyard Manual By Edward Joyce. A friend of my mother and a pioneer of voice recognition, Bruce Poetsch, had recommended it. I didn’t have a computer but I poured over that book. I think I read it three times that year, each time until the last getting stuck on the chapter covering pointers and going back to the beginning and starting over. I didn’t have a computer, but it didn’t stop me from writing software. I would write out programs on college-ruled paper and trace over them with my finger.

The ‘86-‘87 school year was an awesome time for me in terms of intellectual development. The pastor of our church, who had a PhD in Philosophy from USC, was very interested that the church kids developed whatever gifts of the mind we possessed and convinced my Dad to enroll me in a private school with a strong college prep. program. The church even covered a substantial part—if not all—of my tuition. Mr. Beardshear, my seventh grade geography teacher who ordinarily taught the high school European history course, made it clear that he wasn’t going to lower his standards just because we happened to be in the seventh grade. We had to learn every country, capital, major export, mountain, river, etc. in every country in the world and be able to reproduce maps from memory. And we strayed from geography proper quite a bit. The two hour semester final ran over 20 pages long and included essay questions in which were to compare and contrast the communism of Mao Tse Dung and Joseph Stalin, describe the twelve steps in the traditional cycle of Chinese history, list all the Chinese dynasties with dates and major characteristics, etc. Mr. Beardshear would lean way back in his chair and tell stories of his wide travels to exotic places. It was all so invigorating in the excitement of exploring new people and places, thinking about how the world worked and especially in the tremendous demands it placed on me as a student. My parents never put any pressure on me for grades. They figured it was my life, my business. Neither did Mr. Beardsheer. He treated us like adults, he had a relaxed demeanor and he expected us to deliver. I just could not fail to live up to his expectations. His demands were enough to engage fully me in school for the first time. My GPA hit an all-time high, I made the honor roll and was voted most organized student in the seventh grade. It actually was not true but with my high water khakis I was now an established nerd despite my skater haircut. Go figure. I think my performance in volleyball during physed sort of cemented that reputation. Ugh.

At some point during that year the impossible happened. Bruce gave my Mom a computer. It was an old Heathkit Zenith CPM-80 machine with three floppy drives. One hard-sector and two soft-sector drives. The steel-cased equipment was mammoth. I could have killed my seven year old brother by dropping the external drive unit on him—if I had wanted to. Instead, I just woke my Mom out of sound sleep every Saturday morning at 6:00 AM by formatting floppy disks. CLANG, CLANG, CLANG. I read and wrote thousands and thousands of lines of code that year and hundreds of pages of a BASIC reference manual in a big black three-ring binder. I read them over and over. This was big boy BASIC-80. I convinced friends at school who had computers to bring print-outs of any BASIC programs they could find for me. One morning in Bible class while the rest of the class was having a discussion, I uttered in audible, “ah ha.” Happily I was able to conceal the fact that my sudden recognition had little to do with the topic at hand. I had finally understood a programming technique I never seen before and was pondering. But I did like Bible class. I probably would have melted down completely if Mr. Tennis were as demanding as Mr. Beardshear, but I might have paid better attention. Impossible to know.

By the time I busted the Heathkit Zenith trying to understand its internals (with the power on—oops), I had mastered BASIC and had a good start on Modula-2. Bruce had me over to his place and had me working on an IBM PC writing Modula-2 code to control various appliances in his house using his voice recognition equipment and an X10 system. Way cool. He helped me with pointers. I wish I had been a little more as ease at Bruce’s, less self-conscious and jittery. And I wish I could have had more time with Bruce. I think I could have learned even more from him than I did. Cancer took Bruce in 1996. I wish he could see what a strong start he gave me, though I suspect he knew.

With the Heathkit done, I was again without a computer and would steal as much time as I could with store displays, computers owned by friends or left unattended at school. It was back to public school for me in the eighth grade and I learned how to evade the hall monitors at lunch and sneak to an Apple IIe machine no one watched too carefully. I lacked good manuals and didn’t learn too much. I was getting bored with BASIC, but didn’t have much else available. I read books on AI and learned what I could about computer viruses. The next few years not too much happened in computer-nerdom.

During my freshman year a high school teacher of mine, Mr. Cupp, did computer consulting on the side and took me along on jobs. I got $6/hr. laying network cable with him—which was petty good for a high school kid back then. He taught a computer class where I learned formal stuff like sort algorithms. On one memorable occasion, a junior girl in computer class who seemed to like the nerdy sort was paying me special attention so I dashed off a solution to a programming assignment and handed it in with a flourish hoping to be free to receive this girl’s attentions for the rest of the period. Mr. Cupp—a giant of a man—stood up crumpled up my paper with as much as drama as I had delivered it to him and announced rather loudly and jarringly, “This is crap!” Thoroughly humbled, this rock star returned to his seat and started over. Don’t be cocky, coder. I’ll never forget it.

Also during my freshman year I wrote the largest, most complex program I had ever written—a book cataloging system for the school. By this time I was working on IBM PC compatible machines and using QuickBasic, which offered many extensions to the BASIC language and a nice programming environment complete with debugger and compiler. This was the first project on which I ever did an all-night coding session. My grandfather had allowed me to stay over at his place and use his computer. My program, The Book Master, Shelf Tamer, kept consuming the heap and running out of memory. Disk IO from a floppy even on a new AT&T 6300 was too slow to load the titles while scrolling or searching through the catalog, but the catalog was too big for the heap. I had to do a major refactoring so as to keep complete book records in random access files and only load titles in memory so that one could rapidly browse the catalog and load complete records only when needed. I remember thinking that what I handed in still wasn’t good enough, but I finished it and Mr. Cupp was happy with the result.

Beyond that, not much was happening in my computer world. I was doing much better socially—even after having been dumped by that junior girl—and enjoying people more than I had. I also began studying Latin which was a great outlet for my love of technical detail during the stall in my computer learning.

I N T E R M I S S I O N

Magic happened the first day of my Junior year. Big Magic. Somehow someone had goofed the school scheduling and one teacher, Mr. Higgins was assigned to teach two electives at once in two different rooms separated by a partition: yearbook and computer. He was standing there trying to figure out how to make this work, when I approached and offered to teach the computer class. He asked me some questions and then handed me the grade book. I was on cloud nine. I had the con. The whole class (all freshman and sophomores) was mine. I could select my own curriculum, write my own exams, and I would be issuing the grades. I am not sure how this escaped the principal but it was one of the most amazing things that had ever happened to me. I loved school like I never loved it before. I lived for 6th period.

I quickly tossed out the stupid high school computer class book and made everybody copies of a BASIC reference manual and announced to the class that they were going to learn this whole thing. By the end of the first semester the class had the basics down and we moved from coding problems onto larger projects. One kid was working on a movie database, another was working on something to help with his Dad’s real estate business, it was all so cool. I even had the students take apart all the computers in the lab one day and redistribute memory among them so that we would have a few workstations that could run the QuickBasic compiler and produce executables. Mr. Higgins walked in while we were in the middle of this project and I was nervous that he’d be upset with me, but when I explained what were upto and why these kids needed to see the inside of a computer, he smiled and walked right back out. Thank you, Mr. Higgins.

The other bit of anxiety I had about the class is that I had a student that needed a failing grade. She needed it. Nothing else could help this girl whose problems had nothing to do with capacity or interest in the material but with basic self-discipline stuff her parents were going to have to address with her. The trick was that this girl’s parent was another teacher in the school and that her teacher was me, a high school kid who probably was not really supposed to be a teacher. I discussed the issue with Mr. Higgins who agreed with my assessment and said he would cover for me. Perhaps that would have been good enough, but it didn’t satisfy me. I swallowed hard thinking that this could be the end of a beautiful thing and went to see the other teacher, this girl’s Mom. I explained how it is that I came to be involved in assigning a grade to her daughter and why her daughter was going to fail my class and waited to see what would happen. She smiled and and told me that I had done the right the thing and that she and her daughter would have some things to talk about. Whew! Now that I have taught professionally, I know and that encounters with moms often don’t always go so well.

During this Junior year of high school I took a few night classes so that I could graduate and head to college the next year. Ever since I attended my uncle’s graduation ceremony at Stanford (where he earned an M.S. in electrical engineering), I’d dreamed of going there myself but not as an engineering student. Uncle Steve had left the computer science at program at Cal Poly because there wasn’t enough math in computers for him. (He has since worked in signal processing, esp. ultrasound and had an invention on the cover of Time magazine.) Lacking his genius for math made electrical engineering sound unappealing and I think his lack of enthusiasm for computer science also dampened my interest in pursuing a computer science education. I also kept running into people doing very impressive things in software without a computer science background and computer scientists who seemed either to be either unimpressed with their own education or who did not seem to be working on especially interesting problems. I do not believe I had a particularly balanced view of the topic but as it was, I always assumed I would study something other than computers in college. At the same time I always assumed computers would be some part of my career life and figured I would continue on self-taught. I never made it to Stanford. My academic work was not consistent enough and family problems continued to play a large role in my thinking about the future. I was eager to leave home as quickly as I could manage so I graduated as a Junior in 1991, moved out before eighteenth birthday and enrolled at Cal State Fullerton where I took humanities courses: literature, history, Latin, linguistics.

While at Cal State and living with my grandparents I worked at Egghead Software starting at the height of the MS-DOS 5.0 sales. In my spare time I worked with a buddy developing a strategy war game on an Amiga 500. He lent me the equipment and provided funding—we bought a hard drive and an audio digitizer—and we used James Dunnigan’s How to Make War as the basis for the model. I ordered a Benchmark Modula-2 compiler for the Amiga from an outfit in Plano Texas, Avant-Garde Software. I wanted to create the appearance of a 3D globe that could be rotated in any direction and zoomed—very much like Google Earth’s except with line drawings instead of satellite imagery. I worked on converting examples in a couple of Amiga BASIC books to Modula-2 (including one on 3d graphics) and struggled with learning how to compile and link against Amiga 3d libraries. A little help from somebody who’d done this before would have helped tremendously, but there was no Googling for answers back then and few Amiga programmers were working in Module-2. (I suppose that should have been a clue, but it never occurred to me to change languages.) My efforts to explain to the compiler maker the issues I was having didn’t help much, given the gaps in my understanding and the challenges of coding by phone. I continued to work away at it as often as school-work and my part-time job at Egghead would allow—and probably more often than that, to be truthful.

Back at Egghead I kept meeting people who were wasting hours struggling with their computers—hours they wanted to spend running their business. They had basic problems that anyone with a little computer savy could quickly solve and help them solve themselves with a little instruction. As tempted as I was to hand out my phone number to offer free help, Egghead had strict policies preventing such things. Eventually I realized as I met computer consultants that frequented the store that there was money to be made helping people with computers in their homes and at their businesses.

During the second semester of my Freshman year, I left Egghead and started a consultancy, The Computer Handy Man. I did the requisite paperwork with the city and county, IRS, etc. filed for a fictitious name, hired a couple of others as subcontractors and took off. My clients kept telling me I wasn’t charging them enough at $35/hr., two-hour minimum charge. It wasn’t bad money for a college freshman in 1992 and soon I was too busy for school. I had almost no expenses. I paid a little rent to my grandparents and rode my uncle’s old 10 speed to all my jobs. My grandfather, who had never finished college but had joined the navy and later had a successful career as the director of a data center for a large savings in loan, was worrying that this would not add up to a stellar career for me. My head was too in the noise to notice, though in the back of my mind I think it was bothering me that I had taken a short-cut my successful uncles had not and that it might catch up with me.

I was doing plenty of IT work and training for my clients and I continued to code for my own enjoyment. One day while I was still at Egghead I had a visit from a Borland rep. who had come to show us Quattro Pro for Windows, a spreadsheet rival to Lotus 1-2-3. It was slick software which introduced common idioms used in software today like “right-click for properties.” (I later learned that Quattro Pro for Windows is still the most productive software project ever measured and a frequent topic of academic research on software development). Somehow during his visit the rep. got himself into some kind of computer trouble which I helped him out with. I cannot remember what I did to help but he was so grateful that he agreed to send me a full version of any Borland product I named. My answer was immediate: “the C++ 4.0 and Application Frameworks package.” This was a heavy duty development kit that ran something like $800 and came with 40lbs of manuals. (I exaggerate, but not by much.) It was shipped to my doorstep a month later and I dug in.

One of the books I read an enjoyed most during this period was The Tao of Objects: A Beginner’s Guide to Object-Oriented Programming by Gary Entsminger. Despite dated code examples, I still tend to choose this book to lend to developers who what a strong grasp of fundamental concepts such as encapsulation, polymorphism and inheritance.

Also while at Egghead I discovered GeoWorks Ensemble which I thought vastly superior to Windows 3.1. It ran faster on a 286 than Windows on a 386 and sported true preemptive multitasking while Windows was still using an inferior cooperative model. The UI was also far more sophisticated. I sold GeoWorks at every opportunity thinking Borland and GeoWorks were going to eat Microsoft’s lunch. I wish I had been right about that. At the time AOL’s client software was based on GEOS and developers interested in coding for GEOS 2.0 would hang out there. So while I was not serving clients, I spent my time gearing up to develop for the GEOS 2.0 platform. I helped found an international GEOS developer’s group and sent in my $200 for the beta release of GEOS 2.0 SDK development manuals. Those were such awesome books. I can still remember reading about the GEOS model for virtual memory—VM chains, if I remember correctly—and being awestruck by the beauty and simplicity of their memory management model—at least from the API client perspective. It was such a great system. In 200k they had a word processor that in many ways was superior to Microsoft word for windows which took a whole box of 1.44 floppies to install.

After running The Computer Handyman for about a year things began to break. My vision was to build a whole big retail chain so that people had more ready access to the kind of services I was offering. My clients would say, “I am just so glad I found you,” as if it had been a stroke of exceptionally good luck. It made no sense to me that most large retail outlets where business people would go to purchase software and computers could offer them little or no computer services. I imagined something like what is now Best Buy’s Geek Squad, but as a Freshman college student with little money or connections, I just couldn’t figure out how to get big players to take me seriously. Everybody was worried about liability—even with my being bonded, insured and having appropriate legal agreements drawn up—and I just didn’t know how to get the help I needed to do what I wanted to do at the scale at which I wanted to do it. The model made sense. I could double a college student’s typical wage and still keep half of what my clients were paying while constantly hearing them say, “you really should raise your rate.” I just didn’t know how to take it to the next level.

At the same time my grandparents were worrying as I spent more and more time squirreled away in my room coding or tying up the phone line chatting with fellow GEOS enthusiasts and coders on AOL. I was so engrossed in my work that I did not recognize that relationships with friends and family were suffering. I have always been good at getting into the zone and focusing, blocking out all else. Even now I can go to work without having eaten breakfast and work for six our seven hours, skipping lunch and taking no pit stops without ever fully realizing that my stomach is growling and foot is tapping frantically under the desk. Yet now it was not just a matter of being focused on a problem, I was having trouble re-emerging.

To be continued in Part 2: The Great Escape 1992-2000

  • 8 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Solo Coding with QuickNote

While I like to code paired, I still regularly work solo when my chums are working on something else, especially since I have been working an iteration ahead of the team doing prep work for the iteration to come. I miss the focus, feedback and the speed with which one uncovers design flaws or edge cases that a solo coder tends to miss without the extra mind at work. This week I am trying something new that appears to be working well for me.

I have been using QuickNote, which has become one of my favorite tools over the last year, to talk through the code as I write it. I’ve found that typing my thoughts rather than leaving notes in a scratch pad or lab book has improved my productivity significantly. I’ll start a test, realize that I have some open problem I need to make a decision about, and then type through a conversation until I have enough of an answer to write my test and perhaps enough direction to write several more. Its so easy to Alt-Tab between my code and QuickNote that I found myself switching back and forth frequently and having to do less back-tracking. Also having the conversation with myself in print seems to bring an extra objectivity to it that actually feels similar to pairing. I spend less time thinking in circles and more time learning and moving forward. Plus, I am left with a record of my decisions, to-do items, etc. which frees up brain cells that would otherwise be burned on anxiety, trying to remember an important thought, etc.

I love the simplicity and obviousness of this.

The following is a snippet from a coding session yesterday. I am building plugin for Resque which allows one to enqueue a directed acyclical graph of jobs while workers dequeue jobs so as to work as many as possible in parallel while respecting the dependencies expressed in the graph. (Fun!)

Now do we really want to be marking job completion in the child process or do we want that in the parent process? What will happen if we kill a stuck job? 

Hmm. It won't be marked complete. That isn't good. So maybe this has go back to the worker... 
    
No, keep it in the child but add an on_exit block. 
    
What about platforms without fork? 
    
In that case we wouldn't be killing child processes, now would we? 
    
Hmm. Worker already uses exit! in the child to avoid at_exit handlers. 
    
Maybe we shouldn't be trying to solve this problem right now. Lets focus on getting the job marked complete. Plus, I suspect that our rescue Object in the Task is going to handle most of what we need.

Sure, it catches SystemExit so the only case we have to worry about is when child process killed with an untrappable signal. That would be easy to detect by checking $?.signaled after Process.wait in worker#perform.

And then back to coding. I like that in addition to the answers I also get the impatience with being off-task or solving too much at once I get in a good pair session. Okay, back to the code…

  • 8 months ago
  • Comments
  • Permalink
  • Share
    Tweet

The Subjunctive is not DRY or the Simplest Thing… in BDD

The typical pattern for writing BDD is as follows (RSpec example):

describe Animal
  it "should eat"
  it "should have an angry noise"
  it "should have a happy noise"

  context "when first born" do 
    it "should be hungry"
  end

  context "having just eaten" do
    it "should not be hungry"
  end               
end

While it is natural to use the subjunctive when describing a future possibility, these statements will live on long after the software specified has gone from being a nice idea to living code. Wouldn’t it be simpler to use the indicative?

describe Animal
  it "eats food"
  it "has an angry noise"
  it "has a happy noise"

  context "when first born" do 
    it "is hungry"
  end

  context "having just eaten" do
    it "is hungry"
  end
end

Not only does this sound more lively and saves an extra word in each statement, it also makes more sense in the output of the test runner. While a statement beginning with should is always true as long as the requirement remains valid, a statement in the present tense is either true or false depending on whether the code actually does what the requirement says it should do—which is exactly what the test runner is telling us.

    • #testing
  • 9 months ago
  • 1
  • Comments
  • Permalink
  • Share
    Tweet

ROXML Factory from Text Node Value

ROXML Basics

The ROXML library provides ruby objects with an XML binding that is easy to specify and round-trip. (Those familiar with ROXML may wish to skip to the punch line.)

class Library
  include ROXML
  xml_accessor :name
end

lib = Library.from_xml( xml ) # pass an IO or String containing the XML
lib.to_xml.to_s # render XML as a String

Easy.

Handle mixedCase element names such as phoneNumber by specifying a convention.

class Library

  include ROXML

  xml_convention do |s|
    c = s.camelcase
    c[0..0].to_s.downcase + c[1..-1].to_s
  end

  xml_accessor :phone_number
end

Changing the element name for an object is easy too.

 class Library
   include ROXML
   xml_name 'mediaCenter'  # yuck
 end

We can nest objects:

 class Book
   include ROXML
   xml_accessor :title
   xml_accessor :author
 end

 class Library
   include ROXML
   xml_accessor :name
   xml_accessor :books, :in   => :books, 
                   :as   => [Book]
 end

lib = Library.new
lib.name = 'Fullerton Public'
lib.books = []

a_book = Book.new
a_book.title  = 'The Story About Ping'
a_book.author = 'Marjorie Flack'

lib.books << a_book
lib.to_xml.to_s

Rendered as so:

<library>
  <name>Fullerton Public</name>
  <books>
     <book>
        <title>The Story About Ping</title>
        <author>Marjorie Flack</author>
        ....

The reverse works too.

Library.from_xml(xml).books.first.title # => The Story About Ping

ROXML also supports much more complex mappings of not just elements but attributes and not only to Arrays but also Hashes. The yardoc for Declarations is a helpful start.

An interesting problem

Now what if our system must also cope with special rules for journals, newspapers, eight-track tapes, laser discs, and the like? Since our XML is coming from a system designed by Acme Card Catalogs and Kitchen Appliances INC., we need to handle the following:

<library>
   <media>
     <item>
        <medium>cassette-tape</medium>
        <title>The Story About Ping</title> 
        ....

So we need to look in the media element to know which class to load—and we want ROXML to handle it all for us.

Tricky Bits

In the following solution a base class, Medium, provides generic mappings for all media and a registration system for subclasses which define additional xml mappings.

class Medium

  include ROXML

  class << self

    def register(medium_id = nil, a_class = self)
      registry.store(medium_id || id_from_class, a_class)
    end

    def id_from_class
      demod       = ActiveSupport::Inflector.demodulize(self.name)
      underscored = ActiveSupport::Inflector.underscore(demod)
      dasherized  = ActiveSupport::Inflector.dasherize(underscored)
    end

    def class_for(medium_id)
      registry[medium_id]
    end

    def registry
      unless Medium.instance_variable_defined?(:@registry)
        Medium.instance_variable_set(:@registry, { })
      end
      Medium.instance_variable_get(:@registry)
    end

    private :registry

    alias __original_from_xml from_xml

    def from_xml(xml, *args)
      if self == Medium
        xml_node = ROXML::XML::Node.from(xml)
        if xml_node.nil?
          raise "Bad xml for action:\n\t#{xml}"
        end
        medium_id = xml_node.xpath('medium').first.text.strip
        medium_class = @registry[medium_id] if defined?(@registry)
        unless medium_class.nil?
          medium_class.from_xml(xml_node, *args)
        else
          $stderr.puts "WARN: no medium for #{medium_id}."
          __original_from_xml(xml, *args)
        end
      else
        __original_from_xml(xml, *args)
      end
    end

  end  # class methods

  xml_name 'medium' # even in subclasses

  xml_convention do |s|
    c = s.camelcase
    c[0..0].to_s.downcase + c[1..-1].to_s
  end

  xml_accessor :title
  xml_accessor :author
end

class CassetteTape < Medium
  xml_accessor :read_by
end

class Book < Medium
  xml_accessor :binding
end

class Library

   xml_accessor :media, 
               :from => 'item',
               :in   => 'media',
               :as   => [Medium]
end

CassetteTape.register
Book.register

With this in place one may now read and write xml in the form:

<library>
   <media>
     <item>
        <medium>cassette</medium>
        <title>The Story About Ping</title> 
        <readBy>A. Reader</readBy>
     </item>
     <item>
        <medium>book</medium>
        <title>The Story About Ping</title> 
        <binding>hardcover</binding>
     </item>
   </media>
</library>

We now have objects with generic methods for all Media as well as data and behaviors specific to a medium.

 lib = Library.from_xml(xml)
 lib.media.each do |item|
   puts "#{item.title} (#{item.class})"
end

The advantage of using this simple registration system is that we can easily substitute mocks and stubs for testing without a fancy dependency injection framework which is typically overkill in Ruby given the language’s power to reopen classes and the availability terrific mocking/stubbing libraries. For example, to test generic functionality without dependencies on specific media:

class FakeMedium < Medium; end
Medium.register('book', FakeMedium)

Library.from_xml( xml ) # with an xml document containing books, 
                        # ROXML now parses the document with our mock medium
                        # instead of Book--which may not exist yet.

Sample code is available as a gist. Happy coding!

Thanks to Tricia Ball for pointing me to ROXML in the first place.

    • #ruby roxml
  • 9 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Search KhanAcademy

Ben Jacobson’s “as you type” search of Sal Khan’s youtube content is slick.

  • 9 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Remembering Christmas 2002.

No lasting damage.

(Click to the right of the photo to see all.)

  • 9 months ago
  • Comments
  • Permalink
  • Share
    Tweet

AUTOTEST + RSPEC2 + JRUBY + RVM + BUNDLER

Today we had trouble firing up autotest on a Rails 3 project. Adding the following to our .autotest file seemed to solve the problem.

class Autotest::Rspec2 < Autotest
   def make_test_cmd(files_to_test)
     files_to_test.empty? ? '' :
        "bundle exec rspec --tty " \
        "#{normalize(files_to_test).keys.flatten.map{|f| "'#{f}'"}.join(' ')}"
   end
end

For more see https://github.com/dchelimsky/rspec/issues#issue/7

    • #ruby
    • #rails
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

jpshackelford

Portrait/Logo

About

John-Mason Shackelford is a software engineer with Pearson Education in Iowa City, IA.

The views expressed here are his. Blame him.
  • Archive
  • RSS
  • Ask me anything

Pages

  • stories
  • résumé

My trail

  • @jpshackelford on Twitter
  • jpshackelford on Flickr
  • shackelford on Delicious
  • jpshackelford on Grooveshark
  • My Skype Info
  • jpshackelford on github

Twitter

loading tweets…

  • RSS
  • Random
  • Archive
  • Ask me anything
  • Mobile

Effector Theme by Carlo Franco.

Powered by Tumblr