Skip to main content

My top tips for junior developers

Last year, I was tasked with mentoring an intern. It wasn't my first time mentoring, but it was my first time being fully in charge of a new employee. In the end, the intern was hired as a full-time employee, and I thought it would be helpful to compile all the advice I've been giving them, for future reference.

The following tips come from my experience and my way of working, as well as my own personal opinions.

Tip 1: Learn how to search effectively

Knowing what to search and how to search is an essential skill. Usually, I don't remember or know most of the things my colleagues ask me. Yet, after 5 minutes I can usually figure it out or at least point them in the right direction. All thanks to the power of search.

How to search

As with most things in life, Google will probably have an answer for you. Make sure to type it in a way that makes sense for Google. For example, if you have an error, copy-paste it word-for-word and put it inside double (") quotes. This might take you to Github issues, Stack Overflow answers, or blogs like this one!

If you don't find anything, try different variations of your search. You can try removing specifics (line numbers are often useless, and also data values). For example, if you get an error like this:

TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number. Received type string
    at validateNumber (internal/validators.js:130:11)
    at validateTimerDuration (internal/timers.js:146:3)
    at ClientRequest.setTimeout (_http_client.js:735:11)
    ...

You could be searching the following instead:

TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number. Received type string

If that's still too long, you can try only

The "msecs" argument must be of type number

If you still can't find anything useful, take advantage of your company's resources. Try the same search on your company's internal systems. Try everything: Slack, bug tracker (e.g.: JIRA), wiki, emails, Google Docs. If you still don't find anything, try reaching out to your more senior colleagues. They will surely know how to help or at least point you in the right direction.

How to navigate codebases

Sometimes your search will guide you to the source code that is throwing the error you were searching for. This is a bit sad since it means probably no one has found a solution yet for the problem you're having. In these cases you will need to read the code you found and try to understand it.

I think the best way to understand code is to see the flow of the data in the code. For example, let's say you have an app that let's you search movies by actor name.

I would first try to understand where the movie data is coming from. An external API? A database? A file?

Then I would see what happens when I type "Nicolas Cage" into the search box and click "Search". Does the app do an external network request? Is the data already available locally? If I search "Search" in the source code, will I be able to find the code for the button that triggers the search?

I would keep asking myself questions and answering them, until I have a better understanding of where the data is going to and coming from.

How to deal with Github issues

You might get lucky and find someone that had the same issue and opened a Github issue for it. If you're even luckier, someone else (or the original reporter) might have found a solution and shared it there. Then, the repository's maintainers may have merged the solution. Or maybe not yet.

If you don't want to wait for the repository's maintainers to merge the fix, there's always the option of forking the repository and merging the fix yourself. This is usually not a good idea unless you need this fix very urgently, since your fork will quickly become outdated. It's up to you and/or your team to decide if this is worth the risks.

Tip 2: Don't copy-paste code without understanding it

I have noticed way too many junior developers copy & paste code without understanding what it's doing. I've been guilty of this as well but I don't remember it, maybe because I rely on copy-pasting so much!

The problem with this: it can cause unintended consequences. If the copy-pasted code breaks you will not know how to fix it since you didn't understand it in the first place. This means sooner or later you will have to come back to this code and understand it.

If you are doing unit testing (which you should), you will need to understand the code first, to be able to write tests for it. You will need to identify every execution path it might take and think about the inputs that might break it.

One thing that has worked for me is to avoid copy-pasting the code and try to write it on my own. Grok what the code is doing and writing it using variable/function/class names that match your project and business logic. Once you have done this you might understand it a bit better.

Tip 3: Know your tools

With tools, I mean everything that helps you get your work done. A few examples:

Shell, text editor, IDE, compiler, package manager, version control, CI/CD (continuous integration/continuous delivery).

Notice I am using the generic terms and not the specific tools you or your company might be using. Why is that? Because you should be able to pick up tools and work with them.

To have a good productivity, you need to become familiar with the tools used by your colleagues, so make sure to ask around for recommendations.

In some cases you will need to use tools that you don't necessarily enjoy using, and that's okay. Tools are a means to an end. Tools should help you build your final product. They should not be your main focus - unless you work for a software company that builds software development tools.

Here are some of my favorite tools at the moment:

  • Bash
  • Visual Studio Code
  • IntelliJ IDEA
  • yarn
  • Git
  • Gitlab CI

Why are they my favorite tools? Because I'm used to them. Only looking at them, many developers will know I am primarily a frontend developer. There's always going to be something better and everyone has different preferences. But it doesn't matter, as long as the tools help you get the job done. Still, always be open to new tools and ask other people why they chose theirs. They might change your mind and you will become even more productive! A good way to quickly get to know a tool is to do a search like this: "<tool> tips and tricks".

Know your programming language(s)

It's also very important to know all the fundamental concepts of the programming language(s) you are using at work. Again, make sure to ask your more experienced colleagues for recommendations. There are tons of books, online courses, and tutorials for every mainstream programming language out there.

You need to be fluent in your language. This will allow you to focus on solving the business problems instead of fighting against the language to make the code work. You don't have to be an expert immediately, it will take time. But make sure to keep learning and aim to become an expert in the language within the first two years of your career.

Tip 4: Know how and when to ask for help

When you are new, you will have a lot of questions, and that's okay. Asking questions is how we learn.

Ask yourself first

Before you ask the question to someone else, ask it to yourself. Then try to come up with a few guesses and try to validate them. This will lead to more and more questions.

This helps you understand what you really need to know to solve the problem, and when you go to someone else you will have a much better question to ask. Good questions breed good answers.

For example, let's say you have to change the href of a link in the footer of your company's website. I would ask myself: "where is the code for this link?"

Then I would come up with a few hypotheses:

  • I can find it if I search for the current href on the codebase.
  • If I change it here and deploy the code, the link will change.

After that, I would try to prove my first hypothesis by searching for the current href. Let's say I could not find it in the code. Then I would come up with a different hypothesis:

  • It is not in the code, so the content must come from somewhere else.

Then I would ask myself more questions:

  • Where is the content for the footer stored?
  • How can I change it?

Once I have these questions, I can go to a more experienced colleague, and they will be able to quickly point me in the right direction: "Oh, that content is stored in our content management system. I will show you how to change it".

If I had asked them my first question instead: "where is the code for this link", they would have given me a very simple answer that would take me straight to the code and that would have not been as helpful.

Fighting forgetfulness

I am very forgetful, so I like to keep notes. Whenever I find the answer to a an important question, I make sure to write it down somewhere. This has several benefits:

  • You don't need to remember everything.
  • You can share your notes with others (this is usually called documentation).
  • You can easily keep track of how much you have learned over time.

You can keep your notes on paper or digitally. Make sure to try both and see what works best for you.

Tip 5: Maintain a healthy work-life balance

When you're starting out you always want to keep learning more and more while also delivering your work. This means you will probably work many hours a day if you're very passionate. This is fine if you are enjoying yourself, but you should be careful and aware of burn out. A good way to avoid this is to have a routine you follow every work day, and make sure you have enough breaks throughout the day. In the end it all comes down to a matter of discipline and knowing yourself.

Remember life is about living, not about working! It's a good idea to have other things outside going on in your life aside from work. There's no right or wrong here because it depends on you, but make sure you manage your stress in a healthy way.

Starry Sky in HTML5 Canvas - Part 2

This is part of a series! Please make sure you have read Part 1 first!

IMPORTANT -- you can try out the result of this tutorial by visiting this CodeSandbox. However, I encourage you to read the blog post and try to follow along to understand how and why it works.

Last time we left off with a very nice starry sky, but it's a bit dead. We need to add some animation to it! The way animation is done on HTML5 canvas is by drawing something else every frame.

For our case, we can use the requestAnimationFrame() function to call our render() function.

First, we will add a counter variable. We will increment this every time we draw. This is useful because we will have a number that will change with every render.

let counter = 0;

Then, we will update our render() function so it uses requestAnimationFrame(). We will also make it increment the counter.

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star) {
    const x = star.x;
    const y = star.y;
    const r = star.r;
    fillCircle(ctx, x, y, r, "rgb(255, 255, 255)");
  });
  counter++;
  requestAnimationFrame(render);
}

