Skip to content

Naming Conventions in ConnectSoft Microservice Template

Purpose & Overview

Naming Conventions establish consistent standards for naming classes, methods, properties, namespaces, projects, and other code elements throughout the ConnectSoft Microservice Template. Consistent naming conventions improve code readability, maintainability, and team collaboration by ensuring that developers can quickly understand the purpose and structure of code elements.

The naming conventions in this template follow Microsoft .NET Framework Design Guidelines while incorporating domain-driven design and Clean Architecture principles to create a cohesive, predictable naming strategy across all layers of the microservice.

Naming Philosophy

"There are only two hard things in Computer Science: cache invalidation and naming things."
Phil Karlton

Good naming is critical for code maintainability. The ConnectSoft Microservice Template follows established .NET conventions while adding domain-specific patterns that make the codebase self-documenting and easy to navigate.

General Naming Conventions

Case Styles

Case Style Usage Example
PascalCase Classes, methods, properties, namespaces, constants, enums UserService, GetUserInfo, OrderDetails, MaxRetries
camelCase Variables, parameters, private fields userName, totalAmount, logger
UPPER_CASE Rarely used (only for very specific constants or legacy code) Not recommended in this template

Abbreviations

  • Avoid abbreviations unless widely accepted
  • Accepted abbreviations: Id, Http, Https, Xml, Json, Api, Uri, Url, Db, Di, UI, IO
  • Avoid: Usr, Ord, Cust, Mgr (use full words: User, Order, Customer, Manager)

One Class Per File

Each class, interface, enum, or struct should be in its own file with a matching filename.

// ✅ GOOD - UserService.cs
public class UserService { }

// ❌ BAD - Multiple classes in one file
public class UserService { }
public class OrderService { } // Should be in OrderService.cs

Projects and Namespaces

Project Naming

Projects follow the pattern: ConnectSoft.MicroserviceTemplate.{Layer}[.{Technology}]

Pattern Example Description
ConnectSoft.MicroserviceTemplate Base project Common code, constants, exceptions
ConnectSoft.MicroserviceTemplate.{Layer} EntityModel, DomainModel, ServiceModel Layer-specific projects
ConnectSoft.MicroserviceTemplate.{Layer}.{Technology} PersistenceModel.NHibernate, ServiceModel.RestApi Technology-specific implementations
ConnectSoft.MicroserviceTemplate.{Layer}.Impl DomainModel.Impl Implementation projects (separated from contracts)

Examples: - ConnectSoft.MicroserviceTemplate.EntityModel - Entity contracts - ConnectSoft.MicroserviceTemplate.DomainModel - Domain contracts - ConnectSoft.MicroserviceTemplate.DomainModel.Impl - Domain implementations - ConnectSoft.MicroserviceTemplate.ServiceModel.RestApi - REST API controllers - ConnectSoft.MicroserviceTemplate.PersistenceModel.NHibernate - NHibernate persistence

Namespace Naming

Namespaces match project structure exactly:

// Project: ConnectSoft.MicroserviceTemplate.EntityModel
namespace ConnectSoft.MicroserviceTemplate.EntityModel
{
    public class MicroserviceAggregateRoot { }
}

// Project: ConnectSoft.MicroserviceTemplate.ServiceModel.RestApi
namespace ConnectSoft.MicroserviceTemplate.ServiceModel.RestApi
{
    public class MicroserviceAggregateRootsServiceController { }
}

Classes and Interfaces

Class Naming

  • Use PascalCase
  • Use descriptive nouns
  • Avoid generic names like Manager, Handler, Helper (be specific)
Pattern Example Description
Entity UserEntity, OrderEntity Domain entities
Repository UserRepository, OrderRepository Data access repositories
Service UserService, OrderProcessor Business logic services
Controller UsersController, OrdersServiceController API controllers
Options MicroserviceOptions, MongoDbOptions Configuration options
Extensions ServiceCollectionExtensions, MongoDbExtensions Extension method containers
Constants MicroserviceConstants, ServiceModelConstants Constant containers

