Categories
JavaScript Design Patterns

Commonly Used Design Patterns in JavaScript

Design patterns enable us to organize a program’s code in a standard way.

The book Design Patterns: Elements of Reusable Object-Oriented Software was published in 1994 and came up with 23 design patterns that are used by object-oriented programs.

In this piece, we’ll look at some of the more commonly used design patterns in JavaScript programs, including the singleton, iterator, and factory patterns.


Singleton

Singleton is a pattern that is common in JavaScript. It’s a class that only creates one instance of an object.

In JavaScript, we have the object literal to define an object that isn’t an instance of a class. For example, we have:

const obj = {  
  foo: 1  
}

We also have the class syntax, which does the same thing as constructor functions, where we can define a getInstance method to get an instance of a class.

To make a singleton class, we can write something like the following:

Since we assigned this to this.instance and return it in getInstance, we should always get the same reference.

We should get that foo1 === foo2 being true since they reference the same instance of the Foo class.

Singleton classes are useful for facade objects to hide the complexities of a program. State objects that are shared by different parts of a program also make singleton classes a good choice.

They also let us share data without creating global variables. The global scope isn’t polluted, so it’s a good choice for sharing data.


Iterator

The iterator pattern is a pattern where we create an iterator to sequentially access data in a container.

We need this pattern to traverse items in collections without exposing the underlying data structure. And we should also be able to traverse objects in an aggregate object without changing its interface.

In JavaScript, we can define iterable objects and generators to do this.

To define an iterable object, we can write:

As we can see, iterableObj hides the array that’s inside it from the outside. Also, we can change it to anything else we want and not have to worry about changing the code outside.

[Symbol.iterator] and generator functions have been available since ES6. Ever since then, we can define iterators easily.

We can also define generator functions that return generators. To do this, we can write the following:

It’s similar to iterableObj since they both use generators. The difference is that generatorFn is a generator function that returns generators. Generators are what we iterate through.


Factory

The factory pattern centers around the factory function. It’s a function that returns objects without using the new keyword to construct an instance of a class or a constructor function.

We want to use the factory pattern to make code more readable since it lets us create functions that return new objects from more code.

It also lets us return objects without knowing the code that creates the object. We don’t have to worry about what class is instantiated to create the object or how it’s created otherwise.

In JavaScript, when a function returns an object without the new keyword, then it’s a factory function.

For example, we can create a simple factory function as follows:

const createFoo = () => ({  
  foo: 1  
});

The createFoo function always returns the { foo: 1 } object when it’s called. It always returns an object without the new keyword, so it’s a factory function and uses the factory pattern.

Factory functions are common in JavaScript. For example, browsers have the document.querySelector() method to get a DOM object given the CSS selector.

There are similar methods that return objects everywhere in JavaScript.

The singleton pattern creates a single instance of an object. In JavaScript, we can do this with object literals or a getInstance method of a class that always returns the same instance of a class.

It’s useful for sharing data and hiding the complexity of implementation.

The iterator pattern lets us traverse through collections of objects without knowing the implementation of it. Also, it lets us change the underlying data structure and logic without changing the interface.

JavaScript has iterators to do this in addition to generator functions.

Finally, the factory pattern is common in JavaScript. Any function that returns a new object without using the new keyword to instantiate it is a factory function.

It’s useful for hiding the complexities of creating objects from other developers. For example, we don’t have to worry about how document.querySelector() gets an element from the DOM. It just returns the first DOM element that matches the selector.

Categories
Careers

Programmer Best Practices — Meetings and Breaks

To be a professional programmer, there’re many things that we’ve to do to be a good one.

In this article, we’ll look at best practices for meetings and recharging.

Have an Agenda

All meetings need an agenda. Otherwise, we probably achieve anything in our meetings.

We need to know what discussions are on the table so that we can decide if it’s worth it.

If it has no agenda, we can skip them.

If the meeting goes off course or hijacked, then it should request people to stick to the agenda.

If that doesn’t happen, we can leave.

Stand Up Meetings

Stand up meetings are common in agile development.

They are named that we because people in the meeting are supposed to stand so that they’re uncomfortable enough to keep it quick.

