На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
  
> Rust vs C++ , очередная шляпа
    Буэнос диас, амигос!

    Бимбениву а ла гера санта ... :lol:

    Не буду из себя корчиить большого знатока С++, и, тем не менее - что знаю, то знаю. Сейчас, неспешно смакуя, читаю доку по Rust (книжка второй редакции). Понимаю, я еще далеко на пол-пути от понимания, но прочитанное и осознанное - это нечто!

    Раст:

    • Не задвигает ООП на вершину призеров по проектированию
    • Хотя парадигмы ООП имеет возможность реализовать в полном объеме
    • Имеет краткий и приятный (продуманный) синтаксис - спасибо Ruby!
    • Не парит мозги с возможными утечками памяти по невнимательности
    • Не затыкает дыры "сборщиками мусора"
    • Не вводит в обиход умные, хитрые и мудрые указатели
    • Все решается "прозрачными" парадигмами - "владение", "заимствование", "время жизни"
    • Внесенное в состав языка понятия "типажей" (traits) - гораздо понятнее, значительно понятнее похожей концепции STL из С++
    • Для любителей функциональщины - есть свои реализации ленивых исчислений, бери и ... ленись
    • Встроенные возможности юнит-тестирвания - это прекрасно!
    • Возможность непоследовательного объявления/реализация языковых конструкций радует
    • #pragma once, равно как и #ifdef гарды от С++ - тихо плачут в гардеробе
    • система сборки "cargo" - изящна, просто до безобразия
    • ... дочитаю доку - еще отпишусь!

    Поехали ... 8-)
      По большому счету у Rust, на мой взгляд, только два недостатка - убогий синтаксис(вкусовщина, но ничего не могу с этим сделать) и незрелость(быстрого взлета, как у Go, не получилось, но надежда еще есть).

      Добавлено
      Цитата JoeUser @
      Не задвигает ООП на вершину призеров по проектированию

      Ну C++ вроде тоже :)

      Цитата
      Хотя парадигмы ООП имеет возможность реализовать в полном объеме

      В виду отсутствия четкого определения и критериев ООП тут тяжело что-нибудь сказать.
      Наследование реализации отстутствует, например.
      Но да, противоречий с SOLID нет.

      Цитата
      Не парит мозги с возможными утечками памяти по невнимательности

      Требую подробностей :)

      Цитата
      Не вводит в обиход умные, хитрые и мудрые указатели

      А как же Box<T>, Rc<T>, Ref<T>, RefMut<T> и т.п.?

      Цитата
      Внесенное в состав языка понятия "типажей" (traits) - гораздо понятнее, значительно понятнее похожей концепции STL из С++

      Скорее trait в rust ближе к концептам. STL traits немного о другом.

      Цитата
      Встроенные возможности юнит-тестирвания - это прекрасно!

      Ну на мой взгляд, это не принципиально. Тех же gtest или boost.test в плюсах вполне хватает.

      В остальном соглашусь :)
        Цитата D_KEY @
        По большому счету у Rust, на мой взгляд, только два недостатка - убогий синтаксис(вкусовщина, но ничего не могу с этим сделать) и незрелость(быстрого взлета, как у Go, не получилось, но надежда еще есть).

        Синтаксис, мэй би убогий, но - логичный. Пример - определение ссылок на функции.

        Цитата D_KEY @
        Цитата JoeUser @
        Не задвигает ООП на вершину призеров по проектированию

        Ну C++ вроде тоже :)

        Oга-ога

        Цитата D_KEY @
        Цитата
        Хотя парадигмы ООП имеет возможность реализовать в полном объеме

        В виду отсутствия четкого определения и критериев ООП тут тяжело что-нибудь сказать. Наследование реализации отстутствует, например.
        Но да, противоречий с SOLID нет.

        Быть должно! Помню - в плане ООП реализовано все. OpenGL,хелп!

        Цитата D_KEY @
        Цитата
        Не парит мозги с возможными утечками памяти по невнимательности

        Требую подробностей :)

        Тут сложно объяснить в терминах С++. Если не дословно - компайлер Раст контролит каждую переменную в плане "рождения"-"смерти". А если не понимает - требует явного выставления "времени жизни".

        Цитата D_KEY @
        Цитата
        Не вводит в обиход умные, хитрые и мудрые указатели

        А как же Box<T>, Rc<T>, Ref<T>, RefMut<T> и т.п.?

        Да, похоже я до этого еще де добрался в изучении ... Вычеркиваем! :yes:
          Цитата D_KEY @
          По большому счету у Rust, на мой взгляд, только два недостатка - убогий синтаксис(вкусовщина, но ничего не могу с этим сделать) и незрелость(быстрого взлета, как у Go, не получилось, но надежда еще есть).
          На самом деле это НЕ недостатки, а вкусовщина. Самый большой недостаток на мой взгляд - избыточная жесткость. Пограммирование на Rust - суть борьба с компилятором. Наверное этот недостаток превращается в преимущество если ты пишешь какие-нибудь критические системы вроде ПО для самолетов. Кроме того у Rust дохлое метапрограммирование и дохлые макросы.
            Цитата applegame @
            На самом деле это НЕ недостатки, а вкусовщина

            Это не взаимоисключающие вещи :)
            Я там в скобочках написал, что восприятие синтаксиса - вкусовщина. Но вот лично для меня это довольно существенное препятствие, поскольку ну не нравится мне писать на rust. Неприятно :)
            И судя по инету, я такой не один.

            Добавлено
            Цитата applegame @
            Самый большой недостаток на мой взгляд - избыточная жесткость. Пограммирование на Rust - суть борьба с компилятором. Наверное этот недостаток превращается в преимущество если ты пишешь какие-нибудь критические системы вроде ПО для самолетов.

            А мне вот это нравится как раз :)
            А твои аргументы похоже на аргументацию против статической(и более менее строгой) типизации :D
              Цитата D_KEY @
              Наследование реализации отстутствует, например.

              Были RCF-шки, которые вводили делегирование имплементации трейта какому-либо полю структуре. Но я за ними не следил - почему их не запилили (и будут ли запиливать вообще) - не в курсе.

              Цитата applegame @
              Самый большой недостаток на мой взгляд - избыточная жесткость. Пограммирование на Rust - суть борьба с компилятором.

              А мне наоборот нравится - заставляет сперва продумать архитектуру. Клепать что-либо в нём костылями в стиле С++ говнокодера "а, этот объект и тут ещё нужен. Не беда - как-нибудь передам поинтер на него сюда" выйдет очень неудобно и долго.

              Цитата applegame @
              Кроме того у Rust дохлое метапрограммирование и дохлые макросы.

              Ну метапрограммирование да, даже до плюсового не дотягивает. А макросы чем не угодили?
                Цитата D_KEY @
                А мне вот это нравится как раз

                Да, в учебниках пишут - на первых порах это вынос мозга. Но потом, когда мышление изменяется, когда появляется привычка - то утверждают, что напряга совсем не чувствуется, а профит от большего контроля очевиден жиесть :lol:
                  Цитата JoeUser @
                  Не парит мозги с возможными утечками памяти по невнимательности

                  Ой да ладно. Один только mem::forget, не помеченный unsafe, чего стоит :) От утечек раст и не должен избавлять - в отличие от всяких use after free они не приводят к небезопасным ситуациям.
                    Цитата JoeUser @
                    умные, хитрые и мудрые указатели
                    :D
                    Цитата JoeUser @
                    дочитаю доку - еще отпишусь
                    :lol:
                      Цитата D_KEY @
                      А мне вот это нравится как раз :)
                      Твое право. Некоторые любят пожестче. :)
                      Цитата D_KEY @
                      А твои аргументы похоже на аргументацию против статической(и более менее строгой) типизации :D
                      Да, похожи.

                      Добавлено
                      Цитата OpenGL @
                      А мне наоборот нравится - заставляет сперва продумать архитектуру. Клепать что-либо в нём костылями в стиле С++ говнокодера "а, этот объект и тут ещё нужен. Не беда - как-нибудь передам поинтер на него сюда" выйдет очень неудобно и долго.
                      Не знаю, может в каком-то идеальном мире и можно все продумать заранее и это сработает, а в реальном мире действует следствие закона Мерфи: вероятность возникновения необходимого дополнения не вписывающегося в архитектуру ПО, прямо пропорциональна времени потраченному на проектирование этой архитектуры. :)
                      Ну и архитектура, на мой взгляд, это сущность более высокого уровня, на нее не влияют мелочи вроде контроля над временем жизни и прочие отличия Rust от C++. Языки с одного поля ягоды.

                      Добавлено
                      Синтаксис Rust меня особо не пугает, это дело привычки, проверено лично.
                      Завезли в него уже конкурентность и параллелизм на уровне стандартной либы? Ну там всякие файберы/корутины плюс планировщик?
                      Сообщение отредактировано: applegame -
                        Цитата applegame @
                        Ну и архитектура, на мой взгляд, это сущность более высокого уровня, на нее не влияют мелочи вроде контроля над временем жизни и прочие отличия Rust от C++. Языки с одного поля ягоды.

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

                        Цитата applegame @
                        Завезли в него уже конкурентность и параллелизм на уровне стандартной либы? Ну там всякие файберы/корутины плюс планировщик?

                        Нет, есть только сторонние. Но это не проблема совершенно из-за cargo.

                        Добавлено
                        Кстати, во многом из-за того, что привычные способы проектирования на расте плохо работают, на нём до сих пор нет хоть сколько-нибудь юзабельной gui библиотеки :D
                          Цитата OpenGL @
                          Но это не проблема совершенно из-за cargo.

                          В этом есть определённая проблема: наличие кучи различных способов обеспечить конкурентность и параллелизм, кто во что горазд, приводит к снижению сопровождаемости кода.
                            Цитата korvin @
                            В этом есть определённая проблема: наличие кучи различных способов обеспечить конкурентность и параллелизм, кто во что горазд, приводит к снижению сопровождаемости кода.

                            До прихода C++1x во всю пользовались бустом.
                            Что сподвигло расширить/модернизировать Стандарт.
                            Уверен, что и Раст пойдет по похожему пути.
                              Цитата OpenGL @
                              Нет, есть только сторонние. Но это не проблема совершенно из-за cargo.
                              На самом деле проблема. Сторонние библиотеки, в отличие от стандартной, иногда прекращают развиваться. А это базовые вещи, должны быть из коробки. По моему скромному.
                              Цитата JoeUser @
                              До прихода C++1x во всю пользовались бустом.
                              Что сподвигло расширить/модернизировать Стандарт.
                              Уверен, что и Раст пойдет по похожему пути.
                              Буст - это скорее исключение из правил.
                                Цитата OpenGL @
                                Были RCF-шки, которые вводили делегирование имплементации трейта какому-либо полю структуре

                                С возможностью переопределить часть методов, я надеюсь?
                                В любом случае, прямо сейчас этого нет. Но я не уверен, что это плохо :)
                                Я даже когда-то давно создавал холивар на тему

                                Добавлено
                                Цитата applegame @
                                Цитата D_KEY @
                                А мне вот это нравится как раз :)
                                Твое право. Некоторые любят пожестче. :)

                                На самом деле мне даже мало :D Больше статического анализа!
                                  Цитата D_KEY @
                                  Наследование реализации отстутствует, например.

                                  Мне кажется - это не недостаток, а фишка!

                                  Наследования, как я понял, совсем нет. Ни данных, ни реализации. И это упрощает в некотором смысле архитектуру. Не нужно заботиться, что, где, кого перекрывает, какие классы (при множественном наследовании) могут нечаянно включиться N или даже M! раз ...

                                  Вместо наследования - применяем агрегацию! См. сравнимый по функционалу код:

                                  C++:

                                  ExpandedWrap disabled
                                    #include <iostream>
                                    using namespace std;
                                     
                                    struct A {
                                      int a;
                                      A(int x);
                                      virtual void print();
                                    };
                                     
                                    struct B : A {
                                      int b;
                                      B(int x, int y);
                                      void print() override;
                                    };
                                     
                                    struct C : B {
                                      int c;
                                      C(int x, int y, int z);
                                      void print() override;
                                    };
                                     
                                    A::A(int x):a(x) {
                                    }
                                     
                                    void A::print() {
                                      cout << a << endl;
                                    }
                                     
                                    B::B(int x, int y):A(x),b(y) {
                                    }
                                     
                                    void B::print() {
                                      A::print();
                                      cout << b << endl;
                                    }
                                     
                                    C::C(int x, int y, int z):B(x,y),c(z) {
                                    }
                                     
                                    void C::print() {
                                      B::print();
                                      cout << c << endl;
                                    }
                                     
                                    int main() {
                                      C c = {1,2,3};
                                      c.print();
                                      return 0;
                                    }

                                  Rust:

                                  ExpandedWrap disabled
                                    use std::io::stdin;
                                     
                                    struct A {
                                      a: u32    
                                    }
                                     
                                    struct B {
                                      a: A,
                                      b: u32
                                    }
                                     
                                    struct C {
                                      b: B,
                                      c: u32
                                    }
                                     
                                    trait Print {
                                      fn print(&self);
                                    }
                                     
                                    impl Print for A {
                                      fn print(&self) {
                                        println!("{}",self.a)  
                                      }    
                                    }
                                     
                                    impl Print for B {
                                      fn print(&self) {
                                        self.a.print();
                                        println!("{}",self.b)  
                                      }    
                                    }
                                     
                                    impl Print for C {
                                      fn print(&self) {
                                        self.b.print();
                                        println!("{}",self.c)  
                                      }    
                                    }
                                     
                                    fn main() {
                                      let C = C{b:B{a:A{a:1},b:2},c:3};
                                      C.print();
                                    }


                                  Если говорить про вкусовщину - меня код Раст радует больше! :yes:
                                    А что тебе мешало в C++ написать примерно так же?
                                    ExpandedWrap disabled
                                      #include <iostream>
                                      using namespace std;
                                       
                                      struct Print {
                                          virtual void print() = 0;
                                      };
                                       
                                      struct A : Print {
                                        int a;
                                        A(int x);
                                        void print() override;
                                      };
                                       
                                      struct B : Print {
                                        A a;
                                        int b;
                                        B(int x, int y);
                                        void print() override;
                                      };
                                       
                                      struct C : Print {
                                        B b;
                                        int c;
                                        C(int x, int y, int z);
                                        void print() override;
                                      };
                                       
                                      A::A(int x):a(x) {
                                      }
                                       
                                      void A::print() {
                                        cout << a << endl;
                                      }
                                       
                                      B::B(int x, int y):a(x),b(y) {
                                      }
                                       
                                      void B::print() {
                                        a.print();
                                        cout << b << endl;
                                      }
                                       
                                      C::C(int x, int y, int z):b(x,y),c(z) {
                                      }
                                       
                                      void C::print() {
                                        b.print();
                                        cout << c << endl;
                                      }
                                       
                                      int main() {
                                        C c = {1,2,3};
                                        c.print();
                                        return 0;
                                      }


                                    Добавлено
                                    Цитата JoeUser @
                                    И это упрощает в некотором смысле архитектуру. Не нужно заботиться, что, где, кого перекрывает, какие классы (при множественном наследовании) могут нечаянно включиться N или даже M! раз ...

                                    В C++ ты можешь организовать свою архитектуру так же. А вот в Rust выбора нет :)
                                      Цитата D_KEY @
                                      А что тебе мешало в C++ написать примерно так же?

                                      Не мешало. Наоборот - я хотел от наследования С++ перейти к агрегации на Расте, без потери функционала.

                                      Цитата D_KEY @
                                      В C++ ты можешь организовать свою архитектуру так же. А вот в Rust выбора нет :)

                                      Вот тут давай уточнять! :lol: Правильнее бы было сказать, имхо, так: "В C++ ты можешь организовать свою C++ - шную архитектуру так же. А вот в Rust выбора нет".

                                      Добавлено
                                      D_KEY, и да ... твой код не эквивалентен "растовскому"! Я сперва тоже приплел виртуальные функции, потом подумал, что на 3 структурах можно и без них.
                                        Цитата JoeUser @
                                        D_KEY, и да ... твой код не эквивалентен "растовскому"! Я сперва тоже приплел виртуальные функции, потом подумал, что на 3 структурах можно и без них.

                                        Разница только в том, что в Rust отвязаны структуры и impl. Ты про это?
                                          Цитата D_KEY @
                                          Ты про это?
                                          Нет. Наличие виртуальных Функций - это уже наличие VMT. А это не по фэн-шую :)
                                            Цитата JoeUser @
                                            Цитата D_KEY @
                                            Ты про это?
                                            Нет. Наличие виртуальных Функций - это уже наличие VMT. А это не по фэн-шую :)

                                            Ты думаешь, что Impl'ы как-то иначе устроены? :)
                                              Цитата D_KEY @
                                              Ты думаешь, что Impl'ы как-то иначе устроены?

                                              Думаю да. Иначе бы я не читал этого ;)
                                                Цитата JoeUser @
                                                Цитата D_KEY @
                                                Ты думаешь, что Impl'ы как-то иначе устроены?

                                                Думаю да. Иначе бы я не читал этого ;)

                                                Так оттуда же(про динамическую диспетчерезацию):
                                                Цитата
                                                However, this comes at the cost of requiring slower virtual function calls, and effectively inhibiting any chance of inlining and related optimisations from occurring.


                                                Добавлено
                                                А в Representation заглядывал?

                                                Добавлено
                                                Цитата
                                                The methods of the trait can be called on a trait object via a special record of function pointers traditionally called a 'vtable' (created and managed by the compiler).
                                                  D_KEY, э не ... так не пойдет! :lol: Давай пруф из доков, где говорится, что любая реализация "методов" посредством блока impl породжает одиночную дичпетчеризацию (через VMT). Иначе я моя твоя не понимать. И это ... учитывай, что книгу по Расту я прочел только один раз, в меру своей внимательности! Считай - махровый нубас! :lol:
                                                    JoeUser, смотри в раздел Representation по твоей ссылке. Там даже та же терминология используется(vtable).
                                                      Цитата D_KEY @
                                                      про динамическую диспетчерезацию

                                                      Погоди ... так это вырвано из контекста??? А при статической (как у меня в примере)? Там тоже Раст будет VMT (ну или что-то подобное) городить??? Я в это не поверю! :-?

                                                      Добавлено
                                                      Цитата D_KEY @
                                                      ам даже та же терминология используется(vtable).

                                                      Ну да - для динамической диспетчеризации! Но откуда такое обобщение:

                                                      Цитата D_KEY @
                                                      Ты думаешь, что Impl'ы как-то иначе устроены?


                                                      ??? Читается как "всегда" :-?
                                                        В примере JoeUser-а же компилятору точный тип известен, так что никакого виртуального вызова быть не должно. Хотя изначально разговор был про наличие VMT - возможно, компилятор эту таблицу всё же генерирует :)
                                                        Сообщение отредактировано: OpenGL -
                                                          Цитата OpenGL @
                                                          возможно, компилятор эту таблицу всё же генерирует

                                                          Покажите, что это всегда "да" - и я забуду про Раст :lol:

                                                          Скрытый текст
                                                          По поводу терминологии. Я применил термин "агрегация" как альтернатива наследованию. Покак еще не осознал глубину всех глубин. Возможно был не прав. Есть еще альтернативный вариант - "композиция". Терки об этом тут. Будем еще почитать! 8-)
                                                            Для приведенного плюсового кода компилятор вполне может так же сгенерировать код без обращения к vtable. Это же вопрос оптимизации.
                                                            В C++ для статической диспетчерезации вообще будет достаточно обычных перегруженных функций в данном примере :) В более сложных случаях - шаблоны.

                                                            Добавлено
                                                            Но вообще подход Rust здравый. Я помню еще давно в дельфийских холиварах как-то поднимал вопрос о том, зачем, по большому счету разделять понятия статических "концептов" и динамических "интерфейсов".
                                                              Цитата JoeUser @
                                                              Покажите, что это всегда "да" - и я забуду про Раст

                                                              А почему не должен создавать? Если ты создал трейт, который является trait object-ом, то по-моему вполне естественно ожидать, что ты будешь использовать его именно в таком контексте. Если это не так (что, кстати, в расте не редкость), то в общем-то только и остаётся, что надеяться на оптимизатор, который сообразит, что виртуальные вызовы ты не используешь.
                                                                Цитата D_KEY @
                                                                Для приведенного плюсового кода компилятор вполне может так же сгенерировать код без обращения к vtable.

                                                                Мы не говорим о мудрости компайлеров. Тут чисто концептуально - динамическая диспетчеризация ═► косвенные вызовы. Да, компайлер в ряде случаев ваще может методы заинлайнить. Но разговор не об этом.

                                                                Цитата D_KEY @
                                                                Но вообще подход Rust здравый.

                                                                Вот тут не отвечу предметно, ибо учусь. Но, сска, чуйка подсказывает профит ...

                                                                Скрытый текст
                                                                Хистори

                                                                Практически - де жа вю. Было время, писал на Virtual Pascal, а продвинутые "боссы" гнобили, мол Дельфи - это наше все, модно и современно! А работа была по массовой обработке и трансформации текстов (нормативка). 1997 год. Просто сдуру взялся за Perl. Сперва просто плевался. Как меня только не высмеивали, qwerty-$%#$-птичий язык. Но и тогда БЫЛА ЧУЙКА!!! Через месяцок я пишу обработчик за пол-часа, макс. час - коллеги в пару дней не укладываются на своем Дельфэ. И тогда я понял, это не вселенская мудрость - это практическая чуйка. Надо ее слушать! :lol:

                                                                Вот о5 че-то подмывает ... :whistle:
                                                                  Цитата OpenGL @
                                                                  который является trait object-ом,

                                                                  Стоп! В доках о трэйтах и трэйт-обектах я читал. Это не одно и то же! Более того, я вааще могу не создавать ни явных трэйтов, ни трэйт-объектов!
                                                                  А только реализацию. Но давайте не отвлекаться. Читаем и повторяем ...

                                                                  Цитата D_KEY @
                                                                  Ты думаешь, что Impl'ы как-то иначе устроены?

                                                                  Это я чисто напомнить суть разговора, перевожу: "impl'ы всегда создают косвенные вызовы".
                                                                    Цитата JoeUser @
                                                                    D_KEY, и да ... твой код не эквивалентен "растовскому"! Я сперва тоже приплел виртуальные функции, потом подумал, что на 3 структурах можно и без ни

                                                                    Посыпаю голову пепломъ :lol:

                                                                    В посте с кодом С++ и Rust - я привел первый вариант (с виртуальными функциями), а в ссылке на он-лайн компилятор - привел код без них!

                                                                    С++ вариант должен быть вот так, без виртуальных функций:

                                                                    ExpandedWrap disabled
                                                                      #include <iostream>
                                                                      using namespace std;
                                                                       
                                                                      struct A {
                                                                        int a;
                                                                        A(int x);
                                                                        void print();
                                                                      };
                                                                       
                                                                      struct B : A {
                                                                        int b;
                                                                        B(int x, int y);
                                                                        void print();
                                                                      };
                                                                       
                                                                      struct C : B {
                                                                        int c;
                                                                        C(int x, int y, int z);
                                                                        void print();
                                                                      };
                                                                       
                                                                      A::A(int x):a(x) {
                                                                      }
                                                                       
                                                                      void A::print() {
                                                                        cout << a << endl;
                                                                      }
                                                                       
                                                                      B::B(int x, int y):A(x),b(y) {
                                                                      }
                                                                       
                                                                      void B::print() {
                                                                        A::print();
                                                                        cout << b << endl;
                                                                      }
                                                                       
                                                                      C::C(int x, int y, int z):B(x,y),c(z) {
                                                                      }
                                                                       
                                                                      void C::print() {
                                                                        B::print();
                                                                        cout << c << endl;
                                                                      }
                                                                       
                                                                      int main() {
                                                                        C c = {1,2,3};
                                                                        c.print();
                                                                        return 0;
                                                                      }


                                                                    Да, это мой косяк! :blush:
                                                                      Цитата JoeUser @
                                                                      Это я чисто напомнить суть разговора, перевожу: "impl'ы всегда создают косвенные вызовы".

                                                                      Суть? А по-моему изначально суть была в самом наличии VMT :crazy:
                                                                      Вообще, очевидно, зависит от конкретного сценария использования. Если ты юзаешь статическую диспетчеризацию, то компилятору нет смысла делать виртуальный вызов, и для этого даже оптимизатор не нужен. А вот создавать или нет VMT для конкретного типа (и именно об этом я говорил в прошлом своём комментарии) уже зависит только от оптимизатора.
                                                                        JoeUser, ты можешь поиграться на https://play.rust-lang.org/
                                                                        Умеет выводить asm и llvm-ir
                                                                          Цитата OpenGL @
                                                                          А вот создавать или нет VMT для конкретного типа (и именно об этом я говорил в прошлом своём комментарии) уже зависит только от оптимизатора.

                                                                          Я утверждаю - без динамической диспетчеризации VMT в Расте быть не должно!

                                                                          Ты ответил:

                                                                          Скрытый текст
                                                                          Цитата JoeUser @
                                                                          Цитата D_KEY @
                                                                          Ты про это?
                                                                          Нет. Наличие виртуальных Функций - это уже наличие VMT. А это не по фэн-шую :)

                                                                          Ты думаешь, что Impl'ы как-то иначе устроены? :)

                                                                          Такшта давай определяться :lol: Impl'ы - действительно тупые и всегда лепят VMT (или vtable), или ты решил внезапно "приукрасить" недопиленность Раста?

                                                                          Добавлено
                                                                          Цитата OpenGL @
                                                                          А вот создавать или нет VMT для конкретного типа (и именно об этом я говорил в прошлом своём комментарии) уже зависит только от оптимизатора.

                                                                          :blink: чисто интерес !!! Покажи мне с Раст ну или С++ вариант, когда не используется динамическая диспетчеризация - но VMT па-любэ строятся! Я просто должен это увидеть!!! :wall:
                                                                            OpenGL, D_KEY, с вашего позволения, я немножко, промежуточно, резюмирую!

                                                                            Де-юре, я не должен искать доказательства того, "что этого не может быть" или "не бывает". Так работает "презумпция невиновности" в доказательствах. Если вы утверждаете факт или свойство - вы и доказывайте. Примерами, доками, асм-кодом.

                                                                            Я же аппелирую к здравому смыслу. С++ этого не делает, и это состоявшийся язык. Rust - гораздо моложе, но имеет "базу", включая тот же C++", и свой некороткий путь развития. И не должен этого делать... А вдруг вы правы? Доказательства! :)
                                                                              Мне кажется, что есть какое-то недопонимание :)
                                                                                Цитата JoeUser @
                                                                                Покажи мне с Раст ну или С++ вариант, когда не используется динамическая диспетчеризация - но VMT па-любэ строятся! Я просто должен это увидеть!!!

                                                                                Тебя только что интересовало не наличие VMT, а есть виртуальный вызов или нет. Всё-таки теперь тебя уже VMT интересует? :lol:
                                                                                  Цитата OpenGL @
                                                                                  Тебя только что интересовало не наличие VMT, а есть виртуальный вызов или нет

                                                                                  Упс ... Чисто мое скромное имхо ... А как ты представляешь себе виртуальный вызов без VMT (ну или аналога)? :blink:
                                                                                  Скрытый текст
                                                                                  Дабы не был кривотолков. "Есть ли виртуальный вызов" и "наличие VMT" - для меня вопросы в принципе эквивалентные. Прямой вызов или косвенный. Просто трактовка разная.

                                                                                  Цитата D_KEY @
                                                                                  Мне кажется, что есть какое-то недопонимание :)

                                                                                  Все возможно, даже то - что быть не может :lol: Вощем ... проясняй, а я подтянусь! :lol:
                                                                                    Цитата OpenGL @
                                                                                    Тебя только что интересовало не наличие VMT, а есть виртуальный вызов или нет. Всё-таки теперь тебя уже VMT интересует? :lol:

                                                                                    Зы - ты плохой :lool: Дай линк на мой пост, где мне на VMT пофик и только виртуальные вызовы интересуют.
                                                                                      Цитата JoeUser @
                                                                                      Покажи мне с Раст ну или С++ вариант, когда не используется динамическая диспетчеризация - но VMT па-любэ строятся!
                                                                                      Прям-таки сходу не приведу, но опишу Плюсовый сценарий.
                                                                                      Пишем шаблон класса с хотя бы одним виртуальными методом. Явно его инстанцируем каким-либо набором шаблонных параметров. Никуда компилятор не денется, ему придётся сынстанцировать все методы и построить VMT. При этом в программе может не быть ни одного виртуального вызова, но компилятор об этом знать не может. Впрочем, грамотный линкер сможет соптимизировать, но это будут его личные особенности.
                                                                                      Вероятно, это не тот сценарий, который ты искал, JoeUser, однако вот он. В целом полиморфизм можно построить и руками на обычных указателях на функции, хоть и на С. Считать ли подобный велосипед за VMT, я не знаю.
                                                                                        Цитата JoeUser @
                                                                                        Упс ... Чисто мое скромное имхо ... А как ты представляешь себе виртуальный вызов без VMT (ну или аналога)? :blink:

                                                                                        Я затруднюсь представить, что тебя заставило представить, что я представляю виртуальный вызов без VMT (ну или аналога) :D

                                                                                        Добавлено
                                                                                        Цитата JoeUser @
                                                                                        Цитата OpenGL @
                                                                                        Тебя только что интересовало не наличие VMT, а есть виртуальный вызов или нет. Всё-таки теперь тебя уже VMT интересует? :lol:

                                                                                        Зы - ты плохой :lool: Дай линк на мой пост, где мне на VMT пофик и только виртуальные вызовы интересуют.

                                                                                        Блин, давай сначала. В коде, представленном тобой, а также в коде наподобие
                                                                                        ExpandedWrap disabled
                                                                                          trait Foo
                                                                                          {
                                                                                              fn foo();
                                                                                          }
                                                                                           
                                                                                          fn call_foo<T: Foo>(a: T)
                                                                                          {
                                                                                              a.foo();
                                                                                          }

                                                                                        я нахожу маловероятным то, что компилятор вставит в них виртуальный вызов потому что в нём компилятор знает исходный тип элементов. При этом вопрос наличия VMT у типа, имплементящего это самое Foo, совершенно ортогонален первому - очевидо, она будет если ты юзаешь виртуальные вызовы, а если нет, то её наличие - вопрос исключительно оптимизатора, и ответ я на него не знаю, так что разберись уж как-нибудь сам с ним (ссылки на онлайн-дизассемблер раста кидали выше), раз уж для тебя это настолько важно, что ты готов "забыть про раст" (с) ежели что не так :D
                                                                                          Цитата Qraizer @
                                                                                          хотя бы одним виртуальными методом.

                                                                                          Если компайлер "агрицца" на виртуальный метот неразвернутого шаблона - это плохой компайлер! ИМХО, он должен сперва развернуть все, и только потом - строит код. Низачот! :)

                                                                                          Add:

                                                                                          ЗЫ: Хотя ... В нынешней реализации - ты скорее прав! Если бы развертка шаблонов была шагом а-ля "пост-пре-процессор" - да, можно было бы на компилятор ругаться. А пока - только на линкер надежда, что он "склеит", а что выкинет.
                                                                                            Цитата OpenGL @
                                                                                            то её наличие - вопрос исключительно оптимизатора

                                                                                            :wacko: - извини за мой французский ... не оптимизатора - а говнятора! зачем деспетчировать функции, которые в этом не нуждаются?! Это вопрос оптимизатора?

                                                                                            Цитата OpenGL @
                                                                                            так что разберись уж как-нибудь сам с ним

                                                                                            А-я-яй!!! Это пост в стиле "сетьлера"© - типа я задекларирую какую-то левую шляпу, и если не разберетесь - вы ламеры!

                                                                                            Цитата OpenGL @
                                                                                            что ты готов "забыть про раст"

                                                                                            Вестись на слабо - это прекрасно! :lol:

                                                                                            Цитата OpenGL @
                                                                                            я нахожу маловероятным то, что компилятор вставит в них виртуальный вызов потому что в нём компилятор знает исходный тип элементов

                                                                                            И я нахожу это! А "они" - нет :lol:
                                                                                              Цитата JoeUser @
                                                                                              :wacko: - извини за мой французский ... не оптимизатора - а говнятора! зачем деспетчировать функции, которые в этом не нуждаются?! Это вопрос оптимизатора?

                                                                                              В зависимости от того, что ты понимаешь под этим процессом и в зависимости от того, что ты понимаешь под функциями, которые в нём не нуждаются, будут даны разные ответы :D

                                                                                              Добавлено
                                                                                              Цитата JoeUser @
                                                                                              И я нахожу это! А "они" - нет :lol:

                                                                                              Кто эти самые "они" и почему ты не задаёшь свои странные вопросы им? :D
                                                                                                Цитата OpenGL @
                                                                                                В зависимости от того, что ты понимаешь под этим процессом и в зависимости от того, что ты понимаешь под функциями, которые в нём не нуждаются, будут даны разные ответы :D

                                                                                                Ахтунг! Ахтунг! Ахтунг! Демагогия - детектед!!! >:(

                                                                                                Цитата OpenGL @
                                                                                                Кто эти самые "они" и почему ты не задаёшь свои странные вопросы им?

                                                                                                Эти странные парни - из параллельной вселенной, слушают левой ногой ... и ходят медленно :-?
                                                                                                Сообщение отредактировано: JoeUser -
                                                                                                  Цитата JoeUser @
                                                                                                  Цитата D_KEY @
                                                                                                  Ты думаешь, что Impl'ы как-то иначе устроены?

                                                                                                  Это я чисто напомнить суть разговора, перевожу: "impl'ы всегда создают косвенные вызовы".

                                                                                                  Перевод-то неверный. Даже плюсовые виртуальные функции не всегда создают косвенные вызовы :)
                                                                                                  Trait'ы и Impl'ы в случае динамической диспетчеризации ведут себя как виртуальные функции, о чем прямо написано по твоей ссылке.
                                                                                                    Цитата JoeUser @
                                                                                                    Ахтунг! Ахтунг! Ахтунг! Демагогия - детектед!!!

                                                                                                    То есть узнать от собеседника конкретику, чтобы не рассуждать о сферах в вакууме - демагогия? Ну лаааадно, пусть будет так :crazy:
                                                                                                      Цитата D_KEY @
                                                                                                      Перевод-то неверный. Даже плюсовые виртуальные функции не всегда создают косвенные вызовы :)

                                                                                                      А-би-сь-ня-ю!
                                                                                                      Это бывает тогда, когда компайлер распознает тип при вызове. И даже линкер тут не при чем! Компайлер понял - идет явная инициализация типа предопределенной константой, к примеру, и усе ... Тут действительно VMT не нужнен, вернее - может быть просчитан. А вот если создаем массив (или вектор) указателей на объекты разных классов ... тут только от тебя асм-пруф! И слышать ничего не желаю!
                                                                                                      Цитата D_KEY @
                                                                                                      Trait'ы и Impl'ы в случае динамической диспетчеризации ведут себя как виртуальные функции, о чем прямо написано по твоей ссылке.

                                                                                                      Так я и не спорю! :lol: Ты просто сказал типа "вcегда" (т.е. и при динамической и при статической) - меня это и вштырило :)

                                                                                                      Добавлено
                                                                                                      Цитата OpenGL @
                                                                                                      То есть узнать от собеседника конкретику, чтобы не рассуждать о сферах в вакууме - демагогия? Ну лаааадно, пусть будет так

                                                                                                      Не нужно узнавать, вдаваться в подробности, уточнять настроение и скорость ветра ... нужно просто привести пруфы в коде! Утверждаешь - не спрашивай, доказывай, аргументируй! Или спросишь опять, к примеру, а в какое время?
                                                                                                        Цитата JoeUser @
                                                                                                        Не нужно узнавать, вдаваться в подробности, уточнять настроение и скорость ветра ... нужно просто привести пруфы в коде! Утверждаешь - не спрашивай, доказывай, аргументируй! Или спросишь опять, к примеру, а в какое время?

                                                                                                        :lool: Привести пруфы на что именно? :crazy: Всё, что я утверждал до этого, в каких-либо особых пруфах не нуждается - это всего-навсего элементарная логика и немного базовых знаний. Если тебе не хватает одного из этих компонентов - ну я бессилен :D
                                                                                                          D_KEY я приведу пример почти эталонного ответа :lol: Почти - потому что он был вопросом, хотя по делу! А вот если был бы пруфом с линком на доку ... ты бы мог быть Великим Сенсеем:

                                                                                                          Цитата D_KEY @
                                                                                                          А как же Box<T>, Rc<T>, Ref<T>, RefMut<T> и т.п.?
                                                                                                            Цитата OpenGL @
                                                                                                            элементарная логика и немного базовых знаний

                                                                                                            Именно на этом строятся Стандарты? Ога? :lool:
                                                                                                            Вычеркиваем текст стандарта C++1х, добавляем немножко элементарной логики от OpenGL и ... Qraizer неспешно идет совершать сеппуку :lool:
                                                                                                              Цитата JoeUser @
                                                                                                              Цитата OpenGL @
                                                                                                              элементарная логика и немного базовых знаний

                                                                                                              Именно на этом строятся Стандарты? Ога? :lool:
                                                                                                              Вычеркиваем текст стандарта C++1х, добавляем немножко элементарной логики от OpenGL и ... Qraizer неспешно идет совершать сеппуку :lool:

                                                                                                              И этот человек ещё кого-то в демагогии обвиняет :lool: Не, я пас, пожалуй - так и живот от смеха порвать недолго :D
                                                                                                                Цитата OpenGL @
                                                                                                                в каких-либо особых пруфах не нуждается

                                                                                                                Упс ... Я просил пруфы. Но ты уверен - они мне не нужны.
                                                                                                                Делаю вывод - что ты знаешь лучше меня то, что именно мне нужно.
                                                                                                                Занавес! :lol:
                                                                                                                  Цитата OpenGL @
                                                                                                                  И этот человек ещё кого-то в демагогии обвиняет

                                                                                                                  Блина ... да я просто прошу меньше слов и больше доказательства в виде кода! Стопицотраз прошу.
                                                                                                                  Лан напишу, чтобы было виднее ...

                                                                                                                  OpenGL, хватит трещать попусту - жду доказательства в виде кода!

                                                                                                                  Так видно? Или опять вопросы?

                                                                                                                  Скрытый текст
                                                                                                                  Цитата JoeUser @
                                                                                                                  И этот человек ещё кого-то в демагогии обвиняет

                                                                                                                  И этот прием мы знаем - называется "аргумент к личности".

                                                                                                                  Не надо обсуждать меня! Обсуждай тему.
                                                                                                                    Цитата JoeUser @
                                                                                                                    Если компайлер "агрицца" на виртуальный метот неразвернутого шаблона - это плохой компайлер! ИМХО, он должен сперва развернуть все, и только потом - строит код. Низачот!
                                                                                                                    Он был бы плохим, если б не делал некоторых вещей на "всякий случай" из-за того, что у него нет полной информации. К примеру, он вынужден всегда вставлять в объектный код вызываемую версию подставляемой функции, если только она не с внутренним связыванием, даже притом, что все её вызовы он смог встроить. Если он этого не сделает, то в некой единице трансляции, где он вынужден будет её вызвать, например, если точки её определения и объявления не совпадают, линкер при сборке приложения запросто может столкнуться с неопределённым символом.
                                                                                                                    Та же проблема с виртуальными методами шаблонных классов. Компилятор не обязан и не должен инстанцировать код шаблонных функций и методов шаблонных классов, если они не используются. Но виртуальные методы всегда используются хотя бы раз: нужно заполнить VMT. А будет ли или нет этот метод реально задействован в программе, станет известно лишь во время её исполнения.
                                                                                                                    Сообщение отредактировано: Qraizer -
                                                                                                                      Qraizer, да, в такой постановке вопроса - резонно строить VMT. Но, согласись, в плане обсуждения реализации impl блоков Раста - такая ситуация может быть как частный случай, но не как правило, следуя логике. Или я не прав?
                                                                                                                        Цитата JoeUser @
                                                                                                                        OpenGL, хватит трещать попусту - жду доказательства в виде кода!
                                                                                                                        Я вот тему перечитал, но так и не понял доказательств чего ты хочешь :)
                                                                                                                        Что оптимизатор/говнятор компилятора Rust умнее/тупее такового у компилятора C++ (какого из них?)?
                                                                                                                        Сообщение отредактировано: applegame -
                                                                                                                          Сообщение №21. Утверждение о том, что в Расте всегда будут создаваться VMT.
                                                                                                                            Цитата JoeUser @
                                                                                                                            Сообщение №21. Утверждение о том, что в Расте всегда будут создаваться VMT.
                                                                                                                            То есть ты сначала сделал сделал логический вывод из своих слов и слов D_KEY, потом выдрал из этого вывода слово "всегда" и начал яростно придираться к нему? :lol:
                                                                                                                            Самое забавное, что обсуждаемая деталь реализации крайне малозначительна и не должна быть критерием выбора или отказа от какого-либо языка.
                                                                                                                            Сообщение отредактировано: applegame -
                                                                                                                                Цитата applegame @
                                                                                                                                То есть ты сначала сделал сделал логический вывод из своих слов и слов D_KEY, потом выдрал из этого вывода слово "всегда" и начал яростно придираться к нему?

                                                                                                                                Неа. Дело было не так :lol:
                                                                                                                                Я сперва привел два примера кода - на с++ и на расте.
                                                                                                                                Потом D_KEY свой пример привел на С++, но с виртуальными функциями.
                                                                                                                                На что я указал, что код не совсем эквивалентный коду на расте.
                                                                                                                                И только потом было сообщение 21 ... ну и понеслась.
                                                                                                                                  Очередной ура-фанатик бьется грудью за новую самую-пресамую лучшую игрушку. Коммьюнити радостно поддерживает :) Фанатик трет посты оскорбляющие его нежные чувства :)
                                                                                                                                  !
                                                                                                                                  Хватит флудить!
                                                                                                                                  Твое отличные шутки здесь не нужны.
                                                                                                                                  Лучше по теме пиши ченить.
                                                                                                                                  Сообщение отредактировано: JoeUser -
                                                                                                                                    Цитата JoeUser @
                                                                                                                                    Я сперва привел два примера кода - на с++ и на расте.
                                                                                                                                    Потом D_KEY свой пример привел на С++, но с виртуальными функциями.

                                                                                                                                    А в твоем примере виртуальных функций не было? :D
                                                                                                                                    Я, если что, просто его подправил в части наследования.

                                                                                                                                    Добавлено
                                                                                                                                    ExpandedWrap disabled
                                                                                                                                          #include <iostream>
                                                                                                                                          using namespace std;
                                                                                                                                          
                                                                                                                                          struct A {
                                                                                                                                            int a;
                                                                                                                                            A(int x);
                                                                                                                                            void print() const;
                                                                                                                                          };
                                                                                                                                          
                                                                                                                                          struct B {
                                                                                                                                            A a;
                                                                                                                                            int b;
                                                                                                                                            B(int x, int y);
                                                                                                                                            void print() const;
                                                                                                                                          };
                                                                                                                                          
                                                                                                                                          struct C {
                                                                                                                                            B b;
                                                                                                                                            int c;
                                                                                                                                            C(int x, int y, int z);
                                                                                                                                            void print() const;
                                                                                                                                          };
                                                                                                                                          
                                                                                                                                          A::A(int x):a(x) {
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          void A::print() const {
                                                                                                                                            cout << a << endl;
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          B::B(int x, int y):a(x),b(y) {
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          void B::print() const {
                                                                                                                                            a.print();
                                                                                                                                            cout << b << endl;
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          C::C(int x, int y, int z):b(x,y),c(z) {
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          void C::print() const {
                                                                                                                                            b.print();
                                                                                                                                            cout << c << endl;
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          template<typename T>
                                                                                                                                          void print(const T &x)
                                                                                                                                          {
                                                                                                                                              x.print();
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          int main() {
                                                                                                                                            C c = {1,2,3};
                                                                                                                                            print(c);
                                                                                                                                            return 0;
                                                                                                                                          }
                                                                                                                                    Сообщение отредактировано: D_KEY -
                                                                                                                                      Цитата D_KEY @
                                                                                                                                      А в твоем примере виртуальных функций не было?


                                                                                                                                      Цитата JoeUser @

                                                                                                                                      Посыпаю голову пепломъ :lol:

                                                                                                                                      В посте с кодом С++ и Rust - я привел первый вариант (с виртуальными функциями), а в ссылке на он-лайн компилятор - привел код без них!

                                                                                                                                      Уффф :)
                                                                                                                                        JoeUser, планируешь на rust написать что-нибудь?
                                                                                                                                          Цитата D_KEY @
                                                                                                                                          JoeUser, планируешь на rust написать что-нибудь?

                                                                                                                                          Да. Но чую - не скоро! Только-только дочитал книжку. Мозги набекрень, надо еще разок прочесть и переварить, ибо С++ подход (а еще ранее Turbo Pascal 5.5, Virtual Pascal, Дельфи, отчасти ООП щляпы Perl) не отпускает! :wall: :lol:

                                                                                                                                          Почему, собственно заинтересовался растом ... Помнится я создавал как-то тему на тему "WebApplication на С++". Потом почитал, посмотрел бэнчмарки, и люто меня заинтересовали две штуки:


                                                                                                                                          Второй фреймворк ваще был 5 место занимал в тестах из 40-50 либ на различных языках. Естественно первые три - на чистых Сях. А когда-то найденный мною фрэймворк на С++ TreeRrog - был в конце двадцатки. Вот и подумалось мне - а не глянуть ли мне раст :lol:

                                                                                                                                          Добавлено
                                                                                                                                          ЗЫ: Кстати ... ты случаем не видел шаблонов, а ля Хелло Ворлд для сборки на раст следующего:

                                                                                                                                          1) программа-сервис винды
                                                                                                                                          2) программа-демон *nix'
                                                                                                                                          3) библиотеки динамической линковки .dll и .so

                                                                                                                                          ?
                                                                                                                                            Цитата JoeUser @
                                                                                                                                            Почему, собственно заинтересовался растом ... Помнится я создавал как-то тему на тему "WebApplication на С++". Потом почитал, посмотрел бэнчмарки, и люто меня заинтересовали две штуки:
                                                                                                                                            Интересуйся обратно :) Плюсовой фреймворк (веб в том числе) ULib в большинстве бенчмарков уделывает tokio. :D
                                                                                                                                              applegame, видел я его - пусть он и самый быстрый (а по сути там сущие копейки выигрыша по сравнению с Actix).

                                                                                                                                              Я просто перечислю тебе "избранное" из одного из файлов примеров.
                                                                                                                                              Насладись современным C++:

                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                // HttpHeader.cpp
                                                                                                                                                 
                                                                                                                                                   U_TRACE(5, "HttpHeader::count(%.*S)", U_STRING_TO_TRACE(name))
                                                                                                                                                   U_RETURN(j);
                                                                                                                                                   U_TRACE(5, "HttpHeader::add(%p,%d)", field, index)
                                                                                                                                                   U_INTERNAL_ASSERT_POINTER(field)
                                                                                                                                                   U_RETURN_POINTER(old, HttpField);
                                                                                                                                                   U_RETURN_POINTER(U_NULLPTR, HttpField);
                                                                                                                                                   U_RETURN_POINTER(field, HttpField);
                                                                                                                                                   U_TRACE(5, "HttpHeader::find(%.*S,%d)", U_STRING_TO_TRACE(name), index)
                                                                                                                                                   U_RETURN_POINTER(header[i], HttpField);
                                                                                                                                                   U_RETURN_POINTER(U_NULLPTR, HttpField);
                                                                                                                                                   U_TRACE(5, "HttpHeader::del(%.*S,%d)", U_STRING_TO_TRACE(name), index)
                                                                                                                                                   U_VEC_ERASE1(header, i);
                                                                                                                                                   U_RETURN_POINTER(field, HttpField);
                                                                                                                                                   U_RETURN_POINTER(U_NULLPTR, HttpField);
                                                                                                                                                   U_TRACE(5, "HttpHeader::del(%p)", field)
                                                                                                                                                   U_VEC_ERASE1(header, i);
                                                                                                                                                   U_RETURN_POINTER(field, HttpField);
                                                                                                                                                   U_RETURN_POINTER(U_NULLPTR, HttpField);
                                                                                                                                                   U_TRACE(256+5, "HttpHeader::stringify(%.*S)", U_STRING_TO_TRACE(field))
                                                                                                                                                   U_INTERNAL_DUMP("f = %p", f)
                                                                                                                                                   U_INTERNAL_DUMP("field = %.*S", U_STRING_TO_TRACE(field))
                                                                                                                                                   U_TRACE(5, "HttpHeader::clear()")
                                                                                                                                                   U_INTERNAL_DUMP("f = %p", f)
                                                                                                                                                   U_DELETE(f)
                                                                                                                                                   return U_NULLPTR;


                                                                                                                                              В гробу я видал такое читать.
                                                                                                                                              Сообщение отредактировано: JoeUser -
                                                                                                                                                это больше похоже на древний C++, а на современный.

                                                                                                                                                Добавлено
                                                                                                                                                Посмотрел на actix.
                                                                                                                                                Какая-то убогая пародия на erlang/elixir

                                                                                                                                                И таки, ты наверное имеешь в виду не сам actix, а actix-web.
                                                                                                                                                Сообщение отредактировано: applegame -
                                                                                                                                                  Цитата applegame @
                                                                                                                                                  не сам actix, а actix-web.

                                                                                                                                                  Ага.

                                                                                                                                                  Добавлено
                                                                                                                                                  Цитата applegame @
                                                                                                                                                  это больше похоже на древний C++, а на современный

                                                                                                                                                  Qt - де жа вю :lol:
                                                                                                                                                    Цитата applegame @
                                                                                                                                                    Какая-то убогая пародия на erlang/elixir

                                                                                                                                                    Убогая - не убогая, а 6-е место в бенчах. Мне там в коде не копаться N-лет. Знаю точно! "Наследование типажей" уже меня загнало под плинтус :wacko: И разорвало в клочья всю мою концепцию православного мира. Вот сейчас зашел ко мне Jack Daniel's - сидим и обсуждаем как жЫть дальше! :lol:
                                                                                                                                                      Цитата JoeUser @
                                                                                                                                                      "Наследование типажей" уже меня загнало под плинтус :wacko: И разорвало в клочья всю мою концепцию православного мира.

                                                                                                                                                      А что с ним не так? Это же точь-в-точь наследование интерфейсов из привычных языков программирования. Ну, почти - я не помню, есть ли возможность в явошарпах написать аналог какого-нибудь Clone, но не сказал бы, что это прямо-таки концептуальное отличие.
                                                                                                                                                        Цитата OpenGL @
                                                                                                                                                        А что с ним не так? Это же точь-в-точь наследование интерфейсов из привычных языков программирования. Ну, почти - я не помню, есть ли возможность в явошарпах написать аналог какого-нибудь Clone, но не сказал бы, что это прямо-таки концептуальное отличие.

                                                                                                                                                        Я не знаю что такое Интерфейсы. В классическом С++ этого тет. Явашарпы я презираю есличо. Такова се ля ви.
                                                                                                                                                          Цитата OpenGL @
                                                                                                                                                          А что с ним не так?

                                                                                                                                                          А вот это важно. с ними - вангую, все в порядке. Дело во мне. Инкапсуляцию, наследование и полиморфизм в меня вбивали годами, книжками, обидными ошибками. Это переломать непросто.
                                                                                                                                                            Цитата JoeUser @
                                                                                                                                                            Инкапсуляцию, наследование и полиморфизм в меня вбивали годами, книжками, обидными ошибками. Это переломать непросто.

                                                                                                                                                            И при этом ты не знаешь, что такое интерфейс? :)
                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                              Я не знаю что такое Интерфейсы.
                                                                                                                                                              Хоспаде, шо там знать-то? Интерфейс в плюсах - абстрактный класс содержащий только чистые виртуальные функции.

                                                                                                                                                              Добавлено
                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                              Убогая - не убогая, а 6-е место в бенчах.
                                                                                                                                                              а что ты такое пишешь, что тебе важны какие-то синтетический бенчи, а не например, возможность подрубиться к проду и в реальном времени на живом сервере выяснить где проблема?
                                                                                                                                                              Сообщение отредактировано: applegame -
                                                                                                                                                                Цитата JoeUser @
                                                                                                                                                                Явашарпы я презираю есличо.

                                                                                                                                                                Отличный профи :good:
                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                  а что ты такое пишешь, что тебе важны какие-то синтетический бенчи, а не например, возможность подрубиться к проду и в реальном времени на живом сервере выяснить где проблема?

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

                                                                                                                                                                  Цитата Астарот @
                                                                                                                                                                  Отличный профи

                                                                                                                                                                  Отличный респект от отличного юмориста форума!
                                                                                                                                                                  Запишу этот день пожалуй в прозе!

                                                                                                                                                                  ЗЫ: Между делом ... А ты по прежнему не имеешь возможности писать сколь-нибудь полезные темы?
                                                                                                                                                                  Тро-ло-ло тебя все таки победило и не отпускает?
                                                                                                                                                                    Гляжу я на твои темы - уж лучше трололо, чем так... :D
                                                                                                                                                                    !
                                                                                                                                                                    Астарот, я чел спокойный,  уравновешенный. Но не надо меня "проверять на прочность" - я тя умоляю! Потом же начнешь кричать админам "мИня банят и насилуют модеры, а я чистый и пушистый. А они демоны ...."

                                                                                                                                                                    Это второе предупреждение.

                                                                                                                                                                    Следующее - повлечет форумную кару!  :(
                                                                                                                                                                    Сообщение отредактировано: JoeUser -
                                                                                                                                                                      Нашёл интересную страничку об имплементации различных фич раста. Пусть тут будет :)
                                                                                                                                                                      Ссылка
                                                                                                                                                                        Скрытый текст
                                                                                                                                                                        JoeUser, ты какой-то нервный. Второе предупреждение, а о чем предупреждаешь до сих пор не ясно :) У нас тнхничка в школе такая была, постоянно ругалась, махал грязной тряпкой, чего-то требовала, но никто не мог понять чего именно. Ты мне её напомнил. Ты техничкой в нашей школе работать не мог?
                                                                                                                                                                        Сообщение отредактировано: JoeUser -
                                                                                                                                                                          Астарот, так ты за Rust, за C++ или за очередную шляпу?
                                                                                                                                                                            Скрытый текст
                                                                                                                                                                            Цитата Астарот @
                                                                                                                                                                            а о чем предупреждаешь до сих пор не ясно :)

                                                                                                                                                                            Не знаю, что там ты такого написал, но сильно подозреваю переход на личности :) Это всегда было отличительной особенностью твоих постов(помимо дельных вещей, которые в них иногда присутствовали). Раньше довольно часто тебе их прощали, а вот твоим оппонентам - нет :D

                                                                                                                                                                            Можно тебя попросить высказываться по теме?
                                                                                                                                                                            В кои-то веке живая тема в холиваре :)
                                                                                                                                                                            Сообщение отредактировано: JoeUser -
                                                                                                                                                                              Цитата applegame @
                                                                                                                                                                              Астарот, так ты за Rust, за C++ или за очередную шляпу?

                                                                                                                                                                              Я? Я за отсутствие фанатизма. В умелые руках и хер поварешка, как говорится. А вот это все, это для студентов ещё простительно, а для профи уже нет. Особенно не простительно "презирать" какие-то языки - презираю таких людей :D
                                                                                                                                                                                Цитата Астарот @
                                                                                                                                                                                Я? Я за отсутствие фанатизма.
                                                                                                                                                                                Я не вижу в этой теме фанатизма.
                                                                                                                                                                                Цитата Астарот @
                                                                                                                                                                                В умелые руках и хер поварешка, как говорится.
                                                                                                                                                                                Ты, конечно, можешь помешивать супчик хером, но потом сам хлебай такой супчик. :)
                                                                                                                                                                                Цитата Астарот @
                                                                                                                                                                                А вот это все, это для студентов ещё простительно, а для профи уже нет. Особенно не простительно "презирать" какие-то языки - презираю таких людей :D
                                                                                                                                                                                Полагаю, "презираю", в текущем контексте означает "не нравится, не хочу использовать". Я, можно сказать, презираю жабускрипт и похапе. Презирай меня! Мне насрать! :lol:
                                                                                                                                                                                Сообщение отредактировано: applegame -
                                                                                                                                                                                  Цитата Астарот @
                                                                                                                                                                                  Особенно не простительно "презирать" какие-то языки - презираю таких людей :D

                                                                                                                                                                                  Есть довольно существенная разница между тем, чтобы "презирать" какие-то инструменты и тем, чтобы презирать людей :)
                                                                                                                                                                                  И, на мой взгляд, с ростом профессионализма, неприязнь к инструментам в духе js и php только возрастает :D
                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                    Есть довольно существенная разница между тем, чтобы "презирать" какие-то инструменты и тем, чтобы презирать людей

                                                                                                                                                                                    Наверное тема "презирания" пошла с моей подачки :lol: Ну сами посудите, это же чистой воды - гиперболизация! Да, мне не нравятся Java и С#. Но не потому, что они убогие. А потому, что результат их сборки - исполнение в виртуальной машине. Вот только представьте - каждый вызов виртуализован! Это сколько же тепла выделяется процессором излишне, коего так не хватает Слава Украине!

                                                                                                                                                                                    Возможно вы уличите меня в нечестности, мол обожает Perl, и загоняет о виртуализации. Абисьняю. Не сыпьте соль на рану! Перрл - изумительный язык. Но его реализация в виде интерпретатора - это просто беда! :( Поэтому я и не загоняюсь, и не вкручиваю вам.
                                                                                                                                                                                      Этъты ещё на Аде не писал, наверное.
                                                                                                                                                                                        Цитата JoeUser @
                                                                                                                                                                                        А потому, что результат их сборки - исполнение в виртуальной машине. Вот только представьте - каждый вызов виртуализован! Это сколько же тепла выделяется процессором излишне, коего так не хватает Слава Украине!
                                                                                                                                                                                        Да не так уж и много лишнего тепла, оно ж все равно в итоге компиляется в нативный код. Вот эрланг, это да, чистая виртуалка, но даже там уже придумали HiPE.
                                                                                                                                                                                        Ну и как показывает практика, уменьшение тепла выделяемого процессором автоматически приводит к увеличению тепла выделяемого головой программиста. И наоборот.
                                                                                                                                                                                        Вон Qraizer излучает дофига энергии чтобы протестировать свои критические приложухи, но у него выбора нет, такова специфика профессии. А вот у меня есть, и я с удовольствием уменьшаю тепло головы за счет увеличения тепла процессора. :lol:
                                                                                                                                                                                        Сообщение отредактировано: applegame -
                                                                                                                                                                                          Тут вот JoeUser Раст всуе помянул: Метаклассы в C++
                                                                                                                                                                                          Сообщение отредактировано: JoeUser -
                                                                                                                                                                                            В расте есть процедурные макросы, которые в первом приближении должны давать те же возможности.
                                                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                                                              Наверное тема "презирания" пошла с моей подачки Ну сами посудите, это же чистой воды - гиперболизация! Да, мне не нравятся Java и С#. Но не потому, что они убогие. А потому, что результат их сборки - исполнение в виртуальной машине. Вот только представьте - каждый вызов виртуализован! Это сколько же тепла выделяется процессором излишне, коего так не хватает Слава Украине!

                                                                                                                                                                                              А зря. Как дополнение к плюсам Java/C# очень даже ничего подходят. А вот всякие Rust, жгут излишне твою энергию. А выхлопа в итоге 0,00000%. В итоге ты знаешь С++, и знаешь как то так немного с боку Rust. Но пишешь исключительно на С++(ну если отбросить другие скриптовые язеги). В итоге от знания С++ и Rust эффективность твоего КПД начинает падать, вместо того, чтобы повышаться. И собственно вытекает это в то, что ты начинаешь выделять больше тепла, но эффективность при этом не повышается :D Тут нужно либо полностью переходить например на Rust, и забывать плюсы, либо не эффективно поддерживать знания в актуальном состоянии этих двух языков. Что просто энергетически затратно и глупо. А всякие явошарпы напротив - повышают твой КПД при затрачивании даже меньшей энергии, чем ты тратишь на Rust. :whistle:
                                                                                                                                                                                              Сообщение отредактировано: Wound -
                                                                                                                                                                                                Тут один друг устроился в контору где приходится на шарпе писать (после плюсов и D). Ругает шарп грязными словами.
                                                                                                                                                                                                Последнее на что жаловался: https://stackoverflow.com/questions/5510343...ents-in-c-sharp
                                                                                                                                                                                                Такая простая вещь, а делается через адскую жопу.

                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                Еще, что писал:
                                                                                                                                                                                                - невозможно stderr перенаправить в stdout.
                                                                                                                                                                                                - если из интерфейса функцию убрал (переименовал), а в наследующем классе она осталась, то компилятор никак тебя не предупредит об этом.
                                                                                                                                                                                                - повальный боксинг всего чего ни попадя в object, а потом в рантайме каст обратно. Даже int-ы, говорит, в object пихают.
                                                                                                                                                                                                - нет приличных либок для http-сервера.
                                                                                                                                                                                                - async/await из-за корявой внутренней реализации могут приводить к трудноуловимым дедлокам, а нормальных файберов не завезли.
                                                                                                                                                                                                - отсутствие compile-time рефлексии, а рантайм-рефлексия тормозная аки черепаха.

                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                Я сам на шарпе практически не писал, но копался в сторонних либках и заметил, что энтерпрайз головного мозга весьма распространен среди любителей шарпа.
                                                                                                                                                                                                То бишь обилие говна вроде OutputGenerationContextVisitorStrategyFactory.
                                                                                                                                                                                                Сообщение отредактировано: applegame -
                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                  - невозможно stderr перенаправить в stdout.

                                                                                                                                                                                                  А это хоть где-то можно? Подобное мне кажется слишком низкоуровневой шляпой (в отличие от перенаправления стандартных потоков в файл, например), чтобы её в библиотеку языка запихивать. По крайней мере если бы мне потребовалось сделать такое, я бы просто через api ОС это сделал.

                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                  - повальный боксинг всего чего ни попадя в object, а потом в рантайме каст обратно.

                                                                                                                                                                                                  В чём он проявляется? Ну да, всё является Object-ом, но это же не то же самое, что постоянный каст туда-обратно.
                                                                                                                                                                                                    Цитата OpenGL @
                                                                                                                                                                                                    В чём он проявляется? Ну да, всё является Object-ом, но это же не то же самое, что постоянный каст туда-обратно.
                                                                                                                                                                                                    В том, что люди часто вместо дженерика кастят в обжект, пихают его куда-нибудь, а потом обратно кастят. Может просто он попал в компанию криворуких программистов. Я не знаю.
                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      Последнее на что жаловался: https://stackoverflow.com/questions/5510343...ents-in-c-sharp
                                                                                                                                                                                                      Такая простая вещь, а делается через адскую жопу.

                                                                                                                                                                                                      Я если честно не понял что он там хочет сделать. Это? Ему это вроде приводили в первом же ответе.
                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                    String[] arguments = Environment.GetCommandLineArgs();
                                                                                                                                                                                                                    Console.WriteLine("GetCommandLineArgs: {0}", String.Join(", ", arguments));


                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      Еще, что писал:
                                                                                                                                                                                                      - невозможно stderr перенаправить в stdout.

                                                                                                                                                                                                      Ээээээээ. Ему логгирование нужно? Так пусть возьмет Serilog тот же. У меня сейчас пишется и в файл и в консоль одновременно, еще и с подсветкой, можно в конфиге еще добавить куда писать надо.

                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      - если из интерфейса функцию убрал (переименовал), а в наследующем классе она осталась, то компилятор никак тебя не предупредит об этом.

                                                                                                                                                                                                      Если переименовал - у тебя ничего не соберется, потому что твой класс не будет реализовывать этот интерфейс, это очевидно вроде как. А если ты убрал из интерфейса метод, то в любом языке у тебя не будет ругаться. Ну или пускай не просто убирает, а через рефакторинг меню. Тогда по идее у него везде уберется автоматом.

                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      - повальный боксинг всего чего ни попадя в object, а потом в рантайме каст обратно. Даже int-ы, говорит, в object пихают.

                                                                                                                                                                                                      Не, ну тут уже какая предъява к языку? Это уже предъява к программистам. Так же можно сказать что в С++ повально выделяют память, а освобождать забывают, передают аргументы в методы класса/функции не по ссылке/указателю, а по значению. Из за чего программа жутко тупит.

                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      - нет приличных либок для http-сервера.

                                                                                                                                                                                                      Вот тут чуть не поперхнулся. Для чего? .ASP Net Core Web App ему в руки, плюс есть встроенный kestrel и httpd серверы. kestrel - пока еще сырой, но зато кросплатформенный. httpd - виндовый, допиленный. Все есть из коробки, того чего нет, может достать из Nuget пакетов. Вот я сейчас пилю полностью кросплатформенное серверное Web приложение, пока нехватки либок для http сервера не ощутил, напротив есть все и даже больше, чем нужно. При том что пишу я под kestrel, который еще недопиленный. Чего ему конкретно не хватает то?

                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      - async/await из-за корявой внутренней реализации могут приводить к трудноуловимым дедлокам, а нормальных файберов не завезли.

                                                                                                                                                                                                      Например? Я пока не натыкался если честно.

                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      - отсутствие compile-time рефлексии, а рантайм-рефлексия тормозная аки черепаха.

                                                                                                                                                                                                      Опять же для чего? Дженериков не хватает что ли?

                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      Тут один друг устроился в контору где приходится на шарпе писать (после плюсов

                                                                                                                                                                                                      Я не знаю как после D, но после плюсов - он по идее должен был ощутить внутреннюю гармонию, радость жизни и эйфорию. Ну если он только неделю пишет - то возможно он просто еще не оклиматизировался. И пытается решить задачи С++сными методами в C#. Тогда конечно получаешь некий дискомфорт. Но это по идее должно быть во всех языках.
                                                                                                                                                                                                      Сообщение отредактировано: Wound -
                                                                                                                                                                                                        Цитата applegame @
                                                                                                                                                                                                        если из интерфейса функцию убрал (переименовал), а в наследующем классе она осталась, то компилятор никак тебя не предупредит об этом.

                                                                                                                                                                                                        Об этом сразу предупредит IDE, если ее правильно настроить. За шарпея не скажу, но в жабе идея мигом начинает краснеть по поводу неуместной аннотации @Override
                                                                                                                                                                                                        Прикреплённая картинка
                                                                                                                                                                                                        Прикреплённая картинка
                                                                                                                                                                                                          Цитата Астарот @
                                                                                                                                                                                                          За шарпея не скажу, но в жабе идея мигом начинает краснеть по поводу неуместной аннотации @Override

                                                                                                                                                                                                          Там примерно тоже самое. Можно реализовывать через имя интерфейса. И будет ругаться.
                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                            Там примерно тоже самое. Можно реализовывать через имя интерфейса. И будет ругаться.
                                                                                                                                                                                                            А есть аннотация @override?

                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                            Цитата Астарот @
                                                                                                                                                                                                            Об этом сразу предупредит IDE, если ее правильно настроить. За шарпея не скажу, но в жабе идея мигом начинает краснеть по поводу неуместной аннотации @Override
                                                                                                                                                                                                            Он как раз сетовал на отсутствие override. В D не аннотация, а атрибут override, поэтому ругается не IDE, а компилятор.
                                                                                                                                                                                                            Сообщение отредактировано: applegame -
                                                                                                                                                                                                              Цитата applegame @
                                                                                                                                                                                                              Он как раз сетовал на отсутствие override. В D не аннотация, а атрибут override, поэтому ругается не IDE, а компилятор.

                                                                                                                                                                                                              Тут не знаю. Знаю, что джетбрейнсы для шарпея делают Rider https://www.jetbrains.com/rider/ а так как делают они, обычно, хорошо, то, скорее всего, все, что у твоего друга болит и чешется, там будет полечено и почёсано.
                                                                                                                                                                                                                Цитата applegame @
                                                                                                                                                                                                                А есть аннотация @override?

                                                                                                                                                                                                                Есть, но предназначена она для виртуальных методов класса. Для интерфейсов есть явная имплементация интерфейса.
                                                                                                                                                                                                                  Цитата Wound @
                                                                                                                                                                                                                  Есть, но предназначена она для виртуальных методов класса. Для интерфейсов есть явная имплементация интерфейса.

                                                                                                                                                                                                                  Так как есть способ отловить ситуацию с удалением метода из интерфейса?
                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                    Так как есть способ отловить ситуацию с удалением метода из интерфейса?

                                                                                                                                                                                                                    Конечно есть. Я же выше написал:
                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                    Для интерфейсов есть явная имплементация интерфейса.


                                                                                                                                                                                                                    Дело в том, что override несет несколько другую смысловую нагрузку, и к интерфейсам мягко говоря не применима. Потому как интерфейс не может иметь реализации. Соответственно и переопределять там нечего. Там реализовывать нужно. Поэтому override - это скорее про классы.
                                                                                                                                                                                                                    Но ты можешь написать явную реализацию для интерфейса, например:
                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                          interface MyInterface
                                                                                                                                                                                                                          {
                                                                                                                                                                                                                              string GetMyString();
                                                                                                                                                                                                                              void SetMyString(string value);
                                                                                                                                                                                                                          }
                                                                                                                                                                                                                       
                                                                                                                                                                                                                          public class MyClass : MyInterface
                                                                                                                                                                                                                          {
                                                                                                                                                                                                                              string MyInterface.GetMyString()
                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                  throw new NotImplementedException();
                                                                                                                                                                                                                              }
                                                                                                                                                                                                                       
                                                                                                                                                                                                                              void MyInterface.SetMyString(string value)
                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                  throw new NotImplementedException();
                                                                                                                                                                                                                              }
                                                                                                                                                                                                                          }

                                                                                                                                                                                                                    При таком раскладе, если ты в интерфейсе грохнешь любой метод, будет ошибка компиляции, например можешь попробовать в этом коде закоментировать или переименовать любой метод у интерфейса
                                                                                                                                                                                                                    https://rextester.com/CEPE93720
                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                      Я же выше написал:
                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                      Для интерфейсов есть явная имплементация интерфейса.

                                                                                                                                                                                                                      Ага, я просто не понял. Спасибо за разъяснения :good:
                                                                                                                                                                                                                        Но если ты объявишь методы у класса как public и уберешь явную имплементацию интерфейса - то все будет компилироваться. Но я не совсем понимаю - как должно работать в таком случае. В любом языке будет компилироваться.
                                                                                                                                                                                                                        Это как в С++ удалить чисто-виртуальную функцию в базовом классе.
                                                                                                                                                                                                                          Цитата Wound @
                                                                                                                                                                                                                          Это как в С++ удалить чисто-виртуальную функцию в базовом классе.

                                                                                                                                                                                                                          Если в производных классах писали override, то компилятор будет ругаться. Но тут я особой разницы с "явной имплементацией интерфейса" не вижу.
                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                            Если в производных классах писали override, то компилятор будет ругаться. Но тут я особой разницы с "явной имплементацией интерфейса" не вижу.

                                                                                                                                                                                                                            Да. Только фишка в том, что в С++ нет интерфейсов, там есть только классы. И абстрактный базовый класс - это частный случай обычного класса. Поэтому ты в любом производном классе можешь написать override.
                                                                                                                                                                                                                            А в C# там тоже есть абстрактные классы, и это не то же самое что интерфейс, и если класс наследуется от класса, то override - ты тоже можешь писать, никто не запрещает.
                                                                                                                                                                                                                            А вот в случае с интерфейсом - немного другая фишка. Если ты наследуешься напрямую от интерфейса, то ты не можешь у метода, который имплементишь написать override. Потому что к интерфейсам это не применимо. Ибо интерфейс в C# в принципе не может содержать реализацию, вообще никакую.
                                                                                                                                                                                                                            Я так полагаю, друг applegame, привык в С++ стайл писать нечто вроде:
                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                   interface MyInterface
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      string GetMyString();
                                                                                                                                                                                                                                      void SetMyString(string value);
                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                  public class MyClass : MyInterface
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      public string GetMyString()
                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                          return "MyString";
                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                      public void SetMyString(string value)
                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                  }

                                                                                                                                                                                                                            В таком случае, если ты у интерфейса закоментируешь какой то метод. То компилятор будет просто думать, что у класса есть свой метод, не ну а что, это ведь не запрещено. Главное что интерфейс он то реализует.
                                                                                                                                                                                                                            А вообще эта фича по факту нужна для разруливания множественного наследования интерфейсов.
                                                                                                                                                                                                                            Что то типа:
                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                  interface IAnimal
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      void Run();
                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                  interface IBot
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      void Run();
                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                  public class MyClass : IAnimal, IBot
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      void IAnimal.Run()
                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                          /*implementation for Animal*/
                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                      void IBot.Run()
                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                          /*implementation for Bot*/
                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                               
                                                                                                                                                                                                                                  //! А вот тут уже класс реализует в одном методе два интерфейса
                                                                                                                                                                                                                                  public class MyClass2 : IAnimal, IBot
                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                      public void Run()
                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                          /*implementation for IAnimal and IBot*/
                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                            Сообщение отредактировано: Wound -
                                                                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                                                                              Я так полагаю, друг applegame, привык в С++ стайл писать

                                                                                                                                                                                                                              Но я так понял, там еще D был. И в нем есть интерфейсы.

                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                              А, но в D можно писать override и для метода из интерфейса.
                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                А, но в D можно писать override и для метода из интерфейса.

                                                                                                                                                                                                                                А в интерфейсе можно реализовать метод? Если нельзя, то какой смысл в слове override? А если можно, то какой смысл в слове interface? :D
                                                                                                                                                                                                                                  Цитата Wound @
                                                                                                                                                                                                                                  А в интерфейсе можно реализовать метод?

                                                                                                                                                                                                                                  Можно, но только через final.
                                                                                                                                                                                                                                  Есть даже такой паттерн NVI называется, в C++ часто встречается, в D пропагандируется, как я понял.

                                                                                                                                                                                                                                  Цитата
                                                                                                                                                                                                                                  Если нельзя, то какой смысл в слове override?

                                                                                                                                                                                                                                  Просто для единообразия. В C++ для чисто виртуальной функции так же можно писать override, тебя же это не смущает.

                                                                                                                                                                                                                                  Цитата
                                                                                                                                                                                                                                  А если можно, то какой смысл в слове interface? :D

                                                                                                                                                                                                                                  Ну в Java тоже можно реализацию писать(поля нельзя иметь), но все ок.
                                                                                                                                                                                                                                  Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                    Просто для единообразия. В C++ для чисто виртуальной функции так же можно писать override, тебя же это не смущает.

                                                                                                                                                                                                                                    Так в С++ нет интерфейсов, с чего бы меня должно это смущать? А чисто виртуальная функция это частный случай виртуальной.

                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                    Ну в Java можно реализацию писать(поля нельзя иметь), но все ок.

                                                                                                                                                                                                                                    Ну тогда это уже ближе к абстрактным классам, нежели к интерфейсам, ИМХО.

                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                    Есть даже такой паттерн NVI называется, в C++ часто встречается, в D пропагандируется, как я понял.

                                                                                                                                                                                                                                    Что за паттерн такой? В С++ может и встречал, но аббревиатура точно не знакомая.
                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                      А чисто виртуальная функция это частный случай виртуальной.

                                                                                                                                                                                                                                      Но она не имеет реализацию. Так какой смысл в слове override?

                                                                                                                                                                                                                                      Цитата
                                                                                                                                                                                                                                      Ну тогда это уже ближе к абстрактным классам, нежели к интерфейсам, ИМХО.

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

                                                                                                                                                                                                                                      Цитата
                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                      Есть даже такой паттерн NVI называется, в C++ часто встречается, в D пропагандируется, как я понял.

                                                                                                                                                                                                                                      Что за паттерн такой? В С++ может и встречал, но аббревиатура точно не знакомая.

                                                                                                                                                                                                                                      Non-virtual interface pattern
                                                                                                                                                                                                                                      Если кратко, то ты разделяешь интерфейс для клиента(не виртуальный) и для наследника/реализатора(виртуальный). Клиент работает с одними наборами методов, которые реализуются посредством другого набора методов, которые предоставляет наследник или тот, кто реализует интерфейс. Хорошо ложится на такие паттерны, как шаблонный метод.
                                                                                                                                                                                                                                      Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                        Но она не имеет реализацию. Так какой смысл в слове override?

                                                                                                                                                                                                                                        Вся фишка в том, что эта функция часть класса. А в классах функции могут иметь реализацию. Сегодня она не имеет реализацию, а завтра будет иметь реализацию по умолчанию. А с интерфейсами в C# немного другая история, там даже если ты очень сильно захочешь, реализацию для метода написать ты не сможешь, только реализация в наследуемом классе.
                                                                                                                                                                                                                                        Но вообще, по большому счету, это придирки, да. Но если уж начинать придираться к тому, что в шарпах нельзя писать override для методов класса реализующих интерфейс, то тут скорее притензии не к шарпам, а к тем языкам, где такое можно писать.

                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                        Нет. Абстрактные классы там тоже есть.
                                                                                                                                                                                                                                        Просто иногда удобно предоставить дефолтную имплементацию. Которая, например, работает через другие методы интерфейса.

                                                                                                                                                                                                                                        Тогда какой смысл в интерфейсах? В чем принципиальное отличие интерфейса от абстрактного класса в Java? В ключевом слове?

                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                        Если кратко, то ты разделяешь интерфейс для клиента(не виртуальный) и для наследника/реализатора(виртуальный). Клиент работает с одними наборами методов, которые реализуются посредством другого набора методов, которые предоставляет наследник или тот, кто реализует интерфейс. Хорошо ложится на такие паттерны, как шаблонный метод.

                                                                                                                                                                                                                                        Ясно, да встречал такое. Правда не знал что это NVI паттерн.
                                                                                                                                                                                                                                        Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                          Цитата Wound @
                                                                                                                                                                                                                                          Тогда какой смысл в интерфейсах? В чем принципиальное отличие интерфейса от абстрактного класса в Java? В ключевом слове?

                                                                                                                                                                                                                                          В интерфейсе нельзя иметь поля. Для интерфейсов возможно множественное "наследование".
                                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                                            В интерфейсе нельзя иметь поля. Для интерфейсов возможно множественное "наследование".

                                                                                                                                                                                                                                            Нда. Тогда какой смысл в абстрактных классах? :D
                                                                                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                                                                                              Тогда какой смысл в абстрактных классах? :D

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

                                                                                                                                                                                                                                              Но я честно говоря не очень-то вижу принципиальную разницу между интерфейсами в C# и в Java. Дефолтную реализацию методов добавили не так давно в java. Может и в C# добавят.
                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                Может и в C# добавят.

                                                                                                                                                                                                                                                Да, так и есть :D Default implementations in interfaces
                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                  interface ILogger
                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                      void Log(LogLevel level, string message);
                                                                                                                                                                                                                                                      void Log(Exception ex) => Log(LogLevel.Error, ex.ToString());
                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                  Да, так и есть :D Default implementations in interfaces

                                                                                                                                                                                                                                                  Ну тогда, ИМХО, абстрактные классы уйдут в прошлое. Потому что не совсем понятно зачем они нужны. Разве что для красоты иерархии наследования, и то я сомневаюсь :-?
                                                                                                                                                                                                                                                  Ведь проще будет использовать интерфейсы. Я так понимаю, народ перечитал SOLID принципов и начал везде и всюду писать интерфейсы, даже там, где нужен абстрактный класс. В итоге это вышло вот в такую херню(взято из твоей ссылки): https://docs.microsoft.com/ru-ru/dotnet/csh...embers-versions
                                                                                                                                                                                                                                                  Цитата

                                                                                                                                                                                                                                                  На основе этих интерфейсов команда может собрать библиотеку для удобства работы клиентов своих пользователей. Их целью было более полно взаимодействовать с существующими клиентами и повысить уровень связи с новыми.

                                                                                                                                                                                                                                                  Пришло время перейти к библиотеке для следующего выпуска. Одна из востребованных возможностей — добавление скидки за лояльность для клиентов, размещающих большое количество заказов. Это новая скидка лояльности применяется каждый раз, когда клиент делает заказ. Специальная скидка является свойством каждого клиента. Каждая реализация ICustomer может задавать различные правила для скидки лояльности.

                                                                                                                                                                                                                                                  Наиболее удобный способ добавления этой функции — расширить ICustomer методом для применения любых скидок лояльности. Это предложение по разработке вызвало проблемы среди опытных разработчиков. "Интерфейсы являются неизменяемыми после выпуска! Это критическое изменение!" В C# 8.0 добавлены реализации интерфейсов по умолчанию для обновления интерфейсов. Авторы библиотеки могут добавлять новые элементы интерфейса и реализации по умолчанию для этих элементов.
                                                                                                                                                                                                                                                    Цитата Астарот @
                                                                                                                                                                                                                                                    Тут не знаю. Знаю, что джетбрейнсы для шарпея делают Rider https://www.jetbrains.com/rider/ а так как делают они, обычно, хорошо, то, скорее всего, все, что у твоего друга болит и чешется, там будет полечено и почёсано.
                                                                                                                                                                                                                                                    Это конечно хорошо, но это дело не IDE, это дело компилятора. А то получается, что убогость языка компенсируется IDE.
                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                    Дело в том, что override несет несколько другую смысловую нагрузку, и к интерфейсам мягко говоря не применима. Потому как интерфейс не может иметь реализации. Соответственно и переопределять там нечего. Там реализовывать нужно. Поэтому override - это скорее про классы.
                                                                                                                                                                                                                                                    Если ты аннотируешь @override функцию в классе наследующем интерфейс и если прототипа этой функции в интерфейсе не будет, то будет ли ошибка?
                                                                                                                                                                                                                                                    Скажем вот тут компилятор D будет ругаться (function void Foo.foo() does not override any function):
                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                      interface Bar {
                                                                                                                                                                                                                                                          void bar();
                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                      class Foo : Bar {
                                                                                                                                                                                                                                                          override void bar() {}
                                                                                                                                                                                                                                                          override void foo() {}
                                                                                                                                                                                                                                                      }

                                                                                                                                                                                                                                                    Если аналогично сделать в C# с @override будет также?

                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                    Но ты можешь написать явную реализацию для интерфейса, например:
                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                          interface MyInterface
                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                              string GetMyString();
                                                                                                                                                                                                                                                              void SetMyString(string value);
                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                          public class MyClass : MyInterface
                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                              string MyInterface.GetMyString()
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                  throw new NotImplementedException();
                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                              void MyInterface.SetMyString(string value)
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                  throw new NotImplementedException();
                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                          }

                                                                                                                                                                                                                                                    При таком раскладе, если ты в интерфейсе грохнешь любой метод, будет ошибка компиляции, например можешь попробовать в этом коде закоментировать или переименовать любой метод у интерфейса
                                                                                                                                                                                                                                                    https://rextester.com/CEPE93720


                                                                                                                                                                                                                                                    А в этом случае можно будет потом написать вот так?
                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                      MyClass a = new MyClass();
                                                                                                                                                                                                                                                      a.GetMyString();

                                                                                                                                                                                                                                                    ЕМНИП, GetMyString не будет существовать для MyClass.
                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                      Ну тогда, ИМХО, абстрактные классы уйдут в прошлое. Потому что не совсем понятно зачем они нужны.
                                                                                                                                                                                                                                                      Для того, для чего и всегда: экземпляры таких классов нежизнеспособны или не имеют смысла без того, чтобы быть допиленными производными классами. Ты ко всему ещё подзабыл, что в Плюсах есть множественное наследование реализаций, а также управление разделением/совмещением наследуемых атрибутов при этом. Посему на (не)вирутальном наследовании и (не)абстрактных классах можно собрать кучу всяких патернов, а не только реализацию интерфейсно-ориентированного и/или обычного суб/супер патернов.
                                                                                                                                                                                                                                                      Сообщение отредактировано: Qraizer -
                                                                                                                                                                                                                                                        Цитата applegame @
                                                                                                                                                                                                                                                        Если ты аннотируешь @override функцию в классе наследующем интерфейс и если прототипа этой функции в интерфейсе не будет, то будет ли ошибка?
                                                                                                                                                                                                                                                        Скажем вот тут компилятор D будет ругаться (function void Foo.foo() does not override any function):

                                                                                                                                                                                                                                                        В C# сейчас по крайней мере ты не можешь так написать. Т.е. если у тебя класс реализует интерфейс, то ты не можешь написать override, Но можешь явно заимплементить интерфейс, я уже писал об этом:
                                                                                                                                                                                                                                                        Rust vs C++ (сообщение #3808100)

                                                                                                                                                                                                                                                        https://rextester.com/CEPE93720

                                                                                                                                                                                                                                                        Попробуй закоментить SetMyString в интерфейсе, сразу получишь ошибку компиляции.

                                                                                                                                                                                                                                                        Цитата applegame @
                                                                                                                                                                                                                                                        А в этом случае можно будет потом написать вот так?

                                                                                                                                                                                                                                                        Нет. Но и смысла не вижу потом писать вот так. Значит интерфейс там нафиг не нужен. :unsure:
                                                                                                                                                                                                                                                        Можно юзнуть абстрактный базовый класс вместо интерфейса.

                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                        Цитата Qraizer @
                                                                                                                                                                                                                                                        Для того, для чего и всегда: экземпляры таких классов нежизнеспособны или не имеют смысла без того, чтобы быть допиленными производными классами. Ты ко всему ещё подзабыл, что в Плюсах есть множественное наследование реализаций, а также управление разделением/совмещением наследуемых атрибутов при этом. Посему на (не)вирутальном наследовании и (не)абстрактных классах можно собрать кучу всяких патернов, а не только реализацию интерфейсно-ориентированного и/или обычного суб/супер патернов.

                                                                                                                                                                                                                                                        Я имею ввиду что в явошарпах тогда абстрактные классы отпадут за ненадобностью. Их и так там почти не юзают, везде интерфейсы пихают и реализации этих самых интерфейсов. А с возможностью писать реализацию по умолчанию в интерфейсах, так в абстрактных классах вообще необходимость отпадает. Ведь сейчас в этом и заключается различие. Если ты знаешь что у тебя сущность не будет меняться, нужно множественное наследование - значит юзай интерфейсы. А если планируется расширение базового функционала, то юзай абстрактные классы.
                                                                                                                                                                                                                                                        Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                          Цитата applegame @
                                                                                                                                                                                                                                                          А то получается, что убогость языка компенсируется IDE.

                                                                                                                                                                                                                                                          Если тебе шашечки, то да, а если ехать, то тебе не пофиг, кто повезет?
                                                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                                                            Последнее на что жаловался: https://stackoverflow.com/questions/5510343...ents-in-c-sharp

                                                                                                                                                                                                                                                            What?

                                                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                                                            - невозможно stderr перенаправить в stdout.

                                                                                                                                                                                                                                                            Это вне программы делается.

                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                                                            Если ты аннотируешь @override функцию в классе наследующем интерфейс и если прототипа этой функции в интерфейсе не будет, то будет ли ошибка?
                                                                                                                                                                                                                                                            Скажем вот тут компилятор D будет ругаться (function void Foo.foo() does not override any function):

                                                                                                                                                                                                                                                            Почему это должно быть ошибкой? У класса есть свой неявный публичный интерфейс, в котором есть методы bar и foo, не зависимо от того, определены ли они в каком-то другом интерфейсе, или нет. Если ты убираешь метод из интерфейса, то компилятор будет ругаться на все существующие попытки в коде использовать этот метод через переменную интерфейсного типа:

                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              Bar v = ...;
                                                                                                                                                                                                                                                              v.foo();


                                                                                                                                                                                                                                                            но следующий вызов совершенно законен:
                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              Foo v = ...;
                                                                                                                                                                                                                                                              v.foo();


                                                                                                                                                                                                                                                            Так какого чёрта компилятор должен ругаться на метод foo в Foo? Из-за того, что у него аннотация override? А зачем вы её добавили? Чтобы что? Там и так указано, что Foo <: Bar — это не достаточно информативно? Нужно ещё на все методы override пихать? Чтобы потом убирать? Выглядит как создание пробемы самим себе и героическое её преодоление. В плюсах, делфи, вроде как, override имеет определённое назначение, т.к. методы могут быть не виртуальными и есть разница между
                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              Bar v = new Foo();
                                                                                                                                                                                                                                                              v.bar();

                                                                                                                                                                                                                                                            и
                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              Foo v = new Foo();
                                                                                                                                                                                                                                                              v.bar();


                                                                                                                                                                                                                                                            В D, видимо, тоже?

                                                                                                                                                                                                                                                            Хз как там в C#, но в Java она не имеет никакого смысла. Вот в Kotlin есть ключевое слово override вместо аннотации @Override, и нафига? Чтобы туда-сюда его гонять (добавлять/удалять) при рефакторинге? И саму аннотацию @Override в Java зря добавили, тупое захламление кода.
                                                                                                                                                                                                                                                            Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                                                                                                              А если ты убрал из интерфейса метод, то в любом языке у тебя не будет ругаться.

                                                                                                                                                                                                                                                              override разве нет в шарпе?

                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                              А, ну про это дальше было сказано.
                                                                                                                                                                                                                                                                Цитата korvin @
                                                                                                                                                                                                                                                                Хз как там в C#,

                                                                                                                                                                                                                                                                В C# есть ключевое слово override, но только для классов.

                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                Цитата OpenGL @
                                                                                                                                                                                                                                                                override разве нет в шарпе?

                                                                                                                                                                                                                                                                Есть, для классов.
                                                                                                                                                                                                                                                                  Цитата Wound @
                                                                                                                                                                                                                                                                  В C# есть ключевое слово override, но только для классов.

                                                                                                                                                                                                                                                                  Как это относится к тому, что я написал?
                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                    Как это относится к тому, что я написал?

                                                                                                                                                                                                                                                                    Ну ты написал Хз как там в шарпе, вот я и уточнил как там в шарпе :-?
                                                                                                                                                                                                                                                                    Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                                                                      Там и так указано, что Foo <: Bar — это не достаточно информативно?

                                                                                                                                                                                                                                                                      Ты точно читал тред? :) Очевидно, это недостаточно информативно.
                                                                                                                                                                                                                                                                        Цитата OpenGL @
                                                                                                                                                                                                                                                                        Ты точно читал тред? :) Очевидно, это недостаточно информативно.

                                                                                                                                                                                                                                                                        Ну на сколько я понял. Видимо был мертвый код, от которого друг applegame хотел избавиться, он удалил метод в интерфейсе, оно собралось даже не пискнув, при этом осталась реализация в классах наследниках. Ну дык, ему надо было через меню рефакторинга удалить метод в интерфейсе, тогда бы удалились методы в дочерних классах. А так - что вы от языка хотите то. Нужно было явно имплементить интерфейс. А не просто делать классы с паблик методами.
                                                                                                                                                                                                                                                                          Да это понятно. Я про наезды korvin-а на override - очевидно, override или явная имплементация интерфейса сильно упрощают жизнь при отсутствии в языке чего-то наподобие растовского impl Trait for MyClass, где по определению могут быть те и только те методы, которые есть в интерфейсе.
                                                                                                                                                                                                                                                                            Цитата korvin @
                                                                                                                                                                                                                                                                            Почему это должно быть ошибкой?

                                                                                                                                                                                                                                                                            Потому что в большинстве случаев оно ей является на практике.

                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                            Из-за того, что у него аннотация override? А зачем вы её добавили? Чтобы что?
                                                                                                                                                                                                                                                                            ...
                                                                                                                                                                                                                                                                            Хз как там в C#, но в Java она не имеет никакого смысла. Вот в Kotlin есть ключевое слово override вместо аннотации @Override, и нафига? Чтобы туда-сюда его гонять (добавлять/удалять) при рефакторинге?

                                                                                                                                                                                                                                                                            Чтобы защититься от ошибок при этом самом рефакторинге, например.
                                                                                                                                                                                                                                                                            Конкретно в Kotlin ведь и виртуальные методы нужно явно указывать через open.
                                                                                                                                                                                                                                                                            Так же ещё полезно при чтении кода класса - сразу видно, "родная" эта функция у класса или переопределенная.
                                                                                                                                                                                                                                                                              Цитата OpenGL @
                                                                                                                                                                                                                                                                              при отсутствии в языке чего-то наподобие растовского impl Trait for MyClass, где по определению могут быть те и только те методы, которые есть в интерфейсе.

                                                                                                                                                                                                                                                                              Я тут поигрался на досуге, так вот могу сказать, что при таком подходе лично мне тяжело избавиться от ощущения "размазанности" сущности. Если в "нормальном" языке я читаю класс и вижу весьма цельную сущность, то тут я вижу структурку (в том же C++ я обращаю внимание на поля только при необходимости) и набор разрозненных impl'ов.
                                                                                                                                                                                                                                                                                Цитата korvin @
                                                                                                                                                                                                                                                                                но в Java она не имеет никакого смысла.

                                                                                                                                                                                                                                                                                Подожди. Вот есть у тебя в классе A метод foo. С какой-то реализацией. Наследники переопределили. Override не написали. Потом ты рефакторишь A и меняешь сигнатуру метода. Во всех наследниках код будет валиден и компилятору не к чему придраться, хотя это ошибка. Где-то ты поправил сам(потому что помнил), где-то свалились тесты. А где-то это уехало на прод :)
                                                                                                                                                                                                                                                                                Не?
                                                                                                                                                                                                                                                                                Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                  Цитата Астарот @
                                                                                                                                                                                                                                                                                  Если тебе шашечки, то да, а если ехать, то тебе не пофиг, кто повезет?
                                                                                                                                                                                                                                                                                  Мне как раз ехать, а ты мне предлагаешь привязываться к какой-то определенной IDE.
                                                                                                                                                                                                                                                                                  Цитата korvin @
                                                                                                                                                                                                                                                                                  Так какого чёрта компилятор должен ругаться на метод foo в Foo? Из-за того, что у него аннотация override? А зачем вы её добавили? Чтобы что? Там и так указано, что Foo <: Bar — это не достаточно информативно? Нужно ещё на все методы override пихать? Чтобы потом убирать? Выглядит как создание пробемы самим себе и героическое её преодоление.
                                                                                                                                                                                                                                                                                  Ты чего-то не догоняешь. Впрочем тебе уже все разжевали остальные, так что не буду повторяться.
                                                                                                                                                                                                                                                                                    Цитата applegame @
                                                                                                                                                                                                                                                                                    Мне как раз ехать, а ты мне предлагаешь привязываться к какой-то определенной IDE.

                                                                                                                                                                                                                                                                                    Можно подумать в нормальной ситуации ты пользуешься несколькими :-?
                                                                                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                                                                                      What?
                                                                                                                                                                                                                                                                                      Ну вот есть у тебя список аргументов в виде массива строк, и надо вызвать стороннюю программу с этими аргументами. В аргументах ест пробелы и слеши/бэкслеши, функции для эскейпа нет, приходится городить свой кошмар.
                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                      Нужно было явно имплементить интерфейс. А не просто делать классы с паблик методами.
                                                                                                                                                                                                                                                                                      Да, видимо это он просто с непривычки ругается.

                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                      Цитата Астарот @
                                                                                                                                                                                                                                                                                      Можно подумать в нормальной ситуации ты пользуешься несколькими
                                                                                                                                                                                                                                                                                      Ты намеренно искажаешь смысл? Пользоваться какой-нибудь одной IDE и пользоваться конкретной одной IDE это, по-твоему, одно и то же?
                                                                                                                                                                                                                                                                                        Цитата applegame @
                                                                                                                                                                                                                                                                                        Ну вот есть у тебя список аргументов в виде массива строк, и надо вызвать стороннюю программу с этими аргументами. В аргументах ест пробелы и слеши/бэкслеши, функции для эскейпа нет, приходится городить свой кошмар.

                                                                                                                                                                                                                                                                                        Так а в чем проблема вызвать, я вообще в упор не понимаю? Что он сделать хочет? Там у него написан треш какой то непонятный.
                                                                                                                                                                                                                                                                                        Например, из того что я понял, вот всякие разные варианты, и далеко не последние:
                                                                                                                                                                                                                                                                                        https://rextester.com/FQLFU35600

                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                  public static void Main(string[] args)
                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                      string[] cmd = new string[] { @"C:\Documents and Settings\MyPath\", "--kill-all-humans", "except fry" };
                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                      var commandLine1 = String.Format("\"{0}\"", String.Join("\"", cmd));
                                                                                                                                                                                                                                                                                                      var commandLine2 = commandLine1.Replace(@"\", @"\\");
                                                                                                                                                                                                                                                                                                      var commandLine3 = commandLine2.Replace("\"", "\\\"");
                                                                                                                                                                                                                                                                                                      var commandLine4 = String.Format("\"{0}\"", String.Join("\"", cmd)).Replace(@"\", @"\\").Replace("\"", "\\\"");
                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                      var commandLine5 = String.Join("", cmd.Select(a => String.Format(" \"{0}\" ", a))).Replace(@"\", @"\\").Trim();
                                                                                                                                                                                                                                                                                                      var commandLine6 = String.Join("", cmd.Select(a => String.Format(" \"{0}\" ", a))).Replace(@"\", @"\\").Replace("\"", "\\\"").Trim();
                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine1);
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine2);
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine3);
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine4);
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine5);
                                                                                                                                                                                                                                                                                                      Console.WriteLine(commandLine6);
                                                                                                                                                                                                                                                                                                  }

                                                                                                                                                                                                                                                                                        Вывод:
                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                          "C:\Documents and Settings\MyPath\"--kill-all-humans"except fry"
                                                                                                                                                                                                                                                                                          "C:\\Documents and Settings\\MyPath\\"--kill-all-humans"except fry"
                                                                                                                                                                                                                                                                                          \"C:\\Documents and Settings\\MyPath\\\"--kill-all-humans\"except fry\"
                                                                                                                                                                                                                                                                                          \"C:\\Documents and Settings\\MyPath\\\"--kill-all-humans\"except fry\"
                                                                                                                                                                                                                                                                                          "C:\\Documents and Settings\\MyPath\\"  "--kill-all-humans"  "except fry"
                                                                                                                                                                                                                                                                                          \"C:\\Documents and Settings\\MyPath\\\"  \"--kill-all-humans\"  \"except fry\"

                                                                                                                                                                                                                                                                                        Пусть покажет как он сделал бы такое на С++.

                                                                                                                                                                                                                                                                                        Есть еще StringBuilder и регекспы, написать свою функцию экранирования - обычно не составляет труда, от слова совсем.
                                                                                                                                                                                                                                                                                        Плюс ко всему есть встроенные возможности:
                                                                                                                                                                                                                                                                                        https://docs.microsoft.com/en-us/dotnet/api...etframework-4.8
                                                                                                                                                                                                                                                                                        https://docs.microsoft.com/ru-ru/dotnet/csh...tokens/verbatim
                                                                                                                                                                                                                                                                                        Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                          Цитата OpenGL @

                                                                                                                                                                                                                                                                                          В Java — достаточно
                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                            Например, из того что я понял, вот всякие разные варианты, и далеко не последние:
                                                                                                                                                                                                                                                                                            https://rextester.com/FQLFU35600
                                                                                                                                                                                                                                                                                            Ну хз, Киля. Может вы там в своем шарпе привыкли к говну вроде
                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              String.Join("", cmd.Select(a => String.Format(" \"{0}\" ", a))).Replace(@"\", @"\\").Replace("\"", "\\\"").Trim();

                                                                                                                                                                                                                                                                                            А мы в своем D как-то привыкли к простому:
                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              import std.process;
                                                                                                                                                                                                                                                                                              ...
                                                                                                                                                                                                                                                                                              auto cmd = ["program.exe", `C:\Documents and Settings\MyPath\`, "--kill-all-humans", "except fry"];
                                                                                                                                                                                                                                                                                              ...
                                                                                                                                                                                                                                                                                              auto pid = spawnProcess(cmd);

                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                            Пусть покажет как он сделал бы такое на С++.
                                                                                                                                                                                                                                                                                            Он скорее дешник, чем плюсист. На плюсах еще хуже, ибо плюсы - таки какашка. Впрочем, возможно есть адекватная либка для этого.
                                                                                                                                                                                                                                                                                            Сообщение отредактировано: applegame -
                                                                                                                                                                                                                                                                                              Цитата applegame @
                                                                                                                                                                                                                                                                                              А мы в своем D как-то привыкли к простому:

                                                                                                                                                                                                                                                                                              твой код выдает:
                                                                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                td.process.ProcessException@std/process.d(380): Executable file not found: C:\Documents and Settings\MyPath\
                                                                                                                                                                                                                                                                                                ----------------
                                                                                                                                                                                                                                                                                                ??:? @trusted std.process.Pid std.process.spawnProcessImpl(scope const(char[])[], std.stdio.File, std.stdio.File, std.stdio.File, scope const(immutable(char)[][immutable(char)[]]), std.process.Config, const(char)[]) [0x55f41a88ab08]
                                                                                                                                                                                                                                                                                                ??:? @trusted std.process.Pid std.process.spawnProcess(scope const(char[])[], std.stdio.File, std.stdio.File, std.stdio.File, const(immutable(char)[][immutable(char)[]]), std.process.Configconst , char[]) [0x55f41a88a7d2]
                                                                                                                                                                                                                                                                                                onlineapp.d:7 _Dmain [0x55f41a875067]


                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                              Если нужно просто запустить программу, то кто ему мешает это сделать?
                                                                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                Process.Start("program.exe", String.Concat(Environment.GetCommandLineArgs()));
                                                                                                                                                                                                                                                                                              Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                                Цитата korvin @
                                                                                                                                                                                                                                                                                                Цитата OpenGL @

                                                                                                                                                                                                                                                                                                В Java — достаточно

                                                                                                                                                                                                                                                                                                Ты мои сообщения видел?
                                                                                                                                                                                                                                                                                                  Цитата korvin @
                                                                                                                                                                                                                                                                                                  Это вне программы делается.
                                                                                                                                                                                                                                                                                                  В Сях/Плюсах можно и из кода.

                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                  Цитата Wound @
                                                                                                                                                                                                                                                                                                  Пусть покажет как он сделал бы такое на С++.
                                                                                                                                                                                                                                                                                                  Не осилил сути проблемы.
                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                    твой код выдает:
                                                                                                                                                                                                                                                                                                    Ну а что он должен тебе выдать? :)
                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                    Если нужно просто запустить программу, то кто ему мешает это сделать?
                                                                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                      Process.Start("program.exe", String.Concat(Environment.GetCommandLineArgs()));

                                                                                                                                                                                                                                                                                                    Надо запустить программу со своими аргументами. А ты зачем-то предлагаешь брать в качестве аргументов Environment.GetCommandLineArgs().
                                                                                                                                                                                                                                                                                                    Цитата Qraizer @
                                                                                                                                                                                                                                                                                                    Не осилил сути проблемы.
                                                                                                                                                                                                                                                                                                    Суть:
                                                                                                                                                                                                                                                                                                    Цитата applegame @
                                                                                                                                                                                                                                                                                                    Ну вот есть у тебя список аргументов в виде массива строк, и надо вызвать стороннюю программу с этими аргументами. В аргументах есть пробелы и слеши/бэкслеши,

                                                                                                                                                                                                                                                                                                    В шарпе параметры передаются в запускаемый процесс только в виде строки, причем она должна быть уже экранирована. Человеку не понравилось, что надо руками городить это самое экранирование, которое, как оказывается, не такое уж и тривиальное.
                                                                                                                                                                                                                                                                                                    Сообщение отредактировано: applegame -
                                                                                                                                                                                                                                                                                                      Цитата Qraizer @
                                                                                                                                                                                                                                                                                                      Не осилил сути проблемы.

                                                                                                                                                                                                                                                                                                      Я если честно тоже. :-?
                                                                                                                                                                                                                                                                                                        Забейте, короче. Это все же тема Rust vs C++.
                                                                                                                                                                                                                                                                                                          Цитата applegame @
                                                                                                                                                                                                                                                                                                          Ну а что он должен тебе выдать?

                                                                                                                                                                                                                                                                                                          Понятия не имею. Речь я так понимаю идет про экранирование командной строки. Ну строку пусть выведет что ли, ты у меня спрашиваешь? :-?

                                                                                                                                                                                                                                                                                                          Цитата applegame @
                                                                                                                                                                                                                                                                                                          Надо запустить программу со своими аргументами. А ты зачем-то предлагаешь брать в качестве аргументов Environment.GetCommandLineArgs().

                                                                                                                                                                                                                                                                                                          Хорошо, что мешает тебе написать:
                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                        var cmd = "\"C:\\Documents and Settings\\MyPath\\\" --kill-all-humans \"except fry\"";
                                                                                                                                                                                                                                                                                                                        Process.Start("test.exe", cmd);

                                                                                                                                                                                                                                                                                                          ?

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

                                                                                                                                                                                                                                                                                                          А чем оно не тривиальное? ты можешь сделать это разными способами. Но человек выбрал самый убогий из всех, которые только можно придумать. И решил сделать так.
                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                            Хорошо, что мешает тебе написать:
                                                                                                                                                                                                                                                                                                            Например, то что аргументы пришли откуда-то извне, то есть заранее не известны.
                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                            А чем оно не тривиальное? ты можешь сделать это разными способами. Но человек выбрал самый убогий из всех, которые только можно придумать. И решил сделать так.
                                                                                                                                                                                                                                                                                                            Ну если ты хочешь некое универсальное экранирование, то не тривиально. Я же уже приводил ссылку на Stack Overflow с целыми простынями рассуждений и попыток найти универсальное решение этой задачи.

                                                                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                                                                            На плюсах тоже не просто. Microsoft тоже статью на эту тему запилили: Everyone quotes command line arguments the wrong way
                                                                                                                                                                                                                                                                                                            Сообщение отредактировано: applegame -
                                                                                                                                                                                                                                                                                                              Цитата applegame @
                                                                                                                                                                                                                                                                                                              Например, то что аргументы пришли откуда-то извне, то есть заранее не известны.

                                                                                                                                                                                                                                                                                                              Да и флаг им в руки откуда они пришли. Хоть с марса, пиши:
                                                                                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                var cmd = $"-key \"{param1}\" --kill-all-humans \"{param2}\"";

                                                                                                                                                                                                                                                                                                              String.Join - объединяет массив в строку с разделителем.
                                                                                                                                                                                                                                                                                                              String.Format - формирует строку - как тебе захочется

                                                                                                                                                                                                                                                                                                              Далее есть ArgumentList - который представляет из себя массив строк. Можешь прям в него запихать аргументы командной строки.
                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                Да и флаг им в руки откуда они пришли. Хоть с марса, пиши:
                                                                                                                                                                                                                                                                                                                Киля, это твое решение будет работать далеко не для любых param1 и param2. Почитай что-ли ссылки, которые я дал выше.
                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                Далее есть ArgumentList - который представляет из себя массив строк. Можешь прям в него запихать аргументы командной строки.

                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                Запрашиваемая страница недоступна для .NET Framework 4.8. Вы перенаправлены на последнюю версию продукта, для которой доступна эта страница.
                                                                                                                                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                                                                                                                                  Запрашиваемая страница недоступна для .NET Framework 4.8. Вы перенаправлены на последнюю версию продукта, для которой доступна эта страница.

                                                                                                                                                                                                                                                                                                                  https://docs.microsoft.com/ru-ru/dotnet/api...fo_ArgumentList
                                                                                                                                                                                                                                                                                                                  Цитата



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

                                                                                                                                                                                                                                                                                                                  public System.Collections.ObjectModel.Collection<string> ArgumentList { get; }

                                                                                                                                                                                                                                                                                                                  Значение свойства
                                                                                                                                                                                                                                                                                                                  Collection<String>

                                                                                                                                                                                                                                                                                                                  Коллекция аргументов командной строки.
                                                                                                                                                                                                                                                                                                                  Примеры

                                                                                                                                                                                                                                                                                                                  В этом примере в сведения о запуске процесса добавляются два аргумента.
                                                                                                                                                                                                                                                                                                                  C#

                                                                                                                                                                                                                                                                                                                  var info = new System.Diagnostics.ProcessStartInfo("names.exe");
                                                                                                                                                                                                                                                                                                                  info.ArgumentList.Add("-first Mary");
                                                                                                                                                                                                                                                                                                                  info.ArgumentList.Add("-last Smith");

                                                                                                                                                                                                                                                                                                                  Комментарии

                                                                                                                                                                                                                                                                                                                  ArgumentList, который поддерживается начиная с .NET Core 2,1 и .NET Standard 2,1, а Arguments свойство не зависит друг от друга. Это значит, что строки, назначенные ArgumentList коллекции, не используются для заполнения Arguments свойства, а строка, присвоенная Arguments свойству, не анализируется на отдельные строки, назначенные ArgumentList коллекции.

                                                                                                                                                                                                                                                                                                                  ArgumentListпроще в использовании, Arguments чем свойство. Так как каждая строка назначается элементу коллекции, можно выполнить одиночную, а не тройную escape-последовательность строк, разделенных кавычками. Например, следующий пример включает -full "Mary Smith" в себя как член ArgumentList коллекции:
                                                                                                                                                                                                                                                                                                                  C#

                                                                                                                                                                                                                                                                                                                  info.ArgumentList.Add("-full \"Mary Smith\"";

                                                                                                                                                                                                                                                                                                                  Arguments Свойство имеет соответствующее назначение:
                                                                                                                                                                                                                                                                                                                  C#

                                                                                                                                                                                                                                                                                                                  info.Arguments = "-full \"\"\"Mary Smith\"\"\""

                                                                                                                                                                                                                                                                                                                  При использовании этого свойства для задания аргументов Arguments командной строки необходимо установить пустую строку.
                                                                                                                                                                                                                                                                                                                  Применяется к
                                                                                                                                                                                                                                                                                                                  .NET Core
                                                                                                                                                                                                                                                                                                                  3.0 Preview 8 2.2 2.1


                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                                                                                                                                  Киля, это твое решение будет работать далеко не для любых param1 и param2. Почитай что-ли ссылки, которые я дал выше.

                                                                                                                                                                                                                                                                                                                  Ну ты ведь должен понимать что ты вообще ожидаешь? Это все что ты говоришь - синтетическая выдумка. Ну живет же как то народ. Я тебе выше написал разные вариации на тему, как можно.
                                                                                                                                                                                                                                                                                                                    M

                                                                                                                                                                                                                                                                                                                    Ввиду незрелости топик-стартера в плане идеологии Раста на момент создания топика - предлагаю переместить священные войны по топику в тему "Rust vs Чистейший Си"
                                                                                                                                                                                                                                                                                                                      А что, тема себя изжила, что ли, и никому больше нечего тут сказать? JoeUser, ты может быть что-то для себя и решил ...невероятный случай для холивара... но тема куда ширее.

                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                                                                                                                                      Суть:
                                                                                                                                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                                                                                                                                      Ну вот есть у тебя список аргументов в виде массива строк, и надо вызвать стороннюю программу с этими аргументами. В аргументах есть пробелы и слеши/бэкслеши,

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

                                                                                                                                                                                                                                                                                                                      Задача нерешаема без указания особенностей целевого приложения. Я вот не уверен, что кавычек для экранирования ему хватит.
                                                                                                                                                                                                                                                                                                                        !
                                                                                                                                                                                                                                                                                                                        Qraizer, признаю свою ошибку и тему открываю!
                                                                                                                                                                                                                                                                                                                        Кому интересна тема раста и плюсов - вэлком сюда!
                                                                                                                                                                                                                                                                                                                        Тема без ООП есть рядом.
                                                                                                                                                                                                                                                                                                                        Простите, погорячился!
                                                                                                                                                                                                                                                                                                                          Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                          Задача нерешаема без указания особенностей целевого приложения. Я вот не уверен, что кавычек для экранирования ему хватит.
                                                                                                                                                                                                                                                                                                                          Только кавычек однозначно не хватит, поэтому и пишут сложные регекспы. И почему это задача нерешаема, если ее давно уже решили.
                                                                                                                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                            Подожди. Вот есть у тебя в классе A метод foo. С какой-то реализацией. Наследники переопределили. Override не написали. Потом ты рефакторишь A и меняешь сигнатуру метода. Во всех наследниках код будет валиден и компилятору не к чему придраться, хотя это ошибка. Где-то ты поправил сам(потому что помнил), где-то свалились тесты. А где-то это уехало на прод :)
                                                                                                                                                                                                                                                                                                                            Не?

                                                                                                                                                                                                                                                                                                                            Это фатальный недостаток ООП вообще и наследования в частности. :trollface:

                                                                                                                                                                                                                                                                                                                            Если у тебя после этого все тесты остались зелёными, то либо никакой ошибки и вправду нет, и всё работает корректно, либо у тебя дерьмовые тесты и более серъёзные проблемы. =)

                                                                                                                                                                                                                                                                                                                            Чуть позже распишу про «фатальный недостаток», далеко не уходи. =) Вкратце, он в использовании одной сущности для разных вещей (правильно, ведь зачем плодить сущности, если всё можно сделать одной мегауниверсальной сущностью, да?)
                                                                                                                                                                                                                                                                                                                              Цитата korvin @
                                                                                                                                                                                                                                                                                                                              Если у тебя после этого все тесты остались зелёными, то либо никакой ошибки и вправду нет, и всё работает корректно, либо у тебя дерьмовые тесты и более серъёзные проблемы. =)

                                                                                                                                                                                                                                                                                                                              Ну почему? Они же, вероятно, как раз дергают методы класса, который тестируют, а не базового класса, и это нормально. И такие тесты будут продолжать проходить.
                                                                                                                                                                                                                                                                                                                                Цитата applegame @
                                                                                                                                                                                                                                                                                                                                И почему это задача нерешаема, если ее давно уже решили.
                                                                                                                                                                                                                                                                                                                                Сиречь придумали универсальный протокол, придерживаться которого должны обе стороны.Ага?
                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                  Подожди.


                                                                                                                                                                                                                                                                                                                                  Вот смотри, рассмотрим сначала на примере интерфейсов и Java.
                                                                                                                                                                                                                                                                                                                                  Здесь и далее одиночное слово «интерфейс» подразумевает собственно сущность «интерфейс», объявляемую ключевым словом interface, а словосочетание «интерфейс класса» — набор всех публичных методов класса. protected и package-private не будем рассматривать для простоты. private методы во всей этой вакханалии не участвуют по определению. =)
                                                                                                                                                                                                                                                                                                                                  Методы, унаследованные от java.lang.Object тоже опустим, предположим, что любой объявляемый без указания родителя класс не имеет никаких унаследованных публичных методов. Как в C++, в общем.

                                                                                                                                                                                                                                                                                                                                  Интерфейсы могут использоваться для двух конкретных целей:

                                                                                                                                                                                                                                                                                                                                  1. Поиметь несколько реализаций одного интерфейса под разные случаи жизни
                                                                                                                                                                                                                                                                                                                                  Классы в этом случае
                                                                                                                                                                                                                                                                                                                                  – реализуют только этот один публичный интерфейс
                                                                                                                                                                                                                                                                                                                                  – не имеют публичных методов сверх того
                                                                                                                                                                                                                                                                                                                                  – да и сами не публичны

                                                                                                                                                                                                                                                                                                                                  Пример: java.util.Iterator, его имплементации обычно
                                                                                                                                                                                                                                                                                                                                  – не реализуют никаких других публичных интерфейсов
                                                                                                                                                                                                                                                                                                                                  – не имеют других публичных методов
                                                                                                                                                                                                                                                                                                                                  – являются приватными классами коллекций, для которых реализуют итерацию

                                                                                                                                                                                                                                                                                                                                  2. «Сузить» интерфейс класса для частных случаев
                                                                                                                                                                                                                                                                                                                                  Например, некий класс MutableQueue может реализовывать интерфейсы ReadableQueue и WritableQueue и использоваться в том или ином качестве по ситуации: одним клиентам будет отдаваться интерфейс только для чтения, другим — только для записи, а где-то будет использоваться и сам класс MutableQueue. Либо клиентам может отдаваться ещё более узкий интерфейс, например Iterable вместо конкретного ArrayList, используемого в качестве приватного поля объекта-контейнера.


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

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

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

                                                                                                                                                                                                                                                                                                                                  Естественно на практике часто бывают не только два этих крайних варианта, но и разного рода смеси.

                                                                                                                                                                                                                                                                                                                                  To be continued…

                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                  Они же, вероятно, как раз дергают методы класса, который тестируют, а не базового класса, и это нормально. И такие тесты будут продолжать проходить.

                                                                                                                                                                                                                                                                                                                                  Значит и использование классов продолжить быть корректной. В чём проблема?
                                                                                                                                                                                                                                                                                                                                  Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                                                                                    Значит и использование классов будет продолжать быть корректным.

                                                                                                                                                                                                                                                                                                                                    При использовании через базовый класс/интерфейс не будет :)

                                                                                                                                                                                                                                                                                                                                    Портянки твои завтра уже прочитаю скорее всего :)
                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                      При использовании через базовый класс/интерфейс не будет

                                                                                                                                                                                                                                                                                                                                      Ты не включил в тесты производного класса тестирование методов из базового? Плохой тест. Тест должен тестировать класс целиком, а не только новые (по сравнению с базовым классом) методы. Плохие тесты.
                                                                                                                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                                                                                                                        Ты не включил в тесты производного класса тестирование методов из базового?

                                                                                                                                                                                                                                                                                                                                        Включил. И они проходят, потому что теперь тестируют методы нового класса.
                                                                                                                                                                                                                                                                                                                                          Цитата korvin @
                                                                                                                                                                                                                                                                                                                                          …Продолжение последовало


                                                                                                                                                                                                                                                                                                                                          Теперь выделим оба варианта в отдельные сущности следующим образом:
                                                                                                                                                                                                                                                                                                                                          – для первого варианта будем использовать interface, дополнив её опциональным контрактом
                                                                                                                                                                                                                                                                                                                                          – для второго введём новую сущность и назовём её, например, protocol
                                                                                                                                                                                                                                                                                                                                          – для поддержки первого варианта классы теперь не могут быть использованы в качестве типа переменной, только интерфейсы и протоколы
                                                                                                                                                                                                                                                                                                                                          – класс не может быть просто унаследован от другого класса без описания расширенного интерфейса

                                                                                                                                                                                                                                                                                                                                          Для примера возьмём Iterable, Iterator, Set, HashSet и TreeSet из java.util. Рассмотрим только небольшое подмножество реализованных в JDK методов. Так же опустим некоторые детали реализаций, типа требования имплементации Comaparable для элементов TreeSet.

                                                                                                                                                                                                                                                                                                                                          Set у нас будет interface, Iterable — protocol, HashSet и TreeSet — классами, реализующими Set и удовлетворяющими Iterable. Т.е. в псевдо-Java:

                                                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                            package jdk.collections
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            import jdk.iter.Iterator // Note: not Iterable but Iterator
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            public interface Set<A> {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                int size()
                                                                                                                                                                                                                                                                                                                                                boolean add(A a)
                                                                                                                                                                                                                                                                                                                                                boolean remove(A a)
                                                                                                                                                                                                                                                                                                                                                Iterator<A> iterator() // Note that Set is not extending/implementing/whatever-relating-to Iterable so no "override" needed
                                                                                                                                                                                                                                                                                                                                            } contract {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                void should_not_contain_duplicates() {
                                                                                                                                                                                                                                                                                                                                                    ...
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                            package jdk.collections
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            class HashSet<A> implements Set<A> {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                // fields and constructors
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                // no need for "override" or specifying "public"
                                                                                                                                                                                                                                                                                                                                                // because all not-private methods are implementations of Set interface only
                                                                                                                                                                                                                                                                                                                                                int size() {
                                                                                                                                                                                                                                                                                                                                                    ...
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                boolean add(A a) {
                                                                                                                                                                                                                                                                                                                                                    ...
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                boolean remove(A a) {
                                                                                                                                                                                                                                                                                                                                                    ...
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                Iterator<A> iterator() {
                                                                                                                                                                                                                                                                                                                                                    ...
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                // private helping methods if needed
                                                                                                                                                                                                                                                                                                                                                // private methods are not comming from Set and do not override any Set method by design
                                                                                                                                                                                                                                                                                                                                                // so no need for "override"
                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                // Same thing: java.iter.Iterator is an interface
                                                                                                                                                                                                                                                                                                                                                private class Iterator<A> implements java.iter.Iterator<A> {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                    // some implementation
                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                          И то же самое для TreeSet, только с другой внутренней реализацией, само собой.

                                                                                                                                                                                                                                                                                                                                          Далее мы имеем protocol Iterable, определённый где-то в дргуом месте:

                                                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                            package jdk.iter
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            protocol Iterable<A> {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                Iterator<A> iterator()
                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                          и далее используем это всё вместе:

                                                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                            package my.coolapp
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            import jdk.collections.*
                                                                                                                                                                                                                                                                                                                                            import jdk.iter.*
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                            public void main(String[] args) {
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                HashSet<String> words = new HashSet<>()  // -- compilation error: class cannot be used as a type
                                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                                                Set<String> words = new HashSet<>()      // -- ok
                                                                                                                                                                                                                                                                                                                                                var words = new HashSet<String>()        // -- ok, the type of words is Set<String>
                                                                                                                                                                                                                                                                                                                                                Iterable<String> words = new HashSet<>() // -- ok since Set has a method `Iterator<A> iterator()` which is required by Iterable
                                                                                                                                                                                                                                                                                                                                            }


                                                                                                                                                                                                                                                                                                                                          Зачем это всё? Чтобы лучше всё структурировать вместо каши из override и non-override методов, чтобы IDE лучше понимала семантику кода, в частности выполняла семантически более точный рефакторинг при изменении сигнатуры методов «родителей», который мы тут обсуждали. + один набор юнит-тестов на разные реализации. И при этом добавить некоторую гибкость в виде протоколов. Хз как там в ваших D/Rust/C#, но без аналога Go'шных интерфейсов или OCaml'овских object type'ов в Java грустновато.

                                                                                                                                                                                                                                                                                                                                          Но это только интерфейсы, осталось разобрать наследование реализаций (классов)…


                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                          Включил. И они проходят, потому что теперь тестируют методы нового класса.

                                                                                                                                                                                                                                                                                                                                          Я таки не понимаю, что тебя не устраивает: тесты проходят, значит поведение осталось корректым. Если тесты проходят, но поведение некорректно, значит тесты некорректны.

                                                                                                                                                                                                                                                                                                                                          Давай пример кодом: как было до рефакторинга, как стало и что не так, а то я что-то не могу понять, на что ты жалуешься.
                                                                                                                                                                                                                                                                                                                                            Цитата korvin @
                                                                                                                                                                                                                                                                                                                                            Тест должен тестировать класс целиком, а не только новые (по сравнению с базовым классом) методы.
                                                                                                                                                                                                                                                                                                                                            Зачем? На эти методы можно натравить имеющиеся тесты.
                                                                                                                                                                                                                                                                                                                                              Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                              Сиречь придумали универсальный протокол, придерживаться которого должны обе стороны.Ага?
                                                                                                                                                                                                                                                                                                                                              Более-менее придумали.
                                                                                                                                                                                                                                                                                                                                                Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                Давай пример кодом: как было до рефакторинга, как стало и что не так, а то я что-то не могу понять, на что ты жалуешься.

                                                                                                                                                                                                                                                                                                                                                Ну вот был такой класс:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  class A
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                  public:
                                                                                                                                                                                                                                                                                                                                                      virtual ~A() = default;
                                                                                                                                                                                                                                                                                                                                                      virtual std::string foo() const
                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                          return "A";
                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                  };


                                                                                                                                                                                                                                                                                                                                                И тест
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  void testA()
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                      A a;
                                                                                                                                                                                                                                                                                                                                                      assert(a.foo() == "A");
                                                                                                                                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                                                                                                                                                И вот какой-то из наследников:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  class B: public A
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                  public:
                                                                                                                                                                                                                                                                                                                                                      virtual std::string foo() const
                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                          return "B";
                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                  };


                                                                                                                                                                                                                                                                                                                                                И его тест
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  void testB()
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                      B b;
                                                                                                                                                                                                                                                                                                                                                      assert(b.foo() == "B");
                                                                                                                                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                                                                                                                                                В реальном коде используем как-то так:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                      auto ptr= factory->make_instance(...);
                                                                                                                                                                                                                                                                                                                                                  ...
                                                                                                                                                                                                                                                                                                                                                      std::cout << ptr->foo() << std::endl;


                                                                                                                                                                                                                                                                                                                                                Все ок, если создадим экземпляр B, то будет выведено "B".

                                                                                                                                                                                                                                                                                                                                                Теперь рефакторили и заменили сигнатуру:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  class A
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                  public:
                                                                                                                                                                                                                                                                                                                                                      virtual ~A() = default;
                                                                                                                                                                                                                                                                                                                                                      virtual std::string foo(int x) const
                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                          return "A";
                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                  };


                                                                                                                                                                                                                                                                                                                                                Подправили тесты:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                  void testA()
                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                      A a;
                                                                                                                                                                                                                                                                                                                                                      assert(a.foo(10) == "A");
                                                                                                                                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                                                                                                                                                Подправили использование:
                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                      auto ptr= factory->make_instance(...);
                                                                                                                                                                                                                                                                                                                                                  ...
                                                                                                                                                                                                                                                                                                                                                      std::cout << ptr->foo(10) << std::endl;


                                                                                                                                                                                                                                                                                                                                                Подправили тех наследников, о которых помнили.
                                                                                                                                                                                                                                                                                                                                                А вот про B забыли.

                                                                                                                                                                                                                                                                                                                                                В результате, теперь в случае экземпляра B, выводиться будет A.

                                                                                                                                                                                                                                                                                                                                                И, внезапно, если бы там был override, то компилятор бы ругался и никакой проблемы бы не возникло.

                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                Зачем это всё? Чтобы лучше всё структурировать вместо каши из override и non-override методов, чтобы IDE лучше понимала семантику кода, в частности выполняла семантически более точный рефакторинг при изменении сигнатуры методов «родителей», который мы тут обсуждали. + один набор юнит-тестов на разные реализации. И при этом добавить некоторую гибкость в виде протоколов.

                                                                                                                                                                                                                                                                                                                                                Я правильно понимаю, что это все потребует нового языка? :D

                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                Хз как там в ваших D/Rust/C#, но без аналога Go'шных интерфейсов или OCaml'овских object type'ов в Java грустновато.

                                                                                                                                                                                                                                                                                                                                                Вот тут не понял. Зачем тебе goшные интерфейсый в java?

                                                                                                                                                                                                                                                                                                                                                Цитата

                                                                                                                                                                                                                                                                                                                                                Но это только интерфейсы, осталось разобрать наследование реализаций (классов)…

                                                                                                                                                                                                                                                                                                                                                Это будет ближе к практике?

                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                И, внезапно, если бы там был override, то компилятор бы ругался и никакой проблемы бы не возникло.

                                                                                                                                                                                                                                                                                                                                                Изначальный пример http://ideone.com/cac3Ss
                                                                                                                                                                                                                                                                                                                                                После рефакторинга http://ideone.com/kuCrur
                                                                                                                                                                                                                                                                                                                                                Если бы был override http://ideone.com/SieIBM

                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                error: ‘std::__cxx11::string B::foo() const’ marked ‘override’, but does not override
                                                                                                                                                                                                                                                                                                                                                std::string foo() const override
                                                                                                                                                                                                                                                                                                                                                Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                  И тест

                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                  И его тест

                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                  Все ок, если создадим экземпляр B, то будет выведено "B".

                                                                                                                                                                                                                                                                                                                                                  В твоем примере слово virtual абсолютно бессмысленно. Создай подобие интерфейса и перепиши свой код вот так:
                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                    struct Base
                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                       virtual string foo() const = 0;
                                                                                                                                                                                                                                                                                                                                                       virtual ~Base() = 0;
                                                                                                                                                                                                                                                                                                                                                    };

                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                    class A : public Base
                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                    public:
                                                                                                                                                                                                                                                                                                                                                        virtual ~A() = default;
                                                                                                                                                                                                                                                                                                                                                        virtual std::string foo() const
                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                            return "A";
                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                    };

                                                                                                                                                                                                                                                                                                                                                  Потом перепиши тесты:

                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                    void testA()
                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                        std::uniqe_ptr<Base> pA = std::make_uniqe<A>();
                                                                                                                                                                                                                                                                                                                                                        assert(pA->foo(10) == "A");
                                                                                                                                                                                                                                                                                                                                                    }

                                                                                                                                                                                                                                                                                                                                                  А вот после этого меняй сигнатуру. Тогда будет правильно.

                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                  Ну или хотя бы в тесте testB сделай динамическое создание класса B, присвоей его переменной базового класса А. У тебя ведь А базовый, присутствуют виртуальные функции. Соответственно ты будешь работать с базовым классом, а не напрямую с B/A.
                                                                                                                                                                                                                                                                                                                                                  Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                    В твоем примере слово virtual абсолютно бессмысленно.

                                                                                                                                                                                                                                                                                                                                                    Ты о чем-то своем. Мы обсуждаем пользу override при рефакторинге. При чем тут интерфейсы?

                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                    присвоей его переменной базового класса А.

                                                                                                                                                                                                                                                                                                                                                    И часто ты в тестах такой каст делаешь?
                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                      Ты о чем-то своем. Мы обсуждаем пользу override при рефакторинге. При чем тут интерфейсы?

                                                                                                                                                                                                                                                                                                                                                      Ну речь то зашла изначально про интефрейсы.

                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                      И часто ты в тестах такой каст делаешь?

                                                                                                                                                                                                                                                                                                                                                      Какой такой каст делаю? Это обычный дин. полиморфизм называется. У тебя в твоем примере тесты отличаются от реальной работы классов. Т.е. тесты живут своей жизнью, программа живет своей жизнью. Не совсем понятно что ты тестишь. Посмотри на свои функции тестирования, и посмотри на использование:

                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                        auto ptr= factory->make_instance(...);
                                                                                                                                                                                                                                                                                                                                                        ...
                                                                                                                                                                                                                                                                                                                                                            std::cout << ptr->foo(10) << std::endl;

                                                                                                                                                                                                                                                                                                                                                      Я не вижу использования классов A/B, зато я вижу нечто базовое, через которое может вызваться в зависимости от типа тот или другой метод.
                                                                                                                                                                                                                                                                                                                                                      Раз ты у себя в коде пишешь:
                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                        auto ptr= factory->make_instance(...);

                                                                                                                                                                                                                                                                                                                                                      Значит это же у тебя должно быть и в тестах. Либо на крайняк, если ты не хочешь тестировать фабрику, должно быть так, как я написал выше, а именно работа через базовый класс.
                                                                                                                                                                                                                                                                                                                                                      Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                        Ну речь то зашла изначально про интефрейсы.

                                                                                                                                                                                                                                                                                                                                                        Это обсуждение уже давно откололось от того :)

                                                                                                                                                                                                                                                                                                                                                        Цитата
                                                                                                                                                                                                                                                                                                                                                        У тебя в твоем примере тесты отличаются от реальной работы классов. Т.е. тесты живут своей жизнью, программа живет своей жизнью. Не совсем понятно что ты тестишь.

                                                                                                                                                                                                                                                                                                                                                        Работу класса я тестирую.

                                                                                                                                                                                                                                                                                                                                                        Цитата

                                                                                                                                                                                                                                                                                                                                                        Раз ты у себя в коде пишешь:
                                                                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                          auto ptr= factory->make_instance(...);

                                                                                                                                                                                                                                                                                                                                                        Значит это же у тебя должно быть и в тестах

                                                                                                                                                                                                                                                                                                                                                        Это уже будет не юнит-тестирование.
                                                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                          Это уже будет не юнит-тестирование.

                                                                                                                                                                                                                                                                                                                                                          А что это будет?

                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                          Работу класса я тестирую.

                                                                                                                                                                                                                                                                                                                                                          В таком случае у тебя нет ошибки. И поведение абсолютно предсказуемое. К чему претензия? :D

                                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                                          D_KEY, вот представь я пишу все тоже самое, но у меня B не наследуется от А, ну просто два разных класса, с одинаковым методом. А потом вдруг кто то подумает и решит короче, B унаследовать от А, и заодно изменит вот как ты сигнатуру у А. Ну и все далее как у тебя. Что в этом случае не так? Тесты плохие? Или что?
                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                            D_KEY, вот представь я пишу все тоже самое, но у меня B не наследуется от А, ну просто два разных класса, с одинаковым методом. А потом вдруг кто то подумает и решит короче, B унаследовать от А, и заодно изменит вот как ты сигнатуру у А. Ну и все далее как у тебя. Что в этом случае не так? Тесты плохие? Или что?

                                                                                                                                                                                                                                                                                                                                                            Просто странный код будет :D
                                                                                                                                                                                                                                                                                                                                                            Я не понимаю, о чем ты сейчас. Мы говорим о пользе override. Я просто привел пример, когда он поможет. И все.
                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                              Просто странный код будет
                                                                                                                                                                                                                                                                                                                                                              Я не понимаю, о чем ты сейчас. Мы говорим о пользе override. Я просто привел пример, когда он поможет. И все.

                                                                                                                                                                                                                                                                                                                                                              Так ты прочитай что тебе написали в этом посте: Rust vs C++ (сообщение #3808312)
                                                                                                                                                                                                                                                                                                                                                              И потом посмотри что ты ответил.
                                                                                                                                                                                                                                                                                                                                                              Тебе говорят, что override нафиг не нужен, например в той же Java, потому что надо писать вот так то и так то, вот об этом написано:
                                                                                                                                                                                                                                                                                                                                                              Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                              Зачем это всё? Чтобы лучше всё структурировать вместо каши из override и non-override методов, чтобы IDE лучше понимала семантику кода, в частности выполняла семантически более точный рефакторинг при изменении сигнатуры методов «родителей», который мы тут обсуждали. + один набор юнит-тестов на разные реализации. И при этом добавить некоторую гибкость в виде протоколов. Хз как там в ваших D/Rust/C#, но без аналога Go'шных интерфейсов или OCaml'овских object type'ов в Java грустновато.

                                                                                                                                                                                                                                                                                                                                                              А ты в ответ пишешь, что он будет делать, если забудет гдето там написать override.
                                                                                                                                                                                                                                                                                                                                                              override - синтаксический сахар по сути, который просто лишний раз может тебе сказать что у тебя не совпадают сигнатуры базового и производного методов. Но использование его, еще не означает что ты проектируешь систему правильно. И раз у тебя возникают такие ошибки, и тебе помог override, значит скорее всего будут и другие ошибки, на которые синтаксического сахара не найдется.
                                                                                                                                                                                                                                                                                                                                                              Ну это как скажем assert что ли. То что он есть, еще не спасает тебя от ошибок.
                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                может тебе сказать что у тебя не совпадают сигнатуры базового и производного методов.

                                                                                                                                                                                                                                                                                                                                                                Так и я про то.

                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                Но использование его, еще не означает что ты проектируешь систему правильно.

                                                                                                                                                                                                                                                                                                                                                                А кто говорит о проектировании систем?

                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                И раз у тебя возникают такие ошибки, и тебе помог override, значит скорее всего будут и другие ошибки, на которые синтаксического сахара не найдется.

                                                                                                                                                                                                                                                                                                                                                                Например?

                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                потому что надо писать вот так то и так то

                                                                                                                                                                                                                                                                                                                                                                Это уже совсем из другой области вопрос.
                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                  Например?

                                                                                                                                                                                                                                                                                                                                                                  Например что у тебя factory->make_instance(...); будет работать не так, как ты ожидаешь.

                                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                  Это уже совсем из другой области вопрос.

                                                                                                                                                                                                                                                                                                                                                                  Ну не знаю, просто у вас тогда странный разговор получается. Тебе объясняют почему в принципе не нужен override, а ты объясняешь от чего он спасает. Так если не писать так, как ты показал - то нафиг этот override нужен то? :D
                                                                                                                                                                                                                                                                                                                                                                    А причём тут вообще проектирование? override ему ортогонален совершенно.
                                                                                                                                                                                                                                                                                                                                                                      Между прочим в С++ override появился сравнительно недавно. И до него как то не особо припомню вот таких вот проблем. Обычно все разруливалось ЮТ.

                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                      Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                      А причём тут вообще проектирование? override ему ортогонален совершенно.

                                                                                                                                                                                                                                                                                                                                                                      Ну как выяснилось у некоторых не ортогонален.
                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                        Например?

                                                                                                                                                                                                                                                                                                                                                                        Например что у тебя factory->make_instance(...); будет работать не так, как ты ожидаешь.

                                                                                                                                                                                                                                                                                                                                                                        С чего вдруг?

                                                                                                                                                                                                                                                                                                                                                                        Цитата
                                                                                                                                                                                                                                                                                                                                                                        Тебе объясняют почему в принципе не нужен override, а ты объясняешь от чего он спасает. Так если не писать так, как ты показал - то нафиг этот override нужен то? :D

                                                                                                                                                                                                                                                                                                                                                                        Потому что это всего-лишь пример. Иллюстрация.
                                                                                                                                                                                                                                                                                                                                                                        Ты не всегда сможешь отследить изменение сигнатуры в реальном проекте.

                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                        Между прочим в С++ override появился сравнительно недавно. И до него как то не особо припомню вот таких вот проблем.

                                                                                                                                                                                                                                                                                                                                                                        А для чего добавили, на твой взгляд?

                                                                                                                                                                                                                                                                                                                                                                        Цитата
                                                                                                                                                                                                                                                                                                                                                                        Обычно все разруливалось ЮТ.

                                                                                                                                                                                                                                                                                                                                                                        Во-первых, ЮТ не являются частью языка. Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.
                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                          С чего вдруг?

                                                                                                                                                                                                                                                                                                                                                                          Да просто так, оно ж у тебя в тестах не тестируется. Мало ли там что пойдет не так, вместо класса A, создастся класс B например или наоборот.

                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                          Потому что это всего-лишь пример. Иллюстрация.
                                                                                                                                                                                                                                                                                                                                                                          Ты не всегда сможешь отследить изменение сигнатуры в реальном проекте.

                                                                                                                                                                                                                                                                                                                                                                          А раньше как отслеживал? :D

                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                          А для чего добавили, на твой взгляд?

                                                                                                                                                                                                                                                                                                                                                                          А они как бы все в язык несут, все новомодности модные собирают со всех языков и несут в язык. Чтоб было. :D
                                                                                                                                                                                                                                                                                                                                                                          Ну как синтаксический сахар конечно пойдет. Я ж не против override'ов.

                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                          Во-первых, ЮТ не являются частью языка. Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.

                                                                                                                                                                                                                                                                                                                                                                          Незнаю, мне напротив попадалось другое. Пишешь ЮТ - которые эмулируют работу, с помощью тех же mock объектов. Как правило помимо самих функций - тестируется еще и функционал который они делают. Потому как в 99% случаев, бывает такое, что для того, что бы юзнуть функцию в ЮТ, для нее нужно настроить окружение. А это подразумевает имитирование работы части функционала.
                                                                                                                                                                                                                                                                                                                                                                          Например там функция ждет от тебя какой нибудь коннектор, провайдер, поток с данными и т.д. чтоб дальше с ним работать, или например еще что то, и а те в свою очередь, для того чтоб вернули ожидаемые значения могут еще что то принимать, что в свою очередь может принимать еще другое. И в итоге ты начинаешь делать mock объекты и эмулировать работу программы в ЮТ. Где практически все косяки, в том числе и те, которые ты написал зачастую всплывают.
                                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                            Да просто так, оно ж у тебя в тестах не тестируется.

                                                                                                                                                                                                                                                                                                                                                                            С чего ты взял? Фабрика тестируется отдельно. В своем юнит-тесте.

                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                            А они как бы все в язык несут, все новомодности модные собирают со всех языков и несут в язык. Чтоб было. :D

                                                                                                                                                                                                                                                                                                                                                                            Понятно :D

                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                            Пишешь ЮТ - которые эмулируют работу, с помощью тех же mock объектов. Как правило помимо самих функций - тестируется еще и функционал который они делают. Потому как в 99% случаев, бывает такое, что для того, что бы юзнуть функцию в ЮТ, для нее нужно настроить окружение. А это подразумевает имитирование работы части функционала.
                                                                                                                                                                                                                                                                                                                                                                            Именно так.

                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                            Например там функция ждет от тебя какой нибудь коннектор, провайдер, поток с данными и т.д. чтоб дальше с ним работать, или например еще что то, и а те в свою очередь, для того чтоб вернули ожидаемые значения могут еще что то принимать, что в свою очередь может принимать еще другое. И в итоге ты начинаешь делать mock объекты и эмулировать работу программы в ЮТ.

                                                                                                                                                                                                                                                                                                                                                                            Верно.

                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                            Где практически все косяки, в том числе и те, которые ты написал зачастую всплывают.

                                                                                                                                                                                                                                                                                                                                                                            Да как он у тебя выплывет? Класс B тестируется только в юнит-тесте класса B. В остальных юнит-тестах будет mock-объект вместо реального.
                                                                                                                                                                                                                                                                                                                                                                            Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                              Именно так.

                                                                                                                                                                                                                                                                                                                                                                              У тебя в тестах не так. Если бы у тебя в тестах было бы так, то в одной из тестовой функций ты бы получил ошибку.

                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                              Да как он у тебя выплывет? Класс B тестируется только в юнит-тесте класса B. В остальных юнит-тестах будет mock-объект вместо реального.

                                                                                                                                                                                                                                                                                                                                                                              Ну вся фишка в том, что в твоем случае не тестируется дин. полиморфизм. Т.е. ты просто протестировал в отрыве от функционала два метода двух разных классов. Хотя по факту у тебя там наследование, которое ты не тестируешь.
                                                                                                                                                                                                                                                                                                                                                                              Т.е. другими словами ты написал класс Млекопитающее, написал класс Собака, проверил их методы, но поведение сущности ты не проверил. Допустим в явошарпах, там тестируется буквально все, моки там нужны разве что для объектов, которые невозможно съэмитировать с помощью тестов. Например там физическая железка какая то. А так - даже БД создать можно. Поэтому не совсем понял о каком mock-Объекте ты говоришь. У тебя будет Mock-Объект, вместо тестируемого класса? :-?
                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                У тебя в тестах не так.

                                                                                                                                                                                                                                                                                                                                                                                Мои "тесты" - это лишь пример. Покажи "правильные" тесты для данного случая, кстати.

                                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                                Ну вся фишка в том, что в твоем случае не тестируется дин. полиморфизм.

                                                                                                                                                                                                                                                                                                                                                                                А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                                Хотя по факту у тебя там наследование, которое ты не тестируешь.

                                                                                                                                                                                                                                                                                                                                                                                А ты тестируешь наследование?

                                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                                Допустим в явошарпах, там тестируется буквально все, моки там нужны разве что для объектов, которые невозможно съэмитировать с помощью тестов.

                                                                                                                                                                                                                                                                                                                                                                                Чего? Mock-объекты и нужны для тестов.

                                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                                У тебя будет Mock-Объект, вместо тестируемого класса? :-?

                                                                                                                                                                                                                                                                                                                                                                                Нет, тестируемый класс как раз не Mock. А все его окружение, которое в реальном коде будет реальными объектами, в тестах сделано через Mock-объекты.

                                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                                В моем примере в других тестах(не A и не B), вместо реальных объектов было бы Mock-объект, наследованный от A:
                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                  class MockA: public A {
                                                                                                                                                                                                                                                                                                                                                                                      MOCK_CONST_METHOD0(foo, std::string());
                                                                                                                                                                                                                                                                                                                                                                                  };

                                                                                                                                                                                                                                                                                                                                                                                А после рефакторинга стал бы:
                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                  class MockA: public A {
                                                                                                                                                                                                                                                                                                                                                                                      MOCK_CONST_METHOD1(foo, std::string(int));
                                                                                                                                                                                                                                                                                                                                                                                  };

                                                                                                                                                                                                                                                                                                                                                                                И во всех тестах, кроме тестов A, использовался бы он.
                                                                                                                                                                                                                                                                                                                                                                                Если используется не gtest/gmock, а какой-то другой фреймворк, то код был бы чуть другой, но суть та же.
                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  Мои "тесты" - это лишь пример. Покажи "правильные" тесты для данного случая, кстати.

                                                                                                                                                                                                                                                                                                                                                                                  Так я тебе уже показывал.

                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                                                                                                                                                                                                                                                                                                                                                                                  Практически постоянно вижу, что работают все через интерфейсы. Через классы вообще мало кто работает.

                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  А ты тестируешь наследование?

                                                                                                                                                                                                                                                                                                                                                                                  Почему нет? Я же его для чего то там написал, раз написал - значит нужно тестировать. А ты не тестируешь поведение, да? Тестируешь только голые методы классов?

                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  Чего? Mock-объекты и нужны для тестов.

                                                                                                                                                                                                                                                                                                                                                                                  Для каких тестов? Mock-объекты нужны для имитации того, что ты не можешь иметь в ЮТ. Допустим - это может быть БД, Флешка, какое то устройство, еще чего то, какой нибудь контекст, который получается путем сложных манипуляций и т.д.

                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  Нет, тестируемый класс как раз не Mock. А все его окружение, которое в реальном коде будет реальными объектами, в тестах сделано через Mock-объекты.

                                                                                                                                                                                                                                                                                                                                                                                  Ну ты пишешь что у тебя вот та фишка: factory->make_instance(...); будет где то там в Mock Объекте или вообще будет mock'Ом. Я если честно не понял ничего из того что ты пишешь. Зачем это будет моком? И что он в данном случае будет делать? :D Для чего он нужен другими словами? Ты же не будешь вызывать методы классов через него и проверять значения.

                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                  В моем примере в других тестах(не A и не B), вместо реальных объектов было бы Mock-объект, наследованный от A:

                                                                                                                                                                                                                                                                                                                                                                                  Слишком скудная информация. И как это потом использовать? Т.е. ты возвращаешь из метода что то, что не соответствует реальному результату? Что ты тогда тестишь то? У тебя явно тут идет расхождение в предложенных тестах и моках. Я если честно не совсем понимаю тебя.
                                                                                                                                                                                                                                                                                                                                                                                    Wound, ты не знаешь, что такое mock объекты и как они используются?

                                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                    Практически постоянно вижу, что работают все через интерфейсы. Через классы вообще мало кто работает.

                                                                                                                                                                                                                                                                                                                                                                                    Ты пишешь тест на класс. Что значит никто не тестит через классы? Покажи плиз свой обычный тест на класс.

                                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                                    Wound, я не понимаю тебя, извини.

                                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                    Mock-объекты нужны для имитации того, что ты не можешь иметь в ЮТ. Допустим - это может быть БД, Флешка, какое то устройство, еще чего то, какой нибудь контекст, который получается путем сложных манипуляций и т.д.

                                                                                                                                                                                                                                                                                                                                                                                    Именно. В результате у тебя при тесте конкретного класса другие конкретные классы, как правило, не задействованы. Вместо них у тебя будет mock- объект с нужным интерфейсом.
                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                      Wound, ты не знаешь, что такое mock объекты и как они используются?

                                                                                                                                                                                                                                                                                                                                                                                      Знаю, я не понимаю, зачем делать так, как ты пишешь.

                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                      Ты пишешь тест на класс. Что значит никто не тестит через классы? Покажи плиз свой обычный тест на класс.

                                                                                                                                                                                                                                                                                                                                                                                      Ок, вот у тебя есть метод класса, который принимает две сущности, и линкует одну к другой:
                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                        class EntityLinker
                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                        public:
                                                                                                                                                                                                                                                                                                                                                                                           virtual bool LinkToContainer(IContainer* orgUnit, IPrincipal* principal)
                                                                                                                                                                                                                                                                                                                                                                                           {
                                                                                                                                                                                                                                                                                                                                                                                               if(orgUnit != nullptr && principal != nullptr)
                                                                                                                                                                                                                                                                                                                                                                                               {
                                                                                                                                                                                                                                                                                                                                                                                                   return orgUnit->Link(principal);
                                                                                                                                                                                                                                                                                                                                                                                               }
                                                                                                                                                                                                                                                                                                                                                                                               return false;
                                                                                                                                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                                                                                                                                        };

                                                                                                                                                                                                                                                                                                                                                                                      У тебя вместо IPrincipal может быть например CUser, или там CPrinter, или может быть даже COrganizationUnit. В нашем случае это классы A и B. У юзера и принтера тоже есть свои какие то методы, и они тестируются отдельно.
                                                                                                                                                                                                                                                                                                                                                                                      Я в тесте буду писать:
                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                        void testLinkToContainer()
                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                            /*Тут, вместо new даже может быть Mock, который будет делать все тоже самое, кроме физического создания контейнера в системе, например как в примере создавать эксземпляр класса, напихивать в него данные, возвращать его, но не сохранять в системе*/
                                                                                                                                                                                                                                                                                                                                                                                            IContainer* pContainer = new COrgUnit(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            /*Тут ровно тоже самое, создается либо через mock, либо напрямую нужный класс, забивается данными*/
                                                                                                                                                                                                                                                                                                                                                                                            IPrincipal* pPrincipal = new Personage(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            //! Допустим через интерфейс создаем юзер аккаунт, который нужен будет для линковки
                                                                                                                                                                                                                                                                                                                                                                                            pPrincipal->CreateUserAccountPersonage();
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            EntityLinker* linker = new EntiryLinker(...);
                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                            //! Дальше тут какие то проверки, что все засетаплено честно.
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            //! Дальше собственно выполняем нашу линковку:
                                                                                                                                                                                                                                                                                                                                                                                            linker->LinkToContainer(pContainer, pPrincipal);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                           /*Дальше идет тестирование результатов линковки*/
                                                                                                                                                                                                                                                                                                                                                                                        }

                                                                                                                                                                                                                                                                                                                                                                                      Собственно вот у нас есть вот такая структура, как ты ее будешь тестить? Ну вот линковку?
                                                                                                                                                                                                                                                                                                                                                                                      На сколько я понял, ты будешь писать что то типа:
                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                        void testLinkToContainer()
                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                            /*Тут, вместо new даже может быть Mock, который будет делать все тоже самое, кроме физического создания контейнера в системе, например как в примере создавать эксземпляр класса, напихивать в него данные, возвращать его, но не сохранять в системе*/
                                                                                                                                                                                                                                                                                                                                                                                            COrgUnit unit(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            /*Тут ровно тоже самое, создается либо через mock, либо напрямую нужный класс, забывается данными*/
                                                                                                                                                                                                                                                                                                                                                                                            CAccountPrincipal principal(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            //! Что вот с этим делать? Такого метода нема у CAccountPrincipal
                                                                                                                                                                                                                                                                                                                                                                                            //pPrincipal->CreateUserAccountPersonage();
                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                            EntityLinker* linker = new EntiryLinker(...);
                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                            //! Дальше тут какие то проверки, что все засетаплено честно.
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                            //! Дальше собственно выполняем нашу линковку:
                                                                                                                                                                                                                                                                                                                                                                                            linker->LinkToContainer(&unit, &principal);
                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                           /*Дальше идет тестирование результатов линковки*/
                                                                                                                                                                                                                                                                                                                                                                                        }

                                                                                                                                                                                                                                                                                                                                                                                      Верно? А если тебе до линковки нужно будет вызвать какой нибудь метод, который есть в базовом классе IContainer/IPrincipal, но нет в том, который ты пытаешься протестить? Что делать? :-?
                                                                                                                                                                                                                                                                                                                                                                                      Обычно ЮТ, можно тестировать как отдельные методы, так и функционал в целом, когда ты уже начинает писать ЮТ для классов, которые юзают твои вот эти А/B.
                                                                                                                                                                                                                                                                                                                                                                                      Напиши как ты будешь тестить и куда прикручивать моки?

                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                      Wound, я не понимаю тебя, извини.

                                                                                                                                                                                                                                                                                                                                                                                      Я если честно тоже не понимаю тебя. Ты заглушки тестишь что ли? Или что? Я так и не понял.

                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                      Именно. В результате у тебя при тесте конкретного класса другие конкретные классы, как правило, не задействованы. Вместо них у тебя будет mock- объект с нужным интерфейсом.
                                                                                                                                                                                                                                                                                                                                                                                      "I

                                                                                                                                                                                                                                                                                                                                                                                      Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:
                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                        Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:

                                                                                                                                                                                                                                                                                                                                                                                        Ты слышал про IoC?

                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                        ...
                                                                                                                                                                                                                                                                                                                                                                                        Верно?

                                                                                                                                                                                                                                                                                                                                                                                        Нет. Тесты будут разные на все три класса. Линкер твой вообще не будет знать ничего про конкретные классы и в его тестах вместо них будут mock-объекты, реализующие IContainer и IPrincipal, соответственно.

                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                        А если тебе до линковки нужно будет вызвать какой нибудь метод, который есть в базовом классе IContainer/IPrincipal, но нет в том, который ты пытаешься протестить?

                                                                                                                                                                                                                                                                                                                                                                                        Чего? Еще раз, мы о модульных тестах. Для твоего примера будет три отдельных теста. А в тесте linker'а будут использоваться не COrgUnit и Personage, а mock'и, реализующие IContainer и IProncipal, что позволит мне, например, отслеживать вызовы методов этих интерфейсов, проверять, что они вырвались нужное число раз, написать тесты на аргументы и т.д.
                                                                                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                          Ты слышал про IoC?

                                                                                                                                                                                                                                                                                                                                                                                          Слышал, как это к теме относится?


                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                          Нет. Тесты будут разные на все три класса. Линкер твой вообще не будет знать ничего про конкретные классы и в его тестах вместо них будут mock-объекты, реализующие IContainer и IPrincipal, соответственно.

                                                                                                                                                                                                                                                                                                                                                                                          Конечно разные на все три класса, меня интересует как ты будешь тестить линкер. Он ежели чего, и так не знает про конкретные классы. Так ты мок объекты тестить будешь или что?
                                                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                            Так другие конкретные классы - это у тебя всегда сущности, которые ты не можешь создать в ЮТ? :blink:

                                                                                                                                                                                                                                                                                                                                                                                            Зачем их там создавать, если можно и нужно работать через интерфейсы?

                                                                                                                                                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                            меня интересует как ты будешь тестить линкер

                                                                                                                                                                                                                                                                                                                                                                                            Создам два mock'а, свяжу, проверю связь. Если нужно, чтоб дергались методы интерфейсов, проверю, что дергается нужное число раз и с ожидаемыми параметрами(gmock это позволяет).
                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                              Зачем их там создавать, если можно и нужно работать через интерфейсы?

                                                                                                                                                                                                                                                                                                                                                                                              Вот теперь я тебя вообще перестал понимать. Ты до этого писал:
                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                              А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                              Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.

                                                                                                                                                                                                                                                                                                                                                                                              Теперь ты уже пишешь совершенно противоположное. :-?

                                                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                              Создам два mock'а, свяжу, проверю связь. Если нужно, чтоб дергались методы интерфейсов, проверю, что дергается нужное число раз и с ожидаемыми параметрами(gmock это позволяет).

                                                                                                                                                                                                                                                                                                                                                                                              Что эти моки будут делать? Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?
                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                Зачем их там создавать, если можно и нужно работать через интерфейсы?

                                                                                                                                                                                                                                                                                                                                                                                                Вот теперь я тебя вообще перестал понимать. Ты до этого писал:
                                                                                                                                                                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                А ты часто видишь, чтобы кто-то явно кастил к базовому классу?

                                                                                                                                                                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                Во-вторых, я мало видел тестов, где бы кастили к базовому классу. Возможно, все кастят, а мне попадалось говно. Но это ничего на самом деле не меняет.

                                                                                                                                                                                                                                                                                                                                                                                                Теперь ты уже пишешь совершенно противоположное. :-?

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

                                                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?

                                                                                                                                                                                                                                                                                                                                                                                                Ну я уже написал, например, проверять, что дернул нужные методы нужное число раз с соответствующими аргументами.

                                                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                Зачем их создавать, если у тебя есть возможность уже использовать существующие классы например?

                                                                                                                                                                                                                                                                                                                                                                                                А зачем использовать существующие классы? У них свои тесты есть. Это же модульное тестирование. Кроме того, реализаций обычно несколько, какую выбрать? Моки обычно позволяют сделать дополнительные проверки.
                                                                                                                                                                                                                                                                                                                                                                                                  Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                  Зачем? На эти методы можно натравить имеющиеся тесты.

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

                                                                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                  В результате, теперь в случае экземпляра B, выводиться будет A.

                                                                                                                                                                                                                                                                                                                                                                                                  Так у тебя тесты неправильные, вот ты сам себе и выстрелил в ногу. Тестовый набор для B не должен был включать в себя тесты для родительского метода foo(). В твоём случае такое перекрытие foo в B нарушает контракт (описанный в тесте для A.foo) родительского класса, который гласит, что метод foo() должен возвращать "A". А ты взял и в наследнике нарушил этот контракт. Тесты нельзя оверрайдить. Если ты вдруг это сделал (как в этом примере), тебе стоит тут же ударить себя по рукам, остановиться, подумать и решить: либо класс B не является наследником класса A, т.к. реализует другой контракт, либо контракт в тесте описан некорректно.
                                                                                                                                                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                    Тестовый набор для B не должен был включать в себя тесты для родительского метода foo(). В твоём случае такое перекрытие foo в B нарушает контракт (описанный в тесте для A.foo) родительского класса, который гласит, что метод foo() должен возвращать "A".

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

                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                    либо класс B не является наследником класса A, т.к. реализует другой контракт, либо контракт в тесте описан некорректно.

                                                                                                                                                                                                                                                                                                                                                                                                    Да не реализует он другой контракт. Ты, по-моему, на ходу выдумываешь.

                                                                                                                                                                                                                                                                                                                                                                                                    Ну ок, давай уберем тест foo для B. Мой пример остается валидным. Без override код молча скомпилируется при изменении сигнатуры.
                                                                                                                                                                                                                                                                                                                                                                                                    Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                      Я правильно понимаю, что это все потребует нового языка?

                                                                                                                                                                                                                                                                                                                                                                                                      Не обязательно, существующие могут постепенно эволюционировать. «Внешние» интерфейсы (которые у меня названы protocol) есть в некоторых языках, например, OCaml и Go. Что-то похожее вроде было в Objective-C, возможно, есть и в Swift. Думаю, такие интерфейсы постепенно приобретут широкую популярность и будут постепенно добавлены во все мейнстримные языки. Лямбды ж добавили в консервативную Java =). В некоторм смысле и шаблоны C++ являются таковыми, только compile-time.

                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                      Вот тут не понял. Зачем тебе goшные интерфейсый в java?

                                                                                                                                                                                                                                                                                                                                                                                                      Затем, что если тупые разработчики какой-нибудь библиотеки не предусмотрели общие интерфейсы для sibling-классов, то приходится приседать с бубном, чтобы написать обощённый код. Например, Eclipse'овский SWT: у многих виджетов есть методы `String getText()` и `void setText(String text)`, но при этом они не реализуют какой-нибудь общий интерфейс `HasTextProperty { String getText(); void setText(String) }` и написать какой-нибудь обобщённый код для них просто так нельзя. На выбор такие костыли:

                                                                                                                                                                                                                                                                                                                                                                                                      – написать свои классы, которые наследую SWT'шные и имплементируют нужные интерфейсы, например:
                                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                        public class MyLabel extends swt.Label implements HasText {}

                                                                                                                                                                                                                                                                                                                                                                                                      слава б-гу не нужно явно перечислять методы и писать @Override (ха-ха). Теперь нужно везде использовать эти свои классы, писать свои фабрики вместо тех, что уже есть в самом swt и т.п.

                                                                                                                                                                                                                                                                                                                                                                                                      – воспользоваться рефлексией и написать тройку вспомогательных статических методов где-нибудь в своём UIUtil классе или типа того:
                                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                        boolean hasText(swt.Widget w) { ... }
                                                                                                                                                                                                                                                                                                                                                                                                        String getText(swt.Widget w) { ... }
                                                                                                                                                                                                                                                                                                                                                                                                        void setText(swt.Widget w, String newText) { ... }

                                                                                                                                                                                                                                                                                                                                                                                                      как ты понимаешь, ООП и статическая типизация тут идут лесом.

                                                                                                                                                                                                                                                                                                                                                                                                      В Go же мне было бы достаточно определить в своём коде
                                                                                                                                                                                                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                        type HasText interface {
                                                                                                                                                                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                                                                            GetText() String
                                                                                                                                                                                                                                                                                                                                                                                                            SetText(String)
                                                                                                                                                                                                                                                                                                                                                                                                        }


                                                                                                                                                                                                                                                                                                                                                                                                      и всё. Все классы с такими методами автоматически годились бы для использования в коде, ожидающем объекты такого интерфейсного типа.

                                                                                                                                                                                                                                                                                                                                                                                                      То же самое и с объектными типами в OCaml.

                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                      Это будет ближе к практике?

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

                                                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                      С чего ты взял, что у него такой контракт?

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

                                                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                      Да не реализует он другой контракт. Ты, по-моему, на ходу выдумываешь.

                                                                                                                                                                                                                                                                                                                                                                                                      Ты, по-моему, совсем забыл про LSP, например. И про то, что далеко не во всех языках можно описать полноценно контракт чисто системой типов, поэтому она дополняется применяется тестированием.

                                                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                      D_KEY, может, мы по-разному понимаем слово «контракт»? «Спецификация» тебя больше устроит? Не знаю, «набор инвариантов»?
                                                                                                                                                                                                                                                                                                                                                                                                      Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                        С того, что он описан в тесте. Тесты существуют, чтобы описывать контракты, невыразимые языковыми средствами

                                                                                                                                                                                                                                                                                                                                                                                                        Я тебе привел пример, когда такой код не будет нарушением контракта.
                                                                                                                                                                                                                                                                                                                                                                                                        Еще пример - класс исключений и метод, возвращающий сообщение об ошибке. У разных классов будут разные значения. Тесты можно не писать на это дело, а можно и написать.
                                                                                                                                                                                                                                                                                                                                                                                                        Контракт это нарушать не будет.

                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                        И, повторяю еще раз. Тесты не имеют отношения к моему примеру. Их можно вообще убрать.
                                                                                                                                                                                                                                                                                                                                                                                                        А пример о том, что изменение сигнатуры метода в базовом классе может пройти незаметно без override, а это может являться ошибкой.
                                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                          Пусть это будет метод, возвращающий некое описание класса, например.

                                                                                                                                                                                                                                                                                                                                                                                                          Что значит «некое описание класса»? Если оно «некое», динамическое, для каждого наследника A разное, то нельзя в тесте для A этого не учитывать и хардкодить expected как просто "A", т.к. тест testA не пройдёт для наследников A, как у тебя не пройдёт даже до рефакторинга для B, а должен, потому что B — субтип A и должен следовать LSP и спецификации супертипа (A) соответственно.

                                                                                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                          Я тебе привел пример, когда такой код не будет нарушением контракта.

                                                                                                                                                                                                                                                                                                                                                                                                          Где? Я пропустил, видимо. Понапишут своих портянок, а потом коды не замечают =)

                                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                          У разных классов будут разные значения.

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

                                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                          И, повторяю еще раз. Тесты не имеют отношения к моему примеру. Их можно вообще убрать.

                                                                                                                                                                                                                                                                                                                                                                                                          Если их убрать, то в чём пример? Приведи пример кода без тестов.

                                                                                                                                                                                                                                                                                                                                                                                                          Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                          А пример о том, что изменение сигнатуры метода в базовом классе может пройти незаметно без override, а это может являться ошибкой.

                                                                                                                                                                                                                                                                                                                                                                                                          А может и не являться. И может пройти заметно без override, если IDE не тупая как пробка и видит методы с той же сигнатурой. Я ж уже писал, что Java'вские IDE и так прекрасно показывают, что метод пререопределяет родительский, без аннотации @Override. Точно также IDE это видит и при рефакторинге, если тебе хочется, чтобы она это учитывала. Так зачем явно писать override?
                                                                                                                                                                                                                                                                                                                                                                                                          Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                                                                                                                                                                                            D_KEY, вот смотри до рефакторинга, после рефакторинга и после фикса спецификации. Если бы спецификация изначально была бы корректная, то не пришлось бы её фиксить. В твоём же рабочем процессе (автоматический апдейт дочерних сигнатур или просто ошибки на неуместный оверрайд) девелопер просто будет молча убирать оверрайд / подгонять тело метода под новую сигнатуру (или просто игнорировать новый параметр), совершенно не задумываясь, поменялась ли спецификация родительского класса или нет. В общем, просто уборка мусора под ковёр.
                                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                              В первом случае идет речь о тесте самого класса. Я, наверное, никогда не видел, чтобы в тесте класса перед вызовами унаследованных функций объект явно кастили к базовому(а только это спасло бы помимо override в моем примере).

                                                                                                                                                                                                                                                                                                                                                                                                              Ну и? Сам функционал же ты будешь тестировать? Ты же у себя в программе написал не просто A a; a.foo, а через фабрику эти сущности создаешь. А в тестах у тебя этого нет. Я тебе на это и указал в самом начале.

                                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                              Ну я уже написал, например, проверять, что дернул нужные методы нужное число раз с соответствующими аргументами.

                                                                                                                                                                                                                                                                                                                                                                                                              Где проверять? И зачем проверять сколько раз ты что там дернул? Я не совсем понял.

                                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                              А зачем использовать существующие классы? У них свои тесты есть. Это же модульное тестирование. Кроме того, реализаций обычно несколько, какую выбрать? Моки обычно позволяют сделать дополнительные проверки.

                                                                                                                                                                                                                                                                                                                                                                                                              Как зачем? А как проверять работу? Моки чтоли тестировать? Так это просто заглушки, для имитации того, что ты не можешь получить в ЮТ. Если у тебя несколько реализаций - обычно все нужно тестировать. В идеале. Чтоб у тебя всевозможные сценарии отрабатывали. На практике правда, это не всегда достижимо.
                                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                Как зачем? А как проверять работу? Моки чтоли тестировать? Так это просто заглушки, для имитации того, что ты не можешь получить в ЮТ.

                                                                                                                                                                                                                                                                                                                                                                                                                В ЮТ ты проверяешь работу своего модуля, а не всего подряд.

                                                                                                                                                                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                Если у тебя несколько реализаций - обычно все нужно тестировать

                                                                                                                                                                                                                                                                                                                                                                                                                Так оно и будет протестировано. Для каждой реализации будет свой ЮТ.
                                                                                                                                                                                                                                                                                                                                                                                                                Зачем тестить все реализации в тесте линкера? Он же работает через интерфейсы. В его ЮТ нужно тестить его работу.

                                                                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                Где проверять? И зачем проверять сколько раз ты что там дернул? Я не совсем понял.

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

                                                                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                Чуть позже могу показать на gmock'е
                                                                                                                                                                                                                                                                                                                                                                                                                Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                  В ЮТ ты проверяешь работу своего модуля, а не всего подряд.

                                                                                                                                                                                                                                                                                                                                                                                                                  Конечно. Я так понял классы эти - А и B ты написал, и на этом работа с ними закончена? Ты их будешь как то использовать? Скорее будешь. Вот и напишешь соответствующие ЮТ на их использование. Это уже будет тестирование другого модуля, которые в идеале и должен выявить ошибку в твоем рефакторинге.

                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                  Так оно и будет протестировано. Для каждой реализации будет свой ЮТ.
                                                                                                                                                                                                                                                                                                                                                                                                                  Зачем тестить все реализации в тесте линкера? Он же работает через интерфейсы. В его ЮТ нужно тестить его работу.

                                                                                                                                                                                                                                                                                                                                                                                                                  Ну потому что у тебя есть разные сущности. Например ты протестировал связь CUser с OrgUnit, а связь OrgUnit с OrgUnit не будет выполнятся, потому как для нее нужно сделать больше телодвижений. Ок, возьми не Link, может там эта не совсем очевидно. Возьми например перемещение.
                                                                                                                                                                                                                                                                                                                                                                                                                  Можно перемещать как User, так и OrgUnit в другой OrgUnit, но разница в работе будет очевидна. Когда ты перемещаешь User - тебе нужно просто взять его и переместить, а когда перемещаешь OrgUnit то нужно сделать больше проверок и работы. Например нужно убедится что у тебя OrgUnit не перемещается в тот же самый, нужно как то разорвать связь в дереве OrgUnitov где был старый и обновить новое.
                                                                                                                                                                                                                                                                                                                                                                                                                  Как ты будешь это тестировать? Передашь OrgUnit и CUser - работает, и флаг ему в руки, работу перемещения я протестировал?
                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                    Дерьмовые классы, нарушающие LSP. Или дерьмовая спецификация (а значит и тесты), не учитывающие эту динамику.

                                                                                                                                                                                                                                                                                                                                                                                                                    Ты предлагаешь не тестить конкретные реализации? Ещё раз, вот иерархия ошибок. Метод string message(). Он должен возвращать у всех классов в иерархии одно и то же? :crazy:
                                                                                                                                                                                                                                                                                                                                                                                                                    Почему это нарушение контакта? Или ты предлагаешь не тестить конкретные реализации? Почему?
                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                      Ну допустим твой линкер должен дёрнуть такой-то метод одного интерфейса и такой-то другого. Ты создаешь мок-реализации интерфейсов и проверяешь, что эти вызовы были сделаны нужное число раз и с заданными параметрами.

                                                                                                                                                                                                                                                                                                                                                                                                                      А тестирую я что? Что у меня будет в Expected и Actual ? Количество вызовов? Тогда я не совсем понимаю, что я тестирую.
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                        Ну допустим твой линкер должен дёрнуть такой-то метод одного интерфейса и такой-то другого. Ты создаешь мок-реализации интерфейсов и проверяешь, что эти вызовы были сделаны нужное число раз и с заданными параметрами.

                                                                                                                                                                                                                                                                                                                                                                                                                        А тестирую я что? Что у меня будет в Expected и Actual ? Количество вызовов? Тогда я не совсем понимаю, что я тестирую.

                                                                                                                                                                                                                                                                                                                                                                                                                        Работу линкера, это же его ЮТ.

                                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                        Ты их будешь как то использовать? Скорее будешь. Вот и напишешь соответствующие ЮТ на их использование.

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

                                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                        Wound, видел я такие ЮТ, какие ты хочешь, которые пол системы поднимают для тестов одного модуля :crazy:

                                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                        Или я тебя не понял.

                                                                                                                                                                                                                                                                                                                                                                                                                        Давай другой пример рассмотрим.

                                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                        Если их убрать, то в чём пример? Приведи пример кода без тестов.

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

                                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                        D_KEY, вот смотри

                                                                                                                                                                                                                                                                                                                                                                                                                        Да, можно написать тесты, которые это отловят, но не факт, что именно такие тесты были написаны. И не факт, что ты можешь написать такой обобщенный тест в случае конкретного метода (в данном случае ты смог вычислить нужное значение в тесте, а если бы там не было привязки к типу?)
                                                                                                                                                                                                                                                                                                                                                                                                                        Т.е. может быть ситуация, когда контракт базового класса или интерфейса не накладывает строгих ограничений на значение, но это не мешает написать тест на этот метод для каждой конкретной реализации, если ты знаешь, как он должен формироваться. И даже если ты не станешь это тестить, то от проблемы никак не уйдешь.
                                                                                                                                                                                                                                                                                                                                                                                                                        Кроме того, с override ты это отловишь на этапе компиляции. Мне казалось, что ты всегда за это. Кроме того, ты смешиваешь в одну кучу язык, тесты, IDE и процессы :)
                                                                                                                                                                                                                                                                                                                                                                                                                        Написать override там, где ты хотел перекрыть метод - очень просто. Как и отследить это при ревью кода.
                                                                                                                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                          Я ж уже писал, что Java'вские IDE и так прекрасно показывают, что метод пререопределяет родительский, без аннотации @Override. Точно также IDE это видит и при рефакторинге, если тебе хочется, чтобы она это учитывала. Так зачем явно писать override?

                                                                                                                                                                                                                                                                                                                                                                                                                          То, что видит IDE - это фактическое состояние дел, а писать @Override явно - это декларация твоих намерений. Слегка разные назначения, как мне кажется.
                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                            Работу линкера, это же его ЮТ.

                                                                                                                                                                                                                                                                                                                                                                                                                            Та ка нахрен мне тестировать его в отрыве от сущностей, которыми он манипулирует? Ты ж собрался мок наследовать от IContainer/IPrincipal и писать там свой функционал паралельно. Ну напишешь ты - у тебя с моком будет работать, а в каком нибудь CUser/COrgUnit не будет работать, потому что из класса выше, кто то по ошибке убрал твой override. И все, приплыли? Да и тебе не кажется, что писать паралельно какие то моки на все подряд - это излишняя, бесполезная работа?
                                                                                                                                                                                                                                                                                                                                                                                                                            Я все равно не понимаю зачем так делать :-? Никогда такого не видел, ни в С++, ни в C#, ни где то еще.

                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                            Их будут использовать через интерфейсы. И те, кто их использует, ничего о них не знает, потому в тестах нет никакого смысла использовать эти конкретные реализации. У них есть свои ЮТ, которые проверяют корректность их работы.

                                                                                                                                                                                                                                                                                                                                                                                                                            Так ты же выше написал что в ЮТ тоже будешь юзать интерфейсы, тогда какие проблемы? Я если честно вот вообще не понимаю, что ты мне рассказываешь.

                                                                                                                                                                                                                                                                                                                                                                                                                            У тебя получается что я тестирую исключительно то, что написано в методе, не учитывая совершенно поведение системы в целом. Т.е. у меня ожидаются два каких то класса на входе, с двумя каким то методами, которые нужно вызвать, я беру мочу эти два класса у тебя в ЮТ, делая их методы пустыми, ну или возвращающими константы, и потом эти классы передаю в функцию тестирования функционала. У меня оно как то отрабатывает, но в итоге, что я протестил то? :D Что 2 + 2 = 4 ? Не, ну круто, че. А потом в проде, у тебя хренак, и поплыли баги со всех щелей, потому что у тебя тесты и близко не имитируют то, как работает программа.

                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                            Wound, видел я такие ЮТ, какие ты хочешь, которые пол системы поднимают для тестов одного модуля

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

                                                                                                                                                                                                                                                                                                                                                                                                                            Используя моки ты как раз отдаляешься от реальности, но в конкретном случае, этой реальностью можно пренебречь, поэтому ты и будешь юзать вот тут мок.
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                              Ну напишешь ты - у тебя с моком будет работать, а в каком нибудь CUser/COrgUnit не будет работать

                                                                                                                                                                                                                                                                                                                                                                                                                              Почему не будет-то? У них есть свои тесты, они проверяют. Ты похоже не понимаешь, что такое ЮТ.

                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              что писать паралельно какие то моки на все подряд - это излишняя, бесполезная работа?

                                                                                                                                                                                                                                                                                                                                                                                                                              Не понимаю, о чем ты.
                                                                                                                                                                                                                                                                                                                                                                                                                              Вот есть у тебя класс. Он использует какие-то объекты через интерфейсы.
                                                                                                                                                                                                                                                                                                                                                                                                                              Зачем в его тесте использовать какие-то конкретные объекты, а не моки? Тем более, что их вообще может не быть у тебя(например, клиент предоставляет) или они на другом уровне системы.

                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              Я если честно вот вообще не понимаю, что ты мне рассказываешь.

                                                                                                                                                                                                                                                                                                                                                                                                                              Взаимно.

                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              У тебя получается что я тестирую исключительно то, что написано в методе, не учитывая совершенно поведение системы в целом

                                                                                                                                                                                                                                                                                                                                                                                                                              ЮТ и не должны(да и не могут) учитывать поведение всей системы, для этого есть другие тесты.

                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              Т.е. у меня ожидаются два каких то класса на входе, с двумя каким то методами, которые нужно вызвать, я беру мочу эти два класса у тебя в ЮТ, делая их методы пустыми, ну или возвращающими константы, и потом эти классы передаю в функцию тестирования функционала

                                                                                                                                                                                                                                                                                                                                                                                                                              Моки могут быть довольно сложными.

                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              У меня оно как то отрабатывает, но в итоге, что я протестил то?

                                                                                                                                                                                                                                                                                                                                                                                                                              Этот модуль.

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

                                                                                                                                                                                                                                                                                                                                                                                                                              ЮТ и не должны этим заниматься. Они проверяют работу конкретных модулей. Потому они так и называются, внезапно.

                                                                                                                                                                                                                                                                                                                                                                                                                              Давай какой-то пример рассмотрим? Я покажу на нем.
                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата D_KEY @

                                                                                                                                                                                                                                                                                                                                                                                                                                Давай какой-то пример рассмотрим? Я покажу на нем.

                                                                                                                                                                                                                                                                                                                                                                                                                                - У вас есть книги по садомазохизму?
                                                                                                                                                                                                                                                                                                                                                                                                                                - Да.
                                                                                                                                                                                                                                                                                                                                                                                                                                - Бросьте мне одну в лицо!
                                                                                                                                                                                                                                                                                                                                                                                                                                :facepalm:
                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  Почему не будет-то? У них есть свои тесты, они проверяют. Ты похоже не понимаешь, что такое ЮТ.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Кого они проверяют? Я тебе говорю, что для какой то операции, необходимо вызвать какой то метод из этих классов явно/неявно.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  Вот есть у тебя класс. Он использует какие-то объекты через интерфейсы.
                                                                                                                                                                                                                                                                                                                                                                                                                                  Зачем в его тесте использовать какие-то конкретные объекты, а не моки? Тем более, что их вообще может не быть у тебя(например, клиент предоставляет) или они на другом уровне системы.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Смотря какие объекты в нем используются. Почему бы не использовать конкретные объекты, вместо моков? Ты на все зависимые сущности моки пишешь?

                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  ЮТ и не должны(да и не могут) учитывать поведение всей системы, для этого есть другие тесты.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Не всей системы, а только той части, которая тестируется.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  Моки могут быть довольно сложными.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Могут, и чего? Я тебе пишу про то, что ты можешь в моке не учесть, какую то вещь, которая есть в используемом классе.

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

                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  Этот модуль.

                                                                                                                                                                                                                                                                                                                                                                                                                                  А функционал работы/взаимодействия, не?

                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                  ЮТ и не должны этим заниматься. Они проверяют работу конкретных модулей. Потому они так и называются, внезапно.

                                                                                                                                                                                                                                                                                                                                                                                                                                  Так все верно. У тебя есть три модуля, первый это Пользовател, второй Контейнер, трейти Линковщик. И буду у тебя три модульных теста. Первый у тебя протестирует пользователя, второй Контейнер, а третий Линковку пользователя и контейнера. В итоге ты протестировал функционал своей системы. Я лично понимаю это так.
                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                    Я тебе говорю, что для какой то операции, необходимо вызвать какой то метод из этих классов явно/неявно.

                                                                                                                                                                                                                                                                                                                                                                                                                                    В линковщике? Ну ты же их через интерфейс используешь? Вот и замокай его в тесте линковщика. В чем проблема?

                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                    Почему бы не использовать конкретные объекты, вместо моков?

                                                                                                                                                                                                                                                                                                                                                                                                                                    Потому, что тест линковщика, который использует интерфейсы, а не конкретные объекты, не должен иметь зависимость от конкретных реализаций интерфейсов. Ему это не нужно.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                    Ты на все зависимые сущности моки пишешь?

                                                                                                                                                                                                                                                                                                                                                                                                                                    Если работа идет через интерфейсы, то да. Не могу вспомнить контрпример.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                    Не всей системы, а только той части, которая тестируется.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Так тестируется только конкретный модуль. И ничего больше. Мы же о ЮТ говорим.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                    Я тебе пишу про то, что ты можешь в моке не учесть, какую то вещь, которая есть в используемом классе.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Так у тебя этих конкретных классов может быть 100500. У них свои тесты есть. Понимаешь?

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

                                                                                                                                                                                                                                                                                                                                                                                                                                    Это хреновая декомпозиция системы. Я тебя не зря спросил про IoC. Хотя лучше про dependency inversion principle сказать.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                    Так все верно. У тебя есть три модуля, первый это Пользовател, второй Контейнер, трейти Линковщик.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Может другой пример?
                                                                                                                                                                                                                                                                                                                                                                                                                                    Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                                      Да, я, видимо, неточно выразился. Я имел в виду, что для класса нужно прогонять не только тесты для его собственных методов, но и тесты для всех методов, унаследованных от родительских классов.
                                                                                                                                                                                                                                                                                                                                                                                                                                      Ещё одно хорошее "зачем": разве не достаточно тестом показать факт наследования тестируемого класса от интересующего нас базового? Разве не следует из гарантий языка программирования заранее известный (однозначно предсказываемый) итог запуска тестов на наследуемых методах?
                                                                                                                                                                                                                                                                                                                                                                                                                                        D_KEY, мне кажется мы о разном говорим.
                                                                                                                                                                                                                                                                                                                                                                                                                                        У меня одна картина в голове стоит, у тебя вторая. Поэтому не понимаем друг друга. Ты мне пишешь про тестирование каких то несвязанных вещей, я напротив больше сталкивался с взаимосвязанными системами.
                                                                                                                                                                                                                                                                                                                                                                                                                                        Когда например у тебя один класс, инкапсулирует в себе кучу логики, которая инкапсулирует в себе другую кучу логики, которая инкапсулирует в себе еще какую то кучу логики.
                                                                                                                                                                                                                                                                                                                                                                                                                                        Я не знаю, может быть ты рассказываешь с философской точки зрения. Но хотел бы я посмотреть как ты все это тестировал бы.

                                                                                                                                                                                                                                                                                                                                                                                                                                        Например была такая система на позапрошлой работе, сервер Unix, клиент Windows. Есть продукт со своей логикой, к этой логике вешается требование, что клиент не зависит от версии сервера в принципе. Ну и архитектор налабал там систему классов по примеру Java Beans, т.е. чтоб написать одну сущность, тебе нужно сразу писать 4-5 классов. 1 класс - интерфейс, 2 класс - имплементация, 3 класс - фабрика, 4 класс - хендл, который в себе все это скрывает через 5 класс прокси объект. Все это завязано на каком то жестком контексте, который я разгребал пол года, чтобы понять из чего он состоит. Просто тупо целая куча самых разный мелких типов, персистентные объекты, какие то там еще объекты, это все еще обернуто впридачу высокоуровневыми шаблонами, десятиэтажное наследование. Ты пишешь какой нибудь класс WorkstationRedirection, который оперирует не вот этими классами A и B, а целыми объектами, потому что по другому ты не протестируешь, на все это есть ЮТ. Вот я бы посмотрел сколько бы ты писал свои моки для одного ЮТ, когда тебе нужно протестировать логику перемещения спесимена из одной рабочей станции на другую, где чтобы съимитировать объекты на моках, пришлось бы городить хренову тучу кода и тратить примерно столько же времени, сколько на разработку самого функционала. И моки там были, только нужны они были для замены сервера/клиента/БД/файлвой системы/ит.д. не более.

                                                                                                                                                                                                                                                                                                                                                                                                                                        А ты мне рассказываешь про какую то философию программирования.
                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                          Ты мне пишешь про тестирование каких то несвязанных вещей, я напротив больше сталкивался с взаимосвязанными системами.
                                                                                                                                                                                                                                                                                                                                                                                                                                          Нет, он тебе рассказывает о технологии тестирования связанных систем по отдельности.
                                                                                                                                                                                                                                                                                                                                                                                                                                          Элементарнейший пример – функция вызывает функцию с параметрами: ты можешь написать отдельный тест на вызываемую функцию, которую прочекаешь по полной программе, по всем диапазонам классов эквивалентности всех её входов, не исключая параметры, и убедишься, что она ведёт себя полностью в рамках её модели поведения, описываемой документацией; затем ты пишешь другой тест, на этот раз на вызывающую функцию, соблюдая те же принципы и опираясь на её модель поведения.
                                                                                                                                                                                                                                                                                                                                                                                                                                          При создании второго теста ты вполне имеешь право застабить вызываемую, и пусть она ведёт себя не по её задокументированной модели, это уже неважно. Важно, что её поведение тесту известно, и его не надо тестировать, ведь по сути она его составная часть, и это поведение значительно проще, и им можно легко управлять из теста. При этом вместо того, чтобы учитывать модель поведения вызываемой функции, этому тесту достаточно лишь прочекать, что вызывающая (тестируемая на данном этапе) функция правильно выставляет входы для мока и правильно потребляет результаты его работы.
                                                                                                                                                                                                                                                                                                                                                                                                                                          Т.к. предыдущий тест чекает модель замоканой функции на любой общий случай, способы взаимодействия вызывающей с исходной вызываемой будут лишь какими-то частными их случаями, покрываемыми предыдущим тестом, и на основании результатов этих двух тестов можно сделать экспертный вывод о корректности связки обоих функций. Если экспертного вывода по какой-то причине недостаточно, такое редко, но бывает, то взаимодействие этих двух функций может быть покрыто третьим тестом, но его сферой ответственности будет лишь потоки данных и управления, но не модели управления целиком.
                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                                                            Нет, он тебе рассказывает о технологии тестирования связанных систем по отдельности. Элементарнейший пример – функция вызывает функцию с параметрами: ты можешь написать отдельный тест на вызываемую функцию, которую прочекаешь по полной программе, по всем диапазонам классов эквивалентности всех её входов, не исключая параметры, и убедишься, что она ведёт себя полностью в рамках её модели поведения, описываемой документацией; затем ты пишешь другой тест, на этот раз на вызывающую функцию, соблюдая те же принципы и опираясь на её модель поведения. При создании второго теста ты вполне имеешь право застабить вызываемую, и пусть она ведёт себя не по её задокументированной модели, это уже неважно. Важно, что её поведение тесту известно, и его не надо тестировать, ведь по сути она его составная часть, и это поведение значительно проще, и им можно легко управлять из теста. При этом достаточно лишь прочекать, что вызывающая (тестируемая на данном этапе) функция правильно выставляет входы для мока и правильно потребляет результаты её работы.

                                                                                                                                                                                                                                                                                                                                                                                                                                            Ну когда речь идет об элементарнейших вещах, я это могу понять. Но когда речь идет о какой то хитрой логике(не все же методы возвращают сумму двух чисел или например константную строку), то тут тебе придется мочить все сущности, которые используются в тестируемом алгоритме, а если вдруг какая то сущность внутри получается из другой сущности, или просто живет там, конструируясь на каких то данных, то придется в придачу еще и переписывать всю систему, то тут уж, извиняйте, но я понять не могу. Если речь идет о какой то философии совершенного кода - ну тогда так и говорите. Я как бы исхожу из реальности, а не из каких то там аксиом и теоретических совершенностях.
                                                                                                                                                                                                                                                                                                                                                                                                                                            Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                                                              Ещё одно хорошее "зачем": разве не достаточно тестом показать факт наследования тестируемого класса от интересующего нас базового? Разве не следует из гарантий языка программирования заранее известный (однозначно предсказываемый) итог запуска тестов на наследуемых методах?

                                                                                                                                                                                                                                                                                                                                                                                                                                              Нет, не следует, метод может быть переопределён.
                                                                                                                                                                                                                                                                                                                                                                                                                                                Вклинюсь тут. А никто не поделится ссылкой на какой-нибудь более-менее крупный проект (желательно на плюсах), где тестирование делается как раз вот так, как тут описано - с активным mock-анием всего кроме тестируемой сущности? А то я тоже слабо представляю, что делать, если сущности оказываются сильно связанными.
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Но когда речь идет о какой то хитрой логике(не все же методы возвращают сумму двух чисел или например константную строку), то тут тебе придется мочить все сущности, которые используются в тестируемом алгоритме, а если вдруг какая то сущность внутри получается из другой сущности, или просто живет там, конструируясь на каких то данных, то придется в придачу еще и переписывать всю систему, то тут уж, извиняйте, но я понять не могу.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  А можешь привести такой пример? Было бы интересно рассмотреть.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                                                                                                  А то я тоже слабо представляю, что делать, если сущности оказываются сильно связанными.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  А ты сможешь привести пример?
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                                    А ты сможешь привести пример?

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Пример чего? Связанных сущностей? Да любой контейнер со своими итераторами, в общем-то - если это не тупо вектор, а какая-либо более-менее нетривиальная структура данных, то с большой вероятностью они друг с другом будут связанными. Недавно вообще вот такое писал:
                                                                                                                                                                                                                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                                      for(auto x : my_container.indexer().set_param_1().set_param_2()){}

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Т.е. чтобы можно было настраивать итерирование по этому контейнеру. Сущность, возвращаемая методом indexer() оказывается тоже сильно связанной с контейнером, как и итераторы. У меня вообще получилось, что она является friend-ом для него. Так что по факту и контейнер, и эта сущность, и все типы итераторов это один-единственный класс, и поэтому тестировать их отдельно друг от друга это, фактически, совмещение неприятного с бесполезным.
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Да любой контейнер со своими итераторами

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Так что по факту и контейнер, и эта сущность, и все типы итераторов это один-единственный класс, и поэтому тестировать их отдельно друг от друга это, фактически, совмещение неприятного с бесполезным.

                                                                                                                                                                                                                                                                                                                                                                                                                                                      Тогда и не надо так делать :-?

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                      Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                                      OpenGL, вот если бы у тебя был какой-то Iterator, который мог бы работать с любыем IContainer, то я бы в тестах Iterator'а замокал IContainer, а не тащил бы какую-то из его реализаций в тест.
                                                                                                                                                                                                                                                                                                                                                                                                                                                        А, не, если там уже интерфейс, то лучше замокать, естественно. Причём если тесты нужны побыстрее и ещё вчера, можно поначалу за ним вообще реальный объект спрятать :D
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Нет, не следует, метод может быть переопределён.
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Если ты имеешь в виду "перекрыт", подразумевая полиморфное поведение, то унаследованный метод вообще не при делах. Он либо просто исключается из логики поведения производного, либо на его наличие производный всё-таки рассчитывает, и тогда задача сводится к последующей. Которая вот она: если же ты подразумеваешь, что это новый метод, то у производного класса будет в итоге будет два метода... ну и ты уже понял: новый метод тестится новый тестом, унаследованный, как я и отметил ранее, покрыт гарантиями языка и своим, уже написанным, тестом.
                                                                                                                                                                                                                                                                                                                                                                                                                                                          В любом случае, выбор между вариантами определяется бизнес-логикой и архитектурой, а не правилами "как правильно тестировать". Следовательно тестировать унаследованные методы в тестах на производные классы не требуется, если так или иначе показан факт наличия этой родственной связи между классами. Если что-то где-то когда-то пойдёт не так на рефакторинге, какой-нибудь тест да упадёт, так что ложных пассов не будет.

                                                                                                                                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Но когда речь идет о какой то хитрой логике(не все же методы возвращают сумму двух чисел или например константную строку), то тут тебе придется мочить все сущности, которые используются в тестируемом алгоритме, а если вдруг какая то сущность внутри получается из другой сущности, или просто живет там, конструируясь на каких то данных, то придется в придачу еще и переписывать всю систему, то тут уж, извиняйте, но я понять не могу.
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Не придётся. Берётся минимально возможная единица декомпозиции, в Джаве это класс, например, на Сях/Плюсах единица трансляции, и вокруг него строится каркас их моков. Можно даже не работать с сырцами при этом, достаточно готовых .jar или там .obj, которые вполне подходят для линковки с тестом. Фактически тест и является приложением, а тестируемая сущность его небольшая составная часть, лишь бы она осталась неизменной по сравнению с продашновой. Один раз сделал такой каркас, что может занять не так уж мало времени, но технически реализуется несложно, и готов писать тесты на всё из этой единицы декомпозиции уже без ресурсозатрат. Для другой единицы декомпозиции основной каркас уже есть, нужно лишь исключить её моки и добавить ещё комплект, стабирующий вон ту, с предыдущего этапа. С этого момента у тебя есть всё для всего.
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Заметь, на этапе компонентного тестирования от тестового окружения не требуется каких-либо релеваций с описанным в документации поведением системы. Нужны экземпляры тестируемых классов – ну и создавай их как тебе удобно. Нужны внешние связи, пиши простейшие стабы, откликающиеся на них удобным тебе образом. Из документации на ПО требуется только описательная часть интерфейсов и архитектуры. Из поведения не требуется ничего. Естественно кроме того самого маленького фрагмента, который собственно тестируется. То, что ты описываешь в своих примерах, это уже другой уровень тестирования. Возможно интеграционный, на котором (если, конечно, тестами низкого уровня действительно показана корректность реализации каждого элемента декомпозиции) заостряться на поведении каждой сущности просто уже нет необходимости, достаточно ограничиться лишь их связями по данным и управлению.
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Сообщение отредактировано: Qraizer -
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Можно даже не работать с сырцами при этом, достаточно готовых .jar или там .obj, которые вполне подходят для линковки с тестом.

                                                                                                                                                                                                                                                                                                                                                                                                                                                            Я правильно понял, что ты предлагаешь что-то такое:
                                                                                                                                                                                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                                              // foo.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                              #include "bar.h"
                                                                                                                                                                                                                                                                                                                                                                                                                                                              // Это тестируемый класс
                                                                                                                                                                                                                                                                                                                                                                                                                                                              class Foo
                                                                                                                                                                                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Bar bar;
                                                                                                                                                                                                                                                                                                                                                                                                                                                              };
                                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                              // bar.h
                                                                                                                                                                                                                                                                                                                                                                                                                                                              class Bar
                                                                                                                                                                                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // Методы должны быть реализованы в cpp, т.е. шаблонный класс не катит
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  void method();
                                                                                                                                                                                                                                                                                                                                                                                                                                                              };

                                                                                                                                                                                                                                                                                                                                                                                                                                                            И просто юзать в приложении "официальный" bar.cpp, а в тестах bar_mocked.cpp?
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Речь шла про внешние зависимости для класса, причем такие, которые уже через интерфейсы работают. Киля предлагает в тестах использовать конкретные классы системы, реализующие эти интерфейсы. Я предлагаю замокать.

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Эээ, про какие внешние зависимости? Речь шла про функционал. Я тебе пишу, что ты можешь встретить метод, который юзает другие сущности. Как это мокать, я не совсем понимаю. Придется просто сильно много мокать. А когда у тебя есть метод, который принимает два интерфейса, и использует исключительно только их - тогда конечно тут проблем не возникает.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                А когда у тебя есть метод, который принимает два интерфейса, и использует исключительно только их - тогда конечно тут проблем не возникает.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Но ты именно такой пример и приводил. У тебя было два интерфейса, но ты туда хотел подпихивать конкретные сущности.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  И просто юзать в приложении "официальный" bar.cpp, а в тестах bar_mocked.cpp?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Если очень кратко, то да. Но вообще-то нет. Это как-то слишком искусственно и неудобно.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Сообщение отредактировано: Qraizer -
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Если очень кратко, то да. Но вообще-то нет. Это как-то слишком искусственно и неудобно.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Тогда как конкретно это делать?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Но ты именно такой пример и приводил. У тебя было два интерфейса, но ты туда хотел подпихивать конкретные сущности.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Не правда. Да у меня был пример с двумя интерфейсами, но упор я делал на то, что внутри метода, есть какой то вызываемый функционал, который ты не можешь съимиторовать через мок, вот мой пример:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      void testLinkToContainer()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          /*Тут, вместо new даже может быть Mock, который будет делать все тоже самое, кроме физического создания контейнера в системе, например как в примере создавать эксземпляр класса, напихивать в него данные, возвращать его, но не сохранять в системе*/
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          IContainer* pContainer = new COrgUnit(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          /*Тут ровно тоже самое, создается либо через mock, либо напрямую нужный класс, забивается данными*/
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          IPrincipal* pPrincipal = new Personage(CN, DN, Location,...);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          //! Допустим через интерфейс создаем юзер аккаунт, который нужен будет для линковки
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          pPrincipal->CreateUserAccountPersonage();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          EntityLinker* linker = new EntiryLinker(...);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          //! Дальше тут какие то проверки, что все засетаплено честно.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          //! Дальше собственно выполняем нашу линковку:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          linker->LinkToContainer(pContainer, pPrincipal);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /*Дальше идет тестирование результатов линковки*/
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      }

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Видишь там вызов метода CreateUserAccountPersonage ? Под ним как раз и подразумевалось что у тебя чтобы например что то переместить, нужно выполнить реальный метод, а не моковый. Да, возможно я криво выразился, потому что не получается у меня сейчас сидеть думать как тебе написать чтоб ты понял, приходится в перерывах отвлекатся, но имелось ввиду то, что у тебя метод может содержать не просто какой то несвязанный функционал, а некую логику, которую ты не подсунешь в сам тестируемый метод. И дальше я тебе об этом писал:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Скрытый текст
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Кого они проверяют? Я тебе говорю, что для какой то операции, необходимо вызвать какой то метод из этих классов явно/неявно.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Могут, и чего? Я тебе пишу про то, что ты можешь в моке не учесть, какую то вещь, которая есть в используемом классе.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Я не знаю, то о чем ты пишешь, больше напоминает тестирование несвязанного между собой функционала, например библиотечные функции какие нибудь. На практике же, довольно часто приходится работать с довольно связанными сущностями.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      У меня одна картина в голове стоит, у тебя вторая. Поэтому не понимаем друг друга. Ты мне пишешь про тестирование каких то несвязанных вещей, я напротив больше сталкивался с взаимосвязанными системами.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Когда например у тебя один класс, инкапсулирует в себе кучу логики, которая инкапсулирует в себе другую кучу логики, которая инкапсулирует в себе еще какую то кучу логики.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Я не знаю, может быть ты рассказываешь с философской точки зрения. Но хотел бы я посмотреть как ты все это тестировал бы.


                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Но когда речь идет о какой то хитрой логике(не все же методы возвращают сумму двух чисел или например константную строку), то тут тебе придется мочить все сущности, которые используются в тестируемом алгоритме, а если вдруг какая то сущность внутри получается из другой сущности, или просто живет там, конструируясь на каких то данных, то придется в придачу еще и переписывать всю систему, то тут уж, извиняйте, но я понять не могу.


                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Ты же мне, рассказываешь как я понял какую то философию программирования.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Видишь там вызов метода CreateUserAccountPersonage ? Под ним как раз и подразумевалось что у тебя чтобы например что то переместить, нужно выполнить реальный метод, а не моковый.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Вообще-то вместо вызова этого метода, ты должен был замокать UserAccountRepository или откуда там у тебя тестируемый метод данные берёт.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Вообще-то вместо вызова этого метода, ты должен был замокать UserAccountRepository или откуда там у тебя тестируемый метод данные берёт.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Так а если для получения результата внутритого метода есть еще логика, со своими типами и классами? Их тоже замокать? Я же и пишу, в итоге получится так, что тебе придется мокать вообще все. Да и не всегда прокидывают интерфейсы в метод. Бывает есть у тебя метод какой нибудь, который принимает контекст, а уже внутри из контекста - конструируются какие то типы, например с сервис локатора, или внутренней фабрики, либо на основе имеющихся данных, которые были получены путем других телодвижений.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Сообщение отредактировано: Wound -
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Так а если для получения результата внутритого метода есть еще логика, со своими типами и классами? Их тоже замокать? Я же и пишу, в итоге получится так, что тебе придется мокать вообще все.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Мокать нужно то, что инжектится как зависимость. Все внешние ресурсы (БД и т.п.) должны инжектиться или передаваться аргументами в метод, а следовательно мокаться.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            а уже внутри из контекста - конструируются какие то типы, например с сервис локатора

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Эти сервисы должны быть функциональными (т.е. получать внешние ресурсы в параметрах своих методов, а не хранить их в приватных полях), тогда их не нужно мокать, либо инжектиться и мокаться.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Так а если для получения результата внутритого метода есть еще логика, со своими типами и классами?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Народ пишет про это:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Очень часто наш код (функция, модуль) имеют внешние зависимости. Внешняя зависимость — это все, что делает ваши тесты не правдивыми и сложно-поддерживаемыми. Файловая система — зависимость: структура каталогов может быть другой на другой машине. База данных — зависимость, ее может не быть на другой машине. Веб-сервис — зависимость: может не быть интернета или может присутствовать фаервол и.т.д

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Если на вопрос: «будет ли этот компонент вести себя так же на другой машине?» вы отвечаете нет, то его необходимо “подменить” и тут вам на помощь как раз придут стабы и моки. Но есть и другая сторона медали, когда разработчик начинает увлекаться и приходит к тому, что подменяет вообще все. Соответственно тесты перестают проверять само приложение и начинают тестировать стабы, моки. Это в корне не верно. Если «живых» реализаций в тесте нет, то этот тест не тестирует ничего.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Иногда эти термины stubs и mock путают: разница в том, что стаб ничего не проверяет, а лишь имитирует заданное состояние. А мок — это объект, у которого есть ожидания. Например, что данный метод класса должен быть вызван определенное число раз. Иными словами, ваш тест никогда не сломается из-за «стаба», а вот из-за мока может.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              user posted image

                                                                                                                                                                                                                                                                                                                                                                                                                                                                              С технической точки зрения это значит, что, используя стабы, мы проверяем состояние тестируемого класса или результат выполненного метода. При использовании мока мы проверяем, соответствуют ли ожидания мока поведению тестируемого класса. Также лучше использовать не более одного мока на тест. Иначе с высокой вероятностью вы нарушите принцип «тестировать только одну вещь». При этом, в одном тесте может быть сколько угодно стабов или же мок и стабы.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Народ пишет про это:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Народ немного странные вещи пишет. Например, что значит «не более одного мока на тест»? У тестируемого метода может быть больше одной внешней зависимости.

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  JoeUser, ты привёл классные ссылки, но мимо. Никакой мок (стаб) не должен нарушать инварианты, описанные в документаци.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Сообщение отредактировано: Qraizer -
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Например, что значит «не более одного мока на тест»?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Зачем вырывать из контекста? Написано же "... также лучше использовать ...". Иными словами, если есть выбор.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Никакой мок (стаб0 не должен нарушать инварианты, описанные в документаци.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Хм, а где в тексте ты узрел нарушение моками или стабами инвариантов, описанных в документации? :blink:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Сообщение отредактировано: JoeUser -
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата OpenGL @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Тогда как конкретно это делать?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Простейше? Тебе – и не только – вряд ли понравится: подменять можно лишь реализацию. Соответственно заголовки должны быть "боевыми".
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      0 пользователей:


                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Рейтинг@Mail.ru
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [ Script execution time: 0,5540 ]   [ 18 queries used ]   [ Generated: 28.03.24, 23:04 GMT ]