Interface Naming

  • Prefix with I
  • Use PascalCase
  • Match implementation naming (without I prefix)
Interface Implementation Pattern
IUserRepository UserRepository Standard interface
IMicroserviceAggregateRoot MicroserviceAggregateRootEntity Entity interface
IMicroserviceAggregateRootsProcessor DefaultMicroserviceAggregateRootsProcessor Service interface
IUnitOfWork NHibernateUnitOfWork, MongoDbUnitOfWork Abstract interface

Read-Only Interface Pattern:

// Read-only interface
public interface IUserReadOnly { }

// Implementation
public class UserReadOnlyEntity : IUserReadOnly { }

Methods and Properties

Method Naming

  • Use PascalCase
  • Use verbs to describe actions
  • Be specific about what the method does
Pattern Example Description
Get GetUserById, GetAllUsers Retrieval operations
Create CreateUser, CreateOrder Creation operations
Update UpdateUser, UpdateOrderStatus Update operations
Delete DeleteUser, DeleteOrder Deletion operations
Process ProcessPayment, ProcessOrder Business processing
Validate ValidateUser, ValidateOrder Validation operations
Async Methods GetUserByIdAsync, CreateUserAsync Async methods with Async suffix

Avoid: - ❌ Generic names: Get, Set, Update, Do - ❌ Vague names: Handle, Process, Execute (without context)

Property Naming

  • Use PascalCase
  • Use nouns or noun phrases
  • Boolean properties should be questions or statements: IsActive, HasItems, CanDelete
Pattern Example Description
Simple UserName, Email, OrderDate Simple properties
Boolean IsActive, HasPermission, CanEdit Boolean properties
Collection Users, OrderItems, Permissions Collection properties
ID UserId, OrderId, ObjectId Identifier properties (use Id, not ID)

Constants

Constant Naming

  • Use PascalCase (not UPPER_CASE)
  • Group related constants in a static class
  • Use descriptive names
// ✅ GOOD - PascalCase constants
public static class MicroserviceConstants
{
    public const string NHibernateDIKey = "NHibernateDIKey";
    public const string MongoDbDIKey = "MongoDbDIKey";
}

// ✅ GOOD - Section name constants
public sealed class MicroserviceOptions
{
    public const string MicroserviceOptionsSectionName = "Microservice";
}

// ❌ BAD - UPPER_CASE (not used in this template)
public const string MAX_CONNECTIONS = "100";

Constant Patterns

Pattern Example Usage
Section Names MicroserviceOptionsSectionName Configuration section names
DI Keys NHibernateDIKey, MongoDbDIKey Dependency injection keys
Namespaces BaseNamespace, MessagesNamespace Service model namespaces
Meter Names MicroserviceTemplateMetricsMeterName Metrics meter names

Service Model Naming

Request/Response DTOs

Pattern Example Description
Request CreateUserRequest, GetUserDetailsRequest Request DTOs
Response CreateUserResponse, GetUserDetailsResponse Response DTOs
DTO UserDto, OrderDto Data transfer objects
// Service Model Request/Response
public class CreateMicroserviceAggregateRootRequest { }
public class CreateMicroserviceAggregateRootResponse { }
public class MicroserviceAggregateRootDto { }

Controller Naming

Controllers follow RESTful conventions:

Pattern Example Route
Resource Controller MicroserviceAggregateRootsServiceController api/MicroserviceAggregateRoots
Feature Controller FeatureAController api/FeatureA
[ApiController]
[Route("api/[controller]")]
public class MicroserviceAggregateRootsServiceController : ControllerBase
{
    [HttpPost("MicroserviceAggregateRoots/")]
    public async Task<CreateMicroserviceAggregateRootResponse> CreateMicroserviceAggregateRoot(...) { }
}

API Endpoint Naming

  • Use nouns (resources), not verbs
  • Use plural for collections
  • Use RESTful conventions
