Лирическое отступление: данный текст касается только людей, считающих себя программистом или желающими им стать; если человек считает себя верстальщиком, а ему навешивают задачи по программированию, то у него лишь одна проблема — не те задачи.
За годы программирования, натыкаясь на одни и те же «грабли», волей-неволей начинаешь задумываться над тем, что «нам мешает жить и работать». Данная статья — некий итог размышлений. В основном это результат наблюдения за самим собой, но что-то обнаружено при работе в команде.
Вместо того, чтобы решать проблему, находить объективные причины ее возникновения, программист начинает переживать ее как некий изъян своей личности. В итоге много нервов и времени тратится не на то, чем следовало бы заниматься. Иногда человек на столько «накручивает» сам себя, что решение задачи превращается в душераздирающую трагедию...
При таком подходе программист перестает воспринимать программу вцелом, не может увидеть красоту (или уродство) создаваемой программы, не видит целей, ради достижения которых пишется программа. От этого она может оказаться: нечитаемой, ресурсоемкой, неудобной для пользователя, просто в корне не верно написанной.
Недавно заметил еще одну разновидность данного подхода — назовем его «режим ЕГЭ», поскольку программист в таком «режиме» воспринимает поставленную ему задачу, как некий тест на экзамене и его важно сдать, «не завалить». При этом получается, что на саму задачу, по большому счету, наплевать, важнО лишь формальное выполнение. При этом постановщик задачи потом не может сказать, что задача не выполнена, но результат ее выполнения обычно не достигает тех целей, которые предполагалось достигнуть.
Обычно этому способствует проблема № 1, человек, пускаясь в личные переживания, даже не видит, что истинной причиной трудностей является отсутствие данных. Однако, человек, страдающий первой заморочкой, будет долго мучиться, но в конце концов, скорее всего, обратится к постановщику задачи за дополнительными сведениями. Человек из пункта 2, скорее всего, начнет выдумывать недостающие данные, исходя из своих соображений, что чаще всего потом приведет к необходимости переписывать программу заново.
Еще один вариант данной проблемы — правка неработающей программы наобум, «методом тыка», вместо того, чтобы вывести на экран все данные, влияющие на ход выполнения и вносить правки осознанно. К этому также относится нежелание заглянуть в используемый чужой код (а в PHP с этим проблем нет), чтобы понять как он работает, вместо хождения вокруг да около и гадания на кофейной гуще.
Программист (особенно с некоторым опытом) часто начинает считать всех не-программистов, мягко говоря, не очень сообразительными, а поэтому он «сам лучше знает» как надо делать. При этом все исходные данные могут оказаться очень здравыми и отвечающими нуждам заказчика, если не предвзято, а внимательно их изучить. Результат — трата времени программиста, менеджера, заказчика в попытках объяснить непутевым, «как на самом деле пишутся программы».
Это штука, противоположная п. 4. Если программист перед началом работы не оценивает, реально ли ее выполнить и за какое время, то может оказаться, что заказчик не в состоянии будет оплатить подобные расходы на разработку. Обычно причиной является отсутствие опыта в решении подобного типа задач у программиста или отсутствие этапа планирования при решении крупных задач.
И нежелание понять ближнего своего (заказчика) приводит к попытке программиста любую мало-мальски сложную задачу обозвать как невозможную, уговорить заказчика изменить задание таким образом, чтобы решение пошло по знакомой программисту обкатанной дорожке (перейти к стандартному функционалу Битрикс, например). С одной стороны, это, как правило, обычная лень, но бывает, что связано с п.1, когда программист страдает неуверенностью и «чересчур личностным» восприятием проблемы. Тогда это срабатывает своего рода самозащита: предчувствуя, что реализация задачи принесет массу душевных терзаний, он стремиться избежать ее любым способом. Здесь я, конечно, не имею в виду те случаи, когда сложность задачи действительно неоправдана, или заказчик был не в курсе стандартного функционала, который бы его вполне устроил, и придумывал «свой собственный велосипед».
Когда разработчику с опытом дается мелкая, нудная задачка, бывает, что он исполняет ее спустя рукава — «не барское, дескать, это дело». В результате либо задача начинает выполняться «по-тупому», слово-в-слово («получите, что хотели» , либо в задачу начинают привноситься сущности, которые в ней и не упоминались даже, одним словом — программист сознательно или подсознательно стремится сделать задачу проблемной, обратить таким образом внимание постановщика на то, что не ту ему задачу поставили. Потом начинают всплывать ошибки и приходится еще и еще раз возвращаться к этой «мелкой и нудной» задачке, либо сам процесс ее выполнения затягивается на неопределенно долгое время.
Задача обрастает кучей, вроде как необходимых, действий, сложность выполнения которых иногда превышает на порядок сложность самой задачи. Причина этого — завышенная оценка способа выполнения по отношению к важности самого выполнения. Иными словами, когда КАК становится важнее ЧТО.
Тут даже не важно, что «не знаю» и как это можно узнать, важна привычка скоропалительно приходить к такому выводу, после чего либо долго «тупить», либо просто ничего не делать. В программировании (тем более на PHP, где все программы хранятся в исходных кодах) нет ничего сложного. В большинстве случаев все сводится к простой логике. Вероятно, программист должен быть немного исследователем (немного любить предмет своей работы), чтобы избежать подобной проблемы, и еще он должен знать, что нет ничего невозможного, за исключением того, что в принципе невозможно. Нужно лишь «покопать»...
Можно и дальше продолжать этот список, но суть, я думаю, понятна: решению задачи мешает то, что по разным причинам привносится в нее извне, некий антураж, которым мы обволакиваем нашу задачу. То есть, нужно помнить, что задача не существует сама по себе, она всегда окружена чем-то. И чтобы в этот антураж не попало ничего лишнего (и ничего личного), нужно просто помнить об этом, о том факте, что у задачи есть этот самый антураж, перед и (периодически) в процессе выполнения задачи нужно внимательно смотреть, что мы в него внесли. Ничего нет лишнего?
Как подчеркнул автор, эти проблемы привносятся программистом «извне». Однако я чаще был свидетелем проблем, которые живут именно «внутри» задачи:
Обобщая, можно сказать, что все проблемы программистов возникают из эмоций. Программирование же зиждится на логике, математике и статистике.
являются исключительно следствием каких-то личных качеств программистов. Однако на практике оказывается, что корень проблем лежит часто вне возможностей и способностей программистов. Поэтому хотелось бы встать на их сторону и рассмотреть возможные внешние причины их возникновения.
Поскольку речь идёт о коммерческой разработке ПО, то основной причиной становится финансовая составляющая проекта и, как следствие, минимальные сроки реализации той или иной задачи. К сожалению, сегодня часто приходится слышать, что успешным станет не тот проект, который лучше, а тот, который раньше вышел на рынок. Как бы опытен и квалифицирован не был программист, при сокращении сроков ниже разумного предела он оказывается просто физически неспособен реализовать требуемую задачу на сто процентов, в результате чего приходится экономить на составляющих задачах. Например, на архитектуре приложения.
Отсутствие архитектуры приложения приводит к недопониманию системы у программистов, вследствие чего правки начинают вноситься именно в том месте, где «показал» заказчик, без анализа их возможного влияния на другие подсистемы проекта. Упомянутые автором правки методом тыка тоже позволяют ускорить добавление функционала/исправление видимых ошибок. Негативной особенностью этих способов ускорения процесса разработки является прогрессирующая неспособность разработчиков находить возникающие ошибки во время тестирования, и фактически тестированием начинает заниматься заказчик на реально функционирующей, «живой» системе. Имеет место «исправление ошибок по факту», когда любая ошибка в системе правится лишь по запросу со стороны заказчика. Не потому, что разработчики низкоквалифицированы или хотят сэкономить на тестировании, а потому, что обнаружение ошибок в сложной, запутанной системе, не имеющей архитектуры, практически невозможно.
Вторая причина упомянутых автором проблем — в недостаточном взаимодействии программиста с конечным заказчиком, что может быть обусловлено множеством факторов. Начиная от минимальных сроков на задачу, когда проще сделать «точно как написано в ТЗ», а потом в случае необходимости подправить, чем тратить несколько дней на выяснение от заказчика точных требований, расходуя бюджет проекта фактически впустую (вряд ли заказчик согласится оплатить несколько дней обсуждения функционала, если реализация конечного решения будет занимать от силы несколько часов). И заканчивая иногда довольно большим количеством промежуточных звеньев в цепочке заказчик-программист (особенно характерным для применяемой большими компаниями модели водопада), при котором часть требований заказчика теряется в процессе передачи информации от него к аналитику, проектировщику, менеджеру проекта, дизайнеру интерфейсов и др. и в конечном счёте программисту. В небольших компаниях большинство ролей выполняется одним-двумя сотрудниками, что улучшает обратную связь с клиентом. Однако в этом случае на «программистов» ложится множество обязанностей, не связанных непосредственно с разработкой ПО и лежащих совсем в другой области знаний. Например, программисту бывает проще сократить стоимость проекта под давлением заказчика, чем тратить нервы и время на психологическую борьбу с ним, что в итоге негативно отражается на финансовом состоянии компании и её развитии.
Третья причина — недостаточное взаимодействие программистов внутри команды. Простейший пример здесь — упомянутая автором ситуация «личной драмы». Часто приходится наблюдать ситуации (и не менее часто участвовать в них), когда программист несколько часов или даже дней бьётся над решением какой-то задачи и, когда практически сдаётся, подзывает на помощь кого-то, кто находит решение за полчаса-час, причём большая часть этого времени тратится на объяснение отчаявшимся программистом задачи помощнику. Более того, по личным наблюдениям, данной проблеме больше подвержены более квалифицированные сотрудники, а квалификация помощника роли не играет. Здесь становится важен сам эффект «свежего взгляда». С другой стороны, в век существования ресурсов, подобных habrahabr.ru, stackoverflow.com и других, не стоит из-за каждого пустяка беспокоить коллег, так как лучше запоминается то, что изучено или найдено самостоятельно и на что потрачено некоторое время, чем то, что подсказано другими.
Другим проявлением недостаточного взаимодействия членов команды является отсутствие контроля за новичками со стороны более опытных специалистов. Более опытный коллега, с одной стороны, не позволит новичку выполнить задачу «в режиме ЕГЭ». С другой стороны, глаз работающего в одной области человека замыливается, и возможность видеть, как при решении уже известных ему проблем поступают новички, может позволить взглянуть на эти проблемы с другой стороны и расширить или упростить свой арсенал методов для их решения. Кроме того, делать «по аналогии» всегда проще, чем искать правильное решение самому; одно дело иметь корпоративную wiki с описанием процессов типа особенностей использования IDE в компании, стиля кода, стиля комментариев к коммитам в системе контроля версий и др. и заставлять новичков изучать эту документацию. И совсем другое — позволить новичку в режиме парного программирования увидеть какие навыки применяет и как работает более опытный коллега при решении задач.
И последняя причина, не являющаяся, по большому счёту, виной программиста, — отсутствие его мотивации, вызванное работой в неподходящих условиях. Например, это постоянное переделывание (или незначительные изменения) одного и того же функционала заказчиком или регулярный переброс программистов между проектами. Даже если клиент оплачивает каждое изменение и компания в целом находится в плюсе, у программиста создаётся ощущение, что как хорошо ни делай, а через две недели всё равно придётся всё переделывать.
Последняя ситуация также существенно замедляет развитие сотрудников: вместо того, чтобы совершать ошибки и потом учиться на них, анализируя причины и последствия самостоятельно принятых при реализации той или иной задачи решений, программисты вынуждены постоянно исправлять ошибки других, и не видя последствий собственных решений и продолжают совершать всё те же ошибки.
В целом же, мне кажется, «нам мешает жить и работать» тот факт, что разработка ПО — ещё достаточно молодая область, и все советы на тему того, что и как нужно делать, являются, скорее, рекомендациями, чем общепризнанными формальными стандартами. Невозможно изучить «Правила разработки ПО», сдать на права категории «Веб-разработчик» и после этого делать всё правильно. Большинство программистов развивается в профессиональном плане методом проб и ошибок, вплоть до того, что у разных компаний, занимающихся разработкой ПО в одной области, стандарты процесса разработки и требования к результату могут существенно различаться.
Поэтому одной из основных задач компании является не просто позволить сотрудникам расти в профессиональном плане, реализуя приходящие от заказчиков требования и обмениваясь опытом с коллегами, но и позволить им экспериментировать (в разумных пределах, конечно) при реализации функционала в поисках более эффективных и интересных решений. Это, с одной стороны, позволит программистам почувствовать себя чем-то бОльшим, чем механическим переводчиком с клиентского языка на компьютерный, а с другой стороны, возможно, позволит компании стандартизировать и оптимизировать у себя часть решений и внутренних процессов, дав ей конкурентное преимущество как среди заказчиков, так и среди ищущих работу программистов.
В этой статье замечательно всё, кроме заголовка и вывода. Да, такие проблемы действительно иногда имеют место. Однако, с одной стороны — это не всегда проблемы программиста. По крайней мере, не того программиста, который непосредственно решает задачу. Например, проблемы по пунктам 3, 4 и некоторые другие — это дефекты постановки задачи и контроля выполнения. Программист не виноват, если ведущий программист не в состоянии чётко определить входные/выходные данные для задачи или корректно описать архитектурные и алгоритмические требования.
С другой стороны, все субъективные излишества, которые вносит программист в решение задачи, неизбежны. Как правильно заметил автор, задача не существует сама по себе, всегда есть ещё «что-то». И обязательно в этом «чем-то» есть личность программиста, которая неизбежно привносит какие-то субъективные моменты в решение задачи. Но дело в том, что программист просто не в состоянии обнаружить эти привнесения. Как логическая система сама по себе не в состоянии доказать свою непротиворечивость (вторая теорема Гёделя о неполноте), так и человек никогда не может быть полностью уверенным в том, что он всё делает корректно. И это опять возвращает нас к уже озвученной мысли: необходима чёткая формулировка задачи и контроль выполнения.
Проведите конкурс среди участников CMS Magazine
Узнайте цены и сроки уже завтра. Это бесплатно и займет ≈5 минут.
Ведущий инженер-программист в Simtech
Хотелось бы добавить комментарий к5-ому пункту: «Попытка решить задачу в точности, как ее описал заказчик».
Тут еще может быть проблема несколько в другом. Не только в сроках. Есть люди, которые стараются сделать именно так, как написано в ТЗ, даже если в конкретном случае это может противоречить здравому смыслу. Не всегда изменения хорошо ложатся в архитектуру проекта. И в итоге проект обрастает «костылями», «обходными решениями» и т.д. Но разработчик старается выполнить ТЗ от первой буквы до последней.
Иногда, как мне кажется, лучше обсудить подобные места с Тимлидом/Заказчиком, объяснить сложность реализации и найти другое решение или придумать, как, слегка изменив задачу, добиться лучших результатов.