• Контравариантные тесты
    0
    В случае следования правилам TDD такая ситуация должна быть невозможной.

    Вы пишете контракт и тесты для внешнего интерфейса, а затем реализующий код. Если вы добавили лишней логики во внутренний код, вы нарушили правила TDD (писать минимальное количество кода, проходящее тесты). И тестировать такой код не нужно, т.к. он не будет влиять на внешний интерфейс.
  • Контравариантные тесты
    0
    Если внутренний метод никак не затрагивает внешний интерфейс, то зачем его тестировать?
  • Необразованная молодёжь
    0
    К сожалению, один. Нормальных вузов действительно мало.
  • DevOps в Райффайзенбанке: фаза полета
    +6
    Согласен. Очередная публикация про DevOps ни о чём.
  • Контравариантные тесты
    0
    Как я понимаю, если сущность может быть использована как самостоятельная единица и может быть повторно использована, тогда она становится компонентой и должна тестироваться отдельно. Если же сущность не может существовать отдельно от внешнего интерфейса или присутствует в единственном экземпляре, то и тестировать её отдельно не стоит.
  • DevOps сейчас — как version control десять лет назад, скоро все там будем
    +1
    Вы правы, я не смотрел видео, не читал книгу, и не собираюсь этого делать. Меня не устраивают предлагаемые вами варианты получения информации: посмотреть часовое видео (со звуком) у меня нет никакой возможности, а книгу вы предлагаете купить в зарубежном магазине.

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

    Теперь понятно, почему при прочтении информации о DevOps у меня складывается ощущение разводки в стиле сетевого маркетинга в его негативном смысле.

    Поэтому я прошу вас не отправлять меня читать книги, от которых меня будет воротить, а в 5-10 предложениях описать своими словами, что вы понимаете под DevOps, для русскоязычной аудитории с учётом нашего менталитета.
  • DevOps сейчас — как version control десять лет назад, скоро все там будем
    +1
    Дело не в опыте, а в том, что сущность DevOps описывают так, как будто это какой-нибудь MLM, бизнес-тренинги или секта. Посмотрите видео, почитайте книгу — слов и философии там много, а смысла мало.

    Хотите, я в нескольких предложениях всё это опишу? Да пожалуйста, вот 4 предложения:

    1. (Зачем это надо) В условиях высокой конкуренции преимущество получают компании, которые способны как можно быстрее выкатывать релизы в ответ на запросы заказчика.

    2. (Чем плох существующий порядок) Существование отдельных команд разработки и внедрения приводит к появлению имеющего значение временного лага как при внедрении, так и при обратной связи.

    3. (Что предлагается) Совмещение функций вышеуказанных команд в одной команде позволит уменьшить временной лаг между разработкой и внедрением.

    4. (Каким образом) Несмотря на то, что совмещение нескольких функций в одном человеке обычно снижает эффективность его труда, развитие современных инструментов разработки [список инструментов] позволяет это автоматизировать, делая труд разработчиков более эффективным.

    Всё остальное — вода и философия.
  • DevOps сейчас — как version control десять лет назад, скоро все там будем
    +1
    Здесь нет противоречений. Разработка DevOps командой обходится дороже, чем классическая, т.к. разработчиков нужно тупо больше. Также за счёт их многостаночности у таких разработчиков ещё и выше аппетиты. Но если эта технология даёт конкуретное преимущество и окупает затраты, в ней есть смысл.
  • Контравариантные тесты
    0
    Выделяете валидатор в отдельный интерфейс IValidator и передаёте его в качестве параметра IWebControllerFactory.Create, делая, таким образом, валидацию и обработку запроса независимыми. Если же валидатор — исключительно внутренняя сущность вебконтроллера, например, из-за его тривиальности, то придётся тестировать его через внешний интерфейс.

    Другой пример — реализация ассоциативного массива. У него простой и понятный внешний интерфейс, но реализация под капотом может быть разная. И тестировать правильность построения массивов с хэшами нет никакого смысла.
  • Контравариантные тесты
    0
    Главный вопрос — зачем? Наличие тестов, покрывающих не только публичный интерфейс, но и реализацию, привязывает разработка к конкретной реализации. Захочется сделать рефакторинг или даже поменять саму реализацию — что тогда делать с тестами?
  • Контравариантные тесты
    0
    > Количество тестов растет лавинообразно, если все тестировать через внешний интерфейс, и не тестировать зависимости по отдельности.

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

    > Не говоря уже о том, что сами тесты становятся сложными.

    Про это уже было написано выше. Сложные тесты — следствие ошибок в проектировании системы, нарушение принципов SOLID.

    > Тестировать через общий интерфейс все еще можно, но уже непрактично.

    В TDD тесты — это, в первую очередь, документация. Тестирование внутренностей в данном случае — это информационный шум.

    Я, впрочем, не являюсь приверженцем TDD в его чистом виде, т.к. принцип написания ровно одного теста за раз и минимального количества кода, проходящего тест, считаю контрпродуктивным — приводящим к постоянным рефакторингам и костылям.

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

    Смогут, просто им на это не дадут времени.

  • DevOps сейчас — как version control десять лет назад, скоро все там будем
    0
    Ничего страшного, пройдёт ещё лет 5-10 и вместо DevOps придумают что-нибудь ещё.
  • Необразованная молодёжь. Ответ бизнеса
    0
    Вот только кросс-платформенность ограничена бибиотеками, а не компилятором. Стандартная бибилиотека — неотъемлимая часть как .NET Framework, так и Java. В случае C++/Pascal вы можете не использовать библиотеку и получить компактный код. В случае C#/Java это невозможно by design, и это нормально.
  • Необразованная молодёжь. Ответ бизнеса
    0
    > Как будто если подобного опыта нет, так научится этому составит много труда…

    Да, это может занять несколько месяцев или даже пару лет. Одних знаний мало, нужен ещё и опыт. Не любой работодатель будет готов столько времени потратить на обучение.
  • Необразованная молодёжь. Ответ бизнеса
    0
    > У нас пару лет примерно такая вакансия и висела, но кандидатов вообще были единицы. Потом мы снизили порог, тк нужно было нанимать побыстрее.

    Тогда вопросов нет. В принципе, научиться писать высокопроизводительный код под конкретной окружение не составит труда, если у кандидата уже есть опыт подобной оптимизации в других областях и понимание теории. Поэтому действительно проще подобрать способного кандидата, чем искать готового.
  • Необразованная молодёжь. Ответ бизнеса
    0
    > Как, например, после чтения дикого сгенерированного кода protobuf выяснилось, что он работал медленнее, чем самописный реккурсивный json-parser.

    Ага, а потом программистов почему-то начинают ругать за написание велосипедов.

    У меня в проекте тоже используется самописный Json-конвертер, и он тоже быстрее библиотечных. И библиотека для распараллеливания у меня тоже своя (накладные расходы в parallel_for уменьшились в разы). Ускорение за счёт снижения универсальности — это нормально.
  • Необразованная молодёжь. Ответ бизнеса
    +2

    Ну тогда я не удивляюсь, почему нормальных кандидатов оказалось только 4. Возможно, требование должно было звучать как "опыт написания высокопроизодительных программ под Linux"


    Для меня "опыт разработки под Linux" — слишком общее понятие, которое не подразумевает знания всей подноготной. То есть использование pthread с pthread_mutex_t — это и есть опыт разработки под Linux. Ну а лезть в недра glibc — это уже не задача рядового С++ программиста.

  • Необразованная молодёжь. Ответ бизнеса
    +1
    И если пишешь на С++, то хорошо бы знать такие нюансы, так же знать сколько аллокаций требуется и памяти, например.

    Увы, этого знать невозможно просто потому, что стандарт языка не определяет детали реализации. В библиотеках MSVC, GCC, Intel реализации могут очень сильно отличаться друг от друга, и это нормально.


    Это совсем базовые вещи для С++

    Не соглашусь с данным утверждением.


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

    Ну так высокопроизводительный код и универсальная STL — вещи малосовместимые.

  • Необразованная молодёжь. Ответ бизнеса
    0
    Там всё веселее. Нормальный мьютекс — это несколько итераций спинлока, и только потом системный вызов. Причём спинлок — это не долбаханье CMPXCHG в цикле (это только будет лочить шину почём зря), а CMPXCHG с паузой в виде какой-нибудь бесполезной операции на 50-100 тактов (длина цикла может быть случайной).
  • Иллюзия скорости
    0
    Не забывайте, что у пользователя может быть очень слабый интернет (мобильный, WiFi в метро и т.д.). В случае статики клиент увидит страницу за один запрос. В случае скриптов это будет уже три запроса (получить HTML, получить файл с JS-скриптом, затем получить данные).

    > Клиент зачастую действительно простаивает.

    Вот именно, что зачастую. Но зачастую — не означает всегда. Вот я, например, люблю открыть сразу 10-20 вкладок, а потом по очереди их читать.
  • Необразованная молодёжь. Ответ бизнеса
    +1
    > Если понимает, то в процессе размышлений должен спросить про примитив уровня ядра вида futex

    Это если пишет под Linux, в Windows же аналога ему нет. Наиболее низкоуровная вещь — CRITICAL_SESSION, но она в точности является мьютексом.
  • Необразованная молодёжь. Ответ бизнеса
    +2
    > Но если пользовался std::map — и не читал исходников и не знает как оно работает, то это пробел.

    Вариант ответа: бинарное дерево без уточнения типа (красно-чёрное, AVL или ещё какое-нибудь) устроит? Главное, что время вставки/удаления/поиска — O(log N), а остальное — детали реализации.

    Ну читать исходники C++ STL — сомнительное удовольствие, дефайн на дефайне и дефайном погоняет, плюс дикий объём кода.
  • «Паттерны» функционального программирования
    0
    > А вот если у вас несколько типов — вам придется, по кодстайлу, дать им более значащие название.

    Иногда это T1 и T2 — всяко лучше, чем TFirstArgument и TSecondArgument.
  • «Паттерны» функционального программирования
    0
    Не преждевременная оптимизация, а вынесение повторяющегося кода в отдельную функцию.

    Truncate(Count) забивает элементы null, а вызываемая в ней приватная функция Truncate() уже корректирует размер массива.
  • «Паттерны» функционального программирования
    +1
    Почему если Count больше или равно количеству элементов в массиве, происходит просто возврат, а не, к примеру, выбрасывается исключение?

    Наверное, потому, что функция называется Truncate? И обычная логика работы этой операции — обрезать лишнее.


    Почему массив называется array, но не передаётся параметром?

    Потому что это метод класса WatchableArray, имеющего поле array и generic параметр TValue.


    Что за тип TValue?

    А вот это уже не имеет значения. Да, у него есть constraints, но если его назвать TTrackableAndWatchableValue вместо просто TValue, то на читаемости кода это скажется отрицательно за счёт увеличения объёма кода и тавтологии (WatchableArray<TTrackableAndWatchableValue>).

  • «Паттерны» функционального программирования
    +2
    > или практика запихивать все самые тривиальные действия в функции с односложным названием.

    Ну если с вашей точки зрения приведённая мной функция выполняет тривиальное действие, и от неё нужно отказаться в пользу вставки её содержимого в вызвающий код, то смысла продолжать спор не вижу.
  • Необразованная молодёжь. Ответ бизнеса
    0
    Судя по быстрому поиску — даже на Андроид/iOS его нет

    Как это нет? Xamarin — это миф?


    Ну и в 512К на embeded он влезет? А в 64К?

    А на Delphi под такое можно писать?

  • «Паттерны» функционального программирования
    +1
    А теперь посмотрите, как ваш код разорвало — читать же неудобно.

    Вот вам кусок реального кода:

            public void Truncate(int Count)
            {
                if (Count >= array.Count)
                    return;
    
                for (int i = Count; i < array.Count; i++)
                {
                    TValue value = array[i];
                    if (value != null)
                    {
                        value.SetUpdated(value);
                        value.Rollback();
                        value.SetParent(null);
                        array[i] = null;
                    }
                }
    
                Truncate();
            }


    Впрочем, да, в проекте больше нет мест, где нельзя обойтись без индекса.
  • «Паттерны» функционального программирования
    +1
    Как же с вами сложно-то. Ну давайте так:

    void Modify<T>(this IList<T> data, Func<T, T> func)
    {
        ... // Some code
    
        for (int i = 0; i < data.Count; i++)
            data[i] = func(data[i]);
    
        ... // Some code
    }
  • «Паттерны» функционального программирования
    0

    Ну вот, например, изменить значения массива:


    void Modify<T>(this IList<T> data, Func<T, T> func)
    {
        for (int i = 0; i < data.Count; i++)
            data[i] = func(data[i]);
    }

    Что тут лучше: i или index? Или нормально, что используется T вместо TItem?

  • «Паттерны» функционального программирования
    0
    Вопрос не в том, избегать индексов или нет. Вопрос в том, какое имя переменной вы выберите для индекса, если его избежать нельзя.
  • Необразованная молодёжь. Ответ бизнеса
    +2
    Почему вы считаете, что C# плохо переносим? Потому что нужен Framework для работы программ? Зато программу даже перекомпилировать не нужно.

    Ну и со скоростью тоже неверно. Во-первых, JIT-компилятор вполне себе генерирует нативный код, и не факт, что хуже, чем компилятор Delphi. Во-вторых, C# не используется для вычислений — какая разница, с какой скоростью работает программа, если она большую часть времени ожидает завершения операций ввода-вывода.
  • Необразованная молодёжь. Ответ бизнеса
    0
    Кстати, да, в C# я уже сталкивался с двумя случаями, когда JIT-компилятор генерил некорректный код, и программа падала.
  • Необразованная молодёжь. Ответ бизнеса
    0
    Я прекрасно понимаю, что имеющимися средствами можно эмулировать подобный функционал. Но с другой стороны, почему нельзя сделать язык более удобным? Вы же, наверняка, не пишете на C++11, а предпочитаете использовать возможности и C++14, и C++17, хотя после C++11 никаких фундаментальных изменений в языке не произошло. Так почему бы и finally не стандартизировать?

    И да, реализация finally через выполнение кода в деструкторе плоха тем, что при возникновения исключения могут быть проблемы.
  • Необразованная молодёжь. Ответ бизнеса
    –1
    Постоянно хочется его использовать, т.к. иначе приходится заворачивать многие вещи в классы и пихать код для finally в деструктор. Пример таких вещей — какие-нибудь системные дескрипторы.
  • Необразованная молодёжь
    0
    Упаковки салфеток по 24 штуки, вычисление цены за единицу в уме (что выгоднее: шоколадки по 48 г или шоколадки по 115 г) и т.д.
  • [CppCon 2017] Бьёрн Страуструп: Изучение и преподавание современного C++
    0
    Учитывая, что в большинстве своём программисты используют именно знаковые типы, утверждение

    > Почти любая арифметика может привести к переполнению

    является верным.
  • Необразованная молодёжь
    0
    Вкладываться нужно хотя бы для расширения кругозора.
  • На шаг ближе к С++20. Итоги встречи в Торонто
    0
    В том-то и прикол, что модуль — это не исходник. Считайте, что модуль — это lib-файл, но с дополнительным экспортом объявлений классов. Хотите открыть исходники — не вопрос, IDE в помощь. Именно так всё выглядит в том же C#, и это удобно и устраивает всех, т.к. необходимости лезть в исходники библиотеки обычно не возникает.