HTTP Method Pattern Example
GET GET /api/{resource} GET /api/MicroserviceAggregateRoots
POST POST /api/{resource} POST /api/MicroserviceAggregateRoots
PUT PUT /api/{resource}/{id} PUT /api/MicroserviceAggregateRoots/{id}
DELETE DELETE /api/{resource}/{id} DELETE /api/MicroserviceAggregateRoots/{id}

Avoid: - ❌ Verbs in URLs: /api/GetUser, /api/CreateOrder - ❌ Singular resource names: /api/User (use /api/Users)

Domain Model Naming

Input/Output Models

Pattern Example Description
Input CreateUserInput, GetUserDetailsInput Domain input models
Output CreateUserOutput, GetUserDetailsOutput Domain output models
// Domain Model Input/Output
public class CreateMicroserviceAggregateRootInput { }
public class GetMicroserviceAggregateRootDetailsInput { }
public class CreateMicroserviceAggregateRootOutput { }

Processors and Retrievers

Pattern Example Description
Processor Interface IMicroserviceAggregateRootsProcessor Write operations interface
Processor Implementation DefaultMicroserviceAggregateRootsProcessor Write operations implementation
Retriever Interface IMicroserviceAggregateRootsRetriever Read operations interface
Retriever Implementation DefaultMicroserviceAggregateRootsRetriever Read operations implementation
public interface IMicroserviceAggregateRootsProcessor
{
    Task<IMicroserviceAggregateRoot> CreateMicroserviceAggregateRoot(
        CreateMicroserviceAggregateRootInput input, 
        CancellationToken token = default);
}

public class DefaultMicroserviceAggregateRootsProcessor : IMicroserviceAggregateRootsProcessor
{
    // Implementation
}

Entity Model Naming

Entity Contracts and Implementations

Pattern Example Description
Entity Interface IMicroserviceAggregateRoot Entity contract
Entity Implementation MicroserviceAggregateRootEntity Entity implementation
Read-Only Interface IUserReadOnly Read-only entity contract
Read-Only Implementation UserReadOnlyEntity Read-only entity implementation
public interface IMicroserviceAggregateRoot : IGenericEntity<Guid>
{
    Guid ObjectId { get; }
    string? SomeValue { get; }
}

public class MicroserviceAggregateRootEntity : MicroserviceAggregateRoot, IMicroserviceAggregateRoot
{
    public Guid ObjectId { get; set; }
    public string? SomeValue { get; set; }
}

Messaging Model Naming

Commands and Events

Pattern Example Description
Command CreateOrderCommand, ProcessPaymentCommand Command messages
Event OrderCreatedEvent, PaymentProcessedEvent Event messages (past tense)
// Commands - Imperative verbs
public class CreateMicroserviceAggregateRootCommand : ICommand
{
    public Guid ObjectId { get; set; }
}

// Events - Past tense
public class MicroserviceAggregateRootCreatedEvent : IEvent
{
    public Guid ObjectId { get; set; }
    public DateTimeOffset CreatedAt { get; set; }
}

Best Practices: - ✅ Commands: Use imperative verbs (Create, Process, Approve) - ✅ Events: Use past tense (Created, Processed, Approved) - ❌ Avoid generic names: Message, Data, Info

Persistence Model Naming

Repositories

Pattern Example Description
Repository Interface IMicroserviceAggregateRootsRepository Repository contract
NHibernate Implementation MicroserviceAggregateRootsRepository NHibernate repository
MongoDB Implementation MicroserviceAggregateRootsMongoDbRepository MongoDB repository
Keyed Repository MicroserviceAggregateRootsMongoDbKeyedRepository Keyed DI repository
public interface IMicroserviceAggregateRootsRepository { }

// NHibernate
public class MicroserviceAggregateRootsRepository : GenericRepository<...>, IMicroserviceAggregateRootsRepository { }

// MongoDB
public class MicroserviceAggregateRootsMongoDbRepository : MongoDbRepository<...>, IMicroserviceAggregateRootsRepository { }

