Skip to main content

Code Style Guide

These conventions keep TablePro’s codebase consistent and readable.

Tools

ToolPurposeConfig File
SwiftLintLinting and static analysis.swiftlint.yml
SwiftFormatCode formatting.swiftformat

Running Tools

# Check for linting issues
swiftlint lint

# Auto-fix linting issues
swiftlint --fix

# Format code
swiftformat .

# Check formatting without applying
swiftformat --lint .
Run these before committing. SwiftLint also runs automatically during Xcode builds.

Architecture Principles

Separation of Concerns: Logic in viewmodels, presentation in views. Value Types First: Use struct for data, class for shared state. Immutability: Default to let; use var only when mutation is needed.

Naming Conventions

Types

ElementConventionExample
Classes/StructsUpperCamelCaseDatabaseConnection
EnumsUpperCamelCaseDatabaseType
Enum caseslowerCamelCase.postgresql
ProtocolsUpperCamelCaseDatabaseDriver

Functions and Variables

ElementConventionExample
FunctionslowerCamelCaseexecuteQuery()
VariableslowerCamelCaseconnectionString
ConstantslowerCamelCasemaxRetryAttempts
ParameterslowerCamelCasetableName: String

Boolean Properties

Use is/has/can prefixes:
var isConnected: Bool
var hasValidCredentials: Bool
var canExecuteQuery: Bool

Factory Methods

Use make prefix:
func makeConnection() -> DatabaseConnection
func makeDriver(for type: DatabaseType) -> DatabaseDriver

Formatting

Indentation

  • 4 spaces (never tabs)
  • Configure your editor to convert tabs to spaces

Line Length

  • 120 characters max per line
  • Break long lines for readability
// Good: Line breaks for readability
let result = try await driver.executeParameterized(
    query: "SELECT * FROM users WHERE email = ?",
    parameters: [email]
)

// Avoid: Long single line
let result = try await driver.executeParameterized(query: "SELECT * FROM users WHERE email = ?", parameters: [email])

Braces

K&R style — opening brace on same line:
// Good
if condition {
    doSomething()
} else {
    doSomethingElse()
}

// Bad
if condition
{
    doSomething()
}

Spacing

// Space around operators
let sum = a + b
let isValid = count > 0 && name.isEmpty == false

// No space for ranges
for i in 0..<10 { }

// Space after colon in type declarations
var name: String
func connect(host: String, port: Int)

Access Control

Specify Explicitly

Always specify access modifiers:
// Good: Explicit access
private var connectionPool: [Connection] = []
internal func processResult(_ result: QueryResult)
public func connect() async throws

// Avoid: Implicit internal
var connectionPool: [Connection] = []  // Implicit internal

Prefer Private

Use the most restrictive access that works:
class DatabaseManager {
    // Public API
    public func connect() async throws { ... }

    // Internal helpers
    private func validateConnection() -> Bool { ... }
    private var activeDriver: DatabaseDriver?
}

Extension Access

Specify access on the extension, not individual members:
// Good
public extension NSEvent {
    var semanticKeyCode: KeyCode? { ... }
}

// Avoid
extension NSEvent {
    public var semanticKeyCode: KeyCode? { ... }
}

Optionals & Safety

Never force unwrap. Use if let, guard let, or as? for safe optional handling.

SwiftUI Patterns

Use @StateObject for viewmodels, @State for local state. Order property wrappers: Environment, StateObject, State, Binding, regular properties. Extract large views into subviews.

Limits

SwiftLint Limits

MetricWarningError
Function body length160 lines250 lines
Type body length1100 lines1500 lines
File length1200 lines1800 lines
Cyclomatic complexity4060

Handling Long Files

Extract extensions into separate files:
MainContentCoordinator.swift
Extensions
MainContentCoordinator+RowOperations.swift
MainContentCoordinator+Pagination.swift
MainContentCoordinator+Filtering.swift