Netspective Logo
GuidelinesDevelopment Guidelines

Coding Standards

Language-specific coding conventions and best practices for maintainable software

Coding standards ensure consistency, readability, and maintainability across the codebase. Consistent code reduces cognitive load during reviews and makes onboarding easier for new team members.

Why Coding Standards Matter

BenefitDescription
ReadabilityConsistent formatting makes code easier to understand
MaintainabilityStandard patterns reduce complexity
QualityEnforced standards catch errors early
CollaborationShared conventions reduce friction
ComplianceRequired for regulated industries (FDA, SOX)

General Principles

Code Clarity

Code Clarity Principles

Naming Conventions

ElementConventionExample
ClassesPascalCaseUserAccount, PaymentProcessor
FunctionscamelCase or snake_casecalculateTotal, validate_input
ConstantsUPPER_SNAKE_CASEMAX_RETRIES, DEFAULT_TIMEOUT
VariablescamelCase or snake_caseuserName, order_count
BooleansPrefix with is/has/canisValid, hasPermission

Language-Specific Standards

TypeScript/JavaScript

// File naming: kebab-case
// user-service.ts, payment-processor.ts

// Interfaces: PascalCase with I prefix (optional)
interface UserProfile {
  id: string;
  email: string;
  createdAt: Date;
  preferences?: UserPreferences;
}

// Type aliases for complex types
type UserId = string;
type OrderStatus = 'pending' | 'confirmed' | 'shipped' | 'delivered';

// Functions: clear, descriptive names
async function fetchUserById(userId: UserId): Promise<UserProfile | null> {
  // Implementation
}

// Constants at module level
const MAX_LOGIN_ATTEMPTS = 5;
const SESSION_TIMEOUT_MS = 30 * 60 * 1000;

// Avoid magic numbers
// Bad:
if (retries > 3) { /* ... */ }

// Good:
const MAX_RETRIES = 3;
if (retries > MAX_RETRIES) { /* ... */ }

Python

# File naming: snake_case
# user_service.py, payment_processor.py

from typing import Optional
from dataclasses import dataclass
from datetime import datetime

# Classes: PascalCase
@dataclass
class UserProfile:
    """User profile with basic information."""
    user_id: str
    email: str
    created_at: datetime
    preferences: Optional[dict] = None

# Functions: snake_case
def fetch_user_by_id(user_id: str) -> Optional[UserProfile]:
    """
    Fetch a user profile by ID.

    Args:
        user_id: The unique identifier of the user

    Returns:
        UserProfile if found, None otherwise
    """
    pass

# Constants: UPPER_SNAKE_CASE
MAX_LOGIN_ATTEMPTS = 5
SESSION_TIMEOUT_SECONDS = 30 * 60

# Private functions: prefix with underscore
def _validate_email(email: str) -> bool:
    """Internal validation helper."""
    pass

Go

// File naming: snake_case
// user_service.go, payment_processor.go

package user

import (
    "context"
    "time"
)

// Exported types: PascalCase
type UserProfile struct {
    ID          string
    Email       string
    CreatedAt   time.Time
    Preferences *UserPreferences
}

// Exported functions: PascalCase
func FetchUserByID(ctx context.Context, userID string) (*UserProfile, error) {
    // Implementation
}

// Unexported (private): camelCase
func validateEmail(email string) bool {
    // Implementation
}

// Constants
const (
    MaxLoginAttempts  = 5
    SessionTimeoutSec = 30 * 60
)

// Interfaces: describe behavior
type UserRepository interface {
    FindByID(ctx context.Context, id string) (*UserProfile, error)
    Save(ctx context.Context, user *UserProfile) error
}

Java

AspectStandard/Tool
Style GuideGoogle Java Style Guide
Code QualityCheckstyle, PMD, SpotBugs
Unit TestingJUnit 5, TestNG
Code CoverageJaCoCo
// File naming: PascalCase matching class name
// UserService.java, PaymentProcessor.java

package com.example.service;

import java.util.Optional;

// Classes: PascalCase
public class UserService {
    // Constants: UPPER_SNAKE_CASE
    private static final int MAX_LOGIN_ATTEMPTS = 5;
    private static final long SESSION_TIMEOUT_MS = 30 * 60 * 1000;

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // Methods: camelCase, descriptive names
    public Optional<UserProfile> fetchUserById(String userId) {
        return userRepository.findById(userId);
    }

