Что же мы носим и как?
Все исследуют SQL server на предмет качества и эффективности обслуживания разнообразных клиентов, которые написаны на C++, Csharp, Delphi, etc. Однако, никто не обращает внимание на поведение самого клиента, который, я бы сказал, «распоясался» в своем стремлении к архитектурным вершинам пошива новомодных классов на подиумах пространства имен и вычурных моделей высокой моды XML схем в ателье ООП. Чтобы увидеть изнанку клиента, которого мы собираемся сшить на Csharp, попробуем сравнить два варианта выполнения одинакового скрипта, состоящего из создания первой процедуры:
<%FIRST%>
IF EXISTS (SELECT * FROM [dbo].[sysobjects]
WHERE name='nex_GetGrouping' AND xtype='P')
DROP PROCEDURE [dbo].[nex_GetGrouping]
--Delimiter
GO
CREATE PROCEDURE [dbo].[nex_GetGrouping]
@Class int =null
AS
else
--Delimiter
GO
Данный скрипт можно выполнить непосредственно выполнив SQLCommand.ExecuteNonQuery(), что делает процедура Do Fast?().
Другой вариант более сложный и состоит в выполнении экземпляра класса в новом рабочем процессе с отслеживанием времени его выполнения в виде прогресс бара (процедура Do() ):
Ниже привожу текст кода, который сравнивает время выполнения:
String Builder? s = new String Builder?();
//1
s.AppendFormat(Script Helper.Get Statements?(«FIRST»));
Time Span? x = Date Time.Now?.TimeOfDay;
Do(Connection, s.ToString(), Initialization);
Time Span? y = Date Time.Now?.TimeOfDay;
Do Fast?(s.ToString());
Time Span? z = Date Time.Now?.TimeOfDay;
Message Box.Show?(«новый рабочий процесс с выполнением экземпляра класса:» + y.Subtract(x).ToString() + "\n\r Execute Non Query?():" + z.Subtract(y).ToString());
Message Box.Show?(«в " + (y.Subtract(x).TotalMilliseconds / z.Subtract(y).TotalMilliseconds).ToString() + " раз");
и результаты сравнения:
Я бы не стал писать, но результат настолько поразил меня такой старой и наболевшей проблемой «отцов и детей», что не могу не сказать, что выжимая эффективность со стороны работы сервера баз данных с одной стороны, с другой стороны или со стороны клиента вижу безпрецендентно счастливое детство ребят программистов, транжирящих ресурс для реализации своих классовых бредней в части создания моделей высокой моды. К таким же предметам высокой моды можно отнести и XML, хотя он уже перерос во что-то большее. Да, в общем, к этому я отношу весь ООП на стороне клиента, направленный на обработку данных, а не на их представление. Хочу добавить, что поскольку современных кутюрье много, то и API слоев в современном платье ООП набирается приличное количество в виде сорочек, подъюбников, подрясников, фартуков и подвязок.
Что ж будем программировать распоясавшись.
Понятно, что программировать стало легче, так как путь «написания программ без программистов» начат не сегодня и уже не вчера. Кстати, и теория золотого миллиона человечества также укладывается в парадигму развития программного обеспечения. То есть я тут программирую, но микро результаты труда любого программиста (и меня в том числе) умножат счастливое будущее «золотого миллиона», где каждый будет способен создать программу. Я чувствую, как меня (и может быть Вас) начинает наполнять гордость за свои не бесцельно прожитые годы. Но я не завидую этим прохвостам так как, при таком потребительском подходе, они тогда не смогут думать иначе, чем я сейчас. А это значит, что они могут только повторить. А раз повторение значит процесс творения утрачен, утрачен творческий мотив, тот элемент творчества ради которого стоит жить.
Да, это старый клиент NEXUS проекта VC++ v.6.0. Правда, он уже далек от своего прародителя 247 версии 2000 года. Идея динамического построения иерархий и ее представление при помощи Tree View? контрола состоит в том, что правило построения дерева объектов в контроле Tree View?, во-первых, может быть не одно и, во-вторых, возможен динамический переход от одного правила построения дерева к другому. Самая простая иллюстрация динамизма – это разворачивание дерева объектов с использованием двух иерархий: «по дате» и « «по алфавиту», что показано ниже. Выбор нужной иерархии здесь выполняется при помощи выпадающего меню, что, мягко говоря, не очень удобно.
В новом Csharp проекте Nexus клиента я попытался найти подходящее для выбора иерархий решение на основе контролов Tree View?, Group Box? and Radio Button?.
Конечно, это – решение, но мне, лично, оно не нравится. Логика построения динамических деревьев выходит за рамки стандартного контрола Tree View?. А один из миллионов «биллов гейтсов» уже не может выйти за рамки стандартного мышления. И в этом, как раз и состоит трагизм «мертвой
точки». Я думаю, это присуще не одному моему проекту.
61
Тревожит ночь. Глаза без сна открыты.
Возможно, без любви меня твой образ будит.
И в тенях прошлого желания сокрыты.
Возможно, тень твоя уже тогда не любит?
Не ты ли мысленно так далеко отсюда?
И все же праздные мои дела твой дух ревнует?
Он, как властитель дум, воображения причуда,
Владения границы моего ума диктует.
Но нет, моя любовь твоей сильнее,
Она лишь не дает моим глазам закрыться,
Любовь – слепа, но я еще слепее,
Ради тебя я – страж, которому все снится.
Любовь моя, ты от Амура стрел упала очень низко.
Свободу – мне, раз для него ты – слишком близко!
Как реализовать представление динамических деревьев объектов?
Я думаю, что решение, которое здесь будет предложено, подойдет. Пока оно реализовано частично, но уже работает. Идея реализации проста.
Разрабатывая бизнес приложение мало кто уделяет внимание курсору мыши. Предлагаю именно ее использовать, как носителя информации о том, как будет разворачиваться дерево объектов в treeview контроле. Главный use case поведения курсора мыши следующий:
При наведении указателя мыши на интересующий контрол начинает работать список доступных курсоров, который можно прокручивать повторным нажатием клавиши <esc>. Каждая иконка курсора соответствует своему объекту класса Group и стандартному просмотру дерева по папкам.
Если узел дерева не отмечен, то доступен только один курсор, соответствующий стандартному просмотру дерева по папкам.
Если узел дерева отмечен (selected), то доступен список курсоров, в который войдут все курсоры, соответствующие всем объектам класса Group,
в которых указан класс тех объектов, которые принадлежат выделенному узлу (иными словами они должны появиться в дереве при раскрытии (expand) дерева).
P.S. К этому хочется добавить, что класс C# Cursor не обеспечивает такого решения поскольку работает только с черно-белыми курсорами. Вот тебе бабка и Юрьев день. То есть надо возвращаться к С++ или использовать interop. Я что ли буду дописывть этот класс? не надо забывать, что есть еще анимированные курсоры.
Вчера (2008.04.01) реализовал основной функционал работы динамического разворачивания дерева, где основным элементом является курсор (mouse pointer, курсором назван потому, что в C# реализуется классом Cursor), который связан с соответствующим документов класса Group. Получилось (imho) вовсе недурно и даже удобно. Правой рукой при помощи мыши пользователь ведет раскрытие дерева объектов, а левой рукой при помощи клавиши <esc> (кстати название самой клавиши отражает процесс отказа от текущего разворачивания) выбирает нужные правила разворачивания. Новому правилу разворачивания соответствует другое изображение курсора. На скриншоте можно видеть, курсор в виде папки (это по папкам), далеее по алфавиту (буква А) и по дате (буква D). В любой момент можно перейти к стандартному представлению дерева с одним курсором.
Получив такой механизм разворачивания объектов дерева, приложение получает прекрасный поисковый инструмент. По своей производительности он даст фору многим поисковым системам, которые не ушли дальше представления поисковых результатов в виде линейного списка.
62
Люблю себя, как жизнь земную
Я всеми фибрами души,
И мастерства статую золотую
В глубинах сердца строю я в тиши.
Лица чертами очарован,
Вместилищем всех истин свят,
Превыше всех я здесь и скован
Из себялюбья мой наряд.
Лишь зеркало безмерного порока
Потасканный мой вид способно осветить
И понимаешь, что любовь к себе жестока,
Чудовищно так было бы любить.
Лишь мастерство незримо восхваляю,
Пусть стар, пока я вижу красоту – рыдаю.