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

13

Мне любопытно, потому что я помню, прежде чем изучать какие-либо функциональные языки, я думал, что все они ужасно, ужасно, ужасно нечитаемы. Теперь, когда я знаю Haskell и f #, я обнаружил, что для чтения меньшего количества кода требуется немного больше времени, но этот небольшой код делает гораздо больше, чем эквивалентное количество в императивном языке, поэтому это похоже на чистый выигрыш, и я не очень практикуется в функционале.

Вот мой вопрос, я постоянно слышу от ООП, что функциональный стиль ужасно нечитаем. Мне любопытно, если это так, и я обманываю себя, или если бы они потратили время на изучение функционального языка, весь стиль больше не был бы более нечитаемым, чем ООП?

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

Джимми Хоффа
источник
1
Я помню, как смотрел код для «Братьев Супер Нарио» svn.coderepos.org/share/lang/haskell/nario, когда почти ничего не знал о функциональном программировании и вспоминал, что думал «Ух ты. Это кажется действительно читабельным »
WuHoUnited
1
Взгляните на programmers.stackexchange.com/questions/158715/…
superM
3
@BlackICE linq и lambdas далеки от определения «функционального программирования». Функциональное программирование чаще всего включает в себя системы типов, потому что когда вы начинаете распознавать функции как типы, а не просто объекты / классы / записи как типы, вы получаете множество новых способностей и методов. Выражения LINQ и Lambda (или списочная монада и функции более высокого порядка) - это всего лишь два конкретных результирующих метода, которых гораздо больше.
Джимми Хоффа

Ответы:

15

Читаемость кода очень субъективна . Из-за этого разные люди считают один и тот же код читаемым или нечитаемым.

Назначение, x = x + 1звучит странно для математика, потому что назначение выглядит обманчиво похожим на сравнение.

Простой шаблон проектирования ООП будет совершенно неясен для тех, кто не знаком с этими шаблонами. Рассмотрим синглтон . Кто-то спросит: «Зачем мне нужен закрытый конструктор? Что за загадочный метод getInstance() ? Почему бы нам не создать глобальную переменную и не назначить там объект?»

То же самое относится и к коду FP. Если вы не знаете логические закономерности за кулисами, будет очень трудно даже понять что-то очень простое, например, как передать функцию в качестве аргумента другой функции.

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

bytebuster
источник
Люди должны создавать что-то похожее на себя (человечество). Например, даже в компьютерном зрении у нас теперь есть нейронные сети. Тело человека состоит из объектов, атрибутов, методов, и мы описываем другие вещи, используя объекты, атрибуты, методы. Так что функциональное программирование не имеет никакого смысла
user25
12

Короткий ответ:

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

Длинный ответ:

Функциональное программирование само по себе не может быть читаемым или нечитаемым, поскольку это парадигма, а не стиль написания кода. Например, в C # функциональное программирование выглядит так:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

и будет считаться читаемым любым человеком с достаточным опытом работы с Java, C # или подобными языками.

