Pull to refresh

Comments 20

Мне кажется, вы очень быстро проскочили через 'S-вопрос' (что такое Simple?). Я бы это прям назвал отдельной проблемой для software engineering, проблемой поиска определения простоты.


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


  1. Человек, который читает код, тратит пренебрежимо мало времени на понимание происходящего.
  2. Каждый объект в лексере (переменная, модуль, путь к файлу, класс, etc) имеет имя (или структуру, если это файлы), которая не вызывает вопросов "зачем". Чаще всего это best practices. Например, файл конфигурации для foo в /etc/foo.conf или в /etc/foo.conf.d/01-base.conf оба не вызовут вопросов, а вот /opt/foo/lib/shared/01-base.conf — вызовет и много.
  3. Каждый компонент придерживается одного из двух принципов: либо полная изоляция (чёрный ящик, на вход параметры, на выход результат и никому не интересно что внутри происходит), либо полная прозрачность (код ящика тривиален и выполняет очевидные действия над данными). Добавленной ценности мало, добавленной головой боли нет. Худший вариант — когда модуль пытается реализовать абстракцию, но делает её не до конца; в этой ситуации добавленной ценности маловато, а головной боли больше, чем ценности.
  4. Постоянное слежение за provenance любых артефактов и кода. Откуда этот файл? Чужой? Взятый из другого проекта? Как он обновляется? Как узнать откуда он был взят спустя 5 лет, когда оба проекта давно эволюционировали? Почему этот коммит, а не другой? Это был head или какой-то бранч?

Т.е. моё определение S очень сильно завязано на объём onboarding и investigation со стороны человека, который имеет квалификацию, но не знаком с проектом до момента, когда этот человек может начинать осмысленно работать с кодом.

В статье как раз все идёт к простоте. Но я разделяю вашу точку зрения — «намерение»(intent) в моей команде главенствующий принцип ревью. То есть, код должен реализовывать явное и непротиворечивое намерение, и это намерение должно быть читаемо из кода. Однако, мне кажется, что хоть это сродни простоте, но это все же про лёгкость: simple vs easy.

easy — это для глагола (пусть и подразумеваемого), а simple — для существительного.

С одной стороны хорошо, что статья лёгкая для восприятия (а не как всегда в случае теории категорий).

С другой стороны хочется спросить: «и что?». Какие выводы мы можем сделать из такой интерпретации KISS?

Кроме того, такие идиомы как KISS, DRY и прочие раскрываются в полную силу в более широком контексте, который включает в себя не только сам код, но и его контекст: динамику проекта, планы, команду. Я бы даже сказал, что применять эти идиомы только к коду, без контекста, ошибочко (в большинстве случаев). Соответственно, возникают сомнения в применимости подобной формализации.

Не хочу сказать, что теорию категорий нельзя применить к этому вопросу, но применять её можно точно не тем способом, который описан в статье.

Тысячи и тысячи вещей влияют на принятие решений в проекте. Вот, например, amarao верно подмечает прозрачность намерения. Но от этого принцип за тем же KISS не меняется, по моему мнению. Эти лучшие практики про то как писать код являются одним небольшим срезом к успешному проекту. В этой статье речь лишь про то, что вроде как можно этот срез формализировать а уже имея формальные критерии маленького среза можно дальше смотреть на влияние все этих лучших практик на проект.

Каждая новая большая теория объясняла больше явления природы и при этом была проще предшественников.

Проще в чём? Например, уравнение Ньютона для гравитации проще в плане решений, чем уравнение Эйнштейна. В ОТО устраняется лишняя сущность из Ньютоновской механики, но при этом вводится новая сущность в виде лямбда-члена.


В каком-то смысле, мы получили h ◦ g за так. И теперь можем отобразить A к D когда и если необходимость появится. Скажем в следующем спринте, когда менеджер продукта захочет показать инвойсы (D) пользователя (A) по транзакциям ©.

Это если функции чистые. В жизни там обычно всегда присутствуют побочные эффекты, и всё становится резко сложнее. Собственно, в отрыве от реальности ФП просто как 2 копейки, но в жизни обычно плохо получается так красиво всё формализировать, и проект с обильным ФП очень часто становится write-only через пару месяцев.

Собственно, в отрыве от реальности ФП просто как 2 копейки, но в жизни обычно плохо получается так красиво всё формализировать
IO код в Хаскелле мало чем отличается от обычного императивного языка. Так что формализуется всё запросто.

и проект с обильным ФП очень часто становится write-only через пару месяцев.
Спорное утверждение. При прочих равных, скорее проект без ФП станет write-only.
IO код в Хаскелле мало чем отличается от обычного императивного языка. Так что формализуется всё запросто.

IO — да. Другие монады сложнее.


