Sean is Coding #3: Connect Four
Bootcamp begins with algorithms, OOP, pair programming, and games
In this Issue:
Progress Report (Part 1): Week 1
Progress Report (Part 2): Connect Four
Bug Report: The Trouble with
this
Surf Report: Tech Layoffs Feeding Startup Surge?
Progress Report (Part 1): Week 1
We are off to the races! Today marks the end of my first week at Rithm School. The schedule is necessarily intense, but sustainable. Our days start at 9:30 am and end at around 6 pm. Days are split between a mix of lectures and hands-on labs where we work in pairs building apps and solving algorithmic challenges.
I am really enjoying the teaching staff and my classmates. It's a serious program and it feels serious, but we’re also having fun with it. It very much feels like we're all in this together, supporting each other as we learn and grow as developers.
One thing I'm still trying to figure out is how to make progress on "life stuff" outside class. With such limited “free” daytime hours, I'm still figuring out the best way to stay on top of laundry, exercise, and food consumption.
Overall, though, I’m grateful to have the opportunity to immerse myself in programming to this extent with a cohort of other like-minded people.
Progress Report (Part 2): Connect Four
One of the apps we built in lab this week was a browser-based version of Connect Four in JavaScript. The next day, we refactored our code to fit within the Object-Oriented Programming paradigm centered around a unified Game
object that manages the data and functionality for a given game, along with "Player" objects to manage individual player preferences.
Having to do this refactoring was was a great exercise. It really helped to highlight the importance of context in function calls and also highlighted in practical terms some of the real benefits of OOP. Once we refactored the functionality into Game
objects, things that would have been extremely complicated to do became trivial. For example, spinning up multiple simultaneous instances of a game, extending the game class to allow for subclasses with special rules like more players, bigger boards, and so on.
I’ve started a running list on GitHub of new features I plan to roll out, but in the meantime you can start playing with the simple version here: https://seanoliver.dev/connect-four-oo/
Bug Report: The Trouble with this
If debugging is the process of removing bugs, then programming must be the process of putting them in.
— Edsger W. Dijkstra
Each week, I’ll share a particularly nasty bug I encountered along with how I resolved it.
This week's bug involves the infamous this
keyword in JavaScript. In my game object, I have a method called makeHtmlBoard
, which creates the game board and adds a click event listener to the top of each column, allowing the user to drop a piece in their turn. There's also an endGame
method that congratulates the winner and should stop the user from being able to continue to add pieces to the board.
Here are the relevant sections of code:
class Game {
makeHtmlBoard() {
// ...
top.addEventListener('click', this.handleClick.bind(this));
// ...
}
endGame(msg) {
// ...
top.removeEventListener('click', this.handleClick.bind(this));
// ...
}
}
Unfortunately, we quickly realized that endGame
was not actually removing the event listener, so a user could keep dropping pieces onto the game board even after the game had ended.
We added some console.log()
s in various places to confirm that:
Every line of code was, in fact, running when it was supposed to
this
correctly referenced the current instance ofGame
each time it was used
After exhausting other possibilities, we realized we weren’t fully familiar with all the magic the bind()
function was doing under the hood. We’d only been introduced to it in a lecture earlier that day.
We took a trip to the MDN docs and our mistake dawned upon us:
The
bind()
method creates a new function that, when called, has itsthis
keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
The bind()
method creates a new function! D’oh! 🤦♂️
While they might look the same, the removeEventListener
was referencing a different function in memory than addEventListener
, so it couldn’t find the correct listener to remove!
The solution was to store a single version of the bound function reference in a variable in the Game
constructor and use it for both adding and removing the event listener:
class Game {
constructor(height = 6, width = 7) {
// ...
this.boundHandleClick = this.handleClick.bind(this);
// ...
}
makeHtmlBoard() {
// ...
top.addEventListener('click', this.boundHandleClick);
// ...
}
endGame(msg) {
// ...
const top = document.getElementById('column-top');
top.removeEventListener('click', this.boundHandleClick);
// ...
}
}