На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Конвейерное программирование , предлагаю такой стиль
    Некоторое время назад я придумал стиль программирования, который можно назвать "конвейерным" ( хотя это слово мне не очень нравится ).
    Этот стиль базируется на таком предположении: если объект изменился на текущем шаге, то с большой вероятностью он будет использоваться на следующем шаге.
    Теперь как это предположение можно использовать.
    Все примеры будут на С++, хотя некоторые другие языки тоже позволяют использовать такой стиль.
    Пусть имеется класс у которого есть константные и неконстантные функции-члены ( методы ).
    Первые возвращают какую-то информацию об объекте данного класса, поэтому будем их назвать, для примера, словом info.
    Вторые изменяют объект. поэтому будем назвать их словом exec.
    Т.к. мы предполагаем, что после изменения объект будет использоваться, то неконстантные функции-члены будут возвращать ссылку на этот объект для дальнейшего использования. Это, конечно, не всегда нужно и удобно, но часто это можно сделать.
    Получаем такую общую схему класса.
    ExpandedWrap disabled
      class A
      {
      ...
      public:
      // константные функции-члены
      Info1 info1() const;
      Info2 info1() const;
      ...
      // неконстантные функции-члены
      A & exec1();
      A & exec2();
      ...
      };

    Для простоты у всех функций не указаны параметры.
    Теперь мы может использовать такие выражения:
    ExpandedWrap disabled
      A a;
      if ( a.exec1().exec2()...info1() ) ...

    Из этого примера видно почему я этот стиль назвал "конвейерным".
    То же самое можно делать с обычными функциями.
    Например, пусть у нас есть возможность записать множество объектов в список и в массив, но какая-то групповая операция определена только для массива, а нам надо сделать тоже самое со списком. Тогда запишем это так:
    ExpandedWrap disabled
      Array & copy ( const List & list, Array & array );
      List  & copy ( const Array & array, List & list );
      ...
      Array & exec ( Array & array );
      ...
          copy ( exec ( copy ( list, A() ) ), list );

    А теперь о том, что это даёт. Прежде всего это немного сокращает текст программы. Кроме того, иногда полезно иметь одно выражение, а не группу операторов. Если использовать такие конструкции умеренно, то читабельность программы не пострадает.
    Когда-то давно в некотором круге было модно на языке APL писать "однострочники", т.е. написать выражение которое содержало бы в себе как можно больше функциональности, т.е. одно выражение содержало целую программу. Что-то вроде этого предлагает описываемый стиль.
      Цитата prografix @
      Некоторое время назад я придумал стиль программирования

      прекрасное начало
      из перво-попавшихся под руку в инете примеров
      Цитата jquery
      ExpandedWrap disabled
        $('#foo').slideUp(300).delay(800).fadeIn(400);
        Цитата zera @
        Цитата (prografix @ Сегодня, 13:25)
        Цитата
        Некоторое время назад я придумал стиль программирования

        прекрасное начало


        А как же старый-добрый
        ExpandedWrap disabled
          cout << "bla" << "bla" << oct << 20 << hex << 25 << endl;
          Добавлю, что в конвейере можно делать развилки.
          Например, так:
          ExpandedWrap disabled
            ( a.exec1()...info1() ? a.exec2()... : a.exec3()... ).exec4()...

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

            про такой стиль в каком то учебнике читал...
              Цитата Frees @
              про такой стиль в каком то учебнике читал...

              "Всё уже украдено до нас".

              В шаблоне классов vector такие функции-члены, как resize, push_back и др. возвращают значение void.
              А если бы возвращали ссылку на себя, то можно было бы написать, например, такое:
              ExpandedWrap disabled
                    func ( vec.resize ( n ) );

              Поэтому рекомендую тем у кого есть подобные классы изменить их.
                В случае, если функция изменяет не один, а несколько объектов, можно подумать об объединении их в одну структуру.
                Например, пусть имеется функция изменяющая объекты типов A и B:
                ExpandedWrap disabled
                  void func ( A & a, B & b, ... );

                В этом случае можно сделать структуру:
                ExpandedWrap disabled
                  struct AB
                  {
                      A a;
                      B b;
                  };
                   
                  AB & func ( AB & ab, ... );
                  Такой конвейер реализуется легко - достаточно в языке сделать void автозаменяемым на ссылку на класс, в котором изменяемый метод или вручную это в програме сделать.
                    У некоторых объектов есть метод resize. Недавно заметил, что часто бывает вариант resize ( 0 ), и полностью писать это лень. Можно было сделать для этого случая отдельный метод, но это избыточно.
                    Решил сделать ноль по умолчанию. Теперь запись resize() означает сделать нулевой размер. Может кому-то эта идея тоже понравится.
                    Ну и, конечно, resize возвращает ссылку на объект.
                      Цитата prografix @
                      У некоторых объектов есть метод resize. Недавно заметил, что часто бывает вариант resize ( 0 ), и полностью писать это лень. Можно было сделать для этого случая отдельный метод, но это избыточно.
                      Решил сделать ноль по умолчанию. Теперь запись resize() означает сделать нулевой размер. Может кому-то эта идея тоже понравится.
                      Ну и, конечно, resize возвращает ссылку на объект.

                      Не уверен, что это хорошая идея. Потому что семантически получился уже другой метод. А именно - clear(). resize без параметров - не очевиден.
                        На хабре писали про Python Pipe. И кстати раскритиковали по делу :)

                        http://habrahabr.ru/blogs/python/117679/
                          Да, точно, pipe. В F# широко применяется.

                          Добавлено
                          Использование подобных конвейеров хорошо для однотипных операций, например, перегруженные << и >> для ввода/вывода в C++. Если же использовать такой подход для разнотипных операций, читаемость кода может упасть.
                            Если писать длинные выражения, то они будут плохо восприниматься человеком.
                            В этом случае наиболее часто встречающиеся пары ( группы ) функций можно объединять в одну функцию.
                            Например вместо:
                            ExpandedWrap disabled
                              object.func1().func2()...funcN();

                            можно будет написать:
                            ExpandedWrap disabled
                              object.func1N();

                            Есть известный принцип - "Объединяй и направляй", хотя в данном случае, на мой взгляд, больше подходит - "Объединяй и управляй".
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


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