При прочих равных, скорее проект без ФП станет write-only.
Ну совсем без ФП — наверное да. Я его использую там где нужно просто перегнать данные из одного формата в другой. Но внутри самих функций обычно императивщина. Иначе всё либо скатится в огромную кучу мелких функций и временных переменных, либо в лабиринт композиций. Когда пишешь композицию — то тебе всё понятно. Но через полгода слёту не разберёшься в собственном коде.

Напрмер, от прошлого сотрудника в наследство досталось такое:


const res = filter(isCourseItem, map(pipe(prop<any[]>('path'), p => slice(0, p.length - 3, p), when(<any>length, flip(path)(newState))), df1));

Было бы написано с циклами — разобраться было бы быстрее.

Будет проще разобраться если не экономить на переменных и не пихать промежуточные результаты в конечное выражение.

IO — да. Другие монады сложнее.
Те, что более-менее часто используются достаточно простые: Reader, Maybe, State. Всякие Cont и трансформеры уже действительно посложнее, но ими и пользуются сильно реже.
Было бы написано с циклами — разобраться было бы быстрее.
И код был бы гораздо длиннее. Не знаю, что это за язык, но примерно видно, что происходит фильтрация и обрезание массива. В цикле читать и понимать пришлось бы дольше. На Хаскелле без этой кучи скобок и указаний типов было бы короче и понятнее.
Это если функции чистые.

Это не единственная, и даже не главная проблема. Это все работает тогда, и только тогда, когда существует единственное отображение g: A → C и единственное отображение h: C → D.


В противном случае отображение A → D ниоткуда не выводится, точнее их получается много, и без дополнительных оговорок неясно, что вообще такое h ◦ g. Для примера со строками, самого первого: есть isOdd: Number → Boolean, есть isEven: Number → Boolean. Ну и как теперь получить String → Boolean? Да никак. Проще и понятнее будет определить свою семантически верную функцию, для своего бизнес-случая. Именно поэтому хаскель так чудовищно многословен и перенасыщен таким количеством функций, делающих примерно одно и то же.




проект с обильным ФП очень часто становится write-only через пару месяцев

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

И это именно то, как можно определить простоту.


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

Нельзя вычислить, не беда, сравнивать то сложности мы можем, во всяком случае наши мозги как-то с этим справляются и мы можем сказать, что А сложнее Б. Можно даже выделить специального абстрактного Петю, который и будет единственный определять, является ли А сложнее Б. В такой ситуации хотелось бы уметь немного менять А и сравнивать результат с Б. Что-то вроде A + dx < Б? Для этого А нужно уметь представлять в дифференциальной форме. Тут затык, начинается такая математика, которую я не понимаю. Есть такая штука как differential lambda calculus, потенциально оно про это, но я не осилил.

"Простота" — это философское понятие. Как любое философское понятие, его можно изучать очень долго, создавая в процессе целые дисциплины (например, попытка понять что такое "истина" дала нам булеву логику, теорию предикатов и ещё шути что).


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

image
Как это на практике работает? Например:
A=string, B=boolean, C=int
f=isEmpty A->B
g=length A->C

И как вы собираетесь строить m B->C?

ps: это просто?
image
B->C нельзя построить из A->C и A->B. Придётся писать новую функцию.
Точно так же, как и для каждой новой трансформации универсального объекта в вашем примере.

UFO just landed and posted this here
UFO just landed and posted this here
Есть довольно простая идея, высказанная Фейнманом — цель физики найти простейшую теорию, которая сможет объяснить как можно больше явлений природы. Эта та идея, которая стоит за электродинамикой Максвелла или КЭД. Каждая новая большая теория объясняла больше явления природы и при этом была проще предшественников.

Ох уж эта американская школа. Везде им простота мерещится.
В своих работах физики дошли до физических-медицинских ограничений на сложность: нынешние теории просто сложно осваивать. Это было ещё с классической КМ или статистической физикой, а КЭД, ПМСМ, вообще жуть. Простота кончилась на Ньютоне и Максвелле где-то. Было бы замечательно, если бы появились более простые теории, работающие не хуже, но вот никак не получается.
Хорошей теории для создания самолёта пока что просто нет. В лучшем случае есть расчётные модели.

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

Авиация по большей части живёт на накопленом опыте.
Простота кончилась на Ньютоне и Максвелле где-то.

Полагаю в 17 веке дифференциальное исчисление Ньютона казалось не меньшей абракадаброй чем КЭД сегодня. Если же вы можете понять уравнения Максвелла, то вы уже знаете, что такое уравнения в частных производных, пространственное дифференцирование, операторная запись. Со всеми этими знаниями до понимания КЕД не так уж и далеко.


Простоты, о которой вы говорите никогда не было, просто за 300 лет все привыкли к Ньютону. Через 300 лет привыкнут и к КЕД.

Лично я очень жду продолжения. Интересно, куда дальше разовьётся мысль. Такими маленькими порциям читать — идеально, есть возможность аккуратно осмыслить и обдумать. Спасибо.
Sign up to leave a comment.

Articles

Change theme settings