Pull to refresh
124
0
Роман @rrromka

User

Send message

А как такие системы делают резервные копии БД? Просто переиспользуют инструменты, предоставляемые разработчиками БД? Или у них свой подход? Если свой, то как обстоят дела с консистентностью и целостностью данных в резервных копиях?

Как байпасить reCaptcha V3 с помощью Selenium Python?

Ошибка в заголовке, правильно: «Хау ту байпассить reCaptcha V3 уиз Selenium Python?»
Это полный булщита пресс-релиз, а не статья для технического ресурса. Шутка в тему:
Разница между машинным обучением и искусственным интеллектом:
— Если это написано на Python — это скорее всего машинное обучение,
— Если это написано в PowerPoint — это скорее всего искусственный интеллект.


В долгосрочной перспективе с таким подходом ничего хорошего не получится. В случае если у нас есть десятки типов, которые надо как-то регистрировать или сериализовать, то метод, принимающий на вход много разных типов получится похожим на что-то вроде:
function register($input) {
  if ($input instanceof Type1) { /* do smth with Type1 */}
  elseif ($input instanceof Type2) { /* do smth with Type2 */}
  // ...
  elseif ($input instanceof Type999) { /* do smth with Type999 */}
}


В случае с интерфейсом Registerable код будет предельно простым:
function register(Registerable $input) {
  $input.register();
}


В случае если мы не контролируем тип, который надо зарегистрировать, то просто делаем для него обертку:
class RegisterableInt implements Registerable {
  function register(int $input) {
    // do smth with int
  }
}


Нет. В таком случае метод на вход должен принимать тип Registerable или Serializable (названия из головы), а соответствующие классы их должны имплементить.
Ничего другого язык не пропустит и/или не вернёт.
Это понятно. Но на стороне клиентского кода все равно будет неочевидно, что конкретно будет возвращено методом: число или строка, отсюда мой вывод о том, что это не может считаться строгой типизацией.

Кроме того смешивание чисел и строк это явный пример плохого дизайна, как в моем примере выше. И если в случае «Animal|Vehicle» ошибка дизайна очевидна, то чем в таком случае отличается пример с «int|string».
Почитал про юнион типы в PHP 8, в этом посте в качестве примера приводится тип «int|float». Такой тип в сравнении с «int|string» имеет хоть какой-то смысл.

С точки зрения разработчиков PHP это действительно отдельный тип, но с точки зрения здравого смысла это выглядит очень странно. Эту идею можно развить до примерно следующей (псевдокод):
interface Animal
class Cat implements Animal
class Dog implements Animal

interface Vehicle
class Car implements Vehicle
class Moto implements Vehicle

function process(Animal|Vehicle $item)


Очевидно, что метод с такой сигнатурой спроектирован некорректно, не может один метод что-то делать и с животными, и с транспортом. Точно также и «int|string» говорит о некорректном дизайне метода, даже если с точки зрения разработчиков языка это валидная конструкция.
составные типы данных для меня означают
Ясно, понятно.
Главное — определения.
В моем комментарии выше есть определение алгебраического типа данных и структура «int|string» в него не укладывается.
Это ваша личная трактовка, да?

Нет. Давайте начнем отсюда:
По одной из классификаций, языки программирования неформально делятся на сильно и слабо типизированные.

В русскоязычной литературе часто используется термин «строгая типизация»; общепринятый вариант «сильная типизация» используется лишь при противопоставлении «слабой типизации».

Теперь посмотрим сюда:
Стати́ческая типиза́ция — приём, широко используемый в языках программирования, при котором переменная, параметр подпрограммы, возвращаемое значение функции связывается с типом в момент объявления и тип не может быть изменён позже (переменная или параметр будут принимать, а функция — возвращать значения только этого типа)

Определение «int|string» это не тип, это указание на то, что в этом месте будет или тип int, или тип string, что противоречит определению из цитаты выше.
Тут нет возможности выполнить с аргументами, отличными от string или int


То что в качестве аргумента можно передать или int, или string это уже не строгая типизация. При строгой типизации метод или принимает только int, или принимает только string.
Это уже не примитивный, как не крути. Список примитивных типов фиксирован, а тут комплексный тип.

Здесь int примитивный тип. Тип «или int, или строка» не алгебраический, из-за использования инта.

Кому должен? Откуда такие требования?

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

Ключевая фраза здесь: "используется сопоставление с образцом" (другими словами это паттерн матчинг). Если вам заранее неизвестны все классы, то и написать всеобъемлющий паттерн матчинг вы не сможете.

Отсюда никак не следует, что типизация тут нестрогая.

