Always use // line comments, never /* */ block comments:
// GOOD: Clear explanation before the declaration// Encodes a string to UTF-8 bytes.// Returns an array of bytes representing the encoded string.kj::Array<byte> encodeUtf8(kj::StringPtr text);// BAD: States the obviousint count; // stores the count// BAD: Block comment/* This is a block comment */void foo();
Every declaration in a header file should have a comment if its purpose isn’t immediately obvious:
class RequestTracker {public: // Begins tracking a new request with the given ID. // Returns a handle that automatically stops tracking when destroyed. kj::Own<Request> startRequest(kj::StringPtr id); // Returns the number of currently active requests. uint getActiveCount() const;private: // Map of active request IDs to their start times. kj::HashMap<kj::String, kj::Date> activeRequests;};
Comment every few lines explaining what the next few lines are doing:
void processData(kj::ArrayPtr<byte> data) { // Parse the header to determine the payload size. auto header = parseHeader(data.slice(0, HEADER_SIZE)); // Validate that we have enough data for the payload. KJ_REQUIRE(data.size() >= HEADER_SIZE + header.payloadSize, "incomplete data"); // Extract and process the payload. auto payload = data.slice(HEADER_SIZE, HEADER_SIZE + header.payloadSize); handlePayload(payload);}
// TODO(now): Must be fixed before merging// TODO(soon): Should be addressed in near future// TODO(someday): Nice to have improvement// TODO(perf): Performance optimization opportunity// TODO(security): Security consideration// TODO(cleanup): Code cleanup needed// TODO(test): Additional test needed
TODO(now) comments must be addressed before merging a pull request.
You can also reference specific projects:
// TODO(websockets): Complete when WebSocket redesign lands
# Component Name## OVERVIEWBrief description of what this component does.## KEY CLASSES| Class | File | Role ||-------|------|------|| `MyClass` | `my-class.{h,c++}` | What it does |## WHERE TO LOOK| Task | File(s) ||------|----------|| Do X | `file.c++` |## CONVENTIONS- List of conventions specific to this component## ANTI-PATTERNS- List of things to avoid
/** * Encodes a string to a Uint8Array. * * @param input - The string to encode * @returns The encoded bytes */export function encode(input: string): Uint8Array { return new TextEncoder().encode(input);}
struct WorkerOptions { # Configuration options for a worker. compatibilityDate @0 :Text; # Date in YYYY-MM-DD format determining which compatibility flags # are enabled by default. compatibilityFlags @1 :List(Text); # Explicitly enabled compatibility flags that override the date-based # defaults.}
// GOOD: Shows typical usage// Example:// auto promise = fetchUrl("https://example.com");// auto response = promise.wait(waitScope);// auto text = response.text.wait(waitScope);kj::Promise<HttpResponse> fetchUrl(kj::StringPtr url);// GOOD: Shows both success and error cases// Example:// KJ_IF_SOME(user, findUser("alice")) {// // user found// } else {// // user not found// }kj::Maybe<User> findUser(kj::StringPtr name);
// GOOD// Returns the user's name, or null if not set.kj::Maybe<kj::StringPtr> getName();// BAD// This method is used to retrieve the name of the user. It will return// the name if one has been set, otherwise it returns null to indicate// that no name is available.kj::Maybe<kj::StringPtr> getName();
// GOOD// Returns a borrowed pointer valid until this object is destroyed.const Data* getData() const;// BAD// Returns the data.const Data* getData() const;
// GOOD// Validates the input and throws if invalid.void validate(Input input);// BAD// Will validate the input and will throw if it is invalid.void validate(Input input);
When deprecating APIs, document why and what to use instead:
// DEPRECATED: Use getCount() instead. This method will be removed// in a future version.// // The old name was confusing because it actually returns the count,// not the size in bytes.uint getSize() { return getCount(); }// Returns the number of items.uint getCount();