-
Notifications
You must be signed in to change notification settings - Fork 1
Coding Standards
- Configure your code editor to insert (4) spaces instead of tabs.
- Delete unused code instead of commenting it out.
- One file per class.
- The filename must match the
classorenumname. - Avoid creating/using
partialclasses. - Always use
DateTime.UtcNow. - Extension Methods:
- Extension methods should be in a single file when extending a single class. The file and class should be called
[classname]Extensions.
- Extension methods should be in a single file when extending a single class. The file and class should be called
- Repositories
- Use Create, Read, Update and Delete prefixes for methods (CRUD).
- Services
- Use Load / Save.
- General naming for loading & saving:
object Load(int id);object LoadByParentObjectId(int parentId);
Name instances after the class name, e.g.
Foo foo;
Bar bar;Only differentiate variable names when you need to, e.g.
Foo first;
Foo second;Use the keyword var whenever possible.
Prefer having only one return statement in functions. Define the return value as result.
var result = new Foo();
// ...
return result;Acceptable exceptions to this rule are when your doing validation/assertions at the start of your function.
if (x < 0) return 0;
// ...
return result;Don't use single letter or abreviated variable names. E.g. use var person = new Person(); instead of var p = new Person();
Unless:
- Using geometry (e.g. x, y, z)
- Iterators in for...loops (i, j, k)
- Private Variables:
fooName - Public Variables:
FooName - Camel casing variables: Follow the rules, e.g.
Ebayinstead ofeBayfor a class name. - Constants (private or public):
FooConstantName - Use of base/this qualifiers:
FooMethod()notbase.FooMethod()orthis.FooMethod()unless you need to. - Acronyms: use
http,dvd,url, etc instead of HTTP.
- Use the prefix
Is(oris) - e.g.var isFoo = false; - Named positive, not negative - e.g.
IsAllowedToDeleteand NOTIsDeniedDeleteAccess
Use one nullable property int? etc... instead of int Foo & bool FooSpecified (or IsFooSpecified).
You can use nullable arguments.
By convention all our classes are organised with const variables first, followed by any dependencies, then the constructor(s) then methods. Dispose and copy methods are at the end of class.
Example:
public class Foo
{
public const string Key = "foo";
public const string CollectionKey = "foos";
private const string Thing = "thing";
#region Dependencies
public IService Service { get; set; }
#endregion
public Foo()
{
}
public int MethodOne(int foo)
{
// ...
}
}Use automatic mocking where possible.
When making assertions be as explicit as possible.
public class FooTest : AutoMockingTest
{
private Foo foo;
[SetUp]
public void SetUp()
{
foo = Create<Foo>();
}
[Test]
public void TestFooBar()
{
var bar = new BarFactory.Create();
var result = foo.FooTheBar(bar);
// not Assert.AreEqual(bar.FirstThing, result.FirstThing);
Assert.AreEqual("First Thing", result.FirstThing);
Assert.AreEqual(2, result.SecondThing);
}
}Use the ViewBag to avoid magic strings, have a unit test to assert values have been set correctly.
Use a strongly typed model if you have lots of entries in the ViewBag.
public FooController
{
public ViewData List()
{
// Unit test this line
ViewBag.Foo = new Foo();
}
}When concatenating more than two strings together, use string.Format().
When possible prefer interpolated strings to string.Format().
var username = "User " + seed;
var output = string.Format("User {0} blah", seed);
var value = $"Hello {person.Firstname} {person.Lastname}!";Use a StringBuilder object when concatenating string in a loop.
Use the @prefix when dealing with strings that one for than one line.
var query = @"SELECT Id, Created, Name
FROM TableName
WHERE Id = @id";Avoid using out parameters!
- Avoid it!
- Use
Baseprefix (notAbstract) for base class (e.g.public abstract class BasePerson {}). - Do not re-test inherited code.
For loops always starts at i = 0:
for (var i = 0; i < list.Count; i++) { ... }Don’t mix foreach loops and Linq.
foreach(var customer in customers.Where(c => c.Status == Status.Something))
{
// ...
}Do this instead:
foreach(var customer in customers)
{
// Skip customers without something
if (customer.Status != Status.Something) continue;
// ...
}Use this format for Linq statements:
var things = thing.Where(t => t.Thing)
.OrderBy(t => t.Thing);Format as follow when two or more properties are initalised:
var customer = new Customer
{
Name = “Bob”,
Lastname = “Smith”
};Refrain from using func parameters. They make debugging and understanding the code more difficult.
When you are allowed to use a func:
- Trivial anonymous functions
- Using reflection to avoid magic strings
- HtmlExtensions
Never use .checked (on variable representing a checkbox) to check if it's checked or not: it will NOT work in IE. Use jQuery $(..).checked(true) instead.
Avoid $.get(); when the request parameters rarely change but the content returned does: IE and proxies will cache the answer and behaviour will be broken. Use $.post(); instead.
Write JavaScript like it's JavaScript, use:
if (condition) {
foo();
}NOT
if (condition)
{
foo();
}And:
Use single quotes: foo('bar');
Never: use eval(json) to convert JSON to a JS object. Use $.parseJSON(json) instead.
DO NOT output the JSON with a hidden input <input type="hidden" value="${json}" /> or a hidden div <div id="json" style="display:none">${json}</div>.
DO ouput it in an 'application/json' script tag:
<script id="json" type="application/json">${json}</script>Then in javascript you can do
var json = $('#json').html();
var myData = $.parseJSON(json); Use parameters in SQL string instead of injecting values directly in the query.
var isDeleted = 0;
const string sql = @”SELECT Id FROM TableName WHERE Deleted = @IsDeleted”;
var result = connection.Query<int>(sql, new { IsDeleted = isDeleted });When selecting rows between fromDate and untilDate, use
WHERE [Created] BETWEEN @from AND @untilrather than
WHERE [Created] > @from AND [Created] <= @UntilWhen grouping by time interval, use:
T-SQL:
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0)mysql:
DATE_ADD('1900-01-01 00:00:00', INTERVAL TIMESTAMPDIFF(DAY, '1900-01-01 00:00:00', Created) DAY)The mysql operation above can be pretty CPU intensive. Denormalising the value to a CreatedDay DATE column might be a better option.
When using the LIKE text search function, check the type of the column your are working off, if it is NVARCHAR don't forget the N prefix on your 'value%'.
SELECT *
FROM Item i
WHERE i.Title LIKE(N'%boo%')If you are using like with a parameter, sanitize your string and surround it with the relevant % (e.g. "%foo%") then refer to it using a parameter.
var foo = $"{foo.Keep("0123456789")}%";
var query = @"SELECT *
FROM Item i
WHERE i.Title LIKE @foo"
// ...
return connection.Query<Item>(query, new {foo});To avoid locking the tables use WITH (NOLOCK) when relevant when selecting data.
SELECT *
FROM Item i WITH (NOLOCK)
WHERE Id = @idIf having to add WITH (NOLOCK) to your statements is not an option you can wrap your calls with a READUNCOMMITED transaction.
using (var connection = Context.Connection())
using (var transaction = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
return connection.Query<string>("SELECT Name FROM Item WHERE Id = @id", new {id}, transaction);
}Depending on the underlying database engine, this may or may not be faster. Mysql can be slower with READUNCOMMITED statements than T-SQL.
Be also aware that WITH (NOLOCK) or READUNCOMMITED will return data that hasn't been committed yet!
Delete files from the repo when deleting them from the project
Name branches in lower case with hyphens for spaces, e.g. : feature-branch-foo
Use git style commit messages, e.g.
Title less than 52 chars
[blank line]
- point 1
- point 2