More and more often I see engineers who want to write a code, to resolve a problem, to fix a bug, to create a feature as fast as it is possible. The most important goal is to make your code operating and have to work as expected. From here we face some challenges how to support, maintain, add features into that code and hope without magic.
My past and permanent projects which I work on are the long life projects. Engineers may come and go, a team can be changed, but the most important point here is motivation. When a newcomer joins a team and sees how messy, non-understandable, not-documented code they has two options here. Firstly, to accept and work with it and to resolve tasks because we have the end of a sprint. Secondly, to take under control, to face a challenge and try to bring a team to the better results.
In order to avoid such situation in a team, lets see how we can discuss, brainstorm a feature example task and solve two main problems, make a feature to work and leave some docs for team members.
Dialog in a team.
John: Jeff, do you want to take a new feature?
Jeff: Sure! Which one, this easy one with three drop-downs named “Find your job”?
John: Yes, “Find you job”. I will give you the requirements and please describe how you are going to organize your code. Remember, the requirements may be changed.
John: Good work Jeff. Just before you have shown me the flowchart, the requirements had changed and we know need to support different API’s for each request and the response data will be also changed. To be short, each request should have its parser. Ow, and I almost forget to say, we need to add two more drop-downs.
Jeff: No problem, I will add :)
This is a common behavior and approach to resolving a problem and it is fine. Although, you see that the problem might appear in future, don’t you? Yes, I do. You are right, a duplication, a complex logic for each drop-down listener and as many drop-downs we will have as many “if statements” you should add to MORE listener.
So, let’s jump into Design Patterns and see how we can improve the code.
Design patterns are reusable solutions to commonly occurring problems in software design. They are both exciting and a fascinating topic to explore in any programming language. ~ Design Patterns, Addy Osmani
Looks like The Command Pattern perfectly fits our needs.
The Command pattern aims to encapsulate method invocation, requests or operations into a single object and gives us the ability to both parameterize and pass method calls around that can be executed at our discretion. In addition, it enables us to decouple objects invoking the action from the objects which implement them, giving us a greater degree of overall flexibility in swapping out concrete classes(objects). ~ Design Patterns, Addy Osmani
The updated flowchart will look like that:
As you may see from the flowchart we are going to have one method which is going to get jobs.
We only should pass a config inside. The config has getUrl, parser, optionValue, selectName properties and the method executeGetJobs handles all logic which we need.
Run and check the repository.
Before I started writing a code I was thinking which framework to use to get the faster result, as it usually happens. Angular or maybe React, Vue, oh damn no, lets do that in vanilla JS style with Custom Elements and keep the components approach.
With Custom Elements, web developers can create new HTML tags, beef-up existing HTML tags, or extend the components other developers have authored. The API is the foundation of web components. It brings a web standards-based way to create reusable components using nothing more than vanilla JS/HTML/CSS. The result is less code, modular code, and more reuse in our apps.
That is exactly what we need for our app.
Does not matter how many drop-downs you have the listener on change, which will look like that:
As you may see in PRODUCTION flowchart we should have one method
executeGetJobs which will do all job.
It is simple to build a config. You need to understand what you have to have in the config for making a request and return to UI as a response. So, as you may see the config is flexible and you if you need to add more selects it is easy to do. Have a look:
The last part is HTTP request which I like to call a resource. I use ES6 modules (import/export) and they are singletons, the instance is created when the module is loaded. It is important to remember that when you are working with reusable user interface widgets (components), every object/class which has shareable data should return a new instance.
Do you ask me why? The answer is simple. Singleton initializes once, so if you have a component in two places they will use the same instance data. So, each component will be modified and share one object. In my case, the resource is not an exception. So, let’s get a new instance each time when the component is used:
Finally, let’s see the resource main GET methods. As you may see
executeGetJobs sets all data which we need for the
getMoreJobs request (lastSelectName, lastOptionValue). That data will help us to build correct config.
Remember, that the best solution to any problem is to ask your team members for the help. Do not forget about design patterns, they make a code more readable, scalable and this is one of the most known solutions in software design, so everyone will understand what code does. I like how Web Components work and the way they are created. I keep working on it and soon will share my thoughts and show you an app based on Custom Elements. It is time to remember vanilla JS :)
Thank you for reading. Suggestions, comments, thoughts are welcome :)