Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 31.10.08 20:12
Оценка:
Привет всем!

Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу

В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)

01.11.08 12:04: Перенесено модератором из 'О жизни' — Хитрик Денис
Re: Сложно-алгоритмо-фобия
От: minorlogic Украина  
Дата: 31.10.08 20:26
Оценка:
Здравствуйте, __kain, Вы писали:


__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


Пример в студию , может не все так плохо то ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: Сложно-алгоритмо-фобия
От: russian_bear  
Дата: 31.10.08 21:13
Оценка: 5 (2) +2 :)
__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)

http://www.rsdn.ru/res/book/prog/refactoring.xml
Автор(ы): Мартин Фаулер, Кент Бек, Джон Брант, Дон Робертс, Уильям Апдайк

К тому времени как объектная технология — в частности язык Java — стала обычным
делом, появилось большое количество плохо спроектированных, неэффективных и
малопригодных к сопровождению и расширению приложений. Профессиональные
разработчики программных систем все яснее видят, насколько трудно иметь дело с
таким "неоптимальным" наследием. Уже несколько лет эксперты в области объектного
программирования применяют расширяющийся набор приемов, призванных улучшить
структурную целостность и производительность таких программ. Этот подход,
называемый рефакторингом, до сего момента оставался территорией экспертов,
поскольку не предпринималось попыток перевести профессиональные знания в форму,
доступную всем разработчикам.В данной книге Мартин Фаулер показывает,
как разработчики программного обеспечения могут реализовать существенные выгоды
этой новой технологии, где обычно лежат возможности изменения структуры и как
приступить к переделке плохого проекта в хороший. Каждый шаг рефакторинга прост
— на первый взгляд слишком прост, чтобы сделать его. Это может быть перемещение
поля из одного класса в другой, вынесение какого-то кода из метода и превращение
его в самостоятельный метод или даже перемещение кода по иерархии классов.
Каждый отдельный шаг может показаться элементарным, но совокупный эффект таких
малых изменений в состоянии радикально улучшить проект. Рефакторинг является
верным способом предотвращения распада программы. Помимо описания различных
приемов автор предоставляет подробный каталог, включающий более семидесяти
рефакторингов, а также полезные указания по их применению, пошаговые инструкции
и практические примеры. Примеры написаны на Java, но идеи применимы к любому
объектно-ориентированному языку программирования.
Re: Сложно-алгоритмо-фобия
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 31.10.08 22:12
Оценка: +1
Помогает писать на функциональном языке с более совершенными инструментами декомпозиции.
Ce n'est que pour vous dire ce que je vous dis.
Re[2]: Как часто и почему мы меняем работу
От: blackhearted Украина  
Дата: 01.11.08 07:58
Оценка: +1
Здравствуйте, Don Reba, Вы писали:

DR>Помогает писать на функциональном языке с более совершенными инструментами декомпозиции.


На PL/SQL
Re[2]: Сложно-алгоритмо-фобия
От: gyraboo  
Дата: 01.11.08 08:03
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

__>>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


M>Пример в студию , может не все так плохо то ?


Действительно, было бы интересно увидеть примеры. Ведь многие классы задач, требующих многоэтажные конструкции if или switch при процедурном подходе,
очень изящно решаются с помощью ООП (Джаву можно подключить через PL/SQL). Кстати, это уже будет не алгоритм в классическом понимании этого слова, а какая-нибудь "бизнес-логика", под которую ООП заточено очень хорошо.
Re: Сложно-алгоритмо-фобия
От: 0K Ниоткуда  
Дата: 01.11.08 08:50
Оценка:
Здравствуйте, __kain, Вы писали:

__>Привет всем!


__>И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу


Ну и что? В жизни встречаются сложные вещи.

__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


А не нужно с ней бороться, это полезная фобия. Она удержит вас от того, чтобы всю жизнь искать философский камень и не найти.
Re: Сложно-алгоритмо-фобия
От: klopodav  
Дата: 01.11.08 10:28
Оценка: 3 (1)
__>Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу

