Coding standards
Coding conventions and style rules for Smartstore
Consistency keeps the Smartstore codebase approachable and maintainable. This guide summarizes the most important rules developers should follow when contributing code.
Naming conventions
Types, methods, properties:
PascalCase
.Fields and locals:
camelCase
; prefix private fields with_
.Interfaces: prefix with
I
(e.g.,IPriceCalculator
).Async methods: suffix with
Async
.Generics: use
T
prefixes (TContext
,TEntity
).Avoid abbreviations; if necessary, capitalize like
HttpClient
orDbContext
.
public interface IEmailSender
{
Task SendAsync(EmailMessage message, CancellationToken cancelToken = default);
}
Layout and formatting
Indent with four spaces, never tabs.
Brace style: Allman – opening braces on their own line.
Place
using
directives at the top, sorted alphabetically withSystem
first.Keep file length reasonable; split large classes into partials.
Enable nullable reference types in every file:
#nullable enable
.
namespace Smartstore.Shipping
{
public class RateRequest
{
#nullable enable
public Address? Destination { get; set; }
}
}
Guard clauses and exceptions
Validate arguments early to keep methods small and predictable. Throw ArgumentException
derivatives for bad input and domain‑specific exceptions for business rules.
public Task<Shipment> CreateShipmentAsync(Order order)
{
Guard.NotNull(order);
if (!order.Items.Any())
{
throw new InvalidOperationException("Order has no items.");
}
// ...
}
Asynchronous programming
All I/O operations should be asynchronous.
Use
async
/await
; never block with.Result
or.Wait()
.Propagate
CancellationToken
parameters.Prefer value tasks for hot paths returning synchronously.
public async Task<string> LoadAsync(int id, CancellationToken cancelToken)
{
var entity = await _db.Entities.FindAsync([id], cancelToken);
return entity?.Name ?? string.Empty;
}
Dependency injection
Prefer constructor injection and keep services focused on a single responsibility. Avoid service locators or static access. Controllers deriving from SmartController
receive ICommonServices
via the Services
property and do not need manual injection.
public class PriceController : SmartController
{
public async Task<IActionResult> Index()
{
var customer = Services.WorkContext.CurrentCustomer;
// ...
return View();
}
}
Logging
Expose an optional logger property so DI can inject a contextual ILogger
.
public class ShippingService : IShippingService
{
public ILogger Logger { get; set; } = NullLogger.Instance;
// ...
}
Client code
Use Bootstrap utility classes where possible.
Write JavaScript with progressive enhancement in mind and keep dependencies minimal.
Keep comments short and in English.
Following these standards helps ensure that Smartstore remains a clean, predictable, and enjoyable platform to work with.
Last updated
Was this helpful?