April 15, 2021
Guide to Generating Quality Application Code
Jump to Section
- What is Code Quality?
- What Does it Mean to Have Good Code Quality?
- What Does it Mean to Have Bad Code Quality?
- What Causes Bad Code Quality?
- Why is Code Quality Important?
- What Issues Arise from Poor Code Quality?
- How Can Code Quality Be Improved?
- Are There Formalized Standards for Code Quality?
- How Should a Company Create Its Own Code Quality Standards?
- How is Code Quality Measured?
- What Are the Common Tools to Measure Code?
- What Are Best Practices for Maintaining High-Quality Code?
- Why is Code Quality Important for Security?
- Is Maintaining High Code Quality Difficult When Outsourcing?
- How 3Pillar Maintains Quality and Suggests Improvements for Clients
- Putting EAR Into Practice
- A Process That Continuously Adds Value
When you say “code quality,” most people think about defects—places where the software behaves in an unintended way, including but not limited to error messages. A more comprehensive view of quality goes beyond features to include best practices related to the key attributes of code quality:
- Intuitiveness and consistency of the code
- The deployability of the application as a whole
- The level of reusability within or with other applications
- Reliability (uptime)
- Developer experience
These aspects of quality are often assumed and not called out in the acceptance criteria for a feature. But they are absolutely critical to the success of a digital product or experience.
The importance of consistent quality cannot be overstated and has layers. First, quality ensures the product or the experience delivers the value-added functionality for end-users to perform the task consistently and reliably. Second, the product must protect valuable assets such as customer data. Third, companies that can respond to new information faster have a distinct advantage in the digital economy and are more likely to retain customers.
New information could be anything from a defect found in production to a newly discovered opportunity to expand value for current users or a new competitive threat. Digital products that are well-maintained and easy to deploy with predictable results and quality reduce the time between new information and working software that customers are using.
What quality really safeguards is trust. This means being able to do what you say (maintainability and deployability) and ensuring the details are taken care of (reliability, security and performance). It also means decreasing the time between new requests and deployed software. All of these attributes give your business leaders confidence and increase the chances that customers will find your products or services trustworthy.
Yet, the quest for good quality code requires a disciplined approach. It includes defining best practices and standards across the software development lifecycle. Those practices and standards must also be adopted across entire software engineering teams, which may include both internal and outsourced developers.
To help you take on the challenge of developing quality code, 3Pillar begins this guide with advice from our senior software engineering team. The Q&A format helps you understand the attributes of good as well as the attributes of bad code. Their answers also give you insights on what it takes to ensure proper code quality and some of the tools you can implement to support you in your mission.
The guide also provides an overview of the 3Pillar Engineering Analysis Report (EAR). Many of our clients leverage EAR and collaborate with our software engineering experts to not only measure the quality of their software products, but also the quality of the processes they rely on to develop those products. By doing so, they are much better positioned to deploy applications that help their businesses run more efficiently and generate more revenue.
What is Code Quality?
Code quality pertains primarily to how well an application performs and how easy it is for developers to understand, test, maintain, improve and reuse the code. Engineers should be able to make changes to the code that will have quantifiable impact in a reasonably predictable timeframe. As an application or ecosystem becomes more complex and re-use increases, it is more likely that inadvertent problems will be introduced in one part of the system away from where the changes are made.
“Ultimately, code quality is a measure of how well the code fits the business needs—not only today, but also over time.” – Manuel Ruiz
High-quality code follows best practices and the correct patterns. The code also adheres to an agreed-upon style by the engineers working on it. While bugs and vulnerabilities are unavoidable, they are continuously caught and remedied so that mean-time-to-repair is stable over time as the complexity increases through new features. Finally, quality code makes efficient use of compute resources, runs reliably, and is extensible to other systems through integration capabilities.
“Tests should assert neither more nor less than they should in a healthy environment. That means that 100% code coverage is not a healthy goal for most codebases.”
– Cassi Lup
Across an organization, code quality may be defined by a set of requirements and attributes determined by the organization. Within a specific project, code quality is a measure of how the code complies with a given set of rules, design constraints, and other attributes defined by the project.
The code should also employ the correct package structure, which includes code layers that abstract concepts like endpoints, business services, business logic, and persistence. Unit test (and end-to-end testing) coverage is also critical and a marker of a well-maintained and high-quality code base.
One important trap to avoid is thinking that coding “styles” and code quality are the same thing. Often, languages and frameworks give developers multiple ways to accomplish the same thing. Sometimes there is a real reason one way is better than another in a given situation, but there are plenty of times that it becomes a matter of preference. (A common developer joke is whether it’s “better” to use spaces or tabs in their code. Answer: It doesn’t matter.)
A high-performing and high-quality product can contain multiple styles in syntax and code structure because it might have different languages and technologies. However, a mark of high-quality code is the consistency of formatting across the same language.
The reason to encourage the team to align on common styles is to avoid unnecessary waste. Often, team members can devolve into fights over “best practices” when they are really talking about style and preference.
“The importance of code quality cannot be overstated in an Agile world where software developers need to move fast and switch gears.” – M. Peraza
What Does it Mean to Have Good Code Quality?
High-quality code drives efficient functionality that accomplishes the business requirements. The code goes beyond just fulfilling its purpose to also having zero known security vulnerabilities and performing reliably. It also optimizes the use of compute resources, follows best-practice coding standards, and uses appropriate algorithms and data structures—which makes it more extensible with bug-free functionality.
“Quality code not only refers to code written in the correct way by meeting IT industry best practices. It also aligns to the requirements gathered from the analysis phase to make sure the team delivers code that works and meets the business need.” – Miguel Peraza
Another key facet is how understandable the code is by an engineer that did not build it in the first place. Code built with standard constructs and proper variable names will be easier to maintain. Its behavior can be tweaked without affecting any external code it integrates with. And it can be reused in other parts of a project without requiring major structural changes.
“Efficient artifact naming is a must.” — Cassi Lup
“One of the harder-to-measure aspects of quality code is its elegance or simplicity. Code that is easily read, understood, maintained and changed will generate more value over time. It takes longer to write elegant code, so cultures that value more lines of code checked-in will see team throughput degrade over time.” – Scott Varho
What Does it Mean to Have Bad Code Quality?
Developers often refer to bad code by names such as “spaghetti code” that does not employ layer abstraction or “Frankencode” that is pieced together from other bits of code. No matter what form it comes in, bad code does not follow standard best practices, coding standards, design patterns, and language conventions. This makes it difficult for developers to read and understand the code, and it’s hard to extend and maintain.
The code will also likely be full of security vulnerabilities and bugs. Ultimately, bad code equates to an unreliable application that works in unexpected ways, wastes compute resources, loses data, crashes, and opens itself to security breaches—only to end up losing its most precious asset: user trust.
Bad code often comes into existence when the objective of a development project is limited to accomplishing one thing—without considering the rest of the functionalities of a system or the future requirements of the system. It may be difficult to understand because there is either no documentation, or the documentation uses abbreviations, complex syntax, or uncommon acronyms.
“Bad code is hard to decouple and difficult to test due to the highly-coupled dependencies, and it does not meet the code style standards, methodology, and architecture attributes determined by the company. By not following a defined structure, the code may need to be re-written, which will waste time and other precious resources.” – Miguel Peraza
What Causes Bad Code Quality?
Bad quality code occurs when there’s pressure to deploy the required functionality to production within an unreasonable timeline. Or perhaps the code is produced without long-term thinking—it works today, but it will not be easy to maintain or extend in the future. Taking these approaches usually leads to unreliable, underperforming, and insecure applications.
In other cases, the developers may lack the experience to know how good practices will affect them in the future—even on code they originally wrote themselves. They also may lack awareness of tools that can help, and they may not know how to apply coding standards and best practices for design patterns and enterprise-ready frameworks. A project that gets off to a bad start can seriously endanger the possibility of successful effects of the codebase.
Because of these factors, companies sometimes put oversight processes in place that are insufficient, inefficient and ineffective. Developers may handle revisions poorly, or they may forget to review the code and fix bugs prior to deploying to production. Ideally, you want a near-real-time feedback loop that helps developers check-in increasingly higher quality and consistent code.
When bad code occurs, the development environment in which the code was created is often missing one or more of these key attributes:
- Standardized style guide
- Best practices for code consistency
- Architecture guidelines
- Peer reviews
- Automated testing (unit, end-to-end, integration, regression, and performance)
- Cleaning of code after it works
- Coding standards
- Knowledge of coding languages (or absence of a Cargo-Cult Programming mindset)
“When bad code occurs, there is usually no leader to teach, coach, educate, and help the development team maintain discipline through each phase of code reviews. And a lack of unfamiliarity with the subject plays a big role in writing bad code as well. Some developers write code that works, but it doesn’t meet the basic best practices. They end up with an application that is hard to test, has a high rate of bugs, and in the end, needs more people to fix it.” – Miguel Peraza
Why is Code Quality Important?
Well-structured code with proper levels of unit test coverage enables products to “excel at change.” In any software, change should be assumed. If the code is not well-maintained, future changes to the code will lead to slower cycle times, lower predictability to complete changes, and surprises in production.
“Code quality is the main way to measure the impact of the software development team. It’s also important for quickly adapting to future code changes, which are unavoidable as business requirements change.” – Francisco Ponce
Well-structured code following language rules also allows developers to write code faster, deliver code on time, and make it readable and maintainable so the software continues to meet the business needs. Code quality also dramatically increases the chances that the deployed code has to be reliable, efficient, and secure—which reduces the amount of backlog rework. On another note, reliability and security transcend code quality and also have to do with the infrastructure on which the code runs in production.
“Code quality decreases waste, allows for issues to be found earlier, ensures proper usage of resources, and reduces the costs of software development.” – Francisco Carvajal
The code and the built-in unit tests also allow developers to add new functionality by providing reusable code that’s easy to upgrade and extend without introducing regressions. Additionally, code quality allows the software team to more easily keep development efforts in sync, which facilitates changes, helps identify when code quality degrades, and determines when potential architectural changes are needed to let the team iterate on newer features.
What Issues Arise from Poor Code Quality?
When applications are developed with poor code quality, a high bug count will ensue, and the bugs will be more difficult to fix. This leads to technical debt as the team reworks the code and the application is fully patched. Until the fixes are applied, the code will likely be insecure and deliver unreliable performance, and end-users will find many features are broken or limited in their functionality.
“Issues found late in the process due to bad code quality are harder to correct, especially if they are already impacting production versions. To fix the issue, resources are wasted, which ends up hitting the bottom line.” – Francisco Carvajal
Poor code quality also creates on-going issues for the development team. The code is difficult to understand, which wastes a lot of time trying to figure out how to maintain and extend the code.
“Poor code quality leads to bad software, which can lead to a bad reputation for the development team and the company.” – Eddy Nunez
Developers will also continuously run into delays due to the need for unplanned code refactoring, repairing, and adding functionality for new requirements. They will find the code is difficult to test and consumes compute resources inefficiently. Over time, all these factors add up to decrease the team’s performance significantly.
““When bad code occurs, cost overruns, failure to deliver business solutions, and customer dissatisfaction will ensue.” – Manuel Ruiz
How Can Code Quality Be Improved?
For poor code that’s already developed, the challenge can seem daunting. The business is likely to require new features even as you try to address quality issues. Start by gaining consensus around “what good looks like” and agree on code style guidance, conventions, unit test expectations, regression test coverage, test automation, peer code review expectations, and documentation. Without this, the team won’t be able to achieve quality even on new features.
“Upfront, it’s important to conduct proper planning, clarify the requirements, and to allow for a reasonable amount of time to develop the code and to allocate sufficient budget for the resources required to stay on schedule.” – Francisco Carvajal
It’s unlikely that the business will allow your team to focus only on quality for several sprints. Instead, tie improvements to requested features. If a feature requires work in an existing area, make bringing that section of code up to the new coding standard part of the feature work. In doing so, you are investing in an area of the application that the business has told you is valuable going forward (hence the changes requested).
“I call code improvement the ‘campfire rule’ — leave it better than you found it. This rule will serve your team and application well as standards evolve over time.” – Scott Varho
In parallel, highlight areas where code quality issues are impacting customers or the business and argue for a steady allocation of capacity to pay down quality “debt.” Some of those investments will be seen by the business, and some won’t, so it’s important to address both with that investment. As developers see the quality of the code improve, the impact of things like automated unit tests, and their ability to get work done more efficiently, they will see the benefits and take pride in their work.
“I like to use the metaphor of a business credit card. You use it when you need to go beyond your financial capacity and then you need to ‘service’ that debt and ideally pay down principle as soon as it is prudent and healthy. Software is the same. If you keep acquiring debt without paying it down, it will cripple you.” – Scott Varho
Additional key processes to work into the development lifecycle include continuous integration, version control, and recurrent dependencies. Developers can develop quality code more efficiently if they learn about computational complexity and the latest design patterns, and they will apply what they get trained on more effectively if given a way to practice what they learn.
Automation in continuous integration has also come a long way, and there are tremendous benefits in giving developers instantaneous feedback on code they just worked on and is fresh in their minds. As they make certain mistakes frequently, they are more likely to correct that behavior going forward.
“Another helpful routine is to conduct periodic team meetings to discuss potential architecture improvements and identify parts of the code that are difficult to work with. It’s also easier on the team if it’s given access to code coverage tools and linters.” – Paul Estrada
Are There Formalized Standards for Code Quality?
There are different tools, documentation and extensions to direct software teams on how to achieve code quality. The resources used can vary depending on the phase of the software development lifecycle, industry, and the business context. It’s best to apply standards at the moment the code is written.
Many software communities publish information on how to achieve good code quality. Two leading resources are The Consortium for Information & Software Quality and ISO/IEC 25000—which provides standards defining characteristics for functionality, reliability, usability, efficiency, maintainability, and portability.
That said, “quality” is something the business has something to say about. For example, if you’re doing work in a governmental or educational context, accessibility for users with a variety of impairments may be an important aspect of “quality.”
There are also standards like the Web Content Accessibility Guidelines (WCAG) that you can reference. It’s important to take a contextual view of quality while leveraging standards that can help you achieve the right level.
“Microsoft also provides guides that define coding standards for its languages and best practices to implement its tools and frameworks.” – Francisco Ponce
How Should a Company Create Its Own Code Quality Standards?
Some companies wonder if it’s best to just mimic the standards of an industry-accepted software organization. It’s actually better to develop internal standards as there will be variations from company to company, and there may be variations from project to project.
The internal standards should start with existing industry standards and include any additional in-house rules and definitions deemed necessary. The standards should be adopted daily through predefined processes for code reviews, peer reviews, and static code scans.
One way to begin the process to develop internal standards is to schedule technical sessions among architects, developers, and testers to discuss standards and best practices. The standards should cover the entire development process—from development to code review, unit testing, functional testing, continuous integration, and deployment (to various test environments and production).
“Once the standards have been developed, allow for feedback from the software team, and then conduct training with all developers to show how to apply the standards.” – Abel Gonzalez
Documenting best practices is often hard to maintain, and people might be oblivious of these while writing or reviewing code—unless they are educated adequately. Companies should complement this by defining standard linting templates. It’s a much faster way to inculcate best practices. Even a new employee writing their first code in the company starts adhering to standards instantly.
How is Code Quality Measured?
A wide range of metrics can be applied to measure code quality using static analysis tools:
||# of Bugs/Issues||Security||Maintainability|
Not all of these metrics need to be used, and different metrics can be used on various projects. But it helps to keep the metrics consistent so that the code quality of each project can be compared.
What Are the Common Tools to Measure Code Quality?
Some of the common tools to consider are static code analyzers, IDE code coverage tools, and code inspection tools. Here’s a rundown of some of the leading code quality measurement tools:
- Visual Studio Enterprise
- OWASP Suite
Eslint and JSHint both highlight style and efficiency errors. These two and most of the tools above detect security, syntax and complexity inside repositories. They also generate triggers when someone pushes new code.
“If you are worried about your development team writing good code, you can extend analyzers to integrate with Git hooks to enforce and make sure the developers follow best practices and style before committing changes to the main branch.” – Miguel Peraza
What Are Best Practices for Maintaining High-Quality Code?
Develop readable code with consistency in class, method, and variable names, and establish and stick to a methodology for planning, writing, testing, maintaining, and documenting the code. Ideally, use a starter.
Best practices to implement include defining code style standards, code guidelines, design patterns, enterprise-level frameworks, and design principles like SOLID. Also build a repository of these assets for developers to reference and give them access to all code quality tools.
Another important consideration is to adopt code reviews and peer reviews. Maintaining sufficiently high overall and differential code coverage will ensure new code and new features won’t break existing code. Typically, statically typed languages can afford to keep the code coverage threshold at 70-80%, but it needs to be more than 90% for dynamically typed languages. Additionally, iteratively executing code quality tools helps track bugs, vulnerabilities, and technical debt.
“Writing code isn’t any less than painting, and different craftspeople will have varying dexterity in articulating their thought process into code. As the team grows, new writing styles get introduced, which gradually convolutes the repository. Teams should strive to adopt IDE integrated code-formatting plugins, like Prettier, to ensure eloquent and consistent code is getting committed every time..” – D. Aggarwal
“Prior to merging new code, conduct quality checks to make sure everyone follows the best practices, and make it part of the continuous integration process.” – Paul Estrada
“After developing code, run static analysis tools before committing the code for review (Git hooks), and implement automated testing (unit to integration) to prevent bugs. Also ensure the code meets the business requirements and responds correctly to different inputs.” – Manuel Ruiz.
Why is Code Quality Important for Security?
Code quality tools play an important role in security by searching for vulnerabilities while following industry standards like OWASP. This means software engineers do not have to be security experts to release secure code.
Creating quality code also reduces the risk of security flaws and does not hide backdoors. It spots potential bugs that can enable security exploits and fixes them before they reach production.
Well-structured and maintainable code reduces the possibilities of an attack. It also plays an important role in the case of a breach by speeding up the process to respond and mitigate attacks.” – Miguel Peraza
Good quality code also prevents code from breaking, which can cause fatal errors, introduce security risks, and facilitate security attacks. Using static and dynamic code analysis tools in your continuous integration can help spot many vulnerabilities before they are released to production.
“Quality code allows for a better-structured approach to analyzing security gaps. If the code is messy and hard to understand, performing a security assessment becomes harder, and there’s a higher risk of missing a gap.” – Francisco Carvajal
Is Maintaining High Code Quality Difficult When Outsourcing?
Maintaining good code quality is difficult in general—whether outsourcing to a development firm or handling with internal resources. Both scenarios require the team to establish code rules, code review processes, and other style considerations at the beginning of a project.
Problems can arise when the decision of outsourcing is made because of fast growth and the company hasn’t yet established the process and guidelines for using an outsource partner.
“If an outsourcing company doesn’t have code standards, it will be difficult to ensure their developers align with the practices of the client, and this may affect the progress of the project.” – Abel Gonzalez
When working with an outsourced team, ask them to engage in code reviews—they should have the same responsibility for reviewing code as your internal engineers. Also ask the outsource team to contribute to and be aware of architectural decisions.
Other issues to discuss with the outsource team include the best practices and coding standards they follow, and what they use for linting tools, frameworks, and design patterns. Also ask about their process for code reviews, validation, testing, and static analysis. Ideally, their methods should align to the methods of internal software developers.
Once a project begins, communicate frequently, conduct joint code reviews, and ensure the outsource engineers follow and align with those practices. It’s also important to keep internal developers informed about how code handled by an outsource engineer works so that maintenance of that code can continue if handed back to the internal team. A good outsourcing firm should be able to make suggestions and improvements to the way your internal team has been working.
“We believe that it’s crucial that we meet/exceed the existing standards of our clients, and then make specific recommendations to improve—this can be on process, collaboration, or any aspect of quality. We aim to make our clients stronger as we work alongside them.” – Scott Varho
How 3Pillar Maintains Quality and Suggests Improvements for Clients
The 3Pillar Engineering Analysis Report (EAR)
3Pillar helps clients measure the quality of their software products and application code with our Engineering Analysis Report (EAR). The collection of assessments measure the quality of the inputs (process and collaboration) and the quality of the outputs of product development. We also evaluate the delivery eﬃciency of the software engineering team and its use of Agile practices and culture.
After conducting the assessments, our team presents targeted recommendations for improvement. The results are presented to clients to foster a discussion around how to improve the code and the processes used in building software products.
The 3Pillar EAR consists of two major components:
Engineering Health Index (EHI)
The Engineering Health Index measures engineering excellence, quality, and craft. This includes an assessment of the non-feature quality elements of the code: reliability, maintainability, deployability, performance and security.
For the assessment, 3Pillar utilizes tools and techniques for automating the discovery of deficiencies in any of these areas, and we analyze all the items with checklists to determine the thresholds established for each category on a scale of 1 to 5. The tools and techniques selected depend on the frameworks and architecture of the product.
Process Health Check (PHC)
The Process Health Check assesses the software development culture and analyzes code development processes. Through a series of questions, we evaluate the quality of collaboration, a prerequisite to innovative ideas and high throughput for the software development team:
- Is there a software product roadmap?
- Is the map available for the software engineering team to review?
- Is the team aware of the direction the business owners want the project to take?
- Is there proper release/iteration planning?
- Is there a process for grooming?
- Does the team write comprehensible user stories?
- Is there a definition of done?
- How well do continuous integration and continuous testing work?
- How well does the team communicate?
- Are there any issues onboarding or de-boarding resources?
- Are there retrospectives?
- Do the development processes work well?
We grade the answers to each question on a 1-5 scale so both the client and our team get the most out of the product development experience.
Analysis Summary and Recommendations
After completing the EHI and PHC, we create a summary of the items evaluated. This includes the analysis, grades and recommendations for improvements in each area and the quality of the code.
The EAR metrics can be used for ongoing projects by sharing the results of the assessments and recommendations where software engineering teams can improve. For new projects, 3Pillar can leverage EAR to help clients set up best practice standards and determine which quality metrics to track.
Putting EAR Into Practice – Sample Success Stories
Here are a few examples of how EAR has helped 3Pillar clients:
- Demonstrates the importance of CI/CD and automated testing—We presented our EAR report to the client and then demonstrated the advantages of implementing automated solutions. We also convinced the product owner to include automation in the project roadmap. After putting CI/CD process in place and getting to 99% test coverage, the benefits were already visible: both the quality of the product and the speed of delivery improved.
- Prevents security issues—Going through the EAR report for this client involved proactively looking for risks and concerns, and we found several security issues: SQL injection, data mining keys saved in databases, and passwords saved in clear text. Issues like these often go unnoticed in big, complex projects, and there’s not enough time to go through all the different components at once. We fixed the issues and came up with solutions to proactively prevent them from occurring—instead of just reacting to putting out fires.
- Enriches user-story content—The client discovered it had a lot of user stories in the backlog that didn’t have any content besides the title. The developer who wrote them might have had all the context they needed, but if that person left the team, the other developers would not have access to this critical information. Through the use of the EAR report, we raised awareness over this issue and as a result, the client now has much more comprehensive descriptions and detailed user-acceptance criteria as part of the user stories.
- Strengthens team-member relationships—Going through the EAR process with the whole software team at this client made every member feel like their voice was listened to. It helped increase trust, ensured transparency in the process, and enabled collaboration and communication. It also improved relationships among team members, which in turn improved the quality of the software product. When going through the EAR process, the client realized it’s important to include everyone—not only the team and technical leads. Brainstorming together brings out new recommendations and ideas along with a team-building effect.
In each of these cases, as the clients implemented the EAR this process, they saw progress and were able to measure their success. Over time, they also saw if grades improved and how well their software engineering teams worked together.
A Process That Continuously Adds Value
An application is never done. Planning the features, developing the code, and implementing doesn’t mean the project is finished. Software always changes, as do the environments in which the software functions. This means the code needs to adapt and be maintained, and everything needs to be re-evaluated—on a regular basis.
To address this need, 3Pillar recommends conducting its Engineering Analysis Report (EAR) every six months to analyze the state of your code as well as the process to develop the code. Both aspects impact the success of a project and enable you to funnel your learnings through every stage of delivery of a software product.
Besides continuously improving the quality of the code, going through the EAR process builds an environment of trust among internal and outsource software teams—where everyone feels free to communicate and collaborate. It builds team spirit by giving everybody the right to speak up and come up with ideas on how to make things better. This process represents a powerful weapon for improving the process and the product.
“Jocko Willink says ‘Discipline equals Freedom’ in his book, Extreme Ownership. When the team is disciplined about code quality, it gains the freedom to experiment, to make things go faster, to release early, and to release often. The team takes extreme ownership of the product delivery.” – Sayantam Dey
For more information on how the 3Pillar Engineering Analysis Report can help your company improve the quality of your software code, contact 3Pillar today.