All it does is answer 3 questions:

  • What did I do yesterday?
  • What am I going to do today?
  • What’s in my way?

These questions shouldn’t take more than a minute to answer altogether.

Even if there are 10 people in it, it should take less than 10 minutes.

Iteration Planning Meetings

Agile development also has iteration planning meetings.

These are hard to do well. They may take too much time.

It’s a valuable skill to do these well.

It’s supposed to take items from the backlog and queue them to work on the next iteration.

There should already be estimates on each item that’s queued.

Also, there should be acceptance or component tests written or sketched out.

We should just go through each item quickly to see if we want to do them in the next iteration.

They shouldn’t take more than 5% of the time of each iteration.

This is a generous estimate.

Retrospectives and Demo

These are done at the end of each iteration.

Team members discuss what went well or wrong.

Stakeholders demo new features.

These can take up lots of time, so we should time-box them so that they don’t take too much time.

Arguments

Arguments that can’t be settled in 5 minutes can’t be settled by argument.

Anything can happen with arguments.

Some people may argue by force, some may be passive-aggressive.

To end arguments, we can run experiments, do simulation, or models, or we can just pick a choice.

Focus

Programing requires concentration and focus. It’s a scare resource.

It’s hard to regain focus after losing it,

We got to keep focus. If we don’t keep it, we lose it.

This is why we should minimize meetings. If all the time is used for meetings, then there’s no time for meetings.

Sleep

Sleep is important. If we don’t have enough sleep, then we won’t write anything good.

7 to 8 hours is probably enough.

We got to keep a sleep schedule so that we’re energized the next morning.

Coffee

Some people like coffee to energize themselves.

But they give us jitters that divert our focus.

We may be focusing on the wrong things because of the coffee buzz.

Recharging

We need rest so that we can get energized and focused again.

People may find different ways to recharge. We may take naps, listen to a podcast, or read books.

It’s hard to focus once we don’t have energy.

Muscle Focus

We may want to do exercises so we can take a break from coding and recharge.

Also, we may also have hobbies to take our mind off coding.

What it is, it’ll improve our muscles and our minds.

Avoidance

We can take a break from work if we can do so.

If something isn’t urgent, we may put it off until later.

At the same time, we’re creating defenses on why we put off the task in case anyone judges.

We can evaluate the priority and ignore personal fears and desires.

Going Down the Wrong Path

It’s possible that we may go down the wrong path with what we’re doing.

This may keep us stuck or lead us down the wrong path.

We can’t avoid this entirely.

However, we do have to realize when we’re in one so we can get out of it.

Conclusion

Meetings are time sinks, so we should keep them short and have an agenda to avoid trailing off.

We also have to recharge to stay focused. And we’ve to get ourselves out of paths that lead to nowhere to get back on track.

Categories
Careers

Programmer Best Practices — Testing and Meetings

To be a professional programmer, there’re many things that we’ve to do to be a good one.

In this article, we’ll look at the best practices for testing. We also look at meetings.

Testing

Testing is best done by developers.

QA shouldn’t find much if anything.

This way, we just get through what we worked on faster since QA just passed them right through to the finish line.

QA is part of the team and they can create the automated acceptance tests that run to check that everything is good.

They catch the corner cases and write tests for them.

They can also do exploratory testing to identify the behaviors of the system.

The Testing Pyramid

The testing pyramid groups tests from the types of tests that are the highest quantities to the ones that are the lowest.

Unit Tests

The ones that are the highest quantities are the unit tests.

They test the smallest parts of the system like functions and classes.

Unit tests should be close to 100% coverage. They run fast, so we can have more of them.

Component Tests

Then the component tests are smaller in number than unit tests, but there are still many of them,

They test a component of a system like small features.

These cover the normal paths, and also boundary cases. Most boundary cases should be covered by unit tests.

Integration Tests

Next comes the integration tests which test a part of the system.

They test a bigger part of the system than component tests.

Therefore, they’ll be smaller in number than component tests.

Then higher in the period are the system tests. They test several features together in a workflow end to end.

