Обычно процесс решения задачи у меня протекает так:
1. Понять requirements и изо всех сил постараться их упростить до MVP (minimum viable product). Отбросить все требования по performance, и отбросить/упростить все фичи, которые можно отбросить, чтобы продукт всё ещё мог делать хоть что-нибудь end-to-end. Как правило, начинаю со структур данных и data flow, и упрощаю их.
2. Как можно быстрее написать прототип, работающий end-to-end, написать к нему юнит тесты и end-to-end тесты, и наладить среду разработки так, чтобы можно было очень быстро делать маленькие изменения и отлаживать. Длина итераций критична. В идеале - секунды. Плохо, но терпимо - несколько минут. Неприемлемо - более 5 минут. Т.е. если итерации занимают более 5 минут, я буду всё рефакторить и редизайнить до тех пор, пока не смогу делать изменения быстрее.
3. Уже имея прототип, занимаюсь рефакторингом - делаю много итераций. Зачастую кардинально меняю абстракции, разделение на компоненты, нередко меняются структуры данных и data flow. Обычно это происходят по мере того, как валятся свежие тесты или как обнаруживается неспособность их написать из-за плохого дизайна.
4. Добавляю немножко фич - это всё равно почти MVP, но обычно добавление первых нескольких фич к чему-то уже работающему помогает понять слабые места в дизайне.
5. Уже имея вылизанный и красивый прототип для MVP плюс немного больше, я способен заниматься настоящим дизайном - т.е. рассуждать про requirements в целом, делать какие-то proof of concept, в общем делать какой-то осмысленный дизайн для задачи целиком.
Похоже, что люди, способные генерить дизайн сходу, весь этот процесс проделывают в голове. Мне не очень понятно, как. Ну, наверное, понятно - для несложных задач или для задач, которые я уже делал раньше, или видел код, я могу наваять что-нибудь сходу, но реальные задачи, как правило, сложные. Я не понимаю, как люди могут целый месяц что-то рисовать на доске, не попробовав написать прототип. Мне трудно думать, когда нельзя "пощупать", а "пощупать" это значит "написать и запустить". В общем, кинестетик.
Таким образом, первая проблема - это возможность полноправного участия в design brainstorming на ранних этапах, когда времени на кодинг нет вообще, а задач по дизайну много.
Вторая - это процесс development'а. Для меня куда более естественно добавлять end-to-end вертикали по-простому, а потом постепенно рефакторить. Коллеги, которые лучше подкованы в том, чтобы делать всё в уме, пишут много фидбека, который сводится к тому, что "сделай прямо сейчас то, что ты собирался сделать на 2-й, 3-й и т.д. итерации" (ну, вернее, писали бы, если бы я к ним не подстраивался и делал бы в том порядке, в котором мне комфортнее... конечно же, я подстраиваюсь, чтобы фидбека было мало). При этом итеративный девелопмент, разделённый горизонтально (по комнонентам, когда какие-то компоненты вообще no-op), людьми воспринимается нормально. А вертикальное деление (добавить маленькую фичу, протащив её везде, и зарефакторив) люди не любят. Причём не из-за merge conflict'ов (если изменения небольшие, то merge это ерунда), а именно из-за различий в мышлении, в подходе. Может, у них вызывает отвращение заведомо throw-away код, когда понятно, что вот это уйдёт, когда я добавлю вон то. Может, для них мой подход сложен, примерно так же, как для меня сложен их подход. Точно не знаю причин.
Ещё одна проблема - это споры за то, как надо делать. Скажем, типичная ситуация: двое ожесточённо спорят, каким способом решить одну проблему - первым или вторым. Я видел в жизни разное, и мне кажется, в обоих способах могут выплыть неожиданные вещи, которые куда "дешевле" узнать, быстренько попробовав реализовать любой из этих двух способов (или даже оба), чем ведя вот эти теоретические обсуждения на пальцах. В общем, эта абстрактная информация, без эксперимента, у меня в голове частенько вообще не регистрируется как весомая. Со стороны выглядит, что у меня нет своего мнения, т.к. на этих ранних этапах, где люди обсуждают, я соглашаюсь с любым из способов, лишь бы поскорее перестать спорить и сделать хоть что-нибудь.
Ещё одна проблема - это то, что народ не ценит важность возможности быстрых итераций, поэтому если я своими руками не делаю какие-то улучшения (как в продукте, так и настраивая свой environment, полезные скрипты и прочее), чтобы было быстро, то чьими-то другими руками почти наверняка будет медленно. Будет рождён монстр, который компилируется 10 минут, ещё 10 минут ждать integration test'ов, и ещё минут 5 продираться с помощью десятка third party tools, чтобы собрать всё состояние системы, необходимое, чтобы разобраться, что именно сломалось и почему. Но для большинства это приемлемо, потому что у них натренирован вот этот умственный подход. Они сразу делают всё в уме, или рисуют на доске, и эти эксперименты им вроде как и не нужны.
Есть подозрение, что причина различий ещё в том, что мой подход фундаментально bottom-up, а люди вокруг натренированы использовать в top-down. Я могу воспринимать top-down либо в режиме рефакторинга, либо когда я размышляю вообще очень-очень high-level, либо когда я размышляю только над data flow. А вот в режиме top-down придумывать софтовые абстракции - с этим туго.
У меня вот эта кинестетичность и желание экспериментировать доходит до того, что если я давно не писал код (больше 3-5 дней), у меня вообще пропадает желание работать. Зная это, я придумываю себе coding задачи, которые, может, и не нужны, но помогут мне вернуться в продуктивный режим и держаться в нём.
Расскажите, есть ли у вас похожие проблемы с подходом к дизайну и к решению задач.