    // Private methods: camelCase with underscore prefix optional
    private boolean validateEmail(String email) {
        return email != null && email.contains("@");
    }
}

PHP

AspectStandard/Tool
Style GuidePSR-12
Code QualityPHP_CodeSniffer, PHP Mess Detector, PHPStan
Unit TestingPHPUnit
Code CoverageXdebug, PCOV
<?php
// File naming: PascalCase for classes
// UserService.php, PaymentProcessor.php

declare(strict_types=1);

namespace App\Service;

use App\Repository\UserRepository;
use App\Entity\UserProfile;

// Classes: PascalCase
class UserService
{
    // Constants: UPPER_SNAKE_CASE
    private const MAX_LOGIN_ATTEMPTS = 5;
    private const SESSION_TIMEOUT_SECONDS = 1800;

    private UserRepository $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    // Methods: camelCase
    public function fetchUserById(string $userId): ?UserProfile
    {
        return $this->userRepository->find($userId);
    }

    // Private methods: camelCase
    private function validateEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }
}

Drupal

AspectStandard/Tool
Style GuideDrupal Coding Standards
Code QualityPHP_CodeSniffer + Coder module
Unit TestingPHPUnit (Drupal Test Traits)
Code CoverageXdebug
<?php
// Drupal follows PSR-4 with specific conventions
// modules/custom/my_module/src/Service/UserService.php

namespace Drupal\my_module\Service;

use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * Service for user-related operations.
 */
class UserService {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs a UserService object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * Loads a user by ID.
   *
   * @param int $uid
   *   The user ID.
   *
   * @return \Drupal\user\UserInterface|null
   *   The user entity or NULL if not found.
   */
  public function loadUser(int $uid) {
    return $this->entityTypeManager->getStorage('user')->load($uid);
  }

}

WordPress

AspectStandard/Tool
Style GuideWordPress Coding Standards
Code QualityPHP_CodeSniffer + WPCS
Unit TestingPHPUnit, WP_UnitTestCase
Code CoverageXdebug
<?php
// WordPress uses specific naming conventions
// File naming: lowercase with hyphens for includes
// class-user-service.php

/**
 * User service class.
 *
 * @package MyPlugin
 */
class My_Plugin_User_Service {

    /**
     * Maximum login attempts.
     *
     * @var int
     */
    const MAX_LOGIN_ATTEMPTS = 5;

    /**
     * Fetch user by ID.
     *
     * @param int $user_id User ID.
     * @return WP_User|false User object or false.
     */
    public function fetch_user_by_id( $user_id ) {
        return get_user_by( 'id', $user_id );
    }

    /**
     * Validate email address.
     *
     * @param string $email Email address.
     * @return bool True if valid.
     */
    private function validate_email( $email ) {
        return is_email( $email );
    }
}

Angular

AspectStandard/Tool
Style GuideAngular Style Guide
Code QualityESLint + @angular-eslint
Unit TestingJasmine, Karma
E2E TestingProtractor, Cypress
Code CoverageIstanbul
// File naming: kebab-case with type suffix
// user.service.ts, user-profile.component.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

// Interfaces: PascalCase
export interface UserProfile {
  id: string;
  email: string;
  displayName: string;
}

// Services: PascalCase with Service suffix
@Injectable({
  providedIn: 'root'
})
export class UserService {
  private readonly apiUrl = '/api/users';

  constructor(private http: HttpClient) {}

  // Methods: camelCase
  getUserById(userId: string): Observable<UserProfile> {
    return this.http.get<UserProfile>(`${this.apiUrl}/${userId}`);
  }

  // Private methods: camelCase
  private validateUserId(userId: string): boolean {
    return userId.length > 0;
  }
}

HTML/CSS

AspectStandard/Tool
Style GuideGoogle HTML/CSS Style Guide
Code QualityPrettier, Stylelint, HTMLHint
ValidationW3C Validator
<!-- HTML: lowercase elements, kebab-case attributes -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>User Profile</title>
  <link rel="stylesheet" href="styles/main.css">
</head>
<body>
  <!-- Use semantic elements -->
  <main class="user-profile" data-user-id="123">
    <header class="user-profile__header">
      <h1 class="user-profile__title">User Profile</h1>
    </header>
    <section class="user-profile__content">
      <!-- Content here -->
    </section>
  </main>
