Pull to refresh
1
1.1
Вячеслав @xxxphilinxxx

Веб-разработчик

Send message

Есть отличная пара вопросов для самопроверки, сам пользуюсь и рекомендую: что вы знаете о качестве всеобщего голосования и откуда вы это знаете? Если вдруг механизм, лежащий в основе принятия глобальных решений, не справится со своей работой, то это серьезно повышает риск краха всей цивилизации.
Ну и все-таки: кто вопросы будет составлять (пусть отложим очередность) и как минимизировать их влияние на процесс? Для соц. опросов, например, это очень важная тема, т.к. даже формулировки могут с ног на голову переворачивать результаты. Я уж не говорю о злоупотреблениях. В качестве ответа прошу не указывать ИИ, т.к. даже слабой формы ИИ пока еще не создано, а то, что сегодня маркетологами так называется, работает по принципам, похожим на аппроксимацию: "для похожих вопросов чаще всего давали примерно такие ответы, слепим что-то среднее".
Плюс как-то надо учитывать хотя бы образование и контекст: какой смысл задавать вопрос о целесообразности апгрейда модуля БАК или МКС стереотипному дворнику из провинции и какова ценность его ответа по сравнению со специалистом в этой области? Мне вот будет бессмысленно задавать даже такой простой вопрос как "должен ли получать слесарь 1-го разряда больше, чем слесарь 2-го": я банально не в курсе, в какую сторону идет рост квалификации и является первый разряд лучшим или худшим.

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

Ежедневно по тысячам вопросов? Ок, поставим защиту: пусть только какой-то процент охвата будет. Голосуем: помимо прочих, 1млн шахтеров проголосовали, что шахтеры должны получать больше писателей. 1тысяча писателей прогосоловали, что писатели должны получать больше шахтеров. Выплаты писателям, видимо, снизились, часть писателей перешла в шахтеры. Новый цикл: 1млн+500 шахтеров и 500 писателей прогосовали. Ок, поставим защиту: за себя голосовать нельзя. Включаем в цепочку промежуточный узел: скажем, 10тыс поваров, которые сейчас получают больше писателей. 1млн+500 шахтеров проголосовало, что шахтеры должны получать больше поваров. Ок, поставим защиту...

Самое главное: прежде, чем спорить, неплохо бы договориться о терминах: что понимать под "конечной целью" и целью кого: заказчика, потребителя, программиста, мирового сообщества или кого-то еще. Цель - осознать, где и когда остановиться? Дойти до этой точки? А кто принимает решение? Или каким должен быть идеальный продукт в каждом конкретном случае? Разработка плана, как создавать идеальный продукт? Как перейти от зафиксированного продукта к процессу? Каким должен быть идеальный процесс разработки?

Конечная цель программирования - сам текст программы. Это настолько очевидно, что перестаёт восприниматься как конечная цель

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

Сначала по пирамидке: как у вас Business не оказался основанием? Уровень должен быть самодостаточным, т.е. иметь ценность без верхних, иначе это просто цепочка промежуточных этапов. Нельзя ведь начинать писать код, если не сформулированы хоть какие-то требования? Значит, ниже надо положить постановку задачи. Постановка задачи тоже в свою очередь чем-то будет заблокирована: например, бюджетом и подбором персонала, и так далее. А просто написанный, но неиспользуемый код сам по себе не имеет ценности, только потенциал.

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

Для первого варианта положим в основу банальную практику. Хочу, скажем, IDE-шку получше изучить, библиотеку или язык. Для такого проекта у меня будет только Write в ваших терминах: мне даже критические ошибки в этом коде необязательно исправлять, это просто черновик. Никаких compile, run, bisuness, test, modify тут не будет. Да, write тут станет ценным уровнем, хотя выше я утверждал обратное, но только из-за специальной цели всего действа.

Возьмем прикладную утилитку личного пользования, а то и одноразовую. Ее уже надо собрать, запустить, но test, modify, business не будет. Возьмем инди-игрушку: тесты могут быть, могут нет, зато появляются производительность и бизнес. Построитель отчетов для внутренннего пользователя компании: тесты обязательны, это важная информация, зато производительность может быть выкинута, как и легкая модификация. Фреймворк: тесты, производительность, читаемость, документация, но может не быть business и легкой модификации. Ключевой сервис компании: тесты, легкая модификация, производительность. Открытое ПО - необходим выстроенный и поддерживаемый процесс коллективного принятия решений и внесения изменений; кстати, тут появляется "процесс" помимо продукта и исходника.