Specifications

Pattern Example Description
Specification Interface IMicroserviceAggregateRootsSpecification Specification contract
NHibernate Specification MicroserviceAggregateRootsQueryableSpecification NHibernate queryable specification
MongoDB Specification MicroserviceAggregateRootsMongoDbQueryableSpecification MongoDB queryable specification
public interface IMicroserviceAggregateRootsSpecification { }

public class MicroserviceAggregateRootsQueryableSpecification : QueryableSpecification<...>, IMicroserviceAggregateRootsSpecification { }

Actor Model Naming

Actor Interfaces and Implementations

Pattern Example Description
Actor Interface IBankAccountActor Actor contract
Actor Implementation BankAccountActor Actor implementation
Actor Input WithdrawInput, DepositInput Actor input models
Actor Output WithdrawOutput, DepositOutput Actor output models
public interface IBankAccountActor : IGrainWithGuidKey
{
    Task<WithdrawOutput> Withdraw(WithdrawInput input);
}

public class BankAccountActor : Grain, IBankAccountActor
{
    public Task<WithdrawOutput> Withdraw(WithdrawInput input) { }
}

Configuration and Options

Options Classes

Pattern Example Description
Options Class MicroserviceOptions, MongoDbOptions Configuration options
Section Name Constant MicroserviceOptionsSectionName Configuration section name
Validator ValidateMicroserviceOptions Options validator
public sealed class MicroserviceOptions
{
    public const string MicroserviceOptionsSectionName = "Microservice";

    [Required]
    required public string MicroserviceName { get; set; }

    [Required]
    [Range(0, int.MaxValue)]
    required public int StartupWarmupSeconds { get; set; } = 20;
}

[OptionsValidator]
public partial class ValidateMicroserviceOptions : IValidateOptions<MicroserviceOptions>
{
}

Configuration Section Naming

Configuration sections use PascalCase and match the options class name:

{
  "Microservice": {
    "MicroserviceName": "MyService",
    "StartupWarmupSeconds": 20
  },
  "PersistenceModel": {
    "MongoDb": {
      "MongoDbConnectionStringKey": "MongoDb",
      "DatabaseName": "MyDatabase"
    }
  }
}

Extension Methods

Extension Method Naming

Extension method classes follow the pattern: {TargetType}Extensions

Pattern Example Description
Service Collection ServiceCollectionExtensions, MongoDbExtensions DI registration extensions
Application Builder ApplicationBuilderExtensions Middleware pipeline extensions
Endpoint Route Builder EndpointRouteBuilderExtensions Endpoint mapping extensions
internal static class MongoDbExtensions
{
    internal static IServiceCollection AddMongoDbPersistence(
        this IServiceCollection services,
        IConfiguration configuration)
    {
        // Implementation
    }
}

Naming Pattern: Add{Feature}, Use{Feature}, Map{Feature}

Database Naming

Tables and Collections

Database Pattern Example Description
SQL Tables PascalCase, plural Users, Orders, MicroserviceAggregateRoots SQL table names
MongoDB Collections PascalCase, plural Users, Orders, MicroserviceAggregateRoots MongoDB collection names
Schemas Namespace-style ConnectSoft.MicroserviceTemplate SQL schema names

Columns and Fields

Pattern Example Description
SQL Columns PascalCase ObjectId, SomeValue, CreatedOn
MongoDB Fields PascalCase ObjectId, SomeValue, CreatedOn

Indexes

Pattern Example Description
SQL Indexes IX_{Table}_{Column} IX_Users_Email, IX_Orders_CustomerId
Composite Indexes IX_{Table}_{Column1}_{Column2} IX_Orders_Status_CreatedOn

File and Folder Naming

Files

  • Match class name: UserService.cs contains UserService class
  • Use PascalCase: OrderRepository.cs, MicroserviceOptions.cs
  • One class per file: Each file contains one primary class/interface

Folders

