Community Oriented

Gems

Web Based

Projects For Me

Week 2 at 8th Light

This is like the sequal of 2 blog posts ago, 5 Sep 2011

Bam, another week's gone by already! First, lets dispense with important updates:

  • I've added Neil deGrasse Tyson to my list of inspirational people on Facebook.
  • I'm less keen on 8th Light hand shaking after having a sore throat for 3 days.
  • I've decided that I need to go to Ruby Midwest because I miss my WSU chums (Uncle Bob is a keynote speaker, so I think I can make it happen)
  • My family is awesome :P
  • I've selected Doctors Without Borders as my life insurance beneficiary, so don't think you can cash in on my insurance money by offing me. Ain't gonna happen.

Monday

Alright, now down to business. Monday I started working on a Java webserver. It uses this series of articles (starting at "Once Is Not Enough") as the foundation for dealing with threading and sockets, and everything else comes from my brain. I enjoyed it, but can't help but notice discrepancies between some of Bob's code in the articles and some of the things he says in Clean Code. I get confused, when I use his code, whether I should refactor it or whatever.

Tuesday / Wednesday

Tuesday, I spent a lot of the day trying to figure out how to test some stuff. It made me frustrated and I finally settled for this, which allowed me to override what object the server uses to respond to a request.

public class HTTPRequestHandlerFactory {
    private static HTTPRequestHandler mockHandler = null;

    public static HTTPRequestHandler getHandler() {
        if(mockHandler == null)
            return new HTTPRequestHandlerImp();
        else
            return mockHandler;
    }
    
    public static void handleWith(HTTPRequestHandlerMock handler) {
        mockHandler = handler;
    }
}

But it turns out that as gross as that is, it's what I needed, because it acted as a bridge to my discovering the Abstract Factory Pattern. So now it looks like this:

public interface HTTPRequestHandlerFactory {
    HTTPRequestHandler getHandler() throws IOException;
}

Which I no longer hate, and kind of like. Especially since my mentor, Doug has let me know it's an "official" pattern, and not just some ridiculous interface abuse on my part. I think I could probably get rid of it with reflection (it's not easy in Java, but it exists). I wouldn't have discovered that in Ruby (because you wouldn't need such a thing), so I appreciate Java for that.

I've found a lot of design patterns don't make much sense in Ruby. Design patterns seem to be largely composed of tricks that people have independently discovered to allow them to get around the rigidity of static typing. I want to show them in Ruby (like my last blog) because it strips out all the extra stuff that gets in the way of the example. But it also inherently solves many of the problems that the design patterns are intended to help you jump through, so there's lots of "you don't actually have to do this in Ruby" comments all over the place. A weird conundrum.

Wednesday / Thursday

Wednesday I got my server processing HTML. And then on Thursday, all the apprentices went to the 8th Light office for sort of a consolidated work session. I really enjoyed that, it's a lot more laid back there than at our clients', where I've been working. I totally hopped on the treadmill for a few hours, and cranked out a framework to make it easy to use my server. It wore the crap out of me, but I also enjoyed it. Then I had to code in the hammock because I was sore and exhausted :)It was also nice getting to socialize with the other apprentices, and we're going to start doing coding projects together so I'll get some pairing in, and get to work on projects with more than just myself. I'm really looking forward to that.

Doug liked my web framework, and it's passing the test suite we have for them, so I'm pleased with it. It's about as Sinatra like as you can get in Java, by exploiting some of the nuances of inner classes and inline class bodies. Here's an example.

WebFramework cobSpecApp = new WebFramework(8087) {

    public void defineRoutes() {
        new GetRequest("/") {
            public String controller() {
                return "Hello, world!";
            }
        };

        new GetRequest("/SimultaneousRequests") {
            public String controller() {
                return "Simultaneous :)";
            }
        };
    }
};

cobSpecApp.startRunning();

You can also set headers and status codes in there. On the whole, I'm happy with it. I think my code is generally pretty good. There are a few things in the code I'm not sure about, such as this place where I (privately) use a hash of hashes. This leads to a few methods that have to check that the second hash exists before performing operations on it. Because of my coding style, it's not gross to look at, but I did find I had to explicitly explain it, and am wondering if it wouldn't be better to wrap it in an object of it's own.

