Как стать автором
Обновить
29
0
Артём Владимирович Горчаков @worldbeater

Кроссплатформенное ПО, анализ данных

Отправить сообщение

Типичная тема в рашке.

Этот новояз обязательно было добавлять? Как-то не очень конструктивно Хабр превращать в TJournal.

не могу понять, как вы пришли к тому заключению, откуда вы к примеру знаете что данный человек именно вам поставил минус, видя только counter?

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

Наличие счётчика же не ограничивает анонимность при голосовании, а просто является характеристикой профиля проголосовавшего? На Хабре, кажется, есть счётчики, которые считают минусы и плюсы и отключают голосование, если их становится слишком много, но такие счётчики скрыты. Ваша идея с их показом в списке проголосовавших звучит неплохо!

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

Чтобы потом можно было переходить в профиль этого человека и ставить минусы всем его комментариям подряд, или тем, с которыми Вы идеологически не согласны? Подобная система работает на ресурсах наподобие VC/TJ, и вот такие рейды минусов на почве несогласия с точкой зрения собеседника или обиды на минус там сплошь и рядом, никакого плюрализма мнений там нет. Имеет смысл рассмотреть ещё варианты.

это только switch, который раздувает код

Есть же ещё конструкции наподобие TaskBuilder и MaybeBuilder, которые позволяют делать optional и task chaining, но через переменные — как раз чтобы не обкладывать всё конструкциями match:


let onHello context =
  maybe {
    let! message = context.Update.Message
    let! name = message.Chat.FirstName
    sprintf "Hello, %s!" name
    |> sendMessage message.Chat.Id
  } |> ignore

Здесь, context.Update.Message — это Option<Message>. Аналогично с FirstName. В случае maybe после let! произойдён early return, если в option лежит None.

Может быть, будет уместным отметить, что для решения описанной задачи генерации IObservable из событий есть инструмент Pharmacist, который работает через ICSharpCode.Decompiler, и его версия в виде ObservableEventsSourceGenerator, которую всё никак не опубликуем.

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

Вообще с командами в ReactiveUI работать несколько более удобно, чем с объектами типа Interaction. Привязывать команду модели представления к элементу интерфейса можно как в XAML-разметке — с помощью синтаксиса {Binding CommandName}, — так и в коде на языках программирования C#, F#, или Visual Basic, с помощью extension-методов ReactiveUI, включая методы Bind, BindCommand, OneWayBind, BindTo. То есть можно делать так:


<Button x:Name="AwesomeButton"
        Content="Hello, world!"
        Command="{Binding AwesomeCommand}" />

Или так:


this.BindCommand(
    ViewModel,
    vm => vm.AwesomeCommand,
    view => view.AwesomeButton);

Последний вариант хорош тем, что при переименовании свойства модели представления, к которой мы привязываем данные, мы узнаем о том, что что-то пошло не так, уже на этапе компиляции приложения. Причём для WPF, Windows Forms и Xamarin Forms это более актуально, чем для UWP или Avalonia, которые поддерживают compiled-биндинги. А на Xamarin.Android или Xamarin.iOS других вариантов в общем-то и нет. Дополнительно, можно подписываться на исключения, выброшенные экземплярами ReactiveCommand, двумя способами — можно подписаться на исключения одной команды:


LoadUsers.ThrownExceptions.Subscribe(
    exception => /* update property etc. */
);

Или на исключения всех команд и OAPH в приложении сразу:


RxApp.DefaultExceptionHandler = Observer.Create(
    error => /* Handle errors. */
);

Такой подход, с одной стороны, позволяет сделать приложение более отказоустойчивым и научить его отправлять отчёты об ошибках куда-нибудь для дальнейшего анализа, а с другой — позволяет не писать try { } catch { } блоки повсеместно в лямбдах, предлагая вместо этого написать реактивный пайплайн наподобие:


_errorMessage = Login // ReactiveCommand<TInput, TOutput>
    .ThrownExceptions // Все исключения свалятся сюда.
    .Select(exception => exception.Message)
    .ToProperty(this, x => x.ErrorMessage);

Впрочем, впоследних версиях ReactiveUI должен быть доступен синтаксис BindInteraction, позволяющий привязывать Interaction к действиям более удобным образом:


// В файле *.xaml.cs:
this.BindInteraction(
    ViewModel,
    vm => vm.MyInteraction,
    context => /* Обработчик взаимодействия. */);

Очень любопытно — у вас всё-таки получилось ознакомиться с научными исследованиями, опубликованными в peer-reviewed журналах, на которые ссылается ваш оппонент в последнем сообщении — можете как-то прокомментировать?


Ну то есть я понимаю, что обращать внимание на негативные стороны порноиндустрии сейчас немодно, но игнорировать неудобные результаты вполне приличных научных исследований, опубликованных в рецензируемых журналах, которые приводит ваш оппонент [1, 2, 3], как-то всё-таки ненаучно.


В треде же, кажется, хотели выяснить истину, а не отстоять свою точку зрения, да и что-то запрещать вроде бы никто не призывал. Заранее спасибо.