Конкретно для PL/SQL большое количество строк не так уж страшно, т.к. процедура на много строк может сожержать один-единственный SQL-запрос, код которого может быть даже не на один экран. (причем длинный код запроса получается при аккуратном его форматировании, т.е. когда каждая значащая часть кода вынесена на отдельную строку). И в большинстве случаев правильнее этот запрос так и оставить и поручить его оптимизацию базе, чем пытаться вручную декомпозировать (и, соотвественно, получить вместо одного SQL-запроса несколько).

А бороться с фобией сложных процедур надо традиционными методами — подробным комментированием: что делается, зачем и почему именно так
Re[2]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 01.11.08 19:42
Оценка:
Сорри, интернета не было, скоро отпишусь Код будет, принесу в рабочий день!
Re[3]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 01.11.08 20:29
Оценка:
Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.

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

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

Наверное, не стоит углубляться в дебри заморочек, именуемых бизнесс-правилами, обрисую общую ситуацию. Есть шаблон расписания, с привязкой к дате начала его действия. У расписания есть временные интервалы — периоды, в течение которых человек должен быть "внутри". Расписания бывают разных приоритетов (1-основное, 2-исключений). Накладывая 2 на 1, получаем "реальное" положение дел.

Для того чтобы оценить, когда кто должен ходить, нужно сгенерировать последовательность интервалов с привязками к конкретной дате и времени, а потом в этой последовательности указывать, кто и как ходил. Так вот самое неприятное — генерировать эту последовательность... Потому как нужно правильно отметить студента, учесть правила, ... В этом моменте наслаиваются правила трех подсистем — "Расписание", "Кадры студентов", "Рабочая нагрузка на преподавателей". И поэтому генерировать не просто В общем все это — приамбула к коду ))))))))
Re[4]: Сложно-алгоритмо-фобия
От: klopodav  
Дата: 02.11.08 05:43
Оценка: +1
__>Для того чтобы оценить, когда кто должен ходить, нужно сгенерировать последовательность интервалов с привязками к конкретной дате и времени, а потом в этой последовательности указывать, кто и как ходил. Так вот самое неприятное — генерировать эту последовательность... Потому как нужно правильно отметить студента, учесть правила, ... В этом моменте наслаиваются правила трех подсистем — "Расписание", "Кадры студентов", "Рабочая нагрузка на преподавателей".
Если вот это все написать в виде комментариев внутри PL/SQL-процедуры, то код уже покажется не таким страшным, как раньше. Тут общий принцип такой: чем сложнее код и чем менее он очевиден — тем больше в нем надо комментариев

А своим первым постом я хотел сказать, что именно для PL/SQL длиная функция и сложная функция — это совсем не одно и то же. Потому что код на PL/SQL — это симбиоз двух подходов к программированию: алгоритмического (чистый PL/SQL) и декларативного (SQL)

Пусть, например, есть какая-нибудь такая функция:

FUNCTION some_proc() RETURN INTEGER
IS
   x INTEGER;
BEGIN

   SELECT <что-то> INTO x 
       FROM <много-много таблиц>
       WHERE( <много-много условий> )
       AND EXISTS(
            SELECT <огромадный вложенный запрос на 100 строк кода...>
       ...
       <и т.д.>
            )

   RETURN x;
END some_proc;


Сложный ли здесь алгоритм? Алгоритм здесь тривиальный: сделали запрос, вернули его результат.
Сложный ли запрос внутри этого алгоритма? Да, запрос сложный.
Надо ли в этом примере декомпозировать алгоритм? Нет, декомпозировать здесь абсолютно нечего. Главное — к запросу и его частям написать хорошие комментарии.

Кстати, если рассматривать запрос на SQL, то для него некий аналог декомпозиции — это завернуть часть запроса в отдельное представление (view). Но это не для всякого запроса можно сделать.
Re[4]: offtopic
От: Pavel Dvorkin Россия  
Дата: 03.11.08 02:42
Оценка:
Здравствуйте, __kain, Вы писали:

