All streams
Search
Write a publication
Pull to refresh
15
0

User

Send message
Хорошие разрабы используют ОО языки для процедурного программирования.

Эту фразу стоит превратить в вопрос:


Расскажите почему хорошие программисты используют ОО языки для процедурного программирования?

и смело добавлять в статью, настолько она сильная.


Я не знаю как ещё это комментировать.

При большом количестве понтов есть куча неадекватностей.

Так можно про любой язык сказать если в нём разобраться.

Я вот бекенд разработчик, занимаюсь "чёрными ящиками" (вход -> магия -> выход) — WebAPI, ETL, Streaming. И мне очевидно две вещи:


  • я хочу всё распараллелить, заасинхронить
  • я не хочу проблем

Поэтому я просто пишу в ФП стиле: иммутабельность везде. Сразу снимает проблемы с рейс кондишнами и проблемой глобальных объектов. У меня всё глобально доступно, но кого это волнует если функции чистые и они не мутируют объекты, а создают новые?


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

Почему глобальные объекты и статика — это зло? Можете показать на примере кода?

Чо эт сразу зло-то? В ФП вот всё по умолчанию статика и глобальные объекты. Ну не учитывая разбивку на модули (по сути неймспейс).


Наверное стоит спрашивать почему ИЗМЕНЯЕМЫЕ глобальные объекты зло? Но и это не всегда правда, может у меня есть изменяемый глобально параметр LogLevel, небеса не развернутся если я его буду менять из разных кусков кода.


Многие другие вопросы заранее в себе содержат "правильный" ответ, который собеседуемый должен взять за основу рассуждений (например: почему Java это плохо?).


Короче, плохой опросник.

Это будет совершенно верно до тех пор, пока еще другое знание не подскажет вам про то, что во многих языках программирования (например, C и C++)

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


В рекурсии нет ничего опасного. Если какой-то инструмент её неправильно готовит — это проблема инструмента, а не подхода.

Как уже сказали, рекурсия тут не нужна, и даже опасна — на больших объемах можно стек пробить с очень печальными последствиями.

Кстати, вот вам явный пример, когда знания устройства ОС и работы компиляторов оказываются гораздо ценнее абстрактного «матана» в реальной жизни :)

Ровно до тех пор пока другое знание вам не подскажет про хвостовую рекурсию.

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

Некоторые разработчики ещё и механики, а некоторые — только водители "у меня есть руль, я умею его крутить и знаю куда вонючая водичка на заправке заливается, остальное — не барское дело".

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

А чтобы быть хорошим водителем, обязательно надо собрать машину с нуля. Иначе никак.

Я думаю они совместимы до сих пор, т.к. throw в виде выражения возвращает любой generic тип, который выводится компилятором из второй ветки оператора ?? в виду того что throw не возвращает в обычном смысле.


В F#, где всё является выражением есть похожие функции:


failwith: string -> 'a
raise: exn -> 'a

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

А вы не пробовали F#? Там уже из коробки есть Discriminated Union и монструозные конструкции превращаются в:


type MyResult<'T> = 
    | Success of 'T
    | Error   of exn list

//Это ваш Select
let map f = function
    | Success v -> Success (f v)
    | x -> x

//Это ваш SelectMany
let bind f = function
    | Success v -> f v
    | x -> x

//Это ваш SelectMany от 2 функций
let bind2 f g = bind (fun x -> f x |> bind g)

А вообще в F# уже есть готовый тип Result с map, bind и пр, поэтому это всё не пригодилось бы.
Если у вас такая сложная доменная логика, вы можете отдельный проект под неё на F# запилить и 90% кодовой базы уйдёт за ненадобностью.
Меньше кода — меньше ошибок. А у вас за дженерик параметрами "леса не видно":


public static Result<TDestination>
    SelectMany<TSource, TIntermediate, TDestination>(
    this Result<TSource> result,
    Func<TSource, Result<TIntermediate>> inermidiateSelector,
    Func<TSource, TIntermediate, TDestination> resultSelector)
    => result.SelectMany<TSource, TDestination>(s => inermidiateSelector(s)
        .SelectMany<TIntermediate, TDestination>(m => resultSelector(s, m)));

Зачем пытаться из C# сделать F#?
Тем более этот SQL синтаксис


from x in xs select x

выглядит чужеродно для не коллекций.

Мне кажется человек ошибся и говорил про процедурное программирование. ФП же нифига непростое, т.к. матан.

Я думаю, Вы не уловили сарказм в словах автора.

Не, не подзабил, т.к. F# всегда был у Microsoft языком второго сорта) Их продукт — C#, а F# делается командой Don Syme на гитхабе.


Поддержку .NET Core 2 в Visual Studio только-только завезли. Через год может быть паблиш F# проектов в Azure припилят =)


По поводу инфраструктуры только частично соглашусь. Для большинства библиотек хватает вот этих функций


let curry f a b = f (a, b)
let curry3 f a b c = f (a, b, с)

let uncurry f (a, b) = f a b
let uncurry3 f (a, b, c) = f a b c

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


Кстати Newtonsoft.Json умеет работать с F# из коробки (списки, массивы, DU) кроме option. Достаточно добавить один кастомный Option Converter чтобы вообще всё заработало.


По поводу Jet.com любопытно. У них не так давно была волна агрессивного рекрутинга, где они предлагали "(high 5 to low 6 figures / year)", релокейт, но надо физически находиться в USA на момент обсуждения.
Если не секрет почему ушли из Jet.com?

А вот это немного неправда

Почему же? Где можно, там выводит) Где не получается — надо ручками писать, да.


С фиксированным приоритетом, зависящем от первого символа afaik

Это намного лучше чем их полное отсутствие (дада, C#, я о тебе).
Вполне хватает на любые нужды:
>>=
>?>
>>=.
|>
||>
!>
?>
и пр.
Подробнее можно здесь посмотреть как сделать постфиксные, префиксные и инфиксные операторы — http://www.readcopyupdate.com/blog/2014/09/10/custom-ops-associativity-precedence.html

Jet.com например бекенд весь на F#. Объяснение почему


От себя:
F# умеет всё что и C# (ООП, наследование, интерфейсы, netcore 2.0 вот это вот всё) + много сверху (Discriminated Unions, partial application, type inference везде где можно, кастомные операторы и пр).
Для создания бекенда прям самое оно. Система типов круче, ошибиться сложнее.
Фронты писать в функциональном стиле тоже можно, попытки видел, мне лично не нравится.


Есть просто отдельные крутые нугеты:
Logary, Hopac

Людей в гайдах по WPF/WinForms застращали этим ConfigureAwait, так теперь суют его везде.

Разве я здесь написал, что интерфейсы не нужны вообще?

Конечно нет. Вы написали что "интерфейсы не нужны к классам с единственной реализацией".


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


Расскажите где я неправ, очень будет любопытно.

Покажите мне где я написал, что интерфейсы не нужны?

Показываю:


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

Вам выше рассказали почему это утверждение не соответствует действительности.

Information

Rating
Does not participate
Registered
Activity