Introduction to Naming Conventions

Consistent and clear naming conventions are crucial for writing maintainable, readable, and collaborative codebases. This document outlines a set of universal and language-specific naming guidelines to ensure uniformity across all AutoCode projects. Adhering to these conventions significantly reduces cognitive load for developers, streamlines code reviews, and accelerates onboarding for new team members.

The goal is to establish a common vocabulary and structure that makes it easy to understand the purpose and behavior of any element—be it a class, method, variable, or database table—just by looking at its name.


Universal Naming Conventions

These conventions apply across all programming languages and technologies unless explicitly overridden by language-specific guidelines. They aim to provide a baseline for consistency in common patterns.

Classes

Classes represent blueprints for objects and should be named using PascalCase. Names should be nouns or noun phrases that clearly describe the entity they represent.

  • Convention: PascalCase
  • Examples: UserProfile, OrderProcessor, ConfigurationManager
// Example (Conceptual)
class UserProfile { /* ... */ }
class OrderProcessor { /* ... */ }

Interfaces

All interfaces must start with the uppercase letter I, followed by a PascalCase name that describes the contract they define.

  • Convention: IPascalCase
  • Examples: IAuthenticatable, IRepository, IUserService
// Example (Conceptual)
interface IAuthenticatable { /* ... */ }
interface IUserService { /* ... */ }

Enums & Enum Values

Enums (enumerations) should be declared with the prefix AcEnum, followed by a PascalCase name. Individual enum values should also use PascalCase.

  • Convention (Enum): AcEnumPascalCase
  • Convention (Enum Value): PascalCase
  • Examples: AcEnumUserRole (enum), Admin, Editor, Viewer (values)
// Example (Conceptual)
enum AcEnumUserRole {
    Admin,
    Editor,
    Viewer
}

Model Classes (Data Transfer Objects / Entities)

Model classes, often used for data transfer or representing database entities, should follow the standard class naming (PascalCase). They must include specific methods for serialization and deserialization:

  • fromJson(json: JsonType): ThisClass: A static factory method that creates an instance of the model from a JSON object.
  • instanceFromJson(json: JsonType): this: An instance method that initializes or updates the current instance from a JSON object. This is useful for chaining operations.
  • toJson(): JsonType: An instance method that converts the model instance to a JSON object.
  • Convention (Class): PascalCase
  • Convention (Methods): fromJson, instanceFromJson, toJson
// TypeScript Example
interface JsonType { [key: string]: any; }

class User {
    id: string;
    firstName: string;
    lastName: string;
    email: string;

    constructor(id: string = '', firstName: string = '', lastName: string = '', email: string = '') {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    // Static factory method to create an instance from JSON
    static fromJson(json: JsonType): User {
        return new User(
            json.id,
            json.firstName,
            json.lastName,
            json.email
        );
    }

    // Instance method to initialize/update from JSON
    instanceFromJson(json: JsonType): this {
        this.id = json.id || this.id;
        this.firstName = json.firstName || this.firstName;
        this.lastName = json.lastName || this.lastName;
        this.email = json.email || this.email;
        return this; // Return this for chaining
    }

    // Instance method to convert to JSON
    toJson(): JsonType {
        return {
            id: this.id,
            firstName: this.firstName,
            lastName: this.lastName,
            email: this.email
        };
    }

    // Example of a chained method
    updateEmail(newEmail: string): this {
        this.email = newEmail;
        return this;
    }

    // Another example for chaining
    save(): this {
        console.log("Saving user:", this.toJson());
        return this;
    }
}

// Usage example:
const userJson = { id: "123", firstName: "John", lastName: "Doe", email: "john.doe@example.com" };

// Using static fromJson
const user1 = User.fromJson(userJson);
console.log(user1.toJson());

// Using instanceFromJson for chaining
const user2 = new User().instanceFromJson(userJson).updateEmail("new.email@example.com").save();
console.log(user2.toJson());

Methods & Parameters

Methods should be named using camelCase. Names should be verbs or verb phrases that clearly describe the action the method performs.

  • Convention (Method): camelCase
  • Examples: getUserProfile, processOrder, saveConfiguration

Named Parameters: For languages that support it (like TypeScript), all methods should prefer named parameters. This improves readability and reduces errors, especially for methods with many parameters.

// TypeScript Example with Named Parameters
function createUser({ firstName, lastName, email }: { firstName: string; lastName: string; email: string; }): User {
    // ... logic to create and save user
    console.log(`Creating user: ${firstName} ${lastName}, Email: ${email}`);
    return new User('new-id', firstName, lastName, email);
}

// Usage
const newUser = createUser({ firstName: "Alice", lastName: "Smith", email: "alice.smith@example.com" });

class UserService {
    // Method with named parameters
    updateUser({ userId, newEmail, newStatus }: { userId: string; newEmail?: string; newStatus?: string; }): User {
        console.log(`Updating user ${userId}: email=${newEmail}, status=${newStatus}`);
        // ... actual update logic
        return new User(userId, 'Updated', 'User', newEmail || '');
    }
}

const service = new UserService();
service.updateUser({ userId: "456", newEmail: "alice.updated@example.com" });
service.updateUser({ userId: "789", newStatus: "Active" });

Prefer Return Instance Over Void

Whenever possible, methods that modify an object's state should return the modified instance (this) rather than void. This allows for fluent interfaces and method chaining, enhancing readability and conciseness, like user.create().update().delete().

