Функциональное программирование добавляет сложности в коде? [закрыто]

17

За весь прошлый год я написал Scala- код (исходящий из Java-фона). Мне очень понравилось, как вы могли бы создавать более простой и понятный код с использованием vals, case-классов, функций map / filter / lambda, имплицитов и вывода типа. Я использовал его в основном для приложений на основе Akka .

В этом году я работаю над проектом Scala с новой командой, которая действительно любит функциональное программирование. Они интенсивно используют Scalaz , и код везде заполнен аппликативами, границами контекста, монадой «читатель / писатель / государство», даже основной метод «обернут» в монаду ввода / вывода. Их аргументация заключается в том, что это заставляет компилятор «работать на нас», утверждая, что код верен, и каждая функция не имеет побочных эффектов.

Тем не менее, с моей точки зрения, весь этот синтаксис действительно мешает бизнес-логике. Например, тип «MyBusinessObject» подходит, а также такие типы, как «List [MyBusinessObject]», «Option [MyBusinessObject]» или даже «Future [MyBusinessObject]». Все они имеют четкое значение и цель. С другой стороны, код вроде:

def method[M[_]: Applicative] = {
  case (a, b) => (ca[M](a) |@| cb[M](b)) {
    case t @ (ra, rb) =>
      if (ra.result && rb.result) t.right
      else t.left
  }
}

это добавляет сложности программе, или это только я, что я не привык к такому способу программирования?

Лучано
источник
6
Каков ваш объективно отвечающий вопрос?
Охотник на оленей
1
Похоже, это приводит к большому количеству кода с именами переменных из одной или двух букв. Похоже, APL немного. Это не дополнение.
user949300
3
Я начал играть с Haskell в прошлом году. Это выглядело невероятно сложным в то время, когда я не понимал такие понятия, как карри, функторы, монады и т. Д. Haskell похож на Scalaz в том, что в нем много коротких символических функций, таких как >>=и <$>, которые ничего не значат, пока вы знать, что они делают. Однако, узнав, что они значат, они теперь очень естественно и быстро читают мне. Не совсем ответ, просто мой объективный опыт с такими вещами. Я также использую Scala, но у меня нет опыта работы с библиотекой Scalaz.
KChaloux
3
Вы просто не знакомы с идиомами. @ user949300 короткие переменные на самом деле не являются проблемой для большого количества функционального кода (подумайте о соглашениях по стилю математики!). Также прочитайте блог Тони Морриса для более глубокого обсуждения того, что лучше передает значение, типы или подробные имена переменных.
Андрес Ф.
3
@ user949300: короткие имена переменных предпочтительны локально, это то же самое в функциональном и императивном мире (вы не написали бы for(i=0; i<7; ++i) { trivialOperation(i); }с какой-нибудь неуклюжей trivialOperationCountпеременной, не так ли?) Теперь функциональные языки программирования с сопоставлением с образцом иногда вводят еще несколько переменных, где вы просто выписать вызовы методов доступа в OO. Результат обычно более лаконичен; возможно, немного менее очевидный, но поиск декларации данных, как правило, быстро дает понять. Статическая типизация очень помогает, это не так, как в APL.
оставил около

Ответы:

37

Это не имеет ничего общего с функциональным программированием - вы можете найти такую ​​ситуацию в контексте любого другого языка программирования - разработчиков, которые так любят продвинутые конструкции «своего» языка, что игнорируют здравый смысл в отношении читабельности и простоты. Я сталкивался с такой ситуацией в C, C ++, Perl, Java, C #, Basic и других нефункциональных языках. Это не функциональное программирование, которое добавляет сложности к коду - программисты делают.

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

Док Браун
источник
7
Это также имеет много общего с сообществом. Для разработчика с фоном Java или C # код едва понятен (и его / ее сообщество тоже не поймет). Но если вы пишете, например, на Haskell и не используете монады, аппликативы, функторы и т. Д., Вы сбиваете с толку сообщество этого языка. «Естественность» кода не присуща ему, а связана с его сообществом и сложившейся практикой.
Андрес Ф.
1
Это трудно понять, потому что большинство из нас происходят из императивов, что иногда заставляет нас делать неправильные предположения о том, что естественно.
Андрес Ф.
просто посмотрите на библиотеку SLT C ++, которая может быть написана так, чтобы она была намного более читабельной для любителя
чокнутый урод
@ratchetfreak: Полагаю, вы имеете в виду STL. Я думаю, что это очень хороший пример (и действительно, я имел в виду это в своем ответе). Использование шаблонного метапрограммирования имеет большой смысл, когда вы программист на STL, потому что это делает STL более пригодным для повторного использования. И люди, которым приходится поддерживать этот код, обычно тоже используют шаблоны метапрограммирования. Использование шаблонного метапрограммирования в стиле STL во всех стандартных бизнес-приложениях может легко привести к чрезмерно сложному и трудоемкому коду. Конечно, можно найти (редкие) случаи, когда TMP хорош даже в бизнес-приложениях, конечно.
Док Браун
@DocBrown Да, дислексия началась не вовремя, но, если честно, если бы у меня хватило ума (и гораздо больше времени, чем у меня сейчас), я мог бы переписать многие функциональные тела, чтобы они были гораздо более читабельными.
фрик с трещоткой
7