</body>
</html>
/* CSS: BEM naming convention recommended */
/* File naming: kebab-case (main.css, user-profile.css) */

/* Component block */
.user-profile {
  display: flex;
  flex-direction: column;
  padding: 1rem;
}

/* Element */
.user-profile__header {
  margin-bottom: 1rem;
}

.user-profile__title {
  font-size: 1.5rem;
  font-weight: 600;
}

/* Modifier */
.user-profile--compact {
  padding: 0.5rem;
}

/* Variables */
:root {
  --color-primary: #007bff;
  --spacing-unit: 8px;
}

Android (Kotlin)

AspectStandard/Tool
Style GuideKotlin Coding Conventions
Code QualityAndroid Lint, ktlint, detekt
Unit TestingJUnit 5, MockK
UI TestingEspresso
Code CoverageJaCoCo
// File naming: PascalCase matching class name
// UserService.kt, UserProfileViewModel.kt

package com.example.app.service

import kotlinx.coroutines.flow.Flow

// Classes: PascalCase
class UserService(
    private val userRepository: UserRepository
) {
    // Constants: UPPER_SNAKE_CASE in companion object
    companion object {
        const val MAX_LOGIN_ATTEMPTS = 5
        private const val SESSION_TIMEOUT_MS = 30 * 60 * 1000L
    }

    // Functions: camelCase
    suspend fun fetchUserById(userId: String): UserProfile? {
        return userRepository.findById(userId)
    }

    // Flow for reactive patterns
    fun observeUser(userId: String): Flow<UserProfile> {
        return userRepository.observeUser(userId)
    }

    // Private functions: camelCase
    private fun validateEmail(email: String): Boolean {
        return email.contains("@") && email.contains(".")
    }
}

// Data classes for models
data class UserProfile(
    val id: String,
    val email: String,
    val displayName: String,
    val createdAt: Long
)

iOS/Swift

AspectStandard/Tool
Style GuideSwift API Design Guidelines
Code QualitySwiftLint
Unit TestingXCTest
UI TestingXCUITest
Code CoverageXcode Coverage
// File naming: PascalCase matching type name
// UserService.swift, UserProfileViewController.swift

import Foundation

// Protocols: PascalCase, often with -able, -ing suffix
protocol UserFetching {
    func fetchUser(byId id: String) async throws -> UserProfile?
}

// Classes/Structs: PascalCase
final class UserService: UserFetching {
    // Constants: camelCase for instance, UPPER_SNAKE_CASE less common
    private let maxLoginAttempts = 5
    private let sessionTimeoutSeconds: TimeInterval = 30 * 60

    private let userRepository: UserRepository

    init(userRepository: UserRepository) {
        self.userRepository = userRepository
    }

    // Functions: camelCase, clear parameter labels
    func fetchUser(byId id: String) async throws -> UserProfile? {
        return try await userRepository.find(byId: id)
    }

    // Private functions: camelCase
    private func validateEmail(_ email: String) -> Bool {
        return email.contains("@") && email.contains(".")
    }
}

// Structs for data models (value types)
struct UserProfile: Codable, Identifiable {
    let id: String
    let email: String
    let displayName: String
    let createdAt: Date
}

C#/.NET

AspectStandard/Tool
Style Guide.NET Coding Conventions
Code QualityStyleCop, Roslyn Analyzers, SonarQube
Unit TestingxUnit, NUnit, MSTest
Code CoverageCoverlet, dotCover
// File naming: PascalCase matching class name
// UserService.cs, UserProfileController.cs

using System;
using System.Threading.Tasks;

namespace MyApp.Services
{
    // Interfaces: PascalCase with I prefix
    public interface IUserService
    {
        Task<UserProfile?> GetUserByIdAsync(string userId);
    }

    // Classes: PascalCase
    public class UserService : IUserService
    {
        // Constants: PascalCase
        private const int MaxLoginAttempts = 5;
        private static readonly TimeSpan SessionTimeout = TimeSpan.FromMinutes(30);

        private readonly IUserRepository _userRepository;

        // Constructor injection
        public UserService(IUserRepository userRepository)
        {
            _userRepository = userRepository;
        }

        // Methods: PascalCase, async suffix for async methods
        public async Task<UserProfile?> GetUserByIdAsync(string userId)
        {
            return await _userRepository.FindByIdAsync(userId);
        }

