Важность соглашения о кодировании трудно переоценить — это то, на чем держится общий язык между вами и командой.
Принципы разработки программного обеспечения
- Читабельность кода — должно быть понятно Вам и Вашим товарищам. Сейчас и через несколько лет.
- Отсутствие дублирования. Дублирование возможно только там, где его удаление слишком затратно или сильно противоречит первому принципу.
- Модульность. Каждая функциональность отдельный блок, функция, класс, файл, проект. Часть выделенная из остального кода по смыслу — области ответственности.
- Решение должно быть слабосвязанным — должна быть возможность заменить один модуль другим, легко представить архитектуру решения в виде иерархии (дерева).
- Отделение данных от кода обрабатывающего эти данные (выделение конфигурации).
Методы
1) Ясное четкое именование переменных, классов, функций. Изменилось понятие предметной области — переименовываем.
2) Модульность. Принцип единственности ответственности (SOLID).
3) Один оператор — одна строка. Linq выражения разбиваем по точке. Одно условие — одна строка, оператор перед условием.
1 2 3 4 5 6 7 8 |
var leaders = Contacts .Where(contact => contact.isLeader); if (editContact.surname != contact.surname || editContact.name != contact.name || editContact.patron != contact.patron || editContact.phone != contact.phone) |
4) Избегаем ToArray/ToList. Запросы допускающие выполнения на стороне СУБД выполнять на стороне СУБД.
1 2 3 4 |
var leaders = Contacts .Where(contact => contact.isLeader) .ToArray(); |
5) if, for всегда со скобками:
1 2 3 4 |
if (counter == 0) { break; } |
6) Разделяем разнородные по смыслу блоки пустой строкой:
1 2 3 4 5 6 7 8 9 |
var counter = 0; var summaryPrice = 0; while (conter < n) { ... } return summaryPrice; |
7) Длинный список аргументов функций переносим на новую строку:
1 2 3 4 5 6 |
SalaryCalcualtor.Run ( beginDate, endDate, employee ); |
8) Выносить «волшебные» константы в enum
1 2 3 |
var activePartners = db .Partners .Where(el=>el.activity_id == 1) |
1 2 3 4 5 6 7 8 9 |
public enum ActivityEnum { Active = 1, NotActive = 2 } var activePartners = db .Partners .Where(el=>el.activity_id == (int)ActivityEnum.Active) |
9) Следить за безопасностью и оптимальностью кода. Рассматривать случаи расширения функционала
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
switch (user.EmployeeType) { case EmployeeType.Manager: { … } case EmployeeType.Booker: { … } default: { throw new ArgumentOutOfRangeException( string.Format( "Неожиданное значение EmployeeType = {0}", user.EmployeeType)); } } |
10) Избегать дублирования кода (пример: вынос методов расширения)
1 2 3 4 5 6 7 8 |
var user = db .Users .FirstOrDefault(el=>el.id == userId) public static User ById(this IQueryable<User> users, int userId) { return users.FirstOrDefault(el=>el.id == userId); } |
11) Именование сущностей в единственном числе в БД, EntityFramework.
12) Именование столбцов в БД, EntityFramework:
— primary_key — id (int или guid)
— Составные ключи использовать запрещено
— foreign_key — с маленькой буквы и с подчеркиванием (пример: contact_id)
— Поля и связанные сущности с большой буквы
13) Придерживаться naming conventions (соглашение об именовании) тех языков, на которых пишете (например, в C# именование методов, свойств и типов производится с большой буквы, с использованием CamelCase, а в JavaScript функции именуются с маленькой и т.д.), если отдельные моменты не оговорены выше.
14) Следите за оптимальностью и опрятностью вашего решения: убираем дублирование, а стили, JavaScript и т.д. выносим в отдельные файлы.
15) Ключ бандла должен иметь тот же уровень вложенности, что и скрипты.
16) Критерии вынесения скриптов:
— Скрипт используется где-то еще
— Скрипт содержит 200 и более строк кода
— Для скриптов, которые можно загружать «лениво», использовать includeOnce (встроена в проект)
17) Для каждого класса создавать отдельный файл.
18) В каждый метод, возвращающий результат клиенту, необходимо добавлять обработку исключений. Так же стоит добавлять обработку исключений в потенциально опасные места. Обязательно логгировать исключения, с записью контекста так, чтобы можно было повторить исключение. Пользователю выводить краткое уведомление с извинениями.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public ActionResult LoadPartnerReward( [DataSourceRequest] DataSourceRequest request, int? partnerId, string month = null) { try { ... return Json(data); } catch (Exception ex) { return this.ErrorJson(ex, string.Format("При выводе отчета по линиям за месяц {0} по партнеру {1} произошла ошибка ", month, partnerId)); } } protected JsonResult ErrorJson(Exception ex, string logMessage) { logger.WebErrorWithStatusCode(logMessage, ex); return new JsonResult() { Data = new { success = false, message = logMessage }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } |
19) Все сообщения, выводимые пользователю, сообщения об исключениях должны быть информативны (за исключением сообщений пользователю о непредвиденных исключениях).
— Сообщение об исключительной ситуации должно содержать сообщение с контекстом, внутреннее исключение и трассировку стека:
1 2 3 |
При расчете вознаграждения для сотрудника Петрова Ивана Федоровича id = 56 произошла ошибка: NullRefenceException Трассировка стека... |
— Сообщение пользователю о непредвиденной ситуации:
1 2 |
Извините. При выполнении расчета для сотрудника Петрова Ивана Федоровича произошла ошибка. Обратитесь к администратору. |
— Валидационное сообщение должно содержать пример и направлять на то, что необходимо изменить:
1 2 3 4 5 |
ИНН должен содержать 20 знаков Баланс не может быть отрицательным Введите номер телефона в формате +7(962) 006 78 33 |
20) Предпочтительнее условия в утвердительной форме
1 2 3 4 5 6 |
if(a != b) { } else { } |
1 2 3 4 5 6 |
if(a == b) { } else { } |
Именование сущностей в единственном числе в БД — что есть сущность в БД? таблица «Контрагенты» сущность?
Таблицы в БД. При получении ORM объектная модель сама склоняет окончания во множественном и единственном числе.
Михаил, можете пояснить фразу про то, что в БД/ EF составных ключей не бывает?
Благодарю Алексей за вопрос. Не верная формулировка. Имеется в виду составные ключи использовать запрещено. Поскольку они усложняют манипулирование таблицей, а в MS SQL при вставке полного дубликата строки для удаления этой строки необходимо полностью очищать таблицу. Во избежании данных ситуаций приняли правила:
— любая таблица должна иметь уникальный атомарный ключ. Целочисленный или guid;
— для создания уникальных пар ключей — применяется уникальный индекс.
При наличии атомарного ключа на него проще сослаться. Есть возможность производить удаление\обновление по нему.