Больница № 389, после длительных и безуспешных попыток найти уборщицу, преобразована в грязелечебницу.
Каждый день, приходя на работу, мы усаживаемся за компы и начинаем писать что-то эдакое, да по проекту. Но кто-то садиться писать, а кто-то педалить, и я не берусь осуждать и гневно высказываться, просто пару советов, которые я выловил за год работы.
Для начала хотелось бы ввести два понятия: «писать» и «педалить». Писать у нас будет означать так как надо делать, а педалить, в свою очередь, как не надо. И так, включаем пылесос, начнем-с. Начнем от печки, а точнее от дома. Классный дом — это когда все сделано как надо, а главное фундамент заложен отлично, что гарантирует долговечность. Проведя аналогию с программированием, мы строим каждый день свои дома, и вот как в идеале выглядит чертеж.
И, как тут показано, основой дома является чистый код. Кто-то возразит, что основой является архитектура, то есть то, что задумал архитектор, но я смотрю со стороны обычно строителя Степана, который все выполняет, что задумал архитектор. Так же помимо чистого кода есть еще ряд немаловажных блоков, многие из них будут описаны в следующих статьях. Как хороший строитель, Степан не должен использовать материалы какие попало, к примеру, вместо цемента при кладке кирпича использовать монтажную пену, похоже, а результат будет вообще не тот. Так и в программировании, не стоить педалить js функции в c# коде.
string script = @"<script type="text/javascript">
//
//как правило
//много
//очень много
//строк javascript
//
</script>";
this.Headers.Controls.Add(new Literalcontrol("\r\n"+script));
Не стоит шуметь в коде, писать нужно только кратко и строго по сути, не распыляясь на прочую ерунду. Мозг человека может удержать в памяти приблизительно 7 элементов сущностей, поэтому не стоит педалить вагон и маленькую тележку переменных, флагов и прочего, если их реально много образовалось, то объедините их в сущности.
Не повторяйтесь, согласитесь тяжело понять запущенного заику, так и в коде, если есть большой кусок, который можно вынести в отдельный метод, то сделайте это, назвав значимой фразой метод. Потом вместо повторений дирижаблей люди увидят всего одну строку и поймут, что происходит.
Документирование… вопрос вообще неоднозначный, все к нему относятся равнодушно, ведь писать комментарии, когда имя метода итак все объясняет, нелепо. Но если в методе реализована сложная логика, которая не является известным стандартным алгоритмом, то стоит описать ее, мало кто будет потом разбираться в вашем коде, помогите ему сразу, а то и вообще время пройдет и сами забудете, что писали, к примеру, заставили править и будет трата времени.
Нейминг – не используйте в именах переменных одну букву или сокращения (одну букву – разве что в итераторе). Нейминг классов – не педалим имена, которые ничего не отображают, которые имеют окончания на *Processor, *Info, не используйте аббревиатуры. Именем должно быть существительное и со смыслом. Нейминг методов, тут многие уже все итак прекрасно знают, описать имя метода, так чтобы отображалась суть, которую он выполняет.
Булевые выражения – все мы что то проверяем сравниваем, но прежде всего, ни вкоем случае не педалим такое:
if(isLoggedIn==true)
{
//какой-то код
}
loggedIn и так содержит только true или false значения, и сравнивать их никчемую Не стоит также и педалить подобного рода чепуху:
bool goingToBar;
if(cashInWallet > 10)
{
goingToBar = true;
}
else{
goingToBar = false;
}
Не отрицайте отрицание, да почти схоже с тавтологией, но нагляднее :
if(!isNotLoggedIn)
{
//какой-то код
}
Цель чистого кода - это сделать как можно компактнее код приложения, и так написать, чтоб человек смог его читать как роман, попивая чек иль чего покрепче (в нерабочее время есессно!) поэтому педалинг такого выражения не будет придавать элегантности моменту чтения или распития и чтения .
int pointsCount;
if(isSpeaker)
{
pointsCount = 0;
}
else
{
pointsCount = 50;
}
А правильный вариант выглядит вот так:
int pointsCount = isSpeaker ? 0:50;
Не надо сравнивать со string какие-либо значения.
if(employeeType == “manager”)
{
//какой-то код
}
А правильный вариант:
if(employee.Type == EmployeeType.Manager)
{
//какой-то код
}
Магические числа, вообще прекрасный момент, сравниваем переменную с 25, а что такое 25 ? ответ : 25. И это довольно частая ошибка, ее продолжают и продолжают педалить.
if(age >= 21)
{
//какой-то код
}
А правильный вариант:
const int legalDrinkingAge = 21;
if(age >= legalDrinkingAge)
{
//какой-то код
}
Еще одна очень распространненая ошибка у программистов - это написание очень большого колличества условий в if конструкциях. Для понимания такого выражения, как приведено ниже нужно будет потратить время, возможно большое чем ожидалось :
if(employee.Age > 55 && employee.YearsEmployed > 10 && employee.IsRetired == true)
{
//какой-то код
}
А правильный вариант:
bool eligibleForPension = employee.Age > MinRetirementAge && employee.YearsEmployed > MinPensionEmploymentYears && employee.IsRetired;
/*переменная имеет осмысленное название, которое дает понять сразу,
что проверяется право выхода на пенсию работника*/
if(eligibleForPension)
{
//какой-то код
}
Будьте логичны, изучайте свои инструменты, которыми работаете. Степан не стал бы пахать поле лошадью, если у него есть комбайн, так не стоит и нам. Как пример, использование LINQ для фильтрации данных:
var matchingUsers = new List<User>();
foreach(var user in users)
{
if(user.AccountBalance < minimumAccountBalance &&
user.Status == Status.Active)
{
matchingUsers.Add(user);
}
}
return matchingUsers;
А лаконичнее будет:
return users.Where(u => u.AccountBalance < minimumAccountBalance)
.Where(u => u.Status == Status.Active);
Количество проверок не должно превышать вложенность в три уровня
if(some){
if(anotherSome){
if(anotherSecondSome){
//какой то код
}
}
}
Методы
Методы имеют свои правила, и правила лучше всего соблюдать, дабы не ходить по полю с граблями, и потом рассказывать, как не справедлив мир. Есть всего три правила основных для методов:
- Если код повторяется – выделяй его в метод
- Если в коде может произойти ошибка, сделай так чтоб она проявлялась максимально быстро, а не в самом конце выполнения метода
- Возвращай значение как можно быстрее. Куй железо пока горячо, тык сказать.
И если с первым все ясно и не надо обьяснять, то по оставшимся двум приведу пример.Возвращай как можно раньше :
private bool ValidateUsername(string username)
{
var isValid = false;
const int MinUsernameLength = 6;
if(username.Length >= MinUsernameLength)
{
const int MaxUsernameLength = 25;
if(username.Length <= MaxUsernameLength)
{
var isAlphaNumeric = username.All(Char.IsLetterOrDigit);
if(isAlphaNumeric)
{
if(!ContainsCurseWords(username))
{
isValid = IsUniqueUsername(username);
}
}
}
}
return isValid;
}
А вот как сделать более лаконично:
private bool ValidateUsername(string username)
{
const int MinUsernameLength = 6;
if (username.Length < MinUsernameLength)
return false;
const int MaxUsernameLength = 25;
if (username.Length > MaxUsernameLength)
return false;
var isAlphaNumeric = username.All(Char.IsLetterOrDigit);
if (isAlphaNumeric)
return false;
if (!ContainsCurseWords(username))
return false;
return IsUniqueUsername(username);
}
Если может выпасть исколючение или ошибка, то пускай это произойдет как можно раньше:
public void RegisterUser(string username, string password)
{
if (!string.IsNullOrWhiteSpace(username))
{
if (!string.IsNullOrWhiteSpace(password))
{
//регистрация пользователя
}
else
{
throw new ArgumentException("Username is required.");
}
}
else
{
throw new ArgumentException("Password is required");
}
}
И по традиции:
public void RegisterUser(string username, string password)
{
if (!string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Username is required.");
if (!string.IsNullOrWhiteSpace(password)) throw new ArgumentException("Password is required");
//регистрация пользователя
}
И на последок... Зная все и используя все эти знания, можно получить отличный код, но как же быть, если только в начале пути а дать подзатыльник некому? Ответ есть: Visual Studio любезно предоставила такое средство как Code Metrics. Начать его использовать очень просто : всего лишь правой кнопокй мыши по "проекты" и "выбрать" Calculate Code Metrics. Более детально с результатами и значениями всего этого можно ознакомится вот здесь: Code Metrics
P.S. Пишите отличный код, прочитав статью, дай прочитать ее другу, а тот пусть своему другу передаст, и будет вам счастье, много счастья. И не будет у вас в проекте все так, как было в анекдоте в самом начале статьи.