For now, this will look exactly the same as before, because we always render the same thing. But let's begin to change that now.

We'll make a small change to make the stars look like they're flickering.

First, let's add a function to generate an opacity value. This value will go from 0 to 1 and will determine the opacity of our star.

The use of Math.sin() in the function below is just to make sure we get a value that changes smoothly.

const minStarOpacity = 0.1;
const maxStarOpacity = 0.7;

function getOpacity(factor) {
  const opacityIncrement =
    (maxStarOpacity - minStarOpacity) * Math.abs(Math.sin(factor));
  const opacity = minStarOpacity + opacityIncrement;
  return opacity;
}

Then, we will use this function when rendering our stars. Also notice how we change the color from rgb(255, 255, 255) to rgba(255, 255, 255, opacity).

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star, i) {
    // factor will be a different number for every star
    const factor = counter * i; 
    const x = star.x;
    const y = star.y;
    const opacity = getOpacity(factor);
    fillCircle(ctx, x, y, star.r, `rgba(255, 255, 255, ${opacity}`);
  });
  counter++;
  requestAnimationFrame(render);
}

Animated Starry Sky

Now the sky is looking really nice and animated. But it's still missing a nice big moon. Let's add it next.

We will create a function to render our moon, and call it from render().

const moon = {
  color: "#fea",
  x: height / 3,
  y: width / 3,
  r: 40
};

