Возможно кто-то воспримет эту статью, как очередное нытье на тему того "как плохо жить". Но я все же напишу ее с надеждой, что кого-то это сподвигнет на самосовершенствование. И, вдруг, текущий релиз нашей разумной (хотелось бы верить) цивилизации станет чуточку стабильнее. Причиной моего недовольства стал очередной неудачный опыт работы с фрилансером, именующим себя "мобильным разработчиком". Человеку была поставлена задача, он ее даже выполнил — приложение как-то работало, хотя некоторые баги с удалением объектов навевали грустные мысли о неправильной работе с индексами списков. А это — плохая примета. Если человек не умеет работать с удалением из списков, то это скорее всего только начало проблем, и далее стоит ожидать худшего.  Так, в принципе, все и случилось. Когда ТЗ было почти что выполнено, полностью оплачено и исходники переданы, я понял, что просто зря выкинул деньги на ветер. Напомню, что приложения Android пишутся на Java — объектном (с небольшими оговорками) ЯП. Или даже некоторых объектно-функциональных (тоже с оговорками) ЯП типа Kotlin и Scala.  Наш же герой, назвавшийся «разработчиком Android», не освоил даже процедурного программирования (своеобразный «бронзовый век» программирования) и остался где-то на уровне структурного («каменный век»). Своим каменным топором на палке с единственной функцией "копи-паст", он и сколотил все мое будущее приложение.  О, этот человек — гений копипасты. Например, каждый раз, когда надо было взять объект по id из списка, он писал цикл. А когда ему попадался список списков, он писал вложенный цикл. Поэтому мое новое приложение на 80% состояло из «лесенок» циклов разной степени вложенности…
Все эти циклы были до боли похожи друг на друга, но создать приватный метод, например, getObjectById "разработчик" так и не догадался. Надо ли говорить, что методы insert и update длиной по 200 строк совпадали на 90 процентов?  Я занялся рефакторингом этого "чемодана без ручки" (нести неудобно, бросить жалко — деньги же уплочены). IDEA честно мне подсвечивала дублирующиеся куски и предлагала вынести их в функции. Методом простого нажимания F2 (переход к следующему предупреждению), Alt-Enter (показать варианты действий) и Enter (выбор первого дефолтного варианта). Мне удалось сократить исходный код в 1.5 раза. Остается загадкой, что мешало сделать это самому разработчику. Незнание, что в IDEA есть предупреждения? Потом я занялся уже рефакторингом классов, которые тоже были тупо скопированы, без малейших попыток создания супер-классов с общей функциональностью. Пришлось серьезно поработать и над инкапсуляцией и побочными эффектами — статичные публичные свойства классов с успехом заменили человеку отсутствие глобальных переменных в Java. Например, id редактируемого объекта было просто глобальной переменной главного Activity... В общем, исходный код был раздут как минимум в трое-четверо. А я напомню основную аксиому программирования:  Не глючит только код, которого нет. Отсутствующий код (при сохранении функциональности) – это предел, к которому надо стремиться. Из этой аксиомы неудивительным образом следует утверждение "больше кода — больше глюков". Избыточный код — это главная проблема копипасты — она примерно квадратично увеличивает количество багов в коде. Для борьбы с этим явлением еще на заре императивного программирования придумали процедуры. Но наш программист не искал легких путей…  Впрочем хватит ныть. Речь ведь не о нем, а о методиках обучения программированию в ВУЗах, когда свежего первокурсника сажают сразу на какой-нибудь С++ (прямо скажем, не самый лучший язык для новичков) учить ООП или зубрить алгоритмы сортировки с «о-большое-от-эн-логарифм-эн». И хорошо, если перед этим им хотя бы объяснили "черепашью графику". По факту же люди не знают самых основ программирования. Но давайте по чесноку! Вот вы там такие умные сидите сейчас и думаете "Ну это же детский сад! Я бы так никогда не сделал.". Допустим, все так, и настолько глупого кода с копипастой вы не напишите. Но насколько вы усвоили (и применяете) остальные, более сложные, концепции и парадигмы? Ведь любой современный ЯП — мультипарадигменный. И все эти парадигмы надо применять одновременно: создавая методы объекта, выделять смыслово-законченный или повторяющийся код в процедуры, возвращая замыкание в качестве результата обобщенной функции, не забыть про инкапсуляцию, заводя в проекте новый утилитарный модуль, вспомнить про решаемый аспект, и т.д.  Ниже в статье голосовалка — проверь себя, все ли из перечисленного ты знаешь. Там нет ни одной технологии или библиотеки специфичной для предметной области, только общие парадигмы. Я убежден, что любой, кто называет себя программистом просто обязан знать и применять все перечисленные подходы в любом языке программирования (от CSS до Erlang, от прости-господи-1С до Rust). Итак, что ты знаешь (можешь объяснить суть и плюсы-минусы в 2-3 предложениях и дать примеры, как ты это применял в последнее время)?  Если что-то для тебя там новое или ты не уверен, что можешь правильно объяснить, советую погуглить на досуге и немного повысить свой уровень с «разработчика» (в плохом смысле этого слова) до настоящего лампового «программиста». P.S.: список парадигм не претендует на полноту. Предлагайте свои дополнения в комментариях.