Categories
Careers

More Ways to Make Money as a Developer

Software is a skill that not everyone has, and it is a useful one. Therefore, it’s a skill that’s worth money.

In this article, we’ll take a look at some ways that we can make money as a developer using our skills.

Consulting

We can use our experience to be a consultant for other businesses that need to implement some business systems.

The good thing about consulting is that we only need to worry about the high-level architecture of things and not have to worry about implementing it ourselves.

This is ideal for people that are tired of writing code every day and taxing our brains doing so.

It’s a breath of fresh air compared to looking at spaghetti code and hard to debug issues every day.

Also, it’s good for people that like to meet people since it’s the way to provide help in consulting is to meet people and listen to their needs.

It pays big potentially with less effort than being a developer in the short or long term.

To reach out to clients, we must build relationships with regular business meetings online or in persons.

Listening is also a very important skill since clients want us to listen to them so that we can give them solutions.

Audio or Video Podcast

We can use our development skills to teach others. If we’re making an audio podcast, then all we can do is talk.

However, it’s still a good way to talk about high-level stuff. As long as we aren’t trying to teach people how to write code, use libraries or frameworks or things like that, then audio podcasts are good.

If we’re trying to make tutorials, then we need to move to video. With today’s technology, anyone can shoot video with professional productional quality.

As we can see from video sites like YouTube, we see that many videos are as professional as television shows, except that there’re many more niche videos than on television.

On television, all we get are reality TV, dramas, and game shows, but online, we get useful tutorials for programming, cooking, and more.

We can make our own video tutorials online easily. Also, we can also make more entertaining videos as well.

Or we can make our tutorials entertaining.

Either way is a great way to build our personal brand. After posting the podcasts, be sure to post and promote them anywhere we can to gain exposure,

Otherwise, no one will know that our podcast exists and we won’t get much of an audience.

Online Shop

Another advantage of being a developer is that we can build an online shop from existing solutions or from scratch.

It’s better to build a shop using existing solutions so that we can gauge the interest of the public on what we’re selling before we get too far into it with coding.

Remember, coding the shop doesn’t make us money, so we shouldn’t spend all our time doing it if we want to make money.

If our shop takes off, then we can think about customizing it further or making our own online e-commerce system from scratch with our own code.

We can consider selling our own product that we can make for a low cost and sell for a high price.

Otherwise, we have to resell other people’s stuff, which means we need to pay for products upfront and hope that they sell.

There’s also drop-shipping, which we may want to consider. However, we should be aware that there’s lots of competition on that already since we don’t have to hold any inventory ourselves as drop shippers.

In any case, we have to promote it heavily and probably sell ads to promote our shop if we want to make money soon.

Conclusion

As developers, there’re lots of advantages. We can use our skills to become a consultant for other business. They can all use our technical knowledge to implement their business systems.

Also, audio and video podcasts are great mediums for us to share our programming insights to the world.

Finally, an online shop can also make us money if we promote it enough and gauge the interests of potential customers before making any big commitments.

Categories
JavaScript Design Patterns

JavaScript Design Patterns — Chain of Responsibility, Singleton, and Flyweight Patterns

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the chain of responsibility, singleton, and flyweight patterns.

Chain of Responsibility Pattern

The chain of responsibility is similar to the observer pattern, except that it sends the notification to one object, and then that object sends the notification to another object, and so on.

In the observer pattern, the notification is sent to all the observers at the same time.

For instance, if we send something to one object and then that object picks that up and does something with and send that to another and so on, then that implements the chain of responsibility patterns.

We can implement that as follows:

const backend = {
  receive(data) {
    // do something with data
  }
}

const middleLayer = {
  notify(data) {
    backend.receive(data);
  }
}

const frontEnd = {
  notify(data) {
    middleLayer.notify(data);
  }
}

In the code above, we have the frontEnd , which calls the notify method of the middleLayer object, which in turn called the backend ‘s receive method.

This way, we can pass data between them with one method seamlessly.

As long as we don’t expose any other methods that do communication between both objects, we have a clean way of sending data between frontEnd and middleLayer and backEnd .

Singleton

The singleton pattern is where we only instantiate one instance of an object.

In JavaScript, we can create objects with one instance by creating an object literal.

