Code review serves several goals in the Carbon project. It directly improves the correctness, clarity, and consistency of contributions, including both code and documentation. These improvements range from the high-level functionality down through the design and implementation details. It also promotes team ownership and spreads knowledge across the team.
More detailed discussions can be found in chapter 9 "Code Review" of the book Software Engineering at Google and chapter 21 "Collaborative Construction" in Code Complete: A Practical Handbook of Software Construction. However, these details aren't essential to understanding code review and how it works in the Carbon project. All of the important details are provided in the project documentation.
Every change to Carbon's repositories requires code review. Even formal evolution decisions which have been approved should have their specific changes to the repository reviewed.
Many changes to Carbon repositories may only require code review. Typically, these include bug fixes, and development or documentation improvements clearly in line with accepted designs. It may in some rare cases extend to exploring experimental or prototype directions whose design is under active consideration.
The term "code review" in the Carbon project is not only about "code". We expect changes to any files to be reviewed, including documentation and any other material stored in the repository.
Everyone should feel free to review Carbon changes. Even providing small or partial review can be a good way to start contributing to Carbon. Contributors with specific domain expertise or familiarity should also try to provide review on changes touching relevant parts of the project.
Additionally, at least one code owner of any file changed needs to review that
change. The code owners and what files they are responsible for are defined
using the
CODEOWNERS
file in the root of the repository. Pull requests will automatically request
reviewers based on this file and enforce that these reviews take place.
While we do encourage people interested in contributing to Carbon by reviewing changes to do so, we also suggest not overloading a single review. It can be daunting for the author of a change to get feedback from a large number of reviewers, and so we suggest keeping the number of reviewers reasonably small.
Any reviews that explicitly request changes should be addressed, either with the changes or an explanation of why not, before a pull request is merged. Further, any code owners who have requested changes should explicitly confirm they're happy with the resolution before the change is merged.
When a team gives an affirm decision on an evolution proposal, each team member should explicitly note any of their comments on the pull request that, while not blocking the decision, still need to be resolved as part of code review prior to it being merged. These might, for example, be trivial or minor wording tweaks or improvements. Otherwise, the decision is assumed to mean the prior review comments from members of that team are addressed; the author is free to merge once the pull request is approved, possibly with a code review separate from the proposal's review.
Carbon uses GitHub pull requests for code review, and we recommend some mechanical best practices to most effectively navigate them.
Files Changed tab.Files Changed tab
and by adding each reply to a new review, and posting them as a batch
when done.Files Changed tab by clicking on the
change listed in the conversation view with the incoming set of in-file
comments.The goal of an author should be to ensure their change improves the overall code, repository, and/or project. Within the context of code review, the goal is to get a reviewer to validate that the change succeeds at this goal. That involves finding an effective reviewer given the particular nature of the change, helping them understand the change fully, and addressing any feedback they provide.
The change description in the pull request is the first thing your reviewers will see. This sets the context for the entire review, and is very important.
The first line of a commit, or the subject of the pull request, should be a short summary of specifically what is being done by that change. It should be a complete sentence, written as though it was an order. Try to keep it short, focused, and to the point.
The description body may need to explain several important aspects of the change to provide context for the reviewer when it isn't obvious from the change itself:
Try to anticipate what information the reviewer of your change will need to have in order to be effective. Also consider what information someone else will need a year in the future when doing archaeology on the codebase and they come across your change without any context.
Small changes have many benefits:
The ideal size of a change is as small as possible while it remains self-contained. It should address only one thing. Often, this results in a change only addressing part of a feature rather than the whole thing at once. This makes work more incremental, letting the reviewer understand it piece by piece. It can also make it much easier to critically evaluate whether each part of a feature is adequately tested by showing it in isolation.
That said, a change should not be so small that its implications cannot easily be understood. It is fine to provide the reviewer context or a framework of a series of changes so they understand the big picture, but that will only go so far. It is still possible to shrink a change so much that it becomes nonsensical in isolation. For example, a change without appropriate tests is not self-contained.
You may want to use a set of stacked pull requests rather than a single, larger pull request in order to keep changes easy to review.
TODO: link to the stacked pull request documentation when available.
Many comments have easy and simple responses. The easiest is "Done". When the comment is a concrete suggestion that makes sense and you implement it, you can simply let the reviewer know their suggestion has been incorporated. If the way you implemented the suggestion might need clarification, add that as well. For example, consider mentioning tweaks to the suggestion or when the suggestion was applied in more places.
When a suggestion from the reviewer is explicitly optional, you may also have a simple response that you're not going to make the change. This is totally fine -- if it weren't, the reviewer shouldn't have listed it as optional -- but it may be helpful to explain your reasoning to the reviewer so they understand better why the optional suggestion didn't make sense to you.
Sometimes comments, even optional ones, center around slight differences or preferences around the code. Consider that the reviewer may be a good proxy for future readers. If the suggestion is essentially equivalent to your original code, consider adopting it as it may make the code easier to read for others. But if you feel the current choice is better, even if only slightly, stand up for yourself and keep it. The reviewer can always push for a change and justify it if needed.
For non-optional comments, this section provides several suggestions on how best to make progress. If none of these work, you may need to resolve an impasse or conflict.
Some comments in code review will be questions or confusion as the reviewer tries to understand the code in question or why a particular approach was used. Don't assume that questions are a request for a change. Reviewers should be explicit if they think a change is needed rather than merely asking questions. You should assume a question or confusion is something which only needs to be clarified.
However, when responding to a question or confusion, consider making changes to improve clarity in addition to responding within the review, such as by adding comments or changing code structure. The reviewer may not be the last person to need more clarity, and you should use their comments as a signal for improvement. Once done, the review response should typically focus on verifying that the clarifications made in the code are sufficient for the reviewer.
At times, review comments may be confusing or frustrating for you. While this is something we always want reviewers to minimize, it will still happen at some times and to some degree. It helps to remember that the goal of the review is to ensure the change results in the project improving over time.
If the review comment doesn't make sense, ask the reviewer to help you understand the feedback better. If it isn't constructive or doesn't seem to provide any meaningful path forward, ask the reviewer to provide this. Making comments both clear and constructive are part of the reviewers' responsibilities.
Once there is a clear and effectively communicated comment that you understand, it may still feel wrong or like it is unnecessarily blocking your progress. It is important to try to step back in this situation and, no matter how certain you are, genuinely consider whether there is valuable feedback. You should be asking yourself whether the reviewer might be correct, potentially in an unexpected or surprising way. If you can't decide this definitively, you may need to work to get a deeper understanding.
If you are confident that the reviewer's comment is incorrect, that is OK. The reviewer is also only human and is certain to make mistakes and miss things. The response needs to try to explain what it is that leads you to be confident in your assessment. Lay out the information you have and how you are reasoning about the issue to arrive at the conclusion. Try not to make assumptions about what the reviewer knows or why they made the comment. Instead, focus on surfacing explicitly your perspective on the issue.
These parts of a review will often be a discussion and may need to iterate a few times. That isn't intrinsically bad, but try to make sure that it doesn't result in reiterating positions or repeating things. Make sure the discussion is progressing towards deeper understanding and recognize when you reach an impasse or conflict and shift strategy to resolve that. It is also useful to avoid long delays between these iterations. Consider discussing over Discord chat or scheduling a quick video chat on the specific issue. This can avoid multi-hour -- or multi-day -- round trips.
The specific goal for a particular review should always be to ensure that the overall health of the code, repository, and/or project improves over time. This requires that contributions make progress -- otherwise, nothing can improve. However, the review should ensure that quality of changes does not cause the health of the project to decrease over time.
The primary responsibility for ensuring that code review remains constructive, productive, and helpful resides in the reviewer. As a reviewer, you are in a position of power and asked to critique the authors hard work. With this power comes responsibility for conducting the review well.
Try to respond to code review requests as soon as you can without interrupting a focused task. At the latest, the next day you are working on the project. Note that the review isn't expected to necessarily be complete after a single review. It is more valuable to give reasonably quick but partial feedback than to delay feedback in order to complete it. If leaving partial feedback, make it clear to the author which parts are covered and which you haven't gotten to yet.
Large changes are especially important to give incremental feedback on in order to do so in a timely fashion. One of the first things to consider with large changes is whether it can be split apart into smaller changes that are easier to review promptly.
This timeliness guidance doesn't apply to the higher-level evolution process reviews. Evaluating those proposals will often require a larger time investment and have their own timelines spelled out in the process. Here, we are talking about simply reviewing changes themselves orthogonally to any evolutionary discussion and evaluation.
Things to consider and evaluate when reviewing changes:
These are general guidelines for writing effective code review comments:
Keep in mind that the goal is to improve the overall health of the code, repository, and/or project over time. Sometimes, there will be pushback on review comments. Consider carefully if the author is correct -- they may be closer to the technical issues than you are and may have important insight. Also consider whether the suggestion is necessary to achieve the overall goal. If the suggestion isn't critical to make the change an overall improvement, it may be fine for it to move forward as-is.
As with all communication in the Carbon project, it is critical that your comments are not unkind, unwelcoming, angry, ad-hominem attacks, or otherwise violating our community's code of conduct.
Be explicit and unambiguous at the end of your review. Select "Approve" when submitting the review to mark this in GitHub. You can always include a message, often "LGTM" or "Looks Good To Me" is often used. If you don't feel like you're in a position to approve the change and are simply helping out with review feedback, make that explicit as well. You should set the review to a "Comment" in GitHub, but also state this explicitly in the message since this is the default and doesn't indicate that your feedback is addressed. For example, say that "my comments are addressed, but leaving the final review to others" to clearly indicate that you're happy but are deferring the decision to others. If you are a code owner and deferring to someone else, it is essential to suggest specific other reviewers. Otherwise, we risk all the code owners assuming another is going to approve the change.
An important technique to make progress, especially with different working hours and timezones, is to approve changes even with outstanding comments. For example, if the comments you have are straightforward and have unambiguous fixes or suggested edits, you should give an LGTM with those comments addressed. The author can always come back to you if they have questions, and we can always revert changes if the resolution for some reason diverges wildly from your expectations.
At some point, a review may reach an impasse or a genuine conflict. While our goal is always to resolve these by building consensus in review, it may not be possible. Both the author and any reviewers should be careful to recognize when this point arrives and address it directly. Continuing the review is unlikely to be productive and has a high risk of becoming acrimonious or worse.
There are two techniques to use to resolve these situations that should be tried early on:
Bring another person into the review to help address the specific issue. Typically they should at least be a code owner, and may usefully be a Carbon lead.
Ask the specific question in a broader forum, such as Discord, in order to get a broad set of perspectives on a particular area or issue.
The goal of these steps isn't to override the author or the reviewer, but to get more perspectives and voices involved. Often this will clarify the issue and its trade-offs, and provide a simple resolution that all parties are happy with. However, in some cases, the underlying conflict isn't actually addressed. While there is a desire to generally bias towards the direction of the code owners during reviews, reviews should not turn into a voting process. The reason for proceeding in a specific direction should always be explained sufficiently that all parties on the review are satisfied by the explanation and don't feel the need to escalate.
Fundamentally, both reviewers and the author need to agree on the direction to move forward. If reaching that agreement proves impossible, the review should be escalated. If you feel like an escalation is needed in a review, be explicit and clear in requesting it. There is nothing bad about going through this process, but it should only occur when needed and so it helps to be very clear.
Once the impasse or conflict is addressed, it is essential to commit to that direction. It can be especially difficult for the author to accept a direction that they initially disagree with and make changes to their code as a result. An essential skill is the ability to disagree and commit.
At the explicit request of any Carbon lead or to resolve any fundamental impasse in a review, the change should move to a formal proposal. Ultimately, the Carbon project governance structure is always available as an escalation path.
Before escalating an impasse or conflict in code review, try asking another reviewer to help resolve the issue or bridge any communication gaps. Consider scheduling a quick video chat to discuss and better understand each others' concerns and position.
Note that the formal evolution process is heavyweight and relatively slow. The expectation is that this is rarely used and only to resolve serious and severe disagreements. If this becomes a more common problem, lighter weight processes may be needed to help ensure a reasonable rate of progress.