< prev 26 Nov 2014 to 16 Nov 2014 next >
  • Rails

    ????

    I've completed the readings for tomorrow. I don't understand anything, except that I've added a data point: the higher the level of abstraction, and the less repetition you have, the more confusing a "simple introduction" will be.

    I think learning Rails will be aided by having a large bottle of something strong. Thankfully, I picked up a handle of Jim Beam. Me and Jim are going to pair program the fuck out of some Active Records this weekend.

  • Week 3 Day 2 - Tumblr.find_post_by_date

    Today's partner: Michael D.

    Unpacking, since I can't actually remember what we did today:

    I know this isn't the point of appAcademy, but today was the most fun I've had since we started. Michael and I were cracking up about mistakes and ruby/SQL absurdities all day.

    Yeah, so we were doing something with SQL… I thought populating the test database would be more onerous than it was, but really it was a couple INSERT procedures copied over and over.

    Oh, I remember now… so we made basically a tiny reddit clone, using database accesses on an SQLite3 instance. By reddit clone, I mean a class structure with Posts, Users, and Comment trees (Questions, Users, and Replys), where we had to write procedures to translate between stored and active objects. It was very educational, but similar to yesterday in that it was a straight walk through the instructions, implementing some calls that were well within our understanding of SQL and Ruby. Certainly nothing earth shattering, but the practice was good.

    In not quite unrelated news, I've been meaning to get my financials in a format I can actually do something with… I think I have just enough tools to start doing something interesting with my data. A CSV parser, an SQLite3 instance, and a lot of ruby code, and I could probably do some pretty damned cool stuff :)

  • Week 3 Day 1 - SELECT * FROM students WHERE confusion > 0

    ;

    Today's partner: Justin

    A good day. The assessment started out okay: I got through 90% of the coding in under 30 minutes… then I choked and couldn't scrape together enough bugfixes to make the last test pass before time was called. After crushing the practice assessment over the weekend, it was a bit weird to have such a turn of events this morning, but it just makes it clear that I need to continue practicing: ruby, rspec, and whatever else we're going to be learning. It needs to come easy, and I need to triumph over my demons of both attention, and attention to detail. (Did you know '8' is different than :eight? Crazy! Crazy eights!)

    So I have to do a three-line bug fix and re-submit before 9:00 to get that last point. Hooray?

    It's telling that by noon, no one was talking about the assessment anymore. SQL was quite the leap for just about everyone, and even though when I listened around it seemed like we were all on the exact. same. exercise at each moment, it turns out there was a lot of hair-pulling and gnashing of teeth at other tables.

    My partner and I didn't have any particularly noteworthy trouble, but there were some hairy JOINs that took a bit of digesting to grasp. Again, I know that I don't understand SQL completely yet - sometimes it feels like a matrix language, with all the associated transformations; sometimes it feels like a procedural language full of loops—but I can guess out what a statement is going to do if I can access the schema. So, hooray.

    I'm actually really excited about tomorrow's SQLite lesson. I keep hearing about SQLite in desktop and mobile app development, and now that SQL doesn't seem such an impenetrable barrier, if I get the hang of things tomorrow, I could theoretically look into learning Obj-C or Swift at some point and actually start making money off development ;)

    ;

  • SEMICOLONS

    That is all.

    ;

  • Week 2 Day 5 - Who Tests the Testmakers?

    Today's partner: Ron

    All the coffee in the world could barely get me through this week. It was fine, in the end; there's been a much more relaxed feeling on the two Fridays we've had so far. (We're 16% through the program already. What the hell.)

    Most of the day was about rspec, the main ruby testing framework. It's actually a really nice language: a language for pedantic testing, by pedantic testers. Tommy joked/not joking that they re-write major portions of the syntax every 3-4 months, and I can totally believe it. When you're as steeped in the mindset of testing software as they have to be, your inclination has got to be to make your domain-specific language as polished as you can.

    I do wonder what their internal unit tests look like, though.

    Other than endless coffee and jokes about writing a test that you yourself are going to be taking, the day/language were interesting. I really like the rspec syntax; once you get used to the grammar, it's actually quite clear to read. It took a mere two hours last night to be able to figure out all I needed to understand to complete the practice assessment. As hard as it was, I got the impression that I understood a bit more this morning than a lot of the other students, so maybe I'm primed to be thinking in the way that the rspec designers do.

    We skipped through the practice exercises, basically doing just enough coverage to make sure we were getting the point. We could tell how much clearer it makes problem solving: break something down into discrete parts, then figure out where those parts should live and how they should interact, and 90% of the hardest work is behind you. I really look forward to using the TDD methodology on a more robust project; it's quite clear that, like so many other student projects, the power of the tool we learned today far exceeds the significance of the work we were doing. It's basically like using a sledgehammer to drive a nail into drywall.

    A couple things I put together today:

    • No one I've worked with or talked to so far has nearly the level of paranoia about breaking things that I do. I think Bruce Schneier is right that the security mindset is probably something you mostly can't train.

    • As I've mentioned, this also makes me a bit overcautious. It might behoove me to look for employers than want careful, deliberate work done, or to force myself to make fast, dumb code, and refactor much faster than I do.

    • All of a sudden today, I understood what all the comments that I've read about "unit tests" and "integration tests" meant. There was a total "aha" moment when we were talking about mocks where I was like, duh, of course that's a thing, and now the difference between these other things makes perfect sense. Maybe I hadn't thought about it before?

    • It's ridiculously easy to write code when you are writing tests alongside.

    • There's a bit of weirdness to crashing your testing framework because of a syntax error. "Okay, which one crashed, and why? Oh, we messed up that syntax, lololol"

    • It's so much cheaper to make coffee at work, EVEN if you're making coffee for everyone else, too. If I leave the money in the can, I've still come out ahead.

  • Week 2 Day 4 - Anagnorisis

    Hoo boy. I can feel stuff stacking up.

    Checkers was basically a repeat of chess, but simpler. I thought I had learned a lot, but today was a real learning day.

    For background: it was our first solo day, and without anyone next to me who was depending on me to drive/navigate, I was somewhat slow to sink my teeth into the project. I thought I was sticking to the spec, but I spent a long time running off on tangents, trying to get minor methods to do what I needed in order to be able to get printable output as quickly as possible.

    This was a mistake.

    I've come to suspect that my working memory isn't great, and that that's why I try to recursively abstract problems—I can only manage 5 +/- 1 ideas at a time, and the more high order the chunks are, the bigger the idea I can digest.

    So when it comes to seeing how different parts of a multi-class project will fit together, I miss things that become both obvious and painful a couple hours in. (Debugging complex interactions in similarly challenging for essentially the same reason.)

    Today's big pain: I misread the spec, in a way. There are basically three general ways to send moves around the core class of the checkers project: as positions ([1,1] to [2,2]), as differences from a starting position (start, [+1,+1]), or as some general class of methods I will refer to by the technical term "totally effing stupid".

    Yesterday we generated moves early, and only passed moves around. That worked well; we had a simple wrapper on the class that translated algebraic notation ("b3" = [2,3] = [1,2] in 0 indexed arrays) to the position references we were using, and then we only passed those around.

    Today, because I misread things, I started out passing around differences, then I realized that I needed moves, then I tried to simplify things using one of the last methods, and that was, predictably, totally effing stupid.

    I got a lot working, but my errors weren't working right on certain literal edge cases, and finally I threw in the towel at 9.

    Lessons "learned":

    • When doing solo work, pseudocode flowcharting might be necessary for someone like me to avoid super-dumb mistakes
    • I need to rubber-duck, either with a human, or with a rubber duck. I think I'm going to put my plush octopus next to the home computer. She needs a name, though, so I can talk to her properly. (Completely serious, by the way.)
    • If I'm going to rubber duck on solo work, I need to not be in a place where I'm going to be self-conscious doing so

    There's more, I'm sure, but I have a ton of readings to do before 2 am, god willing.

    "Am I the one who holds good pairs back?"

  • Week 2 Day 3 - Code Complete

    Today's partner: Anthony

    A cold day in NYC.

    Getting more used to the schedule: even though I woke up a bit later than I prefer this morning, I knew what I needed to do to get out of the house and get fed before class, and I knew what we needed to do when I arrived. Coffee was brewed all day, we did our work, the breaks went well… this program is pretty cool.

    There's still more to be done with chess, but I have to say that we got to a really good place today. We have a really clean codebase that could be hardened a bit, but the code is about as organized and modular as it needs to be.

    I'm mostly done with chess; everything that's left is polish on a solid core. Don't get me wrong - it's good - but there's not a lot of marginal learning value left on this topic. The remainder of the work is the programming equivalent of going to the gym once you've hit your target weight: good practice, but kind of rote and boring.

    When I'm not so tired of it, I may come back, but I'd actually prefer to do something else. Perhaps look at the mazesolver/mazebuilder that I started skeletoning earlier this week: that should provide some interesting problem solving.

    My partner and I worked well today. I was still domineering, sort of, because I didn't want to have to finish chess after class tonight, but he held his own. I hope he learned something from me and didn't hate working with me :)

  • Week 2 Day 2 - The two hardest things in programming...

    … are naming things, cache invalidation, and off by one errors.

    Today's partner: Anthony

    Today was all Chess, all day.

    Actually, that's a lie. We did cover error handling in lecture and did a couple exercises (for about ten minutes; we figured that we'd do a proof of concept, then implement more error handling in chess.rb), but after about 10:30, we were coding the Chess class and its subclasses for about eight hours straight.

    It went well, in my mind. My partner is learning buckets of things, and he's been a real sport in terms of letting me show him how to do things quicker in Atom, pry, and git. We've been sure to make our code readable as we work, and test as we go - what we have now is readable, functional, and succinct. This is the kind of code I can begin to be proud of; lesson learned from the past couple days.

    Strangely, though, all this work results in about 300 lines of code, including whitespace… not a lot, right? Especially for the full-time output of two people. I'm sure that, in time, we'll be faster as a cohort, but this period is very focused on didactic activity: everyone has something to learn, if not from their partner, then from the code or documentation.

    The primary virtue of the Chess project, I think, is to see how you can best handle exceptions1, and to see how important it is to have well-defined roles contained in well-defined source files. It also helps to gain experience with git in different contexts, but I appreciate the simplicity of git's cognitive model, because basic use demands very little cognitive overhead.

    Other thoughts:

    • The office is moving over the weekend, to a more convenient location (for me) that is apparently about twice the size of the current place. Neat.

    • The coffee club is bootstrapping nicely; I'm going to send out a message to the group about a better ruleset.

    • I got three or four specific positive comments from people on various things I've tried to do to make people's lives easier. Feels good, man. (I mean, it's not why I do these things, but it's nice to know I'm not just emailing into the void.)

    • I wish I would have enough money to go out to lunch every day; some of the best conversations happen in the combinatoric randomness of lunch groupings.

    1. Instead of looping over input until it's valid, like I might have done in TI-86 BASIC, you embed your calls in a begin...rescue...retry...end block. 

  • Week 2 Day 1 - "We can refactor that later"

    Today's partner: Marc

    Today was the day of the first assessment. It went well—I was less nervous than when I did the practice assessment, which I guess is the point—but I ended up tripping on the same edge cases as I had doing the practice. Derp.

    (Technical gore ahead: I was writing a sort method per the instructions, specifically bubble sort—I know, I know—and wrote a helper method to implement bubble_sort! that was called by bubble_sort. Somewhere along the way I started getting wrong argument errors—0 for 1 or 1 for 0, depending on what I was doing at the time—and it took me ten minutes to see that I had been checking the function signatures for errors, when it was the call out to the helper method that was causing the problem.)

    I felt guilty for finishing early since it seemed like most everyone else was still working, but looking around it seemed a couple people finished earlier than me. Sure enough, looking at tumblrs, another student finished absurdly quickly—the specific student I expected—and really, I ought to have been just a bit slower than him.

    A lot of students have that moment when they first enter a highly selective program where they realize they're can't easily be the best anymore. I've had enough time in life to get used to that idea, but really there's little enough excuse for me not to push harder to get better. Having a decent target to reach has helped my typing speed (compared to just typing gibberish in a typing trainer) but I still have to test my assumptions about what a method can handle and what it returns too often for comfort. What I'd like, by the end of this program, is to be in the running as the "best" student and not just coast on … whatever it is that's gotten me this far in life. That will take work, and prioritization.

    As any regular reader of this blog will be able to understand, most of my biggest demons are of my own creation.

    We spent the entirety of the rest of the day working on Minesweeper. I can tell after a solid week that one of the critical pieces of Pair Programming is how well or poorly the personal dynamic plays out. Historically, I haven't been one who can easily convince another to adopt my priorities. This is another thing that I think raw competence can help with: people will listen to someone who seems to know what they're talking about, especially if they have easy confidence, even if that person doesn't actually know what they're doing (until, of course, that person is revealed as a sham). Further, sometimes the people you have to work with really want to go in one direction when you wholeheartedly believe that another route will bear more fruit. Wrestling with this sort of thing can be exhausting, because either you defend your idea and "win", or you realize the other person has the better idea and concede your point. Either way, you've expended a lot of mental energy.

    I'm not saying, mind you, that my partner was particularly difficult to work with. I have had some amazing pairings so far, but today was one of those days where we each had an idea for what needed to happen, and we were pulling in different directions—vectored off from one another just enough that it was a challenge to move forward.

    We got where we needed to be by the end of the day. The game worked, we had a somewhat clean data model, and our logic held up. We were even able to add some extensions—we changed the symbols used from rough ASCII to some nice Unicode that I think was much more readable on-screen. But toward 3:00 or so I began to think we ought to order T-shirts that say "Don't worry about that; we'll refactor later." Were this a production codebase, we'd have accumulated a lot technical debt today. Compare this to most of the projects in the first week: my style was much more comfortable and easy to read, with only a couple places (typically method chains) where I could benefit from some cleanup, and I think that's a direct consequence of having a solid idea of where we needed to be and the route we would have to take to get there in the first thirty minutes of class.

    That is to say, all of our problems can be traced back to an overall bad approach to architecting the solution, specifically the separation of class responsibilities and the mechanism for passing certain objects. Prototyping, or figuring out a full schema earlier on, may have helped protect us from some wild goose chasing, but as Fred Brooks said, when solving a new problem teams should design a throw-away system first, because you're going to throw the first one out anyway. (See also: Annie Lamott's "Shitty First Drafts")

    It's not easy to see your own failings, but looking around some common ones that others demonstrate include a resistance to learning skills that are not core to the "purpose" of a course (the purpose being debatable—I've been at enough colleges to know that what's on the final is a small fraction of what a student needs to learn), stubbornness about one particular approach (kill your darlings!), not being able to listen to others at all, not telling others what you're doing because it's obvious to you, not giving people the benefit of the doubt… to some small extent each of these has manifested in my time here, and I'm on the lookout for those times when I, myself, am guilty of these. Small sins can be hard to see.

    It was a good day, overall. I love the people here, but the difference in energy level between a good day an an average day is really noticeable. Still, every day so far has been far better than any day of work or school until this point.

  • Week 1 Day 5 - Painted into a corner

    Today's partner: Connie

    It's a bit of a challenge to reconstruct my memory of Friday after I failed to save my draft Friday evening, so excuse this entry for being perhaps a bit vague. Also, I'm going to speak in the tense I would have had I completed this entry Friday.

    Today was the first day where there wasn't enough work to actually fill out the day. We had two main projects: a small class that built trees of moves for a Knight navigating a chessboard in order to find the shortest possible route between two points via knight's moves, and a Tic-Tac-Toe solving AI (on top of a couple small vignettes). Of course, the point of the AI wasn't to show any great details about AIs; rather, we were working more on Object Oriented programming, data structures, and algorithms.

    These algorithms can broadly be called "paint bucket", or "flood fill" algorithms: starting at a point, do some action to all the "neighbors" (keep in mind that a knight's neighbors on a chessboard are moves of 1,2 away, and not adjacent squares - one of those mathematical things where you have to keep in mind the context you're dealing with), and then repeat for the neighbor's neighbors, ad nauseam until there are no more valid spaces to apply the action.

    Doing this sort of naive AI over and over has certainly helped drive home how to best write recursive OO code to do breadth-first search in different contexts, with different types of objects, but again we're not making contest-winning AIs here.

    Our biggest problem today was a weird edge case bug in the TTT AI. The spec was a bit hard to read, and once we nuked the half-dozen syntax errors in our collected source files, we found the logic as stated in English in the instructions to be a bit vague on what the various parameters means and how to pass them around. It took the better part of an hour or more to vary the code and make the lynchpin methods work properly, but once we got those right, the tests all passed without a hitch, and it was glorious.

    Of course, at that point, we only had an hour left to work. Without a bonus problem to chew on, there wasn't much to be done except to dip our toes into this weekend's reading and talk about the course as a whole. I showed my partner a couple resources I had seen on using git, which I hope she found valuable, and then just chatted about stuff. I know I'll pay for it this weekend in terms of worktime lost, but sometimes you just need a break, you know?

< prev 26 Nov 2014 to 16 Nov 2014 next >