Возьмем любой программный компонент: при наличии доступного уже готового софта выкидываем (!) write, compile, даже run в случае стороннего сервиса. Можно утратить исходники и остаться с бережно отныне хранимым бинарником, который будет годами успешно работать, процеденты такие есть. А то и вовсе все сделают другим способом - механикой, электрикой вместо электроники или еще как-то. Задача решается без написания единой строчки кода, почти что идеал; круче только удалением.

Для специальных случаев добавим всякие интересные условия типа работы в масштабе миллиардов пользователей, в realtime, в жестких ограничениях по CPU/RAM/IO или обязательного использования особенностей конкретного железа, без которых все опять-таки не будет иметь никакого смысла.

Легко заметить, что ни один из ваших пунктов не оказался сразу во всех перечисленных сценариях - правда, занятно? Кстати, производительность и читаемость/поддерживаемость обычно являются взаимоисключающими, их вместе не запихнешь. Получается, что универсальной схемы развития идеального программного продукта попросту не существует, есть лишь цели на конкретные случаи со своими функциональными и нефункциональными требованиями к готовому продукту, исходникам и рабочим процессам. Как только все требования легли в основание, можно поверх что-то строить, но не линейное, а очевидно (хехе) многовекторное, больше похожее на розу ветров. А раз уникальное и многовекторное - значит, единой цели не может быть.

P.S. есть интересные эксперименты (например, Вселенная-25), косвенно связанные с пирамидой Маслоу, показывающие-таки наличие ее верхней границы.

Ну, фулстек - это все еще разработчик ПО, цельное понятие, и его обязанности мало отличаются от обязанностей более узких специалистов; а вот с аналитикой, контролем качества, менеджментом и т.д. уже скрестить сложнее. Вообще по ТК за совмещение должностей даже без увеличения рабочих часов полагается доплата, если, конечно, должность не прописана как "делать всё и вся" и работник на это согласился.

А теперь воплотим абстракции в реальность, но пойдем не идеальным, а ИМХО более вероятным путем.
Раз инженеры получают право голоса, этот голос должен стать частью процесса, а не хватанием за руку в последний момент, следовательно, у инженера появляются новые обязанности, при этом навыки управленца+PO+архитектора в комплекте не идут. Добавим эффективное самоуправление на уровне команды - уже минимум три роли с тимлидом и получаем требования как минимум на ведущего специалиста. Опционально добавим девопс без системных администраторов, работу линией техподдержки, дежурства, прочие процессуальные события, так что в итоге на работу собственно исходным инженером остается один-два дня в неделю. Добавим плоскую структуру компании, так что эти требования автоматически применяются абсолютно ко всем инженерам. Разумеется, бизнесу очень выгодно, когда в проекте есть люди "и швец, и жнец, и на дуде игрец", да еще и инициативные, но где набрать столько универсальных пассионариев, что делать с остальными и можно ли все еще называть такую позицию просто инженером?
Ну и пара очевидностей. Первая: если менеджер не интересуется мнением специалистов, допускает тупики, игнорирует смежные проекты, не имеет долгосрочных планов, то это некомпетентный менеджер. Вторая: стиль КД даже в тексте статьи очень часто соседствует со словом "стартап", а в стартапах так-то традиционный уклад с несколькими уровнями менеджеров встречается все же нечасто.

Инфляцию доллара, думается, еще надо учесть. Доллар в рублях стал дороже (курс вырос), при этом еще и его покупательная способность заметно упала: за 4 года набежало около 20%, так что долларов 4-летней давности в пересчете будет всего $1686 / 1.2 = $1405. Отрицательный рост, как нынче говорят.