  • Convention: Return this (or the modified object) for state-modifying methods.
// TypeScript Example
class Product {
    name: string;
    price: number;
    stock: number;

    constructor(name: string, price: number, stock: number) {
        this.name = name;
        this.price = price;
        this.stock = stock;
    }

    // Method that returns 'this' for chaining
    setPrice(newPrice: number): this {
        this.price = newPrice;
        return this;
    }

    // Method that returns 'this' for chaining
    adjustStock(quantity: number): this {
        this.stock += quantity;
        return this;
    }

    // A method that might return a new object or simply perform an action, not necessarily 'this'
    saveToDatabase(): Promise {
        console.log(`Saving product ${this.name} to DB.`);
        return Promise.resolve();
    }
}

const myProduct = new Product("Laptop", 1200, 50);

// Chaining methods
myProduct
    .setPrice(1150)
    .adjustStock(-5)
    .saveToDatabase(); // Final action might not return 'this' if it's async or a terminal operation

Project Naming Conventions

Consistent project and package naming are essential for organizing large codebases and fostering clarity when integrating different components.

Libraries/Packages/Modules

Libraries, packages, and modules should be named descriptively, typically using kebab-case for folder names and package names in package managers (like npm, pub.dev). The internal module/namespace names within the code should follow the language's specific conventions (e.g., PascalCase for C# namespaces, snake_case for Python modules).

  • Convention (Folder/Package Name): kebab-case (e.g., user-management-lib, data-access-service)
  • Convention (Internal Module/Namespace): Follow language-specific guidelines (e.g., UserManagement, DataAccess).
// Example Directory Structure
my-project/
├── core-utils/             // Library folder (kebab-case)
│   ├── src/
│   │   └── CoreUtils.cs    // C# Class/Namespace (PascalCase)
│   └── package.json        // npm package name: core-utils
├── user-service/           // Microservice folder (kebab-case)
│   ├── src/
│   │   └── user_service.py // Python module (snake_case)
│   └── pubspec.yaml        // Dart package name: user_service

Functionality Implementation

When implementing specific functionalities (e.g., a "login feature"), the naming should be clear and descriptive, typically reflecting the core business domain or technical concern.

  • Folders: kebab-case (e.g., auth-feature, product-catalog)
  • Classes/Components: Follow language/framework-specific conventions (e.g., AuthService, ProductCatalogComponent).
// Example (Conceptual)
features/
├── auth-feature/
│   ├── components/
│   │   └── LoginComponent.vue   // Vue component
│   ├── services/
│   │   └── AuthService.ts       // TypeScript service
│   └── models/
│       └── LoginRequest.ts      // TypeScript model
├── payment-gateway/
│   ├── controllers/
│   │   └── PaymentController.java // Java controller
│   └── models/
│       └── PaymentDetails.java    // Java model

Language-Specific Naming Conventions

While universal conventions provide a baseline, each programming language has its idiomatic naming practices. This section details conventions specific to popular languages and frameworks.

C#

C# generally follows Microsoft's .NET naming guidelines, emphasizing readability and consistency within the ecosystem. Official Microsoft .NET Naming Guidelines

  • Files: PascalCase.cs (Matching the primary class/interface within).
  • Namespaces: PascalCase (e.g., AutoCode.Core.Utilities).
  • Classes, Structs, Records: PascalCase (e.g., UserProfileService, ProductData).
  • Interfaces: IPascalCase (e.g., IUserService, IDataRepository).
  • Enums: AcEnumPascalCase (e.g., AcEnumOrderStatus). Enum values: PascalCase (e.g., Pending, Completed).
  • Methods: PascalCase (Public methods), camelCase (Private helper methods, though PascalCase is also common for private methods).
  • Properties: PascalCase (Public properties).
  • Fields: camelCase (Private fields), often prefixed with _ (e.g., _userId).
  • Local Variables: camelCase (e.g., userName, orderTotal).
  • Constants: PascalCase (e.g., MaxFileSize).
  • Parameters: camelCase (e.g., userId, orderAmount).
using System;
using System.Collections.Generic;

namespace AutoCode.UserManagement
{
    // Interface
    public interface IUserService
    {
        UserProfile GetUserProfile(string userId);
        void UpdateUserProfile(UserProfile userProfile);
    }