Я бы сказал, что вы не привыкли к тому, как они кодируют, по крайней мере, часть картины. Я нахожусь в той же ситуации, что и вы (переходя из C # в F # и работая с людьми с опытом работы в Haskell), и хотя я нахожу это интересным опытом, у меня бывают моменты, когда я бьюсь головой о стену, распутывая особенно запутанная бессмысленная композиция функций только для того, чтобы получить представление о том, что там происходит. Это культурная вещь.

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

Опять же, это также может быть случай «искусства ради искусства», как предполагает @Doc Brown. Не могу исключить это тоже.

scrwtp
источник
5

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

Тем не менее, функциональное программирование делает возможной более высокую степень абстракции, и хотя крайне абстрактный код может быть чрезвычайно полезным, его также может быть трудно понять, поскольку он по определению отделен от контекста, который вы обычно используете для руководства вашим пониманием. Ваш комментарий «Все они имеют ясное значение и цель» о бизнес-объектах, несомненно, является верным, но на самом деле он отражает тот факт, что эта логика очень специфична для потребностей и контекста, которые вы уже понимаете. Существование такой конструкции, как Monad, позволяет вам сделать что-то очень полезное без особых усилий, но в Интернете полно страниц, пытающихся объяснить, что такое Monad. Это абстракция для вас.

Также Scalaz был написан людьми, которые долгое время ели и дышали FP; они хотели перенести функциональность, доступную в Haskell, в Scala. При этом они не пытались быть педагогическими. Скалаз использует словарь и стиль, которые кажутся авторам понятными и понятными, но чужды непосвященным. Методы, которые ставят нас в тупик, кажутся авторам настолько очевидными, учитывая их происхождение из Хаскеля, что они даже не заслуживают комментария.

Кроме того, как функциональный язык программирования Scala имеет некоторые недостатки (отчасти потому, что у JVM есть недостатки), которые вынуждают авторов Scalaz писать более уродливый код в некоторых случаях. Например, отсутствие общего исключения хвостовых вызовов вынуждает использовать батуты в некотором коде, а отсутствие «доброй системы» может усложнить сигнатуры типов.

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

Повесить там. И это может помочь.

AmigoNico
источник
-4

Это добавляет сложности программе или просто вы не привыкли к такому способу программирования?

Почему вы думаете, что эти возможности не одно и то же?

Хорошо написанный код может быть прочитан людьми, которые не знакомы с конкретным языком программирования. Некоторые языки (BASIC, Pascal и т. Д.) Могут быть прочитаны и понятны школьниками, которые никогда раньше не видели языков программирования.

Если кто-то, кто имеет опыт работы с другими языками и имеет опыт работы со Scala (и, как я полагаю, работал со Scalaz по крайней мере неделю и у него есть коллеги, чтобы объяснить более хитрые вещи), все еще в замешательстве; тогда это доказательство того, что это добавило сложности.

Brendan
источник
11
Это просто неправда:"Well written code can be read by people who aren't familiar with the specific programming language."
Андрес Ф.
@Andres: это правда ... в точку. Хорошо написанный код отделяет бизнес-логику от деталей реализации, и бизнес-логика должна быть удобочитаемой, потому что большая часть того, что она делает, - это прямые вызовы хорошо названных вспомогательных функций. Разумеется, эти помощники могут использовать все виды языковых функций, и для их понимания требуется большой опыт работы с языком и библиотеками.
Бен Фойгт
4
Я считаю , что следующий идиоматичен APL: x[⍋x←6?40]. Как вы думаете, что это делает? Я уверен, что не знал бы ...
bdesham
3
@Brendan Только в рамках одной и той же парадигмы (и даже тогда, иногда нет). Например, Prolog, Java и APL настолько различны, что я бы сказал, что если вы знаете только один из них (и никаких других языков), вы не сможете прочитать два других, независимо от того, насколько хорошо вы знаете первый. (Серьезно, в примере Бдесхема, как, черт возьми, вы должны истолковывать «рождественскую елку», если не знаете APL?)
Изката,
1
Брендан, твое определение хорошо написано нестандартно. Хорошо написано всегда по отношению к языку и его сообществу. Программа на языке X написана хорошо, если она не содержит ошибок, она эффективна и понятна ... для данной аудитории! Это относится к письменному языку в целом, кстати: всегда знайте свою аудиторию. То, что подходит для (скажем) научной статьи, вероятно, не подходит для электронной почты вашей маме.
Андрес Ф.