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
orUPPER_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
), orcamelCase
(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
orcamelCase.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
), orcamelCase
(local constants, declared withconst
). - Parameters:
camelCase
. - Named Parameters: Achieved through object destructuring, similar to TypeScript.
- Enums:
AcEnumPascalCase
(class name). Enum values:PascalCase
orUPPER_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), ortable_name_id
(composite primary key, e.g.,user_id
). - Foreign Keys:
referenced_table_name_id
(e.g.,user_id
in anorders
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
). Usesnake_case
. - Views: Prefix with
vw_
followed by a descriptive name (e.g.,vw_active_users
). Usesnake_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
orfk_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
orcamelCasePlural
. Preferkebab-case
for clarity in paths (e.g.,users
,product-categories
). - Documents: IDs are typically generated automatically, but if custom, use
kebab-case
orcamelCase
(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 }
]