Именно это и следует. Если нет, что что тогда такое для вас строгая типизация?
Вот это: string|int не алгебраический тип данных, а кривой костыль, использование которого говорит о том, что метод, использующий такой тип, спроектирован некорректно.

Во-первых, примитивный тип не может быть алгебраическим.

Во-вторых, для алгебраического типа данных должен определяться интерфейс и несколько классов имплементящих этот интерфейс. При этом очень желательно, чтобы заранее были известны все типы имплементящие этот интерфейс. Это может быть достигнуто, например, фичей языка, которая разрешает создавать классы реализующих этот интерфейс только том же файле, где определен интерфейс.
Также как grep не заменяет python

Некорректно сравнивать консольную утилиту с языком программирования. А вот сравнить две консольных утилиты (clickhouse-client и logscli) можно.

Моё приложение требует только того, чтобы в таблице присутствовали колонки со временем и

Все равно это ограничение, которого нет в clickhouse-client и поэтому мне непонятно зачем нужно использовать программу с такой урезанной функциональностью.

Он заточен под ровно одну задачу — быстро и удобно показать текстовые логи и позволяет их легко и быстро фильтровать.

Можно вот так:
clickhouse-client -q "SELECT * FROM table WHERE column LIKE '%some-search-string%'"

Вроде тоже быстро и удобно. И гораздо гибче.

Он также умеет то, что достаточно сложно сделать одним запросом в ClickHouse, например он умеет показывать контекст вокруг совпадений.

Судя по описанию программа ведь просто достает несколько строк вокруг текущей. Это решение приносит мало пользы. Если в лог пишет много потоков, то вокруг строки с ошибкой могут оказаться записи совершенно несвязанные с текущей строкой. В таком случае лучше писать во все логи параметр типа trace_id, затем найти сначала строку с ошибкой, а потом все записи с тем же trace_id.

Вы смешиваете два разных сценария

Нет.

При этом, для той задачи, которую я описываю в статье (например, как я уже говорил, показ контекста вокруг сообщения, или просто фильтрация по фиксированной строке или по регулярному выражению), использовать clickhouse-client напрямую не слишком удобно

Тоже нет. Я уже написал выше, что контекст в таком виде не добавит полезной информации.
ZhelezoDev все правильно говорит.
Я согласен, что пока логи спокойно помещаются на одну машину и можно использовать обычный tail/grep/less для их просмотра, ничего больше и не требуется, и это справедливо примерно для 90-95% компаний.

Ты невнимательно прочитал комментарий, в нем речь не о хранилище логов, а о просмотрщике.

Если логи лежат в Кликхаусе, то чем твое решение лучше чем стандартный cli-клиент Кликхауса? У последнего как минимум следующие преимущества:
1. нулевая цена разработки и поддержки,
2. поддержка любых схем, а не только той, что захардкожена в твоем приложении,
3. поддержка любых типов запросов, а не только тех, что предусмотрены твоим прложением.

Хочешь сгруппировать логи веб-сервера по коду ответа? Пожалуйста. Хочешь сгруппировать ошибки по типу и посмотреть какие новые ошибки появились с момента последнего релиза? Не вопрос. Хочешь еще каким-то хитрым способом повертеть данными? Все это доступно через стандартный клиент Кликхауса и этого нет logscli.

Если рассматривать это приложение как хеллоу ворлд, написанный, чтобы поизучать го и Кликхаус, то это ок, но это точно не решение для продакшена.
Все-таки я считаю <...> термин «машина» уместнее, я думаю.

Вы можете считать и думать как вам больше нравится, это ваше дело, но у термина finite-state machine есть вполне конкретный однозначный перевод (1, 2, 3). И если вы хотите, чтобы ваш перевод был понятен другим людям, то нужно использовать общеупотребительную терминологию, а не выдумывать свою.
Следующий пример парсера определит переход конечного состояния машины из одного начального состояния в одно из двух конечных

"конечного состояния машины" в оригинале наверное было finite state machine, по-русски это "конечный автомат".

вероятно имеется в виду

Это же просто ваш домысел основанный на вашем опыте. Я на своем опыте часто сталкивался с ошибочным мнением, что внутри Докера используется lxc, поэтому с тем же успехом могу домыслить, что автор имел ввиду именно то, что написал:
в линуксе их аналог – LXC, который и используется в containerd

Если отбросить домыслы и посмотреть на эту фразу логически, то чему она эквивалентна:
— фразе «внутри containerd используется lxc»
— или фразе «containerd и lxc внутри себя используют одни и те же инструменты предоставляемые ядром»?
Сейчас эта проблема больше не повторяется.
1
23 ...

Information

Rating
Does not participate
Location
Москва и Московская обл., Россия
Date of birth
Registered
Activity