Pull to refresh
129
0
Григорий Демченко @gridem

Software Engineer

Send message

Каждый раз прикольно видеть единицу измерения кВт/ч, зная, что Вт = Дж/с. По сути, правильная единица - это Дж, или МДж, т.к. кВт * ч = кДж * ч / с = 3.6 МДж. Но всюду используют кВт*ч (потому что счета за электричество?)

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

Полезный совет! А главное - универсальный, работает не только с API, но и с любыми другими вещами, которые сложно изменить просто захотев.

Статья отличная!

Определение пользовательской функции swap – частый случай такой ошибки.

Интересно, а что делать в случае std::hash? Ведь для этого нельзя написать using, когда используешь std::unordered_map, ведь это определение находится в типах, а не реализации. При этом хочется иметь именно обобщенное написание кода.

Пока на препроцессоре приходится делать то, что нельзя никакими другими вещами, его нужно развивать и дополнять. Говорить про то, что препроцессор лучше оставить таким, какой есть - очень странное утверждение. Хочется тогда узнать, а что взамен? Если взамен - ничего, то это самый плохой ответ, который может быть. Лучше пойти навстречу пожеланиям и добавить улучшений в него.

То, что есть в boost PP - это такие костыли и грабли, про которые лучше не вспоминать.

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

Потому что создается временный объект и сразу запускается. Возвращается тип Task, и после этого временный объект со всеми захваченными переменными самоуничтожается. А сопрограмма еще даже не была запущена.

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

Более того, почему это является развитием, еще можно понять. Но почему устойчивым - так же невозможно. В тексте об этом ни слова.

Это такая современная журналистика, или таков пресс релиз от mail.ru? Или оба два?

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

По какой-то неведомой причине фононы (квазичастицы) превратились в фотоны. Вот, что бывает, когда новость интерпретируют авторы, крайне далекие от предметной области.

О сколько нам открытий чудных

Готовят просвещенья дух

И опыт, сын ошибок трудных,

И гений, парадоксов друг,

И случай, бог изобретатель.

Это не является GOTO. С тем же успехом можно записать break и return как GOTO. Главное отличие — GOTO требует указание точного места, куда передать управление. Ни исключение, ни конструкции типа return этого не требуют.

Это была шутка юмора.

Позволю себе покритиковать полученный результат. Приведенный код все еще достаточно низкого качества для современного С++.


Во-первых, колбеки так уже никто не пишет. Желательно вместо std::string (*cb)(Descriptor, std::string) писать std::function<std::string(Descriptor, std::string)>. Однако тут тоже непонятно, что такое std::string в аргументе.


Если же мы говорим про асинхронный код, то так писать — это анахронизм. Лучше всего использовать future или корутины.


Далее, Descriptor — это скорее всего сетевой дескриптор. В таком случае не стоит использовать напрямую низкоуровневые примитивы в логике, а стоит их обернуть хотя бы в Socket. Смешивать высокоуровневую логику и низкоуровневые примитивы — признак плохого дизайна и мешанины.


Ну и напоследок, смешение стилей именования переменных: через _ и camelCase.

true, false и null — это optional<bool>

Проблема с исключениями в том, что:


  1. Жрут немало памяти, даже если их не используешь.
  2. Слишком большие расходы при бросании. Мало того, что проходится по таблицам, так и еще берутся блокировки на эти таблицы, причем не на чтения, а эксклюзивные. Таким образом, в многопоточном коде внезапно исключения из одного потока влияют на исключения в другом.

Да и вообще, сама идея блокировок при однопоточном характере исключений — крайне странно и выглядит как баг.

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

Я не делал подобных предположений.


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

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


Имеет смысл посмотреть реализацию std::function, а также посмотреть, что такое type erasure.

Приведу пример того, как я бы сделал изначально:


class Filter {
public:
    virtual ~Filter() = default;
    virtual bool matches(const Txn& txn) const = 0;
};

template<typename Tx>
class TxFilter : public Filter {
public:
    virtual bool matchesTx(const Tx& txn) const = 0;

    bool matches(const Txn& txn) const override {
        return my::visit<Tx>(txn, [](const auto& txn) {
            return matchesTx(txn);
        });
    }
};

class LargeAmountFilter : public Filter {
    bool matches(const Txn& txn) const override {
        return txn.amount() > Money::from_dollars(10'000);
    }
};

class DifferentCustomerFilter : public TxFilter<DepositTxn> {
    bool matchesTx(const DepositTxn& dtxn) const override {
        return dtxn.name_of_customer() != dtxn.name_on_account();
    }
};

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


Вся проблема автора в том, что:


  1. Не используются все возможности языка. Использование шаблонов позволяет существенно сократить код и переиспользовать возможности без засорения интерфейса и без потери гибкости. Если в будущем появятся новые типы транзакций, то TxFilter автоматически добавит нужную реализацию путем использования нужного шаблона. Тот мусор, который приведен в статье в виде do_casewise не расширяем и громоздок.
  2. Не стоит увлекаться догматами. Я часто слышу, что "не надо использовать X, Y". Однако что дается в замен? Обычно обходятся общими фразами. Но жизнь — она более многогранна. И надо пытаться пользоваться всеми возможностями и выразительностью языка. Профессионал знает, как и в каких дозах стоит использовать тот или иной приём. Правило Скотта Майерса, конечно, звучит замечательно, только сам он не писал продакшен кода с миллионами строк кода, поэтому при всём уважении, я отношусь к таким советам несколько скептически, хоть и понимаю важность и ценность. Я бы переформулировать так: стараться использовать по умолчанию подход "Скотта Майерса", однако если есть весомые основания отклонения, то они должны быть обозначены прям в коде и объяснены. С этим советом я могу согласиться, т.к. это не догмат, а вполне вменяемая рекомендация.

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

Еще полезно знать, что для чисел с плавающей точкой данные утверждения бывают истины:


  1. a + b — b != a
  2. a * b / b != a
  3. (a + b) + c != a + (b + c)
    И т.д.

Под v я имел в виду скорость, не потенциал.


v = U = grad S/m = 0

Я не утверждал, что решений не получится. Я утверждал, что v=0 в этом случае, что не является физичным.

Если применить этот подход к стационарному уравнению Шредингера, то мы получим S = const, а значит v = 0. Получается, что частица просто покоится в центре ядра? Это крайне странное поведение частицы.

1
23 ...

Information

Rating
Does not participate
Date of birth
Registered
Activity