Folders follow namespace structure and use PascalCase:

Folder Purpose Example
Controllers API controllers Controllers/, RestApi/
Repositories Repository implementations Repositories/
Mappings Entity mappings Mappings/, NHibernate/, MongoDb/
Options Configuration options Root of Options project
Extensions Extension methods Root of ApplicationModel project

Metrics Naming

Metric Names

Metrics use lowercase with dots (OpenTelemetry convention):

Pattern Example Description
Meter Name connectsoft.microservicetemplate Meter name
Counter connectsoft.microservicetemplate.aggregateroot.added Counter metric
Duration connectsoft.microservicetemplate.aggregateroot.add.duration Duration metric
public static class MicroserviceTemplateMetrics
{
    public const string MicroserviceTemplateMetricsMeterName = "connectsoft.microservicetemplate";
    public const string AggregateRootsAddedCounterName = "connectsoft.microservicetemplate.aggregateroot.added";
    public const string AggregateRootsAddDurationName = "connectsoft.microservicetemplate.aggregateroot.add.duration";
}

Exception Naming

Exception Classes

  • Suffix with Exception
  • Use descriptive names
  • Indicate the problem
Pattern Example Description
Not Found UserNotFoundException, OrderNotFoundException Entity not found
Invalid InvalidOperationException, InvalidConfigurationException Invalid state/configuration
Validation ValidationException, OptionsValidationException Validation failures
public class UserNotFoundException : Exception
{
    public UserNotFoundException(Guid userId) 
        : base($"User with ID {userId} was not found.") { }
}

Variables and Parameters

Variable Naming

  • Use camelCase
  • Use descriptive names
  • Avoid single letters (except in loops: i, j, k)
Pattern Example Description
Simple userName, orderId, totalAmount Simple variables
Collection users, orders, items Collection variables
Boolean isActive, hasItems, canDelete Boolean variables
Async Result result, response, entity Async method results

Parameter Naming

Parameters follow the same rules as variables:

public async Task<User> GetUserById(Guid userId, CancellationToken cancellationToken = default)
{
    // userId - camelCase parameter
    // cancellationToken - camelCase parameter with default value
}

Private Fields

Field Naming

  • Use camelCase with this. prefix (preferred in this template)
  • Or use _ prefix (alternative style)
// ✅ GOOD - camelCase with this. prefix (template style)
public class UserService
{
    private readonly ILogger logger;
    private readonly IUserRepository repository;

    public UserService(ILogger logger, IUserRepository repository)
    {
        this.logger = logger;
        this.repository = repository;
    }
}

// ✅ ALTERNATIVE - _ prefix (also acceptable)
public class UserService
{
    private readonly ILogger _logger;
    private readonly IUserRepository _repository;
}

Constants and Static Values

Constant Patterns

Pattern Example Usage
Section Names MicroserviceOptionsSectionName = "Microservice" Configuration sections
DI Keys NHibernateDIKey = "NHibernateDIKey" Dependency injection keys
Namespaces BaseNamespace = "ConnectSoft.MicroserviceTemplate.servicemodel/1975/" Service model namespaces
Meter Names MicroserviceTemplateMetricsMeterName = "connectsoft.microservicetemplate" Metrics meter names
Store Names BankAccountActorsStoreName = "bankAccountActorsStore" Actor store names

Enumerations

Enum Naming

  • Use PascalCase
  • Use singular names for the enum type
  • Use PascalCase for enum values
public enum OrderStatus
{
    Pending,
    Processing,
    Completed,
    Cancelled
}

public enum McpServerTransportType
{
    Stdio = 1,
    Http = 2
}

Best Practices Summary

Do's

  1. Use PascalCase for classes, methods, properties, constants
  2. Use camelCase for variables and parameters
  3. Be descriptive - names should clearly indicate purpose
  4. Follow established patterns - use template conventions consistently
  5. Match file names to class names - one class per file
  6. Use verbs for methods - CreateUser, GetOrderDetails
  7. Use nouns for classes - UserService, OrderRepository
  8. Prefix interfaces with I - IUserRepository, IOrderService
  9. Suffix exceptions with Exception - UserNotFoundException
  10. Use Async suffix for async methods - GetUserAsync