    // Enum
    public enum AcEnumUserRole
    {
        Admin,
        Moderator,
        Guest
    }

    // Model Class
    public class UserProfile
    {
        // Public Properties
        public string Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public AcEnumUserRole Role { get; set; }

        // Private field
        private DateTime _createdAt;

        public UserProfile() {
            _createdAt = DateTime.UtcNow;
        }

        // Static factory method
        public static UserProfile FromJson(string jsonString)
        {
            // Deserialize JSON to UserProfile
            // In a real app, use a library like System.Text.Json
            Console.WriteLine($"Deserializing user from JSON: {jsonString}");
            return new UserProfile {
                Id = "FromJsonId",
                FirstName = "Json",
                LastName = "User",
                Email = "json@example.com",
                Role = AcEnumUserRole.Guest
            };
        }

        // Instance method to update from JSON (chained)
        public UserProfile InstanceFromJson(string jsonString)
        {
            // Update current instance from JSON
            Console.WriteLine($"Updating instance from JSON: {jsonString}");
            this.FirstName = "UpdatedJson";
            this.Email = "updatedjson@example.com";
            return this; // Return this for chaining
        }

        // Instance method to convert to JSON
        public string ToJson()
        {
            // Serialize UserProfile to JSON
            // In a real app, use a library like System.Text.Json
            return $"{{ \"Id\": \"{Id}\", \"Email\": \"{Email}\" }}";
        }

        // Public method
        public UserProfile UpdateEmail(string newEmail)
        {
            Email = newEmail;
            return this; // For chaining
        }

        // Private helper method
        private void LogActivity(string activity)
        {
            Console.WriteLine($"[{_createdAt}] Activity: {activity}");
        }
    }

    // Service Class
    public class UserService : IUserService
    {
        // Public method (PascalCase) with named parameters (conceptual in C# 9+, actual depends on records/init-only setters)
        // C# doesn't have true "named parameters" like Python, but you can use object initializers
        public UserProfile GetUserProfile(string userId)
        {
            // ... logic to get user profile
            Console.WriteLine($"Fetching profile for user: {userId}");
            return new UserProfile { Id = userId, FirstName = "John", LastName = "Doe" };
        }

        public void UpdateUserProfile(UserProfile userProfile)
        {
            // ... logic to update user profile
            Console.WriteLine($"Updating profile for user: {userProfile.Id}");
        }

        // Example of returning instance for chaining
        public UserService SaveChanges(): UserService {
            Console.WriteLine("Saving changes to data store...");
            return this;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Using the model and chaining
            UserProfile user = new UserProfile { Id = "1", FirstName = "Jane", Email = "jane@example.com" };
            user.UpdateEmail("jane.new@example.com")
                .InstanceFromJson("{ \"FirstName\": \"JaneX\" }")
                .ToJson(); // Just calling toJson, output not shown here.

            Console.WriteLine($"User Email: {user.Email}");

            // Using static fromJson
            UserProfile jsonUser = UserProfile.FromJson("{...some json...}");
            Console.WriteLine($"JSON User Email: {jsonUser.Email}");

            // Using service
            UserService service = new UserService();
            service.SaveChanges();
        }
    }
}

TypeScript

TypeScript builds on JavaScript, adding static types. Its naming conventions largely mirror JavaScript but with added considerations for types and interfaces. TypeScript Official Guidelines

  • Files: kebab-case.ts for general modules, PascalCase.ts for classes/interfaces that are the main export (e.g., user-service.ts, UserProfile.ts).
  • Folders: kebab-case.
  • Classes: PascalCase (e.g., UserService, Product).
  • Interfaces: IPascalCase (e.g., IUser, IProductRepository).
  • Types (Type Aliases): PascalCase (e.g., UserPayload, OrderStatus).
  • Enums: AcEnumPascalCase (e.g., AcEnumOrderStatus). Enum values: PascalCase or UPPER_SNAKE_CASE (for string enums or constants).
  • Functions/Methods: camelCase (e.g., fetchUsers, processOrder).
  • Variables: camelCase (e.g., userName, isActive).
  • Constants: UPPER_SNAKE_CASE (global constants, e.g., API_KEY), or camelCase (local constants, e.g., maxRetries).
  • Parameters: camelCase.
  • Named Parameters: Use object destructuring for named parameters, as shown in the universal conventions section.
// user.ts file
// Represents a user model
interface JsonType { [key: string]: any; }

export class User {
    public id: string;
    public firstName: string;
    public lastName: string;
    public email: string;
    public role: AcEnumUserRole;

    constructor({ id = '', firstName = '', lastName = '', email = '', role = AcEnumUserRole.Guest }: {
        id?: string;
        firstName?: string;
        lastName?: string;
        email?: string;
        role?: AcEnumUserRole;
    } = {}) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.role = role;
    }