We can create one by writing:

const obj = {
  foo: 1,
  bar: 'baz'
}

An object literal is just sets of key-value pairs, where the value can also be other objects.

If we use classes, we can also write:

class Foo {
  constructor() {
    if (!Foo.instance) {
      Foo.instance = {
        foo: 1,
        bar: 2
      }
    }
    return Foo.instance;
  }
}

We assigned the created instance to the instance property of Foo .

Then when we create the constructor, we check the instance property to see if anything’s created for it.

If there’s nothing assigned to it then we assign an object to it.

Then we return Foo.instance so that we get the instance.

Now if we create 2 instances of Foo :

const foo = new Foo();
const bar = new Foo();

Then we can see if they’re the same instance by writing:

console.log(foo === bar);

We should get true since they both reference the same instance.

Singletons are handy for creating objects that are used by multiple pieces of code to store data in a central place.

If we don’t want conflicts in how data is accessed, then we can create a singleton instance of a class or an object literal to make sure that there are no issues with conflicts.

Flyweight Pattern

The flyweight pattern is where we restrict object creation,

We create a set of small objects that each consume a smaller amount of resources.

These objects sit behind a flyweight object, which is used to interact with these objects,

Those objects also interact with our code.

This way, we get the benefits of a big object, while we interact with smaller objects that are more manageable.

For instance, we can implement it as follows:

class Student {
 //..
}

const studentIdentity = {
 getIdentity(){
   const student = new Student();
    //..
    return {
    //...
    }
  }
}

const studentScore = {
 getScore(){
   const student = new Student();
    //..
    return {
    //...
    }
  }
}

We have a Student class that represents a student’s data.

Then in the studentIdentity and studentScore objects, we have methods to get his or her identity or score respectively.

This way, we don’t have to put all the methods into the Student class.

Instead, we have methods outside of it that are smaller that we can use to deal with specific kinds of student data.

Conclusion

We can use the singleton pattern to create one-off objects.

We can either create class instances with only one instance or with object literals.

The flyweight pattern is where we create smaller objects to deal with big objects, thereby reducing complexity.

The chain of responsibility pattern lets us send data from one object to another in a series fashion.

Categories
JavaScript Design Patterns

JavaScript Design Patterns — Factory Pattern

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the factory and observer patterns.

Factory Pattern

The factory pattern is a design pattern that lets us create new objects and return them in a clean way.

For instance, we may want to return different kinds of things that are similar.

To make this easy for us, we can create a factory function that lets us return different kinds of objects with one factory function.

We can write:

class Fruit {
  //...
}

class Apple extends Fruit {
  //...
}

class Orange extends Fruit {
  //...
}

const fruitFactory = (type) => {
  if (type === 'apple') {
    return new Apple()
  } else if (type === 'orange') {
    return new Apple()
  }
}

We have the fruitFactory factory function that gets the type of an object as the argument and then return an object according to the type.

If we have 'apple' as the value of type , we return an Apple instance.

And if we type set to 'orange' , we return an Orange instance.

Now we can return different subclass instances of Fruit without writing them out explicitly.

If we make any changes to the class or add or remove them, then we can still use the same factory function and don’t break anything.

Some factory functions in JavaScript are in the standard library.

They include String for creating strings, Number for creating numbers from other entities, Boolean for convert variables to boolean, Array for creating arrays, and more.

Now we don’t have to worry about changes to the class structure messing up our code since we used a factory function to create our Fruit objects.

Observer

The observer pattern is where we have multiple objects that listen to the one observable object.

This way, the observable object, which is also called the subject, can notify the objects that subscribed to the observable object with data that are emitted.

For instance, we can write:

const observable = {
  observers: {},
  subscribe(obj) {
    const id = Object.keys(this.observers).length + 1;
    this.observers[id] = obj;
    return id;
  },

  notify(data) {
    for (const o of Object.keys(this.observers)) {
      this.observers[o].listen(data);
    }
  }
}

const observer = {
  listen(data) {
    console.log(data);
  }
}
observable.subscribe(observer);
observable.notify({
  a: 1
});

We have the observable object that lets observer objects, which have a listen method to listen to data, to subscribe to notifications from the observable object.

When we can observable.notify with something as we did above, the listen method of the observer objects is run.