Для добавления атрибута с помощью генератора есть две причины. С одной стороны, мы должны ссылаться на генератор по-особенному, как на анализатор — если бы мы решили атрибут не генерировать, нам бы пришлось собирать два пакета — один был бы собственно генератором, а другой — содержал бы атрибут. Такой паттерн использовался, например, в библиотеке Pharmacist ещё до появления .NET 5 source generators. С другой стороны, сами генераторы исходного кода довольно тесно заинтегрированы в .NET CLI, Visual Studio, JetBrains Rider, в результате генерация происходит при любом изменении исходного файла. Выглядит это следующим образом:



Добавлю эту гифку в статью для контекста, спасибо за вопрос!

Вот, кстати, очень любопытно. Допустим, тернистый путь пройден — вы поступили, выучились, университет закончен, колоссальный объём знаний, позволяющий решать огромное количество сложных задач за вменяемое время, получен, престижный диплом — тоже. А что делать дальше? Ну, то есть, вы после окончания университета собираетесь в какую-то конкретную организацию идти работать по специальности? Наверняка уже есть планы — было бы интересно почитать. Apple, Microsoft, Google, или что-то более интересное и наукоёмкое в зарубежных НИИ?

Да, дебажили тестами. Генератор является вообще говоря обычной библиотекой с таргетом на .NET Standard 2.0, если на него сослаться классическим способом, а не как на анализатор (ProjectReference без OutputItemType="Analyzer").


Поэтому весь интересный код можно вынести в internal-объекты, расставить InternalsVisibleTo для проектов с тестами, и обложить эти объекты с интересным кодом тестами, чтоб в нетестируемом коде было нечему ломаться. Потом уже в JetBrains Rider гулять по коду с дебаггером, разбираясь, что и где пошло не так. Тесты, кстати, сейчас лежат тут: https://github.com/AvaloniaUI/Avalonia.NameGenerator/tree/main/src/Avalonia.NameGenerator.Tests (вообще стараюсь избегать ссылок на этот репозиторий в материале, потому что он скоро уедет в главный репозиторий Avalonia)


А, ещё можно делать context.ReportDiagnostic.

На самом деле всё не совсем так, как вы пишете. Да, действительно, с выходом .NET MAUI Xamarin.Forms отправится на свалку, потому что .NET MAUI и есть, по сути своей, эволюция Xamarin.Forms с новыми API. При этом, в Microsoft собираются сделать API .NET MAUI совместимым с API Xamarin.Forms. Подробнее о планах команды можно посмотреть в видео с виртуальной конференции ReactiveUI под названием Dualscreen, .NET MAUI and ReactiveUI. Там разработчик нового MAUI и старого Xamarin.Forms делится инсайдами о новом API.


Далее, на странице репозитория dotnet/maui мы видим сводку о поддерживаемых платформах, согласно которой Linux всё так же остаётся community-maintained. Это значит, что, ну, Microsoft Linux поддерживать не будет, а Avalonia уже поддерживает. Не исключено, что может появиться бакенд MAUI, основанный на Avalonia, с помощью которого можно будет обеспечить поддержку Linux — будем посмотреть.


Далее, ниши у Xamarin.Forms (или MAUI) и AvaloniaUI (или WPF) принципиально разные. Про производительность Avalonia в сравнении с WPF можно посмотреть в Core2D rendering performance WPF vs Avalonia+Direct2D,SkiaSharp,Cairo vs WPF+SkiaSharp. На Avalonia уже пишут сложные кроссплатформенные редакторы наподобие таких:


image


Было бы любопытно посмотреть на что-то подобное, написанное на Xamarin.Forms и работающее на десктопах. Потому что есть мнение, что основной нишей Xamarin.Forms (и MAUI) останутся приложения попроще, больше ориентированные на мобильный сегмент, а не на высокопроизводительный десктоп.


А Uno пока, как говорят, needs more love. Но я слабо знаком с этим фреймворком — про производительность или сегмент, который оно покрывает, ничего не могу сказать. Надо пробовать.


image

А мне вот очень понравился калькулятор с тёмно-розовыми кнопками. Справедливости ради стоит заметить, что в Avalonia 0.10.0, который уже вот-вот зарелизят, сделали тему, основанную на Microsoft Fluent Design. А ещё есть набор стилей Citrus.Avalonia. С релизом 0.10 будет сложнее угадать эту технологию по UI!


Что-то наподобие интерфейса ICommand и команд в WPF, только интеракции в нашем случае назначались на интерфейсные элементы не декларативно (как с командами в WPF), а программно, что показалось не очень удобным.

Было бы интересно узнать, а почему решили не использовать для подобных штук реактивные команды? ReactiveCommand<TInput, TOutput> — это же реализация ICommand на стероидах, с ThrownExceptions, IsExecuting, etc. Interactions же были задуманы, как один из способов реализации взаимодействий с модальными окнами, и на практике использовать эти штуки обычно доводится нечасто.

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


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

