DEV Community

Cover image for Refactoring a video player using reveal module and command pattern in JavaScript
Carlos Caballero
Carlos Caballero

Posted on • Updated on

Refactoring a video player using reveal module and command pattern in JavaScript


Originally published at www.carloscaballero.io on January 11, 2019.


Today, I’m going to show a basic code in which a video player is done using a
few good practices to develop code in the present days in the JavaScript
language. My intention is show step to step the process from the original code
to the finish code using several classic patterns such as RevealModule and Command.

So, the initial code is the following:

The result of our code is the shown in the following image.

USE INTERNATIONAL LANGUAGE TO CODE: ENGLISH + PRETTIER

The first step in any code of this world is use the international language of
coding. Today the mainstream language is English, I know that the other
languages such as Chinese or Spanish are top trending language but really is
more easy understand a code which is written in English. I’m Spanish-native and
for me is more difficult write and speak in English but I know that if I write
my code in English I can share my code with the world.

So, the first step is translate my code to English, It is not required a perfect
English because the majority of the audience is not English-native.

Another important and basic tip to code is use a tool which normalize your code
because there is not relevant the spaces or tabs in your code, the number of
characters which use in each line or the way in that your create a new object
but there is very important that you always do this task the same way. I.e,
you need normalize your code with you and your partners. The best tool in the
Web develop ecosystem today es Prettier.
So, I recommend you that you install this tool in your favorite IDE (in my case
I’m using the extension in VSCode).

Now, you can read the code using an international language and using a tool
which formatted my code:

The GitHub project in this branch is https://github.com/Caballerog/refactoring-js-patterns-tips/tree/01-international-code.

VARIABLE SCOPE — REVEAL MODULE PATTERN

There is very important that you know how variable scope works in your language
because you can avoid effects side in the future and to do your code more
cleaner and readable.

In JavaScript there are 4 way to define a variable and the main difference
between those way is the scope of the variable. In the following links you can
read about this Vojtechruzicka Blog, Stackoverflow QAand Andy Carter Blog but a brief summary could be the following:

  1. Only write your variable in any place of your code. This is the worst way to declare a variable. In this case, the variable has a scope GLOBAL in your app (OMG!! since a private function are you defining a GLOBAL variable) which can provoke side-effects and several conflicts in your code. So, never declare a variable without a keyword.
  2. Use the keyword var. Using the keyword var you have hoisting and functional scope. Your variable can provoke side-effects inside a function because the variable is define in the top of your code (in your function) and there is in any place inside your function and the value is assigned in the line of code in which you are initializing your variable.
  3. Use the keyword let/const. This is the way in which ES6 and the community prefer used to define the variables because the scope of this variables is block (as you expect it to behave because most languages using a block scope) but the main different between let and const is that the pointer of memory in which is store the reference of the value of the variable can change or not (OMG!). In other words, let is used to variables in which the value can change in the code and const is used when the value of the variable can not change if the type is primitive (number or string) and can the pointer of the value can not change if the type is not primitive, for example objects and array.

Ok, in this moment I know that I should change the way in which I’m defining my
variables in JavaScript. So, the code would be the following:

The global variables that was define in the init function are moved to the top
of the script and use the keyword const because of there are references to the
DOM or a primitive value such as max. Also, there is a variable called loop
which is used to store the reference ID using returned in the setTimeInterval
function.

At the moment, both code are the same behavior because the variables were global
and in this moment are global too. For this reason, we could use the pattern [Reveal Module (https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript) which allow create private scope to the functions and variables. This pattern can be read in this blogpost.

The pattern module reveal allow us convert in public our interface of
communication with the other pieces of the code. In this case the methods
init, click, and move. The method state now has the scope of our module
which is called player. The rest of variables are private too, so there, we
just to avoid side-effects provoke for the global scope of our variables or
methods.

The code with applying this pattern is the following:

But the code below there is not works due to, the pattern module reveal is using
a IIFE which run before that the DOM is loaded, so the variables media,
play, etc. are nullwhen the script run for these lines. The solution is move
the definition of this variables inside the method init, but in this refactoring
we going to create a object called GUIwhich store the information about the
DOM (in large apps this object would be translate to other files using the
famous pattern
MVC.

So, the final code in this step is the following:

The GitHub project in this branch is https://github.com/Caballerog/refactoring-js-patterns-tips/tree/02-scope-module.

CREATE CONDITIONAL METHODS

The following step to avoid complex in our code consist in create functions
which abstract your complex logic in simple and readable functions to take
decision about of different states.

For example, the logic from the conditional sentence can be extract in short
functions using the prefix “is” to express that the function return a boolean
value.

The code could be the following:

The GitHub project in this branch is https://github.com/Caballerog/refactoring-js-patterns-tips/tree/04-create-conditional-methods.

The next step can be extract code in readable pieces of code (functions) which
add semantic value in our code. Thanks to this decision we can think about the
goal of our application. So, the method click and state can be refactor in the
following methods:

Refactor code

The GitHub project in this branch is https://github.com/Caballerog/refactoring-js-patterns-tips/tree/05-short-methods.

COMMAND PATTERN

In this moment, the code is a bit confuse because we are using if-else to use a
function which to do a action or command. There is a classical pattern called
Command which allows us abstract our actions/commands in an object. This
pattern is more complex in its traditional version but in JavaScript we can
implement this pattern using an object which receive a key to indicate the
action to do.

So, the first step is define the commands/actions, to simply the code, this
object is define in the same player.js.

The actions are Play, Pause, State end and State
Playing. The command pattern consist in execute a method or action using this key (in our example there is not required parameters), therefor the command object is the following:

Now, the moment in which the if-else dissapers using the pattern command:

The GitHub project in this branch is https://github.com/Caballerog/refactoring-js-patterns-tips/tree/06-command-pattern.

RESUME

In this example I’ve done several changes to improve the quality of my code. The
quality of my code is not relational with performance but also about the
readable and extensible. The following list is a resume about the different
techniques which I’ve been applied in my code.

  1. International Code. Never programming using your local language, unless your local language is English. Nowadays, the international language is the english. So, you must develop your code using english. Imagine a code in German or French or Polish and you don’t know that language!
  2. Prettier + CommitLint
  3. Variables Scope. Study in your language how the scope works in the declaration of variables. In JavaScript must understand that there are 4 ways to define a variable and its scope is totally different.
  4. Create conditional methods. Refactor your condition in functions which abstract your complex logic in a simple and readable function.
  5. Create short, simple and readable functions. Extract code in reusable functions or, at least, add semantic value in your code.

The GitHub project is https://github.com/Caballerog/refactoring-js-patterns-tips.


Originally published at www.carloscaballero.io on January 11, 2019.


Oldest comments (0)