These are for more critical parts of a system like logging in and things like that.

They test the system as if a user is using the system.

Exploratory Tests

Exploratory tests are the ones that are done for learning purposes.

These are used to get familiarized with the application.

It’s also used to validate other tester’s work.

And it’s also done by testers to perform smoke tests.

Exploratory tests are done manually.

It’s used for exploring unexpected behaviors that may cause issues.

It’s unscripted and the actions aren’t repetitive.

Time Management

Time management is important since there isn’t enough time to do a lot in a day.

Our days are filled with phone calls, meetings, production issues, and other interruptions.

To get things done, we got to manage our time well.

We can wake up, write a schedule on the board, and then do what’s on the schedule.

Meeting

Meetings take lots of time and therefore money.

We also need a space to meet, which is probably another cost.

They are necessary and they’re big time wasters.

We may be able to use both to describe the same meeting.

We’re aware of the cost, so we should resist attending the ones that we don’t need.

Declining Meetings

We don’t have to attend meetings that we’re invited to.

It’s unprofessional to go to too many meetings.

We have to be responsible for managing our own time.

We should go to the ones that are important to what we do. Some meetings are also interesting so we can go even though we don’t have much to contribute.

Someone with authority may also invite us to meetings. In that case, we can check with them if we need to go.

However, good managers shouldn’t ask people to attend too many meetings so people can finish their work.

Leaving

We may also leave meetings that don’t go as planned.

We may decline if we know the meeting goes the way it is now.

If it’s boring, then we can leave.

To leave the meeting, we can excuse ourselves politely.

If we have nothing to contribute to it, we may think about leaving.

Conclusion

Testing is important. Therefore, we need to do that. It’s best to automate that as much as possible.

Meetings are huge time sinks, so we should only go to the ones that we need to go to.

We can always pick which meetings we should go and politely leave if we don’t contribute enough to it.

Categories
Careers

Programmer Best Practices — Being Late and Writing tests

To be a professional programmer, there are many things that we have to do to be a good one. In this article, we’ll look at what to do when we’re late, and why we need test-driven development.

Being Late

Most of us will be late for something eventually. We may be late for various reasons, like not getting enough time for estimates. To manage lateness, we should tell everyone that we might be late- we shouldn’t give people hope and then disappoint them.

If we’re going to miss a deadline, then we shouldn’t rely on hope to get it done. Rather, we must have a fallback plan to deal with being behind. If people try to force us to change the estimate, we must stick with our estimate. We just can’t buckle under pressure to try to make the deadline. If we do, the product probably won’t be good and the code is most likely also going to be bad.

It’s impossible to solve problems faster, we get stuck and we probably can’t get faster. Over time this becomes risky. We’ll be tired and burnt out by the end of it if it lasts one. There is just no way to get something done well by rushing it.

Changing the definition of what it means to be “done” also isn’t good. We may want to move on faster by changing the definition of done but it is not good to do that. No one wants to see all the real work that actually isn’t done even if we say it is. The easiest way to define being done is to make sure that automated tests pass.

Helping Each Other

Programming is hard. Therefore, we need all the help that we can get. We can’t just put together some code and hope that it works. Instead, we’ve to design everything into well-organized pieces that don’t depend much on each other as it’s beyond one person’s ability to do it well.

We’ll certainly benefit from another programmer’s help and ideas. This means that we should help each other so that we can make all our lives easier. If they need help, it’s time for us to jump in. We should also accept help from others when we have problems. This way, we also get things done faster and better. Also, we should learn to ask for help- when we’re stuck, it’s time to ask for help.

Mentoring

Less experienced programmers need help from people with more experience as training courses don’t always cut it and sometimes books can’t help that much either. Receiving mentoring from more experienced programmers, on the other hand, can help with that.

Test-Driven Development

Test-driven development can help us a lot with writing code faster and better. We write the tests first and then we write our code. We write code to make the tests pass and then we’re done. First, we write a few tests and then we make them pass. Then we repeat the same thing for the rest of our project or tasks.

