Pull to refresh
4
0.2
Tony Soloviev @Tony-Sol

Dev-To-Ops transworker

Send message

По сравнению с alacritty поддерживает больше escape-последовательностей, например alacritty не умел (раньше, как сейчас не знаю) в blinking text, а для меня критично.

По сравнению с kitty - конфигурация на lua сильно проще и удобнее, чем на conf-файлах

Как по мне, так все отдельные эмуляторы терминала на electron'е (или аналоге) от лукавого.

На текущий момент пользуюсь wezterm с синхронизацией настроек через git - пока что лучший из всех что я пробовал (alacritty, kitty, konsole, iterm2, warp, tabby, hyper)

Профсоюз имеет кассу, которую наполняют взносами.

Вот только в эту сторону и видел движение денежных потоков - от работников в профсоюз, но никогда в обратную

Так это находится в FtpStorage, который часть библиотеки

В написанных примерах, это не часть библиотеки

Ну а тогда зачем нам StoreException, какая от него польза?

Как раз та, что внутри приложения, код точно знает какое исключение будет при работе с хранилищем.

Также в этом случае в интерфейсе не задокументировано, что может быть в getPrevious()

И не должно быть более того, что предоставляет интерфейс \Throwable - задача разбираться с внутренними исключениями библиотек лежит на обертках этих библиотек - в примерах это AbstractStorage/LocalStorage/FtpStorage

Там где catch (NetworkException $t) можно ретраить, уведомлять, что угодно делать. Можно прокидывать его 3м аргументом во внутренее исключение и уровнем выше делать getPrevious() и так далее.

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

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

namespace App\Infra\Storage

interface Storage { 
    /**
     * @throws StoreException
     */
    public function store(): void
}

abstract class AbstractStorage implements Storage {
    /**
     * @throws StoreException
     */
    abstract public function store(): void;
}

class StoreException extends RuntimeException { ... }

class LocalStorage extends AbstractStorage {
    public function __construct(\ExternalImplLocalStorage $externalClass) {
        $this->smth = $externalClass;
    }
    public function store(): void {
        try {
            ...
        } catch (\Throwable $t) {
            ...
            throw new StoreException(1, ..., $t);
        }
    }
}
class FtpStorage extends AbstractStorage {
    public function __construct(\ExternalImplFtpStorage $externalClass) {
        $this->smth = $externalClass;
    }
    public function store(): void {
        try {
            ...
        } catch (NetworkException $t) {
            ...
        } catch (\Throwable $t) {
            ...
            throw new StoreException(1, ..., $t);
        }
    }
}

либо

namespace App\Infra\Storage

interface Storage { 
    /**
     * @throws StoreException
     */
    public function store(): void
}

class SomeService {
    public function __construct(Storage $engine) {
        $this->engine = $engine;
    }
    /**
     * @throws StoreException
     */
    public function store(): void {
        ... 
        $this->engine->store();
        ...
    }
}

class StoreException extends RuntimeException { ... }

class LocalStorage extends \ExternalImplLocalStorage implements Storage {
    public function store(): void {
        try {
            ...
        } catch (\Throwable $t) {
            ...
            throw new StoreException("...", 1, $t);
        }
    }
}
class FtpStorage extends \ExternalImplFtpStorage implements Storage {
    public function store(): void {
        try {
            ...
        } catch (NetworkException $t) {
            ...
        } catch (\Throwable $t) {
            ...
            throw new StoreException("...", 1, $t);
        }
    }
}

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

Под такого рода зависимостями понимаются любые зависимости, реализующие "один из" вариантов - как в примере реализация сохранения чего либо (local/ftp/webdav/s3/etc.), реализация брокера сообщений (rabbit/kafka/etc.), реализации отправки сообщений (slack/telegram/sms/email/etc.), реализации интеграций с платежными системами и так далее.

Но там есть небольшая проблема которая решится через 20 лет.