        // Private methods: PascalCase
        private bool ValidateEmail(string email)
        {
            return !string.IsNullOrEmpty(email) && email.Contains("@");
        }
    }

    // Records for immutable data (C# 9+)
    public record UserProfile(
        string Id,
        string Email,
        string DisplayName,
        DateTime CreatedAt
    );
}

Code Organization

File Structure

src/
├── components/           # UI components
│   ├── common/          # Shared components
│   └── features/        # Feature-specific
├── services/            # Business logic
├── repositories/        # Data access
├── models/              # Data models
├── utils/               # Utility functions
├── constants/           # Application constants
└── types/               # Type definitions

Module Organization

// Each module should have clear boundaries

// user/index.ts - Public API
export { UserService } from './user-service';
export { UserRepository } from './user-repository';
export type { User, UserProfile } from './types';

// user/user-service.ts - Business logic
import { UserRepository } from './user-repository';
import { User } from './types';

export class UserService {
  constructor(private repository: UserRepository) {}

  async getUser(id: string): Promise<User | null> {
    return this.repository.findById(id);
  }
}

Error Handling

Consistent Error Patterns

// Define custom error types
class ValidationError extends Error {
  constructor(
    message: string,
    public readonly field: string,
    public readonly code: string
  ) {
    super(message);
    this.name = 'ValidationError';
  }
}

class NotFoundError extends Error {
  constructor(
    public readonly resource: string,
    public readonly id: string
  ) {
    super(`${resource} with id ${id} not found`);
    this.name = 'NotFoundError';
  }
}

// Use consistent error handling
async function processOrder(orderId: string): Promise<Order> {
  const order = await orderRepository.findById(orderId);

  if (!order) {
    throw new NotFoundError('Order', orderId);
  }

  if (!order.isValid()) {
    throw new ValidationError(
      'Order validation failed',
      'status',
      'INVALID_ORDER_STATUS'
    );
  }

  return order;
}

Never Swallow Errors

// Bad: Silently swallowing errors
try {
  await processPayment(order);
} catch (error) {
  // Error is lost
}

// Good: Log and handle appropriately
try {
  await processPayment(order);
} catch (error) {
  logger.error('Payment processing failed', { orderId: order.id, error });
  throw new PaymentError('Payment processing failed', { cause: error });
}

Code Review Standards

Review Checklist

  • Code follows naming conventions
  • Functions are appropriately sized (< 30 lines preferred)
  • Error handling is comprehensive
  • Edge cases are considered
  • No hardcoded values (use constants)
  • Comments explain "why" not "what"
  • Tests cover new functionality
  • No security vulnerabilities introduced

FDA/Regulated Requirements

For life-critical systems, additional requirements apply:

RequirementPurpose
TraceabilityCode links to requirements and tests
Code ReviewsDocumented review with sign-off
Static AnalysisAutomated code quality checks
Complexity LimitsCyclomatic complexity thresholds
Coverage RequirementsMinimum test coverage (often 80%+)

Static Analysis Tools

Linting Configuration

// .eslintrc.json (TypeScript/JavaScript)
{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "rules": {
    "@typescript-eslint/explicit-function-return-type": "error",
    "@typescript-eslint/no-explicit-any": "error",
    "no-console": "warn",
    "complexity": ["error", 10],
    "max-lines-per-function": ["warn", 50]
  }
}
# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: eslint
        name: ESLint
        entry: npx eslint --fix
        language: system
        files: \.(ts|tsx|js|jsx)$

      - id: prettier
        name: Prettier
        entry: npx prettier --write
        language: system
        files: \.(ts|tsx|js|jsx|json|md)$

Best Practices Summary

Do

  • Write self-documenting code with clear names
  • Keep functions small and focused
  • Use consistent formatting (automated via tools)
  • Handle all error cases explicitly
  • Write tests alongside code
  • Review code before merging

Don't

  • Use abbreviations that aren't universally understood
  • Write functions longer than 50 lines
  • Nest more than 3 levels deep
  • Leave TODO comments without tickets
  • Copy-paste code (extract to shared functions)
  • Ignore linter warnings


Compliance

This section fulfills ISO 13485 requirements for design and development procedures (7.3.1) and product identification (7.5.3), and ISO 27001 requirements for secure coding practices (A.8.28), secure development lifecycle (A.8.25), and configuration management (A.8.9).

View full compliance matrix

How is this guide?

Last updated on

On this page