Дайте крудошлепа

16d869350972450b8eb1724c0015d36d

Я устроился в небольшую компанию, которая сделал круд-приложуху на 20 таблиц типа «заметки» и активно ее продавала госорганам за невменяемый бабос.

У нас был 3(три) Т-Р-И статуса юзера. Anonym→Logined→Phone_Confirmed. Молодой талант до меня увидел в этом граф, и написал класс на 200+ строк, реализующий алгоритм Флойда–Уоршелла, прикрутил стейт-машину и не найдя интересных задач, c блеском прошел собес в Яндекс и свалил.


Меня наняли сеньором, и я каюсь ничерта не понял, алгоритм прекрасно работал на первой ступени, на второй давал сбои, тоскливо погуглил этот алгоритм, стер все к черту и написал: if (status==Logined & phone!=null){status=Phone_Confirmed}.
Один коллега посмотрел на меня с немой благодарностью, а начальник офигел и сказал, что код нерасширяем и захардкожен, а тот алгоритм мог пройти за время логN через тысячу вершин и по истечению испытательного урока меня уволили нах, так как мой технический уровень не соответствовал их высоким требованиям, впрочем выдали три зарплаты и я благодарен этим людям. Мой код оставили, тот так и не смогли починить.

Это было вступление.


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


Потому что, только я могу решить задачку, которую вы уже 10 лет решить не можете, когда прилетает пуш-уведомление или смс и в твоем всплывающем окне написано:

«Ваш шестизначный пароль доступа в наше приложение: 123…»

и дальше надо клацать и куда-то лезть и приложение закрылось, и куда оно делось так это пуш или смс был или вообще телеграм?
Просто замените строку в пуше на:

«Код: 123456».

Если не один программист у вас до этого не догадался! А я смог! С вас пятьсот мильонов тыщ за консультацию. Если там есть кто-то круче меня, обьясните мне, какого черта, вы не можете починить эту богомерзкую ерунду?

Это статья посвящена людям с моим стеком. Я работаю на спринг-жаве, фронт на реакте. rest-кафка, микросервисы. Тысячи нас.


Я знаю, что существуют другие направления програмиирования и да которые упираются в алгоритмы, графы и матан-матан. Я их не встречал и не работал. Я не про них.


Да я знаю, что даже в жава-крудошлепстве, можно легко принести толику математического безумия, где нобелевский лауреат по математике не справится и потребуются хай-левел сеньоры, чтоб вытащить по айдишнику юзера из базы. Тот кто это сделает — непригодная к программированию сволочь, а вовсе не умник, как в примере вначале.

Если вам надо приколотить полку, наверно вы обалдеете, если мастер,
потратив месяц, сделает вам левитирующий держатель, который впрочем не работает, но излучает радиацию? Да он очень умный, умнее меня. Но зато я приколочу вам полку за 10 минут)))

Дальше набор простых правил. Правила тупые до невозможности, я не понимаю, почему такое редкое количество сеньоров их способно выполнить.

  1. Название переменных.

ОДИНАКОВЫЕ!!! Не разные!!! Буква в букву! Если в базе у вас в таблице user есть поле userName, то в энтити user у вас должно быть userName, и в userDto у вас должно быть поле userName.


Чо блин сложного? почему у Вас энтити person c полем login, а dto Human c полем firstCred?

По аналогии UserController, UserService, UserRepo. Я понимаю, что у вас богатый словарный запас и вы внезапно поняли, что придумали название поудачнее. Но либо все переделывайте, либо продолжайте.


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

Не правда ли легко следовать правилу один?

  1. 20 строк в методе, 200 строк в классе.

    20 — это меньше 25. Вы сеньоры, вы же умеете считать до 20? Ну и до 200, когда пару класс располовинить. Что сложного?
    И да маленькие классы тоже не нужны. Строк 100–200 оптимально.

  2. Полиморфизм. Обожаю вот такой код:

    Class Animal{String type, voice(){
    if (type==dog) -> gav,
    elseif(type==cat)->myau
    else->not}
    }

Но тут приходит корпоративный прогер:

Class Cat extends Animal implements Voicable{
@Override
voice(){myao}
}