20 лет назад также говорили :(

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

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

Когда вы один интерфейс растащили по 5 вы убили высокоуровневую абстракцию.

Не совсем понял что здесь подразумевается, но если имеется ввиду, что «если сделать из 1 интерфейса на 5 методов, 5 интерфейсов по 1 методу, то это убьет высокоуровневую абстракцию», то в корне с этим не согласен

3: info, warning, error

Кажется это покрывает большую часть потребностей

Не настолько сложно, все знакомые php разработчики, начиная с мидла, параллельно умеют/учатся писать на go

TeamCity не далеко от Jenkins, там тоже DSL, и что-то сложное на нем подчас просто не напишешь

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

На одной из работ использовали довольно удобную (имхо) иерархию классов (и тут ООП, ога), что позволило добавлять проекты в CI/CD пайплайны буквально одной строкой.

CI/CD тут уже много шишек набито, и думаю что лучше GitLab ничего нет

свой голос отдаю teamcity

Когда информационный поток огромен, большая часть таких (имею ввиду околоновостных или из категории "наболело") читаются просто по-диагонали, потому и не замечаем

А как же король своего времени Symbian OS. Для тех лет - была хорошая операционка как раз для смартфонов/"бизнес-коммуникаторов".

можно, но не нужно

ИМХО, если разраб сумел освоить compose и/или swarm, то сможет и k8s на уровне, достаточно для локальной разработки/базового понимания как работает его приложение.

Кубер требует достаточной квалификации и хотя бы одного выделенного девопса

Это довольно спорно и сильно зависит от процессов.

начиная с какого масштаба инсталляции Вы считаете оправданным применение k8s

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

Далее, сугубо мое ИМХО и только в рамках web разработки: Так, например, считаю что k8s оправдан практически всегда, когда речь идет о развертывании собственного продукта. От ботика в телеграмме, до соцсети. ("Сайтик на тильде" в моем представлении продуктом не является, продукт там это сама тильда и я почти уверен, что под капотом там тоже кубер).

Ведь за абстрактным k8s может быть много реализаций - это может быть single node инсталяция (вон k3s позволяет в пару команд организовать решение), свой полноценный кластер или облачный кубер.

В этом и вся его прелесть, что сегодня, например, mvp вашего сервиса, внутри k3s на одной виртуалке, а завтра в полноценном кластере в облаках. При этом со стороны сборки/развертывания приложения скорее всего практически ничего не меняется - правильно написанный манифест (helm-чарт/helmfile/helmwave.yml/werf.yaml - тысячи их) почти наверняка будет работать.

Kubernetes - просто еще один инструмент, привносящий слой абстракции, а как говорится:

Любую проблему можно решить введением новой абстракции. За исключением проблемы чрезмерного количества абстракций.

Для кого-то - серебряная пуля (9000 stateless микросервисов с rest api по 3.5 эндпоинта), для кого-то - сущий кошмар (базы данных в кубах это ОЧЕНЬ больно)

Контейнерной виртуализацией. Контейнеризация это тоже виртуализация, просто на другом уровне абстракции - не вне ОС, а внутри нее.

Иронично, ведь я работал во вконтактике как раз в devops команде сопровождения кубера) Да, это было оправдано, но и на проектах кратно меньше, тоже предпочел бы кубер альтернативам типа swarm

У аппимаджей и флатпаклв этого всего нет, есть только изоляция

Только для случая, например "пакет A использует openssl@1, а пакет B - openssl@3".

Изоляцию уровня "веб-серверу A я доверяю 0.5 cpu и запрещаю ходить в файловую систему хоста, а веб-серверу B я разрешаю ходить за данными на диск, но только сюда и только для чтения" средствами appimage/flatpack/итд не обеспечить - потому что это разные абстракции и разные изоляции.

Изоляция, про которую docker, можно сделать и нативными средствами linux (на хабре есть хороший цикл статей про это https://habr.com/ru/articles/458462/)

1
23 ...

Information

Rating
2,316-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity

Specialization

Backend Developer, DevOps
Senior
From 6,000 $
PHP
Docker
CI/CD
Golang
GitLab
Ansible
SRE
DevOps
Git
Kubernetes