Jekyll2020-06-21T20:31:37+02:00https://jsinibardy.com/feed.xmlJuliette SinibardyPending Programmer<br> ████░░░░░░ 40%Juliette SinibardyMy First Weeks as a Software Engineer2020-06-20T18:28:00+02:002020-06-21T18:28:00+02:00https://jsinibardy.com/becoming-software-engineer<p>After a year of solitary learning, I’ve finally started my first software engineering job. I’m
excited, exhausted and extremely grateful for the path that led me here.</p>
<p>I loved to read career switching stories so I thought I’d give a shot at writing my own.</p>
<!--more-->
<ul id="markdown-toc">
<li><a href="#introduction" id="markdown-toc-introduction">Introduction</a></li>
<li><a href="#job-searching" id="markdown-toc-job-searching">Job searching</a></li>
<li><a href="#interviews" id="markdown-toc-interviews">Interviews</a></li>
<li><a href="#my-company-and-position" id="markdown-toc-my-company-and-position">My company and position</a></li>
<li><a href="#bridging-the-gap-between-studying-and-working" id="markdown-toc-bridging-the-gap-between-studying-and-working">Bridging the gap between studying and working</a></li>
<li><a href="#useful-resources" id="markdown-toc-useful-resources">Useful resources</a></li>
<li><a href="#final-notes" id="markdown-toc-final-notes">Final Notes</a></li>
</ul>
<hr />
<h2 id="introduction">Introduction</h2>
<p>For those who don’t know me, I’m a 26 years old woman living with my partner and my cats in Paris,
France. I studied Economics and previously worked in a successful startup, where I ended up
becoming general manager - until I decided to quit and become a software engineer. That was
last August.</p>
<p>Since May 2019, I had joined an online school dedicated to mastery based learning - Launch School,
where I started my programming journey. It took me until the end of 2019 to finish the back-end
portion of the course, and I still haven’t finished the front-end portion (oopsie).</p>
<p>I found a job in March 2020 (more on that later) but only started at the beginning of June, because
I had planned on going to Southern Africa in May 2020 - but covid happened and my safari
became hundreds of hours playing Animal Crossing. Close enough.</p>
<h2 id="job-searching">Job searching</h2>
<p>Not gonna lie - I got extremely lucky on that part. I’m not sure how much of my job searching
experience here is applicable to other situations, but here we go.</p>
<p>I had registered on specialised platforms where software engineers describe their skills and
job / salary expectations, and are later contacted by companies interested in their profile.
Most French engineers use <a href="https://www.talent.io/en/">talent.io</a> or
<a href="https://www.hiresweet.com/">hiresweet</a> for that purpose.</p>
<p>I set up my profile without much expectations - given that I was a half-baked engineer - and
thought I’d go back and improve it later (spoiler: I never did).</p>
<p>A couple of weeks later, I was contacted by a recruiter from a company. I had
already received my fair share of annoying Linkedin recruiters telling me I was perfect for some
position that clearly proved they hadn’t read a thing of my resume - but this offer stood out.
We got in touch, and as I moved along the interview process, it became clear that I could
<em>actually</em> receive an offer from the company.</p>
<p>So I did the only rational thing possible: I dropped everything and job searched like a maniac.
I didn’t want to receive an offer and not be able to actually know whether I liked this company
more than others, or if the salary offer was any good. I had grown accustomed to hearing the
insane salaries that the <a href="https://launchschool.com/results">Launch School Capstone students</a> earn
in the US, so I needed to tune my own expectations to the realities of the French engineering
market.</p>
<p>I approached the job search exercise quite boldly. I had previously hired and interviewed dozens
of candidates, and I think this experience taught me quite a few things on how to craft a good
application. Therefore, I didn’t waste my time sending dozens of applications to positions I didn’t
even know. Instead, I researched the companies that I liked and tried to envision myself working
there. Once I could, I tried to get in touch with their recruiters on Linkedin (recruiters are
craving for connections with engineers so it usually is pretty easy), in order to directly send them
my carefully crafted application. I also contacted my network in order to know whether any
fitting position was opened. This led to interesting leads that never went through though.</p>
<p>In the end, I applied to 5 companies, and received 2 offers - a third was perhaps
on the way, but I got hired before finishing the process. The two offers promised different things,
but in the end I chose the company that contacted me in the first place.</p>
<h2 id="interviews">Interviews</h2>
<p>Most companies I applied to were engineering-centric and had pretty similar processes:</p>
<ol>
<li>a screening call (done by a recruiter) that mostly focuses on whether you’ve actually read the
job opening and know the basics of the company</li>
<li>an on-site interview with a lead developer (with or without some live-coding)</li>
<li>a take-home project that takes between 2 and 4 hours</li>
<li>an on-site live-coding interview with another lead developer</li>
<li>a team lunch / dinner / drink to meet other people of the team and assess the cultural fit</li>
</ol>
<p>Some companies switched steps 2 and 3, but the overall structure remained the same.</p>
<p>As for the coding exercises in particular, I was surprised on how much emphasis there was on
actually building a small working application during the take-home projects. Most were about
writing from scratch a small application with limited features, without forgetting a test suite.
I could usually choose the framework (and opted for Sinatra, of course!). I also made the mistake
of discovering how APIs and JSON conversion worked during one of them!</p>
<p>Live-coding exercises are always pretty stressful but I felt that probably was where I shined
the most. I guess that endless study sessions with Launch School students definitely prepared me
on managing my stress level and on being able to think while I speak (a surprisinly difficult feat).
It also didn’t hurt that I extensively prepared through Leetcode exercises and became familiar
with some algorithmic patterns.</p>
<p>Here are some examples of live-coding exercises I was given:</p>
<ul>
<li>writing a new feature to my take-home project (that seems to be pretty common)</li>
<li>solving the <a href="https://www.geeksforgeeks.org/understanding-the-coin-change-problem-with-dynamic-programming/">coin change problem</a></li>
<li>implementing from scratch the <code class="language-plaintext highlighter-rouge">reduce</code> function</li>
</ul>
<h2 id="my-company-and-position">My company and position</h2>
<p>I’m a proud full-stack software engineer at <a href="https://shipup.co">Shipup</a>, a SaaS company that
helps online retailers create a better post-purchase experience for their customers (eg. better
delivery tracking emails, integration with customer support in case there’s an issue with the
delivery, etc.)</p>
<p>Basically, the company is extremely API-oriented: it’s integrated with dozens of different carriers
and provides multiple ways for online retailers to send them order data. The technical stack is a
mix of Ruby on Rails and React.</p>
<p>I’m still pretty new to the React world so my work has been mostly focused on Rails so far - but
I’m trying to do some
<a href="https://medium.com/launch-school/just-in-time-learning-f6a10886ddfe">“just-in-time” learning</a> in
order to soon become proficient in React.</p>
<p>Shipup is a small French startup, with only 25 employees so far (including 6 engineers). They’re
pretty ambitious and I can see these numbers rapidly growing in the upcoming months - I feel like it’s an
exciting time to join a company!</p>
<h2 id="bridging-the-gap-between-studying-and-working">Bridging the gap between studying and working</h2>
<p>I started working 3 weeks ago, and since then, I’ve had to learn an insane amount of tools
and technologies. Here they are, with a personal assessment on how well I need to know them.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Importance?</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://rubyonrails.org/">Rails</a></td>
<td>Extremely</td>
<td>I was already pretty familiar with the framework</td>
</tr>
<tr>
<td><a href="https://rspec.info/">RSpec</a></td>
<td>Extremely</td>
<td>I use it every day</td>
</tr>
<tr>
<td><a href="https://github.com/bblimke/webmock">WebMock</a></td>
<td>Very important</td>
<td>Essential for API testing</td>
</tr>
<tr>
<td><a href="https://lostisland.github.io/faraday/">Faraday</a></td>
<td>Important</td>
<td>Very useful for opening a persistent connection with an API</td>
</tr>
<tr>
<td><a href="https://www.docker.com/">Docker</a></td>
<td>Limited</td>
<td>I only use some specific commands and so far, I haven’t had to master anything Docker-related</td>
</tr>
<tr>
<td><a href="https://kubernetes.io/">Kubernetes</a></td>
<td>Limited</td>
<td>Same as Docker</td>
</tr>
<tr>
<td><a href="https://reactjs.org/">React</a></td>
<td>Extremely</td>
<td>Unfortunately I’m still very new to the framework so I feel a lot of pressure on quickly becoming up to speed</td>
</tr>
<tr>
<td><a href="https://redux.js.org/">Redux</a></td>
<td>Very important</td>
<td>Same as React</td>
</tr>
<tr>
<td><a href="https://jestjs.io/">Jest</a></td>
<td>Very important</td>
<td>Fortunately, I already knew some basics</td>
</tr>
<tr>
<td><a href="https://storybook.js.org/">Storybook</a></td>
<td>Very important</td>
<td>I’m still unfamiliar with this technology</td>
</tr>
<tr>
<td><a href="https://www.gatsbyjs.org/">Gatsby</a></td>
<td>Important</td>
<td>Used for the corporate website</td>
</tr>
</tbody>
</table>
<p>On top of that, I also have to acclimatize to this gigantic codebase, to the various APIs I have
to work with, and to using a specific git workflow.</p>
<p>I guess it becomes easier with time, but the first few weeks have been packed with discoveries and
frustration at my own ignorance.</p>
<p>The hardest and central part of my job seems to be “making every tool work together”, surprisingly.
I usually do not tackle difficult puzzle or code challenge - most of my Ruby knowledge is more
than enough to solve the problems I’m faced with. However, identifying the problem(s) and
unveiling the various problematic layers take a lot of patience and pugnacity. Finding what to do
is where most of my job resides - actually coding it is the easy part.</p>
<p>So far, I’ve had to build 2 features, that demanded an in-depth understanding of the core business
and the existing codebase. Before writing a single line of code, I’ve had to dive deep in various
files in order to actually understand what the hell was going on there. It doesn’t help that my
first weeks were done remotely (covid, again) and that I’m not very good at asking for help when
I need it - I’m working on that though.</p>
<h2 id="useful-resources">Useful resources</h2>
<p>Launch School’s core curriculum provides strong programming foundations, and is not meant to be
exhaustive. Here are some resources that helped me build on these foundations:</p>
<ul>
<li>Preparing for interviews:
<ul>
<li><a href="https://pragprog.com/titles/jwdsal2/">A Common Sense Guide to Data Structures and Algorithms</a>
by Jay Wengrow</li>
<li><a href="http://www.crackingthecodinginterview.com/">Cracking the Coding Interview</a> by
<a href="http://www.gayle.com/">Gayle Laakmann McDowell</a></li>
</ul>
</li>
<li>Ruby on Rails:
<ul>
<li><a href="https://www.railstutorial.org/">Rails Tutorial</a> by
<a href="https://www.michaelhartl.com/">Michael Hartl</a></li>
<li><a href="https://launchschool.com/books/demystifying_rails">Demystifying Rails</a> by
<a href="https://launchschool.com">Launch School</a> (free)</li>
</ul>
</li>
<li>React:
<ul>
<li><a href="https://www.newline.co/fullstack-react/">Fullstack React</a> by <a href="https://www.newline.co/">Newline</a></li>
</ul>
</li>
<li>APIs:
<ul>
<li><a href="https://launchschool.com/books/working_with_apis/">Working with Web APIs</a> by
<a href="https://launchschool.com">Launch School</a> (free)</li>
</ul>
</li>
</ul>
<h2 id="final-notes">Final Notes</h2>
<p>I’ve been asked a couple of questions by other Launch School students - I’ll try to answer them
here.</p>
<p><strong>In my job search, which industry did I target?</strong></p>
<p>I didn’t target any specific industry. However, I did target one <em>type</em> of company: SaaS companies
(as in <a href="https://www.techradar.com/news/what-is-saas">Software as a Service</a>).</p>
<p>My goal was to join a company where the technical team was a <em>profit-center</em> rather than a
<em>cost-center</em>, ie. where the product shipped by the engineers was the main money-maker of
the company. I felt that SaaS startups fit that description pretty well.</p>
<p><strong>Any surprises during the job interviews?</strong></p>
<p>The highs and lows of job searching are exhausting. Between applications, screening calls,
interviews, take-home projects and preparing for the future interviews, job searching is a full
time job. In my experience, it’s not compatible with other things like still working for your
previous job, advancing through the curriculum or caring for anything else.</p>
<p>As for the interviews themselves, I was surprised by how awkward some companies were regarding
promoting diversity. I felt extremely uncomfortable when a recruiter candidly told me that they
would get an additional bonus for recruiting a female software engineer - ugh, okay.</p>
<p><strong>Is there anything I wished was covered by the LS curriculum?</strong></p>
<p>First, I’ll start by saying how grateful I am that the Networking course is that much in-depth.
I use this knowledge on an everyday basis.</p>
<p>As stated in the prevous section, I have used numerous resources to complement my Launch School
knowledge. Most of these resources are not based on ‘fundamental knowledge’ - I need them because
I use these technologies at my workplace, not because of their intrinsic value.</p>
<p>However, there are two topics that I think should be covered more in LS (or at least seem
pretty fundamental to me):</p>
<ul>
<li>Data Structure and Algorithms</li>
<li>Web APIs</li>
</ul>
<p>That being said, it’s pretty easy to pick up a book about these topics once you’ve worked
through the Core curriculum.</p>
<p><strong>How is using git ‘in real life’?</strong></p>
<p>Short answer: not that difficult and awesome!</p>
<p>Most companies have their own version of a git workflow. We use
<a href="https://www.endoflineblog.com/oneflow-a-git-branching-model-and-workflow">oneflow</a>, which is
a simplified version of
<a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">git flow</a>
(which seems to be pretty widespread).</p>
<p>Using git <em>in real life</em> is mostly, to me:</p>
<ul>
<li>Always working on a separate branch</li>
<li>Being extremely careful with how I name my commits</li>
<li>…and with <em>what</em> I commit (<code class="language-plaintext highlighter-rouge">git add --patch</code> is my new best friend)</li>
<li>Constantly rewriting my local git history (<code class="language-plaintext highlighter-rouge">git rebase -i origin/master</code>) so that my commits
are self-explanatory and grouped logically</li>
<li>Always making a Pull Request once I’m done with my feature (to allow my colleagues to review
my work)</li>
<li>Merging with incredible care into <code class="language-plaintext highlighter-rouge">master</code></li>
<li>And going through the CI/CD pipeline before deploying to production</li>
</ul>
<p><strong>What’s unique about France’s tech industry compared to the US?</strong></p>
<p>I’ve never worked in the US and can only guess.</p>
<p>I think the main difference is the type of companies you can work with here. You won’t find any
tech giant like in the Bay Area or New York. The biggest engineering companies probably have a
maximum of a 100 engineers. Therefore, your options are limited to:</p>
<ul>
<li>tech startups (my choice)</li>
<li>IT services companies (tech consultancy)</li>
<li>companies with a ‘cost-center’ IT department (and you’d rather avoid these)</li>
</ul>
<p>Paris is a great place for tech startups, and I guess that most major cities (Lyon, Lille,
Bordeaux…) have some bubbling startup activity but I wouldn’t expect it to be true elsewhere.
In short, there are only a handful of cities where some interesting engineering work can be found.</p>
<p>Also, English truly is the main language for software engineering - even in France. Most of my
meetings, all of the code and all the documentation is in English. That caught me a bit off-guard
in a country that fought so long against the invasion of the English language. (In all seriousness,
the <a href="http://www.academie-francaise.fr/dire-ne-pas-dire/neologismes-anglicismes">French academy</a> has
a list of English phrases that <em>should</em> be replaced by French sentences.)</p>
<p>Finally, I should mention that the tech industry salaries definitely are above average in France,
but are <em>not</em> exponentially inflated like they are in some US cities. Realistic figures are between
€35-40,000 (graduate) and €100,000 (experienced manager) - and
<a href="https://www.numbeo.com/cost-of-living/in/Paris">Paris</a> has a pretty high cost of life as well.</p>
<p>In short, while most software engineers have a better wage than most here, it’s not exactly
as insanely profitable as it is in the US.</p>
<hr />
<p>Alright! This has been a wildly long article, and I hope you found it useful.
Don’t hesitate to get in touch with me if you have some further questions, and I wish you all
the best on your programming journey!</p>Juliette SinibardyAfter a year of solitary learning, I’ve finally started my first software engineering job. I’m excited, exhausted and extremely grateful for the path that led me here. I loved to read career switching stories so I thought I’d give a shot at writing my own.Using Metaprogramming to Pass an Argument to a Rails Module2020-04-06T15:35:00+02:002020-04-07T10:25:00+02:00https://jsinibardy.com/using-metaprogramming-to-pass-an-argument-to-a-rails-module<p><strong>Refactoring</strong> is my favorite hobby. Nothing feels quite as satisfying than
extracting some common methods to an elegantly named module.</p>
<p>Quickly though, I usually run into trouble - how exactly am I supposed to pass an
argument to a module in Ruby? The answer is: through some <strong>metaprogramming</strong>!
(<em>such a scary word</em>)</p>
<!--more-->
<p>Let’s draft up a (somewhat contrived) example using Ruby on Rails.</p>
<p>Imagine a Facebook-like application with the following models and <code class="language-plaintext highlighter-rouge">Likeable</code>
module:</p>
<script src="https://gist.github.com/jsiny/0baf8980901e299d9534e0d2fae828eb.js"></script>
<p>Through the <code class="language-plaintext highlighter-rouge">Likeable</code> module, we can now retrieve the total number of likes for
any instance of the <code class="language-plaintext highlighter-rouge">Image</code> (or <code class="language-plaintext highlighter-rouge">Video</code>) class with the following pattern:
<code class="language-plaintext highlighter-rouge">Image.find(params[:id]).total_likes</code>.</p>
<p>That’s pretty neat.</p>
<p>Now, let’s assume that the two classes handle differently which users get
notified when a new like is submitted. As it’s related to likes, we’d like to
include this behaviour within the <code class="language-plaintext highlighter-rouge">Likeable</code> module.</p>
<p>However, Ruby does <em>not</em> provide an easy way to pass an argument to a method
defined within a module. We could of course add some conditional logic to the
module method, but that would become messy quickly as we create other
classes mixed in the <code class="language-plaintext highlighter-rouge">Likeable</code> module.</p>
<script src="https://gist.github.com/jsiny/699caa3540195819b844194b0f167412.js"></script>
<p>Let’s <em>not</em> do that.</p>
<p>Instead, we’d like to be able to directly define who should be notified for
each class within the model, like so:</p>
<script src="https://gist.github.com/jsiny/15bb9e42c214db82cdfee5a1800f2d1d.js"></script>
<p>Turns out, we can use some metaprogramming to mimic the passing of an argument:</p>
<script src="https://gist.github.com/jsiny/40b97c1ea25599c0c468b6cfcd322716.js"></script>
<p>Here’s what this code does:</p>
<ul>
<li>Lines 5-7: when the module <code class="language-plaintext highlighter-rouge">Likeable</code> is included within the class, the
(Rails) class attribute <code class="language-plaintext highlighter-rouge">users_to_be_notified</code> is created.</li>
<li>Lines 18-22: Within the <code class="language-plaintext highlighter-rouge">Likeable</code> module is defined the class method
<code class="language-plaintext highlighter-rouge">notifiable_users</code>. This method sets <code class="language-plaintext highlighter-rouge">users_to_be_notified</code> to the
parameters.</li>
<li>Line 34: <code class="language-plaintext highlighter-rouge">notifiable_users :creator, :tagged_users</code>: the <code class="language-plaintext highlighter-rouge">notifiable_users</code>
class method is called with two arguments (representing ActiveRecord attributes).
This sets the class attribute <code class="language-plaintext highlighter-rouge">users_to_be_notified</code> to <code class="language-plaintext highlighter-rouge">[:creator,
:tagged_users]</code> (for the <code class="language-plaintext highlighter-rouge">Video</code> class).</li>
<li>Line 14: we retrieve the values behind <code class="language-plaintext highlighter-rouge">:creator</code> and <code class="language-plaintext highlighter-rouge">:tagged_users</code> for
the specific instances of the class, and notify them individually.</li>
</ul>
<p>You can now create a new class and easily define who gets notified for new
likes:</p>
<script src="https://gist.github.com/jsiny/af94934e767fa0da4f721544278628d4.js"></script>
<p>There you go!</p>Juliette SinibardyRefactoring is my favorite hobby. Nothing feels quite as satisfying than extracting some common methods to an elegantly named module. Quickly though, I usually run into trouble - how exactly am I supposed to pass an argument to a module in Ruby? The answer is: through some metaprogramming! (such a scary word)Introducing Deep Sea Adventure’s Scoring App2019-11-13T09:42:00+01:002019-11-13T11:23:00+01:00https://jsinibardy.com/introducing-deep-sea-adventure-s-scoring-app<p>This <a href="https://deep-sea-adventure.herokuapp.com/">website</a> is a <strong>scoring tool</strong>
dedicated to the board game
<a href="https://oinkgms.com/en/deep-sea-adventure">Deep Sea Adventure</a> edited by
<a href="https://oinkgms.com/en/">Oink Games</a>.</p>
<p>Its goal is to provide players a <strong>reliable way to compute the oxygen decrease</strong>
during a round. It’s meant to be used side by side with the board game,
either on a mobile or computer.</p>
<p>After 6 months of learning, this project is my <strong>first</strong> big, entirely personal
project, and I’m very proud of it.</p>
<table>
<tbody>
<tr>
<td><a href="https://deep-sea-adventure.herokuapp.com/">Visit the website</a></td>
<td><a href="https://github.com/jsiny/deep_sea_adventure">See on Github</a></td>
</tr>
</tbody>
</table>
<!--more-->
<hr />
<ul id="markdown-toc">
<li><a href="#tech-stack" id="markdown-toc-tech-stack">Tech Stack</a></li>
<li><a href="#challenges" id="markdown-toc-challenges">Challenges</a></li>
<li><a href="#motivation" id="markdown-toc-motivation">Motivation</a></li>
<li><a href="#screenshots" id="markdown-toc-screenshots">Screenshots</a></li>
</ul>
<h2 id="tech-stack">Tech Stack</h2>
<p>This tool has been developed in <strong>Ruby</strong>, as I’ve spent the past months
learning programming through that language. I’ve applied an object-oriented
design as it felt natural to segment the various elements into objects with
an interface (<code class="language-plaintext highlighter-rouge">Players</code>, <code class="language-plaintext highlighter-rouge">Round</code>, etc.)</p>
<p>I’ve chosen to develop the website through the light-weight, Ruby
domain-specific language <strong>Sinatra</strong>. Even though I’ve previously worked with
Ruby on Rails, I preferred using a lighter library rather than a comprehensive
framework that may hide away the complexity of web applications.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Homepage</span>
<span class="n">get</span> <span class="s1">'/'</span> <span class="k">do</span>
<span class="n">erb</span> <span class="ss">:home</span>
<span class="k">end</span>
</code></pre></div></div>
<p>For instance, this Sinatra code snippet means that a <code class="language-plaintext highlighter-rouge">GET</code> request to the
homepage (<code class="language-plaintext highlighter-rouge">/</code>) will trigger the loading of the ERB (embedded Ruby) template
<code class="language-plaintext highlighter-rouge">home.erb</code>.</p>
<p>As the project grew in complexity, I’ve added a comprehensive test suite (with
<strong>Minitest</strong>), in order to be able to safely refactor and prevent regressions.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/minitest.jpg">
<img src="/assets/images/minitest.jpg" alt="Minitest" />
</a>
<figcaption>All green! 💚</figcaption>
</figure>
</div>
<p>Additionally, I taught myself to work with <strong>Bootstrap</strong> for this project.
Being a complete beginner in front-end development, with no knowledge of
JavaScript and only the very basics of CSS, this proved to be quite
challenging.</p>
<p>However, I’m happy I went through that struggle because Bootstrap helped me
build a smooth and user-friendly application (both on desktop <em>and</em> mobile).</p>
<p>I’ve deployed the application on <strong>Heroku</strong>, mostly because it’s a
free hosting service. (The app is hosted onto an EU server, so US-based
users might encounter some latency.)</p>
<p>Finally, I also took the opportunity to learn about <strong>Travis CI</strong> and set up
my first continuous integration and automatic deployment, through
<code class="language-plaintext highlighter-rouge">Github > Travis CI > Heroku</code>. As I was working alone on this project,
this configuration probably is a luxury, but it’s never too early to learn
the best practices.</p>
<h2 id="challenges">Challenges</h2>
<p>Through this project, I’ve faced two main challenges:</p>
<ul>
<li>I had to learn the basics of front-end and Bootstrap to go through it</li>
<li>I wanted to build an application <em>with no database and log-in system</em> so
instead, I extensively used session storage to persist user data</li>
</ul>
<p><strong>Why did I choose to steer clear of login and databases?</strong></p>
<p>Mainly because I think that most users find it tiresome to go through a
registration process for almost every Internet service. A “plug and play”
approach is much nicer instead.</p>
<p>Plus, in this situation, using session storage worked pretty well because:</p>
<ul>
<li>Most games last less than 1 hour so sessions expiring was not a concern</li>
<li>Even though several players could want to keep score, it feels acceptable
that they use only one player’s device.</li>
</ul>
<h2 id="motivation">Motivation</h2>
<p>I’ve chosen to build this app mostly because I like games but dislike
arguing over a messy count score.</p>
<p>In Deep Sea Adventure, players dive into the deep ocean looking for treasures.
All divers share the same oxygen tank, and each treasure picked up weighs down
the diver and increases its oxygen intake. All divers must be back into the
submarine before the oxygen tank becomes empty. As such, it is critical to
accurately monitor the available oxygen. (<a href="https://oinkgms.com/en/deep-sea-adventure">More on the game’s rules</a>)</p>
<p>However, experience shows that it can be difficult to accurately compute the
available oxygen in a quick game setup, and that arguments over which player
should have drowned tend to ruin the fun. This is where this Scoring App comes
handy!</p>
<h2 id="screenshots">Screenshots</h2>
<div style="text-align: center">
<figure>
<a href="/assets/images/player_turn.png">
<img src="/assets/images/player_turn.png" alt="Deep Sea Adventure - Player's turn" />
</a>
<figcaption>The app records the choices made by the player and displays the available oxygen supply</figcaption>
</figure>
</div>
<div style="text-align: center">
<figure>
<a href="/assets/images/score.png">
<img src="/assets/images/score.png" alt="Deep Sea Adventure - Score" />
</a>
<figcaption>At the end of the round, players who made it back to the submarine count their treasures</figcaption>
</figure>
</div>
<div style="text-align: center">
<figure>
<a href="/assets/images/end.png">
<img src="/assets/images/end.png" alt="Deep Sea Adventure - Score" />
</a>
<figcaption>After 3 rounds, the app computes the scoreboard</figcaption>
</figure>
</div>Juliette SinibardyThis website is a scoring tool dedicated to the board game Deep Sea Adventure edited by Oink Games. Its goal is to provide players a reliable way to compute the oxygen decrease during a round. It’s meant to be used side by side with the board game, either on a mobile or computer. After 6 months of learning, this project is my first big, entirely personal project, and I’m very proud of it. Visit the website See on GithubHow does the Internet work?2019-10-03T11:06:00+02:002019-10-03T19:50:00+02:00https://jsinibardy.com/how-does-the-internet-work<p>Being born in the 90s, I’ve lived most of my life in a post-Internet world. I
do remember the sweet sound of 56 kb/s modem, but most of my browsing time
has been <em>after</em> the dial-up era.</p>
<p>Internet, for my generation, is just an inherent part of life. It’s kind
of hard to imagine what it was like <em>before</em> (did people actually read books?),
and we never pause to think:</p>
<blockquote>
<p>Wait, how does the Internet even work?</p>
</blockquote>
<p>So <em>that</em>’s exactly the subject of this post. Buckle up your
seatbelt, we’re going deep into networking!</p>
<!--more-->
<div style="text-align: center">
<figure>
<a href="/assets/images/internet.jpg">
<img src="/assets/images/internet.jpg" alt="90s Internet book" />
</a>
<figcaption>Welcome to the Internet! I'll be your guide</figcaption>
</figure>
</div>
<p>We’ll examine two aspects of the Internet:</p>
<ul>
<li>how data is <em>transferred</em> over the network</li>
<li>how users can <em>access a webpage</em></li>
</ul>
<hr />
<p><strong>Table of Contents:</strong></p>
<ul id="markdown-toc">
<li><a href="#how-data-is-transferred-over-a-network" id="markdown-toc-how-data-is-transferred-over-a-network">How data is transferred over a network</a> <ul>
<li><a href="#url-parsing" id="markdown-toc-url-parsing">URL Parsing</a></li>
<li><a href="#dns-lookup" id="markdown-toc-dns-lookup">DNS Lookup</a></li>
<li><a href="#encapsulating-the-request" id="markdown-toc-encapsulating-the-request">Encapsulating the Request</a></li>
<li><a href="#travelling-on-the-network" id="markdown-toc-travelling-on-the-network">Travelling on the network</a></li>
<li><a href="#receiving-the-request" id="markdown-toc-receiving-the-request">Receiving the Request</a></li>
</ul>
</li>
<li><a href="#how-to-access-a-webpage" id="markdown-toc-how-to-access-a-webpage">How to access a webpage</a> <ul>
<li><a href="#the-tcp-handshake" id="markdown-toc-the-tcp-handshake">The TCP Handshake</a></li>
<li><a href="#the-tls-handshake" id="markdown-toc-the-tls-handshake">The TLS Handshake</a></li>
<li><a href="#the-http-request--response-cycle" id="markdown-toc-the-http-request--response-cycle">The HTTP Request / Response cycle</a></li>
</ul>
</li>
<li><a href="#internet---better-than-magic" id="markdown-toc-internet---better-than-magic">Internet - better than magic</a></li>
</ul>
<hr />
<h2 id="how-data-is-transferred-over-a-network">How data is transferred over a network</h2>
<p>What happens when you type a URL into your browser?</p>
<p>Let’s assume you want to reach Twitter, and typed <code class="language-plaintext highlighter-rouge">https://twitter.com/home</code>
into your browser.</p>
<h3 id="url-parsing">URL Parsing</h3>
<p>The first thing your browser does is <em>parse</em> the URL, in order to extract
its components:</p>
<ul>
<li>the <strong>scheme</strong> (<code class="language-plaintext highlighter-rouge">https</code>), which informs the browser that we want to use
the HyperText Transfor Protocol Secure to exchange data with the server;</li>
<li>the <strong>host</strong> (<code class="language-plaintext highlighter-rouge">twitter.com</code>), which is the computer that <em>hosts</em> the
resources of this website (eg. the HTML, the pictures, etc.);</li>
<li>the <strong>path</strong> (<code class="language-plaintext highlighter-rouge">/home</code>), which corresponds to the particular resource we
want to access.</li>
</ul>
<h3 id="dns-lookup">DNS Lookup</h3>
<p>The domain name (<code class="language-plaintext highlighter-rouge">twitter.com</code>) typed is nothing more than a human-friendly name
that refers to a server somewhere on the Internet.</p>
<p>In order for data to be transferred to this server, we need to know
its <strong>IP address</strong>. IP addresses (v4) are sets of 4 numbers (from 0 to 255)
separated by dots <code class="language-plaintext highlighter-rouge">.</code>, like <code class="language-plaintext highlighter-rouge">104.244.42.193</code>. This logicial address is <em>unique</em>
and allows to locate a device on the internet.</p>
<p>As IP addresses would be hard to remember for humans with limited memory
slots, we use domain names to cover up this complexity. But how do we convert
a domain name into an IP address?</p>
<p>That’s where <strong>DNS</strong> (Domain Name System) comes in! The DNS is a distributed
database which translates a domain name into an IP address.</p>
<p>When you typed <code class="language-plaintext highlighter-rouge">https://twitter.com/home</code> into your browser, it first checked
whether <code class="language-plaintext highlighter-rouge">twitter.com</code> was already available in its cache (from a previous
browsing session). If it wasn’t, the browser used its DNS provider in order
to find the IP address associated with the domain name (and cached the answer
for later use).</p>
<h3 id="encapsulating-the-request">Encapsulating the Request</h3>
<p>As we are in possession of <code class="language-plaintext highlighter-rouge">twitter.com</code>’s IP address, we are now ready to
send a request to the server!</p>
<p>The browser thus takes the server’s IP address and combines it with the
port number (optional field from the URL) to create a <strong>socket</strong>.</p>
<p>This request is then passed through several layers where the data is further
encapsulated.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/wrapped-cat.gif">
<img src="/assets/images/wrapped-cat.gif" alt="Cat wrapped in Chritsmas wrapping paper" />
</a>
<figcaption>Example of a cat being encapsulated, with a nice bow header</figcaption>
</figure>
</div>
<p>First, the request is passed to the <strong>Transport Layer</strong>, where a TCP
segment (or UDP datagram) is crafted. This segment now has a <em>header</em>, which
includes the following information:</p>
<ul>
<li>the destination port (which defaults to 80 for HTTP and 443 for HTTPS)</li>
<li>the source port (chosen from the kernel’s available range)</li>
</ul>
<p>These network ports is what allows two specific processes on two different
devices to communicate. A device likely has multiple processes running
at the same time (eg. a browser connected to multiple websites, a Spotify
application running in the background, your email client, etc.), with
each having a special dedicated network port.</p>
<p>Second, the segment is sent to the <strong>Network Layer</strong>, where it is wrapped
with additional headers containing:</p>
<ul>
<li>the destination IP address (obtained through the DNS mapping of the URL)</li>
<li>the source IP address (your device’s IP address)</li>
</ul>
<p>The segment is now an IP packet.</p>
<p>Third, the packet is sent to the <strong>Link Layer</strong>, where another header is added,
containing:</p>
<ul>
<li>the source MAC address (of the device’s NIC)</li>
<li>the destination MAC address (at this point being the exit gateway’s address,
ie. the local router’s)</li>
</ul>
<p>Fourth, the <strong>Physical Layer</strong>. The frame is converted to binary data and sent
through the physicial medium (eg. Ethernet cable, optic fiber, radio waves)
linking your device to the rest of the network.</p>
<p>At this point, the frame is now ready for the great travel throughout the
unknown network beyond your local router!</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/adventure.gif">
<img src="/assets/images/adventure.gif" alt="Adventure through the unknown" />
</a>
<figcaption>Good luck tiny packet!</figcaption>
</figure>
</div>
<h3 id="travelling-on-the-network">Travelling on the network</h3>
<p>The internet is a vast <em>network of networks</em>, which connects your home local
network to an infinite information sphere (the <em>Web</em>).</p>
<p>Once the packet leaves your local network through the subnet’s router, it
needs to find its way up to its destination IP (featured within its Network
Layer header).</p>
<p>On its way, the packet will encounter <strong>routers</strong>, which will extract its
destination IP and orient it to the next relevant network hop. The route
taken by the packet is not necessarily the <em>shortest</em>: among other things,
routers take into account the network congestion when deciding how to
route packets.</p>
<p>If the packet errs for too long on the network (ie. when its Time-to-Live
countdown equals 0), it will be dropped mercilessly.</p>
<p>Additionally, if a router is overflowed with packets, it will not hesitate
to shamelessly abandon the next packets.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/computer-destruction.gif">
<img src="/assets/images/computer-destruction.gif" alt="IT guy destroying a computer with a hammer" />
</a>
<figcaption>Accurate depiction of a router murdering an IP packet</figcaption>
</figure>
</div>
<p>Being a packet on the internet is tough.</p>
<p>All this also means that the internet is essentially an <em>unreliable</em> network.
Fortunately, we’ve invented protocols to abstract away from this
unreliability: this is the role of the Transport Control Protocol (see below).</p>
<p>Let’s assume here that our packet has a safe travel and reaches its destination
server (congrats tiny packet!)</p>
<h3 id="receiving-the-request">Receiving the Request</h3>
<p>When the packet gets to the destination host, it has to go through the same
encapsulation layers, but in reverse order, in order to strip off all the
header information that was attached by the sender for a safe navigation
on the internet seas.</p>
<ol>
<li>The Physical Layer receives a frame containing the packet, and sends it to
the Link Layer.</li>
<li>The Link Layer verifies that the frame is intact (through its checksum), and
removes the frame header, before sending it to the Internet Layer.</li>
<li>The Internet Layer assembles the fragmented packets into the original
datagram. It also removes the packet header before sending the datagram
over to the Transport Layer.</li>
<li>The Transport Layer (in our example, TCP) uses the destination port
(contained in the header) to know to which application to route
the request. It removes the Transport headers and sends the segment to the
Application Layer.</li>
<li>The Application Layer receives the segment and performs the requested
operation.</li>
</ol>
<div style="text-align: center">
<figure>
<a href="/assets/images/phew.gif">
<img src="/assets/images/phew.gif" alt="Jeff Goldblum sighing" />
</a>
<figcaption>Our tiny packet made it all the way!</figcaption>
</figure>
</div>
<p>Our original request has now arrived to the server. However, that doesn’t
explain <em>how</em> our browser communicates with a remote server. For all we know,
our request could have been immediately dropped by the server because
it didn’t speak <em>the same language</em>.</p>
<p>So - how does our browser communicate with a web server? To answer this
question, we will now explore HTTP, the Web Protocol.</p>
<hr />
<h2 id="how-to-access-a-webpage">How to access a webpage</h2>
<p>A web page is a document written in HTML, with references to various
resources (images, videos, etc.)</p>
<p>However, the browser and the server exchange quite a lot before displaying
a webpage onto your screen. There are several round-trips of exchanges
before a single HTTP request is sent to the server.</p>
<h3 id="the-tcp-handshake">The TCP Handshake</h3>
<p>One of these exchanges correspond to the TCP handshake, ie. the way our
browser establishes a <em>connection</em> to a remote server.</p>
<p>This handshake goes a little bit like this:</p>
<ul>
<li>Browser: “Hey server, I have something to ask you, do you mind?” [<code class="language-plaintext highlighter-rouge">SYN</code>]</li>
<li>Server: “Hey browser, I’m listening. What do you want?” [<code class="language-plaintext highlighter-rouge">SYN ACK</code>]</li>
<li>Browser: “Cool! I’ll tell you what I want” [<code class="language-plaintext highlighter-rouge">ACK</code>]</li>
</ul>
<div style="text-align: center">
<figure>
<a href="/assets/images/syn-ack.jpg">
<img src="/assets/images/syn-ack.jpg" alt="SYN ACK joke" />
</a>
<figcaption>I'll tell you what I want, what I really really want!</figcaption>
</figure>
</div>
<p>Once the browser has sent the last <code class="language-plaintext highlighter-rouge">ACK</code> segment, it can now start sending
data to the server.</p>
<p>Using the Transport Control Layer protocol ensures that the
exchange of data is now being done onto a reliable network.
One a connection is established, TCP takes care of:</p>
<ul>
<li>Checking that the data has not been altered during transit</li>
<li>Checking that the various segments are all here, and if not, supervises
the retransmission of lost packets</li>
<li>Logically ordering the packets</li>
<li>De-duplicating the packets</li>
</ul>
<p>TCP effectively allows us to abstract away from the unreliability of the
lower-layer protocols. However, this reliability comes at the price of
performance, as TCP requires an entire round-trip of latency before the
browser can send its request.</p>
<h3 id="the-tls-handshake">The TLS Handshake</h3>
<p>Furthermore, if the URL’s scheme is <code class="language-plaintext highlighter-rouge">https</code> (which it is, in our example), we
need another exchange before the HTTP requests can begin. This exchange
will ensure the <strong>encryption</strong> of all subsequent HTTP requests between
the client and the server, and <strong>authenticate</strong> the host.</p>
<p>Here’s a broad picture of how this handshake works:</p>
<ul>
<li>Browser: “Here’s the TLS version I support, and here are my favourite
cipher suites” [<code class="language-plaintext highlighter-rouge">ClientHello</code>]</li>
<li>Server: “Okay so let’s use this TLS version, this cipher, and by the way,
here are my public certificate and my public encryption key” [<code class="language-plaintext highlighter-rouge">ServerHello</code>]</li>
<li>Browser: <em>checks the validity of the certificate</em> “Ok you’re good!”</li>
<li>Browser: “Here’s how we’ll decide on a private symmetric key for encryption”</li>
<li>Server: “Copy 5/5! Will now start using this key for encryption”</li>
</ul>
<p>This TLS handshake uses asymmetric encryption to agree on:</p>
<ul>
<li>which version of TLS to use</li>
<li>the exchange of symmetric encryption key</li>
<li>the validity of the host’s certificate</li>
<li>the cipher suite used</li>
</ul>
<p>Once the TLS handshake is completed, all messages exchanged between the server
and the browser are now encrypted.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/matrix.gif">
<img src="/assets/images/matrix.gif" alt="Neo from the Matrix" />
</a>
<figcaption>There is no spoon</figcaption>
</figure>
</div>
<h3 id="the-http-request--response-cycle">The HTTP Request / Response cycle</h3>
<p>“Okay”, the browser asks timidly, “am I good to send my HTTP request now?” -
Yes, dear browser, you can!</p>
<p>The browser uses HTTP, a protocol designed for the communication between
a browser and a server, to ask the server for a particular web page.</p>
<p>The requests are sent in plaintext and would look like this:</p>
<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">GET</span> <span class="nn">/home</span> <span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span>
<span class="na">Host</span><span class="p">:</span> <span class="s">twitter.com</span>
<span class="s">[Other headers]</span>
</code></pre></div></div>
<p>The HTTP request (v1.1) features a request line, one mandatory header (<code class="language-plaintext highlighter-rouge">Host</code>)
and ends with an empty line.</p>
<p>Here are the components from the request line:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">GET</code> is the HTTP request method, which tells the server what we want
to do with the resource (in this case, to retrieve it)</li>
<li><code class="language-plaintext highlighter-rouge">/home</code> is the path of the resource we want to access</li>
<li><code class="language-plaintext highlighter-rouge">HTTP/1.1</code> is the version of the HTTP protocol we want to use</li>
</ul>
<p>The server receives the request, and responds, also in plain text:</p>
<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">200 OK
</span></code></pre></div></div>
<p>This status line (which indicates that the request was processed successfully)
can be accompanied with optional headers and body, like the raw HTML that
composes Twitter’s home page:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"fr"</span> <span class="na">data-scribe-reduced-action-queue=</span><span class="s">"true"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="c"><!-- Rest of the page --></span>
</code></pre></div></div>
<p>If the HTTP response contains references to other resources (like images,
fonts, or scripts), our browser automatically sends new HTTP requests to
collect them. If these resources are hosted on a different domain than
the current one, the whole TCP / TLS process starts again for these new
domains.</p>
<p>Now that our browser has everything it needs, it parses the HTML, CSS
and JavaScript files, and renders the web page. I’m still a newbie in
front-end so this part of the explanation will be for a future article 🥺</p>
<hr />
<h2 id="internet---better-than-magic">Internet - better than magic</h2>
<div style="text-align: center">
<figure>
<a href="/assets/images/internet-surfing.gif">
<img src="/assets/images/internet-surfing.gif" alt="Surfer between internet memes" />
</a>
<figcaption>Here we are, surfing on the web!</figcaption>
</figure>
</div>
<p>Turns out: internet is <em>actually</em> a tangible thing that can be explained!</p>
<p>But it’s still damn hard to do so.</p>Juliette SinibardyBeing born in the 90s, I’ve lived most of my life in a post-Internet world. I do remember the sweet sound of 56 kb/s modem, but most of my browsing time has been after the dial-up era. Internet, for my generation, is just an inherent part of life. It’s kind of hard to imagine what it was like before (did people actually read books?), and we never pause to think: Wait, how does the Internet even work? So that’s exactly the subject of this post. Buckle up your seatbelt, we’re going deep into networking!What’s up with the & (ampersand) in Ruby closures?2019-09-09T08:19:00+02:002019-09-09T17:14:00+02:00https://jsinibardy.com/ampersand-&-ruby-closures<p>Quite surprisingly, the following Ruby program is correct:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">first_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">second_method</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">second_method</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="n">third_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">third_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="n">first_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hello!"</span> <span class="p">}</span>
<span class="c1"># "hello!"</span>
</code></pre></div></div>
<p>You might therefore notice that the <code class="language-plaintext highlighter-rouge">&</code> (ampersand) pops up and disappears
pretty randomly in the above program. As it’s pretty hard to wrap one’s head
around all this <code class="language-plaintext highlighter-rouge">&</code> madness, let’s dive into this!</p>
<!--more-->
<ul id="markdown-toc">
<li><a href="#whats-a-closure" id="markdown-toc-whats-a-closure">What’s a closure?</a></li>
<li><a href="#blocks" id="markdown-toc-blocks">Blocks</a> <ul>
<li><a href="#implicit-block-calling" id="markdown-toc-implicit-block-calling">Implicit Block-Calling</a></li>
<li><a href="#explicit-block-calling" id="markdown-toc-explicit-block-calling">Explicit Block-Calling</a></li>
</ul>
</li>
<li><a href="#the--within-a-method-call" id="markdown-toc-the--within-a-method-call">The <code class="language-plaintext highlighter-rouge">&</code> within a method call</a></li>
<li><a href="#explaining-our-initial-example" id="markdown-toc-explaining-our-initial-example">Explaining our initial example</a></li>
<li><a href="#tldr---its-all-about-context" id="markdown-toc-tldr---its-all-about-context">TL;DR - It’s all about context!</a></li>
</ul>
<hr />
<h2 id="whats-a-closure">What’s a closure?</h2>
<p>In this post, we’ll talk about <strong>closures</strong> (and in particular, <em>blocks</em> and
<em>Proc objects</em>). And as I like nothing more than a proper introduction, let’s
first define a closure.</p>
<p>One of the “official-looking” (and pretty unhelpful) definition I have found
is the following:</p>
<blockquote>
<p>A closure is a first-class function that has lexical scope.</p>
</blockquote>
<p>… 😒 (sigh)</p>
<p>It might help to consider the following instead:</p>
<blockquote>
<p>A closure is a ‘bunch of code’ that can be defined and saved for later use.</p>
</blockquote>
<p>Additionally, a closure ‘remembers’ its surrounding context at the time it was
initialized, ie. it <em>binds</em> its environment (local variables, method
definitions, constants) to be sure to have everything it needs to run
successfully.</p>
<p>In Ruby, closures are: Proc objects, blocks and lambdas.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/closure.gif">
<img src="/assets/images/closure.gif" alt="Friends Serie Dialogue Closure" />
</a>
<figcaption>Not exactly *that* type of closure though</figcaption>
</figure>
</div>
<p>Here, we’ll only talk about blocks and Procs, and more specifically, how
to call them from methods.</p>
<h2 id="blocks">Blocks</h2>
<p>First, let’s talk about <em>blocks</em>.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">n</span><span class="o">|</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">2</span> <span class="p">}</span>
</code></pre></div></div>
<p>In the above program, <code class="language-plaintext highlighter-rouge">{ |n| n + 2 }</code> is the block. A block is an ‘unnamed’
function that can be called implicitly or explicitly.</p>
<h3 id="implicit-block-calling">Implicit Block-Calling</h3>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span>
<span class="nb">puts</span> <span class="s2">"hi from the method"</span>
<span class="k">end</span>
<span class="n">some_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi from the block!"</span> <span class="p">}</span>
<span class="c1"># "hi from the method"</span>
</code></pre></div></div>
<p>The above program only outputs the first string (<code class="language-plaintext highlighter-rouge">"hi from the method"</code>)
and somehow forgets about the second string (<code class="language-plaintext highlighter-rouge">"hi from the block!"</code>).</p>
<p>That’s because even though we implicitly passed the block to the method,
we didn’t execute the block within the method. To do that, we’d need to
<em>yield to the block</em> by using the keyword <code class="language-plaintext highlighter-rouge">yield</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span>
<span class="nb">puts</span> <span class="s2">"hi from the method"</span>
<span class="k">yield</span>
<span class="k">end</span>
<span class="n">some_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi from the block!"</span> <span class="p">}</span>
<span class="c1"># "hi from the method"</span>
<span class="c1"># "hi from the block!"</span>
</code></pre></div></div>
<p>As a matter of fact, <strong>all Ruby methods can implicitly take a block</strong>, without
needing to specify the block in its argument list or even having to execute
the block.</p>
<h3 id="explicit-block-calling">Explicit Block-Calling</h3>
<p>When we write a method definition, it can be relevant to explicitly
require a block. To do that, Ruby uses a <code class="language-plaintext highlighter-rouge">&</code> prepending the parameter’s name:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">yield</span>
<span class="k">end</span>
<span class="n">some_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi from the explicit block!"</span> <span class="p">}</span>
</code></pre></div></div>
<p>Here, <code class="language-plaintext highlighter-rouge">block</code> acts as a handle (a reference) for the block: within the method
definition, that block is no more an <em>unnamed</em> function.</p>
<p>The <code class="language-plaintext highlighter-rouge">&</code> prefixed to <code class="language-plaintext highlighter-rouge">block</code> signals that any block passed to <code class="language-plaintext highlighter-rouge">some_method</code>
upon method invocation will be converted to a <code class="language-plaintext highlighter-rouge">Proc</code> object.</p>
<p>As such, we can do a bit more than simply <em>yield</em> to it:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="n">some_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi from the explicit block!"</span> <span class="p">}</span>
</code></pre></div></div>
<p>As <code class="language-plaintext highlighter-rouge">block</code> now refers to a <code class="language-plaintext highlighter-rouge">Proc</code> object, we can invoke <code class="language-plaintext highlighter-rouge">call</code> on it. We can
also pass this object to another method like in our initial example:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">first_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">second_method</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="c1"># rest of the code omitted for brevity</span>
<span class="n">first_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hello!"</span> <span class="p">}</span>
</code></pre></div></div>
<p>Here, the block <code class="language-plaintext highlighter-rouge">{ puts "hello"! }</code> is converted to a <code class="language-plaintext highlighter-rouge">Proc</code> thanks to the <code class="language-plaintext highlighter-rouge">&</code>
prefixed in the method definition, and assigned to the local variable <code class="language-plaintext highlighter-rouge">block</code>.
Then, a second method is invoked and the <code class="language-plaintext highlighter-rouge">Proc</code> object is passed to it as
an argument.</p>
<p>Notice that we dropped the <code class="language-plaintext highlighter-rouge">&</code> in the <code class="language-plaintext highlighter-rouge">second_method</code> method invocation.</p>
<p>To sum up: in the context of a <strong>method definition</strong>, prepending the last
parameter with an <code class="language-plaintext highlighter-rouge">&</code> indicates that the method takes an explicit block and that
this block is converted to a <code class="language-plaintext highlighter-rouge">Proc</code> object (with a name) within the method body.</p>
<h2 id="the--within-a-method-call">The <code class="language-plaintext highlighter-rouge">&</code> within a method call</h2>
<p>As a <a href="/codewars-kata-launch-school-109-oral-assessment">Codewar addict</a>,
I’ve had my fair share of time spent on coming up with “one-liners”, aka
the shortest programs possible.</p>
<p>One of the tricks I use is the <code class="language-plaintext highlighter-rouge">&</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">].</span><span class="nf">each</span><span class="p">(</span><span class="o">&</span><span class="ss">:upcase!</span><span class="p">)</span>
<span class="c1"># ['A', 'B', 'C']</span>
</code></pre></div></div>
<p>Somehow, this code:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="o">&</span><span class="ss">:upcase!</span><span class="p">)</span>
</code></pre></div></div>
<p>…is converted to this code:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span> <span class="o">|</span><span class="n">char</span><span class="o">|</span> <span class="n">char</span><span class="p">.</span><span class="nf">upcase!</span> <span class="p">}</span>
</code></pre></div></div>
<p>Here’s the mechanism at play here (in the context of a <strong>method invocation</strong>):</p>
<ul>
<li>Ruby checks whether the object right after the <code class="language-plaintext highlighter-rouge">&</code> is a Proc:
<ul>
<li>If it is: great! Ruby uses the Proc object as it is</li>
<li>If it isn’t, Ruby calls a <code class="language-plaintext highlighter-rouge">to_proc</code> method on the object, if such a method
exists for that particular class. Fortunately, a <code class="language-plaintext highlighter-rouge">Symbol#to_proc</code> instance
method does exist. In our example, the <code class="language-plaintext highlighter-rouge">:upcase</code> symbol is therefore
converted to a <code class="language-plaintext highlighter-rouge">Proc</code> object.</li>
</ul>
</li>
<li>If the object is now a <code class="language-plaintext highlighter-rouge">Proc</code>, the <code class="language-plaintext highlighter-rouge">&</code> converts the <code class="language-plaintext highlighter-rouge">Proc</code> into a <code class="language-plaintext highlighter-rouge">block</code>.</li>
</ul>
<p>Let’s go back to our initial example (and recall that the <code class="language-plaintext highlighter-rouge">first_method</code>
converted the initial block to a <code class="language-plaintext highlighter-rouge">Proc</code> and passed that object to the
<code class="language-plaintext highlighter-rouge">second_method</code>):</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">second_method</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="n">third_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">second_method</code> receives a <code class="language-plaintext highlighter-rouge">Proc</code> object, assigned to the local variable
<code class="language-plaintext highlighter-rouge">block</code>. Within the method body, a <code class="language-plaintext highlighter-rouge">third_method</code> is called, with <code class="language-plaintext highlighter-rouge">&block</code>
passed to it as an argument.</p>
<p>As we’re here in the context of a <strong>method invocation</strong>, the <code class="language-plaintext highlighter-rouge">&</code> does the
following:</p>
<ol>
<li>Checks whether <code class="language-plaintext highlighter-rouge">block</code> is indeed a <code class="language-plaintext highlighter-rouge">Proc</code> (which it is)</li>
<li>Converts the <code class="language-plaintext highlighter-rouge">Proc</code> into a block</li>
</ol>
<h2 id="explaining-our-initial-example">Explaining our initial example</h2>
<p>We now have everything required to understand our initial example! Let’s
rewrite it with more self-explanatory names:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">block_to_proc_method</span><span class="p">(</span><span class="o">&</span><span class="n">block_to_proc</span><span class="p">)</span>
<span class="n">proc_to_block_method</span><span class="p">(</span><span class="n">block_to_proc</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">proc_to_block_method</span><span class="p">(</span><span class="n">proc_to_block</span><span class="p">)</span>
<span class="n">call_the_block_to_proc</span><span class="p">(</span><span class="o">&</span><span class="n">proc_to_block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">call_the_block_to_proc</span><span class="p">(</span><span class="o">&</span><span class="n">block_to_proc</span><span class="p">)</span>
<span class="n">block_to_proc</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="n">block_to_proc_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hello!"</span> <span class="p">}</span>
</code></pre></div></div>
<p>Let’s explain the program step-by-step, thanks to our new understanding
of the subtleties behind the <code class="language-plaintext highlighter-rouge">&</code>:</p>
<ul>
<li>At first, the <code class="language-plaintext highlighter-rouge">block_to_proc_method</code> is invoked, with a block
<code class="language-plaintext highlighter-rouge">{ puts "hello!" }</code> passed to it as an argument.</li>
<li>The block <code class="language-plaintext highlighter-rouge">{ puts "hello!" }</code> is converted to a <code class="language-plaintext highlighter-rouge">Proc</code> object thanks to the
<code class="language-plaintext highlighter-rouge">&</code> prefixed within <code class="language-plaintext highlighter-rouge">block_to_proc</code>’s method definition. This <code class="language-plaintext highlighter-rouge">Proc</code> is
assigned to the local variable <code class="language-plaintext highlighter-rouge">block_to_proc</code>.</li>
<li>Within the first method’s body, a second method is invoked
(<code class="language-plaintext highlighter-rouge">proc_to_block_method</code>), with the <code class="language-plaintext highlighter-rouge">Proc</code> passed to it as an argument.</li>
<li>The <code class="language-plaintext highlighter-rouge">proc_to_block_method</code> initializes the local variable <code class="language-plaintext highlighter-rouge">proc_to_block</code>
and assigns the <code class="language-plaintext highlighter-rouge">Proc</code> object to it.</li>
<li>Within the second method’s body, a third method is invoked
(<code class="language-plaintext highlighter-rouge">call_the_block_to_proc</code>), with <code class="language-plaintext highlighter-rouge">&proc_to_block</code> passed to it as an argument.
In the context of a method invocation, that <code class="language-plaintext highlighter-rouge">&</code> first checks whether
<code class="language-plaintext highlighter-rouge">proc_to_block</code> is a <code class="language-plaintext highlighter-rouge">Proc</code> (it is) and then converts it to a block.</li>
<li>The block received by <code class="language-plaintext highlighter-rouge">call_the_block_to_proc</code> is converted to a <code class="language-plaintext highlighter-rouge">Proc</code>
object because of the <code class="language-plaintext highlighter-rouge">&</code> prefixed to the parameter within the method
definition. Therefore, <code class="language-plaintext highlighter-rouge">block_to_proc</code> refers to a <code class="language-plaintext highlighter-rouge">Proc</code> object within the
third method’s body.</li>
<li>The <code class="language-plaintext highlighter-rouge">Proc</code> is then called, which outputs <code class="language-plaintext highlighter-rouge">"hello!"</code></li>
</ul>
<div style="text-align: center">
<figure>
<a href="/assets/images/spongebob.gif">
<img src="/assets/images/spongebob.gif" alt="Spongebob Squarepants goes Phew" />
</a>
<figcaption>Phew! We made it</figcaption>
</figure>
</div>
<h2 id="tldr---its-all-about-context">TL;DR - It’s all about context!</h2>
<p>To sum up, an <code class="language-plaintext highlighter-rouge">&</code> prefixing an object can do two opposite actions, depending
on the <em>context</em>:</p>
<ul>
<li>Within a <strong>method definition</strong>, the <code class="language-plaintext highlighter-rouge">&</code> converts a block (passed as an
argument) to a <code class="language-plaintext highlighter-rouge">Proc</code></li>
</ul>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span> <span class="c1"># & within a method definition</span>
<span class="n">block</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="n">some_method</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi from the explicit block!"</span> <span class="p">}</span>
</code></pre></div></div>
<ul>
<li>Within a <strong>method invocation</strong>, the <code class="language-plaintext highlighter-rouge">&</code> first converts the object to a <code class="language-plaintext highlighter-rouge">Proc</code>,
and then converts the <code class="language-plaintext highlighter-rouge">Proc</code> to a block</li>
</ul>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="ss">:odd?</span><span class="p">)</span> <span class="c1"># & within a method invocation</span>
</code></pre></div></div>Juliette SinibardyQuite surprisingly, the following Ruby program is correct: def first_method(&block) second_method(block) end def second_method(block) third_method(&block) end def third_method(&block) block.call end first_method { puts "hello!" } # "hello!" You might therefore notice that the & (ampersand) pops up and disappears pretty randomly in the above program. As it’s pretty hard to wrap one’s head around all this & madness, let’s dive into this!How I Prepared for Launch School’s 109 Oral Assessment2019-08-12T12:25:00+02:002019-08-12T16:53:00+02:00https://jsinibardy.com/preparing-launch-school-109-oral-assessment<p>A couple of weeks ago, I took Launch School’s first oral exam (RB 109).
Since I’m now somewhat stuck on the next lesson, I thought it’d be best to
reflect on the road taken thus far.</p>
<p>You’ll find here my time logs and general advice regarding this Launch
School exam.</p>
<!--more-->
<p>I’ll include the same disclaimer as in
<a href="preparing-launch-school-109-written-assessment">my previous related article</a>:
the timelogs included are entirely personal, and should not impact your
own study flow.</p>
<h2 id="getting-through-launch-schools-101-course">Getting through Launch School’s 101 course</h2>
<p>First, let’s answer the big question, the one that tormented my days in
the Preparatory course: <em>How long does it take to get through course 101?</em></p>
<p>Of course the answer is: it varies. On your time commitment, on your
previous coding experience, on how easily you can grasp the difficult concepts,
on how much repetition your memory needs, etc.</p>
<p>Therefore, the answer provided here is nothing but the time it took
<em>me</em> to pass this course.</p>
<h3 id="overall">Overall</h3>
<p>Overall, it took me <strong>156 hours</strong> of active learning to pass Launch
School’s first course. I studied for approximately 2 months and a half (72
days), with an average of more than 2 hours per day. The daily effort
varied greatly, from 30 min to more than 5h per day - as I had other
commitments, like my day job 😒</p>
<p>However, I tried to study every single day (even during my week-long holiday).
I wanted programming to become one of my natural routines, and I felt that
daily practice probably helped my memorization.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/github-commit-history.png">
<img src="/assets/images/github-commit-history.png" alt="My Github commit history" />
</a>
<figcaption>Proof: my Github commit history 💚</figcaption>
</figure>
</div>
<h3 id="time-breakdown">Time breakdown</h3>
<p>I’ll detail here the time spent on various topics, for the entire 101-109
course. I’ve done a similar table for the
<a href="preparing-launch-school-109-written-assessment">written assessment</a>, and
felt it’d be weird to only detail the time I spent afterwards preparing the
<em>oral</em> exam. Indeed, the time spent for the written exam
greatly prepared me for the oral exam as well, therefore splitting the
two didn’t really make sense to me.</p>
<p>Without further ado, here’s my time breakdown per topic:</p>
<table>
<thead>
<tr>
<th>Topic</th>
<th style="text-align: right">Duration</th>
<th style="text-align: right">Percentage</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lessons</td>
<td style="text-align: right">33.5 hours</td>
<td style="text-align: right">21 %</td>
</tr>
<tr>
<td>Video Lessons</td>
<td style="text-align: right">6.5 hours</td>
<td style="text-align: right">4 %</td>
</tr>
<tr>
<td>Walk-through / Assignments</td>
<td style="text-align: right">12 hours</td>
<td style="text-align: right">8 %</td>
</tr>
<tr>
<td>Ruby Small Problems</td>
<td style="text-align: right">59.5 hours</td>
<td style="text-align: right">38 %</td>
</tr>
<tr>
<td>Practice Problems</td>
<td style="text-align: right">10 hours</td>
<td style="text-align: right">6 %</td>
</tr>
<tr>
<td>Code Wars</td>
<td style="text-align: right">12 hours</td>
<td style="text-align: right">8 %</td>
</tr>
<tr>
<td>Live-coding</td>
<td style="text-align: right">15 hours</td>
<td style="text-align: right">10 %</td>
</tr>
<tr>
<td>Exams (incl. quizzes)</td>
<td style="text-align: right">7.5 hours</td>
<td style="text-align: right">5 %</td>
</tr>
</tbody>
</table>
<p>And per lesson:</p>
<table>
<thead>
<tr>
<th>Chapter</th>
<th style="text-align: right">Duration</th>
<th style="text-align: right">Percentage</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lesson 1</td>
<td style="text-align: right">7 hours</td>
<td style="text-align: right">5 %</td>
</tr>
<tr>
<td>Lesson 2</td>
<td style="text-align: right">21 hours</td>
<td style="text-align: right">14 %</td>
</tr>
<tr>
<td>Lesson 3</td>
<td style="text-align: right">14.5 hours</td>
<td style="text-align: right">9 %</td>
</tr>
<tr>
<td>Lesson 4</td>
<td style="text-align: right">20 hours</td>
<td style="text-align: right">13 %</td>
</tr>
<tr>
<td>Lesson 5</td>
<td style="text-align: right">14.5 hours</td>
<td style="text-align: right">9 %</td>
</tr>
<tr>
<td>Lesson 6</td>
<td style="text-align: right">10 hours</td>
<td style="text-align: right">6 %</td>
</tr>
<tr>
<td>Assessment Preparation</td>
<td style="text-align: right">68.5 hours</td>
<td style="text-align: right">44 %</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="key-take-aways">Key Take-Aways</h2>
<p>What to make of these tables?</p>
<h3 id="1--almost-50-of-my-time-was-spent-working-after-the-end-of-lesson-6">1. ⌛ Almost 50% of my time was spent working <em>after</em> the end of Lesson 6</h3>
<p>When I prepared this article, this is the first thing that struck me:
44% of my time on 101 was spent in the Assessment preparation part, where my
“only job” was to make sure I had indeed fully understood the material.</p>
<p>Within this period, I’ve spent my 68 hours doing the following:</p>
<table>
<thead>
<tr>
<th>Topic</th>
<th style="text-align: right">Duration</th>
<th style="text-align: right">Percentage</th>
</tr>
</thead>
<tbody>
<tr>
<td>Reviewing lessons</td>
<td style="text-align: right">16 hours</td>
<td style="text-align: right">23 %</td>
</tr>
<tr>
<td>Ruby Small Problems</td>
<td style="text-align: right">22 hours</td>
<td style="text-align: right">32 %</td>
</tr>
<tr>
<td>Live-coding</td>
<td style="text-align: right">15 hours</td>
<td style="text-align: right">22 %</td>
</tr>
<tr>
<td>Code Wars</td>
<td style="text-align: right">12 hours</td>
<td style="text-align: right">18 %</td>
</tr>
<tr>
<td>Exams</td>
<td style="text-align: right">3.5 hours</td>
<td style="text-align: right">5 %</td>
</tr>
</tbody>
</table>
<p>Going through the lessons was not enough for me: I needed to practice for
dozens of hours afterwards before feeling ready to tackle the exams.</p>
<p>You may have noticed that I spent a significant time live-coding, either
during TA sessions or with another fellow Launch School student
(<a href="https://www.orgamizer.com/">hello Dimitri</a>!)</p>
<p>This was by far the most important part of my preparation, and I think what
was decisive for my good exam grades. I cannot recommend this enough: if
you’re currently preparing for the 109 exam, please register to a TA study
session, and practice on 1-to-1 with another student!</p>
<p>Solving a code problem and explaining out loud your thought process are
two difficult and <em>different</em> skills. My first live coding attempts were
disastrous: I misread the instructions, kept getting errors on my method
implementations, and was half-panicked.</p>
<p>But fortunately, with a bit of practice, solving problems in front of a peer
becomes <em>much</em> easier.</p>
<h3 id="2--practice-practice-practice">2. 👩💻 Practice, practice, practice</h3>
<p>If you do the math, I’ve actually spent 60% of my overall time practicing
code. The Ruby Small Problems, the Practice Problems, the
<a href="codewars-kata-launch-school-109-oral-assessment">Code Wars katas</a>
and the Assignments amounted to more than 90 hours.</p>
<p>The reason behind this is simple: as with any skill, you need to build your
<a href="https://medium.com/@talentaccurate/how-to-create-muscle-memory-in-programming-ff881fae52d0">muscle memory</a>.
And the secret ingredients are: 1) practice, and 2) practice.</p>
<hr />
<h2 id="how-my-interview-went">How my interview went</h2>
<p>My interview was with <a href="https://medium.com/@srdjancoric">Srdjan</a> and lasted
for about 20 minutes; I received two exercises.</p>
<p>During the first one, as usual, I misread the instructions, and only realised my
mistake once my code was written and half of my test cases refused to pass.
Oops. 🤦♀️</p>
<p>At that point, I was fairly sure that I’d blown my interview. What (probably)
‘saved’ me was: going back to the algorithm part of
<a href="https://medium.com/launch-school/solving-coding-problems-with-pedac-29141331f93f">the PEDAC process</a>
and solving the <em>actual</em> exercise there before
attempting another line of code. And this time, it worked!</p>
<p>The second exercise went quite smoothly.</p>
<p>During the interview, Srdjan was pretty silent, which can be intimidating.
I received my grades less than 2 hours afterwards, and I had <em>actually</em>
passed the exam 🎉</p>
<hr />
<p>If you’re currently preparing the 109 Launch School exams, good luck! 🤞
You might want to check out those two other posts:</p>
<ul>
<li><a href="preparing-launch-school-109-written-assessment">How I Prepared for Launch School’s 109 written assessment</a></li>
<li><a href="codewars-kata-launch-school-109-oral-assessment">My Favorite Katas to Prepare for Launch School’s 109 oral assessment</a></li>
</ul>Juliette SinibardyA couple of weeks ago, I took Launch School’s first oral exam (RB 109). Since I’m now somewhat stuck on the next lesson, I thought it’d be best to reflect on the road taken thus far. You’ll find here my time logs and general advice regarding this Launch School exam.Making Sense of Equality in Ruby2019-08-05T11:23:00+02:002019-08-05T18:01:00+02:00https://jsinibardy.com/ruby-equality<p>When I discovered programming, I was bamboozled by the incredible amout of
times you type the <code class="language-plaintext highlighter-rouge">=</code> key. Among other things, I couldn’t help but
wonder: Why on earth was I supposed to use <code class="language-plaintext highlighter-rouge">==</code> instead of the
more ‘natural’ <code class="language-plaintext highlighter-rouge">=</code> to express equality?</p>
<p>Turns out, it’s actually possible to make sense of this <code class="language-plaintext highlighter-rouge">=</code> madness!
Here’s a cheat sheet to gain a better understanding of equality and the
equal sign <code class="language-plaintext highlighter-rouge">=</code> in Ruby.</p>
<!--more-->
<ul id="markdown-toc">
<li><a href="#the--madness" id="markdown-toc-the--madness">The <code class="language-plaintext highlighter-rouge">=</code> Madness</a></li>
<li><a href="#what-about-" id="markdown-toc-what-about-">What about <code class="language-plaintext highlighter-rouge">=</code>?</a> <ul>
<li><a href="#general-case-the-assignment-operator" id="markdown-toc-general-case-the-assignment-operator">General Case: the Assignment Operator</a></li>
<li><a href="#-and-the-combined-assignment-operators" id="markdown-toc--and-the-combined-assignment-operators"><code class="language-plaintext highlighter-rouge">+=</code> and the combined assignment operators</a></li>
<li><a href="#element-assignment-" id="markdown-toc-element-assignment-">Element Assignment <code class="language-plaintext highlighter-rouge">#[]=</code></a></li>
<li><a href="#setter-methods-method" id="markdown-toc-setter-methods-method">Setter Methods <code class="language-plaintext highlighter-rouge">#method=</code></a></li>
</ul>
</li>
<li><a href="#the--method-and-value-equality" id="markdown-toc-the--method-and-value-equality">The <code class="language-plaintext highlighter-rouge">==</code> method and Value Equality</a> <ul>
<li><a href="#examples-of--usage" id="markdown-toc-examples-of--usage">Examples of <code class="language-plaintext highlighter-rouge">==</code> usage</a></li>
<li><a href="#the--method" id="markdown-toc-the--method">The <code class="language-plaintext highlighter-rouge">==</code> method</a></li>
<li><a href="#implications-for-object-oriented-programming" id="markdown-toc-implications-for-object-oriented-programming">Implications for Object Oriented Programming</a></li>
</ul>
</li>
<li><a href="#the-equal-method" id="markdown-toc-the-equal-method">The <code class="language-plaintext highlighter-rouge">equal?</code> method</a></li>
<li><a href="#what-about--1" id="markdown-toc-what-about--1">What about <code class="language-plaintext highlighter-rouge">===</code>?</a></li>
<li><a href="#the-eql-method" id="markdown-toc-the-eql-method">The <code class="language-plaintext highlighter-rouge">eql?</code> method</a> <ul>
<li><a href="#ruby-documentation" id="markdown-toc-ruby-documentation">Ruby Documentation</a></li>
<li><a href="#when-should-you-use-the-eql-method" id="markdown-toc-when-should-you-use-the-eql-method">When should you use the <code class="language-plaintext highlighter-rouge">eql?</code> method?</a></li>
<li><a href="#implications-for-object-oriented-programming-1" id="markdown-toc-implications-for-object-oriented-programming-1">Implications for Object Oriented Programming</a></li>
</ul>
</li>
<li><a href="#key-take-aways" id="markdown-toc-key-take-aways">Key Take-Aways</a></li>
</ul>
<hr />
<h2 id="the--madness">The <code class="language-plaintext highlighter-rouge">=</code> Madness</h2>
<p>Here’s a short program:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">some_method</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="mi">5</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">elsif</span> <span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span> <span class="o">===</span> <span class="n">a</span>
<span class="n">a</span> <span class="o">+=</span> <span class="mi">10</span>
<span class="k">else</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="mi">4</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="n">some_method</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># => 3</span>
<span class="nb">p</span> <span class="n">some_method</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => 12</span>
<span class="nb">p</span> <span class="n">some_method</span><span class="p">(</span><span class="mi">15</span><span class="p">)</span> <span class="c1"># => 4</span>
</code></pre></div></div>
<p>In the above code, we have no less than <em>5 different forms</em> of <code class="language-plaintext highlighter-rouge">=</code>:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">=</code> in <code class="language-plaintext highlighter-rouge">a = 3</code></li>
<li><code class="language-plaintext highlighter-rouge">+=</code> in <code class="language-plaintext highlighter-rouge">a += 10</code></li>
<li><code class="language-plaintext highlighter-rouge">[]=</code> in <code class="language-plaintext highlighter-rouge">[1, 2, 3][2] = 4</code></li>
<li><code class="language-plaintext highlighter-rouge">==</code> in <code class="language-plaintext highlighter-rouge">if a == 5</code></li>
<li><code class="language-plaintext highlighter-rouge">===</code> in <code class="language-plaintext highlighter-rouge">elsif (1..10) === a</code></li>
</ul>
<p>Granted, the last situation is actually quite uncommon, but this
profusion of <code class="language-plaintext highlighter-rouge">=</code> signs is still confusing. Let’s dive in!</p>
<h2 id="what-about-">What about <code class="language-plaintext highlighter-rouge">=</code>?</h2>
<h3 id="general-case-the-assignment-operator">General Case: the Assignment Operator</h3>
<p>In most cases, the <code class="language-plaintext highlighter-rouge">=</code> character refers to the <strong>assignment operator</strong>,
ie. the operator used to assign a new value to a variable.</p>
<p>Therefore, <code class="language-plaintext highlighter-rouge">a = 3</code> is Ruby’s way of informing the program that from
now on, the <code class="language-plaintext highlighter-rouge">a</code> variable will now reference the <code class="language-plaintext highlighter-rouge">Integer</code> <code class="language-plaintext highlighter-rouge">3</code>.</p>
<h3 id="-and-the-combined-assignment-operators"><code class="language-plaintext highlighter-rouge">+=</code> and the combined assignment operators</h3>
<p>Ruby comes with 6 extremely handy “combined assignment operators”,
that both operate on a variable <em>and</em> assign the result back to the
variable.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">a</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">a</span> <span class="o">+=</span> <span class="mi">10</span> <span class="c1"># => 12</span>
<span class="n">a</span> <span class="c1"># => 12</span>
</code></pre></div></div>
<p>They are: <code class="language-plaintext highlighter-rouge">+=</code>, <code class="language-plaintext highlighter-rouge">-=</code>, <code class="language-plaintext highlighter-rouge">*=</code>, <code class="language-plaintext highlighter-rouge">/=</code>, <code class="language-plaintext highlighter-rouge">%=</code> (modulus), <code class="language-plaintext highlighter-rouge">**=</code> (exponent).</p>
<p>As with regular assignment, these operators have nothing to do with
testing for equality.</p>
<h3 id="element-assignment-">Element Assignment <code class="language-plaintext highlighter-rouge">#[]=</code></h3>
<p>Another common Ruby construct is <strong>element assignment</strong>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str</span> <span class="o">=</span> <span class="s2">"hello"</span> <span class="c1"># => "hello"</span>
<span class="n">str</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Y"</span> <span class="c1"># => "Y"</span>
<span class="n">str</span> <span class="c1"># => "Yello"</span>
</code></pre></div></div>
<p>Element assignment is actually a method (<code class="language-plaintext highlighter-rouge">#[]=</code>), available to Strings,
Arrays and Hashes. It replaces the element referenced
by its index. Again, it doesn’t check for equality.</p>
<h3 id="setter-methods-method">Setter Methods <code class="language-plaintext highlighter-rouge">#method=</code></h3>
<p>Finally, you’ll encounter methods with a final <code class="language-plaintext highlighter-rouge">=</code>, which (spoiler
alert) have nothing to do with equality. These methods are <strong>setter
methods</strong>: they’re used to set a value to an instance variable.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Cat</span>
<span class="k">def</span> <span class="nf">name</span>
<span class="vi">@name</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">name</span><span class="o">=</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span> <span class="c1"># setter method</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">kitty</span> <span class="o">=</span> <span class="no">Cat</span><span class="p">.</span><span class="nf">new</span>
<span class="n">kitty</span><span class="p">.</span><span class="nf">name</span> <span class="o">=</span> <span class="s2">"Pixel"</span>
<span class="nb">p</span> <span class="n">kitty</span><span class="p">.</span><span class="nf">name</span> <span class="c1"># => "Pixel"</span>
</code></pre></div></div>
<hr />
<p>To sum up, <code class="language-plaintext highlighter-rouge">=</code> on its own is <em>never</em> used to check whether
two elements are equal.</p>
<p>Instead, the <code class="language-plaintext highlighter-rouge">==</code> method will 99% of the times do the job 🌈</p>
<h2 id="the--method-and-value-equality">The <code class="language-plaintext highlighter-rouge">==</code> method and Value Equality</h2>
<h3 id="examples-of--usage">Examples of <code class="language-plaintext highlighter-rouge">==</code> usage</h3>
<p><code class="language-plaintext highlighter-rouge">==</code> usually checks whether the two objects on either side have
the same <em>value</em>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">3</span> <span class="o">==</span> <span class="mi">3</span> <span class="c1"># => true</span>
<span class="n">str</span> <span class="o">=</span> <span class="s2">"hello"</span>
<span class="n">str</span> <span class="o">==</span> <span class="s2">"hello"</span> <span class="c1"># => true</span>
<span class="n">str</span> <span class="o">==</span> <span class="s2">"world"</span> <span class="c1"># => false</span>
<span class="p">{</span> <span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span> <span class="p">}</span> <span class="o">==</span> <span class="p">{</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">,</span> <span class="ss">a: </span><span class="mi">1</span> <span class="p">}</span> <span class="c1"># => true</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="c1"># => true</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="c1"># => false</span>
</code></pre></div></div>
<p>From these examples, we can deduce the following:</p>
<ul>
<li>2 identical integers have equal value (which sounds pretty obvious)</li>
<li>A <code class="language-plaintext highlighter-rouge">String</code> of value <code class="language-plaintext highlighter-rouge">"hello"</code> referenced by a variable has the
same value than another <code class="language-plaintext highlighter-rouge">String</code> of value <code class="language-plaintext highlighter-rouge">"hello"</code></li>
<li>Two <code class="language-plaintext highlighter-rouge">String</code> objects of different values (<code class="language-plaintext highlighter-rouge">"hello"</code> and <code class="language-plaintext highlighter-rouge">"world"</code>)
are unequal</li>
<li>Two <code class="language-plaintext highlighter-rouge">Hashes</code> are equal if their key-value pairs are identical (even
if the order is different)</li>
<li><code class="language-plaintext highlighter-rouge">Arrays</code> must also have an identical order to be considered equal</li>
</ul>
<h3 id="the--method">The <code class="language-plaintext highlighter-rouge">==</code> method</h3>
<p>How does Ruby know how to compare two Hashes? Two Arrays? Two
custom objects? The answer lies in the fact that <code class="language-plaintext highlighter-rouge">==</code> is not
an operator but an <strong>instance method</strong>. You could actually write
<code class="language-plaintext highlighter-rouge">2.==(2)</code> instead of <code class="language-plaintext highlighter-rouge">2 == 2</code>.</p>
<p>Additionally, <code class="language-plaintext highlighter-rouge">==</code> is a <code class="language-plaintext highlighter-rouge">BasicObject</code> instance method (ie. the class
that contains every other object in Ruby), which means it’s available
to <em>any</em> object.</p>
<p>However, we almost never use the default <code class="language-plaintext highlighter-rouge">BasicObject#==</code> method.
Instead, each subclass is supposed to <strong>override</strong> the <code class="language-plaintext highlighter-rouge">==</code> method with a
custom definition that suits its own needs.</p>
<p>For instance, the <code class="language-plaintext highlighter-rouge">Hash#==</code> method does not account for key-value pairs order.
Here’s the corresponding entry in the
<a href="https://docs.ruby-lang.org/en/2.6.0/Hash.html#method-i-3D-3D">Ruby documentation</a>:</p>
<blockquote>
<p><strong>hsh == other_hash → true or false</strong></p>
<p>Equality—Two hashes are equal if they each contain the same number of keys
and if each key-value pair is equal to (according to <code class="language-plaintext highlighter-rouge">Object#==</code>)
the corresponding elements in the other hash.
<em>The orders of each hashes are not compared.</em></p>
</blockquote>
<h3 id="implications-for-object-oriented-programming">Implications for Object Oriented Programming</h3>
<p>Therefore, if you create a custom class and want to compare for “value equality”
between two instances, you’ll need to implement your own custom <code class="language-plaintext highlighter-rouge">==</code> instance
method.</p>
<p>Otherwise, <code class="language-plaintext highlighter-rouge">==</code> will still work, but probably not how you intended it:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Cat</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">kitty</span> <span class="o">=</span> <span class="no">Cat</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"teacup"</span><span class="p">)</span>
<span class="n">kitten</span> <span class="o">=</span> <span class="no">Cat</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"teacup"</span><span class="p">)</span>
<span class="nb">p</span> <span class="n">kitty</span> <span class="o">==</span> <span class="n">kitten</span> <span class="c1"># => false</span>
</code></pre></div></div>
<p>Those two <code class="language-plaintext highlighter-rouge">Cat</code> objects have exactly the same value but <code class="language-plaintext highlighter-rouge">kitty == kitten</code>
returns <code class="language-plaintext highlighter-rouge">false</code> - why?</p>
<p>The answer is that Ruby applied the <code class="language-plaintext highlighter-rouge">BasicObject#==</code> method, which has the
same implementation than <code class="language-plaintext highlighter-rouge">BasicObject#equal?</code> (see next section), and
basically checks whether two <em>objects</em> are equal (not whether they
have the same value).</p>
<p>Indeed, how could Ruby know when 2 <code class="language-plaintext highlighter-rouge">Cat</code> objects are equal? It doesn’t
know how to compare these two custom objects. We need to explicitly tell
Ruby how to compare them, by including an instance method <code class="language-plaintext highlighter-rouge">Cat#==</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Cat</span>
<span class="nb">attr_reader</span> <span class="ss">:name</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">==</span><span class="p">(</span><span class="n">other_cat</span><span class="p">)</span>
<span class="vi">@name</span> <span class="o">==</span> <span class="n">other_cat</span><span class="p">.</span><span class="nf">name</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">kitty</span> <span class="o">=</span> <span class="no">Cat</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"teacup"</span><span class="p">)</span>
<span class="n">kitten</span> <span class="o">=</span> <span class="no">Cat</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"teacup"</span><span class="p">)</span>
<span class="nb">p</span> <span class="n">kitty</span> <span class="o">==</span> <span class="n">kitten</span> <span class="c1"># => true</span>
</code></pre></div></div>
<p>Here, we chose to consider two cats identical if they have the same <code class="language-plaintext highlighter-rouge">name</code>
value. It’s completely up to us: we could also have chosen their <code class="language-plaintext highlighter-rouge">size</code> or
<code class="language-plaintext highlighter-rouge">color</code>. And it works! <code class="language-plaintext highlighter-rouge">kitty == kitten</code> now returns <code class="language-plaintext highlighter-rouge">true</code> 🍾</p>
<h2 id="the-equal-method">The <code class="language-plaintext highlighter-rouge">equal?</code> method</h2>
<p>If we want to know whether two objects are actually <em>the same object</em>, we can
use the <code class="language-plaintext highlighter-rouge">object_id</code> method and compare their IDs:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">1</span><span class="p">.</span><span class="nf">object_id</span> <span class="c1"># => 3 </span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">a</span><span class="p">.</span><span class="nf">object_id</span> <span class="c1"># => 3 </span>
<span class="mi">1</span><span class="p">.</span><span class="nf">object_id</span> <span class="o">==</span> <span class="n">a</span><span class="p">.</span><span class="nf">object_id</span> <span class="c1"># => true</span>
</code></pre></div></div>
<p>Here, both <code class="language-plaintext highlighter-rouge">1</code> and <code class="language-plaintext highlighter-rouge">a</code> share the same ID <code class="language-plaintext highlighter-rouge">3</code>, which means they are both
pointing to the same object.</p>
<p>However, there’s an easier way to compare for object equality, using the
<code class="language-plaintext highlighter-rouge">BasicObject#equal?</code> method:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span><span class="p">.</span><span class="nf">equal?</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># => true </span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">equal?</code> goes deeper than <code class="language-plaintext highlighter-rouge">==</code>: it checks whether two objects have the same
value <em>and</em> whether the two variables point to the same object.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">str1</span> <span class="o">=</span> <span class="s2">"hi there"</span>
<span class="n">str2</span> <span class="o">=</span> <span class="s2">"hi there"</span>
<span class="n">str3</span> <span class="o">=</span> <span class="n">str1</span>
<span class="n">str1</span> <span class="o">==</span> <span class="n">str2</span> <span class="c1"># => true </span>
<span class="n">str1</span><span class="p">.</span><span class="nf">equal?</span> <span class="n">str2</span> <span class="c1"># => false </span>
<span class="n">str1</span><span class="p">.</span><span class="nf">equal?</span> <span class="n">str3</span> <span class="c1"># => true</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">str1</code>, <code class="language-plaintext highlighter-rouge">str2</code> and <code class="language-plaintext highlighter-rouge">str3</code> all have the same value <code class="language-plaintext highlighter-rouge">"hi there"</code>.</p>
<p>However, only <code class="language-plaintext highlighter-rouge">str1</code> and <code class="language-plaintext highlighter-rouge">str3</code> point to the same object (as expected, given
that <code class="language-plaintext highlighter-rouge">str3</code> is a copy of <code class="language-plaintext highlighter-rouge">str1</code>). Therefore, <code class="language-plaintext highlighter-rouge">str1.equal? str3</code> returns <code class="language-plaintext highlighter-rouge">true</code>,
while <code class="language-plaintext highlighter-rouge">str1.equal? str2</code> returns <code class="language-plaintext highlighter-rouge">false</code>: <code class="language-plaintext highlighter-rouge">str1</code> and <code class="language-plaintext highlighter-rouge">str2</code> are different
objects which happen to have the same value <code class="language-plaintext highlighter-rouge">"hi there"</code>.</p>
<p>It’s pretty rare to use the <code class="language-plaintext highlighter-rouge">equal?</code> method, but it’s still useful to
understand its behavior, especially when implementing custom classes.</p>
<h2 id="what-about--1">What about <code class="language-plaintext highlighter-rouge">===</code>?</h2>
<p>If we know how to check for value equality (<code class="language-plaintext highlighter-rouge">==</code>) <em>and</em> for object equality
(<code class="language-plaintext highlighter-rouge">equal?</code>), what is <code class="language-plaintext highlighter-rouge">===</code> good for? It’s actually used to check for
<strong>range inclusion</strong>.</p>
<p>The <code class="language-plaintext highlighter-rouge">===</code> method compares two objects by checking whether the first element
(the <em>group</em>) includes the second element. It’s rarely used explicitly.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span> <span class="o">===</span> <span class="mi">3</span> <span class="c1"># true: 3 is included in the range from 1 to 10</span>
<span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span> <span class="o">===</span> <span class="mi">12</span> <span class="c1"># false</span>
<span class="p">(</span><span class="s1">'a'</span><span class="o">..</span><span class="s1">'d'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'c'</span> <span class="c1"># true: 'c' is included in the range from a to d</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">===</code> is much more often used implicitly though, as this is the method used
“under the hood” by <code class="language-plaintext highlighter-rouge">case</code> statements:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">char</span> <span class="o">=</span> <span class="s1">'d'</span>
<span class="k">case</span> <span class="n">char</span>
<span class="k">when</span> <span class="p">(</span><span class="s2">"a"</span><span class="o">..</span><span class="s2">"e"</span><span class="p">)</span>
<span class="s2">"yay"</span>
<span class="k">end</span>
<span class="c1"># => "yay"</span>
</code></pre></div></div>
<p>The above case statement is equivalent to the following code:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"yay"</span> <span class="k">if</span> <span class="p">(</span><span class="s2">"a"</span><span class="o">..</span><span class="s2">"e"</span><span class="p">)</span> <span class="o">===</span> <span class="n">char</span>
<span class="c1"># => "yay"</span>
</code></pre></div></div>
<h2 id="the-eql-method">The <code class="language-plaintext highlighter-rouge">eql?</code> method</h2>
<p>Here’s a last method to consider when thinking about equality. This one is
pretty obscure, and there’s a good chance you’ll never even have to use it,
but I’m aiming for exhaustivity here 👩🏫</p>
<h3 id="ruby-documentation">Ruby Documentation</h3>
<p>According to the
<a href="https://docs.ruby-lang.org/en/2.6.0/Object.html#method-i-eql-3F">Ruby documentation</a>:</p>
<blockquote>
<p><strong>eql?(other) → true or false</strong></p>
<p>The <code class="language-plaintext highlighter-rouge">eql?</code> method returns <code class="language-plaintext highlighter-rouge">true</code> if <code class="language-plaintext highlighter-rouge">obj</code> and <code class="language-plaintext highlighter-rouge">other</code> refer to the same hash
key. This is used by <code class="language-plaintext highlighter-rouge">Hash</code> to test members for equality. For objects of class
<code class="language-plaintext highlighter-rouge">Object</code>, <code class="language-plaintext highlighter-rouge">eql?</code> is synonymous with <code class="language-plaintext highlighter-rouge">==</code>. Subclasses normally continue
this tradition by aliasing <code class="language-plaintext highlighter-rouge">eql?</code> to their overridden <code class="language-plaintext highlighter-rouge">==</code> method, but
there are exceptions. <code class="language-plaintext highlighter-rouge">Numeric</code> types, for example, perform type conversion
across <code class="language-plaintext highlighter-rouge">==</code>, but not across <code class="language-plaintext highlighter-rouge">eql?</code>.</p>
</blockquote>
<p>Therefore, two <code class="language-plaintext highlighter-rouge">Numeric</code> objects could be equal (with <code class="language-plaintext highlighter-rouge">==</code>), but different with
<code class="language-plaintext highlighter-rouge">eql?</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">2</span> <span class="o">==</span> <span class="mf">2.0</span> <span class="c1">#=> true</span>
<span class="mi">2</span><span class="p">.</span><span class="nf">eql?</span><span class="p">(</span><span class="mf">2.0</span><span class="p">)</span> <span class="c1">#=> false</span>
<span class="mf">2.0</span><span class="p">.</span><span class="nf">eql?</span><span class="p">(</span><span class="mf">2.0</span><span class="p">)</span> <span class="c1">#=> true</span>
</code></pre></div></div>
<p>But most of the time, two objects that are equal through <code class="language-plaintext highlighter-rouge">==</code> should return
<code class="language-plaintext highlighter-rouge">true</code> when <code class="language-plaintext highlighter-rouge">eql?</code> is called.</p>
<h3 id="when-should-you-use-the-eql-method">When should you use the <code class="language-plaintext highlighter-rouge">eql?</code> method?</h3>
<p>The answer is: probably never. However,
it’s routinely used by <code class="language-plaintext highlighter-rouge">Hash</code> objects to check for hash key equality. As you
know, hash keys must be unique, and this is enforced through <code class="language-plaintext highlighter-rouge">eql?</code>.</p>
<p>To check for this uniqueness, <code class="language-plaintext highlighter-rouge">Hash</code> objects use the <code class="language-plaintext highlighter-rouge">eql?</code> method to
convert the keys through the <code class="language-plaintext highlighter-rouge">hash</code> method. This method returns a hash code for
each key.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Two different String objects with a value of "a" have the same hash:</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">hash</span> <span class="c1"># => -3382060362238486793</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">hash</span> <span class="c1"># => -3382060362238486793</span>
</code></pre></div></div>
<p>If the two <code class="language-plaintext highlighter-rouge">hash</code> return values are equal (like for <code class="language-plaintext highlighter-rouge">"a"</code>), then only one
element can serve as a <code class="language-plaintext highlighter-rouge">Hash</code> key.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">hash</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">'a'</span> <span class="o">=></span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'a'</span> <span class="o">=></span> <span class="mi">2</span> <span class="p">}</span>
<span class="c1"># warning: key "a" is duplicated and overwritten</span>
<span class="c1"># => {"a"=>2} </span>
</code></pre></div></div>
<p>In this case, it’s interesting to note that both <code class="language-plaintext highlighter-rouge">"a"</code> elements share the same
<code class="language-plaintext highlighter-rouge">hash</code>, but not the same <code class="language-plaintext highlighter-rouge">object_id</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Different object IDs</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">object_id</span> <span class="c1"># => 33313480</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">object_id</span> <span class="c1"># => 33412160</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">eql?</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span> <span class="c1"># => true</span>
<span class="s1">'a'</span><span class="p">.</span><span class="nf">equal?</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span> <span class="c1"># => false</span>
</code></pre></div></div>
<p>Therefore, <code class="language-plaintext highlighter-rouge">eql?</code> returns <code class="language-plaintext highlighter-rouge">true</code> (as it compares the two <code class="language-plaintext highlighter-rouge">hash</code>) and <code class="language-plaintext highlighter-rouge">equal?</code>
returns <code class="language-plaintext highlighter-rouge">false</code> (because their <code class="language-plaintext highlighter-rouge">object_id</code> are different).</p>
<h3 id="implications-for-object-oriented-programming-1">Implications for Object Oriented Programming</h3>
<p>If you happen to override <code class="language-plaintext highlighter-rouge">eql?</code> in a custom class, you’ll also need to
override the <code class="language-plaintext highlighter-rouge">hash</code> method. If you don’t, instances of this class won’t
work as keys in a <code class="language-plaintext highlighter-rouge">Hash</code>.</p>
<p>Indeed, objects used as keys <em>must</em> have a method named <code class="language-plaintext highlighter-rouge">hash</code> that returns
a numeric hashcode for the key.</p>
<hr />
<h2 id="key-take-aways">Key Take-Aways</h2>
<p>To sum-up:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">=</code> on its own is <em>not</em> about equality: it’s an <strong>assignment operator</strong>.</li>
<li><code class="language-plaintext highlighter-rouge">==</code> checks whether two objects have the same <strong>value</strong>.</li>
<li>The <code class="language-plaintext highlighter-rouge">==</code> method should be <strong>overriden</strong> when creating a custom class, in order
to tell Ruby how to compare two custom objects.</li>
<li>The <code class="language-plaintext highlighter-rouge">equal?</code> method checks whether two variables point to the <strong>same object</strong>.</li>
<li><code class="language-plaintext highlighter-rouge">===</code> checks for <strong>range inclusion</strong>, and is mostly used by <code class="language-plaintext highlighter-rouge">case</code>
statements.</li>
<li>The <code class="language-plaintext highlighter-rouge">eql?</code> method is almost exclusively used by <code class="language-plaintext highlighter-rouge">Hash</code> objects to check the
uniqueness of their hash keys.</li>
</ul>Juliette SinibardyWhen I discovered programming, I was bamboozled by the incredible amout of times you type the = key. Among other things, I couldn’t help but wonder: Why on earth was I supposed to use == instead of the more ‘natural’ = to express equality? Turns out, it’s actually possible to make sense of this = madness! Here’s a cheat sheet to gain a better understanding of equality and the equal sign = in Ruby.My Favourite Codewars Kata to Prepare for Launch School’s 109 Oral Assessment2019-07-29T21:11:00+02:002019-08-12T16:56:00+02:00https://jsinibardy.com/codewars-kata-launch-school-109-oral-assessment<p>I’ve recently passed with success my first Launch School oral assessment (the
dreaded 109 oral exam) 🍾</p>
<p>It was a hell of a ride, and I’d like to share my secret recipe: training with
<a href="https://codewars.com">Codewars</a>.</p>
<!--more-->
<h2 id="launch-schools-ruby-small-problems">Launch School’s Ruby Small Problems</h2>
<p>I’ll start by stating the obvious: you should first and foremost do the
Ruby Small Problems provided by Launch School. Once you’re done, you
should also re-do them at least once. They’re literally made to prepare you
for the 109 exam so you should put in a lot of efforts on them.</p>
<p>However as I’m blessed with an excellent memory, re-doing the same
exercises wasn’t much of a challenge as I mostly (sometimes vaguely)
remembered the pattern I was supposed to follow. I sometimes ended up with
the exact same solution I had found on my first pass.</p>
<p>Sure, easily redoing the exercises somewhat boosted my confidence, but I felt
unsure on whether I was actually getting better at coding or if I was doing it
all from memory.</p>
<p>I needed fresh exercises! And this is how I started doing exercises on
Codewars.</p>
<h2 id="whats-codewars">What’s Codewars?</h2>
<p>Codewars is a community-based website where you can train on exercises and
gain points (<em>honor</em>) solving them. (You can also submit new exercises
or translate the problem on another programming language.)</p>
<p>What I liked most is the fact that once you submit your answer, you gain access
to the solutions provided by others. As the best ones get upvoted, you can
therefore discover a much clever way to solve the “Kata”. This is how
I’ve discovered new methods, like <code class="language-plaintext highlighter-rouge">String#scan</code> or <code class="language-plaintext highlighter-rouge">Enumerator#with_index</code>.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/codewars.png">
<img src="/assets/images/codewars.png" alt="Codewars solution to a kata" />
</a>
<figcaption>You can now compare your 10 line method to the glorious one-liners</figcaption>
</figure>
</div>
<h2 id="my-favourite-katas">My favourite Katas</h2>
<p>I’ve listed here my favourite Katas that could help you prepare the 109
assessment. I’ve tried to avoid the Katas where advanced Math knowledge
is necessary, and aimed at selecting problems that looked like the ones given
by Launch School. The Katas are ordered by complexity (<em>8 kyu</em> is the easiest).</p>
<p>My personal challenge before the assessment was being able to solve the 6 kyu
katas in less than 20 minutes. Bear in mind that the problem given during
the oral exam will be more or less of the level of 6 kyu katas, <em>and</em> you’ll be
much more stressed out and prone to mistakes.</p>
<h3 id="7-or-8-kyu">7 or 8 kyu</h3>
<ul>
<li>[8 kyu] <a href="https://www.codewars.com/kata/59342039eb450e39970000a6">Count Odd numbers below n</a></li>
<li>[7 kyu] <a href="https://www.codewars.com/kata/58aa68605aab54a26c0001a6">Distinct Digit Year</a> ⭐</li>
<li>[7 kyu] <a href="https://www.codewars.com/kata/5a523566b3bfa84c2e00010b">Minimize Sum of Arrays</a></li>
<li>[7 kyu] <a href="https://www.codewars.com/kata/5a4ea304b3bfa89a9900008e">Form the Largest</a> ⭐</li>
<li>[7 kyu] <a href="https://www.codewars.com/kata/544aed4c4a30184e960010f4">Find the Divisors</a></li>
<li>[7 kyu] <a href="https://www.codewars.com/kata/56269eb78ad2e4ced1000013">Find the Next Perfect Square</a></li>
</ul>
<h3 id="5-or-6-kyu">5 or 6 kyu</h3>
<ul>
<li>[6 kyu] <a href="https://www.codewars.com/kata/514b92a657cdc65150000006">Multiples of 3 or 5</a></li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/5894318275f2c75695000146">Delete a Digit</a></li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/5970df092ef474680a0000c9">Alphabetized</a></li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/5ae326342f8cbc72220000d2">Simple Simple Simple String Expansion</a> ⭐</li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/58f5c63f1e26ecda7e000029">Mexican Wave</a></li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/53bb1201392478fefc000746">Sherlock on pockets</a> (good to practice hashes)</li>
<li>[6 kyu] <a href="https://www.codewars.com/kata/546f922b54af40e1e90001da">Replace with Alphabet Position</a> ⭐</li>
<li>[5 kyu] <a href="https://www.codewars.com/kata/520b9d2ad5c005041100000f">Simple Pig Latin</a> ⭐</li>
</ul>
<p>I’ve marked of a star (⭐) the Katas that I enjoyed the most.</p>
<p>And for the perfectionists out there, stop fretting because your solution to the
kata is not as elegant as the top-voted solutions. It’s OK, we’ll get there!
(I can spot you from afar, I’m the same 😉)</p>
<hr />
<p>If you’re interested in preparing Launch School’s exams, you might want
to check out these other posts:</p>
<ul>
<li><a href="/preparing-launch-school-109-written-assessment">How I Prepared for Launch School’s 109 written assessment</a></li>
<li><a href="preparing-launch-school-109-oral-assessment">How I Prepared for Launch School’s 109 oral assessment</a></li>
</ul>Juliette SinibardyI’ve recently passed with success my first Launch School oral assessment (the dreaded 109 oral exam) 🍾 It was a hell of a ride, and I’d like to share my secret recipe: training with Codewars.How I Prepared for Launch School’s 109 Written Assessment2019-07-17T12:14:00+02:002019-08-12T16:57:00+02:00https://jsinibardy.com/preparing-launch-school-109-written-assessment<p>I recently took Launch School’s first written exam (RB 109), that comes at the
end of the first course, RB 101, Programming Foundations.</p>
<p>This course is especially challenging because it forces us to simultaneously:</p>
<ul>
<li>learn to learn again,</li>
<li>learn Ruby syntax,</li>
<li>learn problem solving.</li>
</ul>
<p>I thought it would be a good time to reflect on my study methods and the time
it took me to get there.</p>
<!--more-->
<p><strong>Disclaimer</strong>: The time it takes to get through the course is entirely
personal. I may have been at ease on some topics, and completely stuck
on other parts. The time logs are simply indicative and should not impact
your own study flow.</p>
<h2 id="going-through-the-101-courses">Going through the 101 courses</h2>
<p>During the lessons, I always took notes in <strong>Markdown</strong> (this will come in handy
later), using <a href="https://typora.io/">Typora</a>. My notes were pretty detailed
(sometimes even bordering on copying word after word the lesson). I guess
this meticulous copying helps my memorization, even though I haven’t re-read
my notes for the most part.</p>
<p>I spent a significative time going through the lessons (<strong>37.5 hours</strong>), and
was striving to understand every line of the lesson.</p>
<h2 id="the-ruby-small-problems">The Ruby Small Problems</h2>
<p>To take a break in between lessons, I was also advancing on the <strong>Ruby Small
Problems</strong>. My goal was to always find a working solution myself, and if I
didn’t, I added this problem in my “to be done again” list.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/to-do-list.png">
<img src="/assets/images/to-do-list.png" alt="My exercises to do list" />
</a>
<figcaption>Pro tip: you can create a checkbox in markdown with `[ ]`</figcaption>
</figure>
</div>
<p>I would then briefly read the solution (trying not to spend more than a
couple of seconds on it), then hide the solution and try to come up with
the exact same program without peeking too much.</p>
<p>If the solution introduced a new method, I would look it up on the
documentation and sometimes incorpore it in my Anki memory cards (more on that
below).</p>
<p>If I could, I would also work on the Further Exploration. But most of the time,
the Further Exploration joined the “to be done again” list.</p>
<p>When I was nearing the end of the 101 course, I started re-doing the “to be
done again” exercises, and even though some remained difficult, most of them
felt much easier. This was probably the biggest sign that I was actually
making a progress (and it felt good!)</p>
<p>Most of my time on 101 was spent on the Ruby Small Problems, which took me
more than <strong>60 hours</strong>. (And I haven’t quite finished a couple of
Advanced Problems.)</p>
<h2 id="creating-flash-cards-on-anki">Creating Flash cards on Anki</h2>
<p>Everytime I would encounter an information that seemed important enough,
I would create an Anki flash card.</p>
<p><strong>Note:</strong> on desktop, I prefer using <a href="https://ankiweb.net">Anki’s web interface</a>
rather than their pretty dated software interface.</p>
<p>What’s my gradiant for “important enough”?</p>
<ul>
<li>An information that contains some general knowledge about computer science
(eg. regular expressions, command line interface…)</li>
<li>An information about Ruby’s behavior (eg. pass by value / reference,
variable scope, truthiness)</li>
<li>A method that seemed particularly useful (eg. <code class="language-plaintext highlighter-rouge">Array#|</code> to merge two arrays
while only keeping the unique values)</li>
</ul>
<p>Example of questions and answers:</p>
<blockquote>
<p>How can I add an element to the beginning of the array?</p>
<p>By using <code class="language-plaintext highlighter-rouge">Array#unshift</code> (destructive)</p>
</blockquote>
<blockquote>
<p>How can I check that a collection has at least one element that satisfies an
expression?</p>
<p>By using <code class="language-plaintext highlighter-rouge">Enumerable#any?</code></p>
</blockquote>
<blockquote>
<p>What does the last expression return?</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">arr</span> <span class="o">=</span> <span class="p">[[</span><span class="s1">'a'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'b'</span><span class="p">]],</span> <span class="p">{</span> <span class="ss">b: </span><span class="s1">'bear'</span><span class="p">,</span> <span class="ss">c: </span><span class="s1">'cat'</span> <span class="p">},</span> <span class="s1">'cab'</span><span class="p">]</span>
<span class="n">arr</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="ss">:b</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
</code></pre></div> </div>
<p><code class="language-plaintext highlighter-rouge">"b"</code></p>
</blockquote>
<p>I would use my commute time to go through my Anki deck (on the mobile app),
sometimes editing old questions when the formulation was too vague or implied
that I didn’t quite grasp a concept at that time.</p>
<h2 id="the-study-sessions">The Study Sessions</h2>
<p>At the end of the 101 course, I started to attend as many study sessions as
I could. Before that, I was pretty embarrassed to showcase my lack of
mastery, and prefered avoiding them.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/buzz.gif">
<img src="/assets/images/buzz.gif" alt="Buzz Lightyear gif" />
</a>
<figcaption>How I thought TAs would react when I'd open my mouth</figcaption>
</figure>
</div>
<p>However, I can now see how mistaken I was. The Teacher Assistants are nothing
but kind and encouraging. Attending study sessions both helped me
try new solving methods and gain in confidence. These sessions are
absolutely essential for the oral assessment, but I believe they helped me
for the written assessment as well.</p>
<h2 id="the-study-guide">The Study Guide</h2>
<p>Launch School provides a Study guide that details what will be covered in the
written assessment. And this is actually 100% true: what is listed <em>will</em>
be useful during the exam.</p>
<p>I personally spent quite some time on the following:</p>
<ul>
<li>Variables as pointers</li>
<li>Mutative methods</li>
<li>Pass by reference & Pass by value</li>
<li>Truthiness</li>
</ul>
<p>Whenever a concept came up, I tried to create my own example on Ruby and saved
it for the exam. Complete mastery of the concept is not enough: you need to be
able to answer fast, and having pre-made bits of answers can go a long way.</p>
<p>Keep in mind that you’ll have more than 20 questions (I had 23) and only
3 hours: if you take into account the necessary time to read the questions and
proofread your answers, you’ll have less than 10 minutes per question.</p>
<p>To assess whether I was ready to take the exam, I’ve worked on
<a href="https://medium.com/how-i-started-learning-coding-from-scratch/advice-for-109-written-assessment-part-3-d39dceb06c0c">Srdjan</a>’s
programs while trying to spend less than 5 minutes to precisely describe
what was happening under the hood.</p>
<p>I ended up creating a handful of pre-made sentences that were useful all the
time, like:</p>
<blockquote>
<p>We’ve initialized the variable <code class="language-plaintext highlighter-rouge">var_name</code> and assigned to it the
Integer/String/etc object <code class="language-plaintext highlighter-rouge">value</code> to it.</p>
</blockquote>
<p>This little trick saved me a couple of critical minutes during the exam.</p>
<h2 id="my-timelogs">My Timelogs</h2>
<p>I’ve used <a href="https://www.toggl.com/">Toggl</a> to keep track of how long I spent
on each topic, and also to make sure that I reached my 15-hours per week
objective.</p>
<p>Here’s the total breakdown of my <strong>127 hours</strong> spent on the 101 course:</p>
<table>
<thead>
<tr>
<th>Topic</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lessons</td>
<td>33.5 hours</td>
</tr>
<tr>
<td>Video Lessons</td>
<td>4 hours</td>
</tr>
<tr>
<td>Walk-through / Assignments</td>
<td>12 hours</td>
</tr>
<tr>
<td>Ruby Small Problems</td>
<td>52 hours</td>
</tr>
<tr>
<td>Practice Problems</td>
<td>10 hours</td>
</tr>
<tr>
<td>Live-coding</td>
<td>8 hours</td>
</tr>
<tr>
<td>Exams (incl. quizzes)</td>
<td>7.5 hours</td>
</tr>
</tbody>
</table>
<div style="text-align: center">
<figure>
<a href="/assets/images/toggl.png">
<img src="/assets/images/toggl.png" alt="My weekly toggle timelogs" />
</a>
<figcaption>The weekly breakdown</figcaption>
</figure>
</div>
<p>Now, time to practice for the interview assessment!</p>
<hr />
<p>If you’re currently preparing the 109 Launch School exams, congratulations! 🎉
Additionally, you might find these other posts useful:</p>
<ul>
<li><a href="preparing-launch-school-109-oral-assessment">How I Prepared for Launch School’s 109 oral assessment</a></li>
<li><a href="codewars-kata-launch-school-109-oral-assessment">My Favorite Katas to Prepare for Launch School’s 109 oral assessment</a></li>
</ul>Juliette SinibardyI recently took Launch School’s first written exam (RB 109), that comes at the end of the first course, RB 101, Programming Foundations. This course is especially challenging because it forces us to simultaneously: learn to learn again, learn Ruby syntax, learn problem solving. I thought it would be a good time to reflect on my study methods and the time it took me to get there.A Beginner’s Guide to SEO optimization in a Jekyll static website2019-07-09T09:16:00+02:002019-07-09T23:06:00+02:00https://jsinibardy.com/optimize-jekyll-seo<blockquote>
<p>What? There’s no sitemap here?
<em>- Me when I discovered my new Jekyll blog</em></p>
</blockquote>
<p>Although Jekyll comes a little “naked” in terms of necessary SEO tools
(especially in comparison to traditional CMS), it’s pretty easy to remedy this
situation. Here are a couple of easy steps to follow, in order to improve your
SEO ranking and
<a href="https://developers.google.com/web/tools/lighthouse/">your Lighthouse score</a>.</p>
<!--more-->
<ul id="markdown-toc">
<li><a href="#install-jekyll-seo-tag" id="markdown-toc-install-jekyll-seo-tag">Install jekyll-seo-tag</a></li>
<li><a href="#install-jekyll-sitemap-and-optimize-date-management" id="markdown-toc-install-jekyll-sitemap-and-optimize-date-management">Install jekyll-sitemap and optimize date management</a></li>
<li><a href="#add-a-google-analytics-tracking-id" id="markdown-toc-add-a-google-analytics-tracking-id">Add a Google Analytics tracking ID</a></li>
<li><a href="#performance-optimizations" id="markdown-toc-performance-optimizations">Performance optimizations</a> <ul>
<li><a href="#google-analytics-tracking" id="markdown-toc-google-analytics-tracking">Google Analytics tracking</a></li>
<li><a href="#reduce-image-size" id="markdown-toc-reduce-image-size">Reduce image size</a></li>
<li><a href="#replace-github-gist-by-code-snippets" id="markdown-toc-replace-github-gist-by-code-snippets">Replace Github gist by code snippets</a></li>
<li><a href="#remove-useless-fonts" id="markdown-toc-remove-useless-fonts">Remove useless fonts</a></li>
</ul>
</li>
<li><a href="#accessibility" id="markdown-toc-accessibility">Accessibility</a></li>
<li><a href="#seo-101" id="markdown-toc-seo-101">SEO 101</a></li>
</ul>
<hr />
<h2 id="install-jekyll-seo-tag">Install jekyll-seo-tag</h2>
<p>The first thing you want to do is install the
<a href="https://github.com/jekyll/jekyll-seo-tag">jekyll-seo-tag plugin</a>.</p>
<p>This plugin will automatically generate the following meta tags:</p>
<ul>
<li>Page title and description</li>
<li>Canonical URL</li>
<li>Open Graph title, description (useful for Facebook or Linkedin)</li>
<li>Twitter Summary Card metadata</li>
<li>and other stuff</li>
</ul>
<p>Once the plugin is added to your <code class="language-plaintext highlighter-rouge">_config.yml</code> file, you’ll need to add a simple
line to the <code class="language-plaintext highlighter-rouge">head</code> of every page. To do that, I created a
<code class="language-plaintext highlighter-rouge">custom-head.html</code> file in the <code class="language-plaintext highlighter-rouge">_includes</code> folder and added the following
SEO tag:</p>
<script src="https://gist.github.com/17b76ed8bf8dc7d892dd2e19ca9a59d4.js"> </script>
<p>Now, all you have to do is to update your title, metadescriptions and permalink
on every article or page ✨</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">How</span><span class="nv"> </span><span class="s">to</span><span class="nv"> </span><span class="s">Set</span><span class="nv"> </span><span class="s">Up</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">Contact</span><span class="nv"> </span><span class="s">Form</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">Jekyll"</span>
<span class="na">permalink</span><span class="pi">:</span> <span class="s">setup-contact-form-jekyll</span>
<span class="na">description</span><span class="pi">:</span> <span class="s">Here's a detailed tutorial on how to set up a</span>
<span class="s">free contact form on static websites like Jekyll</span>
</code></pre></div></div>
<h2 id="install-jekyll-sitemap-and-optimize-date-management">Install jekyll-sitemap and optimize date management</h2>
<p>The next thing you’ll need is have a good sitemap, to help web crawlers
do their job.</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/happy-index-robot.jpg">
<img src="/assets/images/happy-index-robot.jpg" alt="Busy robot from Wall-E" />
</a>
<figcaption>🤖 Must... index... everything... 🤖</figcaption>
</figure>
</div>
<p>Fortunately, there’s a plugin for that:
<a href="https://github.com/jekyll/jekyll-sitemap">jekyll-sitemap</a>! And its use is
pretty straightforward.</p>
<p>The only subtlety is the date and time management. The sitemap plugin will
automatically use your <strong>Created date</strong> to fill the <code class="language-plaintext highlighter-rouge"><lastmod></code> tag.</p>
<p>However, you probably want to have your <strong>Last modified date</strong> instead.
To do that, you could use
<a href="https://github.com/gjtorikian/jekyll-last-modified-at">the jekyll-last-modified-at plugin</a>.</p>
<p>However the plugin isn’t compatible with Github Pages, because of Github’s
automatic builds. Instead, you can add add the parameter <code class="language-plaintext highlighter-rouge">last_modified_at</code>
inside your front matter directly, and the sitemap will automatically use
this date as the Last modified date.</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">date</span><span class="pi">:</span> <span class="s">2019-07-03 10:28:08 +0200</span>
<span class="na">last_modified_at</span><span class="pi">:</span> <span class="s">2019-07-07 11:55:00 +0200</span>
</code></pre></div></div>
<p>To simplify your use of timestamps, I recommend using the
<a href="https://github.com/jekyll/jekyll-compose">jekyll-compose plugin</a>. It will
automatically create your posts with the perfect timestamp and your custom
front matter.</p>
<p>All you need to do is correctly set up your <code class="language-plaintext highlighter-rouge">_config.yml</code> file and then
type <code class="language-plaintext highlighter-rouge">bundle exec jekyll post "My post name"</code> in your CLI.</p>
<p>Here are my own custom front matter settings:</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">jekyll_compose</span><span class="pi">:</span>
<span class="na">post_default_front_matter</span><span class="pi">:</span>
<span class="na">last_modified_at</span><span class="pi">:</span>
<span class="na">permalink</span><span class="pi">:</span>
<span class="na">description</span><span class="pi">:</span>
<span class="na">image</span><span class="pi">:</span>
<span class="na">published</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">sitemap</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">excerpt_separator</span><span class="pi">:</span> <span class="s"><!--more--></span>
<span class="na">categories</span><span class="pi">:</span>
<span class="na">tags</span><span class="pi">:</span>
</code></pre></div></div>
<p>Additionally, you should specify your UTC timezone in your <code class="language-plaintext highlighter-rouge">_config.yml</code> file,
using the <a href="https://en.wikipedia.org/wiki/Tz_database">IANA TimeZone Database</a>
naming convention.</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">timezone</span><span class="pi">:</span> <span class="s">Europe/Paris</span>
</code></pre></div></div>
<p>This will allow your timestamps to use your correct timezone:</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Before setting the timezone</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2019-07-03 08:28:08 +0000</span>
<span class="c1"># After setting the timezone</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2019-07-03 10:28:08 +0200</span>
</code></pre></div></div>
<h2 id="add-a-google-analytics-tracking-id">Add a Google Analytics tracking ID</h2>
<p>If you haven’t already, you’ll need to add a Google Analytics tag in order
to follow your traffic.</p>
<p>To do that, let’s create an <code class="language-plaintext highlighter-rouge">analytics.html</code> file in your <code class="language-plaintext highlighter-rouge">_includes</code> folder.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- Global site tag (gtag.js) - Google Analytics --></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"preconnect"</span> <span class="na">as=</span><span class="s">"script"</span>
<span class="na">href=</span><span class="s">"https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID"</span><span class="nt">></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">dataLayer</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">dataLayer</span> <span class="o">||</span> <span class="p">[];</span>
<span class="kd">function</span> <span class="nx">gtag</span><span class="p">(){</span><span class="nx">dataLayer</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);}</span>
<span class="nx">gtag</span><span class="p">(</span><span class="dl">'</span><span class="s1">js</span><span class="dl">'</span><span class="p">,</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">());</span>
<span class="nx">gtag</span><span class="p">(</span><span class="dl">'</span><span class="s1">config</span><span class="dl">'</span><span class="p">,</span> <span class="nx">YOUR_TRACKING_ID</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>Then, you’ll need to include <code class="language-plaintext highlighter-rouge">analytics.html</code> in your <code class="language-plaintext highlighter-rouge">custom-head.html</code> file:</p>
<script src="https://gist.github.com/e8a02a89d20d53ba4c5671f1c6121de8.js"> </script>
<p>The <code class="language-plaintext highlighter-rouge">% if %</code> condition removes the tracking tag from my own local server. Thus,
my own local tests will not be taken into account in my global Analytics
reports.</p>
<h2 id="performance-optimizations">Performance optimizations</h2>
<h3 id="google-analytics-tracking">Google Analytics tracking</h3>
<p>You may have noticed that, in the <code class="language-plaintext highlighter-rouge">analytics.html</code> file, I did not use the
default script provided by Google.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!--Default script--></span>
<span class="nt"><script </span><span class="na">async</span>
<span class="na">src=</span><span class="s">"https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID"</span><span class="nt">></span>
<span class="nt"></script></span>
<span class="c"><!--Custom script--></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"preconnect"</span> <span class="na">as=</span><span class="s">"script"</span>
<span class="na">href=</span><span class="s">"https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID"</span><span class="nt">></span>
</code></pre></div></div>
<p>Instead, I’m using the resource hint <code class="language-plaintext highlighter-rouge">rel="preconnect"</code> in order to tell the
browser to start loading the Google Analytics script before an HTTP request
is sent to the server. This performance optimization improved my loading time
by <strong>130 ms</strong>.</p>
<h3 id="reduce-image-size">Reduce image size</h3>
<p>Before uploading an image, you should always:</p>
<ul>
<li>Resize the image at its minimum. For instance, my blog accepts images up to
800 px width, therefore it’s no use uploading a 1500 px photo.</li>
<li>Compress the image with a service like <a href="https://tinypng.com/">TinyPNG</a></li>
</ul>
<p>This simple action will save you dozens of ms of loading time.</p>
<h3 id="replace-github-gist-by-code-snippets">Replace Github gist by code snippets</h3>
<p>Whenever possible, use Markdown code snippets instead of Github gist. As
pretty as they are, they also take up some precious loading time (about
<strong>300 ms</strong> for my blog).</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/sloth.jpg">
<img src="/assets/images/sloth.jpg" alt="Cute sloth" />
</a>
<figcaption>Accurate picture of a Github asset being loaded</figcaption>
</figure>
</div>
<h3 id="remove-useless-fonts">Remove useless fonts</h3>
<p>My Jekyll theme came with a <strong>190 ms</strong> loading time title font. Which could
mean only one thing: the font had to go.</p>
<p>Surprisingly, it was actually pretty difficult to get rid of it.</p>
<p>As the font was present in the default <code class="language-plaintext highlighter-rouge">_includes/font-includes.html</code> file,
I had to create a custom <code class="language-plaintext highlighter-rouge">_includes/head.html</code> file.</p>
<p>Inside this new <code class="language-plaintext highlighter-rouge">head</code>, I deleted the infamous
<code class="language-plaintext highlighter-rouge">% include font-includes.html %</code> line, and the font loading time magically
disappeared. 🚀</p>
<h2 id="accessibility">Accessibility</h2>
<p>The theme I’ve used scored pretty poorly on Accessibility items, because the
colors chosen (albeit beautiful) lacked contrasts. This was especially true
for the theme’s code snippets.</p>
<p>Therefore, I’ve used this
<a href="https://dequeuniversity.com/rules/axe/3.3/color-contrast">contrast tool</a>
to select new colors. Then, I’ve included the new hexadecimal codes in
my <code class="language-plaintext highlighter-rouge">assets/css/main.scss</code> file. Here’s an excerpt:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">/* Literal.Number */</span>
<span class="nc">.highlight</span> <span class="nc">.s</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="m">#C04343</span><span class="p">;</span> <span class="p">}</span>
<span class="c">/* Literal.String */</span>
<span class="nc">.highlight</span> <span class="nc">.na</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span> <span class="m">#8B38D1</span><span class="p">;</span> <span class="p">}</span>
</code></pre></div></div>
<h2 id="seo-101">SEO 101</h2>
<p>Finally, and perhaps the most important thing, is to consistently respect
the SEO Best practices throughout your website.</p>
<p>Here are a few of them:</p>
<ul>
<li>Use <strong>HTTPS</strong> (plus it’s so easy to enforce HTTPS with Github Pages!)</li>
<li>Declare the <strong>HTML doctype</strong> at the beginning of the page, along as the
<code class="language-plaintext highlighter-rouge"><lang></code> attribute</li>
<li>Have a valid <strong>robots.txt</strong> file</li>
<li>Use <strong>consistent URLs</strong> (either <code class="language-plaintext highlighter-rouge">/my_link</code> or <code class="language-plaintext highlighter-rouge">/my_link/</code> but not a mix
of both)</li>
<li>Use the <strong><code class="language-plaintext highlighter-rouge">alt</code> attribute</strong> on your images, both for ranking and accessibility
reasons</li>
<li>Choose a discernable name for your <strong>links</strong></li>
<li>Make all <strong>external links</strong> <code class="language-plaintext highlighter-rouge">_blank</code> and <code class="language-plaintext highlighter-rouge">nofollow noopener</code></li>
<li>Create a <strong>netlinking</strong> strategy, to improve your pagerank and enhance the
Internet user’s journey</li>
<li>…and a bunch of other stuff</li>
</ul>
<p>Your best bet is to frequently run
<a href="https://developers.google.com/web/tools/lighthouse/">Lighthouse audits</a>
on your pages and fix every problematic item.</p>
<p>Here’s the Lighthouse audit for this page:</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/lighthouse-audit.png">
<img src="/assets/images/lighthouse-audit.png" alt="Lighthouse audit's results on this web page" />
</a>
<figcaption>All green! 💚</figcaption>
</figure>
</div>
<p><em>Note</em>: My performance score here is somewhat lowered because of the inclusion of
Github gists, that significantly increases the loading time. The First
Meaningful Paint is therefore at 2.5 seconds.</p>
<p><a href="/">My blog’s homepage</a> has a much better overall performance, with a
First Meaningful Paint at 0.8 second. This is mostly explained by the lack
of external resources loaded on the front page (no Github gist, no images).</p>
<div style="text-align: center">
<figure>
<a href="/assets/images/lighthouse-homepage.png">
<img src="/assets/images/lighthouse-homepage.png" alt="Lighthouse audit's results for the homepage" />
</a>
<figcaption>Static websites are incredibly fast 😍</figcaption>
</figure>
</div>Juliette SinibardyWhat? There’s no sitemap here? - Me when I discovered my new Jekyll blog Although Jekyll comes a little “naked” in terms of necessary SEO tools (especially in comparison to traditional CMS), it’s pretty easy to remedy this situation. Here are a couple of easy steps to follow, in order to improve your SEO ranking and your Lighthouse score.