How We Make Sure Our Code Meets Our High Standards
In a previous post, we talked about what it means to have “high quality code” and why that matters to our clients’ businesses. Focusing on high-quality code in the app development process creates long-term time and budget savings and a better, more sustainable product. Our dedication to developing and designing high-quality apps sets us apart from our competitors, and we have some principles and specific practices that we adhere to in order to ensure our code truly is high quality.
We use Git and GitHub throughout every project so that everyone on the team can see what is being written, what changes are being made and who is making those changes. This helps us to keep each other sharp, and to make sure we have many sets of eyes on what’s being written on the project. We believe in the benefits of this GitHub flow, and have even written about it a few times.
Pull requests, or “PRs”, are a standard part of our development process. What this means is that no one adds code without a review from a teammate. Once a peer review has happened and feedback has been given, the code then must be approved by multiple people before it can be merged into the “master branch,” or main body of the code. Our use of the GitHub flow model ensures that our developers are free to try new ideas and experiment with the code in a safe environment, without breaking the main codebase.
Both writer and reviewer are responsible for the quality of the code, which helps avoid the natural personal bias and ensure everyone is held to a high standard. Writer and reviewer often pair—that is, meet in person or via Google Hangouts—to talk through feedback. This way, when the code in question is finally merged into the master branch, everyone involved in the writing and review process shares accountability.
Science y’all. As part of development, we write tests along the way that check that the code we are writing does exactly what it is supposed to do. If our code passes the test, it’s able to move forward. This is part of test-driven development, in which a computer can check thousands of lines of code for errors much faster than a programmer. As we create increasingly complex codebases, this allows us to ensure that the code quality stays high without dedicating hundreds of hours to review.
These tests become a permanent part of the codebase so they can continue to ensure that future work does not break parts of the code. Without tests, we would have to rely on constant, manual quality assurance testing. At Big Nerd Ranch, we don’t ship code if tests are failing because we hold to our principles—to save you time and money in the long run.
A Few Notes on Testing
We won’t go too far into this subject here since it is extensive enough to be its own blog post series, but there are a few types of testing we employ.
- Unit tests: These test smaller, more targeted bits of the code.
- Integration tests: These test the interactions between pieces.
- Testing of the UI: This is a mix of automated and manual testing, depending on what makes sense.
A note on test coverage—we don’t aim for 100% coverage. We target the most complex areas of the app with unit tests, and test the UI either manually or with automated tests. This helps us ensure that we’re spending our time (and your budget) effectively.
When our developers work on projects, documentation is vital. We always include a README in each codebase, which is an introduction and roadmap that exists within GitHub and helps developers get up-to-speed with the project.
In addition, inline comments are used whenever there is something that we think may cause confusion later down the road. Think of these as akin to notes in page margins—they allow other developers to understand what a piece of code is used for or why it is placed in a certain section. This is useful not only for our own developers as they transition on and off of projects, but also for your developers as they take over the code once the project is complete.
In my last post, we talked about technical debt, which is the pile of inconsistencies that accumulate between existing code and newer code as changes are made to the app. Ideally, we allow a little time in every sprint to address the natural amount of technical debt that builds up as we go. This idea of refactoring along the way is important—it ensures that our code is not bogged down with issues and works efficiently, which prevents backtracking and maintains a more solid codebase at any given time.
Why The Fuss?
All this seems like a lot of extra work, and it is. But the fact of the matter is that we care a lot about our clients’ bottom lines and solving their business challenges. It’s part of who we are and our shared company values of being hardworking, brilliant and kind.
All of the practices mentioned above help us produce code of the highest quality, which helps you meet your current business needs and prepare for the future as the technology—and your codebase—continues to change.