function renderMoon(ctx, blur) {
  fillCircle(ctx, moon.x, moon.y, moon.r, moon.color);
  // render a smaller circle above the moon to give it that well-known moon-shape
  fillCircle(
    ctx,
    moon.x - moon.r / 3,
    moon.y - moon.r / 3,
    moon.r,
    backgroundColor
  );
}

And our updated render() function:

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star, i) {
    const factor = counter * i;
    const x = star.x;
    const y = star.y;
    const opacity = getOpacity(factor);
    fillCircle(ctx, x, y, star.r, `rgba(255, 255, 255, ${opacity}`);
  });

  renderMoon(ctx);

  counter++;
  requestAnimationFrame(render);
}

That leaves us with the finished product: Animated Starry Sky with Moon

Thanks for following this tutorial to the end! Remember you can look at a working example in the CodeSandbox.

Have fun experimenting and tweaking the values used to render the stars and the moon. Some ideas you may want to try to learn more and improve your skills:

  • Make the stars more colorful.
  • Make the moon move across the sky.
  • Add shooting stars.
  • Add a gradient background instead of a solid color.
  • Add multiple moons.

Don't hesitate to contact me at @KaeruCT if you have any questions, suggestions, or improvements for this tutorial!

Starry Sky in HTML5 Canvas - Part 1

In my spare time I often enjoy creating visualizations using HTML5 canvas. I'm planning to do a little presentation about this so I thought a good way to get started was to create a blog post explaining how to do a simple one.

This tutorial will teach you how to create something like the image below from scratch!

Animated Starry Sky with Moon

IMPORTANT -- you can try out the result of this part of the tutorial by visiting this CodeSandbox. However, I encourage you to read the blog post and try to follow along to understand how and why it works.

First, you will need an HTML file, let's name it index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Starry sky</title>
    <style>
      body, html {
        padding: 0;
        margin: 0;
      }
      canvas {
        position: absolute;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas"></canvas>
  </body>
</html>

Nothing crazy so far, just some styles and a canvas element.

Next, let's create a JavaScript file. Let's name this index.js.

const backgroundColor = "#030318";
const width = window.innerWidth;
const height = window.innerHeight;
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
}
render();

In the code above, we set the canvas' width and height so it takes up the whole window. Then, in the render() function, we fill the canvas with the background color. If you run it on your browser, it will look like this:

Step 1

Yup. Not very interesting. Let's put something in there! Let's add some code to our index.js file to draw some stars.

First, let's have a function that creates the stars.

function createStars(width, height, spacing) {
  const stars = [];

  for (let x = 0; x < width; x += spacing) {
    for (let y = 0; y < height; y += spacing) {
      const star = {
        x: x,
        y: y
      };
      stars.push(star);
    }
  }
  return stars;
}

const stars = createStars(width, height, 30);

The spacing parameter will control the spacing between stars.

Then, let's update our render() function so it renders the stars.

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star) {
    const x = star.x;
    const y = star.y;
    const r = 5;
    ctx.beginPath();
    ctx.fillStyle = "rgb(255, 255, 255)";
    ctx.arc(x, y, r, 0, Math.PI * 2);
    ctx.fill();
  });
}

For our purposes, a star is a circle, so we can use the arc() function to draw our stars. An explanation of the parameters:

  • x and y are used for the position.
  • r is used for the radius of the circle.
  • 0 and Math.PI * 2 are the start and end angle, respectively. A full circle goes from 0 to 2pi.

The line ctx.fillStyle = "rgb(255, 255, 255)"; is used to set the color of the circle to white.

Let's see what we get now:

Step 2

It's definitely a bit more interesting. But it doesn't look like a starry sky at all! Stars don't usually look so uniform and boring. We need to add some randomness.

Let's create a function called randomInt(max) that will return a random number:

function randomInt(max) {
  return Math.floor(Math.random() * max);
}

Then, let's use these random numbers when creating our stars:

function createStars(width, height, spacing) {
  const stars = [];

  for (let x = 0; x < width; x += spacing) {
    for (let y = 0; y < height; y += spacing) {
      const star = {
        x: x + randomInt(spacing),
        y: y + randomInt(spacing)
      };
      stars.push(star);
    }
  }
  return stars;
}

Step 3

That looks already almost real! Now let's make it so the stars are different sizes. To do this, we will need a different radius for each star, so we will add it to the star objects.