    // Static factory method
    public static fromJson(json: JsonType): User {
        return new User({
            id: json.id,
            firstName: json.firstName,
            lastName: json.lastName,
            email: json.email,
            role: json.role ? AcEnumUserRole[json.role as keyof typeof AcEnumUserRole] : AcEnumUserRole.Guest
        });
    }

    // Instance method for chaining
    public instanceFromJson(json: JsonType): this {
        this.id = json.id ?? this.id;
        this.firstName = json.firstName ?? this.firstName;
        this.lastName = json.lastName ?? this.lastName;
        this.email = json.email ?? this.email;
        this.role = json.role ? AcEnumUserRole[json.role as keyof typeof AcEnumUserRole] : this.role;
        return this;
    }

    // Convert to JSON
    public toJson(): JsonType {
        return {
            id: this.id,
            firstName: this.firstName,
            lastName: this.lastName,
            email: this.email,
            role: AcEnumUserRole[this.role]
        };
    }

    // Example of a chained method
    public updateEmail(newEmail: string): this {
        this.email = newEmail;
        return this;
    }

    // Another chained method
    public save(): this {
        console.log("Saving user:", this.toJson());
        // In a real app, this would involve API calls
        return this;
    }
}

// user-role.ts file
export enum AcEnumUserRole {
    Admin,
    Editor,
    Guest
}

// user-service.ts file
import { User, AcEnumUserRole } from './user'; // Assuming 'user.ts' and 'user-role.ts' are in the same folder

// Interface
export interface IUserService {
    getUserById(params: { userId: string }): Promise;
    updateUser(params: { userId: string; newEmail?: string; newRole?: AcEnumUserRole }): Promise;
}

// Class implementing the interface
export class UserService implements IUserService {
    private users: User[] = [
        new User({ id: "1", firstName: "John", lastName: "Doe", email: "john@example.com", role: AcEnumUserRole.Admin }),
        new User({ id: "2", firstName: "Jane", lastName: "Smith", email: "jane@example.com", role: AcEnumUserRole.Editor })
    ];

    public async getUserById({ userId }: { userId: string }): Promise {
        console.log(`Fetching user by ID: ${userId}`);
        const user = this.users.find(u => u.id === userId);
        return user ? User.fromJson(user.toJson()) : null; // Return a fresh instance
    }

    public async updateUser({ userId, newEmail, newRole }: { userId: string; newEmail?: string; newRole?: AcEnumUserRole }): Promise {
        console.log(`Updating user ${userId} with newEmail=${newEmail}, newRole=${newRole}`);
        const user = await this.getUserById({ userId });
        if (!user) {
            throw new Error(`User with ID ${userId} not found.`);
        }
        if (newEmail) {
            user.updateEmail(newEmail);
        }
        if (newRole !== undefined) {
            user.role = newRole;
        }
        user.save(); // Chained save operation
        return user;
    }

    // A private helper method
    private _logActivity(activity: string): void {
        console.log(`[LOG]: ${activity}`);
    }
}

// --- Usage Example (e.g., in main.ts) ---
async function runExamples() {
    const userService: IUserService = new UserService();

    // Create a new user using the model and chaining
    const newUser = new User({ firstName: "Alice", lastName: "Brown", email: "alice@example.com" })
        .updateEmail("alice.new@example.com")
        .save(); // This will log the saving action

    console.log("New user email after chaining:", newUser.email);

    // Fetch and update a user using the service with named parameters
    const existingUser = await userService.getUserById({ userId: "1" });
    if (existingUser) {
        console.log("Existing user:", existingUser.toJson());
        const updatedUser = await userService.updateUser({ userId: "1", newEmail: "john.updated@example.com", newRole: AcEnumUserRole.Editor });
        console.log("Updated user:", updatedUser.toJson());
    }

    // Using fromJson/instanceFromJson
    const userData = { id: "3", firstName: "Bob", lastName: "White", email: "bob@example.com", role: "Guest" };
    const bob = User.fromJson(userData);
    console.log("Bob (fromJson):", bob.toJson());

    bob.instanceFromJson({ email: "bob.updated@example.com", role: "Admin" }).save();
    console.log("Bob (after instanceFromJson chaining):", bob.toJson());
}

runExamples();

Python

Python emphasizes readability and explicit naming, guided by PEP 8. The focus is on clear, descriptive names rather than rigid prefixes for types.

  • Files/Modules: snake_case.py (e.g., user_service.py, data_models.py).
  • Packages: snake_case (e.g., my_package, utilities).
  • Classes: PascalCase (e.g., UserService, Product).
  • Functions/Methods: snake_case (e.g., get_user_profile, process_order). Private methods are prefixed with _ (e.g., _helper_method), and "dunder" (__) methods for name mangling.
  • Variables: snake_case (e.g., user_name, is_active).
  • Constants: UPPER_SNAKE_CASE (e.g., MAX_FILE_SIZE, API_KEY).
  • Parameters: snake_case.
  • Named Parameters: Python inherently supports named parameters (keyword arguments).
  • Enums: AcEnumPascalCase (class name). Enum values: UPPER_SNAKE_CASE (e.g., AcEnumOrderStatus.PENDING).
