瀏覽代碼

doc: add style doc for backend

KernelDeimos 2 月之前
父節點
當前提交
9180261472
共有 1 個文件被更改,包括 212 次插入0 次删除
  1. 212 0
      src/backend/doc/contributors/coding-style.md

+ 212 - 0
src/backend/doc/contributors/coding-style.md

@@ -0,0 +1,212 @@
+# Backend Style
+
+## File Structure
+
+### Copyright Notice
+
+All files should begin with the standard copyright notice:
+
+```javascript
+/*
+ * Copyright (C) 2025-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+```
+
+### Imports
+
+```javascript
+const express = require('express');
+const passport = require('passport');
+
+const { get_user } = require("../../helpers");
+const BaseService = require("../../services/BaseService");
+const config = require("../../config");
+
+const path = require('path');
+const fs = require('fs');
+```
+
+Import order is generally:
+1. Third party dependencies. Having these occur first makes it easy to quickly
+   determine what this source file is likely to be responsible for.
+2. Files within the module.
+3. Standard library, "builtins"
+
+## Code Formatting
+
+### Indentation and Spacing
+
+```javascript
+const fn = async () => {
+    const a = 5; // Spaces between operators
+
+    // Note: "=" in for loop initializer does not require space around
+    // Note: operators in condition part have space around
+    for ( let i=0; i < 10; i++ ) {
+        console.log('hello');
+    }
+    
+    // Control structures have space inside parenthesis
+    for ( const thing of stuff ) {
+        // NOOP
+    }
+    
+    // Function calls do not have space inside parenthesis
+    await something(1, 2);
+}
+```
+
+- Use 4 spaces for indentation.
+- Use spaces around operators (`=`, `+`, etc.); not required in
+  for loop initializer.
+- Use a space after keywords like `if`, `for`, `while`, etc.
+  ```javascript
+  return [1,2,3]; // Sure
+  return[1,2,4];  // Definitely not
+  ```
+- Use spaces between parenthesis in control structures unless
+  parenthesis are empty.
+  ```javascript
+  if ( a === b ) {
+    return null;
+  }
+  ```
+- No trailing whitespace at the end of lines
+- Use a space after commas in arrays and objects
+- Empty blocks should have the comment `// NOOP` within braces
+
+### Line Length
+
+- Try to keep lines under 100 characters for better readability
+  - Try to keep them under 80, but this is not always practical
+- For long function calls or objects, break them into multiple lines
+
+
+### Trailing Commas
+
+```javascript
+// This is great
+{
+    "apple",
+    "banana",
+    "cactus", // <-- Good!
+}
+
+// This is also fine
+[
+    1, 2, 3,
+    4, 5, 6,
+    7, 8, 9,
+]
+
+[
+    something(),
+    another_thing(),
+    the_last_thing() // <-- Nope, please add trailing comma!
+]
+```
+
+We use trailing commas where applicable because it's easier to re-order
+lines, especially when using vim motions.
+
+### Braces and Blocks
+
+- Single statement blocks must either be on the same line as
+  the corresponding control structure, or surrounding by braces:
+  ```javascript
+  if ( a === b ) return null; // Sure
+  if ( a === b )
+      return null; // Please no 🤮
+  if ( a === b ) {
+      return null; // Nice
+  }
+  ```
+- Opening braces go on the same line as the statement
+- Put a space before the opening brace
+
+
+## Naming Conventions
+
+### Variables
+
+- Variables are generally in camelCase
+- Variables might have a prefix_beforeThem
+
+```javascript
+const svc_systemData = this.services.get('system-data');
+const svc_su = this.services.get('su');
+effective_policy = await svc_su.sudo(async () => {
+    return await svc_systemData.interpret(effective_policy.data);
+});
+```
+
+In the example above we see the `svc_` prefix is used to indicate a
+reference to a backend service. The name of the service is `system-data`
+which is not a valid identifier, so we use `svc_systemData` for our
+variable name.
+
+### Classes
+
+- Use PascalCase for class names
+- Use snake_case for class methods
+- Instance variables are often `snake_case` because it's easier to
+  read. `camelCase` is acceptable too.
+- Instance variables only used internally should have a
+  `trailing_underscore_` even if in `camelCase_`. We avoid using
+  `#privateProperties` because it unnecessarily inhibits debugging
+  and patching.
+
+### File Names
+
+- Use PascalCase for class files (e.g., `UserService.js`)
+- Use kebab-case for non-class files (e.g., `auth-helper.js`)
+
+## Documentation
+
+### JSDoc Comments
+
+- Backend services (classes extending `BaseService`) should have JSDoc comments
+- Public methods of backend services should have JSDoc comments
+- Include parameter descriptions, return values, and examples where appropriate
+
+```javascript
+/**
+ * @class UserService
+ * @description Service for managing user operations
+ */
+
+/**
+ * Get a user by their ID
+ * @param {string} id - The user ID
+ * @returns {Promise<Object>} The user object
+ * @throws {Error} If user not found
+ */
+async function getUserById(id) {
+    // ...
+}
+```
+
+### Inline Comments
+
+- Use inline comments to explain complex logic
+- Prefix comments with tags like `track:` to indicate specific purposes
+
+```javascript
+// track: slice a prefix
+const uid = uid_part.slice('uid#'.length);
+```