Синтаксис языка, с другой стороны, более компактен для многих функциональных языков (включая Haskell и F #) по сравнению с популярными языками ООП, отдавая предпочтение символам, а не слову в простом английском языке.

Это относится и к языкам вне FP. Если вы сравните популярные языки ООП с некоторыми менее популярными, которые, как правило, используют больше английских слов, то последним будет легче понять людей, не имеющих опыта программирования.

Для сравнения:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

чтобы:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

Точно так же:

var a = ((b - c) in 1..n) ? d : 0;

можно выразить на воображаемом языке как:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

Чем короче синтаксис лучше?

В то время как более подробный синтаксис легче понять для новичка, более компактный синтаксис легче для опытных разработчиков. Более короткий код означает меньше символов для ввода, что означает большую производительность.

В частности, не имеет смысла заставлять человека вводить ключевое слово для обозначения чего-то, что может быть выведено из синтаксиса.

Примеры:

  • В PHP вам нужно вводить functionперед каждой функцией или методом, без особых причин делать это.

  • Ада всегда ужасала меня за то, что я заставлял разработчиков печатать много английских слов, тем более, что нет правильной IDE с автозаполнением. Я недавно не пользовался Ada, и их официальный учебник не работает, поэтому я не могу привести пример; если у кого-то есть пример, не стесняйтесь изменить мой ответ.

  • Синтаксис 1..n, используемый во многих FP (и Matlab), может быть заменен на between 1, nили between 1 and nили between (1, n). betweenКлючевое слово делает его гораздо легче понять , для людей , которые не знакомы с синтаксисом языка, но все - таки, две точки гораздо быстрее набрать.

Арсений Мурзенко
источник
8
Я согласен с мнением, но по разным причинам. Дело не в том, насколько легко эксперт может писать код, поскольку код обычно читается гораздо чаще, чем пишется. Более короткий код также может улучшить читабельность, не тратя драгоценное время, место на экране и умственные способности, если что-то уже будет очевидно из более короткого индикатора (например, новые строки вместо точек с запятой, оба совпадения в любом случае). Она также может больно , когда он становится слишком загадочен (например, я предпочитаю for x in xsболее for x xs, потому что это помогает мне различать переменный цикл и контейнер).
Многие из тех, кого я нахожу, жалуются на FP, а также на фрагмент кода C #, который вы перечислили, как вы сказали, это также пример FP. Возможно, это больше проблема моих коллег, чем читабельности, если большинство ООП считают этот фрагмент читаемым, хотя я не совсем уверен, что большинство ООП делают это из моего опыта… поэтому я так не уверен в этой теме.
Джимми Хоффа
@ Джимми Хоффа: см. Programmers.stackexchange.com/a/158721/6605, где я обсуждаю именно фрагмент C # и как его воспринимают начинающие программисты.
Арсений Мурзенко
1
@Sergiy: в Java или C # в сигнатуре метода нет methodключевого слова. Пример: public int ComputePrice(Product product). Добавление такого ключевого слова, как то, что сделал PHP, просто добавляет беспорядок, а не упрощает чтение. Если программист не может понять, что функция является функцией по своей сигнатуре, либо у этого программиста нет никакого опыта, либо код гораздо более нечитабелен, чем худший код, который я когда-либо видел.
Арсений Мурзенко
1
@Sergiy: бывают случаи, когда многословие может помочь (в противном случае мы увидели бы языки и код, например p i ComputePrice(product): _.unitPrice * ~.cart[_]), но некоторые языки слишком далеко зашли. Пример избыточного functionключевого слова в PHP является хорошим примером.
Арсений Мурзенко
6

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

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

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

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

Петр Пудлак
источник
2

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

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

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

SK-логика
источник
1

Читаемость кода субъективна. Я уверен, что некоторые люди критикуют это из-за отсутствия понимания. Существуют разные идиомы в способе реализации общих шаблонов. Например, шаблон Visitor не имеет смысла в языке с сопоставлением с шаблоном .

Вывод типа может быть сложной функцией. Обычно это отличный ускоритель разработки, однако иногда бывает сложно выяснить, какие типы задействованы, из-за отсутствия контекста, приводящего к ошибкам, приводящим к путанице. Это не ограничивается языками функционального программирования - я видел это и в шаблонах C ++!

Современные языки имеют тенденцию быть мультипарадигмы . Это включает в себя как C # и F #. Можно написать функциональный стиль в C # и императивный стиль в F #. Те же люди, которые критикуют функциональные языки, вероятно, пишут функциональный код на своем объектно-ориентированном языке.

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

  1. Изменение стиля при изучении языка (а не рефакторинг) приводит к несогласованности.
  2. Слишком много в одном файле.
  3. Слишком много утверждений в одной строке.
Дэйв Хиллиер
источник
В отношении ошибок я также добавил бы: 4. Чрезмерное использование символов, например: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Неявные функции: необязательные объявления / ключевые слова / операторы, неявные преобразования и т. Д .;
Сергей Соколенко