import json
from enum import Enum

# File: ac_enum_user_role.py
class AcEnumUserRole(Enum):
    ADMIN = "admin"
    EDITOR = "editor"
    GUEST = "guest"

# File: user_model.py
class User:
    def __init__(self, user_id: str = '', first_name: str = '', last_name: str = '', email: str = '', role: AcEnumUserRole = AcEnumUserRole.GUEST):
        self.user_id = user_id
        self.first_name = first_name
        self.last_name = last_name
        self.email = email
        self.role = role

    @staticmethod
    def from_json(json_data: dict) -> 'User':
        """Creates a User instance from a JSON dictionary."""
        return User(
            user_id=json_data.get('id'),
            first_name=json_data.get('firstName'),
            last_name=json_data.get('lastName'),
            email=json_data.get('email'),
            role=AcEnumUserRole(json_data.get('role', AcEnumUserRole.GUEST.value))
        )

    def instance_from_json(self, json_data: dict) -> 'User':
        """Updates the current User instance from a JSON dictionary."""
        self.user_id = json_data.get('id', self.user_id)
        self.first_name = json_data.get('firstName', self.first_name)
        self.last_name = json_data.get('lastName', self.last_name)
        self.email = json_data.get('email', self.email)
        self.role = AcEnumUserRole(json_data.get('role', self.role.value))
        return self # Return self for chaining

    def to_json(self) -> dict:
        """Converts the User instance to a JSON dictionary."""
        return {
            'id': self.user_id,
            'firstName': self.first_name,
            'lastName': self.last_name,
            'email': self.email,
            'role': self.role.value
        }

    def update_email(self, new_email: str) -> 'User':
        """Updates the user's email."""
        self.email = new_email
        return self # Return self for chaining

    def save(self) -> 'User':
        """Saves the user (conceptual)."""
        print(f"Saving user: {self.to_json()}")
        return self

# File: user_service.py
class IUserService: # Python doesn't have explicit interfaces, typically ABCs or informal
    def get_user_by_id(self, user_id: str) -> User | None:
        raise NotImplementedError

    def update_user(self, user_id: str, new_email: str | None = None, new_role: AcEnumUserRole | None = None) -> User:
        raise NotImplementedError

class UserService(IUserService):
    def __init__(self):
        self._users = [
            User(user_id="1", first_name="John", last_name="Doe", email="john@example.com", role=AcEnumUserRole.ADMIN),
            User(user_id="2", first_name="Jane", last_name="Smith", email="jane@example.com", role=AcEnumUserRole.EDITOR)
        ]

    def get_user_by_id(self, user_id: str) -> User | None:
        """Fetches a user by their ID."""
        print(f"Fetching user by ID: {user_id}")
        for user in self._users:
            if user.user_id == user_id:
                return User.from_json(user.to_json()) # Return a copy
        return None

    def update_user(self, user_id: str, new_email: str | None = None, new_role: AcEnumUserRole | None = None) -> User:
        """Updates an existing user's details."""
        print(f"Updating user {user_id} with new_email={new_email}, new_role={new_role}")
        user = self.get_user_by_id(user_id)
        if not user:
            raise ValueError(f"User with ID {user_id} not found.")

        if new_email:
            user.update_email(new_email)
        if new_role:
            user.role = new_role
        user.save()
        return user

    def _log_activity(self, activity: str) -> None:
        """A private helper method."""
        print(f"[LOG]: {activity}")

# --- Usage Example (e.g., in main.py) ---
def run_examples():
    user_service: IUserService = UserService()

    # Create a new user using the model and chaining
    new_user = User(first_name="Alice", last_name="Brown", email="alice@example.com") \
        .update_email("alice.new@example.com") \
        .save()
    print(f"New user email after chaining: {new_user.email}")

    # Fetch and update a user using the service with named parameters
    existing_user = user_service.get_user_by_id(user_id="1")
    if existing_user:
        print(f"Existing user: {existing_user.to_json()}")
        updated_user = user_service.update_user(user_id="1", new_email="john.updated@example.com", new_role=AcEnumUserRole.EDITOR)
        print(f"Updated user: {updated_user.to_json()}")

    # Using from_json/instance_from_json
    user_data = {"id": "3", "firstName": "Bob", "lastName": "White", "email": "bob@example.com", "role": "guest"}
    bob = User.from_json(user_data)
    print(f"Bob (from_json): {bob.to_json()}")

    bob.instance_from_json({"email": "bob.updated@example.com", "role": "admin"}).save()
    print(f"Bob (after instance_from_json chaining): {bob.to_json()}")

