Documenting my projects, milestones, and transition to web development.

: Mintbean Hackathon

Recently I participated in my first hackathon ... Mintbean's 'Hiring Hackathon for Jr Web Devs' (Jul 27, 2021 to Aug 3, 2021). The goal of the hackathon was to build a card game. My entry was Crazy Eights, written using React and Redux. Last month I wrote about learning Redux, so this hackathon was a great opportunity to cement that knowledge.

Also, in the process of completing the hackathon, I discovered some new npm packages:

  1. redux-batch: The redux store for the game contains various slices, and each slice has its associated reducer. Each slice contains data for an entity in the game ... so there's a slice for the deck, the discard pile, the computer's hand, the player's hand, etc. Some events that arise during game play will affect multiple slices. For example, when a card is played, it needs to be removed from the player's hand (player's slice) and added to the discard pile (pile slice). So I began wondering if there was a way to group these actions together, and notify the UI only after all the batched actions were executed. Enter @manaflair/redux-batch! After I added it as an enhancer to the redux store:
    
                  import { configureStore } from '@reduxjs/toolkit';
                  import { reduxBatch }  from '@manaflair/redux-batch';
                  import deckReducer from './slices/deckSlice';
                  import pileReducer from './slices/pileSlice';
                  import playerReducer from './slices/playerSlice';
                  import computerReducer from './slices/computerSlice';
                  import infoSlice from './slices/infoSlice';
    
                  const store = configureStore({
                    reducer: {
                      deck: deckReducer,
                      pile: pileReducer,
                      computer: computerReducer,
                      player: playerReducer,
                      info: infoSlice
                    },
                    enhancers: [reduxBatch]
                  });
                
    I'm now able to group actions affecting multiple slices together (simply by supplying an array of those actions to store.dispatch()):
    
                  import {
                    addCard as addCardToPile
                  } from '../store/slices/pileSlice';
                  import {
                    removeCard as removeCardFromPlayer
                  } from '../store/slices/playerSlice';
    
                  ...
                  card = cardToPlay();
                  store.dispatch([
                    removeCardFromPlayer(card.id),
                    addCardToPile(card)
                  ]);
                
  2. esm: During development, I would sometimes write test code to try out some ideas, and I wanted to run this code from the terminal/command-line like so: node ./debug.js. My test code was written with the import/export module syntax (to inter-operate with the redux code) but this syntax is not supported by node (v14) by default. When you launch the react app, react's scripts take care of the ES6 import/export syntax for you, but if you run directly from the command-line, you'll need your own solution. This is where I found the 'esm' package to be immensely helpful. After installing the package: npm install --save-dev esm, it was easy to run my debug code: node -r esm ./debug.js. (Eventually I migrated these debug scenarios into jest tests.)
  3. cross-env: When playing the react/UI version of the game, after the player puts a card onto the discard pile, you need to insert a delay before the app/computer plays, so that the user is able to observe these two separate events. However, for debug/testing purposes, I also wanted to retain a version of the code that runs without those delays. I used an environment variable to enable/disable the delay. React can read in environment variables either from the shell or a .env file. As outlined in the react docs, the command for configuring a temporary environment variable via the shell is different for windows vs linux/mac. Here cross-env was able to provide a cross-platform solution. Here's a snippet of my package.json showing how I use cross-env to run the tests without delay (and also run a command-line/terminal version of the game).
    
                "test": "cross-env REACT_APP_POST_PLAYER_DELAY=0 react-scripts test",
                "cmdline": "cross-env REACT_APP_POST_PLAYER_DELAY=0 node -r esm -r dotenv/config ./scripts/playGame.js"
              

: Redux

Following my bootcamp, when it came to learning new technologies, I would just follow my interests. After some months of interviewing and job applications, I decided to change course. To narrow the gap between what I learnt at the bootcamp versus what employers are looking for, I decided to be more strategic with my learning objectives. Here's my new priority list:

I previously did a Data Structures and Algorithms course on Udemy, but I've found it wasn't comprehensive enough, so I'll likely do another course in the near future. I've also taught myself some of the jest framework, but I feel as though I've only scratched the surface, so I'd like to explore testing in more detail going forward.

Today, I crossed Redux off my list! I did the Redux Essentials Tutorial (twice), as well as the Redux Fundamentals Tutorial. Next I refactored my previous Reading List project to use Redux.

: My First Open Source Contribution!

I recently reached out to a recruiter for advice on breaking into the web development field. One of her suggestions was to contribute to open source projects. I had seen this advice before, but it did seem a bit daunting.

By chance, in the previous weeks, I discovered an opportunity where I could make a contributuion. One technical assessment for a job application involved having to learn a new technology: webdriver.io. The WebDriver test framework allows you to programatically control the browser, simulate user input, and write assertions for the presence or absence of various components on the page. (It has other features, but these were the features I used for the assessment.) WebDriver can be used in association with the following test frameworks: mocha, jasmine, and cucumber.

As a newbie to WebDriver, I naturally started with a tutorial, but that's when I ran into an issue. The sample test that's included with the jasmine framework fails! After some research online, I was able to fix the test by changing two lines in the test file. That's when I initially began thinking of contributing a fix. Fast forward to the advice I received from the recruiter, and I decided to start working on the contribution sooner rather than later. Also, if the issue gets fixed, fellow newbiews like me can have a much smoother on-ramp learning WebDriver (with the jasmine framework). (As a side note, after having read their contribution guidelines, the WebDriver community has designated various issues as 'first-timers-only' or 'good first pick', so that's another option for finding a beginner friendly contribution to work on.)

