Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Клуб программистов > Свободное общение
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.12.2011, 02:11   #111
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Хм, а разве возможно в for-init объявлять переменные разных типов?
ну да...нельзя, ступил в 2 ночи.
ну значит лучше блок, а в который вложить цикл.
так мы достигаем трех вещей, и ограничиваем область для переменной, и выносим её из цикла, и переменная находиться рядом с циклом(причем видно что она только для цикла)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.12.2011, 08:06   #112
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Сtrl Посмотреть сообщение
... Но в рамках большинства задач читаемость кода важнее производительности, так что я бы во всех случаях вносил объявления в цикл (даже если объект очень тяжелый).
И убиваете читабельность.

Упреждая ваш вопрос, поясню на примере.
Но сначала, небольшое лирическое отступление:

Что такое исходный код? Это - мысли программиста, в терминах его языка программирования.

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

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

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

Теперь рассмотрим следующий псевдокод:
Код:
//псевдокод

SomeClass targetData; //данные, которые нужно обработать
while(...) 
{
    ....  //вот здесь происходит обработка данных
}
Почему может получится так, что создание сущности находится далеко от места её использования?

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

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

Это свидетельствует о том, что автор кода не привел свои мысли в порядок. Не сумел сформулировать их четко. Его мысли не обладают четкой структурой. Они не разбиты на самостоятельные логические единицы. Автор кода не использовал принципа "разделяй и властвуй". У него всё в куче, и получилась чача.

А теперь вот такой пример:

Код:
//псевдокод

SomeStruct targetData= ReadyProcess();  //Данные
int Err = NO_ERROR;                                //Аспективные флаги
while(...) 
{
    Err = AnalyseData(targetData); 
    ReactionForError(Err);                   
    ... //ещё какие то действия
}

FinishProcess(targetData); //почистим за собой
Смысл в том, что если тело блока разбухает - это серьёзный признак того, что пора бы навести в голове порядок, и пересмотреть структуру собственной мысли. Соответственно на бумаге все станет более четким, и красивым.

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

Маскируете проблему, перенося создание сущности к месту использования. Типа, даже в разбухшем туловище блока читать будит легче.

То есть, вот так:

Цитата:
Сообщение от Сtrl Посмотреть сообщение
... так что я бы во всех случаях вносил объявления в цикл (даже если объект очень тяжелый)
Вы боретесь с последствиями чачи, а не с причинами её возникновения.


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

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

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

Однако, четкость мыслей, и их структура имеет критическое значение и на паскале, и на с++.

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

Последний раз редактировалось _Bers; 26.12.2011 в 08:44.
_Bers вне форума Ответить с цитированием
Старый 26.12.2011, 08:52   #113
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Почему может получится так, что создание сущности находится далеко от места её использования?
тут вы кое что путаете, эту сущность еще нужно заполнить, именно потому она и появиться раньше, иначе она появиться именно около цикла.
Цитата:
Такой цикл трудно читать, его не видно целиком на мониторе, и поэтому трудно сразу весь охватить мысленным взором, и держать в голове.
вынеся типы данных хрен знает куда читабельность вы не повысили.
Цитата:
Смысл в том, что если тело блока разбухает - это серьёзный признак того, что пора бы навести в голове порядок, и пересмотреть структуру собственной мысли. Соответственно на бумаге все станет более четким, и красивым.
если вы считаете что любой код можно уменьшить, то ошибаетесь.(да и не всякий стоит уменьшать)
я разношу по функциям лишь повторяющиеся блоки, не более.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.12.2011, 09:43   #114
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
тут вы кое что путаете, эту сущность еще нужно заполнить, именно потому она и появиться раньше, иначе она появиться именно около цикла.
Не вразумел.


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

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

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

Я разделил монолитный механизм на кучку частей, инкапсулировав внутренности этих частей.

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

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

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

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

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

А можно просто читать код.

Разницу понимаете?