Сколько вижу статей про web3, столько не вижу в этом вообще никаких предпосылок "эпохи". И далеко не я один, судя по типичному отсутствию реакции на статью. Мало того, не вижу сервисов, которые бы после переезда на такую платформу стали бы более привлекательными для пользователей, чем существующие реализации. Блокчейн даже для титульного назначения - криптовалют - далеко не идеален, и в итоге, наверное, большинство платежей проходит все-таки через централизованные сервисы, отказ от которых вроде как заявлялся одной из главных целей.
Вот пример с почтой, да? Давайте посмотрим: нельзя общаться с пользователями вне этой системы; а если будет можно, то это будет опять обычная почта. Каждое письмо платное. Зависимость от криптовалюты в основе. Про крайне высокие требования к глобальной инфраструктуре и ресурсам в статье уже написано.

[...] Единственная архитектура для по-настоящему безопасной почты – приложение, развернутое в распределенной сети, со сквозным шифрованием.

А это вообще ложь; выдаем желаемое за действительное. Старое доброе end-to-end шифрование писем с помощью GPG точно так же скроет переписку от почтового сервиса и всех, кто через него получил доступ. Я уж не говорю о собственных почтовых серверах. В распределенной сети, кстати, к зашифрованному письму будет доступ у каждого - минус один шаг и осталось только ключ раздобыть. Или вовсе бери и брутфорси все подряд, с серьезным оборудованием или даже просто наудачу.

Удалить письма нельзя. Утек ключ - как минимум вся прошлая переписка стала доступна кому-то еще в любое время.

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

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

Для точности сравнения: открываются новые выставки, где представлены бумажки с надписями "картина X, размещенная в галерее N, принадлежит господину A", причем, на разных выставках одна и та же картина может быть приписана разным владельцам, создатель бумажки не обязан подтверждать право владения, а стоимость ее едва ли зависит от самой картины. И народ в основной массе ринулся не искусством заниматься, а клепать хоть что-нибудь ради шанса продать бумажку подороже.

Промежуточные суммы вижу, а где хеширование из заголовка? В вычислении ключа этих сумм?

Тут выше упомянули дерево отрезков - вы его фактически и реализовали, просто зафиксировали кол-во уровней на трех (книга/сотни/страницы) и зафиксировали кол-во потомков на третьем уровне на сотне элементов.

А можно было бы просто из "неограниченного числа читателей" вычесть число пользователей, прочитавших столько же страниц, сколько и заданный, но тогда бы не родилась статья :)
По условиям задачи мы не знаем, сколько пользователей прочитало столько же страниц, что и искомый пользователь.

Если хранить счетчик пользователей, не читающих страницу, а уже прочитавших ее, то все как раз становится тривиально: total_book_readers - pages_read_count[current_pages[user_id]-1]. Даже Read станет проще, не нужно будет декрементить предыдущую страницу.

Плюс не более 99 итераций для поиска в users_by_pages , это константа и при расчете сложности она не учитывается.

99 итераций помимо остальных действий для вас несущественны, а в статье 1000 называете уже сильно замедляющими программу, хотя тут всего один порядок разницы.

Получаем тот же O(log N).

Логарифм у вас там в поиске по пользователям, а не по страницам; его, кстати, еще приплюсовать надо. К тому же у меня немного другая математика: если N - кол-во страниц, то кол-во чтений будет (N/100 + 99). Константы убираем и получаем вполне линейную из-за фиксации только на сотнях сложность O(N) безо всяких логарифмов. Вместе с пользователями O(N) + O(log U).

Еще в глаза бросилось, что в функции Read чтение из map "pages_by_users[user_id]" пять раз фигурирует в пределах одной функции, причем дважды по дважды в пределах одной строки. И сотни почему-то int[10], а не вектор, хотя книги ооочень длинными бывают - не встречали, например, "Червя" Джона Маккрея?

Интересно вы собираете свой накопленный опыт копипастом библиотечной документации https://libpqxx.readthedocs.io/en/6.4/a01477.html

