Чрезмерная Сложность

Я слышал выражение, что для того, чтобы стать программистом, нужно быть ленивым.

Но иногда лень в программировании приводит к ужасному техническому долгу.

В своей заметке про SRP я упоминал, что нарушение этого принципа может привести к увеличению сложности или даже умножению.

Один из моих коллег привел интересный пример, и я решил использовать его, чтобы продемонстрировать, как это выглядит.

Чрезмерная сложность

Давайте определим, что это за избыточная сложность.

Но сначала давайте поговорим о противоположности — о сложности, возникающей из требований.

Например, есть требования рассчитывать зарплату сотрудника исходя из почасовой ставки и отработанного времени.

А, если сотрудник проработал в компании более пяти лет, начисляется премия.

Это «если» вытекает из требований, и его невозможно избежать.

В той или иной форме он станет элементом сложности кода приложения, скорее всего, в виде условного оператора «if».

Но иногда сложность исходит не из требований, а из подхода разработчика к решению проблемы.

Оператор «if», такие шаблоны, как «стратегия», полиморфные методы — это не полный список методов программирования, которые могут сдержать эту избыточную сложность.

Лично я, кстати, всегда против использования разработчиками паттернов просто потому, что они могут, а не для решения конкретной задачи.

Вот простой пример.

Это может показаться фикцией, но это не так.

Это даже не упрощенно, именно так я наткнулся на это во время ревью кода пару лет назад. В двух местах кода были вызовы одной и той же функции, но с разными логическими параметрами:

  
  
  
  
  
   

// first place doSomething(true); // second place doSomething(false);

Такие конструкции всегда выглядят подозрительно и эта особенность меня не разочаровала.

Этот параметр был передан с единственной целью проверки внутри этой функции:

doSomething(flag: boolean): void { if(flag) { // do first thing } else { // do second thing } }

Эту проверку можно описать так: «если мне позвонили из места А, делаем одно, иначе мне позвонили из места Б, делаем другое».

Этот флаг, это «если» — вот о чем вся эта заметка.

Сложность не связана с бизнес-требованиями.

Естественно, я рекомендовал изменить код следующим образом:

// first place doFirstThing(); // second place doSecondThing(); //method is split into 2 parts each having their own responsibility doFirstThing(): void { // do first thing } doSecondThing(): void { // do second thing }

Всё, лишней сложности больше нет. Именно здесь разработчику следует потратить время на написание еще одной сигнатуры функции.

Здесь можно воскликнуть: «Но это всего лишь одно «если»» или: «Это нарушение очевидно, кто вообще такой код пишетЭ» И здесь на сцену выходит второй пример.

Это показывает, что увидеть нарушение может быть заметно сложнее, а также что цена этого нарушения может быть больше, чем одно «если».

Как и в первом примере, функция используется в двух местах:

// first place checkValidity(obj); // second place checkValidity(arrayOfObjs);

Метод, как следует из названия, проверяет достоверность объекта.

Однако не было очевидно, что он также может проверять достоверность массива объектов.

Я изменил имена переменных, чтобы подчеркнуть это нарушение.

Метод выглядит следующим образом:

checkValidity(parm: MyType | MyType[]): void { if(Array.isArray(parm)) { parm.forEach(p => checkValidity(p)); } else { // here the object gets checked // and conditional exception is thrown } }

Вот. Одно «если» превращается в множество «если».

Если в массиве 100 объектов, то это «если» будет выполнено 101 раз.

Но на реальных данных у нас там могло быть 30 тысяч объектов, а это уже впечатляющий удар по производительности.

Очевидно, что, следуя принципу единой ответственности, этот метод необходимо реорганизовать, чтобы появилось 2 метода:

checkItemsValidity(parms: MyType[]): void { parms.forEach(p => checkItemValidity(p)); } checkItemValidity(parm: MyType): void { // here the object gets checked // and conditional exception is thrown }

Точки вызова также необходимо соответствующим образом отрегулировать.

Интересно, что примеры, которые я привел в заметке про SRP, привели к увеличению SLOC, эти же примеры, наоборот, приводят к небольшому его снижению вместе с ожидаемым улучшением качества кода.

Вот и все.

Всего пара простых примеров, демонстрирующих наиболее важные принципы хорошего кода.

Теги: #программирование #Идеальный код #солид #srp #сложность

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.