В-третьих, Я не пытаюсь уменьшить количество кода. Я лишь изменяю саму его структуру так, что бы его можно было легко читать, и понимать что он делает.
_Bers вне форума Ответить с цитированием
Старый 26.12.2011, 17:34   #115
Сtrl
C++
Форумчанин
 
Аватар для Сtrl
 
Регистрация: 27.03.2011
Сообщений: 803
По умолчанию

Цитата:
читающему мой код не нужно думать о том, как работает код. Но по говорящим названиям функций, и комментариям, читатель сразу поймёт, что делает код.
Вы используете не тот инструмент. Для кода, который описывает что нужно получить, а не как это сделать, есть функциональное программирования. C++ же, напротив, императивный язык. Это так, к слову. Вернемся к нашим баранам. Давайте рассмотрим пример кода:
Код:
while (...)
{
  char choose = '\0';
  cin >> choose;
  if (choose == 'y')
    //действия
  else
    break;
}
Переменная choose является деталью реализации. Сама идея заключается в том, что мы спрашиваем пользователя, желает ли он выполнить действие (тогда он вводит 'y') или нет. При этом переменная choose используется только в цикле. Нарушение инкапсуляции, о чем вы так старательно рассказываете, как раз произойдет, если дать внешнему коду доступ к этой переменной, объявив ее вне цикла.
Ищете информацию по C++?
cplusplus.com
Сtrl вне форума Ответить с цитированием
Старый 26.12.2011, 17:54   #116
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Сtrl Посмотреть сообщение
Вы используете не тот инструмент. Для кода, который описывает что нужно получить, а не как это сделать, есть функциональное программирования. C++ же, напротив, императивный язык. Это так, к слову.
Не вразумел. Какое отношение имеет "разделяй и властвуй" к функциональной парадигме?

Цитата:
Сообщение от Сtrl Посмотреть сообщение
Вернемся к нашим баранам. Давайте рассмотрим пример кода:
Код:
while (...)
{
  char choose = '\0';
  cin >> choose;
  if (choose == 'y')
    //действия
  else
    break;
}
Переменная choose является деталью реализации. Сама идея заключается в том, что мы спрашиваем пользователя, желает ли он выполнить действие (тогда он вводит 'y') или нет. При этом переменная choose используется только в цикле.
Во-первых, существуют ещё манипулятивные классы/функции. Которые собственных данных членов не имеют, и лишь работают со значениями целевых данных.

Использовать манипуляторы в циклах предпочтительнее, ибо они ничего не создают, и не удаляют. И таким образом экономят время на конструкторах/диструкторах. Однако целевые данные, с которыми работают манипуляторы являются частью тех блоков, которые их порождают, а вовсе не самих манипуляторов. Поэтому, ни о каком нарушении инкапсуляции тут речи не идёт.

Во-вторых, любая логически целостная единица имеет три состояния:
1. Подготовка.
2. Рабочий цикл.
3. Завершение.

О каком нарушении инкапсуляции может идти речь, при подготовке данных перед началом основного действия?
Ну или при завершении? Подготовительный этап не имеет право знать, что именно ему следует подготовить? Так что ли?

Ещё раз: вместо чара тяжелый объект. Будите иметь нерациональные потери производительности, или все таки по уму подготовите блок к работе?

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

Если вам так сильно нужно скрыть детали реализации механизма, то к вашим услугам функция, в которую можно вынести и подготовку, и сам цикл, и завершение. Либо классы ООП с их конструкторами/диструкторами.
_Bers вне форума Ответить с цитированием
Старый 26.12.2011, 19:17   #117
ITTI
Пользователь
 
Регистрация: 19.12.2011
Сообщений: 65
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Нельзя научится бегать, не научившись стоять на ногах. С++ язык, который постигается постепенно.
"Но где вы видели ребенка, к-рый учился бы именно ходить, а не бегать?...Мы должны научиться бегать раньше, чем ходить!" Страуструп.
Так, к слову.
Как можно сделать:
while(a<int)?
ITTI вне форума Ответить с цитированием
Старый 26.12.2011, 19:26   #118
ITTI
Пользователь
 