Initially I thought, two lines of code, how hard can it be? It turned out to be a bit more involved. The sample tests are generated from a template. One template was being used to generate a test for both the mocha and jasmine frameworks. The mocha test was fine, only the jasmine test fails. So, my fix involved creating separate templates for the mocha and jasmine frameworks, and then adding the code changes to the jasmine template. I also had to modify the existing test of this feature as well as add a new test.

Yay! My first open source contribution!

: Udemy’s The Coding Interview Bootcamp: Algorithms + Data Structures

This was a good course on Algorithms and Data Structures (in JavaScript), for anyone that's interested. One interview I had (before taking this course!!) did ask questions that were covered in the course. So it could be a helpful part of your technical interview prep.

You can view my certificate of completion here.

: Quote Catalog Android Kotlin Edition

I was always interested in mobile app development ... I have a few app ideas I hope to complete in the near future. A friend also suggested I learn Kotlin. So I decided to jump in. I did the Kotlin Bootcamp for Programmers, followed by Android Kotlin Fundamentals. It turned out to be much more intensive that I had expected ... it was like doing a full bootcamp all over again! Having started, I decided to follow through.

To test what I learnt, I re-implemented all the features of my Quote Catalog application (with the exception of multi-user login). This task was of sufficient complexity that I got to exercise many of the techniques covered in the lessons as well as some that were not (such as permissions, changing the app icon, and writing to the filesystem). This was my very first Andorid application, and I was pleased with how it turned out. However, I’m not as proficient in Kotlin as I’d like to be, so I’ll continue working on that.

If you have Android Studio, you can download the code and try it on a phone that’s in developer mode.

: Quote Catalog

Quote Catalog was the result of a pre-interview technical challenge for a job application. The task was to build an image browser. At the same time, I took the opportunity to test out some new technologies.

For one of the bootcamp assignments, we were given some code, and our task was to explain how it worked. That code made use of passport.js. In the process of completing the assignment, I was able to document how passport.js could be used for user authentication, however I didn’t write any code that used passport.js. So now, this was my chance.

Also, having completed the MongoDB developer courses a few days earlier, I wanted to use the MongoDB driver in this new project as well.

So I created a MERN (MongoDB, Express.js, React, Node.js) full stack application that allowed users to create, browse and search images of text quotes.

: MongoDB University's Developer Learning Path

This was my first post-bootcamp endeavour. During the bootcamp we were introduced to MongoDB via Mongoose.js. Mongoose is a thin layer on top of MongoDB. Mongoose adds Models, schemas, and validation. With Mongoose, you use a schema to define a Model. The Model represents your data collection. An instance of the model represents one document in your collection. It is possible to do schemas and validation using the underlying MongoDB, but it’s optional; with Mongoose, it’s included in the box (so to speak).

What I was noticing however is that you need to know some of the MongoDB syntax to use Mongoose. It’s not a full replacement. So naturally, I asked why? I googled it and read some blog and stackoverflow posts discussing Mongoose vs the native MongoDB driver. (I’m guessing that the intended migration path is actually from native MongoDB to Mongoose.) Once the bootcamp was over I decided to dig into MongoDB a bit deeper.

MongoDB has a (free) developer learning path consisting of 6 courses. Afterwards you can take a (paid) certification exam. Having taken the courses, I would say, if you want to learn just enough native MongoDB for a project, taking all 6 courses would be overkill. M001, M121, and M220 should be adequate for that purpose. However, if you have some spare time, the remaining courses do raise some topics that are helpful to know in the long-term, like how to make the best use of indexes, considerations for modeling your data, and why the default MongoDB deployment is a cluster of 3 machines.

You can view my course completion certificates via the links below.

While my initial intention was to follow-through with certification, after an admittedly poor technical interview performance, I decided to put studying for the certification on hold and instead focus on preparing for technical interviews.

: Bootcamp Completed!

The end of a 3 month bootcamp ... and the beginning of a new path as a web developer!