I also have a class whose only job is to present a consolidated interface for requests and responses. All of its methods really just forward their arguments to these objects, but I'm wondering if it isn't better to just pass the request and response around by themselves.

I also have duplication in my test "helpers". I wasn't sure what to do with them for a long time, because they really didn't belong anywhere (you can't reopen classes in Java, and the tools it gives you are rudimentary, so you end up writing lots of little helpers) For example, I convert socket streams into strings a character at a time in several places. Where should that go? In retrospect, I've decided they probably should go in their own class "TestHelpers.socketToString(socket)" or something, but I'm not looking forward to going through all my tests looking for duplication.

Friday

On Friday everyone got together and one of the other apprentices presented the String Calculator Kata. It's kind of a weird kata, and I don't think I like it. It has this whole delimiter thing which is unnecessary since it's implicit that any character which isn't a digit or minus sign must be a delimiter allowing for a more straightforward solution of:

module StringCalculator
  def add
    raise "Negatives not allowed: #{negatives.join ', '}" if negatives.any?
    numbers.inject(0) { |sum, num| sum + num }
  end
  
  def negatives
    numbers.select { |num| num < 0 }
  end

  def numbers
    scan(/[\d-]+/).map(&:to_i)
  end
end

I suppose you could make the argument that you should be able to specify a negative sign or a digit as your delimiter, but that requirement has not been made explicit, so this solution passes the full spec.

After the Kata, we had the next installment in 8th Light University (I think this site is under development as an apprentice project, because I know we have a lot more content than is currently displayed), where Brian talked more about CoffeeScript. After that, Stephanie Briones, a design apprentice, gave a talk and presentation about CSS. Then everyone did some coding, I added Bundler to RubySlim, as it uses an older version of RSpec that you won't necessarily know about. Later I closed the request as I realized that Rubygems will handle that for you (though I think some thought should go into how it should be distributed and installed, because the version on rubygems is old, and I don't think most people know how to install gems from a gemspec). I also worked loosely with Kevin, one of the other apprentices, on an assortment of different things.

After work, I had a drink with one of our outspokenly religious craftsmen. The bar was not conducive to conversation, but we made it work. I'd been wanting to have that conversation for a few weeks because it's a topic I'm opinionated about and biting my tongue makes me agitated, but Twitter just isn't sufficient for real conversations (plus I didn't want to irritate all my new colleagues). It's good to have gotten that in, it's not unlikely that we'll have more in the future, seeing as we're both opinionated about it.

Other thoughts

Over the weekend, I've mostly just been reading Clean Code, I need to have it finished by Tuesday. It's slow going, because it keeps sparking ideas which I want to go try out or play with.

This city is strange, I realized I made a mistake choosing to live in the loop. I thought I would be in the heart of it, but everything shuts down at 7PM, there wasn't even anywhere to buy cough drops. I probably won't renew my lease here as I hate how the city turns off, it's about twice as expensive to live in the loop, and given that I often work from a client's place it's not actually all that close (20 min by foot, 30 min by train). The place across the street has these nice balconies and I realized I really want to sit in one of them coding into the evening with Chicago all around me. I think I'll get a place with a balcony next time.

I also joined the Ruby group here in Chicago. They're having a meetup tomorrow, but it's completely full and has a waiting list, so I'll wait for the next one. The topic will be recursion, which I already love :)I even made a video about it for Ruby Kickstart. Looking forward to that one.

I've realized what a gem 8th Light is, not only do I have a mentor, and a curriculum (so much nicer than trying to cobble together my own education out of all the disparate opinions and resources out there), but the people here aren't just Rubyists and they don't just do Rails. They care about the process, and about software development as a whole. I've worked with Ruby and Java and even Clojure this week. In conversations I've had with 8th Lighters, C and D and Haskell and OCaml and Go have all come up. I think that's pretty rare, and I'm really exciting that I get to be part of a group like that.

Alright, I think that covers week 2 as an 8th Light apprentice in Chicago. Don't go too far, there'll be another one of these soon :).

blog comments powered by Disqus