Регистрация: 19.12.2011
Сообщений: 65
По умолчанию

Вопрос не по теме, за него преподаватель обещал 5 за зачет. Ответ узнаю через две недели, так что есть только предположение.
Есть три дома и отдельно газ, свет и вода. Нужно провести к каждому дому по три трубы, но так, чтобы они не пересеклись. Размещать элементы можно как угодно.
ITTI вне форума Ответить с цитированием
Старый 26.12.2011, 19:36   #119
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Во-вторых, я сократил размер блока, за счет дробления его большой задачи на кучку мини-задач. Теперь этот блок влазиет на экран монитора, и его можно целиком охватить мысленным взором.
мысленным взором можно охватить и больше экрана.
я лично наоборот ненавижу когда литой код разорван выносами в функции.(особенно когда в них нет необходимости)
особенно когда цикл с ветвлением, и проходя мысленно(не знаю как вы, я уже года 4 назад научился выполнять код в голове, медленно читая его) по нему.
Цитата:
Таким образом, читатель абстрагируется от сложности реализации алгоритма, но зато прекрасно понимает, что хотел сделать автор кода.
не знаю как вы читаете код, но когда я читаю код, то мне важно знать что и как он делает.
Цитата:
В-третьих, Я не пытаюсь уменьшить количество кода. Я лишь изменяю саму его структуру так, что бы его можно было легко читать, и понимать что он делает.
если не будет инлайновой оптимизации, то получите падение производительности.
Цитата:
Ещё раз: вместо чара тяжелый объект. Будите иметь нерациональные потери производительности, или все таки по уму подготовите блок к работе?
да поймите вы разницу между переменной для всего цикла и переменной итерации цикла.
например тут:
Код:
std::map<std::wstring,unsigned> doIt(std::vector<std::wstring>& names)
{
    std::map<std::wstring,unsigned> result;//допустим результат
    unsigned i=0;
    for(std::vector<std::wstring>::iterator it=names.begin();it<names.end();it++,i++)
        result[*it]=i;
    return result;
}
нет смысла вносить в цикл что-либо.
но тут:
Код:
void doIt(std::vector<std::wstring>& names;std::wstring data)
{
    for(std::vector<std::wstring>::iterator it=names.begin();it<names.end();it++)
    {
        std::ofstream t(it->c_str());
        t<<data<<std::endl;
    }
}
тут объект принадлежит именно итерации цикла(хотя в данном случае можно оптимизировать, но сейчас не этот случай(допустим объект не может быть переинициализирован))

но это если функция-цикл(функция по сути состоящая из цикла), для больших функций те же правила, но выносить не во всю функцию, а в блок в который уже помещать функцию.
то есть первый пример будет таким:
Код:
    std::map<std::wstring,unsigned> result;//допустим результат цикла
    {
        unsigned i=0;
        for(std::vector<std::wstring>::iterator it=names.begin();it<names.end();it++,i++)
            result[*it]=i;
    }
тогда переменная остается в минимуме видимости.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.12.2011, 19:36   #120
Сtrl
C++
Форумчанин
 
Аватар для Сtrl
 
Регистрация: 27.03.2011
Сообщений: 803
По умолчанию

Цитата:
Сообщение от ITTI Посмотреть сообщение
Нужно провести к каждому дому по три трубы, но так, чтобы они не пересеклись. Размещать элементы можно как угодно.
http://mathforum.org/dr.math/faq/faq.3utilities.html
Ищете информацию по C++?
cplusplus.com
Сtrl вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
PopupMenu со мной не дружит Жигилий_Ульяна Компоненты Delphi 5 25.12.2008 11:04
проблемы с select или со мной... smoke888 JavaScript, Ajax 2 23.09.2008 19:02