We get fewer bugs because we have the tests to catch them. If we have tests, then we wouldn’t worry about making changes because we can clean them up on the spot. The tests will make sure that our code is still good. Clean code is easier to understand, change, and extend. Defects are less likely because we simplified our code.

Documentation

The tests have descriptions to describe what it’s testing. This is a great source of documentation for us. It also shows us how to use some APIs in the code with the test code. The tests call functions, so we know how to use them. And they make requests, so we’ll know how to make requests with them if it’s a web app.

Design

To make code easy to test, we test them in isolation. This means that we have to decouple the code. This is great since we don’t want tightly coupled code. Therefore, writing tests first will help us improve our design. Most of the time, it’s practical to use test-driven development. However, there are some rare times that it’s not the case.

Conclusion

If we’re late for a project, then we should communicate that and stick to our timeline for finishing stuff. Getting and receiving help is also a great thing to do. Writing tests are great since they test our code and also serves as documentation.

Categories
Careers

Programmer Best Practices — Practicing and Testing

To be a professional programmer, there’re many things that we’ve to do to be a good one.

In this article, we’ll look at why we should practice so we can get better, and why we should automate acceptance testing.

Practicing

To learn any skill, we practice.

Programmers don’t practice a lot outside of work.

Some things have changed a lot. Now our computers are much better. Now we can do more faster.

We don’t have to wait for programs to compile today.

Therefore, we can just write programs and test them all the time.

Since we don’t have to wait for days or hours for programs to compile, we can write programs at any time for practice.

To do something fast, we have to practice. We got to write code to practice things that haven’t been done before.

Once we learned by practicing, we’ll gain muscle memory and we don’t have to look anything up to know what to type in.

In programming, we’ve to write in some code to make the program what we want them to be.

To get to that point, we have to practice solving problems.

Once we write enough programs, we can write something t at we want without much trouble.

Broadening Experiences

We can practice programming in many ways. Work is probably not enough since there’s a lack of diversity in what w work on.

If we don’t broaden our experiences, then we’re confined to what we do at work.

Employers want a consistent set of languages, platforms, and domains in which programmers must work.

This means that the technologies we’re exposed to are limited.

There are a few ways that we can practice.

Open Source

We can stay ahead of the curve by joining open source projects.

We can contribute to projects that use technologies that we don’t have exposure to.

For instance, if we use C# regularly, then we may want to work on some Ruby project for example.

Practice Ethics

We should practice in our own time. This way, we keep our time at work to do work-related things.

However, we can practice during breaks as well.

Testing

Testing is part of the job of programmers.

We got to know the requirements clearly before we can write software and test it.

Communication of requirements also has errors and we can never build what people expect the first time when we build it.

Getting Requirements

Getting requirements is always hard.

There are somethings that we shouldn’t do when we’re getting requirements.

We shouldn’t get too precise too early since things often change in the middle of the project.

Things can be different when we work on it now than some time later.

There is uncertainty in any project. Once we built something, then people may come up with different ideas for changes.

This is why we don’t want to make requirements too precise at the beginning since they’re going to change anyway.

Estimation

Estimation is always something we have a problem with.

There’s no point in being too precise with estimates since they are estimates.

They are never exactly correct.

Estimates should be made on low precision requirements. Uncertainty will also throw estimates off.

This is another reason not to be too precise at the beginning.

There are always disagreements and changes.

Acceptance Tests

Acceptance tests are some tests to check if something is good enough for release.

The thing we have to do is to define the definition of done.

When we say we’re done it means that code is written, testing passed, and stakeholders accepted.

To get to that, we need automated tests, and stakeholders can look over them later.

Communication

We got to communicate clearly. Acceptance tests can help us do that.

When we agree to the tests, we agree with what the behavior should be.

We can make it their responsibility to work with stakeholders and testers to ensure that all parties know what we’ll build.

Automation

To reduce the burden of testing, we should automate our tests.

Manually testing all the test cases is too slow and costly.

Automating the tests will make testing a lot faster and we can do them without looking at our program.

Conclusion

Practicing is an important part of improving ourselves as a programmer.

Also, we shouldn’t be too precise at the beginning with our acceptance requirements.

And we should automate acceptance tests to reduce the burden of testing.