Class Dog extends Animal implements Voicable{
@Override
voice(){gav}

Abstract Class Animal implements Voicable{
String type;
@Override
voice(){myao}

interface Voicable{
voice()}

Так вот первый код короче и работает быстрее. И читается проще, потому что весь на одной странице, а не раскидан по 4 разным классам. Еcли код можно сделать свичом, сделайте его свичом. Не насилуйте мозг своими полиморфизмами!

  1. Повторяемость кода

    Тут все сложно, не все сеньоры поймут. Если взять ребенка и попросить его посчитать количество повторений слова voicable, то он ответит 4, если взять сеньора, и попросить его посчитать, то он ответит полиморфизм. Сеньор может нахерачить десяток полиморфических классов, которые на 96% одинаковые и различаются одной строчкой — и это будет корректно и полиморфизм, как в примере сверху. Но они накрест порвутся если в двух методах рядом одинаковая строчка есть. Повторяемость кода улучшает его понимание и быстрочтение, а вынос кода из метода в отдельный класс или другой метод, заставляют ходить в другие классы. Это тонкое равновесие сеньоры не способны понять, потому что сеньоры очень умные, они много помнят, и если обычному смертному желательно логическую единицу кода на одном экране, то сеньор может корректно монить сразу два десятка классов, поэтому у них равновесие сильно смещается в сторону усложнения кода.

Но даже в этом случае есть простое правило, которое может понять даже сеньор: после убирания повторяемости кода, количество строчек кода должно уменьшиться, а не увеличиться!
Если количество строчек уменьшилось меньше, чем в три раза, верни все обратно! Так его проще читать.

  1. Слабая связанность.

    Если у интерфейса одна имплементация — сразу нахер иди со своими связанностями и прочими хернями. Код должен быть лаконичиным. Помни про повторяемость.

  2. Связки в базе 1 к 1.

    НЕТ! НЕТ! НЕТ! Даже объяснять не буду. Просто НЕТ! Захотел сделать связку 1-к-1 — поешь гуано. Понравилось? Поешь еше. Подумай о связи любви к Гуано и любовью писать 1-к-1.

  3. Юнит-тесты.

    Есть дебильный вопрос на собесах: что такое легаси-код? И один из ответов — не покрытый тестами. Самый гуанокод, который я видел был покрыт юнит-тестами полностью. Ваще чем код гуанистей, тем больше тестов. Юнит-тесты слетаются на гуано-код, как мухи.


    Когда код начинает превращается в гуано его начинают обсаживать юнит-тестами, типа он перестанет быть от это гуаном. Нет он просто будет гуано с юнит-тестами.
    Ваш код должен быть ясным и понятным даже дауну — это лучшая защита от багов. Если не так — сам виноват!

Ксати, легаси — это когда время на импрувменты стремится к бесконечности.

И философский вопрос:, а если разработчик не смог написать грамотного простого кода, ты уверен, что он сможет написать нормальные юнит-тесты?

  1. Системность.

  2. Идеальная системность — это когда все описывается одним правилом.

Пример: 11111111 — правило простое «все 1»
123456789 — тоже ясно «последовательное увеличение»
413912316 — это сеньор писал. после 4 в будний день идет 1, третья цифра 3(потому что третья, очевидно ж), а седьмая равна сумме шестой и пятой (смотри документацию). Но это только если ты козерог.


У сеньоров очень хорошая память, они действительно все помнят и думают это просто и понятно. И кто-то другой прочитал и сразу запомнил. Нет.

Теперь о правила системности:
Тут самые сложные правила: UserController→UserService→UserRepo, UserHelper, UserConverter Все названия классов строятся по одному принципу и так далее. Человек должен знать название класса в котором искать ошибку без стектрейса. Все процессы должны идти через стандартные классы. Все одинаково!


Любой процесс вы должны привести к КРУД и запихнуть его в стандартную цепочку классов. РЕАД, АПДЕЙТ, ДЕЛЕТЕ. Любой бизнес-процесс вы обязаны декомпозировать на серию логичных КРУД-операций, будь-то заказ пиццы или перечисление денег.

Ну и выводы.

Я много работал в разных компаниях и все они крудошлепили, но чем выше уровень сеньоров, тем сложнее и непонятнее код. Он становится все более запутанным, непонятным и сложным.
Ты приходишь в другую компанию, там сидит мидл, его код работает быстрее, он легко читается и легко модернизируется, и он в разы более многофункциональный.
Мидл скромно смотрит в стену: дженерики я не очень люблю, хотел сделать микросервисы, но как-то сложно получается, у меня всего два джуна. Тесты не пишем — времени нет. Открываешь репу: чистенький код. Наслаждение.

Каждый сеньор мнит себя гением, и поэтому программа создается этакими гениальными умельцами. Каждый КРУД, который я видел был на свой лад и по разному сложен.

Сила в стандартности и простоте решений. Когда промышленность перешла от мастеров к конвееру, где от работников не требовалась высокая квалификация. Настоящий сеньор превратит свой код в конвеер, где десяток джунов будут быстро и легко творить новую функциональность, и часто примитивным копипастом.

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

  2. Любую программу можно превратить в примитивный КРУД и любую в матан-треш. Смотри пример с алгоритмом Уоршалла.

  3. Задача сеньора наладить конвеер для джунов. Если у вас требуется три сеньора, чтоб починить маппер, значит это делал не сеньор.

    Всем добра, женщин и праздников!

© Habrahabr.ru