Comments 718
Но ещё больше бесит, когда продукты, которые по своей сути должны являться mobile first не имеют нормального приложения на телефоне, а только планируют его сделать, особенно когда этот продукт для менеджера «в полях».
Меня одного бесит промотка статьи при открытии? Скачет все хрен знает как и куда. Зачем? На крайняк добавьте настройку, «проматывать при открытии». Уверен, 99% отключат шнягу эту. А то грузится статья с каментами, уже половину прочел, вдруг скачок вверх. Бред какой-то.
В то время, как почти везде перейти в начало страницы до этих же кнопок — одно/два нажатия.
А чего стоит вдоль и поперек перепиленная джаваскриптом textarea для набора комментария… Даже на моем i7 буквы при наборе комментария появляются с заметным отставанием при небольшой скорости набора. А если набирать быстро, то часть букв пропадет, а другая часть встанет не на свое место.Вот этот текст я был вынужден редактировать несколько раз из-за пропадания и перемешивания букв.
А на айпаде набрать ответ вообще невозможно из-за жутких тормозов в десятки секунд.
Но это же все неважно, правда, Boomburum ?
Чтобы тупил ввод конкретно на Хабре, такого не помню.
Единственно я не залогинен, мб это пропадает после логина?
1. открывать ссылки правой кнопкой мыши «открыть в новой вкладке»
2. надоедливое окно с регистрацией, которое закрывает весь экран можно парой кликов убрать в firefox в режиме инспектора. Просто ткнуть в него и удалить из дерева. Дальше можно про него забыть.
Веб версией после реги вполне позволяет…
Как я понимаю — они просто закрыты блоком весь экран и на этом успокоились. Просто возможно там остаётся иногда поверх него ещё какой-то блок, который клики перекрывает. Но почему это работает через раз и почему работают кнопки непонятно. Времени сейчас посмотреть нет :(
Что, и пост можно сделать? Видео залить, например? Это же дико неудобно, коллега делаешь видео в Premiere, закидываешь на телефон и только с него постишь. И ещё и отложенную запись просто так сделать нельзя…
В общем, автор был прав — это приложение ориентировано на тех, кто делится селфи.
Просто он недооценил коммерческое количество таких людей, ине учёл, что профессиональная аудитория как раз сумеет подстроиться ко всему.
Точно так же люди массово пользуются WhatsApp вместо Telegram, хотя там нельзя даже сообщение отредактировать, и ещё десяток полезных функций отсутствует. Зато он понятнее.
Меня тоже реально бесит что работаешь за ноутбуком или ПК и для того, чтобы «полноценно» пользоваться каким-то приложением с него (да пускай тем же самым Инстаграммом) нужно на ПК поставить эмулятор Андроид.Вас бы меньше это бесило, если бы на компьютере был бы предустановлен эмулятор андроид, позволяющий прозрачно запускать любые приложения из гугл-плей скажем? То есть качнул и запустил — без доп. плясок с бубном, но технически это был бы «инстаграм в эмуляторе», а не нативное приложение.
Вопрос не риторический, ответ правда интересен, особенно если подробный.
Делаете продукт — делайте для него нормальную веб-версию, по тому что браузер можно открыть на любой кофеварке.
Я не буду от каждого сервиса приложение ставить чтобы посмотреть что у вас там.
Интересно значит когда вэб браузерами ломали user experience в нормальных приложениях вы были за это а как браузеры прошли на свалку так против? ;)
Когда-то были удобные приложение "толстые клиенты" в которых были нормальные сочетания клавиш, последовательность выбора объектов, подогнанные расположение элементов (чтобы нужная информация была рядом), удобное редактирование, отсутствие потерь информации из-за нажатия f5 (или просто протухания сессии ;) ). Но нет модой стал web anywhere :) а теперь просто следующий шаг.
И ладно когда это Инстаграм, который изначально для плиток с камерой и их владельцев, так нет сейчас у нас справочные ресурсы под телефон с кнопками в пол экрана и свёрнуты и по умолчанию комментариями :)
Когда-то были удобные приложение «толстые клиенты» в которых были нормальные сочетания клавиш
Я, кстати, потому из аппаратных гипервизоров держусь за xen — у него есть отдельный клиент. А esxi и прочие proxmox уже только в браузере.
Интересно значит когда вэб браузерами ломали user experience в нормальных приложениях вы были за это а как браузеры прошли на свалку так против? ;)Смотря о каких приложениях идет речь.
Тяжелые проф. приложения типа графических редакторов, IDE, офисных пакетов должны быть полноценными приложениями с полноценным интерфейсом — так было и так есть.
А вот всякая информационная мелочевка с парой кнопок интерфейса прекрасно работает в браузере и не требует отдельного софта. Помнится в начале 2000-х у меня была куча всяких информационных приложений: карта города, справочник лекарств, и т.п. — сейчас все подобное доступно в Веб.
Я не буду от каждого сервиса приложение ставить чтобы посмотреть что у вас там.Спасибо. Неожиданный ответ.
Нам как старым десктопщикам привычнее как раз когда на десктопе можно поставить отдельную прогу для отдельной задачи. К онлайн мсоффису не привыкли до сих пор — пользуемся десктопным, долгое время на форумах предпочитали сидеть через оффлайн клиент — сейчас они просто вымерли все, до сих пор оффлайновым десктопным почтовым клиентом пользуемся и так далее.
а есть задачи которые надо сделать разово и забыть о них, вот тут веб однозначно в плюсе.
Время от времени попадаются ноуты (в основном — девичьи), на которых открыто неподдающееся никакому учету количество окон (не вкладок :) примерно трех разных браузеров (или всех, что есть на компе) — это как раз и есть «сделать разово» — но не забыть :)
Самое интересное — владельцы ноутов как-то ориентируются в этом лабиринте и ухитряются находить нужное.
Но вот установка обновлений с последующей перезагрузкой — для них настоящая боль :)
(ноуты никогда не выключаются, владельцы этой кнопкой не пользуются: открыл/закрыл и все дела :)
В нормальных десктопных программах используется концепция «открыл — поработал — сохранил и закрыл». В браузерах с этим есть определенные проблемы, что и приводит к описанным выше результатам.
Закладки людьми не используются, так как процесс создания закладки обычно сложнее процесса сохранения обычного документа.
Нажать на звездочку в адресной строке это сложнее нажатия иконки дискеты?
Да.
Пункт Папка: по дефолту — «Другие закладки»
Попытка сменить папку выводит на систему навигации по папкам, заметно отличающуюся от простой навигации по папкам файловой системы ОС.
В результате у обычного пользователя возникают проблемы, приводящие к тому, что либо пользователь не может найти сделанную им закладку, либо все закладки сваливаются в одну кучу в папку «Другие закладки».
А попытка создать иерархию (с перемещением закладок туда-сюда) становится делом нетривиальным и весьма утомительным.
Плюс далеко не все пользователи слышали о функции облачной синхронизации данных в браузере — и тем более — умеют ей пользоваться.
И плюс плюс — пользователи пользуются несколькими разными браузерами на одном компьютере одновременно.
В результате имеем умножение сущностей сверх необходимого, и любая программа типа OneNote становится намного удобнее системы закладок в браузерах.
Я один перетаскиваю вкладку на панель закладок, которая вся в заранее созданных папках?
Все с этого начинают :) Я — не исключение.
Но потом возникают ситуации, когда компьютеры меняются по несколько раз в день.
Компьютеры с разными браузерами.
Чужие компьютеры, на которых что-то устанавливать и настраивать в собственных интересах нельзя.
В такой ситуации синхронизация вкладок через облако браузера теряет всякий смысл.
Намного проще зайти в уже упомянутый OneNote через тот же браузер и получить доступ ко всей своей коллекции ссылок (которая может быть весьма обширной- 16 блокнотов по темам, по десятку-полтора разделов в каждом блокноте, по сотне страниц в каждом разделе, десятки ссылок на каждой странице :)
А обычные пользователи пасуют уже при виде альтернативы в лице трех вариантов (см картинку выше):
«Другие закладки»
«Панель закладок»
«Меню закладок»
И еще один пункт «Другие закладки» (уже внутри пункта «Другие закладки» :)
Все, такого количества близких по смыслу вариантов — уже вполне достаточно для хаоса в голове обычного пользователя
Сколько ни читаю про подобные случаи, ни разу не сталкивался.
Преподаватель проводит занятия в компьютерных классах.
Одна пара у него в корпусе А, вторая, на другом факультете — в корпусе Б. Затем он едет проводить занятия в колледже — корпус В. При этом, в зависимости от расписания, компьютерные классы даже в пределах одного корпуса меняются.
В такой ситуации даже флешку в эти компы вставлять нельзя, это как в борделе… нет, это хуже чем в борделе — там хоть проверяют состояние здоровья время от времени…
Про командировки-конференции и прочее и речи нет.
Я бы не стал на таких ПК входить в какой либо аккаунт.
Я тоже предпочитаю использовать Continuum (не помню, в какой именно теме я вчера давал описание его использования, может быть и в этой)
Но не всегда есть время на подключение/отключение.
Поэтому используется специальная учетная запись, заточенная сугубо под конкретные задачи.
Если вы, например, закрыли, открыли (пока есть активный пункт восстановить сессию), снова закрыли (случайно) — оно не появится, сессия потеряна. В Firefox по крайней мере именно так.
Один раз так ошибившись можно напугаться настолько, что потом отказываться закрывать под любым предлогом.
У меня вот ни разу проблем с этой кнопкой не былоОшибка выжившего )
Не понимаю вообще, зачем эту страницу выводить. Просто нужно восстанавливать предыдущие вкладки по дефолтуВот лично я не люблю восстанавливать предыдущую сессию, потому что стараюсь держать открытыми только нужные именно сейчас вкладки.
Почта — тут уже кому как. В своё время, когда почта шла большим потоком, был большим поклонником the bat с его системой фильтров. Сейчас же количество почты резко уменьшилось, потому вполне хватает и веб-интерфейса с нормальным поиском.
А почта — у Gmail/GSuite не такая уж плохая система фильтров… настраиваемая через веб-клиент а не мобильные приложения. У всяких Zimbra оно тоже есть.
Тем более, что у меня есть оффлайновые приложения — так что облачным офисом вообще смысла пользоваться нет в повседневной жизни. Очень изредка с чужого компьютера запускается.
Я только это увидел — сразу закрыл и вернулся к google docs, хотя он меня и не полностью устраивает.
Заполнить форму — не проблема, регистрация на гугле тоже не одно поле заполнить.
А заполнять длиннющую (по нынешним временам) форму, чтобы просто попробовать какой-то сервис — данафигэтоникуданеупёрлось!
Если вообще есть.
Но пароли помнятся в каком-то менеджере паролей в минте и дальше уже хром с этим сам разбирается.
Поэтому войти под гугл (вк или где там я ещё зареген) аккаунт ещё проще: даже пароль не надо помнить.
А тут предлагают заполнить какую-то форму, придумать логин, пароль ещё там что-то.
Плохо идеологи платформы подумали.
Я, вон, даже на али покупаю под… не помню… ВК-аккаунтом что-ли.
А то каждый интернет магазин на SPA, торгующий спиннерами будет требовать уникальную, именно для себя регистрацию — смешно даже…
можно войти под аккаунтом других распространённых веб-сервисов.
Почему-то у меня во всех случаях, когда я пытаюсь войти под аккаунтом фэйсбука или гугла, оттуда дёргают только почту, а остальные данные требуют ввести дополнительно.
И, на самом деле, я предпочитаю отдельный логин для каждого сайта держать. Потому что соцсеть обойдётся без дополнительной информации обо мне.
Просто. Заходите на двач и общаетесь, качаете картинки, видеоролики без смс и регистрации.
Если на свой сервер надо — есть ж community edition www.onlyoffice.com/ru/download.aspx (+гитхаб)
На стартовой странице уяснил, что штука платная, но есть триал на 180 дней.
ОК — ткнул «Попробовать в облаке» — увидел длинную форму — закрыл.
К вопросу о дезигнерах интерфейсов.
Это не дезингеры интерфейсов виноваты… это маркетологи хотят собрать с вас максимум инфы.
Босс придумал некую "анкету контагента" из 240 полей, включая чекбоксы. Потенциальный контрагент должен заполнить вот это всё только ради того, чтобы "попобовать" поработать с Газпромом в области ремонта спецтехники. Воевал-воевал с ним, да все бесполезно: бигдату босс хочет...
Так что вполне может статься, что вы еще не встечали по-настоящему длинных форм :)
Попытка отредактировать вордовый документ с track changes и комментариями вне MS Office разрушит этот документ с вероятностью 99%.
А это не такой оедкий кейс, и для аналитика, и для юриста.
Gmail и прочие: нормальных таблиц не вставишь, копипаст из Ворда не сделаешь.
Вот последний файл, который мне присылали для заполнения:
OnlyOffice: banshee.ms/public/screenshots/2020-07-30_072645.jpg — плющит, накладывая таблицы друг на друга.
ГуглОфис: banshee.ms/public/screenshots/2020-07-30_072925.jpg — наоборот, разносит на две страницы.
Office365 онлайновый: banshee.ms/public/screenshots/2020-07-30_073110.jpg — тоже разносит, как в гугле.
А вот так оно должно выглядеть: banshee.ms/public/screenshots/2020-07-30_073206.jpg (оффлайновый офис).
Лучшие результаты показывает оффлайновая либра — там только верхняя табличка чуть вправо уезжает, но это довольно легко исправляется.
Вот потому онлайновые офисные пакеты полноценного документооборота слабо подходят, если уж даже MS не может нормальную совместимость онлайн и оффлайн версий обеспечить.
это в первую очередь проблема конкретного документа сверстанного непонятно кем и непонятно как.
Нет, это не проблема документа. Это моя проблема. Ибо автор документа скажет «на моей стороне всё нормально», а прогибать большой МТС под маленького меня — без шансов.
Вот если вы сами большой, то маленьких окружающих можете прогибать хоть под либру, хоть под гуглодоки, хоть под лексикон досовский.
с юрлицами все зависит от наличия в штате хороших юристов, ну или одного хорошего юриста
Юристы первые, кто просит MS Office им купить, чтобы не возиться с форматированием. Плюс ещё они любят всякие истории редактирования и выноски ставить, а это между либрой и MSO ещё хуже переносится, чем таблички.
хуже всего, что весь этот зоопарк приложений оказывается просто обёрткой для взаимодействия через браузерные интерфейсы.
OK, закрываем сберприложение, следом открываем браузер на этом же телефоне, заходим в веб-интерфейс сбера и теперь платёжки можно подписывать на любые суммы! Але! Вы чего там в сбере накурились? :D
И это всё еще при том, что в сбер-приложение встроен анальный зонд имени кашпировского вирусы, типа, отлавливать, а браузеру доверяем слепо!
Насколько я помню, имея вашу симку и зная номер карты, можно просто установить приложение сбера и увести все ваши деньги.
Или вместе с ним отключится и смс информирование о состоянии счёта?
Но, кстати, да, пока пополняет и в ответ приходит «С 31.08 оплатить свой телефон через СМС-запрос можно будет, если подключена опция «СМС-платежи»».
Если отправить платёж на другой номер, то никакого ответа нет.
Если отправить USSD пополнение другого номера, то получаем ответ «Операция не выполнена. Для проведения ПЛАТЕЖА подключите опцию «СМС-платежи»».
Так что работает частично.Но через три дня заработает как надо.
Увы, гугаккаунт при заходе с другого IP начинает вымогать номер, и, если никакой номер не привязан, то принимает любой
У меня для этого есть специальная сим-карта, только для Гугла.
(и еще одна — для Микрософта :)
Хорошее, конечно, решение, но уж больно геморрное
Ничуть: двухсимочный смарт и мобильная точка доступа.
Точка доступа маленькая и легкая, плюс для меня необходимая.
(Плюс отдельная сменная карта для всех явных будущих спамеров :)
Ну, с двумя симками скрытие от гугла так себе.
Гугл всегда видит одну сим-карту.
При необходимости скрыть гугл о гугла используется третья сим карта, в мобильной точке доступа.
Первая же используется только для звонков.
Хотя у меня есть большие сомнения, что можно скрыть гугл от гугла в принципе — есть куча других факторов, кроме номера телефона.
С паролями у большинства пользователей творится полная лабуда.
Один пароль для всех ресурсов — это еще наименьшее из зол.
И конечно же учить пользователей паролям никто не стал
А это бесполезно.
Все равно человек пойдет по пути наименьшего сопротивления и, в конечном счете, выберет наименее трудозатратный вариант- либо простой пароль, либо бумажка на мониторе/файл с паролями на компе, либо один пароль для всех ресурсов.
Проверено многократно.
И конечно же учить пользователей паролям никто не сталА еще есть простой вариант, почему-то многим неочевидный.
Пользователь оценил риск инцидента и ожидаемый ущерб, признал его ничтожным, и использовал пароль «qwe123».
Но увы — аффтыри сервиса они же умнее — только strong password для форума с котиками! 16 знаков, прописные и строчные, цифры и спецсимволы, проверка по словарям, смена раз в месяц — Пентагон плачет в уголку :-)
Вот от паролей и ушли.
В Альфа- банке у меня при восстановлении утерянной симки перестало работать приложение.Они отслеживают номер симки, что на мой взгляд очень даже правильно… Злоумышленник при замене симки не сможет войти в мобильное приложение, потому что на новой симке номер будет другой… Позвонил оператору, объяснил ситуацию, ответил на кучу вопросов, и все заработало...
А если нет, то её достаточно вытащить из аппарата
А кто позволит вытаскивать симку из своего телефона?
Это очень заметная процедура, на глазах не сделаешь.
При этом я давно уже не замечал, что бы народ своими телефонами разбрасывался, сорри, люди даже в сортир идут с телефоном.
Потому как на телефоны сейчас много завязано — в том числе и сугубо личного, что понятно уже даже самым беспечным.
Сейчас смарт уже как связка ключей, и отношение тоже соответствующее.
А кто запретит вот тому гопнику с кирпичом, или вору, который уже украл устройство? А утеря?
При утере или краже, а так же и при грабеже- пострадавший всегда может блокировать свою сим-карту, либо у провайдера мобильной связи, либо на ресурсе, где используется этот номер.
Исключением является случай «сняли с бесчувственного тела, наконец — с трупа!» (с).
Но трупу уже в принципе все равно.
Ну так если у вас из телефона вытаскивают симку, то заодно из кошелька вытащат наличку и карточки. И, кажется, хорошо, если больше ничего не вытащат и вы своим ходом до полиции дойти сможете, и симка будет меньшей проблемой. Не?
Ну так если у вас из телефона вытаскивают симку, то заодно из кошелька вытащат наличку и карточки.
Был у нас случай, когда человек вечером поймал попутку и в конце пути сказал, что расплатится, сняв наличку с банкомата. Попросил остановится у ближайшего.
Его вывезли за город и запытали до смерти — узнавали пин-код.
Думаю человек имел в виду другое. есть необходимые отдельные приложения. калькулятор, фонарик, браузер, офис, плеер и т.д, а дальше пошел треш. Хочешь инсту — приложение, мордокнигу — приложение, контакт — приложение, хабр — приложение, 4pda — приложение, алиэкспресс — приложение.Это не другое по сути, это просто другая оценка того же самого.
Лично для нас это не треш, а наоборот неплохо, когда отдельные функции реализуются отдельным десктоп-приложением.
Та же почта. До сих пор предпочитаем десктоп-клиент, хотя все современные люди используют почту в браузере. Брокерское приложение — можно в браузере, но поставили десктопное. Для некоторых форумов до сих пор приложения используем десктопные, а не браузер. В вордпресс из ворда постим, а не с браузера.
Мы не говорим что это правильный подход, просто ну вот так вот — мы не перестроились на использование браузера, кто-то не перестроился на использование мобилы — каждому своё, ничего плохого в этом нет.
Плюс если так посмотреть, фактически браузер здесь выступает как условная виртуальная машина для запуска приложений. Поэтому…
МНОГО приложений для телефона имеют главную цель: показать как можно больше рекламы. В браузерах с этим давно разобрались с помощью ад-блокеров, поэтому злые маркетологи придумали отдельные приложения :)
Другой вопрос, что если бы вместо Android была бы мобильная OS-броузер, у которой нет различия между приложениями и вкладками, то может быть, это было бы и лучше.
Как пример (полагаю, что удачный) могу привести так называемые браузерные игры «Троецарствие» и «Танки онлайн». В первую давно играл, во второю иногда играю. В них можно играть в браузере, но не всегда удобно и иногда тормозит, но можно, зависит от мощности ПК и ширины канала. Официальный клиент игры это по сути браузер, но заточенный под один сайт (одно приложение). В целом вроде бы неплохо. У Битрикс24 так же новый клиент выглядит. Но у тех же Танков онлайн новая версия клиента это по сути эмулятор телефонной версии на ПК. Скачал, запустил, но лично мне не нравится визуально (за 7 лет игры привык к другому виду «гаража», «настроек» и т.п.).
Есть кейс ещё интереснее, называется "плохое качество мобильной связи в конкретном месте"...
Это плата за e2e шифрование без большой головной боли.
А так — большинству как-то пофиг на шифрование, если оно удобству использования мешает. Тем более, что я слышал про то, что в ваззапе нормального клиента пилят. Правда это было в прошлом году ещё, так что либо забросили, либо одно из двух.
А такой консольный подход — да, из-за желания сэкономить на e2e шифровании.
И даже не с интернетом, а с той локалкой, в которой сидит комп.
В ТО вроде бы до сих пор флеш-версия рабочая, её можно через standalone player запустить. Как игрок с семилетним стажем вы, вероятно, про это знаете.
Меня бы бесило. Меня вообще бесят виртуальные машины, удаленные рабочие столы и прочее, потому что там не мое родное настроенное окружение, а черт знает что. И если приложение с предустановленным андроидом захочет авторизоваться в гугле, оно не откроет мой десктопный браузер, где я уже авторизовался. Ну, это возможно, но потребует поддержки со стороны гостевой ОС. И сколько еще точек взаимодействия придется проработать? И вот из кучи таких мелочей складывается адское неудобство.
А уж ели в каком-то разумном виде заработает хотя бы часть гуглосервисов — то это будет вполне себе победа, запустил полдесятка андроидо-приложений, каждое в своем окошке одновременно — лепота…
И подозреваю, куда-то в эту сторону мы в итоге и придем.
Даже жалко, что лайтовое железо, которое тащит по 10 часов не чихая Хром с кучей вкладок, связку эту по факту не тянет. В итоге нужен хромбук, но с железом полноценного лаптопа. И тут уже проще влепить убунту и перестать натягивать сову на глобус. Ну или разделить на два девайса — вот тут хром, вот тут хрень.
А у влепленной убунту будет минус — не столь удобная интеграция с приложениями android. Шашлык от KDE так и не появился, да и Anbox далеко не идеал. Ну и планшетного интерфейса нормального не будет.
И как оно сейчас? Я его тыкал, когда вышел, ничего толком не работало.
Все так же запутанно и требует большого бубна. Первый запуск все так же крышесносящ — о том как называются два демона на вики не пишут, но прилагают картинку о том что они существуют :-)Примерно как anbox сейчас делает
И как оно сейчас?
Правда появились отдельные «выжившие», которые скриптуют установку тех же opengapps… но не только лишь всякий может долйти до этого шага.
Мне для своего кода надо было, а штатный эмулятор бесит неимоверно. Можно было конечно использовать реальный телефон — но я как раз с графикой развлекался, на мелком экранчике как-то не очень.
Так что opengapps существует — и хорошо, если понадобится — попробую :-)
а есть версия от противного — samsung Dex
В случае с эплом, это просто бонус фича к арм макам, имхо
Такое ощущение, что Каталист приложения будут позиционироваться как полноценные маковсковские приложения с адаптацией UI конкретно для мака. К примеру, UISwitch превращается в checkbox (NSSwitchButton). И это будет работать как на arm, так и на x86-64
А вот запуск iOS апп на арме — альтернатива для тех, кто не хочет заморачиваться с портированием и будет просто работать.
— А давайте на мобильных устройствах напишем всё заново, там же всё другое! Ой нет, давайте интерфейс сделаем один на компе и на мобилке (привет майкрософт!), это же так удобно, когда у вас меню из здоровенных прямоугольников, на мобилке можно нажимать пальцем, а в монитор — головой. Эх нет, неудобно, давайте сделаем разные интерфейсы, вернём пуск. Идея! Надо вообще сделать одни и те же приложения и на мобилках и на рабочем столе. Сейчас мы вам ещё притащим 100500 игрушек «тапни чтобы перепрыгнуть какашку» с мобилок (привет Яблоки).
Работать с телефона/планшета можно если вместо работы из дома лежишь на пляже и в чатиках делаешь вид что работаешь :D
vdsina_m, а вы почему сделали фит с филпакартом? Он у вас типа рекламное лиуо или вроде этого, вы за рекламу ему платите или как?
Но это кстати круто — раз слог фила так легко детектится просто по куску текста — значит можно обучить нейросетку писать тексты в стиле Фила, а того — отправить писать код.
И почему вы считаете, что отправить Фила писать код будет хорошо? Насколько я понял из этой статьи и комментариев к ней, чем меньше он будет трогать клавиатуру, тем лучше.
Это, кстати, уже второй персонаж на Хабре за последний год, который пишет фанфики для программистов, а ему все хлопают.
Я вообще испытал когнитивный диссонанс
Когнити́вный диссона́нс — состояние психического дискомфорта индивида, вызванное столкновением в его сознании конфликтующих представлений (украл с вики).
Ну т.е. когда статью открыл — увидел что это ВДСина
ВДСина — провайдер впс-серваков и прочего подобного, официлальный российский, зарегестрированный в реестре распространителей информации, и по сообщениям их поддержки в чатике — без задней мысли готовый пускать майора на свое оборудование.
почему-то подумал что писал статью Фил.
Автор поста, fillpackart — знаменит на хабре тем, что пишет посты, провоцирующие волны споров, холиваров и прочего хорошего.
Потом подумал — «да не, это ВДСина, просто какой-то копирайтер с двача пишет в стиле Фила»
Два.ч — самая крупная и достаточно популярная среди школоты, студентоты и постаревших, но не потерявших молодецкой тяги к угару людей, русскоязычная «анонимная» имиджборда (форум с картинками без регистрации) — настолько крупная, что иногда на двач в качестве источника ссылаются всякие журналисты типа ленты.
Копирайтер с двача — человек, не имеющей вменяемого источника дохода, и пытающийся заработать выполняя задания на толоке и пописывая поганенького качества тексты на яндекс.дзен, в надежде на монетизацию. Очень часто работают за еду.
Но это кстати круто — раз слог фила так легко детектится
Детектится — распознается.
просто по куску текста — значит можно обучить нейросетку
Нейросетка — нейросеть, например GAN — Генеративно-состязательная сеть (англ. Generative adversarial network, сокращённо GAN) — алгоритм машинного обучения без учителя, построенный на комбинации из двух нейронных сетей, одна из которых (сеть G) генерирует образцы, а другая (сеть D) старается отличить правильные («подлинные») образцы от неправильных (wiki). По-сути, эта та штука, что стоит за проектами типа «thispersondoesntexist» и тысячами разных других.
Надеюсь стало яснее.
Скоро как у Татьяныча будет. Нейросетка будет писать тексты для забора.
Про удобную джира на мобилке улыбнуло
Всё нормально, меня уже убедили, что я болван (тупой)
А меня наоборот. Теоретически это мешает переделывать интерфейс в класс и обратно (главное роль типа в программе, а интерфейс это или класс — вторична). Практически, правда, я соблюдаю нейминг конвеншнс того места, где я оказался.
В Java, кстати, его и не делают, насколько я знаю. Тут вопрос не в том, нужен он или нет, вопрос в том, чтобы писать привычный для шарпистов код на C#. По крайней мере, меня убедили именно таким аргументом.
В Java его не ставят, потому что канонично оперировать именно объектом интерфейса, а не реализующим интерфейс классом (которые часто обозначаются суффиксом Impl, но это не обязательно).
Так и в C# тоже
Я предпочитаю префикс I, это куда нагляднее, чем инверсная логика «нет суффикса — интерфейс, есть суффикс Impl — реализация».
Не могу говорить за все языки, потому как их не знаю.
КМК, ставить префиксы имело смысл в языках без явного синтаксического разделения сущностей (Pascal, C, C++), но там, где семантическая роль выделена синтаксисом самого языка, дополнительное обозначение избыточно. Может еще кто-то кодит в блокноте, и ему/ей сложно искать в коде определение сущности — ну как бы штош...
Возникает вопрос, а почему важно знать интерфейс это или реализация? Ведь везде должны быть только интерфейсы, не?
Например чтобы на кодревью надавать по шапке тому кто поленился и вместо интерфейса использует класс :)
P.S. И да, кодревью далеко не всегда делается в IDE и поэтому удобнее когда интерфейс можно отличить от реализации просто по названию.
Например чтобы на кодревью надавать по шапке тому кто поленился и вместо интерфейса использует класс :)А зачем? Какая разница чем представлен тип — классом или интерфейсом? При условии, что речь не идет об АПИ какой-нибудь библиотеки, а о внутреннем коде.
Если это вот прямо совсем "внутренний код", то никакой. А если речь идёт хотя бы о разных проектах, то использование классов может создать определённые проблемы. Например лишние зависимости между отдельными проектами. Или даже перекрёстные ссылки.
С префиксами в имени такое заметнее. Особенно если ревьюишь не в IDE.
Нет. Префикс "I" или его отсутствие очень просто и быстро видно в самом APl.
И да, с интерфейсами можно тоже кучу глупостей наделать. Просто такая банальная вещь как naming conventions заметно облегчает жизнь отдельным людям в отдельных ситуациях.
Это не значит что все должны их использовать. И уж тем более не значит что всем надо использовать одни и те же. Но вот у нас такие и нам так удобнее.
Интерфейс — прилагательное, класс — существительное, метод — глагол ;)
Выделение интерфейса бывает неизбежным, например, для развязывания кольцевых зависимостей.
А Dependency Injection чем хуже?
Ничем, но это более внешнее требование по отношению к данному компоненту.
Ну, так-то интерфейс — сам по себе анти-паттерн, хотя бы потому, что нарушает SRP. External protocols — это интерфейс здорового человека, а охапка методов, которые каждая собака должна имплементировать, даже если это выходит за рамки разумного, — порождающих безумную копипасту и груду полуживых имплементаций — несомненное зло.
Использование интерфейсов — уже само по себе звоночек, но ведь создатели языков любят еще разрешить пустые интерфейсы, а это уже вообще за гранью здравого смысла (точнее, это признание в собственной некомпетентности).
Интерфейсы кажутся приемлемым решением только людям, которые вообще не способны в архитектуру.
У меня такое впечатление, что вы увидели слово-триггер и завелись на него. Иначе такой поток атаки на интерфейсы сложно объяснить. Но хорошо, попробуем разобрать детальнее, мне уже стало интересно:
Ну, так-то интерфейс — сам по себе анти-паттерн, хотя бы потому, что нарушает SRP.
Чем нарушает-то? Прошу подробностей.
External protocols — это интерфейс здорового человека,
External protocol в контексте ООП вообще не гуглится. Дайте расшифровку, что вы понимаете под этим. Если имеется в виду связь с другими компонентами через сетевые протоколы, то я не понимаю, зачем их тут вообще примешивать.
а охапка методов, которые каждая собака должна имплементировать, даже если это выходит за рамки разумного, — порождающих безумную копипасту и груду полуживых имплементаций — несомненное зло.
Красивый пассаж. Но я бы заменил "даже если" на "только если". То есть зло, если эти механизмы абсолютизируются там, где от них начинается усложнение (и та же копипаста).
Использование интерфейсов — уже само по себе звоночек
Чего именно звоночек-то?
но ведь создатели языков любят еще разрешить пустые интерфейсы, а это уже вообще за гранью здравого смысла (точнее, это признание в собственной некомпетентности).
Пометка, что определённый тип декларируется как обладающий определённым свойством. Конечно, было бы лучше дать возможность компилятору это вывести, но они ещё много лет не будут способны делать выводы только за пределами самых простейших. Если тут кто-то некомпетентен, то человечество в целом. И что, прикажете стреляться атомными бомбами?
Интерфейсы кажутся приемлемым решением только людям, которые вообще не способны в архитектуру.
Ваши альтернативные предложения — в студию. Только конструктивно.
Начну с середины, для связности.
External protocol в контексте ООП вообще не гуглится. Дайте расшифровку, что вы понимаете под этим.
Причем тут контекст ООП? Что в ООП такого особенного, что у него должны быть паттерны, идущие вразрез с не ООП? В Хаскеле это называется Type Class. В Эликсире — протокол. Полиморфизм без необходимости размазывать имплементацию по разным частям кода. Наиболее внятно принципы расписаны в гайдах по эликсиру.
нарушает SRP.
Чем нарушает-то? Прошу подробностей.
Давайте возьмем в качестве примера набивший оскомину Comparable
. Сравнение — само по себе сущность, которая, кхм, отвечает за сравнение. SRP решение: описываем type class / protocol, который умеет сравнивать. Интерфейсное решение: каждый класс, который хочет уметь сравниваться, должен, видите ли, немного отвечать за сравнивание. Хотя он, вообще-то, модель User
. Вы не видите тут нарушение SRP? С какой радости модель должна отвечать за данные, и еще немножко за сравнивание? А что если я хочу научить чужой класс сравниваться? Аспекты, рефлекшн, магия?
Чего именно звоночек-то?
Того, что люди ведутся на хайп и авторитет вместо здравого смысла.
Пометка, что определённый тип декларируется как обладающий определённым свойством.
Угу. А зачем? Вернемся к Comparable
. Кому хорошо от того, что User
знает, что он умеет сортироваться? Никому. Сущность «Сравнивание» должна уметь принять пару объектов типа User
и либо вернуть -1 | 0 | 1
, либо вежливо отказаться сравнивать несравнимое. Тогда и для чужих сущностей я смогу определить любой нужный мне «интерфейс» без хаков и магии.
Ваши альтернативные предложения — в студию.
Озвучил же уже: протоколы / тайпклассы и dependency injection.
Сравнение — само по себе сущность, которая, кхм, отвечает за сравнение. SRP решение: описываем type class / protocol, который умеет сравнивать. Интерфейсное решение: каждый класс, который хочет уметь сравниваться, должен, видите ли, немного отвечать за сравнивание.
И почему нет? Почему нельзя чтобы каждый класс сам решал как для него выглядит сравнение? Чем лучше если ваша сущность «Сравнивание» должна знать как выглядит сравнение для абсолютно всех существующих классов? И если в вашей ситуации мы добавляем новый класс, которые должен сравниваться, то мы должны лезть и менять вашу сущность «Сравнивание». И когда у какого-то класса вдруг почему то изменилось сравнение, то тоже самое — надо лезть в сущность «Сравнивание» и её менять. И при этом мы в теории можем сломать сравнение для уже существующих классов.
А теперь представьте себе что классы скажем пишу я, а сущность «Сравнивание» находится в вашей зоне отвественности(или вообще купленная библиотека). Или я пишу классы, пакую их в библиотеку и отсылаю клиенту у которого где-то там запускается сравнение и сущность «Сравнивание» он там пишет и изменяет сам. Или скажем у вас десять человек пишут классы и пользуются сравнением. Или сто. Или тысяча.
И что теперь делать когда нужно добавить новый сравниваемый класс? Каждый раз просить кого-то там изменить сущность «Сравнивание»?
А интерфейсом Comparable я пишу классы, которые его имплементируют, а кто хочет там просто берёт их и сравнивает так как я это задумал. И ему не надо ничего у себя там писать или менять или думать как вообще должны сравниваться мои классы.
Угу. А зачем? Вернемся к Comparable. Кому хорошо от того, что User знает, что он умеет сортироваться? Никому. Сущность «Сравнивание» должна уметь принять пару объектов типа User и либо вернуть -1 | 0 | 1, либо вежливо отказаться сравнивать несравнимое.
Угу, а потом ваш код великолепно компилируется, а во время исполнения ваша сущность «Сравнивание» начинает выдавать одну ошибку за другой.
Озвучил же уже: протоколы / тайпклассы и dependency injection.
И каким конкретно образом dependency injection должна заменять интефейсы?
И если в вашей ситуации мы добавляем новый класс, которые должен сравниваться, то мы должны лезть и менять вашу сущность «Сравнивание»?
Подозреваю, что речь идёт о подходе а-ля Rust, в котором будет (псевдокод)
... неважно где...
class Foo<T> {
внутренности класса
}
... где-то ближе ...
impl Compare for Foo<T> {
func less(a: & const T, b: & const T) {
...
}
}
то есть оно не оформляется внутри типа и формальная сравниваемость не строится в зависимостях типа, а объявляется вне его.
Она может быть и сразу рядом с описанием типа, и добавлена кем-то со стороны, а увидит её компилятор или нет — зависит от того, какие объявления подключены к этому моменту, не хотим — не подключаем. Объявить Compare для чужого типа, не зная его названия — сложно, для всех сразу — невозможно, поэтому явный абьюз малореален.
Мне этот подход скорее нравится, хотя тут надо бы уточнить ряд особенностей — могу ли я, например, для производного класса запретить, наоборот, такую имплементацию, если ломаю её контракт?
И если в вашей ситуации мы добавляем новый класс, которые должен сравниваться, то мы должны лезть и менять вашу сущность «Сравнивание».
Стандартный полиморфизм по параметру X в impl Compare for X — решает эту проблему.
И когда у какого-то класса вдруг почему то изменилось сравнение, то тоже самое — надо лезть в сущность «Сравнивание» и её менять.
Если автор класса сразу рядом с классом поставил подобную имплементацию — это уже его ответственность.
Если кто-то другой снаружи такое придумал — то это его ответственность следить за особенностями того класса, в сущность которого он лезет своим сравнением.
Тут всё корректно, и даже конфликты должны решаться стандартными средствами их разрешения (давно подточенными под 100500 правил поиска лучшего соответствия при полиморфизме).
На самом деле это вполне естественный сдвиг по сравнению от явного объявления интерфейсов, когда вам надо определить какое-то свойство, которое автору соответствующих типов просто никак не было нужно.
Например, он сделал иерархию животных и выделил базовые свойства — рептилии, млекопитающие, птицы…
А мне нужно определить всех летающих: птицы, но не все; белки-летяги; летучие рыбы; рукокрылые. Я беру отдельный типаж FlyingAnimal и назначаю его применимость к заданным типам по иерархии (причём, если язык позволяет, включаю туда птиц, а потом исключаю страусов, эму, казуаров и дронтов).
В C++ строится подобное, но косвенно (через хаки типа std::enable_if, замусоривающие имя типа и закаменяющие применённое ABI). Во многих других языках и сейчас нельзя.
Другой вопрос, стоит ли от этого отказываться от интерфейсов в принципе. Наличие требования соответствия интерфейсу позволяет уже при компиляции типа (а не его использования) проверить, например, отсутствие реализации затребованного метода (название с опечаткой, сигнатура попутана — да мало ли что). Сейчас я не готов сказать, насколько хорошо решаются эти вопросы новыми подходами.
И ещё очень хорошо надо подумать над бинарной совместимостью. Если есть библиотека, в которую мы передаём просто указатель/ссылку/чтоугодно на Comparable, FlyingAnimal, etc., и её нельзя перекомпилировать под каждое применение — требуются решения, сходные с тем, как в Java для интерфейса, в C++ для базового класса при множественном наследовании...
Она может быть и сразу рядом с описанием типа, и добавлена кем-то со стороны
Но это всё равно уже не
Сущность «Сравнивание» должна уметь принять пару объектов типа User и либо вернуть -1 | 0 | 1, либо вежливо отказаться сравнивать несравнимое.
И опять же чтобы её написать надо знать либо внутренности класса, либое его интерфейс, либо ещё какое-то формальное описание этого класса. Без этого знания вы всё равно Compare не напишите.
Объявить Compare для чужого типа, не зная его названия — сложно, для всех сразу — невозможно, поэтому явный абьюз малореален.
На мой всзгляд проблема скорее не в абьюзе, а в возможной необходимости писать Compare для чужого типа, не зная его названия/содержания.
На самом деле это вполне естественный сдвиг по сравнению от явного объявления интерфейсов, когда вам надо определить какое-то свойство, которое автору соответствующих типов просто никак не было нужно.
Это совсем другая проблема и естественно интерфейсы вроде Comparable и не должны её решать.
На мой всзгляд проблема скорее не в абьюзе, а в возможной необходимости писать Compare для чужого типа, не зная его названия/содержания.
Compare как раз тут, да, слегка проблемный пример. Тип может и не экспортировать необходимые данные для сравнения. Мне кажется, с летающими получилось немного лучше.
Но совсем для неизвестных типов вроде ж никто такое и не пишет?
Это совсем другая проблема и естественно интерфейсы вроде Comparable и не должны её решать.
Тут тот момент, что при наличии таких типажей/протоколов/you_name_it может оказаться, что интерфейсы в классическом виде и не нужны...
То есть в такой ситуации вам нужна какая-то форма «договора», которого будут придерживаться обе стороны. И для меня как раз вот это в первую очередь и является интерфейсом. А как там эти интерфейсы реализованны в отдельных ЯП/фреймворках/ситуациях и какие они там ещё дополнительные функции могут нести это на мой взгляд уже вторично.
А как там эти интерфейсы реализованны в отдельных ЯП/фреймворках/ситуациях и какие они там ещё дополнительные функции могут нести это на мой взгляд уже вторично.
Ну а вся ветка дискуссии как раз посвящена тем особенностям, которые для вас тут вторичны :) но далеко не так в том случае, когда это начинает влиять на реализацию.
Я его не распарсил, а ответить хочется.
:)))
Ну вот буквально в соседнем комментарии. Мне нужен типаж "летающие животные" (предположим игру, где персонаж может улететь от врага через пропасть).
Я знаю, что 99% птиц летают и это осилят (даже какая-нибудь курица, хоть она и не любит летать). Но есть нелетающие: персонаж-страус этого не осилит.
И у меня иерархия типов. Я могу всем птицам раздельно ставить пометку "этот летает", но если я где-то пропущу, пойдут жалобы на нелетающих астрильдов. А могу исключить только мелкие группы действительно нелетающих — но тогда я должен иметь возможность для каких-то типов выключать возможность, которая включена для их предковых типов.
В идеале я ожидаю что-то вроде:
impl Flying for Bird {
// неважно что, важен факт разрешения impl Flying
}
#[prohibited] impl Flying for Ostrich {
}
Если такого нет, я или помечаю каждую подветку птиц раздельно (задолбаться и с ошибками), или должен рисовать что-то типа:
impl FlyingCheck for * {
func Flies() bool { return false; }
}
impl FlyingCheck for Bird {
func Flies() bool { return true; }
}
impl FlyingCheck for Ostrich {
func Flies() bool { return false; }
}
но при этом проверка усложняется до
impl EscapeByFly for T
when FlyingCheck[T] and T.Flies()
{ ... }
и мы впадаем в C++ с его проблемой, что чтобы скомпилировать, нужно интерпретировать какое-то подмножество языка и во время компиляции проверять constexprʼы.
Ну, вот, жду ответа :)
Но какова связь между Bird и Ostrich? В расте (насколько я знаю) нет наследования типов, поэтому у вас будет просто отдельный тип Bird и отдельный тип Ostrich, с которым ваш Bird никак не может быть связан.
Я упомянул, что у нас иерархия типов. И Ostrich — подкласс (неважно, насколько дальний) для Bird. От Rust здесь только условный стиль.
Ну вот вы это проблемой считаете, а куча людей в том же хаскель-комьюнити (включая меня) спят и видят, как бы сделать это возможным со всеми этими зависимыми типами.
Не понял, что тут "это", расшифруете?
Ну нельзя же просто рассматривать стиль, чтобы и тайпклассы были, и ООП-наследование. Получится скала какая-то, а там своих костылей дофига.
Я не говорю про тайпклассы в вашем понимании — из-за нулевого опыта в подобных языках я уверен, что то, что я понимаю под этим термином на основании просто прочтения публичных док, будет принципиально отличаться от того, что вы видите.
В том же C++ я вполне могу определить, в согласовании со стандартными правилами разрешения полиморфизма, или функцию, которая параметризована типом и вернёт true для Bird, но false для Animal и Ostrich; или структуру, в которой будет функция со свойством; и компилятор будет обязан разобрать такие константные функции и разрешить или запретить соответствующее воздействие:
#include <cstdio>
#include <type_traits>
using namespace std;
struct Animal {
};
struct Chordatum : Animal {
};
struct Bird : Chordatum {
};
struct Struthionida : Bird {
};
struct Ostrich : Struthionida {
};
template<typename> struct is_flying_helper : public false_type {};
template<> struct is_flying_helper<Animal> : public false_type {};
template<> struct is_flying_helper<Bird> : public true_type {};
template<> struct is_flying_helper<Ostrich> : public false_type {};
template<typename Tp> struct is_flying
: public is_flying_helper<typename remove_cv<Tp>::type>::type
{};
template<typename Tp>
typename std::enable_if<is_flying<Tp>::value>::type
makeItFly(Tp&)
{
printf("It flies!\n");
}
int main() {
//printf("%d\n", is_flying<Animal>::value);
Bird animal;
makeItFly(animal);
}
поиграйтесь с типами в main, чтобы убедиться в отказе компиляции при несоответствии требованиям.
Но то, как оно выглядит внутри — вместе со всем C++ — как китайские ёлочные игрушки: не радует.
(Ваш боевой походный комплект экспериментальных языков (а для моего мирка даже Haskell входит пока что туда же), впрочем, не радует с другой стороны.)
И ему не надо ничего у себя там писать или менять или думать как вообще должны сравниваться мои классы.
Кстати, вот это как раз очень часто неадекватно именно потому, что сравнение может быть для разных целей заметно по-разному — тут я согласен скорее с коллегой chapuza@. Методы стандартных библиотек, которые используют сравнение (как сортировка или хранение в дереве), по умолчанию используют некоторый штатный компаратор, но дают переопределение для своих целей — и это неспроста (и не только для изменения на обратный порядок).
Возьмите, например, даты. Для списка дней рождений нам надо сравнивать, выкинув год из учёта.
Встроенное сравнение обычно предназначено обеспечивать только что неидентичные объекты неравны.
Если вам нужны несколько видов сравнения для одного класса, то вам нужно либо несколько интерфейсов для кажой из целей, либо действительно уже использовать «внешнее» сравнение. Для этого в C# существует тот же IComparer интефейс. И этот самый IComparer тоже понимают/поддeрживают большинство библиотек.
Но в подавляющем большинстве случаев хватает одного IComparable.
Причем тут контекст ООП? Что в ООП такого особенного, что у него должны быть паттерны, идущие вразрез с не ООП?
Я разве сказал про обязанность таких паттернов? :) Я сказал, в каком контексте пытался гуглить термин, потому что он явно не из общеизвестных. Вы заводитесь там, где просто не нужно.
Давайте возьмем в качестве примера набивший оскомину Comparable. Сравнение — само по себе сущность, которая, кхм, отвечает за сравнение. SRP решение: описываем type class / protocol, который умеет сравнивать.
Понятно. Тут я согласен с облегчением из-за типажей, но на SRP это не тянет, пока возможность определения свойства должна присутствовать как минимум рядом с определением класса. От того, что вы формально выносите эту роль наружу, только формальные признаки и меняются.
Такой же результат можно было получить, потребовав, например, явного задания имени интерфейса в названии каждой определяемой функции.
Сущность «Сравнивание» должна уметь принять пару объектов типа User и либо вернуть -1 | 0 | 1, либо вежливо отказаться сравнивать несравнимое.
И вы получаете на этом большее нарушение — необходимость выдать этой самой Comparable в доступ (хотя она определена снаружи) внутренности объекта, которые вполне могут быть приватными. Что, friend-ы объявлять?
Вы заводитесь там, где просто не нужно.
Когда я завожусь, я надеваю цилиндр и прыгаю до потолка. Это не тот случай, поверьте :)
От того, что вы формально выносите эту роль наружу, только формальные признаки и меняются.
Отнюдь. Я не выношу «роль» наружу. Я предлагаю писать код так, чтобы модель отвечала за свойства модели, а сравниватель —за сравнение. Сериализатор — за сериализацию. И так далее.
Еще ярчайший пример: Object.hashCode()
— как только я захочу в хэшмапе использовать в качестве ключей разные объекты — мне придется идти и смотреть на реализацию самих объектов, а не тайп-класса.
Ну и, я все-таки настаиваю, что вынесение разных ролей за пределы одной сущности — это и есть краеугольный камень SRP.
необходимость выдать этой самой Comparable в доступ (хотя она определена снаружи) внутренности объекта, которые вполне могут быть приватными. Что, friend-ы объявлять?
Изящно, но мимо. Сортировка по чему-то такому, что недоступно извне — за гранью разумного. Это как сортировать Object
ы. Не бывает такого, что мне нужно отсортировать по какому-то признаку, но получить доступ к этому признаку мне нельзя, это нежизнеспособный пример.
Ну и это… Вот представьте, что мне втемяшилось сравнивать яблоки и столы. В какой класс: «Apple» или «Table» мне положить правильный компаратор?
А с чего вы решили что Comparable должен применяться для сравнения разных классов между собой? Он отвечает за сравнение объектов одного класса.
Но давайте другой пример. Скажем я пишу ORM, которой будут пользоваться какие-то неизвестные мне люди для каких-то своих неизвестных мне нужд. То есть они просто берут какие-то свои классы, а мой ORM генерирует из них таблицы в базе данных и сам целиком отвечает за работу БД.
И скажем мне чтобы решить использовать Insert или Update надо знать есть у меня уже где-то этот объект или он новый. Для этого мне нужна какая-то функциональность, которая банально сравнивает два объекта произвольного класса и говорит мне идентичны они с точки зрения бизнес-логики или нет. Я такое всегда решал через интерфейс IEquatable. Как вы предлагаете такое решать без интерфейсов?
А с чего вы решили что Comparable
должен применяться для сравнения разных классов между собой? Он отвечает за сравнение объектов одного класса.
Ну с того, например, что чуть-чуть разбираюсь в CS.
public interface Comparable<T>
→ This interface imposes a total ordering on the objects of each class that implements it. — Java8
public int CompareTo(object obj) { if (obj == null) return 1;
— .NET
От микрософтов я ничего внятного в документации и не ждал, но поправьте меня, если я ошибаюсь: сравнение с null
вот прямо в первом же примере.
И скажем мне чтобы решить использовать Insert или Update надо знать есть у меня уже где-то этот объект или он новый.
Погуглите Upsert, эта проблема решена в XIX веке.
сравнивает два объекта произвольного класса и говорит мне идентичны они с точки зрения бизнес-логики или нет
Я такое всегда решал через интерфейс IEquatable.
Круто, что вам разрешили изменить код, к которому вы даже теоретически доступа не имеете. Либо вы можете обязать ваших пользователей написать вам пол-библиотеки за вас — и тогда вариантов масса. Либо нет — и тогда у вас нет гарантии, что IEquatable
имплементирован хоть кем-то вообще.
От микрософтов я ничего внятного в документации и не ждал, но поправьте меня, если я ошибаюсь: сравнение с null вот прямо в первом же примере.
null в шарпах это не отдельный класс. Это грубо говоря просто «пустая ссылка». Более того там ниже по тексту:
This interface is implemented by types whose values can be ordered or sorted. It requires that implementing types define a single method, CompareTo(Object), that indicates whether the position of the current instance in the sort order is before, after, or the same as a second object of the same type.
Погуглите Upsert, эта проблема решена в XIX веке.
Допустим мой ORM должен работать и с базами данных, которые такое не поддерживают. Да и вообще это гипотетический пример для того чтобы показать целый класс проблем.
Круто, что вам разрешили изменить код, к которому вы даже теоретически доступа не имеете.
Кто и где мне разрешил менять какой-то код? Я вообще ничей код менять не собираюсь. Я пишу свою собственную ORM и ставлю условие что для того чтобы использовать с ней какой-то класс, то этот класс должен имплементировать интерфейс IEquatable.
Либо вы можете обязать ваших пользователей написать вам пол-библиотеки за вас — и тогда вариантов масса.
Они вообще не должны за меня ничего писать. Они должны сами для себя решить как должны сравниваться на идентичность их собственные классы.
Может им достаточно одного id для сравнения. А может у них id композитные. А может у них как id вообще используется какой-то их собственный класс. Или им для идентичности необходимо чтобы абсолютно все поля были идентичны.
Откуда я должен это знать когда я пишу своё ORM?
Этот комментарий стал выстрелом в голову самому себе. Я не вижу смысла продолжать что-то объяснять людям, которые в соседних предложениях пишут буквально следующее:
Я [...] ставлю условие что для того чтобы использовать с ней какой-то класс, то этот класс должен имплементировать интерфейс IEquatable.
Они вообще не должны за меня ничего писать.
Ну так а в чём конкретно претензии? Особенно если учитывать что предложенные вами альтернативы с инъекциями и DP имеют точно ту же проблематику.
Они не имеют этой проблематики. И я примерно пятьсот раз это уже повторил и расписал, с примерами, которые вы просто не понимаете.
Претензий никаких нет вообще.
А если вы вашу имплементацию финализировали, отдали кому-то и этот кто-то хочет добавить сравнение для каких-то своих новых классов при помощи инъекции или DP, то он это точно так же должен делать сам. Или вы предлагаете ему в такой ситуации обращаться к вам и ждать пока вы найдёте время сделать это сами?
Так что конкретно в данном аспекте разницы нет ровно никакой.
А с чего вы решили что Comparable должен применяться для сравнения разных классов между собой? Он отвечает за сравнение объектов одного класса.
То есть даже с производным классом сравнить нельзя? По-моему, это чрезмерное ограничение.
Это очень толсто.
Вы мне лично сами пару месяцев тому — демонстрировали мощь хаскеля на примере сортировки разных типов; лень ссылку искать.
Я ожидаю, что если у меня есть дни рождения, национальные праздники, график отпусков и выдачи зарплат, имеющих между собой общего — только то, что они все привязаны к дате — мне дадут их отсортировать по дате.
Kanut вон выше пишет, что в шарпе мне даже не удастся изобрести специальный интерфейс, чтобы сравнивать по нему, все равно придется построить God-объект, который будет сортировать разношерстные коллекции.
В джаве, слава Гослингу, мне хотя бы дадут объявить IHavingDate
с методом getDate
, и я смогу их отсортировать, если ни одна из имплементаций не забудет про него.
Kanut вон выше пишет, что в шарпе мне даже не удастся изобрести специальный интерфейс, чтобы сравнивать по нему, все равно придется построить God-объект, который будет сортировать разношерстные коллекции.
На самом деле не совсем так. В теории вы можете написать интрефейс IGodComparable, который будет сравнивать любые классы, которые имплементируют интефейc ISpecialComparable. Просто мне сложно представить зачем это нужно.
Любые в зависимости от задачи.
Вот у меня есть например 3 подвида таймеров: однократные, многократные с интервалом между стартами и многократные с интервалом между работами. Но для сравнения мне нужно только время ближайшего старта.
То есть в теории можно сравнивать разные объекты до тех пор пока они все либо имеют один базовый класс, либо имплементируют один общий интерфейс.
Но вот именно IComparable и именно с абсолютно произвольными классами работать не будет.
То есть в теории можно сравнивать разные объекты до тех пор пока они все либо имеют один базовый класс, либо имплементируют один общий интерфейс.
В какой теории? В теории ущербных языков программирования?
Перечитайте самое начало этого треда: интерфейсы — тупиковая ветвь эволюции, придумавшим их людям должно быть стыдно. Они приносят проблемы на ровном месте, нарушают основные работающие принципы CS и вообще бессмысленны со всех точек зрения, кроме «я умею только в один энтерпрайзный язык, и тут так, поэтому это хорошо».
Вы же даже сами чуть ниже расписываетесь в том, что интерфейс не нужен:
К счастью для этого у отдельных классов/типов есть CompareTo
[...].
В какой теории? В теории ущербных языков программирования?
В теории, обсуждая ситуацию, имеющуюся на данный момент в C#.
Перечитайте самое начало этого треда: интерфейсы — тупиковая ветвь эволюции, придумавшим их людям должно быть стыдно
Я вот пока вижу с вашей стороны кучу критики интеpфейсов, но так и не увидел ни одного конкретного ответа на поставленные мною вопросы. И вариaнтов «безинтерфейсных» решений озвученных мною проблем я от вас тоже пока не увидел.
Так что нет, на мой взгляд интерфейсы это не тупиковая ветвь эволюции. На мой взгляд это вы просто похоже в вашей работе не сталкиваетесь с проблемами, которые решаются при помощи интерфейсов.
Вы же даже сами чуть ниже расписываетесь в том, что интерфейс не нужен:
Это уже какая-то демагогия начинается. Естественно интерфейсы нужны не всегда и естественно не все проблемы решаются с помощью интерфейсов. Но это не значит что интерфейсы не нужны в принципе.
обсуждая ситуацию, имеющуюся на данный момент в C#
Если вы вдруг не обратили внимание, C# сюда принесли и здесь обсуждаете только вы.
так и не увидел ни одного конкретного ответа на поставленные мною вопросы
Потому что вы начали задавать вопросы в этой ветке после того, как я на них ответил вот тут. Там даже ссылка есть.
вариaнтов «безинтерфейсных» решений озвученных мною проблем я от вас тоже пока не увидел
Прям беда. Ваши «проблемы» — это не проблемы вообще, их можно решить и интерфейсом, и отдельным сортировщиком, и как угодно. Но только интерфейсный вариант заставляет пользователей вашего кода писать кучу им не нужного бойлерплейта, чтобы ваша библиотека была способна работать.
На мой взгляд это вы просто похоже в вашей работе не сталкиваетесь с проблемами, которые решаются при помощи интерфейсов.
Ваша правда; ибо таких задач нет. Точнее, не так: такие задачи появляются как искусственные ограничения, поставленные плохо спроектированным языком программирования. Я не пишу на языках, которые вынуждали бы меня постоянно чувствовать себя удаляющим гланды проктологом.
не все проблемы решаются с помощью интерфейсов
Тут ветка, в ветке контекст. Контекст — волею случая — интерфейс Comparable
. Простейший, как амеба. Один, блин, метод. Но костылей вокруг пришлось понагородить — районную больницу можно было бы этими костылями обеспечить. ПростоComparambe, ComparambeСВывертом, CompareTo… Удивлен, что нет CompareFrom и CompareInstead.
А всего-то надо было: понять, что сравниваемость ортогональна физическим свойствам и вынести ее в отдельную сущность сбоку.
Если вы вдруг не обратили внимание, C# сюда принесли и здесь обсуждаете только вы.
Вообще-то нет. Про Comparable и, цитирую, «чуть-чуть разбираюсь в CS» начал совсем не я.
Потому что вы начали задавать вопросы в этой ветке после того, как я на них ответил вот тут. Там даже ссылка есть.
Это не отвечает на поставленные мною вопросы и не даёт решения для описаных мною примеров. И как раз поэтому я их вам и задал.
Ваша правда; ибо таких задач нет.
Ну давайте я ещё раз повоторю если вы что-то пропустили или не поняли:
Допустим я пишу библиотеку, которая должна отвечать за сортировку данных. Как мне без интерфейсов сделать так чтобы эта библиотека могла сортировать абсолютно любые сравниваемые типы данных? Причём даже те типы данных, которые появятся после окончания работы над этой библиотекой? И с ошибками во время компиляции, а не во время исполнения?
Тут ветка, в ветке контекст. Контекст — волею случая — интерфейс Comparable. Простейший, как амеба. Один, блин, метод.
Я не вижу здесъ «простейшего как амёба метода». Я вижу пожелания вроде того чтобы этот метод мог сравнивать между собой абсолютно любые типы данных. Чтобы он мог сравнивать по разному в зависимости от контекста. Чтобы он мог сравнивать даже те типы данных, которые пока ещё не существуют. И так далее и тому подобное.
Но если для вас это простейщий метод, то наверняка вам не составит труда показать имплементацию метода, который удовлетворяет хотя бы трём вышепречисленным условиям. На любом удобном вам языке и без интерфейсов.
И с ошибками во время компиляции, а не во время исполнения?
Ух ты, как мы прямо на лету ТЗ-то меняем, любо-дорого смотреть. А ничё, что не все языки — компилируемые?
Я вижу пожелания вроде того чтобы этот метод мог сравнивать между собой абсолютно любые типы данных.
Нет только те, которые хотят сравниваться. Ну да ладно, я и для любых могу (идея позаимствована у Армстронга и Вирдинга) — оператор сравнения работает из коробки для всех типов данных языка:
number < atom < reference < fun < port < pid < tuple < map < nil < list < bit string
Да, это не совсем то, чего вы ожидали. Ну ладно, давайте поближе к земле.
Чтобы он мог сравнивать по разному в зависимости от контекста
ruby
, классическая Dependency Injection, пример из моего первого комментария.
def compare o1, o2, comparator = Comparator.def
comparator.(o1, o2)
end
Чтобы он мог сравнивать даже те типы данных, которые пока ещё не существуют. И так далее и тому подобное.
Пример поизящнее: map-sort из elixir.
Инъекция кода, изменение AST.
defmodule User do
use Comparable, compare_to: fn
me, %User{} = user -> me.full_name < user.full_name
me, %{id: id} = other -> me.id < id
me, other -> me < other
end
...
Ну и, наконец, протоколы.
defprotocol Comparable do
@doc "Returns a term that would be used to compare"
def term(data)
end
...
@spec sort(any(), any()) :: boolean()
def sort(e1, e2) do
case {Comparable.impl_for(e1), Comparable.impl_for(e2)} do
{nil, _} -> e1 < e2
{_, nil} -> e2 < e1
{c1, c2} -> c1.term(e1) < c2.term(e2)
end
end
Теперь если какая-то сторонняя сущность пожелает участвовать в конкурсе, от автора потребуется имплементация одного метода из протокола, причем он может как сам ее написать, так и воспользоваться любой существующей.
Ах да, ошибки во время компиляции. Ну, эликсир компилируется, так что всегда пожалуйста: в последнем примере имплементация протокола будет такая:
@compile {:inline, sort: 2}
def sort(e1, e2) do
[e1, e2]
|> Enum.map(&Comparable.impl_for!(&1).term(&1))
|> Enum.reduce(&:</2)
end
Ух ты, как мы прямо на лету ТЗ-то меняем, любо-дорого смотреть. А ничё, что не все языки — компилируемые?
Почему же на лету. Это уже упоминалось в дискуссии. Вы пропустили?
Нет только те, которые хотят сравниваться. Ну да ладно, я и для любых могу (идея позаимствована у Армстронга и Вирдинга) — оператор сравнения работает из коробки для всех типов данных языка:
Меня не имнтересует сравнение для ограниченного набора типов данных. Меня интересует сравнение для вообще всех сравниваемых типов данных.
ruby, классическая Dependency Injection, пример из моего первого комментария.
Это здорово, но откуда ваш comparator знает как сравнивать эти самые о1 и о2? Откуда функция вызывающая comparator знает сколько у него входных параметров и какого типа результат? Это где-то описано или я могу в качестве comparator'a запихнуть всё что угодно?
Пример поизящнее: map-sort из elixir. Инъекция кода, изменение AST.
Откуда я знаю как должен выглядеть инъектируемый код? Сколько параметров он должен иметь? Что возвращать? Это где-то описано? Чем это описание принципиально отличается от интерфейса?
Меня не имнтересует сравнение для ограниченного набора типов данных. Меня интересует сравнение для вообще всех сравниваемых типов данных.
А это вообще все типы данных. Эрланг — функциональный язык, в нем нет «произвольных объектов». Интересует вас это, или нет (на самом деле это только демонстрирует ширину вашего кругозора), — мне фиолетово, не я просил примеров «на любом удобном вам языке и без интерфейсов».
Это уже упоминалось в дискуссии.
В дискуссии между кем и кем? Я не читаю побочные ветки, и вы совершенно не вправе ожидать от меня, что я стану тратить на это время.
откуда ваш comparator знает как сравнивать эти самые о1 и о2?
Вы его передаете при вызове метода. Передайте тот, который знает. А лучше, почитайте что-нибудь про DI в целом.
Откуда я знаю как должен выглядеть инъектируемый код?
Да вам это и не нужно, главное, что компилятор в курсе.
Что возвращать?
Код никому не обязан что-то возвращать.
Чем это описание принципиально отличается от интерфейса?
Тем, что оно — одно из великого множества вариантов, тем, что от модуля, который зовет use
не требуется никаких имплементаций, тем, что весь бойлерплейт, если он есть, можно заинжектить.
А это вообще все типы данных. Эрланг — функциональный язык, в нем нет «произвольных объектов». Интересует вас это, или нет (на самом деле это только демонстрирует ширину вашего кругозора), — мне фиолетово, не я просил примеров «на любом удобном вам языке и без интерфейсов».
Это здорово. То есть если кому-то нужны эти самые произволные объекты, то он должен про них забыть только потому что вам не нравяться интерфейсы?
В дискуссии между кем и кем? Я не читаю побочные ветки, и вы совершенно не вправе ожидать от меня, что я стану тратить на это время.
Ну так а я дискутирую здесь не только с вами, но и с другими людьми.
Вы его передаете при вызове метода. Передайте тот, который знает. А лучше, почитайте что-нибудь про DI в целом.
То естъ вы точно так же предлагаете «скинуть половину работы на пользователя»? Подождите, но разве это не было одним из пунктов вашей критики в сторону решения с интерфейсами?
Откуда я знаю как должен выглядеть copmarator? что бдует если я передам функцию с тремя входными параметрами, которая возвращает boolean?
Да вам это и не нужно, главное, что компилятор в курсе.
В смысле мне это не нужно? Я могу инъкетировать абсолютно что угодно и ваш пример будет работать?
Ксатати а что будет если два человека инъектируют две разные имплементации для сравнения данных одного типа? Будет ошибка при компиляции? При выполнении? Будет использоваться первый или последний?
Код никому не обязан что-то возвращать.
Как тогда узнать результат сравнения?
Тем, что оно — одно из великого множества вариантов, тем, что от модуля, который зовет use не требуется никаких имплементаций, тем, что весь бойлерплейт, если он есть, можно заинжектить.
А у интерфейсов нет множества вариантов? Про абстрактные классы вы ничего не слышали? Инъекция в принципе не может работать вместе с интерфейсами?
П.С. И самое главное «простейшего метода» я так и не вижу. Я точно так же вижу достаточно сложную конструкцию, котороая точно так же сваливает кучу работы на пользователя. Да ещё и требует иъекций и/или DI.
Я не пишу на языках, которые вынуждали бы меня постоянно чувствовать себя удаляющим гланды проктологом.
То есть вы правда считаете, что иметь возможность хранить в каком-то одном списке сущности разных типов только на том основании, что у них всех есть атрибут "дата" — это нормально?
Я правда считаю (как и все нормальные люди, не ужаленные хайпом по строгой типизации), что хранить в каком-то одном списке сущности разных типов — абсолютно нормально, даже если у них вообще нет ничего общего.
Так же считают авторы всех column-based и NoSQL баз данных, ивентлогов, мессаджброкеров, любого GUI, включая браузеры, и вообще примерно всего в мире софта, которым люди пользуются, а не показывают на закрытых конференциях для избранных.
любого GUI
А с ним-то что?
С ним то, что любой простой layout — это список, который в подавляющем большинстве случаев умеет разные типы.
С ним то, что любой простой layout — это список, который в подавляющем большинстве случаев умеет разные типы.
Разные типы или абсолютно произвольные типы?
Потому что по моему опыту даже в GUI у всех типов в списке обычно есть либо базовый класс, либо общий интерфейс, либо хотя бы одни и те же методы/проперти.
Мне второй подход симпатичнее, хотя и с тайп-классами это не так убого, как с интерфейсами в ООП.
Ну да, я в курсе, что это можно имплементировать с нуля (причем вообще как угодно). И вообще, в этой конкретной ветке я (как это ни странно :)) вообще не гнал на типы, я всего лишь сказал, что хранить разные типы в списке — нормально.
Но тут, как обычно, выяснилось, что что такое «разные типы» — каждый понимал по своему: от радикального ООП от Kanut
по моему опыту даже в GUI у всех типов в списке обычно есть либо базовый класс, либо общий интерфейс
GTK
, так, просто например, — написан на C
. Там нет классов и интерфейсов.
до радикального type everything от вас
class Widget a => TextBox a where ...
class TextBox a => TextEdit a where ...
А ведь почти все, например, системные утилиты в гуях — чуть ли не рефлекшеном ходят по свойствам того, что им попалось, и достают оттуда все подряд. Так в 95 венде делал EventLog (или как он там назывался) — так в современных линуксах делают графические оболочки для systemd
. Чистая магия.
а есть сравнение того, что возвращает условная getStartTime.
Да. Но это как раз то, что нужно в данном случае.
Вы не сравниваете исходные объекты
Ну а для каких объектов может быть сравнение именно "исходных объектов", а не каких-то их проекций, или вообще левых сущностей? По-моему, оно остаётся таким только для целых чисел (и их проекций 1:1, вроде дат). Уже для плавучих мы имеем выбор между ordered/unordered и total.
А дальше? Точки? Можно упорядочивать по ax+by с любыми a и b, а можно ещё и проецировать на квадраты. Работников? По фамилии, имени, отчеству, номеру паспорта, ИНН, дате рождения, в любых комбинациях. Что дальше?
Вы знаете заметные классы (в смысле общего рассуждения) таких объектов, чтобы для них сравнение объектов "в себе" имело важный смысл и превосходило по значимости все альтернативные критерии сравнения?
Э-кхм…
— Верно, — сказал Чапаев, с силой проводя щеткой по спутанным конским волосам, — умею. А потом как дать из пулемета…
— Но мне кажется, — сказал я, — что я и могу.
— Попробуй.
— Хорошо, — сказал я. — Я тоже задам последовательность вопросов о местоположении.
— Задавай, задавай, — пробормотал Чапаев.
— Начнем по порядку. Вот вы расчесываете лошадь. А где находится эта лошадь?
Чапаев посмотрел на меня с изумлением.
— Ты что, Петька, совсем охренел?
— Прошу прощения?
— Вот она.
вот я определил сравнение. Тут — по x, тут — по y, а тут — по порядку установки на карту.
Вот оно, определено.
> или, ну, вот из моего текущего проекта
У меня не скоро будет время грок это всё вот на неосвоенном языке, поэтому, если хотите продолжения дискуссии не через пару месяцев, то расшифруйте.
вот я определил сравнение. Тут — по x, тут — по y, а тут — по порядку установки на карту.
Вот оно, определено.
Ну это же не порядок на самих объектах, а порядок на некоторой их проекции.
У меня не скоро будет время грок это всё вот на неосвоенном языке, поэтому, если хотите продолжения дискуссии не через пару месяцев, то расшифруйте.
Я не Дедфуд, но расшифрую. deriving Ord
позволяет автоматически вывести порядок для типа, если для всех его составляющих определён порядок. Сам выводимый порядок является, условно говоря, лексикографическим: два значения этого типа сравниваются покомпонентно в порядке, перечисленном в определении типа.
С какой радости модель должна отвечать за данные, и еще немножко за сравнивание? А что если я хочу научить чужой класс сравниваться? Аспекты, рефлекшн, магия?Если сравнение целиком и полностью определяется данными (т.е. вы уверены, что не возникнет ситуации, когда изменение логики сравнение будет вызвано не изменениями данных), то интерфейс Comparable не нарушает SRP.
Если же есть значимая вероятность, что логика сравнения может поменяться не в связи с изменениями данных, то тут действительно будет нарушение SRP и лучше сделать отдельный Comparator.
Условно: Integer implements Comparable — это ОК. User implements Comparable — скорее всего не ок, т.к. велика вероятность что мы захотим в разных ситуациях сравнивать пользователей по разным полям, и даже сравнение по-умолчанию вполне может меняться без изменения данных.
Integer implements Comparable — это ОК
А потом я решу написать библиотеку, которая умеет неограниченный сверху BigInt
, и она будет прекрасна, вот только сравнивать с встроенным Integer мне придется с привлечением бубна.
Я уже прямо чувствую, как в воздухе запахло перегрузкой операторов, кострами, каменными наконечниками стрел и пещерами.
То есть именно в случае с BigInteger именно этой проблемы у вас не будет:)
если мы говорим про Comparable
из java
Нет, в этой ветке мы говорим о том, что интерфейсы в целом, равно как и Comparable
из java, — никому не нужная сущность, появившаяся оттого, что авторы языка плохо умели в проектирование языков.
Джаву и шарп я как раз приводил в пример костыльного, нерабочего решения, к тому же — нарушающего SRP. Если нужно уметь сравнивать объекты только одного типа — даже простой метод на объекте, формирующий то, что умеет сравниваться из коробки (беззнаковое целое, например) — был бы уместнее (и быстрее).
Но теперь я вижу, что у вас просто какое-то свое представление о SRP, ибо как можно аргументируя нарушения SRP ссылаться на рефлекшен, аспекты и перегрузку операторов я не понимаю. Это вообще ортогональные друг другу понятия.
2) Как параллельная разработка влияет? Если вы выделяете код в библиотеку и сторонняя команда её использует, то им нет разницы, SomeCoolManager — это интерфейс или класс. Это бы противоречило сути интерфейсов.
1) У вас ЯП не поддерживает моки классов?
Чтобы сделать мок класса этот класс сначала должен быть в наличии. И как бы если ещё в каких-нибудь юнит-тестах с мока работать более-менее удобно, то в остальных случая не особо.
Как параллельная разработка влияет? Если вы выделяете код в библиотеку и сторонняя команда её использует, то им нет разницы, SomeCoolManager — это интерфейс или класс. Это бы противоречило сути интерфейсов.
Как раз таки разница интерфейс или класс в таком случае очень большая. Потому что если у меня прописан класс, то я могу использовать только этот класс. А если прописан интерфейс, то я могу использовать любой класс его имплементирующий.
И проблема как раз в том что я могу «выделить интерфейс» но не дать никакой имплементации и стороняя команда уже может начинать имплементировать свои вещи ориентиpуясь на этот интерфейс. А я буду параллельно писать свою имплементацию под него.
Потому что если у меня прописан класс, то я могу использовать только этот класс. А если прописан интерфейс, то я могу использовать любой класс его имплементирующий.Это не имеет смысла в контексте существования SomeCoolManager и SomeCoolManagerImpl, который, судя по бессмысленному суффиксу Impl, принципиально единственный наследник интерфейса, кроме моков (но тесты не должны управлять кодом). У класса уже есть интерфейс. Вы можете использовать интерфейс класса SomeCoolManager невзирая на то, есть ли там под капотом имплементация или нет. Клиентский код от этого факта абстрагирован.
Я говорю о ЯП вроде C#, Java, PHP, где где субтипизация только явная. В более структурно-типизированных ЯП с интерфейсами-протоколами как Go, Typescript, это имеет больше смысла.
В остальном, это не особо резонирует с моим опытом. Возможно, в вашей среде это имеет больше смысла (в тех интерфейсах, которые отделяются от основного кода и используются другими). Но, по моим наблюдениям, многие уже издавна стали выделять интерфейсы из классов просто потому что использование интерфейсов вместо классов само по себе ведёт к большей гибкости. Скорее к иллюзии гибкости и бесполезной церемониальности.
Это не имеет смысла в контексте существования SomeCoolManager и SomeCoolManagerImpl, который, судя по бессмысленному суффиксу Impl, единственный наследник интерфейса.
Занчит возможно в данном конкретном случае интерфейс и не нужен. Я же вроде нигде не писал что интерфейсы нужны абсолютно везде и всегда.
Возможно, в вашей среде это имеет больше смысла (в тех интерфейсах, где смысл есть). Но по моим наблюдениям люди уже издавна стали выделять интерфейсы из классов просто потому что это использование интерфейсов сама по себе ведёт к большей гибкости.
Ну лично у меня «внутри» проектов/библиотек/модулей интерфейсы используются редко. Но тут каждый сам решает для себя что ему удобнее.
Банковское приложение
Калькулятор
Программа для распознавания растений
Мобильный планетарий
мой список
1./2./3./4. и 7. — да
Для создания заметок использую OneNote, он сейчас отлично синхронизируется с десктопной версией, а возможностей у него выше крыши.
Из неупомянутого — офис (в основном — просмотр документов), сканирование/распознавание, почта, калькулятор, мобильная точка доступа, читалка, погода, банковское приложение, фонарик и казуальные игры.
Калькулятор, фонарик и погода — согласен
По роду работы есть необходимость сканировать и распознавать фрагменты текста.
Наиболее удобный для этих целей инструмент — смартфон.
По востребованности у меня это фича номер один (после основных функций телефона, естественно :) А уже намного потом — калькулятор, фонарик и погода.
Не надо портить инженерам десктопы своими мобильными решениями, одумайтесь