Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[44.200.210.43] |
|
Сообщ.
#1
,
|
|
|
Некоторое время назад я придумал стиль программирования, который можно назвать "конвейерным" ( хотя это слово мне не очень нравится ).
Этот стиль базируется на таком предположении: если объект изменился на текущем шаге, то с большой вероятностью он будет использоваться на следующем шаге. Теперь как это предположение можно использовать. Все примеры будут на С++, хотя некоторые другие языки тоже позволяют использовать такой стиль. Пусть имеется класс у которого есть константные и неконстантные функции-члены ( методы ). Первые возвращают какую-то информацию об объекте данного класса, поэтому будем их назвать, для примера, словом info. Вторые изменяют объект. поэтому будем назвать их словом exec. Т.к. мы предполагаем, что после изменения объект будет использоваться, то неконстантные функции-члены будут возвращать ссылку на этот объект для дальнейшего использования. Это, конечно, не всегда нужно и удобно, но часто это можно сделать. Получаем такую общую схему класса. class A { ... public: // константные функции-члены Info1 info1() const; Info2 info1() const; ... // неконстантные функции-члены A & exec1(); A & exec2(); ... }; Для простоты у всех функций не указаны параметры. Теперь мы может использовать такие выражения: A a; if ( a.exec1().exec2()...info1() ) ... Из этого примера видно почему я этот стиль назвал "конвейерным". То же самое можно делать с обычными функциями. Например, пусть у нас есть возможность записать множество объектов в список и в массив, но какая-то групповая операция определена только для массива, а нам надо сделать тоже самое со списком. Тогда запишем это так: 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 писать "однострочники", т.е. написать выражение которое содержало бы в себе как можно больше функциональности, т.е. одно выражение содержало целую программу. Что-то вроде этого предлагает описываемый стиль. |
Сообщ.
#2
,
|
|
|
Цитата prografix @ Некоторое время назад я придумал стиль программирования прекрасное начало из перво-попавшихся под руку в инете примеров Цитата jquery $('#foo').slideUp(300).delay(800).fadeIn(400); |
Сообщ.
#3
,
|
|
|
Цитата zera @ Цитата (prografix @ Сегодня, 13:25) Цитата Некоторое время назад я придумал стиль программирования прекрасное начало А как же старый-добрый cout << "bla" << "bla" << oct << 20 << hex << 25 << endl; |
Сообщ.
#4
,
|
|
|
Добавлю, что в конвейере можно делать развилки.
Например, так: ( a.exec1()...info1() ? a.exec2()... : a.exec3()... ).exec4()... А теперь предлагаю желающим программистам посмотреть свою программу на предмет того, что возвращают функции меняющие объект. Если это не ссылка на объект, то подумайте не стоит ли возвращать ссылку? Это не всегда удобно, но часто это так. |
Сообщ.
#5
,
|
|
|
Цитата prografix @ Некоторое время назад я придумал стиль программирования про такой стиль в каком то учебнике читал... |
Сообщ.
#6
,
|
|
|
Цитата Frees @ про такой стиль в каком то учебнике читал... "Всё уже украдено до нас". В шаблоне классов vector такие функции-члены, как resize, push_back и др. возвращают значение void. А если бы возвращали ссылку на себя, то можно было бы написать, например, такое: func ( vec.resize ( n ) ); Поэтому рекомендую тем у кого есть подобные классы изменить их. |
Сообщ.
#7
,
|
|
|
В случае, если функция изменяет не один, а несколько объектов, можно подумать об объединении их в одну структуру.
Например, пусть имеется функция изменяющая объекты типов A и B: void func ( A & a, B & b, ... ); В этом случае можно сделать структуру: struct AB { A a; B b; }; AB & func ( AB & ab, ... ); |
Сообщ.
#8
,
|
|
|
Такой конвейер реализуется легко - достаточно в языке сделать void автозаменяемым на ссылку на класс, в котором изменяемый метод или вручную это в програме сделать.
|
Сообщ.
#9
,
|
|
|
У некоторых объектов есть метод resize. Недавно заметил, что часто бывает вариант resize ( 0 ), и полностью писать это лень. Можно было сделать для этого случая отдельный метод, но это избыточно.
Решил сделать ноль по умолчанию. Теперь запись resize() означает сделать нулевой размер. Может кому-то эта идея тоже понравится. Ну и, конечно, resize возвращает ссылку на объект. |
Сообщ.
#10
,
|
|
|
Цитата prografix @ У некоторых объектов есть метод resize. Недавно заметил, что часто бывает вариант resize ( 0 ), и полностью писать это лень. Можно было сделать для этого случая отдельный метод, но это избыточно. Решил сделать ноль по умолчанию. Теперь запись resize() означает сделать нулевой размер. Может кому-то эта идея тоже понравится. Ну и, конечно, resize возвращает ссылку на объект. Не уверен, что это хорошая идея. Потому что семантически получился уже другой метод. А именно - clear(). resize без параметров - не очевиден. |
Сообщ.
#11
,
|
|
|
На хабре писали про Python Pipe. И кстати раскритиковали по делу
http://habrahabr.ru/blogs/python/117679/ |
Сообщ.
#12
,
|
|
|
Да, точно, pipe. В F# широко применяется.
Добавлено Использование подобных конвейеров хорошо для однотипных операций, например, перегруженные << и >> для ввода/вывода в C++. Если же использовать такой подход для разнотипных операций, читаемость кода может упасть. |
Сообщ.
#13
,
|
|
|
Если писать длинные выражения, то они будут плохо восприниматься человеком.
В этом случае наиболее часто встречающиеся пары ( группы ) функций можно объединять в одну функцию. Например вместо: object.func1().func2()...funcN(); можно будет написать: object.func1N(); Есть известный принцип - "Объединяй и направляй", хотя в данном случае, на мой взгляд, больше подходит - "Объединяй и управляй". |