Вам про Фому, Вы про Ерему :(
Давайте отделим мух от котлет данные от структур.

Да, если взять json/xml, содержащий древовидные данные, и преобразовать в программные структуры, используя Map и только Map без дополнений и соглашений - это будет древовидное представление древовидных данных. Но у него будет несколько недостатков/особенностей, которых у классического полноценного Tree быть не должно.

  1. Оно не дает инструментов для работы с деревом: хочешь переставлять узлы или даже просто совершать обход - делай это сам. А из дочернего узла к родительскому вообще перейти невозможно - нет ссылки;

  2. Оно не дает никаких гарантий относительно структуры: например, отсутствия циклов или множественных связей между двумя узлами;

  3. Оно позволяет использовать любые типы в качестве узлов, причем даже такие, которые принципиально не могут иметь дочерних узлов: я на это намекал в примере с Map<string, int>. Тип int не является составным, поэтому потребуется, например, дополнительный контейнер;

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

  5. Родительские объекты не имеют собственного значения.

Чуть более сложный случай возьмем: {"root": {"a":1}}. Здесь, очевидно, уже два Map, причем, разных: Map<string, int> для дочернего узла и Map<string, Map<string, int>> для родительского. Их нельзя взять и поменять местами - это разные типы и они не взаимозаменимы. Дочернему нельзя взять и добавить потомков - тип int этого не позволяет. У обоих родительских элементов нет значения; значение есть только у самого последнего потомка - единица.

Разница, которую я пытаюсь объяснить, в том, что даже если представляемые данные являются частным случаем дерева сами по себе (Data ⊂ TreeSet), то комбинация Map, использованных для этого представления, все равно из-за указанных выше причин не способна самостоятельно предоставить полноценную работу ни с общим случаем дерева, ни даже с представленным (Map ! implements TreeInterface) и годится только для ограниченного набора действий и в основном в режиме read-only.

По этой же причине нельзя назвать деревом и обычный массив, хотя он тоже может представлять некоторые древовидные данные с ограниченной функциональностью - например, [[1,2],[3,4]]. Рутовый объект не имеет своего значения, но имеет пару потомков, каждый из которых тоже не имеет своего значения и имеет еще пару потомков типа int.

Вы правы с математической точки зрения, но смотрите не на данные, а на структуры данных, мы же все-таки их обсуждаем: Map без дополнений не способен представить общий случай дерева и дать инструменты для работы с ним, годится только для подмножества (такого же, как и обычный массив). А иначе тогда и NULL надо тоже считать программной реализацией дерева, просто пустого - математически корректно, но совершенно неприменимо.

Так сказать, Map ⊂ Tree, but Map ! implements Tree

Гоняя энтерпрайзные json-ы, я уже и забыл, какой красивой бывает математика. Спасибо, что напомнили *tears* *awe*

Не моя ветка ( :) ), но вот простой пример: {"a":1, "b":2} => map<string, int>. Нет ключевой возможности задать связи между родительскими и дочерними узлами без дополнительного вмешательства - значит, это еще не представление дерева. Возможно, конечно, например, использование дополнительного контейнера или хранение всех связей еще где-то отдельно, но это ведь уже выходит за возможности самого map, т.к. сама по себе эта структура данных все же одноуровневая.

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

Примечательные IT-разработки
прорывные IT-разработки, удивляющие весь мир

Итого:

  • пара-тройка локальных платежных сервисов/маркетплейсов с инновационными QR-кодами

  • игры. Просто "игры" и небольшой список имен

  • есть какие-то планы развития и международные соглашения

  • есть аж несколько случаев использования ИИ

Я что-то упустил?

Ох, свежая мозоль прям заныла. Почти месяц недавно угробил на авторизацию через ну очень кастомный OAuth 1.0a. С дополнительной криптографией. С почти отсутствующей документацией, да еще и содержащей ошибки. Часть параметров в заголовках, часть в теле json-ом. Вместе с документацией выдали исходники каких-то проектов на Vuejs/Java - а там все через Store, с кучей хранимых состояний, - никаких чистых функций, чтобы было хотя бы понятно, что именно передается. Всех и вся проклял на отладке. Часть информации оказалось возможно узнать только через обращение в техподдержку - чуть не десяток раз заходили в тупик и таки задавали вопросы. А, еще и само API имело состояние + короткие пути, так что после одного корректного запроса через выданный проект могло некоторое время успешно отвечать на некорректные запросы (!) из портированной реализации, так что даже просто необходимый тут TDD дал сбой из-за ложно-положительных наборов исходных данных и результатов.

За пренебрежительно-оскорбительный тон, вестимо: "этих айтишников развелось как собак нерезанных", "кодерка", который еще и якобы сколь угодно опытный, а ни в какое сравнение с а-ля product owner не идет.

Information

Rating
1,513-th
Location
Санкт-Петербург и область, Россия
Registered
Activity