__>Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.


__>На данный момент, я перерабатываю систему учета посещаемости студентов ВУЗа (пишу заново). Данные для оценки посещений получаются автоматически, за счет проходных турникетов. Можно сказать, что такой подход не точен (мало ли где в универе студент шляется), но практика показала, что если в системе посещаемости студент не ходит, то он и в действительности не ходит.


Хм... Вообще-то последнее утверждение тривиально — если, конечно, нельзя пройти помимо турникета.

Если не секрет — какой университет ? Мне просто как преподавателю интересно... Честно говоря, мне бы и в голову не пришло бы, что такое где-нибудь может быть.
With best regards
Pavel Dvorkin
Re[5]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 03.11.08 07:40
Оценка:
Здравствуйте, klopodav, Вы писали:

K>А своим первым постом я хотел сказать, что именно для PL/SQL длиная функция и сложная функция — это совсем не одно и то же. Потому что код на PL/SQL — это симбиоз двух подходов к программированию: алгоритмического (чистый PL/SQL) и декларативного (SQL)


K>Сложный ли здесь алгоритм? Алгоритм здесь тривиальный: сделали запрос, вернули его результат.

K>Сложный ли запрос внутри этого алгоритма? Да, запрос сложный.
K>Надо ли в этом примере декомпозировать алгоритм? Нет, декомпозировать здесь абсолютно нечего. Главное — к запросу и его частям написать хорошие комментарии.

Абсолютно с Вами согласен!

K>Кстати, если рассматривать запрос на SQL, то для него некий аналог декомпозиции — это завернуть часть запроса в отдельное представление (view).


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

2 Pavel Dvorkin
ВУЗ Ростовский, называется РГУПС (Ростовский Государственный Университет Путей Сообщения).

Задумка получения "халявных" данных о посещаемости хорошая, осталось ее до ума довести А вообще эта система — любимая погремушка деканатов и проректоров
Re: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 03.11.08 14:44
Оценка: 75 (3) +2
Здравствуйте, __kain, Вы писали:

__>Привет всем!


__>Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу


__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)



Сложно посоветовать что-то конкретное, поэтому ограничусь
общими советами.

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

2. Процедурный код упрощается путем разбиения на части, как ты и делаешь.
Код со сложной логикой (признак такого кода — много сложных вложенных операторов
if, в которых трудно разобраться) можно упростить, например, если сначала
описать решение при помощи таблицы решений, а потом уже на ее основе
писать код.

3. Сложные SQL-запросы можно упростить несколькими способами:
— Использовать представления для выделения отдельных частей
запроса, как уже было сказано выше.
— Использовать WITH для улучшения читабельности запроса
(описано, например, в блоге Кевина Мида).
— Писать свои функции для упрощения сложных выражений в запросах
— Использовать табличные функции.
Re: Сложно-алгоритмо-фобия
От: Кодёнок  
Дата: 04.11.08 17:39
Оценка:
Здравствуйте, __kain, Вы писали:

__>разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк.


правильно делаешь

__>Смотрю я на нее, и впадаю в уныние


неправильно делаешь
Re[2]: Сложно-алгоритмо-фобия
От: Aikin Беларусь kavaleu.ru
Дата: 05.11.08 07:55
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD> — Использовать WITH для улучшения читабельности запроса

Спасибо за With Отличное средство декомпозиции.
Re[3]: Сложно-алгоритмо-фобия
От: Plague Россия 177230800
Дата: 05.11.08 14:25
Оценка: 1 (1)
A>Спасибо за With Отличное средство декомпозиции.

Уже обсуждалось и тут тоже... CTE (Common Table Expressions) называется... Очень удобно использовать для рекурсий, построения деревьев, например, в MS SQL... в оракле для этого давно CONNECT BY есть, при этом в Оракле CTE и CONNECT BY можно смешивать ...