This way, the communication is all done by communicating via the notify method and nowhere else.

No implementations are exposed and therefore no tight coupling.

As long as the methods do the same thing, we shouldn’t have to worry about breaking the observer objects that subscribe to the observable .

We can also add an unsubscribe method to observable which uses the returned id from subscribe to remove an observer object from the observers object.

For instance, we can write:

const observable = {
  observers: {},
  subscribe(obj) {
    const id = Object.keys(this.observers).length + 1;
    this.observers[id] = obj;
    return id;
  },

  notify(data) {
    for (const o of Object.keys(this.observers)) {
      this.observers[o].listen(data);
    }
  },

  unsubscribe(id) {
    delete this.observers[id];
  }
}

const observer = {
  listen(data) {
    console.log(data);
  }
}
const subscriberId = observable.subscribe(observer);
observable.notify({
  a: 1
});

observable.unsubscribe(subscriberId);

We added an unsubscribe method so that we can remove the observer object from the this.observers list.

Once we unsubscribed, we won’t get notifications any more with the unsubscribed observer if we call notify again.

Examples of the observer pattern are used in many places.

Another good thing about the observer pattern is that we don’t communicate anything through the classes.

Loose coupling should always be preferred to tight coupling.

We only communicate through one channel in the example above so the observer pattern is as loose as coupling can get.

They include message queues and event handlers for GUI events like mouse clicks and key presses.

Conclusion

We can use the observer pattern to decouple objects as much as possible.

All we do is receive events from one observable object that we want changes from.

The observable sends notifications to observer objects.

The factory pattern lets us create objects of similar types in one place by creating a factory function that lets us do that.

Categories
JavaScript Design Patterns

JavaScript Design Patterns — Strategy and Decorator Pattern

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the strategy and decorator design patterns.

Strategy Pattern

The strategy design pattern is a design pattern that lets us select from a family of algorithms during run time.

The algorithms should be substitutable with each other.

This pattern’s main idea is to let us create multiple algorithms for solving the same problem.

We have one object that does things one way and another that does things another way.

There may be more than one way to do the same thing.

For instance, we may have one function that calls a function depending on what we want to do.

We may write:

const smartStrategy = () => {
  //..
}

const smarterStrategy = () => {
  //..
}

const dumbStrategy = () => {
  //..
}

const doTask = () => {
  if (shouldBeSmart) {
    smartStrategy()
  } else if (shouldBeSmarter) {
    smarterStrategy()
  } else if (shouldBeDumb) {
    dumbStrategy()
  }
}

We have the doTask function that runs the functions that have the strategies that we want to use to accomplish a task.

This way, we can pick the algorithm that suits the task the most.

This can be from a user setting or it can be chosen automatically.

The whole idea is to define a family of algorithms, encapsulate each one, and make them interchangeable.

Making them interchangeable is important since we want them to accomplish the same results at the end.

The strategy pattern is good for separating volatile code from a part of the program so that the part that changes are separate from the stable code.

Also, using the strategy pattern, we don’t have to split the implementation code over several inherited classes as often.

Using this pattern reduces the chance of having many child classes for one parent class.

This is a simple pattern that let us choose different ways to do the same thing and reduce the risk of volatile code that break things by separating them out.

Algorithms are encapsulated by one interface that doesn’t change so that outside code can just use that instead of changing the inner workings of the code all the time.

Closed for Modification, Open for Extension

In the same vein, once we wrote some code, we shouldn’t be modifying them too often.

Instead, they should be open to extensions so that we can add capabilities to them later.

Changing code always introduces risks. The more changes we make, the higher the chance that we break things.

Therefore, we should just extend things as much as possible so that the existing code stays untouched.

Decorator Pattern

The decorator pattern is a pattern where we write wrapper code to let us extend the core code.

We just keep wrapping objects around objects that we want to use so that we keep extending the capabilities of the existing objects by defining new objects that have the capabilities of the existing object.

For instance, we can write:

const computer = {
  //...
  description() {
    //...
  }
};

const disk = {
  ///...
  computer,
  description() {
    //...
  }
}

const laptop = {
  ///...
  disk
}

The computer object has the core capabilities of a computer.

Then we extend the capabilities of disk with by putting the computer object inside the disk object.

