Class Instantiation Patterns


Class Instantiation Patterns

While Javascript does not have classes in the way that most other languages do, it does provide class-like functionality through several different instantiation patterns. I will provide a brief description and an example for four instantiation patterns.

Functional

This pattern provides the easiest to read format, particularly to those who are not as familiar with Javascript syntax.

var animalMaker = function(name,age,height){  
  var newAnimal = {};
  newAnimal.name = name;
  newAnimal.age = age;
  newAnimal.height = height;
  newAnimal.say = function(){
    console.log("My name is " + newAnimal.name);
  };
  newAnimal.setHeight = function(height){
    newAnimal.height = height;
  };
  return newAnimal;
};

Functional-shared

Similar to functional, the main difference is that each new instance points to the same method objects, hence the ‘shared’ distinction in its name. The advantage is that if you conduct a large number of instantiations, you will not unnecessarily take up additional memory.

var animalMaker = function(name,age,height){  
  var newAnimal = _.extend({},animalMaker.methods);
  newAnimal.name = name;
  newAnimal.age = age;
  newAnimal.height = height;
  return newAnimal;
};

animalMaker.methods = {};

animalMaker.methods.say = function(){  
  console.log("My name is " + newAnimal.name);
};
animalMaker.methods.setHeight = function(height){  
  newAnimal.height = height;
};

Prototypal

Prototypal provides several distinct advantages compared to functional and functional-shared. Because it takes advantage of the prototype property, it allows you to add and edit methods for all instances of a class at any point in the program, not just when you define the constructor. Like functional-shared, all of the instances in a class will point to one object for its common methods and properties.

var animalMaker = function(name,age,height){  
  var newAnimal = Object.create(animalMaker.prototype);
  newAnimal.name = name;
  newAnimal.age = age;
  newAnimal.height = height;
  return newAnimal;
};

animalMaker.prototype.say = function(){  
  console.log("My name is " + this.name);
};
animalMaker.prototype.setHeight = function(height){  
  this.height = height;
};

Pseudoclassical

In terms of functionality, pseudoclassical is the exact same as prototypal. It provides more magic by utilizing an implied this = Object.create(prototype) and then returning ‘this’.

var animalMaker = function(name,age,height){  
  this.name = name;
  this.age = age;
  this.height = height;
};

animalMaker.prototype.say = function(){  
  console.log("My name is " + this.name);
};
animalMaker.prototype.setHeight = function(height){  
  this.height = height;
};

So which one should you use? 
When I first learned about these four instantiation patterns, my initial gut instinct was to ask, “so which is the best one on some XYZ technical measure?” The truth is, when it comes to deciding which instantiation pattern to use, there’s a whole set of reasons why one is used over others, without strong technical rationale.

So in terms of hierarchy, this is how I believe you will pick your instantiation pattern:

  • Because someone (more senior than you) told you to - Let’s face it, if your technical lead picks any of the four instantiation patterns, it’s unlikely that an impassioned argument for another pattern will result in switching patterns. Picking one consistent instantiation pattern is more important than any alleged technical advantage will provide in using multiple patterns.
  • Pseudoclassical because it’s the industry standard- Many tech companies (if not most) who use javascript significantly will prefer the pseudoclassical instantiation pattern. The initial popularity of pseudoclassical was due to its early introduction in the language and its syntactic familiarity for programmers that come from other languages that have robust class functionality. Because pseudoclassical has been popular for so long, browsers have optimized their interpreters to run pseudoclassical the fastest. Even though prototypal and pseudoclassical are exactly the same functionality-wise, pseudoclassical has received special favor and runs even faster than prototypal.

Disciplined software engineering


The 12-factor App Manifesto

I've been reading this online guide called 12-Factor App that's been written by Heroku.

I recommend taking a look as it essentially lists a series of best practices that web development and ops teams should follow.

As I'm reading through the list, one of the things that strikes me is that following these best practices require significant discipline. For example, the principle of explicitly declaring dependencies sounds like a no-brainer, and nobody would really disagree about the importance of doing so. But they use the example of curl as a system dependency that you should not always assume exists on your various environments.

