Skip to content

Style Guide

kevin-montrose edited this page Apr 10, 2021 · 2 revisions

Style Guide

Introduction

Cesil generally follows C# conventions, and uses an .editorconfig file to concretely enforce some rules. You can force a format of code by using Analyze -> Code Cleanup -> Run Code Cleanup (Profile 1) in Visual Studio.

You can find Cesil's .editorconfig checked into the root of the repository.

Some style conventions overlap Opinions, by design.

File Conventions

Each separate code unit should be in a separate file, except that it is acceptable to place delegate declarations in the same file as the code unit that primarily consumes it. For example, GetterDelegate<TRow, TValue> is defined in the same file as Getter.

Nested classes and partial classes may be placed in the same file as the other parts of the unit. Nested classes are an implementation detail, and partial classes are commonly used with #if DEBUG pragmas to enable some test infrastructure and aren't really "separate" logically.

Naming Conventions

Generally follow .NET naming conventions for exposed types. Internally, do not use m_ or _ prefixes for private members except that is permissable to use _ as a prefix for a field backing a property. This is most useful when explicitly implementing an interface that only defines a getter.

Namespaces And Directories

Cesil only defines a single namespace, Cesil. As a rule, do not introduce new namespaces.

Files may be organized into directories, grouping common functions together.

Cesil's code is organized into the following directory structure:

  • Cesil - project for the main Cesil library
    • Common - helper and utility classes used across Cesil
      • Attributes - various Attribute classes, mostly used for public interface tests
    • Configuration - classes for building Options and creating IBoundConfiguration<TRow>
    • Context - classes for creating Contexts
    • Interface - definitions of the major public interfaces for Reading, Writing, and Convenience Utilities
    • Reader - code backing read functionality
      • Adapaters - code that abstracts over various supported "stream" types for read purposes
      • Dynamic - parts of reading that are particular to dynamic deserialization
      • RowConstructors - code that manages constructing instances of different types, in particular managing the gradual deserialization of columns and how that interacts with constructors
    • Result - code for the various ReadXXXResult<TRow> types
    • TypeDescriber - code backing ITypeDescriber and its consumption, along with provided implementations like the Default Type Describer
      • Defaults - code backing Default Parsers and Default Formatters
      • Wrappers - code for abstracting over constructors, methods, fields, and delegates as they're used by other type describing code
    • Writer - code backing write functionality
      • Adapters - code that abstracts over various supported "stream" types for write purposes
      • Dynamic - parts of writing that are particular to dynamic serialization
  • Cesil.Tests - project containing tests for Cesil
    • Helpers - utilities classes and methods used by tests, that are not themselves tests
  • Cesil.Benchmark - BenchmarkDotNet project of benchmarks for Cesil's performance
    • Internals - benchmarks for internal types, typically used to verify that certain operations are indeed faster than a built-in or naive alternative
    • Read - benchmarks for read operations, comparing either to other .NET libraries or comparing dynamic operations to static ones
    • Write - benchmarks for write operations, comparing either to other .NET libraries or comparing dynamic operations ot static ones
    • Helpers - utility classes used by benchmarks, that are not themselves benchmarks
    • Models - common data classes used by benchmarks