a violinist learns to program
I had a great chat yesterday with the new Makers Academy remote cohort, discussing feeling inadequate, strategies for learning, how soon to send a CV to employers, and myriad other topics. This morning I found myself reflecting on how I used Makers not just to learn to code but to reset my life.
A bit of background: my previous job was as a professional violinist. I was doing a lot of international touring, working as a freelancer. This was stressful because of the constant travel (between November 2016 - January 2017 I was in ten countries on 3 continents), the uncertainty of a freelance income, and the inability to plan downtime.
The intense experience of Makers forced me to look at my life and understand where I received sustenance; to make sure I was getting enough sleep; to develop patterns that made me a good coder but also a joyful human being. So I decided to seize the opportunity to use my Makers experience to set healthier boundaries between my work and personal life.
Here are six things I did that helped transform my life:
1. Resist peer pressure to overwork
I remember vividly coming back from a five-minute pomodoro break and asking my pair how his break had been. He said, ‘Oh it wasn’t much of a break - I spent the time researching.’ I’d gone into the garden and smelled some flowers. Guess which of us was better prepared for work? As the course went on, my cohort challenged each other to take healthier breaks: play music, take photos of bees, read Stack Overflow’s programmer jokes page.
2. Ask yourself what's the best thing you can do for your learning
For me on the course, if it was during lunch or after 6pm, the answers included:
And one memorable morning my pair and I were too knackered to do the diagram workshop, so we did a hip-hop Bollywood dance workout instead.
The answer to this question will be unique for everyone but it’s really important to ask it and understand that the answer may very well not be ‘write more code’!
3. Don’t compare yourself
Rather than looking at what the other people in the course have done, ask yourself these two crucial questions:
A great way of being able to figure out the answer to those questions is to use the pomodoro technique and at the end of each pomo, write down what you did. You will be surprised and happy to realise how much you’ve learned, even as you’re struggling and frustrated.
4. Ask your coach or Dana if you’re worried about your progress
One of the most difficult things for me, especially at the beginning of the course, was not having much awareness about what I didn't know and how I was progressing. Was I learning enough, not enough, pushing myself too hard? It’s impossible to know this as a newbie coder, but as adult beginners we are keenly aware of a vast skills chasm.
So talk to your coach if you want to find out how you’re doing - but be warned, have specific ideas (i.e., I struggle with ‘attr_readers’ and ‘instantiating objects’). The act of having that conversation with yourself is in fact a really valuable part of learning, reducing the terror from ‘Oh my god, I don’t know anything’ to ‘Here are three specific things I don’t know and can I get some help learning them’.
If you’ve done that and you’re still full of anxiety, talk to Dana. She will help - and not by patting you on the head and saying you’re great but actually by helping you discover these thoughts that are tearing you down and realising that the reality is a lot kinder.
5. Be kind to yourself
I can’t say enough how brave you are for doing the Makers course. Taking three months off work is difficult! You will struggle. You will be frustrated. But that’s such a good thing - it means you are being stretched, that you’re growing. Lots of people talk about making big changes in their lives, but you’ve actually had the courage to go for it. Remember that, and be proud of yourself when the going gets rough.
6. Ask yourself what’s the bravest thing you can do in that moment
Maybe it’s meditating instead of smoking. Maybe it’s shutting off the computer and reaching out to a friend. Maybe it’s admitting your vulnerability. Maybe it’s asking the ‘dumb’ question that’s actually on everybody’s minds. Maybe it is writing more code! The answer will look different for everyone, and will change frequently. And if you're really comfortable with your pair, you can ask them this question too.
And if you feel like sharing, tweet me at @FiddlersCode with #BraveMakers and let’s all celebrate these moments!
Dear Future Makers,
It’s the final day of my Makers experience and I’m on the train down to London for the careers fair, so I thought I’d chuck in my two cents about what you can do to make your Makers experience fantastic. Good luck, and Slack me - I like meeting people!
10 Tips for Smashing your Makers Course
I was a little worried when I read in a description of Makers students that you will “eat, breathe, and sleep code”. I’d done an intense undergrad where I didn’t sleep for four years, but I’m 30 now and I like to go to bed at 11pm. So I figured out pretty quick that in order to keep my sanity, I’d have to put strict boundaries in place. For me, this meant:
Your own boundaries may look different but I encourage you to make sure you spend time away from coding - your brain will need a rest and you’re still human and need fun time!
Or yoga or Alexander technique or gym or whatever it is you do to relax. Mindfulness meditation is a great way of settling your brain, clearing out all the crap and worries and stress. I meditated with a pair partner on the course - at 8:50am every morning we’d meditate (she in Paris, I in Cambridge) and send each other a meditation emoji when we’d finished. Talk to Dana if you need help getting started.
3. Work smart, not hard
If you’re up until 2am working, you’re doing it wrong. Use the pomodoro technique (there’s a great Chrome extension) and don’t work for more than two pomos on a problem without asking for help. If you’re stuck, take a break, go for a walk, sleep on it…you’ll come back to it refreshed and the solution may magically pop into your mind. Also, don’t merge to master branches when you’re in a rush. This never ends well.
4. Diagram first
The physical act of writing 100 lines of code takes five minutes. Making those lines of code work really well takes a lot more preparation. Especially if you’re working on a team, make sure you are on board with building the same thing.
5. Let go of your ego
Full disclosure, this is the one I struggle with the most, so this advice is primarily directed toward me.
Listen more than you talk. Ask yourself what’s best for your pair or team, not what’s best for you. As one of my best friends and I say to each other, “Isn’t it annoying when other people don’t do exactly what you want, in the way and time that would suit you?” It is annoying and you’re not alone. Acknowledge that annoyance, take a step back, breathe, remember that it’s only code and at the end of the day, people > code.
And remember that Makers is the beginning, not the end of your coding journey. You’ll have plenty more chances to build all the features and use all the tech that you don’t get to on the course.
Running late to standup? Slack the team! Feeling ill and need to take a day off? Slack the team. Pipe burst in your kitchen and you almost get insanely flooded before figuring out how to turn off the water and your heart rate is way up and you haven’t had coffee? Slack the team. (This happened to me.)
People are not mind readers (thankfully!). If you are ill/tired/stressed, they will not know and you may come across as uncaring when in fact you just need time off. Have the courage to communicate that.
You’re going to be in an uncomfortable space of not knowing things. Especially if you’ve already been a working professional, you will be frustrated to be back at square one. I know I spent the first couple weeks on the course feeling like the village idiot, and thankfully our coach said that even if we were the absolute worst person on the course, we’d still get a job and do well. So be proud of yourself for having the courage to take this step, and walk into the vulnerability of being a beginner again. And if you need some company, read this blog from my first weekend on the course.
8. Do something tactile
Colouring in, jigsaw puzzles, gardening, Play-Doh, Legos, music…find something creative that doesn’t involve looking at any screens and involves your body.
Writing about your experience is a great way to reflect on your learning. And reflecting on your learning means analysing, learning from, and improving. If you’re not comfortable writing for the public, keep a private journal. It’s amazing to look back and see the things you struggled with a month ago are now second nature.
10. Have fun!
Remember that you are spending three months of your life LEARNING HOW TO CODE!!!! How totally awesome is that?? Remind yourself of this! And make sure to check out the Stack Overflow page of programmer jokes. And have Zoom drinks with your cohort (‘the cohort that drinks together thinks together’, I like to say).
Good luck on your Makers journey!
Our practice tech test for the past two days at Makers Academy was? Refactoring some hideous legacy code. See that method above? That SINGLE method that is over 40 lines long and bursting with nested if/else conditionals?
Yep, that one. So we had to refactor it AND THEN add an additional item type.
(Ever heard of a squint test? Screw up your eyes and just look at the layout - see all those arrows? A bad sign.)
So this is what I did:
1. Wrote some tests
There was one pre-existing test, which was pretty meaningless anyway. I had no idea what all this code was meant to do, nor did I have any intention of losing myself in a forest of nested conditionals. I read the specs and wrote tests to pass the specs. As luck would have it, the hideous nests actually did work, so eventually I had a full suite of tests and a good knowledge of what the program was designed to do.
2. Deleted everything in the update_quality method
Nuking is not always the best method for refactoring, but that code was just irritating me. Luckily I had tests to guide me so I wasn't too worried about writing the code.
3. Googled 'ways to refactor nested conditionals'
Came up with references to duck typing
4. Took a nap in the sunshine
Seriously. I was tired at this point and knew I had to have a clear grasp of the design before moving forward. So a nap sounded good.
5. Read POODR's chapter on duck typing
A lot. Also looked into inheritance but that seemed possibly messy.
A big issue at this particular moment was the instruction that I wasn't allowed to change the item class. Duck typing was a great solution, but it would require changing the item class, which would apparently upset a goblin.
6. Damn the goblin, I'm writing well-designed code
Once I made that decision, it was full steam ahead with TDD'd duck typing. I ran into some snafus about how I was storing and calling objects, but after a few hours had sorted those out and it was really simple. I ended up with several small classes and super-extensible code. I added the new feature on in about half an hour, complete with full testing.
At this point I felt I'd done enough original work to watch Sandi Metz's video on the Gilded Rose. In it, she mentioned that inheritance isn't always bad, as long as all of the subclasses share the behaviour of the superclass. So I thought, hey why not DRY this out a bit more and create a Product class which will contain the instantiation behaviour common to all the objects? Easy!
8. Satisfying the goblin
On my way back from the gym later that day, I had an epiphany: I could in fact satisfy the absurd goblin by making the original Item class the superclass and having all the other classes inherit their behaviour! It meant a bit of name-switching (my product and item classes switched names, along with all attendant methods), and the one downside is I couldn't work out how to throw the errors upon instantiation without changing the item class, so the goblin's code has slightly less functionality. Still, I'm pretty damn happy with this duck typed, inherited code.
You can check out the full code on my GitHub repo. It should be pretty self-explanatory!
Master branch (with errors for instantiating with disallowed max/min quality)
Item-class branch (item class totally unchanged from original repo)
Don't hesitate to get in touch if you have more ideas on duck typing, inheritance, or just want to chat code. I'm friendly and I like meeting people!
So you've read my blogs Why TDD and 5 Steps to Good TDD and you think, that's great, makes a lot of sense.
Then it comes time to write the code and you have a tight deadline and testing just goes by the wayside. Sound familiar?
So here are some good ways to motivate yourself and your team to actually practise TDD.
1. Have a test coverage race!
Simplecov will record your unit test coverage for Ruby and I'm sure other frameworks have similar coverage units. Figure out an appropriate prize (honor? a pint? ice cream?) and give it to the person or team with the highest test coverage. Or if you're on your own, you choose the prize!
2. Understand that TDD is a form of delayed gratification
You're balancing the immediate reward of having a feature to show off against the later and bigger reward of having a debuggable and extensible feature. It's in our nature to want immediate gratification but building the discipline to delay it means you'll end up with better features. Delayed gratification is a useful skill in many areas of life, so you definitely won't lose anything by strengthening that skill while programming.
3. Spend a week rigorously TDDing and find out if your code is actually better
We humans aren't always great at accurately judging how we spend our time. TDD may seem slow, but why not actually measure your progress with it? Some ideas of things to track: how many bugs are deployed, average time spend solving each bug, how easily you can make changes and catch bugs.
4. Read research on TDD efficiency
A quick Google search led me to quite a lot of papers on the efficiency of TDD. It's midnight, and I have only glanced at a few, but it's probably better to read those than spend a week tracking your own code (although sometimes the hands-on approach is best). In particular:
"This study finds that Test-Driven Development provides a substantial improvement in code quality in the categories of cohesion, coupling, and code complexity." -Rod Hilton
"We observed a significant increase in quality of the code (greater than two times) for projects developed using TDD compared to similar projects developed in the same organization in a non-TDD fashion." -T. Bhat
Is there hard evidence of the ROI of unit testing? A very interesting Stack Overflow thread.
5. Sing the Ballad of RSpec
Testing is definitely an epic adventure, so you need questing music to go along with it. I've written this ballad - apologies to those who test in other languages but I'm sure you'll still enjoy it. I'll record it at some point, and then you can really get into the testing groove.
Read my other posts:
5 Steps to Good TDD
In the first of three blog posts about TDD, I discussed why TDD is important.
In this post, I'll highlight five behaviours that will make your TDD much more effective.
1. Write the test first
Obvious? Yes. Easy? No. But it's really important to make sure your test can fail (is red) - if it can't fail, then there's no point in writing it, because it's vacuous (won't tell you anything). Don't you dare write a single line of code before having a failing test!
2. Solve one error at a time
It's tempting to jump ahead when you know what the next two steps should be. But get in the habit of being rigorously methodical about your test-solving. If you have a no-method error, define the method but don't let it do anything. Let the error messages guide you.
Again - obvious but difficult to do.
3. Run your tests before committing to GitHub
You never know what fun thing has broken and it's awfully embarrassing to push code up with failing tests.
4. Run your tests after pulling from GitHub
In case your colleague or you in a previous life has forgotten step 3.
5. Don't refactor until you have a green test.
This is a hard discipline, but it will save you hours. Trust me. I spent a couple hours in a red/refactor/red/red/red/red/red/red/red/red/red. Total waste of time. Never again.
Read my other blog posts in this series:
Committing to TDD
It's week 9 at Makers, and I've noticed a recurrent theme: the importance of TDD (test-driven-development) and why people (i.e. me) struggle to get round to doing it.
So I'm going to write three blogs on TDD addressing why TDD is important, how to do TDD, and possibly most importantly, how to motivate yourself (me) to do TDD better.
So here are some questions about why programmers should bother with TDD:
1. Why not just write the code correctly in the first place?
Definitely a good idea to write good code - but your code will inevitably change. Example: I wrote a rails app a few days ago and used the Devise gem for user authentication. I wanted to style the forms, so I changed some buttons to a link. I was proudly showing off my beautiful creation to a friend when the buttons stopped working (good tip: rails forms default to a POST request and you have to specify if you want GET - I hadn't done this, which is why my code broke). If I'd had a feature test, I would have known right away that my routes had broken when I changed the form.
2. Doesn't writing tests takes away time from adding features?
But it gives you the time back in debugging those features later. Even if you manually inspect your site (for example), you still have to reload the server (depending on which server you're using), possibly clear the cache, and run the tests yourself. Much easier to run RSpec (or whatever testing framework you use) and have it tell you the exact line of the error, and possibly even how to solve it.
3. Wouldn't you rather be writing features?
Doing good work means sometimes you have to do something that's less fun in pursuit of an overall goal. Violinists play scales, athletes do something athletic, programmers write tests. It's part of the less glamorous part of our job that means we are way better at our job. And we want to be kickass programmers, right?
4. But doesn't writing tests just make the whole process slower?
Not so much slower as break it down into smaller steps! The idea of sitting down at a machine, typing furiously for six hours, and emerging with your keyboard smoking and an amazing app fully developed is really sexy. But even if you manage to do that perfectly, your app will have to change - and possibly even be changed by someone else who may not have your brilliance and depth. Much better to code in tiny pieces, each new bit being tested so you can immediately pinpoint problems.
5. Is there anything else great about tests?
Yeah! They satisfy the XP value of communication: tests tell the next programmer maintaining your code what exactly it's meant to do. I'm struck by how often my coach asks to see my tests - it's a quick way to get an overview of what the code is meant to do. Also very importantly, tests demonstrate that you've accounted for edge cases - so think of them as an opportunity to show off how expansive your thinking is.
Ok, so that's it for post one. Check out the next one: 5 Steps to Good TDD
Ok, so what's a favicon? Possibly my new favourite little bit of code, favicons are the images that display in browser tabs.
You probably recognise most of those icons, right? They're a quick and easy visual way for a user to orient herself while using the browser.
So I present to you my guide to adding a favicon to a Rails app.
Find the image or logo you want to use as a favicon. Save it to your rails project's public folder.
Go to your favourite favicon generator online - I quite like Favicomatic. Upload your image and save it as favicomatic.zip (or whatever yours is called) to your public folder. (I already had a favicomatic.zip folder, which is why mine has the (2)).
Grab the HTML code from the website (there are two sizes to choose from) and paste it to your application.html.erb file, just under the title.
Open the favicon folder (here renamed from favicomatic(2) to favicon.zip) in the finder so you can unzip it. It'll appear as an unzipped folder in your project. Delete the zipped version. Note that the folder MUST be called favicon for Rails to find it.
Refresh your browser and admire your favicon!
PS Hawk-eyed readers will notice that I named this 'starfleet logo' in Step 1. Apparently I am unable to tell Star Trek and NASA apart.
This week was Rails week, and our remote cohort of 17 programmers from 5 countries working in 3 timezones spent a week making Acebook, a clone of - you guessed it - Facebook.
It was a great, if hard, week. My learning shot up exponentially. Also my ice cream consumption. Here is what I learned:
1. Red/refactor/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red is not a great cycle. Red, green, and ONLY THEN refactor. We spent a lot of time looking for bugs in our code when it turned out our partial was named incorrectly and Rails couldn't find it.
Polymorphic (alas, not paulamorphic, much as I love eponymous taxonomy) associations are really cool. I'm glad they're so cool, because here was the process in which my pair and I learned about them:
Build a PhotoComments functionality, almost wholly copying the already-existing Comments functionality. This was not remotely DRY, but we couldn't figure out how to get round the database issues. This took a whole day because of the aforementioned red/refactor/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red/red and we were super pumped to finally have it submitted for PR.
Our coach tells us that there has to be a dryer way and blocks our PR. His name is Dan, and he's a great coach because he made us go and find something way better. Was I still banging my head in frustration? Yes.
Help my landlord remove the old dishwasher that's being replaced and end up with a broken hose and water gushing out over the kitchen floor before I luckily had the presence of mind to switch off the water switch on the pipe. Not flooding the kitchen is possibly my proudest moment of the whole week, and I'm pretty proud of Rails. I did later get a bottle of prosecco as a reward for valiant behaviour, so all in all, a good week.
Have standup without coffee or breakfast (see Step 2.5) and decide to throw out everything we did yesterday.
Go to make coffee, forgetfully turn on the kitchen tap, and watch the water flow out everywhere. Put a tea cosy over the faucet so that doesn't happen again.
Google. It's a solved problem, so look for the most obvious answer:
This first searched proved extremely productive (newer searches first):
Use TDD to build a polymorphic database!
Be foiled in your attempts to merge your PR because of merge conflicts that can't be resolved in the ten minutes before retro.
Spend another hour that night working on all kinds of git conflicts.
Give up on resolving the merge and write a blog.
Still, polymorphism is really cool. And if you're still awake, you might be wondering what it is! Basically, it's a way of reusing code so that, for example, the code for comments could be used for both posts and photos. It defines the DB associations so that the comments are polymorphic, i.e. can exist with either a post_id or a photo_it. The Ruby on Rails Guide has a great section which we found really useful, and there are various other blogs with step-by-step instructions.
So I think that's it for Rails week. I'm building an Instagram clone this weekend, so I'd better get off the computer. I can't stand Instagram, so if you're very lucky, you might get a grumpy post from me about how I wish I could use Rails to build something more interesting this weekend. Or about how I tried to build something more interesting and ended up melting my laptop.
Read about the first half of Rails week: Buttoning Up Code: a valiant team uses TDD, pairing, and XP values to defeat a bug
This is the story of a bug.
This bug was annoying and caused the coders a great deal of heartache and misery.
The coders were tempted to give up on solving the bug.
But they persevered, and the bug was fixed.
This is also the story of Makers Academy, encapsulated in this one small story about a bug.
On Monday 29 May 2017, my pair partner and I submitted a pull request for the front end we had built and styled using Ruby on Rails 5. We were quite proud of our design, and rightly so. It was a clean, elegant user interface, modelled shamelessly on Facebook (our whole-team project was to build “Acebook”).
Our coach asked for some changes, one of which being to fix a test that had mysteriously begun to fail (first lesson learned: run your tests again before submitting a PR), the second to restyle a button class according to Rails syntax.
The first failing test was relatively easy to fix: a stylesheet had been required twice. Turns out you don’t need to explicitly require your stylesheet as it will be automatically required as long as it’s located correctly.
Which led to the second error: ‘unable to find button "New Post"’.
This error would drive us round the bend.
We could see quite clearly on the page that there was a button; we could inspect it with the chrome devtools and see its lovely button classiness.
And yet Capybara couldn’t find it.
I Zoomed one of my teammates, and when he couldn’t find the error either, I retired in defeat for the night. When we resumed the next morning, I showed the error to my full team of four and no one could figure it out.
So we called in the big guns: our coach.
We then spent a good half an hour exploring differences between Rails 4 and 5 syntaxes (‘form_to’ vs. ‘form_with’ anyone?), changed a lot of things around, and eventually reset the test and code to a point at which it was working. We couldn’t figure it out.
Eventually our coach said, “Sometimes you just have to say ‘that happened’.” That sure did happen. But there was one thing I couldn’t understand: why the test passed when it said ‘click_link” when the code was clearly a button, yet failed when the code said ‘click_button’.
Then our coach got the light in his eyes that said, “I now know the answer, and I am going to leave it to you guys to figure it out.”
Needless to say, I was annoyed.
I’d been plugging away at this error for a good three hours now, with several different teammates and lots of attempted solutions, and had gotten nowhere. I was at the frustrating stage where my code worked (I thought - I could clearly see the front end doing exactly what I wanted the test to do) but I didn’t how I had broken the test, or why it was working with the reset code.
At this point part of me still wanted to implement one of the two suboptimal solutions:
It was also lunchtime, which may have had something to do with my frustration.
I switched pairs to get fresh input and we plugged away at the problem and then all of the sudden it came to us in a flash - in fact, the bit of Rails magic was a link, not a button, which is why ‘click_link’ worked, even though this link had managed to get attached to a button class.
Great, so all we needed to do was to change ‘link_to’ to ‘button_to’ and be on our merry way. Simple.
Have you ever tried editing code from one unfamiliar syntax to another unfamiliar syntax while it’s lunchtime and your brain is fried from a morning of debugging?
We reconvened after lunch (in my case, a nap) and in twenty minutes had sorted out the syntax, the tests passed, and the browser looked fantastic.
The evil bug was defeated because:
The whole Makers Academy experience is summed up in this bug experience: pairing, TDD, XP values, and rigorous code review. I’ve never been so proud to be a MA student as I was today.
With thanks to teammates Jon, Miles and Sandy, to the rest of the remote April 2017 cohort, and to the MA staff.
Read about the second half of Rails week: Paulamorphism: tales from Rails
I did eventually learn to do cool things in JS, but what a sweet relief to be back in the land of Ruby, where there is a useful method for anything we could possibly want.
So I had a lovely romp in the park with my old, dear friend Ruby this weekend and now forward to making as many puns on the word rails ("keeping it rail", "the holy gRail") as I can possible manage.