So in addition to being thoughtful during the development process, it's important to run through these principles in a deliberate way in order to make sure you're not accidentally violating one.

Can checklists save lives?

One way of doing that is creating a checklist and having yourself or another team member, run through the checklist carefully at particular milestones (e.g. after each sprint).

While I was in consulting and focused on healthcare, I came across a book called Checklist Manifesto by Atul Gawande. While the book focuses on the application of checklists in healthcare, Gawande highlights several lessons that are relevant to other disciplines including software engineering. One takeaway is that checklists, when designed well, can dramatically improve performance and reduce errors. As a surgeon and researcher, Gawande led a wide-scale research effort to document the effectiveness of using checklists for surgeries. In various hospitals across the world, the bottom line was that complications and fatality dropped significantly.

In spite of the concrete evidence that checklists can save lives when used in the surgery room, there was tremendous pushback from clinicians in actually adopting it in daily practice. Gawande explores various reasons of why this is, but the main reason is that suggesting the use of a checklist is in some ways seen as a criticism of the ability of a clinician. The thought goes, after years of medical school, residency, and practice as a physician, of course I know how to administer a routine heart surgery. But the fact is, because heart surgery is a complicated task that requires many handoffs between team members, there are many ways an error of omission or commission can occur.

Checklists for software engineering

For us software engineers, we probably have a similar adverserial reaction to the idea of using checklists in our daily work. After all, don't we have computer programs that never accidentally forget something? The truth is, we still need to use checklists for various activities in software engineering. Sure, your function might perform the exact same action each time you run it, but how do you know you designed it properly or accounted for edge cases?

Writing automated tests is oftentimes seen as the solution for catching bugs in software development, but the problem is that it requires writing the appropriate tests, which is oftentimes more difficult than writing the code to pass the tests itself. Test-Driven Development has gained popularity in industry because studies have shown that it can dramatically reduce the number of errors in a program.

To be clear, writing tests is certainly a good thing and should be done to ensure a program is ready for production, but there should also be checklists to help you make sure that you're writing the right tests. Beyond testing, other aspects of software engineering, such as git workflow could benefit from checklists. As a software engineering team, it is vital to be following the same git workflow, otherwise the commit history will become a mess, or worse there will be unnecessary merge conflicts that make it a pain to work on the repo.

Just as a running list of ideas, these are some places that we can use checklists:

  • Writing unit tests
  • Configuring servers / deployment (which should be done using configuration management tools)
  • Git workflow
  • Agile / Scrum practices (e.g. overview of a sprint workflow)
  • Setting up a development environment across team members (using a tool like Vagrant to automate it)

In a couple of these cases, you can see that I'm not advocating regular ol' checklists with checkboxes, but rather advocating for a systematic method or tool to consistently do a repeated task. While this may seem like an obvious point, but one of the greatest benefits of utility programs (in addition to saving time) is that it reduces the potential for cognitive error. Even though our work revolves around creating these automated programs, there are many aspects where our work involves manual steps that require human intervention and decision-making.

By insisting on using checklists or automated tools where appropriate, we can eat our own dogfood and become better software engineers.

Docker Generator - Revised Idea

After pitching this idea to my classmates at Hack Reactor, I've received some helpful feedback on the Docker Generator.

Summary:

Docker Generator enables developers to quickly setup containers for a new or existing project in their development and production environments.

The goal: make deployment simple and painless.

Considerations:

  • There are already a handful of open-source projects that use Docker containers to create a PaaS (e.g. Heroku) to simplify deployment
  • Consensus that SOA (service-oriented architecture) is a good design pattern for many cloud-native applications as it scales well
  • Spinning up Docker containers and deploying them the first time can take significant effort (learning Docker CLI commands, configuring the containers to ensure security, running Docker on a Linux-OS VM using Vagrant, etc)

