Pull to refresh

«Однопоточный программист»

Reading time5 min
Views47K
Всё нижеизложенное вымысел, основанный на реальных событиях.

Не являясь мастером писать заметки, пытался «с пылу с жару» изложить это вчера. Но просто и доступно выстроить мысли в стройном порядке «по горячим следам» не вышло.

Кроме того на личном опыте выяснилось, что описываемый подход, хоть он, на первый взгляд и кажется мне очень простым, статистически таким не является. Известное высказывание о том, что «простые вещи, они самые сложные» оказывается в данном случае верным.

«Практическое» применение данного подхода требует усилий и кропотливой работы над собой, до тех пор, пока он не станет безусловным рефлексом, пока допускаемая «неточность» не будет заметна ещё до её совершения.

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

В связи с чем, публикуя эту заметку здесь, ожидаю, что вторым «застреленным зайцем» может стать помощь кому-нибудь ещё в избавлении от подобных ситуаций.

UPD3 спасибо dimka_ben: под «однопоточностью» подразумевается особенность мышления конкретного индивидуума, когда в один момент времени он может думать только о чем-нибудь одном.



Итак, есть два программиста. Нормальные парни, знают много, работают достойно.

UPD1: gо совету из комментария bachin:
#define Никита «программист номер один»
#define Денис «программист номер два»

Оба занимаются UI, оба пишут код для браузера на JavaScript. Оба понимают код друг друга, и оба же без серьёзных проблем его исправляют.

Но при этом раз за разом повторяется следующая ситуация: если Денис исправляет код Никиты, то у него это никогда не получается с первого раза. Никита же всегда сразу исправляет код Дениса без задержек и проблем.

Тут можно было бы подумать, что Денис просто «хуже». Но на самом деле это не совсем так, они просто «разные», и сталкивались с разными вещами. А сейчас делают «одно и то же дело».

И вот настал момент, когда Никита ушел в отпуск. Естественно вскоре ситуация усугубилась, и Денису пришлось править хоть и знакомый, но всё же «чужой» код.

Он переделывал его трижды. Почти целый рабочий день на тридцать строк кода. При том, что этот код был ему знаком и существенно не изменялся уже несколько месяцев.

И нужно-то было, даже не исправление, а мелкая доработка, вывод сообщения в случае одного из трёх возможных Use Case.
Когда он вывел «Сообщение» в первый раз, в Jira появился баг о том, что отвалилось два других Use Case. Он исправил ошибку, но в Jira тут же появились два бага о том, что больше нет нужного «Сообщения» и не работает третий Case. В итоге, так повторилось несколько раз, суммарно накопилось 10 багов.

Так как данная ситуация была уже более чем привычна, я решил вспомнить когда и в каких конкретно условиях это повторялось.
Оказалось, что это всегда происходит в примерно одинаковой ситуации, с почти неизменным дано:
  • Производится обработка UI событий (действий) пользователя: нажатие кнопки, выбор из списка, в общем – «интерактив».
  • Обычно ситуация происходит в очень простом, можно даже сказать «элементарном» алгоритме, когда кажется, что исправить это можно за пять минут.
  • В обработке разных Use Case используется один метод или одна функция. Т.е. одна и та же «точка входа в алгоритм» но от разной последовательности пользовательских действий. Часто даже от разных экранов.


В последний раз Денис закопался в ситуации из трёх кнопок:
  1. «Сохранить» и «Сохранить и создать ещё» на экране «Создания» записи,
  2. «Сохранить» на экране «Редактирования».


На все три кнопки Никитой был поставлен единственный обработчик, т.е. все три кнопки «сходились» в один метод. Получилось три разных комбинации, выполняющих похожие, но всё же немного разные алгоритмические последовательности. В методе так же были задействованы пара других последовательностей, доступных через «статусы» по IF. Тогда Денису потребовалось ещё больше времени, так как суммарное число Use Case в одном методе было 7.

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

Никита половину жизни работал со строго типизированными языками программирования, требующими компиляции перед запуском приложения.

Денис больше всего работал со скриптовыми языками со слабой типизацией, можно сказать, что всю жизнь использовал JavaScript в качестве основного языка.

Никита разбирался в ООП на уровне переопределения методов посредством разного набора входных переменных. Денис же без проблем реализовывал наследование на базе прототипов.

Никита работал с многопоточными приложениями. Денис собирался начать разбираться с реализацией многопоточности в рамках Node.JS.

Получилась интересная картинка:
  • Никита при отладке может думать о том, что этот код будет работать в разных Use Case.
  • Денис вспоминает о том, что здесь несколько Use Case только получив пачку багов.


То есть, Денис «сразу» вообще не воспринимает ситуации, когда в один и тот же алгоритм сходится несколько разных поведений пользователя.

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

Оказалось, что в отличие от Никиты, он пишет «разделяемый код» по-другому. Конечно, он выносит то, что повторяется, в отдельные методы, но то, что мы уже прозвали «точкой входа пользователя в Use Case» у него всегда реализовано одним отдельным методом.

Тогда я спросил его: «Почему ты так делаешь?»

Ответ меня шокировал: «Так я никогда не забуду, что здесь отрабатывает что-то ещё, т.к. ничего больше здесь и не описывается».

То есть, как только он сталкивался с ситуацией, в которой появлялся второй «входной» Use Case в рамках одного метода, он делил код на два, а «повторяющиеся» части выносил в отдельные сопутствующие методы. Причем обычно он делал это ещё в процессе обдумывания алгоритма и анализа того, что он собирается написать.

Таким образом, у него получалось, что в «отладчике» может одновременно быть только одна, единственная реализация обработки последовательности действий от пользователя.
И он никогда не сталкивался с тем, что может что-то забыть или упустить, т.к. было просто нечего забывать.
В тот момент, когда он начинал исправлять «разделяемый код» Никиты, его «однопоточный» подход ломался, и ему требовалось дополнительное время, чтобы вспомнить, что может быть совершенно другой способ изложения мыслей.

И тут я решил посмотреть, а нет ли у Никиты подобных ситуаций. Оказалось, что, как это ни странно, но – есть. Просто справлялся он с ними сразу по появлении соответствующего бага. Т.е., в силу привычки он просто помнил, что здесь может сходиться несколько Use Case, но от ошибок он тоже не был застрахован.

Тогда я проанализировал «баги» Дениса и выяснил, что в его коде вообще нет подобных багов, т.е. он никогда не возвращается к тому, что уже работает, до тех пор, пока не нужно внести изменения. Нет, ошибки были и у него, но они не были связаны с тем, что точкой входа в разные Use Case был один и тот же метод, т.к. у него просто не было такого кода.

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

Оставался последний вопрос – почему Никита тоже попадает в такие ситуации. Пытаясь это понять, я подумал о самом языке. JavaScript «однопоточен». И Денис всегда думает в один поток и «отлаживается» тоже только в «один поток». Никита думает о многих ситуациях сразу, но даже он порой ошибается при «смешивании Use Case'ов».

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

Не знаю, как назвать этот подход и откуда он пришел. Может быть это один из принципов KISS, может быть это что-то от graceful degradation, может быть это часть unix way (одно действие, но «хорошо»).

В вики, кстати, есть нечто похожее en.wikipedia.org/wiki/Separation_of_concerns, но не уверен, что это прям вот совсем то.

Но в любом случае мне нравится, что у «номера два» может в один момент сломаться только что-то одно, и не нравится, что у «номера один», если вообще ломается, то всё сразу.

UPD2: спасибо zloddey, может быть это SRP
Tags:
Hubs:
Total votes 92: ↑77 and ↓15+62
Comments129

Articles