Почему люди не используют формальные методы? Хабр, 2019.


А в F# изобрели type providers. Которые, тем не менее, в продакшене пока встречаются нечасто.


Incidentally, further on in the SO post, someone makes a comment about setting AutoDetectChangesEnabled and LazyLoadingEnabled to false. This has no effect on the performance (or lack thereof, at least in EF Core.)

AsNoTracking в EFCore выключит отслеживание изменений, но на производительность не повлияет, судя по замерам и выводам из статьи Choose Your Poison on the rPi: Entity Framework, Linq2DB, or ADO.NET. Причём в секции Querying Large Sets of Data есть ещё более интересные графики. Любопытно, как там linq2db умудряется работать быстрее, чем ADO.NET. Скорее всего, linq2db делает хитрые оптимизации, а код автора — нет.


Получилось достаточно кратко. Не будет лишним упомянуть, хотя бы в комментариях, ORM для .NET и .NET Core без change tracking, которая отличается лучшей производительностью — linq2db. В связке с чем-нибудь наподобие FluentMigrator в некоторых случаях может заменить EntityFramework. Ещё есть Dapper, но это инструмент более низкоуровневой категории.

Оказывается, в некоторых нормативных базах действительно бывает закреплено и такое. Согласно FBI’s Uniform Crime Reporting (UCR) Program:


Forcible rape, as defined in the FBI’s Uniform Crime Reporting (UCR) Program, is the carnal knowledge of a female forcibly and against her will. Attempts or assaults to commit rape by force or threat of force are also included; however, statutory rape (without force) and other sex offenses are excluded.

Цитировать Википедию в общем случае неприлично, но там сформулировали понятно:


In common law jurisdictions, statutory rape is nonforcible sexual activity in which one of the individuals is below the age of consent.
Ну, просто страшный вред для здоровья, не правда ли? К сожалению, опять не первоисточник, но вы можете его найти…

Может быть, согласно исследованию цитируемых вами авторов вред не настолько страшный, но всё же ведь вред, судя по приведённой цитате. А приведённая цитата (дублирую ниже) очень напоминает алкогольную зависимость, зависимость от курения и наркотиков — там тоже человеку нужна всё большая и большая доза, при этом человек испытывает удовольствие. Конечно, употреблять или не употреблять — каждый решает сам. Но не всякое удовольствие может иметь благоприятные последствия.


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

Думаю, о таких вещах знать очень важно — ведь не все насильники, и для большинства сверхпотребление может вызвать зависимость, что в общем случае — не очень хорошо. Цитируемый вами anews почему-то не предоставляет ссылку на оригинальное исследование, которое обсуждается в статье, поэтому есть риск, что материал очень opinionated. Впрочем, это уже буквоедство, будем надеяться, что авторы не опустили ничего важного, а смысл мы уловили.


До 1972 г. любые открыто-сексуальные материалы были в Японии строго запрещены. Количество изнасилований с 1972 по 1995 г. снизилось втрое. Особенно сильно уменьшилось число групповых изнасилований и изнасилований, совершенных подростками. В 1972 г. подростки совершили 33 % всех изнасилований, а в 1995 – только 18%.

Благодарю за ссылки на материалы про возможную корреляцию изнасилований и легализации материалов для взрослых. Наверное, здесь действительно может быть связь. Хотя нельзя исключать влияние иных факторов на снижение количества преступлений — например, в 1991-ом году интернет стал публично доступным, предлагая новые способы досуга.


On 6 August 1991, exactly twenty years ago, the World Wide Web became publicly available.

Согласно статистике из США, число изнасилований там начало снижаться как раз после 1991-ого года. Но, возможно, на это могло повлиять и что-то ещё.


image


Я, например, не пытаюсь скрывать свои взгляды.

А какие у вас взгляды? Вот я считаю, что если от чего-то может быть вред — значит надо об этом знать. Предупреждён — значит вооружён. Как распоряжаться этим знанием — это выбор каждого, как в случае с курением, алкоголем или иными штуками. Возможно, это некорректное сравнение, потому что от курения и алкоголя вред серьёзнее. На всякий случай напомню, что криминализовывать порнографию я не призываю.

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

Конечно, но это негодная аналогия, полагаю. Потому что в сообщении выше посыл был в том, что мы не можем бороться с похожими инцидентами без участия и усиленного контроля со стороны компаний наподобие PornHub. Возможно, следует разработать какие-нибудь интеллектуальные алгоритмы, которые бы более оперативно вычищали вредоносный контент того типа, про который рассказывает автор на пикрилейтед предыдущего поста — почему нет? Но если всем будет всё равно, то сами компании вряд ли займутся такими тонкостями, потому что не будет общественного запроса, потому что лишнее видео с монетизацией не помешает. В довесок, нормативная база всё-таки должна отвечать интересам общества, в котором она функционирует — не вижу в выражении интереса ничего дурного! Может быть, этот комментарий тоже можно счесть демагогией, конечно. Пинайте, если это так.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность