Каковы характеристики хорошего кода?

Ответ

Хороший код — это прежде всего код, который легко понять, изменить и поддерживать другим разработчикам (или вам самим через полгода). Его основные характеристики:

Принцип Описание Пример (Swift)
Читаемость Имена переменных, функций и классов ясно отражают их назначение. Соблюдается единый стиль (например, Swift API Design Guidelines). func calculateTotalPrice(for items: [Item]) -> Decimal вместо func calc(_ i: [Item]) -> Dec
Простота (KISS) Каждая сущность (функция, класс) решает одну четкую задачу. Отсутствует преждевременная оптимизация и избыточная абстракция. Разделить монолитную функцию processDataAndUpdateUI() на parse(data:), validate(model:), updateView(with:).
Модульность и слабая связность Код разбит на независимые компоненты с четкими интерфейсами. Изменение одной части системы минимально затрагивает другие. Использование протоколов для абстракции зависимостей, что упрощает тестирование.
Повторное использование (DRY) Исключено дублирование логики. Повторяющийся код вынесен в общие функции, утилиты или базовые классы. Вместо копирования блока форматирования даты в 10 местах — создать функцию formatDate(_:).
Тестируемость Код написан так, чтобы его можно было легко проверить автоматическими тестами (юнит-тестами). Зависимости (сеть, база данных) инжектируются, а не создаются внутри класса напрямую.

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

Ответ 18+ 🔞

А, ну вот, опять про «хороший код» заговорили. Давайте я вам, как человек, который потом этот код разгребать будет, на пальцах объясню, что это такое, а то вы тут с табличками разошлись, ебать мои старые костыли.

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

Читаемость — это пиздец как важно.
Вот смотрите. Есть у вас функция. Можно назвать её func x(_ y: [Z]) -> A. А можно — func calculateTotalPrice(for items: [Item]) -> Decimal.
Во втором случае даже ваш кот, если он не совсем долбоёб, поймёт, что тут происходит. Первый вариант — это как записка «заходи вечером, обсудим». Обсудим что, блядь? Ядерный реактор или кто за пивом сходит? Имена должны говорить сами за себя, без всяких «а вот тут у меня гениальная аббревиатура».

Простота (KISS) — не надо выебываться.
Вот есть у вас задача: пришли данные, их надо распарсить, проверить и на экран вывести.
Мудак сделает одну функцию на три экрана длиной, которая всё делает: processDataAndUpdateUIAndMakeCoffeeAndCallMother().
А человек с мозгами разобьёт это на: parse(data:), validate(model:), updateView(with:).
Каждая функция делает одну простую вещь. Если одна сломается — вы сразу поймёте, какая, а не будете, как обосанный, полчаса дебаггером тыкать в эту простыню из кода.

Модульность — чтобы не было «поправил одно, сломалось всё».
Это как в машине: чтобы поменять лампочку в фаре, не надо двигатель снимать. Вот и в коде так же.
Класс, который показывает новости, не должен сам из интернета их качать, парсить JSON и в базу данных складывать. Он должен просто показывать то, что ему передали. А кто качает и парсит — это проблемы другого модуля.
Используйте протоколы, абстракции, инжектьте зависимости. Это не для красоты, а чтобы потом, когда API поменяется, вы не переписывали половину приложения, а поменяли только один маленький класс-загрузчик. И тесты написать легко — подсунули заглушку и проверили логику.

Повторное использование (DRY) — чтобы не изобретать велосипед каждый день.
Видите, что один и тот же кусок кода скопипащен в пяти разных файлах? Это пиздец, товарищи. Это мина замедленного действия. Захотите поменять логику — и вам придётся бегать по всем этим файлам и править вручную, а один обязательно забудете, и потом в три часа ночи будете получать краш-репорт.
Вынесите эту логику в одну функцию или утилитный класс. Один раз написали, один раз протестировали, везде используете. Экономия времени и нервов — овердохуища.

Тестируемость — это не прихоть, а страховка.
Если ваш класс для работы с сетью создаёт URLSession прямо внутри себя, как сука, в конструкторе, то как вы его протестируете? Никак. Придётся делать реальные сетевые запросы, что медленно, ненадёжно и зависит от интернета.
А если вы принимаете NetworkService как параметр (через протокол), то в тестах вы просто подсовываете заглушку, которая возвращает заранее приготовленные данные. И проверяете, правильно ли ваш код себя ведёт. Это называется «не быть распиздяем».

Итог, блядь.
Хороший код — это не про то, чтобы блеснуть умом и написать хитровыебанный алгоритм в одну строку. Это про то, чтобы через полгода, в понедельник утром, с похмелья, вы (или ваш коллега) могли открыть этот код, быстро понять, что тут происходит, и внести нужные правки, не боясь, что всё развалится, как карточный домик. Он снижает нагрузку на мозги, уменьшает количество ошибок и, в конечном счёте, экономит всем время и нервы. А время, как известно, — деньги. Вот и думайте.