Деревья на Ls?

Тема в разделе "Lotus - Программирование", создана пользователем fedotxxl, 25 янв 2008.

  1. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Буянит во мне идея, но недели две не получается реализовать
    Смысл:

    В начале и в конце каждого Sub'a/Function'a пишется wf.Start / wf.End
    В середине можно залогировать какое-либо событие, запусть что-либо (например benchmark - тест производительности)... В итоге нужно получить отчет типа:
    Код (Text):
    Sub1 LogEvent
    Sub2 AnotherLogEvent
    Sub1 BenchmarkEvent
    Т.е. построить дерево, состоящее из сабов + доп инфа...
     
  2. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
    где построить?

    аа.... кажеться понял... хотя возможно и не так понял
    в скрипте ваши сабы зделайте функциями boolean и дальше

    Код (Text):
    if LogEvent then
    if AnotherLogEvent then...


    if BenchmarkEvent then
    ....
     
  3. Yakov

    Yakov Гость

    В wf.Start передавайте в качестве параметра имя вызывающей процедуры/функции: wf.Start(GetThreadInfo(LSI_THREAD_PROC)).
    Или в самом методе wf.Start берите имя вызвавшей процедуры/функции: GetThreadInfo(LSI_THREAD_CALLPROC).
    Было бы интресно узнать задачу/цель и взглянуть на пример кода. Есть идеи. :)
     
  4. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    желаете-с универсальное логирование получить, да еще и с учетом стека вызовов?.. :)

    поройте функцию lsi_info() (аналог GetThreadInfo), возможно там есть весь стек вызовов, кто знает... в дебагере-то как-то строится стек вызова, значит и так можно построить...
     
  5. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Для: Akupaka
    Именно... нужен стек вызовов. lsi_info выдает стек, но это не дело. Если в каждом Sub'e писать Start и End, то мы сможем составить этот стек сами. Другое дело, как правильно это сделать. В этом и вопрос
    Логирование я сюда приписал как вариант использования

    Для: Yakov
    Спасибо, сам знаю.

    Для: Morpheus
    Мне кажется вы неправильно поняли

    Задача: посторить стек вызовов на основе классов, запоминания информации по вызовам. +возможность расширения до логирования, benchmarka и т.д.

    В итоге у нас получится, я так понимаю, разветвленное дерево Sub'ов
    Нужно вспомнить как строить деревья и принемимо ли это тут
     
  6. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Удивительно, но какую-то вменяемую хрень я написал
    Код (Text):
    Class wfSubController
    Private scCurrentSub As wfSub

    Public Sub Start(ID As String)
    If scCurrentSub Is Nothing Then
    Set scCurrentSub = New wfSub(ID, Nothing)
    Elseif scCurrentSub.ID <> ID Then
    Dim scTempSub As wfSub
    Set scTempSub = New wfSub(ID, scCurrentSub)
    Call scCurrentSub.AddSub(scTempSub)
    Set scCurrentSub = scTempSub
    End If
    Call scCurrentSub.Start
    End Sub

    Public Sub End(ID As String)
    If scCurrentSub.ID <> ID Then
    Error 1
    Exit Sub
    End If
    Call scCurrentSub.End
    End Sub

    Public Sub GoToPrevSub
    Set scCurrentSub = scCurrentSub.ParentSub
    End Sub

    End Class

    Class wfSub
    Private sID As String
    Private sParentSub As wfSub
    Private sSubs List As wfSub
    Private sActions() As Action
    Private sLevel As Integer

    Public Sub New(ID As String, ParentSub As wfSub)
    sID = ID
    If ParentSub Is Nothing Then
    sLevel = 1
    Else
    sLevel = ParentSub.Level + 1
    End If

    Set sParentSub = ParentSub
    End Sub

    Public Sub AddSub(wfSub As wfSub)
    Set sSubs(wfSub.ID) = wfSub
    End Sub

    Public Sub Start

    End Sub

    Public Sub End

    End Sub

    Property Get Level
    Level = sLevel
    End Property

    Property Get ParentSub
    Set ParentSub = sParentSub
    End Property

    Property Get ID
    ID = sID
    End Property
    End Class
    Это наброски... в дебагере получил очень хороший результат... Прикол в том, что писал наугад... просто писал, почти не думая :)
    Пример Сабов:
    Код (Text):
    Sub Sub1(sc As wfSubController)
    sc.Start(Lsi_info(2))

    Call Sub2(sc)

    sc.End(Lsi_info(2))
    sc.GoToPrevSub
    End Sub
    Есть соображения, что неправильно, как улучшить?
    Сейчас проблема - если в самом первом Sub'e вызвать sc.GoToPrevSub, то scCurrentSub станет Nothing... Вобщем утро вечера мудренее
     
  7. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    хм... я, наверное, не понимаю в чем смысл... вернее, задачу-то, понял, а вот область применения не "вижу"... :D

    деревья-то не сложно строить, сложнее их анализировать :)
    но в чем смысл? получить дерево процедур для дальнейшего анализа?.. других применений не вижу...
     
  8. Yakov

    Yakov Гость

    <!--QuoteBegin-fedotxxl+26:01:2008, 06:33 -->
    <span class="vbquote">(fedotxxl @ 26:01:2008, 06:33 )</span><!--QuoteEBegin-->Есть соображения, что неправильно, как улучшить?
    [snapback]95115" rel="nofollow" target="_blank[/snapback]​
    [/quote]
    Выбросить sc.GoToPrevSub. Действия по перемещению указателя осуществлять в sc.End().
    Сделать класс wfSubController Singleton'ом, это избавит от необходимости передавать экземпляр всем процедурам.
    Убрать аргументы у процедур sc.Start() и sc.End().
     
  9. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Для: Yakov
    Дело в том, что между sc.End и sc.GoToPrevSub будет стоять метод sc.Process, который будет обрабатывать полученную информацию в случае необходимости... Например, что-либо распечатывать... А если делать этот метод после GoToPrevSub, то саб-то уже другой... впринципе можно запихнуть метод process в End...
    Аргументы передаются для контроля - если закрывается процедура отличная от текущей, то ошибка...
    Не очень понял...

    Лично сейчас я вижу два применения - качественная отладка длительности работы и логирование, которое будет создавать один файл с логами на весь агент, а нет по файлу на саб
    Может быть ещё прибавится
     
  10. Yakov

    Yakov Гость

    Для: fedotxxl
    Singleton кратко описан в Википедии.
    Наверное, хотелось бы иметь отладочный лог прогонки агента, тест производительности и т.п., но чтобы всего этого не было в продакшн-версии без переписывания кучи кода. Тогда имеет смысл создать класс "контроллера" с пустыми реализациями методов start() и end() и его подклассы, выполняющие действия по профилированию или записи лога.
    Далее код, иллюстрирующий мои замечания. Писал прямо здесь, это только наброски.
    Код (Text):
    Public Class Controller

    Private Sub New()
    End Sub

    Public Sub start()
    End Sub

    Public Sub stop()
    End Sub

    End Class

    Public Class Logger As Controller

    Private sc As wfSubController

    Private Sub New()
    Set sc = New wfSubController(...)
    End Sub

    Public Sub start()
    Call sc.Start(GetThreadInfo(LSI_THREAD_CALLPROC))
    End Sub

    Public Sub stop()
    Call sc.End(GetThreadInfo(LSI_THREAD_CALLPROC))
    Call sc.Process()
    Call sc.GoToPrevSub()
    End Sub

    End Class

    Public Class Profiler As Controller

    '...

    End Class

    Private theController As Controller

    Public Function getController() As Controller
    If theController Is Nothing Then
    Set theController = New Controller() 'New Profiler(), New Logger()
    End If
    Set getController = theController
    End Function
    Пример клиентского кода.
    Код (Text):
    Sub Initialize
    Call getController().start()
    Call sub1()
    Call sub2()
    Call getController().stop()
    End Sub

    Sub sub1
    Call getController().start()
    '...
    Call sub11()
    '...
    Call getController().stop()
    End Sub

    Sub sub11
    Call getController().start()
    '...
    Call getController().stop()
    End Sub

    Sub sub2
    Call getController().start()
    '...
    Call getController().stop()
    End Sub
    Изменив одну строчку, получим нужную функциональность.
    Кстати, в Lotus есть логгер NotesLog.
    И еще замечание. В справке указано:
     
  11. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Для: Yakov
    Прости, в ООП я пока не силен, и голова не варит...

    1. Для того, чтобы не передавать контроллер как параметр, ты его объявляешь global'ом?
    2. Любое общение с контроллером идет через функцию getController?
    3. Новая для меня вещь - переменной объявленной как Base класс можно присваивать наследующие классы?
    4. Предположим, что у Logger'a и Profiler'a существуют свои методы, которые не совпадают (например в Logger'e - .Log, в Profiler'e - .Profile)... Тогда я в контроллере определяю все возможные методы, а соотв классах переопределяю только нужные?
    5. В итоге при тестировании метод getController() у меня будет выглядеть
    Код (Text):
    Public Function getController() As Logger
    If theController Is Nothing Then
    Set theController = New Logger() 'New Profiler(), New Logger()
    End If
    Set getController = theController
    End Function
    , а при конечной сдаче
    ?
    6. Я так понял, что такая реализвация позволит мне переключаться между Logger, Profiler и Controller путем переписания двух строк? Есть ли ещё какие преимущества?

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

    Кстати, посмотрел насколько оправдано использование метода getController только лишь для того, чтобы не писать дополнительную строку проверки на существование класса в начале каждого метода. Получил, что 10000 раз исполнения этого метода занимают .015 сек =) Темная вещь
     
  12. Yakov

    Yakov Гость

    ==== к сожалению, случайно закрыл вкладку браузера вместе с постом на три экрана. восстановлю, когда высплюсь. :) ====
    краткое содержание.

    0. Ничего, что в ООП не силен, это проходит.
    1. Нет.
    2. Да.
    3. Да. Один из принципов ООП - полиморфизм.
    4. Вариантов море. Один вы озвучили.
    5. Да.
    6. Да. Разве этого преимущества недостаточно?

    Не более 1.5 микросекунд на вызов функции не такое большое время, чтобы его заметить, если вы не робот-андроид.
     
  13. fedotxxl

    fedotxxl Well-Known Member

    Регистрация:
    9 ноя 2005
    Сообщения:
    614
    Симпатии:
    0
    Для: Yakov
    Жду вашего развернутого поста, если не сложно

    Как же подругому?
    Гм.. все-равно мне это сложно понять. В чем преимущество?
    Это очень интересная техника, но мне несколько иное требовалось
     
  14. Yakov

    Yakov Гость

    Для: fedotxxl

    Прошу прощения за столь долгое отсутствие.

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

    1. ООП и дизайн.
    Классика - Гради Буч. Объектно-ориентированный анализ и проектирование.

    Паттерны (шаблоны) проектирования - опять же классическая книга "банды четерых" - Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования.
    Но эту книгу читать очень тяжело. В принципе, практически в любой книге по UML приводится большое количество паттернов проектирования.
    Еще одна очень хорошая книга - Мартин Фаулер. Архитектура корпоративных программных приложений.

    2. Рефакторинг (переработка кода).
    Мартин Фаулер. Рефакторинг. Улучшение существующего кода.
    (Мартин Фаулер вообще очень мощный профессионал. Считаю, что его книги нужно брать не раздумывая. А лучше сразу две: одну самому читать, вторую коллегам/друзьям дарить. См. также http://martinfowler.com/)
    Джошуа Кериевски. Рефакторинг с использованием шаблонов (паттернов проектирования).
    Эта книга из серии Martin Fowler Signature Series. После ее прочтения становятся понятны многие паттерны и способы их применения. Must have (как и всю Martin Fowler Signature Series).

    3. Измерение производительности и оптимизация кода.
    Крис Касперски. Техника оптимизации программ. Эффективное использование памяти.


    Еще мощный источник знаний и опыта - исходные коды. И не только лотусовые исходники. К примеру, в java очень хорошая и большая библиотека классов. В ней есть практически все, что нужно.
    Существует масса библиотек и инструментов с открытыми исходными кодами, к примеру, Apache log4j для журналирования (проект apache.org).
    Я считаю, что чтение исходников - это своего рода обучение программерскому ремеслу (и искусству) у профессионалов. Изучил исходник, проникся, применил к своей задаче (пусть даже на другом ЯП).
     
Загрузка...

Поделиться этой страницей