Ideas:

  • Focus on a simple, interactive command line interface that allows developers to pick basic settings, choose the number of containers to spin up, and deploy it to a cloud provider
  • Decoupling the tech stack with the deployment script used. One of the issues with Yeoman generators is that they typically include easy one-command deployment for a couple cloud providers (whichever are the author's favorites). This means that if you use another cloud provider, it can be quite challenging to initially deploy the scaffold. Since a container by definition abstracts its innerworkings, it should be the same to deploy any container
  • Base container images - These are basic starting points for various services (e.g. express server, mongodb, redis) that will be used
    • Many of these container images likely already exist on Docker Hub or another image registry. If we can vet the quality (e.g. works and is secure), then we source these in the CLI utility
    • One challenge will be connecting the various images together
    • There may be one container that acts as the master / controller node and coordinates the other nodes (need to research further)
  • Deployment plugins - Simple shell scripts (or use a tool like Ansible) that are configured specifically for various cloud providers
    • Big 3: AWS, Azure, Google Cloud
    • Others: Heroku, Digital Ocean, Red Hat, etc
  • Fitting into the Docker / container ecosystem: Use well-established tools such as Ansible, CoreOS, Vagrant, and VirtualBox.

Roadmap for Learning Javascript and Web Development

Learning programming is oftentimes seen as a daunting task, and it's understandable.

After all, as soon as you begin learning a little bit about programming, you start reading on Stack Overflow or some trendy programming blog that you should start using library XYZ to do functional programming in Javascript or you should avoid ever doing ABC method because it's time complexity is inferior to DEF.

The following list of resources is designed for somebody who has never done programming before. The goal of this roadmap is to get you comfortable with creating full-stack web applications.

Going from no programming knowledge to basic understanding:

  • Code Academy provides a very gentle introduction to programming. It's simple gamefied interface is a good starting point. I would recommend only doing the Javascript track for now. For now, I would ignore the jQuery course. This will help you get down the basic syntax of Javascript.

Javascript foundation

  • Code School offers a combination of videos and interactive coding challenges. Overall the instruction material is better than Code Academy, but it also costs money ($30/month, the last time I checked). Many of their Javascript courses are quite good, but for now I would recommend just doing these two:
    • Javascript Roadtrip Part Two - I purposefully left out Part One because it's mostly repetitive with what you learned in Code Academy.
    • Javascript Roadtrip Part Three - At this point, some of this should feel quite challenging
  • Coder Byte has interactive programming challenges that you can solve in your browser. At this point, you should be able to tackle some of the easy problems. Some of the easy problems will feel much harder than the other easy problems. If you have trouble remembering syntax, simply try pseudocoding your answer first. Basically, write in comments, your explanation of your approach in english words. As you get more and more comfortable, it will become easier to translate your pseudocode to actual working Javascript code.

Intermediate Javascript:

  • Object-oriented Javascript by Hack Reactor @ Udacity: Hack Reactor recently co-developed with Udacity a programming course on Javascript. This covers some of the content from the first two weeks of Hack Reactor's full-time bootcamp program, and from what I have seen, looks very similar to what I received from the Hack Reactor on-site program in SF and is high-quality. I would just do the free version of the course.
  • Eloquent Javascript is a widely recommended book for learning Javascript and luckily there's a free official version online that you can read. I don't think you need to read this cover to cover, but if there are any concepts that you find confusing, this is a good resource to use.
  • You Don't Know JS book series provides really nice explanations for some confusing Javascript concepts. Some of this may be overlapping with the Udacity course, so again use this more as a resource than something to read cover to cover.

At this point, you know more of the core concepts of Javascript than most programmers using Javascript. This is more frequent than you'd expect because a lot of people learn Javascript in a haphazard manner.

The goal at this point is to create a simple to-do web application using jQuery, but first you'll need to learn some HTML and CSS, which are easier to learn in Javascript (although they might be more frustrating to use later on!)

Learning HTML / CSS: Remember, the key is to learn basic HTML and CSS. Timebox yourself to 6-8 hours learning the material and then start working on creating a simple to-do application.

  • Try jQuery @ Code School is a free course on Code School. It'll take a few hours to complete, but will be immensely useful.
  • Learning HTML and CSS can be a rabbit hole. There's a lot of nuances to pick up along the way, but because they're not programming languages I think it's fine to learn them in a less structured basis and more of a need-to-know basis. Resources for learning them:
    • The HTML & CSS book by Jon Duckett is the most popular book on Amazon on this topic. Again, I would skim through it. The goal is to create a simple interface, nothing very fancy.
    • Team Treehouse offers interactive tutorials (videos and coding challenge) similar to Codeschool. The biggest difference is that I think Codeschool has more rigorous programming instruction, but Team Treehouse has more web design-type content.

Creating a simple to-do application: So you have learned HTML, CSS, and Javascript and have done a bunch of short coding challenges. The key is to apply all of it in a sort of realistic web application. What better, than to create a to-do list application. There's a whole website dedicated to various implementations of the to-do list using different Javascript libraries.

Your app should allow the user to:

  • Create a task
  • Delete a task

Future sections to include:

  • Algorithm & data structures
  • Deployment
  • Learning Git
    • Codeschool
    • Interactive tutorial?
  • jQuery to Backbone tutorial (MVC)
  • Node.js (codeschool)
  • Express (codeschool)
  • Database
    • MySQL
    • MongoDB / Mongoose
      • Recommend the Amazon book on Mongoose

Docker 101 - and how it can make shipping apps easier

Docker is an interesting technology that is very new and recently released version 1.0. The story behind it is that the founder Solomon Hykes ran a Platform-as-a-Service (PaaS) company a few years ago and wanted a convenient way to allow customers to ship their application to his PaaS.

In a couple of the talks I saw on Youtube by Solomon, he empasizes the reason for the rapidly growing popularity of Docker is due to a much larger underlying trend which is that consumers expect apps (web and mobile) to act like the Internet / cloud. That is, apps should always be available, quickly accessed anywhere around the world, and deliver a consistent experience.

At the same time, development shops have oriented themselves around service-oriented architectures (SOA) and creating loosely coupled components. Instead of having a monolithic stack, today's web apps are being built on top of a myriad number of choices.

To make a long story short, what makes Docker so appealing is that it attempts to bridge the gap between your dev server (e.g. laptop) and your production servers (e.g. hundreds of instances on AWS / Google Cloud / Azure / what have you). Instead of trying to spin up VMs and configuring them so they are 'normalized' (which is difficult to do because they may be running slightly different versions of the OS and have different dependencies installed), you create containers, which contain the dependencies, the settings, and the application itself. In fact the container runs on a copy of the host OS.

Unlike traditional virtualization (VM), where the host OS contains a hypervisor that spins up multiple guest OS, there is only one OS when using containers.

So why choose Docker? Well, there's (at least) 3 different choices you can make.

Docker

  • Pro: Provides a replicable, normalized environment that you can deploy to a wide variety of machines
  • Pro: By using a versioning system like Git, only the incremental changes need to be sent to update a container. This means you don't need to send large VM files
  • Con: Technology is less mature than other solutions, less documentation and support on using Docker (although this is quickly changing as more developers get excited about using it)
  • Con: Security is a concern as you are sharing the OS and underlying binary files.

VM

  • Pro: Ensures maximum consistency between one environment and another. (In essence you are deploying the same machine on multiple physical boxes).
  • Con: Sending enormous files (you are including an entire OS) takes up a significant bandwidth and sending a large payload may overwhelm the production environment that you are trying to upload to.
  • Con: If you need to run many VMs because you have many services for your app (particularly if it's complex and you follow a loosely-coupled SOA paradigm), it can easily overwhelm your Macbook dev machine.

Configuring Production Environments Manually / Using Tools

  • Rather than listing the specific pros and cons as there are a wide variety of ways to accomplish this, the biggest takeaway is that this is an uphill battle as you are trying to normalize environments across many machines. Even if you use an automated tool, it's still hard to ensure that these environments are normalized. And even with automation, there are still instances when you are manually SSH-ing into a production server to make changes because something isn't working properly.