if __name__ == "__main__":
    run_examples()

Java

Java's naming conventions are well-established and widely adopted, heavily influencing other C-style languages. Oracle Java Code Conventions

  • Files: PascalCase.java (Must match the public class name within).
  • Packages: alllowercase, separated by dots (e.g., com.autocode.core.utils).
  • Classes, Interfaces, Enums: PascalCase (e.g., UserService, IProductRepository, AcEnumOrderStatus).
  • Enum Values: UPPER_SNAKE_CASE (e.g., PENDING, COMPLETED).
  • Methods: camelCase (e.g., getUserProfile, processOrder).
  • Variables: camelCase (e.g., userName, isActive).
  • Constants (final static): UPPER_SNAKE_CASE (e.g., MAX_FILE_SIZE).
  • Parameters: camelCase.
  • Named Parameters: Java does not natively support named parameters in the same way as Python or C#. However, the builder pattern or method overloading can achieve a similar effect for complex constructors/methods.
// File: AcEnumUserRole.java
package com.autocode.usermanagement.enums;

public enum AcEnumUserRole {
    ADMIN,
    EDITOR,
    GUEST
}

// File: User.java
package com.autocode.usermanagement.models;

import com.autocode.usermanagement.enums.AcEnumUserRole;
import com.fasterxml.jackson.databind.ObjectMapper; // Example for JSON handling

public class User {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private AcEnumUserRole role;

