Good Quality Software; From Develop To Production
How we kept the quality of our web applications best from the developing to releasing and long-running phase, If you don’t start with a spec, every piece of code you write is a patch. (Leslie Lamport)
In this article, we’ll take a brief look into some theoretical concepts about the quality of the software, and then we’ll take a look at the real world and how to apply it to our approaches
What’s a Good Quality Software?
As well as the theory and articles about “good quality software” on Wikipedia, I would like to emphasize that you and your team, your business goals, and your resources can all play a major role in the success of your software. However, some parts are the same for different teams and software, and we want to talk about this exactly in this blog post.
# 1 — Reliability
The main cause of poor reliable software is not following the best and known practices and not having a strict pattern during coding your software, they’re found in a combination of non-compliance with good architectural and coding practices.
To avoid an un-reliable code you can have a detailed plan before starting code, modeling your software before writing your first code helps you to be on the way during the drive, one of the best articles about planning your application architecture ( for Frontend! ) can be found here: https://medium.com/swlh/frontend-architecture-in-scale-for-large-organizations-593930ed10cd
These practices and parameters can be monitored and strictly checked during the coding process.
- Application Architecture Practices
- Coding Practices
- Complexity of algorithms
- Component or pattern re-use ratio
- Dirty programming
- Error & Exception handling
- Multi-layer design compliance
- Software avoids patterns that will lead to unexpected behaviors
- Resource bounds management
# 2 — Efficiency
Inefficient performance is typically caused by violations of good architectural and coding practices, or we can say that “ Good Quality Software Should Be Efficient! “
It doesn’t matter how much time you spend on your codes and how much it was tough and exhausting, the end users and consumers gonna use it on different scales, and the much better experience you gave them, the much better resource management and cost you made matters;
The mindest of the “ Working Code “ should be replaced with “ Good and Efficient Working Code ”.
- Application Architecture Practices
- Appropriate interactions with expensive and/or remote resources
- Data access performance and data management
- Memory, network, and disk space management
- Compliance with Coding Practices
# 3 — Maintainability
Maintainability is a big word, we can easily break it down into modularity, understandability, changeability, testability, and reusability.
Modularity:
Your code should be able to easily down into separate or independent modules and parts, having their own context and not really affecting the others in different parts, common approaches for this pattern can be found here: https://en.wikipedia.org/wiki/Modular_programming
Understandability:
I can’t say enough related to the importance of this concept while you are coding your code, Even we can say most of the other parts depends on this concept, not readable code is a pure wasting time and resource, your code should be producible during long-running and by others, without this we don’t have a “ Scaleable Software “.
Changeability:
We’ll lose the game to others without a well-changeable codebase, not to mention that this also affects the parts!
Testability:
Not testable code is hard to maintain and develop, if you can’t picture a test case for your software modules then your code is not efficient and clear as it should be! With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.
Reusability:
By making reusable code, you can start off as many other projects as you can conceive, and when software is reusable, we can say it is good quality!
Good Quality Software: How to?
Well done! Our understanding of “What makes good software” is almost complete, but how do we achieve it?
As exhausting as it can be following all the above rules and events and strictly monitoring other team members to do the same job, there is no escape from it, and it will take some time and patience, but in the end, we have a nice accomplishment at least :)
As long as our curious mindset strictly looks for bad smell code to drop off, we can easily follow the rules because they are common and known across the software development industry, like the TDD approach which does take care of lots of parts like Testability, Understandability, and Modularity.
This case is a mixed code of “ Dirty “ and not understandable and not modular code ( it has more bad parts… )
/**
* We're not following any practices for coding our functions,
* Functions are randomly with different naming conventions,
* and different declaring approaches and undefined types.
**/
function What_TimeNow() {
let time = Date.now();
return time;
}
let heightRequirement = 46;
function canRide(height) {
return height >= heightRequirement;
}
const log_error = (error) => {
console.log(error);
};We can easily transform it into a “Good Quality” code by following some practices and approaches like functional programming and Airbnb javascript practice ( feel free to any other source )
/**
* We're following Airbnb and FP practices for coding now :D
*
* Function declarations are hoisted, which means that it’s easy - too easy
* to reference the function before it is defined in the file.
* This harms readability and maintainability.
**/
/* For the time function, we can just remove it! we were do over-engineering */
const canRide = function canRideCheck(height: nubmer, heightRequirement: number) {
return height >= heightRequirement;
}
const logError = function logErrorToConsole(err_message: string) {
return console.error(err_message);
};See?! it’s not too difficult and we can simply follow know practices and decide between the different options we have.
Good Quality Software: Monitor and Maintain.
Assuming that you are reading this to become a good quality software writer, how about your team or the project you contribute to?! It is true that we can do some manual and strict things to prevent poor-quality software. However, the majority is up to you and influencing your team to use good software and prepare their mindsets, many teams and startups ignore good software just because they believe they have too much pressure and too little time, but with the dirty, unclean software they wrote, the number of bugs increased as time passed and customers are unhappy with the product. They spend the double time writing good quality code to fix an infinity bug loop that never ends, and every code they write is a patch for the previous bug. This loop occurs until the product fails or wastes a lot of resources.
But how about strict rules across the project?! Contribution guides can be governed by some strict rules that we can apply to everyone and force them to follow, let’s check some of them.
# Husky & Commit-lint
To enforce conventional commit messages and run some commands before each person commits we can use commit linting tools and standards like Conventional Commits.
By this, we can make sure that commit messages are standard and that our strict commands run before committing ( but remember that it can be escaped by the — no-verify command )
# Lint from stdin
echo 'foo: bar' | commitlint
⧗ input: foo: bar
✖ type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]
✖ found 1 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint# ESLint
Linting across the code is one of the best ways to keep software patterns in mind, and Eslint is one of the most useful tools for that purpose.
Below is an example of how we can use some rules to keep different modules looking the same across the code, such as a single quotation or double quotation, semi-colons or not semi-colons, and import orders, also applying Airnbnb javascript style guide to the project.
{
...
"rules": {
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"],
"prettier/prettier": ["error"],
"react/react-in-jsx-scope": "off",
"simple-import-sort/imports": [
"error",
{
"groups": [
// Packages `react` related packages come first.
["^react", "^@?\\w"],
// Side effect imports.
["^\\u0000"],
// Parent imports. Put `..` last.
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
// Other relative imports. Put same-folder imports and `.` last.
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
// Style imports.
["^.+\\.?(css)$"]
]
}
],
}
}# Prettier
In addition to Eslint, Prettier is a really impressive tool that can enforce coding style on our project and throw errors on escapes.
Here we’re not allowing single quotes, the code should not be longer in width than 90 and we should add semi-colons also.
{
"singleQuote": false,
"printWidth": 90,
"proseWrap": "always",
"tabWidth": 2,
"useTabs": false,
"semi": true
}# Tests
When the code grows and becomes bigger day by day then keeping eye on other components when adding new code is hard and most of the time we broke things.
Tests can help us in this way to keep the product testable and keep an eye on the product code and workability, and the decision on the tests is based on you and your project type, we can have e2e, integration, unit, and many more test types.
for the frontend projects we mostly use E2E tests to make sure that the product is working and also test our components.
The below test is an example that how we can keep the URLS live and not break by the new pages we made and it can be simply checked during the both development and deployment phases.
// Test all pages are available on the Mobile
// and not breaked by the new changes -> !404
import { expect, test } from "@playwright/test";
test.use({
viewport: { width: 780, height: 900 },
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || "http://localhost:1024",
});
const URLS = ["/", "/profile", "/login"];
test.describe("Mobile URLs validation", () => {
URLS.forEach(async (URL) => {
test(`URL: ${URL}`, async ({ page }) => {
await page.goto(URL);
await expect(page).not.toHaveTitle(/Page not found!/);
});
});
});# Merge requests & Actions
We can check the code style on the merge requests and run the CI/CD & pipelines to do some tests before deployments to make sure everything is right.
Good Quality Software: Conclusions
First I want to be very thankful for reading my article and paying attention to it! also need to mention that the writing is based on my experience in different teams and from some articles on Wikipedia and trustable sources.
I was in charge of leading projects and especially in re-factoring sprints and saw the process with my own eyes, how teams failed just because of not paying attention to writing good quality code and trying to escape it by some sentences like, “We don’t have time” or “We can refactor it later” and later in time of refactoring they dug by the pressure of the refactoring codes and new change requests and many developers experienced burn-out during the process and left their job, Time not spent debugging code, time not spent supporting customers who’ve suffered from bugs released into the wild. A time that can now be invested in building a better product.
As Michael Feathers eloquently puts it in the great book “ Working Effectively with Legacy Code “:
“Code without tests is bad code. It doesn’t matter how well written it is; it doesn’t matter how pretty or object-oriented or well-encapsulated it is. With tests, we can change the behavior of our code quickly and verifiably. Without them, we really don’t know if our code is getting better or worse.”
resources:
- Working Effectively with Legacy Code, Michael Feathers
- https://en.wikipedia.org/wiki/Software_quality, Wikipedia
Want to Connect, and read more article related to optimizations?!
Medium: medium.com/@sinafarhadi
Portfolio: bugpointer.devMore content at PlainEnglish.io. Sign up for our free weekly newsletter. Follow us on Twitter, LinkedIn, YouTube, and Discord.
Interested in scaling your software startup? Check out Circuit.