const maxStarRadius = 1.5;

function createStars(width, height, spacing) {
  const stars = [];

  for (let x = 0; x < width; x += spacing) {
    for (let y = 0; y < height; y += spacing) {
      const star = {
        x: x + randomInt(spacing),
        y: y + randomInt(spacing),
        r: Math.random() * maxStarRadius,
      };
      stars.push(star);
    }
  }
  return stars;
}

Then, we will update the render() function so it uses the star's radius when drawing. While we're at it, let's extract the circle drawing logic to a new function as well.

function fillCircle(ctx, x, y, r, fillStyle) {
  ctx.beginPath();
  ctx.fillStyle = fillStyle;
  ctx.arc(x, y, r, 0, Math.PI * 2);
  ctx.fill();
}

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star) {
    const x = star.x;
    const y = star.y;
    const r = star.r;
    fillCircle(ctx, x, y, r, "rgb(255, 255, 255)");
  });
}

Step 4

Much better! Now the stars are all different sizes!

This is all for part 1. You can continue reading Part 2, where we will add a moon and make our stars flicker!

How to show preview images when sharing links of your website

When you share a link on social media or mesagging apps, sometimes the app shows a nice preview thumbnail with a description? You can click on it and it will take you to the linked website. I wanted to have this functionality for a website I was working on, so I did some research on how to get it working.

Short answer: use the og:image meta tag.

Longer answer: read on.

You have to use Open Graph meta tags. There's a bunch of meta tags to use, but the ones you need for previews are the following:

    <meta name="twitter:card" content="summary">
    <meta property="og:title" content="Thumbnail example">
    <meta property="og:description" content="Only for Nic Cage fans">
    <meta property="og:image" content="https://www.placecage.com/c/460/300">
    <meta property="og:url" content="https://kaeruct.github.io/">

When a website with the previous tags is shared on social media, you will get a nice preview card with thumbnail, title, and description.

Important points:

  • You NEED to include the twitter:card meta tag for Twitter to display the preview. Otherwise it won't work. If you don't care about Twitter you can remove it.
  • Some apps/websites will not include your preview thumbnail if it's not served via HTTPS. So make sure the image URLs always start with https://!
  • The og:url value should point to the canonical URL of the page, not to the root of your website.

Below you can see some examples:

Twitter

Twitter

Slack

Slack

Telegram

Telegram

WhatsApp

WhatsApp

Discord

Discord

Migrating old-style JavaScript code to ES6

Recently (at work) I had to migrate a medium-sized JavaScript codebase (20KLOC) to ES6.

We wanted to migrate to take advantage of the new features such as arrow functions, destructuring, and classes (there are a bunch more!). Additionally, I was tasked with introducing eslint and prettier to improve the quality of our code a bit more.

Before diving into the migration process, first I'd like to give some context on the state of the application.

We already used npm and webpack to build our frontend, so I thought the migration should be straightforward -- and it was.

I was heavily involved in modifying our build process to use npm instead of ad-hoc shell scripts, and I found this guide to be incredibly helpful.

Back to the migration, the first thing I did was to add babel to webpack using babel-loader. It was easy to add to webpack and took almost no time to set up. This meant that webpack would take our JavaScript files and transpile them from ES6 to "normal" JavaScript that all browsers can run. However, in order to get our mocha tests running, it was necessary to hook babel into our tests as well. I used this guide from istanbul and was able to get them running fairly quickly.

Once I ran the build and the tests and everything looked good, then it was time to really port our code to ES6. First, it was necessary to port some code that was using the module pattern to ES6 module syntax. I did this manually (using search/replace tools) and it took me a few hours.

In some cases we had some ugly dependencies on globals so a bit of refactoring was required. In cases where it wasn't possible, webpack has the ProvidePlugin, which covers most cases. I also found the expose-loader to be useful becase we have some code not under our control that required jQuery to be a browser global.

Once that was done, it was time to get started with the syntax changes. I found an amazing tool for that, Lebab. It is a very realiable tool and I would totally use it again. I ran all the "safe" transformations, verified them, and then ran some of the "unsafe" ones, checking how the code changed each time.

Finally, I ran the build and our mocha tests to make sure they still passed. The tests broke in a few places because of things like variables being shadowed because of the changes from var to let or const.

However, with the help of the no-shadow eslint rule, I was able to find all those cases quickly and get them fixed. ESLint was also very helpful in making sure I was not breaking any code with the refactoring I had to do.

The lines of code initially went down because of the ES6 syntax sugar, but they went back up with the introduction of prettier and its opinionated formatting -- especially regarding line length.

In the end, the migration was not as terrible as I initially thought it would be, and now it's a bit more enjoyable to work on that codebase.