Вот в MS SQL есть табличные функции с параметрами, а в Оракле ничего подобного нет, но в Оракле есть Пакеты, а подобного нет в MS SQL... они словно сговорились... =((
Re[4]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 05.11.08 19:53
Оценка:
2 Flying Dutchman
> В твоем случае структура базы довольно сложная, тем более что используются темпоральные данные, так что этому надо уделить особое внимание.
Структуру я весь диплом проектировал, и потом еще месяц =) Она получилась универсальной и вроде более-менее простой, но, действительно, наличие темпоральных данных только усложняет дело. Причем все эти данные могут потом еще и перегенерироваться (полностью и частично)... Я тут подумал, нужно наверное в структуру еще что-то добавить, чтобы в коде нужно было проводить меньше вычислений.

> Код со сложной логикой (признак такого кода — много сложных вложенных операторов if, в которых трудно разобраться)

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

> 3. Сложные SQL-запросы можно упростить несколькими способами:

Спасибо

В общем я понял, нет неразрешаемых проблем, просто мне нехватает теоретической базы Буду изучать предложенную матчасть

Наконец принес код. Прошу не вчитываться в него, это только пробный вариант, да и непонятен он будет. Просто взгляните на картинку
DECLARE
  PROCEDURE BuildIntervalSeq(p_att_User  IN 
                             p_date_from IN TIMESTAMP := NULL,
                             p_date_to   IN TIMESTAMP := NULL) IS
                             
    v_priority_idz    isa_att.TimeTableType.idz%TYPE;
    v_time_table_idz  isa_att.TimeTable.idz%TYPE;
    v_index           BINARY_INTEGER;
    v_date_offset     TIMESTAMP;
    v_interval_offset TIMESTAMP;
    v_time_step       INTERVAL DAY TO SECOND := p_att_common.GetSingleAdjustment('STUD_RASP_DUR');
    
    TYPE IntervalArray IS TABLE OF isa_att.TimeInterval%ROWTYPE;
    v_intervalArray  IntervalArray;
    
    -- Выбрать типы расписаний по приоритетам.
    CURSOR cTimeTablePriority IS
      SELECT idz
        FROM isa_att.TimeTableType
       ORDER BY priority ASC;
    
    -- Выбираем расписания, принадлежащие
    -- иерархическим группам студентов.
    CURSOR cTimeTableCur IS
      SELECT TimeTable_view.*
        FROM isa_att.TimeTable_view,
             isa_att.HierarchyGroup
       WHERE HierarchyGroup.s_HierarchyType = p_att_common.GetSingleAdjustment('STUD_HIERARCHY')
         AND TimeTable_view.s_Timetabletype = v_priority_idz
         AND TimeTable_view.s_HierarchyGroup = HierarchyGroup.Idz
         AND SYSTIMESTAMP BETWEEN TimeTable_view.Validfrom
                              AND NVL(TimeTable_view.ValidTo, SYSTIMESTAMP);
    
    CURSOR cTimeIntervals IS
      SELECT *
        FROM isa_att.TimeInterval
       WHERE s_TimeTable = v_time_table_idz
       ORDER BY fl_nad_chertoy DESC, TimeOffset;
       
    -- Выбираем расписание и валидных
    -- юзеров для этого времени
    CURSOR cTimeTableValidView IS
      SELECT *
        FROM isa_att.TimetableValid_View
       WHERE s_TimeTable = v_time_table_idz
         AND s_attUser = (SELECT idz FROM isa_att.AttUser where s_teksost = 40351);
  BEGIN
    v_intervalArray := IntervalArray();
    
    FOR curPriority IN cTimeTablePriority LOOP
      v_priority_idz := curPriority.Idz;
      FOR curTimeTable IN cTimeTableCur LOOP
        v_time_table_idz := curTimeTable.Idz;

        -- Выбираем в массив для многократного использования
        OPEN cTimeIntervals;
        FETCH cTimeIntervals BULK COLLECT INTO v_intervalArray;
        CLOSE cTimeIntervals;
        
        FOR curUserValidView IN cTimeTableValidView LOOP
          -- Получили временную метку начала расписания: отступаем "назад" до понедельника,
          -- т.к. занятия начинаются не обязательно в понедельник, а отсчет
          -- временных интервалов начинается с понедельника.
          v_date_offset := curTimeTable.ValidFrom - TO_NUMBER(TO_CHAR(curTimeTable.Validfrom, 'D')) + 1;
          
          -- <Перебираем даты>
          LOOP
            EXIT WHEN v_date_offset > curTimeTable.ValidTo;
            
            -- <Перебираем интервалы>
            v_index := v_intervalArray.FIRST;
            LOOP
              EXIT WHEN v_index IS NULL;
             
              v_interval_offset := v_intervalArray(v_index).TimeOffset + v_date_offset;
              IF  v_intervalArray(v_index).fl_nad_chertoy = 0 THEN
                v_interval_offset := v_interval_offset + 7;
              END IF;
               
              IF v_interval_offset  >= curTimeTable.ValidFrom THEN
                --dbms_output.put_line(TO_CHAR(v_interval_offset, 'DD.MM.YYYY HH24:MI'));
                DoLogic (v_interval_offset,
                     v_intervalArray(v_index).Duration,
                     curUserValidView.s_AttUser,
                     curUserValidView.Validfrom,
                     curUserValidView.Validto,
                     curTimeTable.s_Hierarchygroup,
                     curTimeTable.Idz,
                     v_intervalArray(v_index).idz);
              END IF;
                         
              v_index := v_intervalArray.NEXT(v_index);
            END LOOP; -- </Перебираем интервалы>
            
            v_date_offset := v_date_offset + v_time_step;
          END LOOP; -- </Перебираем даты>
        END LOOP; -- </Перебираем пользователей>
      END LOOP;
    END LOOP;
  END;
  
BEGIN
  BuildIntervalSeq;
END;
Re[5]: offtopic
От: maggot  
Дата: 06.11.08 00:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, __kain, Вы писали:


__>>Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.


__>>На данный момент, я перерабатываю систему учета посещаемости студентов ВУЗа (пишу заново). Данные для оценки посещений получаются автоматически, за счет проходных турникетов. Можно сказать, что такой подход не точен (мало ли где в универе студент шляется), но практика показала, что если в системе посещаемости студент не ходит, то он и в действительности не ходит.


PD>Хм... Вообще-то последнее утверждение тривиально — если, конечно, нельзя пройти помимо турникета.


PD>Если не секрет — какой университет ? Мне просто как преподавателю интересно... Честно говоря, мне бы и в голову не пришло бы, что такое где-нибудь может быть.

Такое даже в некоторых школах (в Москве) есть.
У учеников есть персональные магнитные карты, которые они прикладывают к турникету. В этот момент на экране монитора у охранника высвечивается фотография ученика и какие-то данные (наверное опаздывает ли учник в соответствии с расписанием). Если опаздывает, могут поругать =))
А также записывается в базу данных время входа и выхода из школы. В конце каждого месяца данные распечатываются и передаются классному руководителю.
Re[6]: offtopic
От: __kain Россия  
Дата: 06.11.08 07:25
Оценка:
Здравствуйте, maggot, Вы писали:

M>Такое даже в некоторых школах (в Москве) есть.

M>У учеников есть персональные магнитные карты, которые они прикладывают к турникету. В этот момент на экране монитора у охранника высвечивается фотография ученика и какие-то данные (наверное опаздывает ли учник в соответствии с расписанием). Если опаздывает, могут поругать =))
M>А также записывается в базу данных время входа и выхода из школы. В конце каждого месяца данные распечатываются и передаются классному руководителю.

У мну подсистема связана с кадрами, рабочей нагрузкой и учебным расписанием. Отчет выдается в виде соответствия расписания и посещения его человеком, т.е. автоматизация полная. Если сделать тупо, то да, за месяц можно. А если сделать нормально — с учетом плавающих, периодических и других графиков посещений, то тут прийдется извилины напрягать!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.