Но и критика ваша понятна.
Ограничением F# является то, что это язык, заточенный под инфраструктуру .NET — т.е., на нем писать можно/есть смысл, если по каким-то причинам вы пишите именно под .NET и хотите функциональщины и прочих улучшений в языке и практике работы с платформой.
С плюсами F# уже стало понятно, что ничего непонятно и объяснить на пальцах никто не может.
Это примерно (но только примерно) как то, когда спрашивают "ну а какие такие плюсы у Kotlin по сравнению с Java? Все это можно же и на Java написать."
Также, как 15 лет назад спрашивали "зачем C#, если есть Delphi и/или C++"
В том то и дело, что помимо функциональной парадигмы, на которой в F# писать легко (в C# нужно постараться), это еще и куча всего, что облегчает жизнь — можно просто взять и писать под .NET на F#.
При этом есть возможности при необходимости писать на F# более низкоуровнево, как мы это делали бы на C#.
Было бы очень интересно писать на F#, но проектов на рынке действительно нет.
Предлагать компаниям уже в процессе работы над проектом попробовать F#?
— Какое там, если в большинстве случаев нерешаемой «проблемой» является обновление CI для поддержки C# 7 вместо 5 (Карл, 2012-й год!). Какой тут F# (который до недавнего времени еще и свой отдельный рантайм имел).
После знакомства с F# действительно начинаешь мыслить и писать на C# по другому.
Впрочем, в своем случае «по-другому» я начал еще до изучения F#, самостоятельно доходя до ФП-парадигмы (и речь не только о «лямбдах как стратегиях») — пытаясь действительно эффективно решать задачи и нивелировать недостатки существующих подходов, и уже затем актуализировав выработанные подходы до общепринятой функциональной парадигмы.
Кто в теме поясните если не сложно, что такого есть в телеграмах, вайберах и ватцапах чего не было в аське.
Долго объяснять — от множества технических, интерфейсных и концептуальных моментов до общего вписывания в современную мобильную облачную архитектуру и вообще в современный дискурс.
Тут столько всего, что речь можно вести о переходе количества в качество.
Аналогия из мира программирования:
Что было не так в Delphi 20 лет назад, если на первый план вышли C# и Java?
Ведь в первых версиях C# и Java было практически все то же самое, что и в Delphi, кроме завезенного Garbage Collector (ага, а вот и началось — GC, то-се, дальше — больше).
И вроде бы сейчас Delphi догнал по возможностям своих конкурентов, но..
В .NET тоже есть определенный бардак в базовом API — в тех же коллекциях и датах.
Насчет коллекций — мое любимое:
А вот почему практически во всех проектах разработчики используют в открытых контрактах своих API либо List(T) (ай-ай, реализация, а не интерфейс, и при этом наиболее "полная" реализация — а как же SOLID?) либо IEnumerable(T) (ай-ай, сколько раз приходилось видеть вызов метода Count())?
Хотя в большинстве случаев по смыслу подходит использование IReadOnlyList(T) или IReadOnlyCollection(T) (список с конечным количеством элементов — упорядоченный по индексу, либо нет).
Если разобраться, то на это разработчиков провоцирует устройство базовых типов самой платформы:
Тип List(T) реализует интерфейсы IList(T) и IReadOnlyList(T).
Но что будет, если одна функция возвратила экземпляр IList(T), который мы хотим передать в функцию, которая на входе требует IReadOnlyList(T) или IReadOnlyCollection(T)?
Правильно — ошибка компиляции, т.к. интерфейс IList(T) не реализует интерфейс IReadOnlyList(T).
Вот и получается, что, чтобы работало, везде лепят List(T).
А вот если вторая функция на входе требует IEnumerable(T), то подойдет любая коллекция, в т.к. IList(T).
Кроме того, использование IEnumerable(T) провоцируется стандартной библиотекой платформы, хотя в большинстве случаев по смыслу речь идет о коллекции с конечным и известных количеством элементов (а что, если в будущем коду самой функции потребуется проверка коллекции на количество элементов? — а ведь замена типа параметра на IReadOnlyCollection(T) приведет к поломке компиляции всего написанного с ипользованием этой функции кода).
Та же проблема касается и словарей — Dictionary(K,V), IDictionary(K,V), IReadOnlyDictionary(K,V).
Получается, при казалось бы, такой сильной реализации Interface Segregation Principle в системе базовых коллекций, из-за такой мелочи по факту этот принцип не используется в прикладном коде.
И еще определенную путаницу вносит наличие ReadOnly- и Immutable-версий коллекций (да, мы знаем, чем они отличаются).
Последние так и не начали использоваться в проектах (у кого-то есть реальные примеры?), а еще перечень Immutable-коллекций не полностью соответствует 1-в-1 набору обычных (что-то добавлено, что-то отсутствует).
У меня смутное дежавю, но как будто бы уже была похожая по структуре и лейтмотиву статья .NET vs Java, только N-летней давности…
По теме статьи — статья как будто хочет сказать, что после знакомства с Java — в .NET все оказывается не так плохо.
Но что по поводу проектов на рынке?
На .NET по-прежнему их меньше чуть ли не в разы, и в основном легаси.
Кое-что появляется на .NET Core, но именно что «появляется», и с качеством кодинга и архитектурой в проектах проблемы (унаследованные подходы или криво применяемые новые).
Т.е., несмотря на тенденции последних лет — развитие C# (6.0-7.x + C# 8 в черновике), взросление F#, появление .NET Core, модульности, новой экосистемы, до сих пор сохраняется неясность по поводу настоящего и будущего платформы.
И еще кое-что.
Изначально .NET затачивался под декстоп и UI, потом плавно перешел на back-end, а с появлением .NET Core стал практически полностью полноценной зрелой back-end платформой.
Но из-за соображений обратной совместимости функции работы со строками (преобразование чисел и дат в строку и обратно и большинство других методов со строками) в большинстве своем работают в текущей культуре, а не в инвариантной или Ordinal-режиме.
В итоге получается, что в бек-енд приложении работа по записи/парсингу какого-нибудь XML, передеваемого между частями системы, превращается в сущий ад, ибо разработчики не заботятся о явном указании культуры, и все сводится, чтобы на всех серверах стояла в системе (т.е. внешней Environment) одинаковая культура (чем это плохо, и что происходит по ходу дела, думаю, не нужно объяснять).
XSD-схемы, платформенно-независимый формат XML? — не, не слышали.
И вот из-за одной даже такой мелочи (работа со строками) — вот как это применять на back-end?
В Java функции работы со строками работают так, что типы данных представляются в том формате, в котором значения типов записываются в коде самого Java-приложения, т.е., в инвариантном.
А для UI-представления нужно использовать класс Formatter.
Авторам Go все эти годы приходится иметь иметь дело с обиженными экспертами, которым не хватает в языке дженериков, концептов и прочей мути.
Дженериков действительно не хватает (если их в консервативную джаву добавили...), и вроде обсуждается, чтобы добавить их в Go
А вот с остальным вопросы — наверное, действительно не нужно, т.к. идеи и реализации спорные, и будут противоречить основной идее Go как "простого" языка.
Как же просто всё в Java: ClassName, varName, methodName, CONST_NAME
CONST_NAME пришло в Java качестве одного из стилей C.
На мой взгляд, для Java это смотрится достаточно чужеродно, хотя хорошо уже то, что это стандарт.
Больше импонирует C#-подход, когда константы выносятся в отдельный статический класс и именуются в PascalCase:
Path.DirectorySeparatorChar
Path.AltDirectorySeparatorChar
Хотя иногда, как в случае того же Path, констатанты могут смешиваться с методами в одном классе.
Хуже, когда в C# пытаются переносить Java-стандарт объявления констант (встречал в паре проектов): для C# это совсем чужеродно и размывает уже имеющиеся в языке стандарты.
Основное отличие в том, что байт-коды виртуальной машины это ограниченный набор высокоуровневых кодов (.NET IL, Java byte code), которые почти 1-в-1 соответствуют высокоуровнему языку (C#, Java).
Например, есть в .NET фильтры исключений на уровне IL.
Когда мы на C# пишем так (when):
Понятно, что в современных процессоров таких "байт-кодов" нет, и современные JIT переводят эти байт-коды низкоуровневые процессорные системы команд.
И идея была в том, чтобы система команд процессора была именно такой высокоуровневой, а остальное (что сейчас делает программный JIT) — под аппаратным капотом.
Сейчас, когда нажимаешь на кнопку хаброката, строчки, которые были выше кнопки, сразу все уходят за пределы экрана, и теряется контекст.
Хотелось бы, чтобы хабракат работал по примеру PageDown в барузерах, когда пара-тройка строчек предыдущей страницы после нажатия кнопки остается видной вверху и не теряется контекст.
Возможно, «старые» строчки при это стоит сделать чуть более светлым/серым шрифтом или замылить.
И наконец-то, допилите мобильное приложение, чтобы им можно было полноценно пользоваться, как десктопным сайтом.
Сейчас, например, в своем же профиле не видно своих же комментариев.
> Сила XML в неймспейсах (namespace) — но их мало кто понимает
В теории.
На практике, когда они используются, их не обрабатывают нормально, а делают всякие костыльные решения, вроде удаления неймспейсов перед чтением, или читая, игнорируя неймспейсы.
Так же, как никто не обрабатывает нормально XML схему перед чтением.
Суть в том, что XML это сложное решение, которое требует промышленного подхода в работе, и в эпоху скрама и аджайла с ним точно никто не будет работать нормально, к сожалению.
Сделать поддержку какого-нибудь сложного XML-based формата или конфига за пару дней никто ж е даст — это ж чуть ли не Epic Story, за которую нужно делать продуктовые таски.
Верно, в вакансиях открытого рынка в Западной Европе и США именно такие суммы.
В Восточной Европе, если поисследуете, увидите вакансии максимум по 2500 ± евро, из которых нужно вычесть налог.
И если в исходном сообщении имелось в виду, что столичные ЗП приближаются (только приближаются) к этому уровню, то как то меркнет исходный посыл, что это "много", особенно если учесть, что, опять же, на открытом рынке, в столицах квартиры стоят в 3 раза больше, чем с ИТ-миллионниках, а ЗП в 2 разы выше.
Уровень зарплат в столицах вполне на европейском уровне. Если налоги учесть.
Каков порядок сумм (по вашим данным)?
И что вы понимаете под под европейским уровнем?
Зарплаты в вакансиях на открытом рынке в Западной и Восточной Европе отличаются в примерно 2 раза.
Т.е., прежде, чем говорить о "в разы больше в США", давайте определимся, о каком именно европейском уровне зарплат вы говорите (забегая вперед — на открытом рынке, в свою очередь, тоже примерно в 2 раза больше, чем в Западной Европе, что слабо тянет на "в разы").
> Не знаю насчет Иннополиса, но в столицах вполне себе зарплаты по европейским меркам.
По вашим данным, какой именно уровень зп в столицах, и приближается ли он к европейскому уровню именно в ИТ (разработке софта, точнее)?
И что вы имеете в виду под европейским уровнем — Западную или Восточную Европу (из открытых данных, разница в разработке примерно в 2 раза)?
Если судить только по открытым данным (вакансии на HH), то зп в столицах примерно 2 в раза выше, чем в городах миллионниках с развитым ИТ, а стоимость квартир в 3 раза выше (ну это если ставить цель осесть в столицах).
Может быть, на закрытом рынке ситуация другая (вопрос про столицы)?
Проблема буков, что они имеют специфическое железо и кучу предустановленного софта.
Если же вы накатите чистую виндоус, она все равно будет пытаться скачать что-то специфическое их репозитория драйверов.
На компах, собранных самосбором из типовых комплектующих, проблем при обновлениях нет.
И еще есть смысл апгрейдиться до Pro-версии (на буках обычно Home), там с обновлениями и их обязательносттю полегче.
В современном ИТ, когда предлагаешь заточить пилу и многократно ускориться/повысить качество, такой ответ и получаешь: некогда точить пилу, нужно пилить (иногда буквально этими словами).
Впрочем, возможно, это на взгляд исполнителя. Все зависит от постановки задачи. Что если целью является именно тот процесс, который и происходит (или именно он приводит к целевым результатам)?
Но и критика ваша понятна.
Ограничением F# является то, что это язык, заточенный под инфраструктуру .NET — т.е., на нем писать можно/есть смысл, если по каким-то причинам вы пишите именно под .NET и хотите функциональщины и прочих улучшений в языке и практике работы с платформой.
Это примерно (но только примерно) как то, когда спрашивают "ну а какие такие плюсы у Kotlin по сравнению с Java? Все это можно же и на Java написать."
Также, как 15 лет назад спрашивали "зачем C#, если есть Delphi и/или C++"
В том то и дело, что помимо функциональной парадигмы, на которой в F# писать легко (в C# нужно постараться), это еще и куча всего, что облегчает жизнь — можно просто взять и писать под .NET на F#.
При этом есть возможности при необходимости писать на F# более низкоуровнево, как мы это делали бы на C#.
Предлагать компаниям уже в процессе работы над проектом попробовать F#?
— Какое там, если в большинстве случаев нерешаемой «проблемой» является обновление CI для поддержки C# 7 вместо 5 (Карл, 2012-й год!). Какой тут F# (который до недавнего времени еще и свой отдельный рантайм имел).
После знакомства с F# действительно начинаешь мыслить и писать на C# по другому.
Впрочем, в своем случае «по-другому» я начал еще до изучения F#, самостоятельно доходя до ФП-парадигмы (и речь не только о «лямбдах как стратегиях») — пытаясь действительно эффективно решать задачи и нивелировать недостатки существующих подходов, и уже затем актуализировав выработанные подходы до общепринятой функциональной парадигмы.
Долго объяснять — от множества технических, интерфейсных и концептуальных моментов до общего вписывания в современную мобильную облачную архитектуру и вообще в современный дискурс.
Тут столько всего, что речь можно вести о переходе количества в качество.
Аналогия из мира программирования:
Что было не так в Delphi 20 лет назад, если на первый план вышли C# и Java?
Ведь в первых версиях C# и Java было практически все то же самое, что и в Delphi, кроме завезенного Garbage Collector (ага, а вот и началось — GC, то-се, дальше — больше).
И вроде бы сейчас Delphi догнал по возможностям своих конкурентов, но..
Вот то же самое и с QIP.
В .NET тоже есть определенный бардак в базовом API — в тех же коллекциях и датах.
Насчет коллекций — мое любимое:
А вот почему практически во всех проектах разработчики используют в открытых контрактах своих API либо List(T) (ай-ай, реализация, а не интерфейс, и при этом наиболее "полная" реализация — а как же SOLID?) либо IEnumerable(T) (ай-ай, сколько раз приходилось видеть вызов метода Count())?
Хотя в большинстве случаев по смыслу подходит использование IReadOnlyList(T) или IReadOnlyCollection(T) (список с конечным количеством элементов — упорядоченный по индексу, либо нет).
Если разобраться, то на это разработчиков провоцирует устройство базовых типов самой платформы:
Тип List(T) реализует интерфейсы IList(T) и IReadOnlyList(T).
Но что будет, если одна функция возвратила экземпляр IList(T), который мы хотим передать в функцию, которая на входе требует IReadOnlyList(T) или IReadOnlyCollection(T)?
Правильно — ошибка компиляции, т.к. интерфейс IList(T) не реализует интерфейс IReadOnlyList(T).
Вот и получается, что, чтобы работало, везде лепят List(T).
А вот если вторая функция на входе требует IEnumerable(T), то подойдет любая коллекция, в т.к. IList(T).
Кроме того, использование IEnumerable(T) провоцируется стандартной библиотекой платформы, хотя в большинстве случаев по смыслу речь идет о коллекции с конечным и известных количеством элементов (а что, если в будущем коду самой функции потребуется проверка коллекции на количество элементов? — а ведь замена типа параметра на IReadOnlyCollection(T) приведет к поломке компиляции всего написанного с ипользованием этой функции кода).
Та же проблема касается и словарей — Dictionary(K,V), IDictionary(K,V), IReadOnlyDictionary(K,V).
Получается, при казалось бы, такой сильной реализации Interface Segregation Principle в системе базовых коллекций, из-за такой мелочи по факту этот принцип не используется в прикладном коде.
И еще определенную путаницу вносит наличие ReadOnly- и Immutable-версий коллекций (да, мы знаем, чем они отличаются).
Последние так и не начали использоваться в проектах (у кого-то есть реальные примеры?), а еще перечень Immutable-коллекций не полностью соответствует 1-в-1 набору обычных (что-то добавлено, что-то отсутствует).
Но взросление неизбежно.
По теме статьи — статья как будто хочет сказать, что после знакомства с Java — в .NET все оказывается не так плохо.
Но что по поводу проектов на рынке?
На .NET по-прежнему их меньше чуть ли не в разы, и в основном легаси.
Кое-что появляется на .NET Core, но именно что «появляется», и с качеством кодинга и архитектурой в проектах проблемы (унаследованные подходы или криво применяемые новые).
Т.е., несмотря на тенденции последних лет — развитие C# (6.0-7.x + C# 8 в черновике), взросление F#, появление .NET Core, модульности, новой экосистемы, до сих пор сохраняется неясность по поводу настоящего и будущего платформы.
И еще кое-что.
Изначально .NET затачивался под декстоп и UI, потом плавно перешел на back-end, а с появлением .NET Core стал практически полностью полноценной зрелой back-end платформой.
Но из-за соображений обратной совместимости функции работы со строками (преобразование чисел и дат в строку и обратно и большинство других методов со строками) в большинстве своем работают в текущей культуре, а не в инвариантной или Ordinal-режиме.
В итоге получается, что в бек-енд приложении работа по записи/парсингу какого-нибудь XML, передеваемого между частями системы, превращается в сущий ад, ибо разработчики не заботятся о явном указании культуры, и все сводится, чтобы на всех серверах стояла в системе (т.е. внешней Environment) одинаковая культура (чем это плохо, и что происходит по ходу дела, думаю, не нужно объяснять).
XSD-схемы, платформенно-независимый формат XML? — не, не слышали.
И вот из-за одной даже такой мелочи (работа со строками) — вот как это применять на back-end?
В Java функции работы со строками работают так, что типы данных представляются в том формате, в котором значения типов записываются в коде самого Java-приложения, т.е., в инвариантном.
А для UI-представления нужно использовать класс Formatter.
Дженериков действительно не хватает (если их в консервативную джаву добавили...), и вроде обсуждается, чтобы добавить их в Go
А вот с остальным вопросы — наверное, действительно не нужно, т.к. идеи и реализации спорные, и будут противоречить основной идее Go как "простого" языка.
CONST_NAME пришло в Java качестве одного из стилей C.
На мой взгляд, для Java это смотрится достаточно чужеродно, хотя хорошо уже то, что это стандарт.
Больше импонирует C#-подход, когда константы выносятся в отдельный статический класс и именуются в PascalCase:
Path.DirectorySeparatorChar
Path.AltDirectorySeparatorChar
Хотя иногда, как в случае того же Path, констатанты могут смешиваться с методами в одном классе.
Хуже, когда в C# пытаются переносить Java-стандарт объявления констант (встречал в паре проектов): для C# это совсем чужеродно и размывает уже имеющиеся в языке стандарты.
Основное отличие в том, что байт-коды виртуальной машины это ограниченный набор высокоуровневых кодов (.NET IL, Java byte code), которые почти 1-в-1 соответствуют высокоуровнему языку (C#, Java).
Например, есть в .NET фильтры исключений на уровне IL.
Когда мы на C# пишем так (when):
Понятно, что в современных процессоров таких "байт-кодов" нет, и современные JIT переводят эти байт-коды низкоуровневые процессорные системы команд.
И идея была в том, чтобы система команд процессора была именно такой высокоуровневой, а остальное (что сейчас делает программный JIT) — под аппаратным капотом.
Хотелось бы, чтобы хабракат работал по примеру PageDown в барузерах, когда пара-тройка строчек предыдущей страницы после нажатия кнопки остается видной вверху и не теряется контекст.
Возможно, «старые» строчки при это стоит сделать чуть более светлым/серым шрифтом или замылить.
И наконец-то, допилите мобильное приложение, чтобы им можно было полноценно пользоваться, как десктопным сайтом.
Сейчас, например, в своем же профиле не видно своих же комментариев.
В теории.
На практике, когда они используются, их не обрабатывают нормально, а делают всякие костыльные решения, вроде удаления неймспейсов перед чтением, или читая, игнорируя неймспейсы.
Так же, как никто не обрабатывает нормально XML схему перед чтением.
Суть в том, что XML это сложное решение, которое требует промышленного подхода в работе, и в эпоху скрама и аджайла с ним точно никто не будет работать нормально, к сожалению.
Сделать поддержку какого-нибудь сложного XML-based формата или конфига за пару дней никто ж е даст — это ж чуть ли не Epic Story, за которую нужно делать продуктовые таски.
Верно, в вакансиях открытого рынка в Западной Европе и США именно такие суммы.
В Восточной Европе, если поисследуете, увидите вакансии максимум по 2500 ± евро, из которых нужно вычесть налог.
И если в исходном сообщении имелось в виду, что столичные ЗП приближаются (только приближаются) к этому уровню, то как то меркнет исходный посыл, что это "много", особенно если учесть, что, опять же, на открытом рынке, в столицах квартиры стоят в 3 раза больше, чем с ИТ-миллионниках, а ЗП в 2 разы выше.
Каков порядок сумм (по вашим данным)?
И что вы понимаете под под европейским уровнем?
Зарплаты в вакансиях на открытом рынке в Западной и Восточной Европе отличаются в примерно 2 раза.
Т.е., прежде, чем говорить о "в разы больше в США", давайте определимся, о каком именно европейском уровне зарплат вы говорите (забегая вперед — на открытом рынке, в свою очередь, тоже примерно в 2 раза больше, чем в Западной Европе, что слабо тянет на "в разы").
А вот внезапно, Java в последнее время живее всех живых, и не только за счет Андроида.
Много бек-енда с блек джеком.
Просто какое-то второе рождение — то, что прочили .NET Core, происходит с Java (ну тут понятно — Java 8+, Kotlin, Scala, всякие облачные фреймворки).
По вашим данным, какой именно уровень зп в столицах, и приближается ли он к европейскому уровню именно в ИТ (разработке софта, точнее)?
И что вы имеете в виду под европейским уровнем — Западную или Восточную Европу (из открытых данных, разница в разработке примерно в 2 раза)?
Если судить только по открытым данным (вакансии на HH), то зп в столицах примерно 2 в раза выше, чем в городах миллионниках с развитым ИТ, а стоимость квартир в 3 раза выше (ну это если ставить цель осесть в столицах).
Может быть, на закрытом рынке ситуация другая (вопрос про столицы)?
Проблема буков, что они имеют специфическое железо и кучу предустановленного софта.
Если же вы накатите чистую виндоус, она все равно будет пытаться скачать что-то специфическое их репозитория драйверов.
На компах, собранных самосбором из типовых комплектующих, проблем при обновлениях нет.
И еще есть смысл апгрейдиться до Pro-версии (на буках обычно Home), там с обновлениями и их обязательносттю полегче.
Впрочем, возможно, это на взгляд исполнителя. Все зависит от постановки задачи. Что если целью является именно тот процесс, который и происходит (или именно он приводит к целевым результатам)?
Есть третий:
Сделать обновление прозрачными без перезагрузки, с горячей заменой обновленных библиотек так, как будто система уже перезагрузилась.
Помнится, такое хотели сделать еще во времена Windows Server 2003...