    // Constructor with default values (can use Builder pattern for more complexity)
    public User(String id, String firstName, String lastName, String email, AcEnumUserRole role) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.role = role;
    }

    // Default constructor for deserialization
    public User() {
        this("", "", "", "", AcEnumUserRole.GUEST);
    }

    // Static factory method for fromJson
    public static User fromJson(String jsonString) {
        // In a real application, use a JSON library like Jackson or Gson
        System.out.println("Deserializing user from JSON: " + jsonString);
        try {
            ObjectMapper mapper = new ObjectMapper();
            User user = mapper.readValue(jsonString, User.class);
            return user;
        } catch (Exception e) {
            e.printStackTrace();
            return new User("error", "Error", "User", "error@example.com", AcEnumUserRole.GUEST);
        }
    }

    // Instance method for fromJson (chained)
    public User instanceFromJson(String jsonString) {
        // Update current instance from JSON
        System.out.println("Updating instance from JSON: " + jsonString);
        try {
            ObjectMapper mapper = new ObjectMapper();
            User tempUser = mapper.readValue(jsonString, User.class);
            this.id = tempUser.id != null ? tempUser.id : this.id;
            this.firstName = tempUser.firstName != null ? tempUser.firstName : this.firstName;
            this.lastName = tempUser.lastName != null ? tempUser.lastName : this.lastName;
            this.email = tempUser.email != null ? tempUser.email : this.email;
            this.role = tempUser.role != null ? tempUser.role : this.role;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this; // Return this for chaining
    }

    // Instance method to convert to JSON
    public String toJson() {
        // In a real application, use a JSON library like Jackson or Gson
        System.out.println("Serializing user to JSON.");
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(this);
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }

    // Chained method example
    public User updateEmail(String newEmail) {
        this.email = newEmail;
        return this;
    }

    // Chained method example
    public User save() {
        System.out.println("Saving user: " + this.toJson());
        return this;
    }

    // Getters and Setters (PascalCase for property names)
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void LastName(String lastName) { this.lastName = lastName; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public AcEnumUserRole getRole() { return role; }
    public void setRole(AcEnumUserRole role) { this.role = role; }
}

// File: IUserService.java
package com.autocode.usermanagement.services;

import com.autocode.usermanagement.models.User;
import com.autocode.usermanagement.enums.AcEnumUserRole;

public interface IUserService {
    User getUserById(String userId);
    User updateUser(String userId, String newEmail, AcEnumUserRole newRole);
}

// File: UserService.java
package com.autocode.usermanagement.services;

import com.autocode.usermanagement.models.User;
import com.autocode.usermanagement.enums.AcEnumUserRole;
import java.util.ArrayList;
import java.util.List;

public class UserService implements IUserService {
    private List users; // Private field (camelCase)

    public UserService() {
        this.users = new ArrayList<>();
        this.users.add(new User("1", "John", "Doe", "john@example.com", AcEnumUserRole.ADMIN));
        this.users.add(new User("2", "Jane", "Smith", "jane@example.com", AcEnumUserRole.EDITOR));
    }

    @Override
    public User getUserById(String userId) {
        System.out.println("Fetching user by ID: " + userId);
        for (User user : users) {
            if (user.getId().equals(userId)) {
                // Return a deep copy to prevent external modification
                return User.fromJson(user.toJson());
            }
        }
        return null;
    }

    @Override
    public User updateUser(String userId, String newEmail, AcEnumUserRole newRole) {
        System.out.println("Updating user " + userId + " with newEmail=" + newEmail + ", newRole=" + newRole);
        User user = getUserById(userId);
        if (user == null) {
            throw new IllegalArgumentException("User with ID " + userId + " not found.");
        }

        if (newEmail != null) {
            user.updateEmail(newEmail);
        }
        if (newRole != null) {
            user.setRole(newRole);
        }
        user.save(); // Chained save
        return user;
    }

    // Private helper method
    private void logActivity(String activity) {
        System.out.println("[LOG]: " + activity);
    }
}

// File: Main.java (Example Usage)
package com.autocode.usermanagement;

import com.autocode.usermanagement.models.User;
import com.autocode.usermanagement.services.IUserService;
import com.autocode.usermanagement.services.UserService;
import com.autocode.usermanagement.enums.AcEnumUserRole;

public class Main {
    public static void main(String[] args) {
        IUserService userService = new UserService();

        // Create a new user using the model and chaining
        User newUser = new User("3", "Alice", "Brown", "alice@example.com", AcEnumUserRole.GUEST)
                .updateEmail("alice.new@example.com")
                .save();
        System.out.println("New user email after chaining: " + newUser.getEmail());

        // Fetch and update a user using the service
        User existingUser = userService.getUserById("1");
        if (existingUser != null) {
            System.out.println("Existing user: " + existingUser.toJson());
            User updatedUser = userService.updateUser("1", "john.updated@example.com", AcEnumUserRole.EDITOR);
            System.out.println("Updated user: " + updatedUser.toJson());
        }

        // Using fromJson/instanceFromJson
        String userData = "{\"id\":\"4\",\"firstName\":\"Bob\",\"lastName\":\"White\",\"email\":\"bob@example.com\",\"role\":\"GUEST\"}";
        User bob = User.fromJson(userData);
        System.out.println("Bob (fromJson): " + bob.toJson());

        bob.instanceFromJson("{\"email\":\"bob.updated@example.com\",\"role\":\"ADMIN\"}").save();
        System.out.println("Bob (after instanceFromJson chaining): " + bob.toJson());
    }
}
```

JavaScript

JavaScript naming conventions are generally relaxed but tend towards camelCase for most identifiers. Modern JavaScript often uses modules and constant declarations for better organization. MDN JavaScript Naming Conventions

  • Files: kebab-case.js or camelCase.js (e.g., user-service.js, utilities.js).
  • Folders: kebab-case.
  • Classes: PascalCase (e.g., UserService, Product).
  • Functions/Methods: camelCase (e.g., fetchUsers, processOrder).
  • Variables: camelCase (e.g., userName, isActive).
  • Constants: UPPER_SNAKE_CASE (global constants, e.g., API_KEY), or camelCase (local constants, declared with const).
  • Parameters: camelCase.
  • Named Parameters: Achieved through object destructuring, similar to TypeScript.
  • Enums: AcEnumPascalCase (class name). Enum values: PascalCase or UPPER_SNAKE_CASE (for string enums or constants).
// ac-enum-user-role.js
export const AcEnumUserRole = {
    ADMIN: 'admin',
    EDITOR: 'editor',
    GUEST: 'guest',
};

// user.js
import { AcEnumUserRole } from './ac-enum-user-role.js';

export class User {
    constructor({ id = '', firstName = '', lastName = '', email = '', role = AcEnumUserRole.GUEST } = {}) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.role = role;
    }

    static fromJson(json) {
        return new User({
            id: json.id,
            firstName: json.firstName,
            lastName: json.lastName,
            email: json.email,
            role: Object.values(AcEnumUserRole).includes(json.role) ? json.role : AcEnumUserRole.GUEST
        });
    }

    instanceFromJson(json) {
        this.id = json.id ?? this.id;
        this.firstName = json.firstName ?? this.firstName;
        this.lastName = json.lastName ?? this.lastName;
        this.email = json.email ?? this.email;
        this.role = Object.values(AcEnumUserRole).includes(json.role) ? json.role : this.role;
        return this;
    }

    toJson() {
        return {
            id: this.id,
            firstName: this.firstName,
            lastName: this.lastName,
            email: this.email,
            role: this.role
        };
    }

    updateEmail(newEmail) {
        this.email = newEmail;
        return this;
    }

    save() {
        console.log("Saving user:", this.toJson());
        return this;
    }
}

// user-service.js
import { User } from './user.js';
import { AcEnumUserRole } from './ac-enum-user-role.js';

// Conceptual Interface for documentation purposes (JS doesn't have native interfaces)
// const IUserService = {
//     getUserById: ({ userId }) => {},
//     updateUser: ({ userId, newEmail, newRole }) => {},
// };

export class UserService {
    #users = [ // Private class field
        new User({ id: "1", firstName: "John", lastName: "Doe", email: "john@example.com", role: AcEnumUserRole.ADMIN }),
        new User({ id: "2", firstName: "Jane", lastName: "Smith", email: "jane@example.com", role: AcEnumUserRole.EDITOR })
    ];

    async getUserById({ userId }) {
        console.log(`Fetching user by ID: ${userId}`);
        const user = this.#users.find(u => u.id === userId);
        return user ? User.fromJson(user.toJson()) : null;
    }

    async updateUser({ userId, newEmail, newRole }) {
        console.log(`Updating user ${userId} with newEmail=${newEmail}, newRole=${newRole}`);
        let user = await this.getUserById({ userId });
        if (!user) {
            throw new Error(`User with ID ${userId} not found.`);
        }
        if (newEmail) {
            user.updateEmail(newEmail);
        }
        if (newRole) {
            user.role = newRole;
        }
        user.save();
        return user;
    }

    #logActivity(activity) { // Private method
        console.log(`[LOG]: ${activity}`);
    }
}

// main.js (Example Usage)
import { User } from './user.js';
import { UserService } from './user-service.js';
import { AcEnumUserRole } from './ac-enum-user-role.js';

async function runExamples() {
    const userService = new UserService();

    const newUser = new User({ firstName: "Alice", lastName: "Brown", email: "alice@example.com" })
        .updateEmail("alice.new@example.com")
        .save();
    console.log("New user email after chaining:", newUser.email);

    const existingUser = await userService.getUserById({ userId: "1" });
    if (existingUser) {
        console.log("Existing user:", existingUser.toJson());
        const updatedUser = await userService.updateUser({ userId: "1", newEmail: "john.updated@example.com", newRole: AcEnumUserRole.EDITOR });
        console.log("Updated user:", updatedUser.toJson());
    }

    const userData = { id: "3", firstName: "Bob", lastName: "White", email: "bob@example.com", role: "guest" };
    const bob = User.fromJson(userData);
    console.log("Bob (fromJson):", bob.toJson());

    bob.instanceFromJson({ email: "bob.updated@example.com", role: "admin" }).save();
    console.log("Bob (after instanceFromJson chaining):", bob.toJson());
}

runExamples();

Database Naming Conventions

Consistent database naming is critical for data integrity, query readability, and easier database administration. These conventions focus on clarity and avoiding keywords.

General Database Conventions

  • Tables: snake_case_plural (e.g., users, product_categories).
  • Columns: snake_case_singular (e.g., first_name, order_total).
  • Primary Keys: id (simple primary key), or table_name_id (composite primary key, e.g., user_id).
  • Foreign Keys: referenced_table_name_id (e.g., user_id in an orders table).
  • Indexes: Prefix with idx_ followed by relevant table and column names (e.g., idx_users_email).
  • Stored Procedures/Functions: Prefix with a verb or abbreviation (e.g., sp_get_user, fn_calculate_tax). Use snake_case.
  • Views: Prefix with vw_ followed by a descriptive name (e.g., vw_active_users). Use snake_case.
  • Triggers: Prefix with trg_ followed by table name and event (e.g., trg_users_after_insert).

MySQL

MySQL is flexible, but snake_case is the most common and recommended convention for tables and columns.

  • Tables: snake_case_plural (e.g., customers, orders).
  • Columns: snake_case_singular (e.g., customer_id, order_date).
  • Indexes: idx_table_name_column_name (e.g., idx_customers_email).
  • Foreign Keys: Typically fk_source_table_target_table or fk_column_name.
-- Example MySQL
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    product_name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    stock_quantity INT DEFAULT 0
);

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    total_amount DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

CREATE INDEX idx_users_email ON users(email);

Firebase (Firestore)

Firestore is a NoSQL document database. Naming focuses on collections, documents, and fields.

  • Collections: kebab-case-plural or camelCasePlural. Prefer kebab-case for clarity in paths (e.g., users, product-categories).
  • Documents: IDs are typically generated automatically, but if custom, use kebab-case or camelCase (e.g., john-doe-123, order456).
  • Fields: camelCase (e.g., firstName, orderTotal).
  • Subcollections: Follow collection naming conventions.
-- Example Firestore Structure (Conceptual)
/users/
    {userId}/
        firstName: "John",
        lastName: "Doe",
        email: "john.doe@example.com",
        createdAt: "2023-01-15T10:00:00Z",
        /addresses/
            {addressId}/
                street: "123 Main St",
                city: "Anytown"

/products/
    {productId}/
        productName: "Laptop Pro",
        price: 1200.00,
        stockQuantity: 50,
        categoryRef: "/product-categories/electronics"

/orders/
    {orderId}/
        userId: "user-id-abc",
        orderDate: "2023-08-22T14:30:00Z",
        totalAmount: 1250.00,
        items: [
            { productId: "product-id-xyz", quantity: 1, price: 1200.00 },
            { productId: "product-id-abc", quantity: 1, price: 50.00 }
        ]