Surf has been in the app development market since 2011, and we have been creating apps for KFC, Mars, the Home Depot, and other market leaders. We collaborate with fintech, banking, foodtech, and retail industries where fast product delivery, reliability, and safety are vital. Our clients trust us with the present and the future of their businesses, so we cannot afford any compromises in the quality of our products. The app or software quality implies an intuitive user interface, thorough testing, reliable security, and high code quality.
In this article, we will go through the latter, but definitely not the least important, aspect. We want to share with you some proven practices in source code quality monitoring and measuring we use through our Flutter cross-platform development department.
But before doing that, let’s make a quick recap of what the term “quality code” stands for.
What is quality code?
The quality code, or clean code, is the code that is easy to read, maintain, and extend.
To better understand how important code quality is for the overall product quality, let’s refer to ISO/IEC 25010:2011 Systems and software engineering — Systems and software Quality Requirements and Evaluation (SQuaRE) — System and software quality models. The standard defines eight software quality characteristics, as shown in the image below.
Within this quality model, the code quality and coding practices have a direct correlation with four characteristics, namely Security, Reliability, Performance Efficiency, and Maintainability. The focus on measuring and monitoring quality at the code level helps avoid unacceptable operational risks and excessive IT costs for your business.
Code quality at Surf
We at Surf believe that a high-quality code is a code that requires the least amount of maintenance and minimum attention after it was written, and we return to it only when we need to change anything.
The key points that define a high-quality code are as follows:
- It works well;
- The style is consistent;
- It is easy to understand;
- It is well-documented;
- It can be tested.
To achieve all the points mentioned, we adhere to a definite culture of code within a complete mobile app development process. We apply the same generally accepted principles for writing code for every project and use any possibility to improve our coding practices.
Surf code quality best practices
Whatever our task is, we always focus on security and strive to deliver our clients more than they expect. For example, even at the mobile app designing prod, we are attentive to the client’s existing products. In case of detecting eventual vulnerabilities, we are ready to help fix them.
When writing code, our developers consider any security implication of their work:
- code shall be secure and exclude any vulnerabilities;
- there shall be no logic errors and bugs that make the product vulnerable to attacks;
- the tools and libraries we use are up-to-date and have no security-related issues;
- along with complying with general safety rules and procedures we practice penetration tests or any other types of tests according to the client’s needs.
Our developers have solid expertise in both manual and automated tests. Tests differ for cross-platform and native development, but there is a single approach within our company. Our goal is to achieve maximum possible code coverage to exclude quality gaps or weak points in our products.
- Golden tests refer to a type of test that helps ensure that UI does not change after adding new features. It makes it easier to control that some layout changes on definite devices do not look breaking. You do not need to take multiple devices to check whether this or that particular feature looks as expected. Our developers create a task with certain conditions and parameters (width, height, pixel ratio) and run the tests to compare the images.
- Unit tests allow checking a specific part of the system without emulating the work of the application. For example, you can ensure that the component controller sets the desired state. In Surf, the unit tests are written by developers, as they are more involved in describing the internal logic of the application.
Two following types of tests, namely widget and End-to-End tests, are written by QA engineers, as they refer more to the operation of the finished application and the verification of user scripts. But they also help improve the code quality through early detection and bug fixing.
- Widget tests are a level above the unit tests. They allow emulating widgets and perform the necessary tests with their help. This is especially beneficial for Flutter, because Flutter applications are entirely made of widgets. It can be a whole screen or its elements: data entry fields, buttons, and so on. In general, widget tests are written not only by QA specialists, but by developers as well. It depends on the purpose of the tests.
- E2E (End-to-End) tests check the operation of the entire application and simulate user actions (swipes, button presses, filling out forms) in realistic infrastructure with realistic services, Application Programming Interfaces (APIs), and everything required. In Flutter development, such tests are called integration tests. These tests are carried out before each build and before release – they take a lot of time, but they allow us to check the app quality thoroughly.
Collecting and analyzing code quality metrics
We automatically collect software code quality metrics from our projects on a regular basis and analyze them to determine the best values and methods to achieve them. The metric reports allow us to monitor any eventual suspicious cases to avoid them.
The metrics we monitor:
- Cyclomatic complexity indicates the program complexity. It is a quantitative measure of linearly independent paths through a program’s source code. If the cyclomatic complexity for a particular function is high, the feature will be hard to understand and more difficult to test. That, in turn, means it can be reasonably expected to have more undetected defects than more simple features.
- Maximum nesting level sets the maximum nesting level for stored procedures and triggers. Code with a deep nesting level is often complex and hard to maintain.
- Number of parameters indicates the number of parameters received by a method.
- Source lines of code is a number of lines in the text of the program’s source code. The metric can be used to predict the effort required to develop a program and to estimate programming productivity or maintainability once the software is produced.
- Number of methods is the total number of methods in a class, where too many methods indicate a high complexity.
- Weight of class is calculated through dividing the number of functional public methods by the total number of public methods. Low values indicate poor encapsulation that makes it difficult to understand the program, thus concealing potential software vulnerabilities
- Maintainability index is an index value that specifies how easy it is to maintain the code. The higher the value is, the better its maintainability.
Choosing the strictest rules
Our developers use static analysis as a method to examine the code without executing the program. It allows us to avoid any programming errors, coding standard violations, undefined values, syntax violations, or security vulnerabilities.
For our Flutter developers, we created a set of rules to be followed. We did not reinvent the wheel and selected the rules among those that already exist. Still, they are beyond the recommended minimum and we are committed to comply with them.
Code linting is automated checking of the source code for programmatic and stylistic errors that is time-saving and efficient. In the near future we plan to create an analysis board to visualize dynamics by projects.
How we improve code quality
There’s no such thing as “too high-quality solution” that is why we continue improving our coding practices and procedures to end up with even better applications:
- We follow and comply with internationally recognized industry-specific software coding standards and rules. Based on these regulations, we have developed our internal procedures and update them as new requirements and conditions appear.
- We have clearly defined roles and responsibility levels. The Team Lead is responsible for the quality within the project, including the quality of the code. The Tech Lead and Department Head are involved in quality monitoring at the higher level through the cross-platform or native development team, and finally, our CTO is responsible for quality at the company level.
- We share expertise inside the company, starting from analyzing the current conditions and taking additional measures to keep the quality at the same level or higher to sharing efficient methods and practices between projects, implementing updated requirements and conditions, and synchronizing regularly.
Surf quality code is a significant part of our expertise that helps us:
- win our clients’ trust, as we ensure good performance and stability, security, easy maintenance and scalability of all apps we develop;
- achieve top positions in ratings: we are on the list of top-5 Flutter developers in the world, as well as 14 app awards received over the past 5 years;
- build a good reputation in the community: we share our best practices on GitHub, our top experts arrange and take part in streams, hackathons, and industry events.