To stay productive in programming you need to receive feedback for your code as fast as possible.
For example, when you want to test out some styling effects with CSS, the best way is to use the inspector in the browser and change the attributes and values to see how it works. The browser would update the CSS changes immediately. I find the experience enjoyable.
Sometimes the feedback doesn’t come until you run the application. Only at that time your code gets executed and you see the consequences as changes the UI, user behaviour, or an exception message in the inspector.
That sounds like a lot of overhead just to check if your code is correct. Unfortunately, if you don’t optimize the workflow you would end up wasting time like that.
For example, with some IDE plugins you can receive feedback for syntax errors, obvious mistakes like undefined variable, type inconsistency etc right in the editor.
Or, with a good test suite it can help verify any update in the code or the business logic and provide feedback for higher level change.
I believe the more feedback, and the faster you have the feedback would tremendously improve your programming productivity.
1. Fast update with hot module reload
Hot module reload watches and updates the UI when you change the code.
It’s helpful because you don’t have to manually refresh the page every time.
It also saves you some repetitive steps if the page being changed is deep in the navigation hierarchy.
This seems like just a small thing, but hot reload can free up your mind, create a smooth development flow, and save tons of time from doing something so frequently and repeatedly.
I work with React, Redux and use Webpack’s Hot Module Reload. Webpack’s HRM however isn’t limited to only React app, you can configure it for any project. This article explains it pretty well http://andrewhfarmer.com/webpack-hmr-tutorial/
Unfortunately configuring this is error-prone. Unless you are doing something special, I would recommend to choose a boilerplate project with some pre-configured Hot Reload, it can save you a lot of time.
2. Syntax checking with Linter
Linter can help you catch early programming bugs by defining syntax rules.
There are rules like undefined variable, unused variable, uninitialized variable that prevent obvious errors and avoid exceptions at run time.
Linter can be run ahead of time. For example it can be triggered when a file is saved. This way you can have immediate feedback for potential lint rule violations and fix them before the code runs.
Most IDEs have plugins to integrate with lint checking. Even though lint checking is rudimentary, it can still catch a lot of common programming mistakes.
Lint rules also help maintain code convention. This is important when you have multiple team members as every one needs to agree on certain rule and stick to it.
ESlint is a new and popular tool. There are some popular lint config for it:
You can also customize it to create the best fit for your team.
3. Type checking with FlowType
For example you can assign anything to a variable, or you can create an array with each element having different data type, or you can call a function with missing argument, or a function can return different data types based on the current state or inputs.
This flexibility seems convenient at the beginning. However in the long run it usually leads to unmanageable code base, especially when a project evolves to certain complexity.
Facebook introduces FlowType to solve such headache. It is basically a type checker.
Having a type checker is beneficial in multiple ways. One of those is code readability. For example by looking at a variable declaration you know that it always has certain type and it won’t change throughout its lifespan. Or an array with a unified data type for all its elements are more predictable. Another example is a function with guaranteed input and output types give you the confidence about its behaviour.
Type checker also enables code auto completion. Since it can refer to the type of a variable with all of available functions or fields.
Code refactoring is easier and faster as well. For example an IDE can find and replace across files when you change a function name in a class.
It guarantees reliable integration from module to module, or client to server. If data payload between integrated components is wrong it’ll be detected right away instead of being passed down in the data flow.
For more information about flow type, please check out https://flowtype.org/.
I find the learning curve for flow type isn’t too steep. If you use flow type at the beginning of the project, that’s good. If you have an existing code base, that’s fine too, as you can enable flow file by file.
Microsoft’s Typescript is also a very nice alternative. This article has a thorough comparision between the 2 solutions http://djcordhose.github.io/flow-vs-typescript/2016_hhjs.html#/.
4. Writing tests
Test can give you valuable feedback when you change something. Developers spend a lot of time to change and refactor code as the project evolves.
Having good test coverage ensures that changes won’t break any functionality. That gives you tremendous confidence to make bold refactoring or improvements.
The feedback received from automatic tests is always faster than manual checking, and it run with no costs.
Of course you spend extra time to write it, but it results in better code quality of the project, faster to add more functionalities, more relaxing to do code refactoring.
For me test is there to ensure the business logic is under check. This is kind of a high-level feedback that other tools and techniques can’t provide.
Unless the project is trivial, it’s always worth writing code to cover important business logic pieces.
Those are practices and tools that our team apply to stay productive. If you have any hint or suggestion please let us know. Thank you!