Posts tagged 'ruby'
My time the past couple days:
- Writing Project Euler solutions in Ruby, using the "get it done, get it fast, get it good" (alt: make it X) philosophy
- Realizing that I could no longer write the Python code I wrote less than a year ago
- Crushing it on phone interviews that I didn't plan on having anyway
- Faceplanting on an in-person interview that I should have been able to do better on
- Writing and analyzing algorithms with people at the office
- Taking on projects that sound interesting until you realize that you're trying to bite off way more than you can chew
It's important to stay busy with productive work, but it's tempting to think that what you're doing is valuable when in truth the marginal utility is pretty low.
In other news, it's interesting to see how natural writing Project Euler solutions is in Ruby compared to Python. I have many fewer head-scratching moments when it comes to the natural plan of attack—generally, I can just implement the solution that comes to mind, and it runs well enough. Project Euler is, I think, like Alaska: it's not where you learn, it's where you prove yourself. It just happens to be the biggest name in toy programming problems, and many people assume that it's good at teaching you… something.
Not sure what else to say. I'm trying to keep at good habits, and I started thinking about what I wanted to write on the train in today, but then I started thinking about how to build an Abstract Syntax Tree in Ruby (and whether I really need to in the first place, to do what I'd like) and lost what I was going to write. Oh well. More practice; back to the grind.
Today's partner: Mark S.
Today was all about Controllers. Well, and ActiveRecord relations and SQL queries… first things first.
The assessment went really well, I believe for most people, but especially for me. I did the practice assessments two (and a half) times, and when I came in this morning asked my neighbors what they had done to practice. One had a really good suggestion—look for foreign keys early on, in the
schema.rbfile, and then implement the
belongs_torelations based on those keys. With this hint, a bit of practice, and a much greater understanding of SQL, I didn't really have any issues with this assessment.
The readings last night were a different story, and I was really worried about how the day would play out. I knew coming in that today was going to be about the C of the MVC paradigm - we've covered models, we'll get to views tomorrow, and we were doing controllers today. But none of the readings we had to do made it clear what, exactly, controllers would consist of. I sort of struggled through, and collapsed into bed.
Well, this morning, it was much more clear. During the lecture, Jonathan and Constance showed us a lot of the same stuff we saw in the readings, but watching it live, it became clear how it was going to fit together. REST combined HTTP verbs with URIs to produce a variety of different responses… which are handled by the routes handles in
routes.rband the controllers generated by rails.
There's not a lot to say about the controllers themselves—you define them in a predictable way, they have actions defined in an easily readable way, and you write those actions in pretty predictable ways.
Ultimately, because rails is actually pretty sane, learning more about controllers teachers you a lot about generating, models, and I presume views… in addition to me focus on learning snippets, shortcuts, and so forth, it feels like we're really picking up speed. Or at least I am. But looking forward at the readings, there are certainly a lot, and it's clear that having a repeat of today—hard work, but valuable—will require sticking to the readings and making sure I'm ready for the next day.
As others have remarked, because of the holidays, the weeks and days are just pointers to lesson plans, and not actual days and weeks. I actually got to the end of the day yesterday and asked someone "what day is it?" honestly hoping that they'd say Wednesday. It felt like a Wednesday.
It wasn't Wednesday.
(week 4, day 2)
Today was all about meta-programming, centered around the ActiveRecord Lite pet project. Real ActiveRecord does a lot of the work of writing repetitive code for you, and our toy AR did a lot of the same things, albeit not as gracefully. Meta-programming itself revolves mostly around defining methods at runtime that build out in predictable ways, so you can do all that cool stuff for free.
It's actually quite nifty, if only you are able to keep track of who will be calling each of the methods you write and where. In essence, Ruby offers faculties that permit you to give methods to a class or an instance (or an instance of a class…); variables can be local, or belong to the instance, class, or class instance… I'm still not totally solid on all the distinctions. My coding style today was essentially "keep changing whether you say
self.nameor nothing at all until the damn thing passes."
Aside: A potential project for a later date would be to make a simple file full of classes, instances, and modules, and see how different things behave and what they think they are. To wit: I could make a
Class, and see what that module's methods say they are, and then
includethe same module in the same class and see what the methods do when they're called by instances of the class…
A huge part of reading and understanding code centers around being able to simulate system state in your head, or at least to scan idioms and interpret them subconsciously. Like reading English, you can only leave so many pieces as null references, hoping to pick up their meaning through context, before the main idea of the block is completely lost.
Anyway, so I felt like I was lagging all morning, and yet again, once lunch had passed I picked up a lot of steam. (There's gotta be a better way to get through the morning doldrums!) I managed to complete the exercises with five minutes to spare, and it felt really good.
I was much more patient and thoughtful today than during Checkers. At lunch I thought this post would be starting with a discussion of my demons, but being aware of them and having to face them a solid day at at time seems to be working.
Today's partner: Eva
The assignment today was deceptive. It began simply enough—with me completely forgetting everything I learned about ActiveRecord last week. Wait, back up.
Today's assignment expanded on what we learned about ActiveRecord before Thanksgiving. It took a little bit to warm up, but thankfully Eva had done enough practice to get me on track quickly. It was a lot of boilerplate:
has_many( :method_name, class_name: "Blah", ...)(which is a bit annoying, because of course the solutions all use the more succinct forms of relations), which seems somewhat typical of this phase of Rails.
The project centered, again, around a standard online trope: the survey.
Users and their selections from these answers. The core work: outlining the migrations, defining the initial validations and relations, and adding indices all went smoothly, and we were done with the core logic that was demanded of us (mostly custom validations) well before 2. There was a bit of tricky SQL and ActiveRecord Relation syntax (not logic, per se) that we struggled with, but overall it was very smooth.
… and then came the Bonus work. Four hours of bonus. Holy mother of god, there's some convoluted rules for what can and can't be put in different places in a Relation. (
joinscan't take parameters… wat.) However, I gained some respect for the power of building queries step-by-step, especially when Eva and I stumbled across the finish line and read through the solutions. One of the validations we struggled with was addressed by defining the
SELECTlogic and the
JOINlogic separately from the heart of the SQL statement, then glued everything together, firing off a single db query at the last possible moment. Pretty neat.
I'm a bit concerned about the upcoming assessment (this Wednesday, although I need to do at least one practice run tonight) because it's clear that it takes me a minute to spin up when it comes to starting work in Rails. I have time to practice, and as long as I make use of it, I should be fine.
Today's partner: Ed
Today was our first exposure to Real Rails™. We delved into ActiveRecord and creating relations between our created classes and their associated tables (created via migrations).
Setup is pretty straightforward: specify your database during creation, or edit the .yml file to specify your database because you're dumb and forgot to throw rails the configuration option, then get to writing migrations. It's clear that rails is designed around a fast iteration cycle, either Agile or TDD, because just about every action has an easy way to build up, reload, or rollback.
But that's not really what today was about. Today was about trudging though a lot of examples of the most basic Rails structures, which are superficially similar to their SQL roots and the code that's created when you create raw SQL glued together with Ruby. It's certainly nice, and we learned a lot about the basics of Rails, but it felt kind of like a slog because it never went much of anywhere… yet.
So this weekend, I'm going to try to re-read Hartl's tutorial alongside the pre-readings for next week to try to build some excitement for what Rails can do. I know it's powerful, but I don't feel it yet.
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
INSERTprocedures 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 (
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 :)
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.
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.
- 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?"
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 :)
… 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
Chessclass 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
gitin different contexts, but I appreciate the simplicity of git's cognitive model, because basic use demands very little cognitive overhead.
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.
Instead of looping over input until it's valid, like I might have done in TI-86 BASIC, you embed your calls in a