Then we create a laptop object, that has the disk object, which has the computer object.

Now we created extensions computer , which are disk and laptop , without modifying the computer object itself.

That’s a safe way to add capabilities to computer without the risks of modifying computer directly.

Modifying things directly may break the thing itself or the things that use it.

Likewise, we can use the same pattern as an object but replacing them with classes.

For instance, we can write:

class Computer {
  //...
  description() {
    //...
  }
}

class Disk {
  constructor() {
    this.computer = new Computer();
  }
  //...

  description() {
    //...
  }
}

const laptop = {
  constructor() {
    this.disk = new Disk();
  }
  //...
}

We nest the Disk and Computer instances within Laptop so we can use them.

Conclusion

The strategy pattern lets us use different ways of solving the same problem by encapsulating them within one entity that can be invoked directly.

With this pattern, the strategies themselves are hidden from the outside.

With the decorator pattern, we can extend the capabilities of things by creating new things rather than changing things directly.

This reduces the chance of breaking things.

Categories
JavaScript Design Patterns

JavaScript Design Patterns — Composition, Inheritance, and Configuration

Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the difference between composition and inheritance, and look at why we should make our program have some flexibility.

Composition Versus Inheritance

Composition is when our object contains other objects.

Inheritance is when we receive the parent object’s members in the current object.

They both have their place.

Composition is a has-a relationship while inheritance is a has-a relationship.

It’s very important to make distinctions between the 2 since they do different things.

In JavaScript, there’re various ways that 2 things are composed.

For instance, we can have functions that are nested in other functions.

We can write:

const foo = fn => {
  //...
  fn();
  //...
}

We have a foo function that calls fn .

Also, we can have nested objects. For example, we can write:

const obj = {
  foo: 1,
  bar: {
    baz: 2,
  }
}

We have an object as the value of bar .

We can also have functions as values of object properties.

Composition is used for holding functionality that’s needed by something.

Inheritance, on the other hand, is an is-a relationship.

This means a child object is also a parent object. It’s just that a child object may have additional things.

For instance, if we have:

class Animal {
  //...
}

class Cat extends Animal {
  //...
}

Then Cat is a subclass of Animal . Cat is an animal.

Cat shares all the members of Animal .

We can any methods ofAnimal and access any instance variables of Animal from a Cat instance.

For example, we can write:

class Animal {
  speak() {
    //...
  }
}
class Cat extends Animal {
  //...
}

The extends keyword indicates that Cat inherits the members of Animal .

Then if we create a Cat instance, we can write:

const cat = new Cat();

Then we can call speak by calling:

cat.speak();

Likewise, we can create an is-a relationship between 2 objects with the Object.create method:

const animal = {
  speak() {
    //...
  }
}

const cat = Object.create(animal);

Object.create takes a prototype object which will be the prototype of the child object.

So animal is the parent of cat in the example above.

Like with class instances, we can call speak by writing cat.speak() .

In both the class and object examples, the prototype of the object resides in the __proto__ property of the object.

Inheritance is good for creating multiple classes or objects that share things from the parent class or object respectively.

The general principle is that if we have volatile code, then we should use more has-a relationships rather than an is-a relationship since we assume that shared code between a parent and different children may change.

If we change shared code between parents and children, then we break all the children as well.

Creating Algorithms

Once we decided on the patterns to use, then we’ve to devise our algorithm for our program.

This should be easy once we created some basic designs. Implementation is all that’s needed in most cases.

We can use existing libraries to make our lives easier, which is what we should do in most cases.

If we have an is-a relationship between classes or objects, then we need to think about which pieces of code are shared and which ones are unique to classes or objects.

If we use a has-a model instead, then we can create algorithms in different places and use them as we wish to.

We should think about making our program configurable so that we don’t have to change code to have slightly different functionality.

This way, we make our lives easier since code change always has some risks.

To reduce that, we should make things that change frequently be configurable so that we don’t have to deal with them.

For instance, we can read settings from a file or database so an algorithm can be selected according to settings that are set in those places.

Conclusion

Our programs should have some flexibility so that we don’t have to change code for it to do different things.

Composition is when we have something in an object or class so we can use them as we wish.

Inheritance is when we have some shared code that’s used by other objects or classes.