Don'ts

  1. Don't use abbreviations unless widely accepted (Id, Http)
  2. Don't use generic names - Manager, Handler, Helper
  3. Don't use Hungarian notation - strUserName, intCount
  4. Don't use UPPER_CASE for constants (use PascalCase)
  5. Don't mix naming styles - be consistent within a project
  6. Don't use verbs in URLs - /api/GetUser ❌ → /api/Users
  7. Don't use singular for resource collections - /api/User ❌ → /api/Users
  8. Don't skip Async suffix for async methods
  9. Don't use single letters (except in loops)
  10. Don't use magic strings - use constants instead

Examples from Template

Complete Example: REST API Controller

namespace ConnectSoft.MicroserviceTemplate.ServiceModel.RestApi
{
    [ApiController]
    [Route("api/[controller]")]
    public class MicroserviceAggregateRootsServiceController : ControllerBase
    {
        private readonly ILogger<MicroserviceAggregateRootsServiceController> logger;
        private readonly IMicroserviceAggregateRootsRetriever retriever;
        private readonly IMicroserviceAggregateRootsProcessor processor;
        private readonly IMapper mapper;

        public MicroserviceAggregateRootsServiceController(
            ILogger<MicroserviceAggregateRootsServiceController> logger,
            IMicroserviceAggregateRootsRetriever retriever,
            IMicroserviceAggregateRootsProcessor processor,
            IMapper mapper)
        {
            this.logger = logger;
            this.retriever = retriever;
            this.processor = processor;
            this.mapper = mapper;
        }

        [HttpPost("MicroserviceAggregateRoots/")]
        public async Task<CreateMicroserviceAggregateRootResponse> CreateMicroserviceAggregateRoot(
            [FromBody] CreateMicroserviceAggregateRootRequest request,
            CancellationToken token = default)
        {
            // Implementation
        }
    }
}

Complete Example: Domain Processor

namespace ConnectSoft.MicroserviceTemplate.DomainModel.Impl
{
    public class DefaultMicroserviceAggregateRootsProcessor : IMicroserviceAggregateRootsProcessor
    {
        private readonly IUnitOfWork unitOfWork;
        private readonly IMicroserviceAggregateRootsRepository repository;
        private readonly IEventBus eventBus;
        private readonly ILogger logger;

        public DefaultMicroserviceAggregateRootsProcessor(
            IUnitOfWork unitOfWork,
            IMicroserviceAggregateRootsRepository repository,
            IEventBus eventBus,
            ILogger<DefaultMicroserviceAggregateRootsProcessor> logger)
        {
            this.unitOfWork = unitOfWork;
            this.repository = repository;
            this.eventBus = eventBus;
            this.logger = logger;
        }

        public async Task<IMicroserviceAggregateRoot> CreateMicroserviceAggregateRoot(
            CreateMicroserviceAggregateRootInput input,
            CancellationToken token = default)
        {
            // Implementation
        }
    }
}

References

Summary

The ConnectSoft Microservice Template naming conventions provide:

  • Consistency: Predictable naming patterns across all layers
  • Clarity: Self-documenting code through descriptive names
  • Maintainability: Easy to navigate and understand codebase
  • Standards Compliance: Follows Microsoft .NET guidelines
  • Domain-Driven: Aligns with DDD and Clean Architecture principles

By following these conventions, teams can:

  • Onboard Quickly: New developers understand code structure immediately
  • Maintain Easily: Consistent patterns make refactoring and updates straightforward
  • Collaborate Effectively: Shared understanding of naming reduces confusion
  • Scale Confidently: Established conventions support growth

Naming conventions are the foundation of code quality—they enable teams to write code that is not just functional, but also readable, maintainable, and professional.