вторник, 20 октября 2009 г.

.NET Label with transparent background

Чтобы организовать средствами .NET Framework такое чудо современных технологий разработки GUI, как текстовое поле с прозрачным фоном размещённое поверх какой-то картинки в Win Forms нужно:
  1. Разместить на форме компонент Panel, задав в качестве свойства BackgroundImage желаемую картинку.
  2. Затем поместить на этот Panel новый Label и задать в качестве параметра BackColor значение Transparent.
Если же, по каким-то причинам использовать Panel с размещённым на нём Label вам не с руки, то можно использовать для этих целей компонент PictureBox (MyPicture) с нужной картинкой и расположенный поверх него Label со значением свойства BackColor равным Transparent и свойством Parent программно установленным в значение MyPicture (Label1.Parent = MyPicture;).

вторник, 22 сентября 2009 г.

Links: Trac & Apache with Open SSL on Windows

http://r3code.livejournal.com/77730.html - Немного уже устаревший, но всё ещё очень полезный материал годовой давности по настройке Trac 0.11.1 + Python 2.5 + Apache 2.0.x + Subversion 1.5.2 под Windows.

http://www.neilstuff.com/apache/apache2-ssl-windows.htm - Хорошая How-to-шка по настройке Apache + Open SSL.

http://vingrad.ru/blogs/Bishop/2009/07/19/ustanovka-trac-pod-windows/ - Тоже хорошая How-to-шка по установке Trac под Windows, но без Apache и Open SSL.

http://stackoverflow.com/questions/309412/how-to-setup-setuptools-for-python-2-6-on-windows - setuptools под Python 2.6.

http://badwords.org/w/Compile_mod_python_for_Python_2.6 - Компиляция mod_python.so для Apache под Python 2.6. С этим делом у меня так ничего и не получилось, ибо исходники mod_python из релиза компилиться отказались, вывалив мне 2 какието ошибки во время компиляции, а до репозитория я достучаться так и не смог.

Из личного опыта
Процесс установки из статьи r3code, в принципе, очень прост, не занимает много времени и сил. Проблемы начинаются, когда хочется отойти от инструкций и поставить версию софта посовременне и сделать что нибудь, чего r3code не описал. С Apache 2.2 проблем никаких не возникло. При попытке настроить SSL шифрование только в директории /svn/ на одном из виртуальных хостов своего Apache пришлось долго и упорно плясать с бубном по причине отсутствия опыта и понимания опций конфига Open SSL. Далее мне приспичило вместо Python 2.5, как в статье, поставить Python 2.6. В итоге убил не один час на разбор вопроса "где взять setuptools для питона 2.6 под винду?" и попытки откомпилить mod_python.so для Apache под всё тот же Python 2.6. Провозившись с питоном 2.6 несколько часов, плюнул и установил 2.5.
P.S.: На этом процесс поднятия Trac пока застопорился по причине моей занятости на другом проекте. Позже отпишу, как прошли остальные этапы установки.

Update
http://trac.edgewall.org/wiki/CookBook/Installation/TracOnWindowsWithAccountManager - Пошаговая инструкция по установке Trac под Windows (Eng).

среда, 19 августа 2009 г.

Last.fm recently played list by XternalX Userbars

Итак, наконец-то мой друг Виктор XternalX выпустил первую бета версию своих динамических юзербаров, с чем я его от всей души и поздравляю! :) И в этом блогпосте я постараюсь описать процесс создания юзербара отображающего списко последних пяти прослушанных мной на Last.FM композиций. Надо сказать, что родной сервис юзербаров от last.fm работает, мягко говоря, не корректно, поэтому сервис динамических юзербаров XternalX Userbars тут оказался, как нельзя кстати.

Last.FM XternalX Userbar

Первое, что мы делаем, регистрируем себе новый аккаунт в XternalX Userbars. Форма регистрации находится здесь. После чего войдя в XternalX Userbars под только что созданной учётной записью, мы попадаем в редактор юзербаров (Рис. 1).

Рис. 1 Панель управления XternalX Userbars


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

Рис. 2 Файловый менеджер

В файловом менеджере уже есть несколько картинок, которые можно использовать в качестве фона, но мы загрузим свою картинку. Для этого внизу окна файлового менеджера щёлкнем ссылку "Загрузить файл". Откроется диалог изображенный на рисунке 3.

Рис. 3 Диалог загрузки фона юзербара

Нажмём кнопку "Обзор..." и выберем нужный нам фон, в моём случае -- это давно заготовленная картинка, которую я безуспешно пытался, в своё время, скормить сервису юзербаров last.fm. Учтите, что картинка обязательно должна быть в формате PNG!
Теперь понравившийся нам фон выбран, жмём ссылку "Загрузить" внизу диалога загрузки фонового изображения. После загрузки мы снова окажемся в Файловом менеджере. Не спешите искать в списке файлов, только что загруженный нами, его там нет (бета версия как ни как ;)). Необходимо закрыть файловый менеджер, щелчком по крестику в его верхнем правом углу, и открыть его снова. Теперь список файлов в файловом менеджере обновился и мы можем спокойно найти только что загруженный нами файл и выбрать его (Рис. 4).

Рис. 4 Предпросмотр выбранного в файловом менеджере изображения

Теперь закрываем файловый менеджер (да-да, я не опечатался, именно закрываем). И в панели управления XternalX Userbars щёлкаем плюсик справа от поля "Основа юзербара". Теперь в текстовом поле "Основа юзербара" образовалось название только что загруженного нами файла. Для того, чтобы выбранный нами фон отобразился в предпросмотре юзербара нажмём кнопочку "Сохранить" внизу панели упарвления XternalX Userbars. Результат на рисунке 5.

Рис. 5 Предпросмотр юзербара

Теперь включим необходимые нам плагины. Для этого заходим в "Расширения" и приводим там всё в соответствие с рисунком 6.

Рис. 6 Менеджер расширений XternalX Userbars

Затем щёлкаем по гаечному ключу справа от расширения "Last.FM Track Feed" и настраиваем его (Рис. 7). В поле "Введите URL до Вашей RSS Ленты" вводим следующий адрес: http://ws.audioscrobbler.com/1.0/user/Akinfold/recenttracks.rss естественно, заменяя имя пользователя last.fm на своё. В поле "Формат даты и времени" вводим "H:i". И нажимаем "Сохранить".

Рис. 7 Настройки Last.FM Track Feed


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

Листинг 1.
str(100,12,7,0,arial,000000,lastfm(1,date))
str(130,7,12,0,arial,000000,lastFm(1,title))

str(100,24,7,0,arial,666666,lastfm(2,date))
str(130,23,8,0,arial,666666,lastFm(2,title))

str(100,36,7,0,arial,666666,lastfm(3,date))
str(130,35,8,0,arial,666666,lastFm(3,title))

str(100,48,7,0,arial,666666,lastfm(4,date))
str(130,47,8,0,arial,666666,lastFm(4,title))

str(100,60,7,0,arial,666666,lastfm(5,date))
str(130,59,8,0,arial,666666,lastFm(5,title))
Как мы видим, код юзербара разбит на 5 однотипных блоков. Каждый блок кода отвечает за вывод одной строки формата <время> <композиция>. Каждый такой блок состоит из двух вызовов функции str, которая отвечает за вывод текста в XternalX Userbars. Эта функция принимает 7 параметров:
  1. Горизонтальное положение левой границы надписи относительно левого края юзербара. Или, проще говоря, координата текста по оси X.
  2. Вертикальное положение верхней границы надписи относительно верхнего края юзербара. Или, проще говоря, координата надписи по оси Y.
  3. Размер шрифта в пикселях.
  4. Угол поворота текста.
  5. Шрифт, которым будет отрисовываться текст на юзербаре.
  6. Цвет шрифта.
  7. Текст. В нашем случае текст возвращает функция lastFm речь о которой пойдёт далее.
Таким образом, каждая первая строка блока отображает время, когда была прослушана композиция, а каждая вторая строка отвечает за отображение названия и автора композиции. В нашем примере для вывода информации о композициях мы используем функцию lastfm, которая принимает два параметра:
  1. Номер композиции в списке недавно прослушанных композиций. Последняя прослушанная композиция имеет номер 1, прослушанная до неё композиция имеет номер 2 и так далее.
  2. Ключевое слово, сообщающее функции, какую информацию о композиции выводить. В нашем случае мы выводим время прослушивания композиции (ключевое слово date) и название композиции (ключевое слово title).
Ну вот, наконец-то всё готово и мы жмём ссылку "Сохранить" внизу панели управления XternalX Userbars. Теперь результат наших трудов отображается в предпросмотре юзербара (Рис. 8).

Рис. 8 Юзербар готов к употреблению

Теперь смело копируем ссылку на наш юзербар из поля "Ссылка на Ваш юзербар" и вставляем в подпись на форумах, в блогах и т.д. и т.п. кому на что фантазии хватит. ;)

Форум XternalX Userbars.

пятница, 14 августа 2009 г.

Google Sync, а счастье было так близко, казалось рукой подать...

... ан нет! Оказалось не всё так просто.

Google Sync -- это новый, хотя уже и не особо, сервис от google inc. Идея сервиса заключается в глобальной синхронизации контактов, календарей, почтовых ящиков и т.д. и т.п. на мобильных девайсах с гуглесервисами. На данный момент синхронизируются только контакты и календарь. Синхронизация происходит с помощью протокола Microsoft® Exchange ActiveSync®, поэтому google настоятельно рекомендует для синхронизации использовать спец. софтину Nokia Mail for Exchange. Хотя в интернете мелькают инструкции по настройке синхронизации и без неё (но у меня сей вариант не прошёл).

Скачав и установив на свой Nokia 3250 спец. софтину, я бэкапнул все настройки телефона с помощью Nokia PC Suite и полез в инструкцию по установке Google Sync. Первое и единственное на чём я споткнулся, было поле "Домен", которое по инструкции следовало бы оставить пустым, но mail for exchange категорически отказалась принимать настройки с пустым полем "Домен", пришлось написать там "m.google.com", не знаю на сколько это решение было верно, ибо после первого же запуска, залез в настройки и опустошил это поле, как того требует инструкция. В принципе, установка и настройка потребовали минимум времени и прошли легко и не принуждённо.

Далее, причесав контакты в Gmail аккаунте, я попытался синхронизировать контакты gmail'а и телефона. Залез в "Мои приложения", запустил Mail for Exchange, и начал синхронизацию. Порадовало, что и этот процесс прошел без малейших осложнений. Софтина аккуратно в течении всего процесса синхронизации показывала сколько записей она обновила и где, хотя вполне можно было и не следить за этим, закрыв приложение.

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

Итог. После экспериментов с контактами, пробовать тоже самое и на календаре желание как-то само собой отпало. Удалил с телефона Nokia Mail for Exchange и решил на полгодика-годик забыть о тотальной синхронизации девайсов, а там поглядим...

вторник, 11 августа 2009 г.

Следование стандартам...

Так сложилось, что вот уже несколько месяцев занимаюсь программированием на PHP, пишу свои классы и модули, попутно ковыряя чужие, верстаю и т.д. и т.п. И за всё это время я не видил НИ ОДНОГО продукта (естественно опенсорс) полностью соответствующего стандартам W3C и парадигмам ООП. Интересно, почему разработчики столь наплевательски относятся к стандартам, по сути писавшимся для них, дабы облегчить их нелёгкий труд?

С ООП всё, более или менее, понятно. PHP изначально был процедурным языком и ни о каком ООП в нём речи не шло. Да и сейчас в версии 5.1 часть парадигм ООП не полностью поддерживается или поддерживается с помощью всевозможных "костылей" выдаваемых за преимущества PHP.
Например в PHP нет т.н. акцессоров и мутаторов, точнее они "как бы" есть, предлагается пользоваться следующей конструкцией:
<?php
class MyClass {
private $properties;
function __set($name, $value) {
echo "задание нового свойства $name = $value";
$this->properties[$name]=$value;
}
function __get($name) {
echo "чтение значения свойства ", $name;
return $this->properties[$name];
}
}
$obj = new MyClass;
$obj->property = 1; // Выводит "задание нового свойства property=1"
$a = $obj->property; // Выводит "чтение значения свойства property"
echo $a; // выводит 1;
?>

Таким методом конечно можно обрабатывать изменения свойств объектов, но для того чтобы заставить класс принимать только нужные (запланированные) параметры придётся писать switch и в нём проверять имена указываемых пользователем параметров, что не слишком то удобно.

А вот со стандартами косорциума W3C всё не так просто. По какой то не ведомой мне причине практически все разработчики плюют на эти стандарты и воротят ТАКОЕ, что хватаешься за голову.
Вроде бы HTML все в школе/техникуме/институте изучают, да и W3C на месте не сидит, создавая для разработчиков всякие валидаторы, обнаруживающие ошибки в гипертексте странички и подробно разбирая каждую в соответствии со стандартом. В инете полно русско-язычных (и не только русско) ресурсов с подробным объяснением всех этих стандартов. И тем не менее разработчики продолжают испытывать браузеры на прочность своим бредом в гипертексте и жабаскрипте. Просто ради интереса зайдите вот сюда -> http://validator.w3.org/check?uri=http%3A%2F%2Fwww.lastfm.ru%2F&charset=%28detect+automatically%29&doctype=Inline&group=0&user-agent=W3C_Validator%2F1.654 и обалдейте от количества ошибок и варнингов найденных валидатором в коде странички (страничка подвернулась случайно, просто этот сайт упорно отказывается у меня работать под оперой уже в течении двух его версий).
А вот и тест любимого ВКонтакта -> http://validator.w3.org/check?uri=http%3A%2F%2Fvkontakte.ru&charset=%28detect+automatically%29&doctype=Inline&group=0
Причём заметьте, и тот и другой -- являются коммерческими проектами. Про не коммерческий код я вообще молчу...

SEF Service Map & UTF-8 encoded URLs

SEF Service Map это компонент, перед которым стоит задача создания полной карты сайта.
Кроме того компонент совместим со всеми стандартными расширениями Joomla! (статьи, RSS ленты, ссылки, контакты и т.д.),
SEF Service Map является открытым компонентом - это позволяет интегрировать его с другими компонентами,
такими как галереи, форумы, каталоги и другие, благодаря встроенным механизмам интеграции!

SEF Service Map создает не только карту сайта, но и карту совместимую со стандартом sitemaps.org :
- XML карта (например: для Google)
- TXT карта (например: для Yahoo)

Но эта зараза на отрез отказывается работать совместно с русскоязычными UTF-8 урликами вида: http://some.site/Новости/Новости-сайта/Превеееед-медвед.html
Точнее работать то она с ними работает и даже HTML-карту генерирует валидную, а вот с XML- и TXT- картами проблема. Все красивые русские урлики в них выглядят примерно так: http://some.site/Ð�овоÑ�ти/Ð�овоÑ�ти-Ñ�айта/

Порывшись в коде нашёл проблему. Разработчики при генерации XML- и TXT- карт выполняют перекодировку линка на статью в UTF-8. Вобщем проблема решается таким образом:
  1. Открываем файлик /components/com_sefservicemap/sefservicemap.html.php
  2. Закомменчиваем или удаляем все вхождения строки "$link = utf8_encode($link);" (их 2)
  3. Радуемся жизни... ;)

суббота, 8 августа 2009 г.

Автопрокрутка многострочного Textbox из .NET Framework

Понадобилось сегодня сделать автопрокрутку лога приложения, нашёл для себя два способа реализовать задуманное.
Первый и, пожалуй, самый простой способ:
Устанавливать, например в обработчике события TextChanged, позицию начала выделения текста равной длине текста в textbox'е и, затем, перематывать scrollbar textbox'а до текущей позиции каретки.
private void tbLog_TextChanged(object sender, EventArgs e)
{
this.tbLog.SelectionStart = this.tbLog.TextLength;
this.tbLog.ScrollToCaret();
}

Однако, у этого способа есть один недостаток: при такой перемотке scrollbar'а перемещается каретка ввода текста, что не всегда бывает приемлемо.

Второй способ немного интереснее и лишён вышеописанного недостатка, хотя и немного сложнее:
Посылать textbox'у, например всё в томже обработчике события TextChanged, сообщение WM_VSCROLL.
private const int WM_VSCROLL = 0x115;
private const int SB_BOTTOM = 7;

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

private void tbLog_TextChanged(object sender, EventArgs e)
{
SendMessage(this.tbLog.Handle, WM_VSCROLL, (IntPtr) SB_BOTTOM, IntPtr.Zero);
}

среда, 29 июля 2009 г.

"Продвинутый" пример использования PHPLinq

Музыка: Hospital Mix.Six (Mixed By Cyantific)

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

Представим, что есть у нас пять яблок массив объектов Employee (служащий). А нужно нам отсортировать этот массив по имени и возрасту служащих и получить в результате массив только тех служащих, имя которых состоит из четырёх символов. И чтобы уж совсем усложнить задачу, в результате мы хотим получить не массив экземпляров класса Employee, а массив объектов, содержащих мыло и домен почтового сервера служащего. Жестоко, не правдали? ;)
Перво на перво, объявим класс служащих и заполним массив экземплярами этого класса:

class Employee {
public $Name;
public $Email;
public $Age;

public function __construct($name, $email, $age) {
$this->Name = $name;
$this->Email = $email;
$this->Age = $age;
}
}

$employees = array(
new Employee('Maarten', 'maarten@example.com', 24),
new Employee('Paul', 'paul@example.com', 30),
new Employee('Bill', 'bill.a@example.com', 29),
new Employee('Bill', 'bill.g@example.com', 28),
new Employee('Xavier', 'xavier@example.com', 40)
);

А теперь легко и не принуждённо с помощью PHPLinq брюки превращаются... превращаются... выполним, поставленную в начале, задачу:

$result = from('$employee')->in($employees)
->where('$employee => strlen($employee->Name) == 4')
->orderBy('$employee => $employee->Name')
->thenByDescending('$employee => $employee->Age')
->select('new {
"EmailAddress" => $employee->Email,
"Domain" => substr($employee->Email, strpos($employee->Email, "@") + 1)
}');

И снова, как и в предыдущем примере, вы могли заметить странный код 'new { }'. Что он делает? А он конвертируется в объект анонимного типа (класса). Например, конструкция вида new { "name" => "test" } преобразуется в объект содержащий поле "name" со значением "test".

понедельник, 20 июля 2009 г.

PHPLinq: Language Integrated Query for PHP

PHPLinq -- это набор классов PHP имитирующий функциональность предоставляемую расширением LINQ языка C#. LINQ позволят обращаться к данным из программы, способом очень сильно напоминающим SQL, но минуя написание SQL запросов как таковых.
Например, пусть у нас есть массив строк и мы хотим выбрать из него только те строки, длина которых меньше пяти символов. Обычным способом нам потребовалось бы писать цикл, в котором мы бы проверяли длину каждого элемента массива и добавляли бы подходящие по длине элементы во временную переменную:
// Создаём массив строк
$Names = array("John", "Peter", "Joe", "Patrick", "Donald", "Eric");
$Result = array();
foreach ($Name in $Names) {
if (strlen($Name) < 5) {
$Result[] = $Name;
}
}
С помощью PHPLinq это легко сделать следующим способом:
// Создаём массив строк
$Names = array("John", "Peter", "Joe", "Patrick", "Donald", "Eric");
$Result = from('$Name')->in($Names)
->where('$Name => strlen($Name) < 5')
->select('$Name');
Похоже на SQL? ;) Кроме того, решение с использованием PHPLinq гораздо компактнее и выглядит гораздо более красиво. Сам автор PHPLinq, Maarten Balliauw, пишет:
С LINQ есть одна проблемка... Если вы начали использовать его, то вы не захотите больше обращаться к источникам данных иными способами.
P.S.: В четвёртой строчке второго листинга вы могли заметить странную конструкцию '$Name => strlen($Name) < 5. Эта конструкция преобразуется в анонимную функцию или другими словами лямбда-выражение. Эта функция принимает параметр $Name и возвращает булево значение которое является результатом вычисления выражения strlen($Name) < 5.

Домашняя страничка PHPLinq -> http://www.phplinq.net/

пятница, 10 июля 2009 г.

Поддержка нотации Dimensional в CA ERWin Data Modeler

Музыка: Noisia - Fabric Live.40

В продукте ERWin Data Modeler компании Computer Associates имеетя поддержка нотации Dimensional, предназначенной для поддержки методологии размерного проектирования хранилищ данных. Данная нотация в ERWin доступна только для физической модели. Для её включения в ERWin 3.x:
  1. Создай новую модель (Меню File / New...).
  2. В диалоге Template Selection выбери из списка предлагаемых шаблонов -- Dimension.
В ERWin 4.x и старше эта нотация "вшита" уже более жестко и подключается не файлом шаблона, а в настройках модели:
  1. Создай новую (Меню File / New...) или открой уже существующую физическую или смешанную модель.
  2. Открой свойства модели (Меню Model / Model Properties...).
  3. В диалоговом окне Model Properties перейди на вкладку Notation.
  4. В группе Physical Notation выбери DM (Dimensional Modeling) и нажми OK.
  5. Если выполняется конвертация уже существующей модели, а не новой пустой, то ERWin проверит возможность конвертации всех связей и типов данных в модели и в случае возникновения каких либо конфликтов спросит, что делать.

вторник, 7 июля 2009 г.

Введение в OLAP: часть 2. Хранилища данных.

Музыка: Noisia - Fabric Live.40

Да простят меня авторы оригинальной статьи, Алексей Федоров и Наталия Елманова, преподаватели УКЦ "Interface Ltd", опубликовавшие её в пятом номере журнала КомпьютерПресс за 2001 год, но уж больно не хочется терять такую ценную статью из вида.

Итак...

Введение в OLAP: часть 2. Хранилища данных.
Первая статья данного цикла (см. Введение в OLAP: часть 1. Основы OLAP) была посвящена основам OLAP (On-Line Analytical Processing) — технологии многомерного анализа данных. В ней мы обсудили концепции хранилищ данных и OLAP, требования к хранилищам данных и OLAP-средствам, логическую организацию OLAP-данных, а также основные термины и понятия, относящиеся к многомерному анализу.
В настоящей статье мы рассмотрим типичную структуру хранилищ данных, поговорим о том, что представляет собой OLAP на клиенте и на сервере, а также обсудим некоторые технические аспекты многомерного хранения данных.

Типичная структура хранилищ данных

Как мы уже знаем, конечной целью использования OLAP является анализ данных и представление результатов этого анализа в виде, удобном для восприятия и принятия решений. Основная идея OLAP заключается в построении многомерных кубов, которые будут доступны для пользовательских запросов. Однако исходные данные для построения OLAP-кубов обычно хранятся в реляционных базах данных. Нередко это специализированные реляционные базы данных, называемые также хранилищами данных (Data Warehouse). В отличие от так называемых оперативных баз данных, с которыми работают приложения, модифицирующие данные, хранилища данных предназначены исключительно для обработки и анализа информации, поэтому проектируются они таким образом, чтобы время выполнения запросов к ним было минимальным. Обычно данные копируются в хранилище из оперативных баз данных согласно определенному расписанию.
Типичная структура хранилища данных существенно отличается от структуры обычной реляционной СУБД. Как правило, эта структура денормализована (это позволяет повысить скорость выполнения запросов), поэтому может допускать избыточность данных.
Для дальнейших примеров мы снова воспользуемся базой данных Northwind, входящей в комплекты поставки Microsoft SQL Server и Microsoft Access. Ее структура данных приведена на рис. 1.

Рис. 1. Структура базы данных Northwind

Основными составляющими структуры хранилищ данных являются таблица фактов (fact table) и таблицы измерений (dimension tables).

Таблица фактов
Таблица фактов является основной таблицей хранилища данных. Как правило, она содержит сведения об объектах или событиях, совокупность которых будет в дальнейшем анализироваться. Обычно говорят о четырех наиболее часто встречающихся типах фактов. К ним относятся:
  • факты, связанные с транзакциями (Transaction facts). Они основаны на отдельных событиях (типичными примерами которых являются телефонный звонок или снятие денег со счета с помощью банкомата);
  • факты, связанные с «моментальными снимками» (Snapshot facts). Основаны на состоянии объекта (например, банковского счета) в определенные моменты времени, например на конец дня или месяца. Типичными примерами таких фактов являются объем продаж за день или дневная выручка;
  • факты, связанные с элементами документа (Line-item facts). Основаны на том или ином документе (например, счете за товар или услуги) и содержат подробную информацию об элементах этого документа (например, количестве, цене, проценте скидки);
  • факты, связанные с событиями или состоянием объекта (Event or state facts). Представляют возникновение события без подробностей о нем (например, просто факт продажи или факт отсутствия таковой без иных подробностей).
Для примера рассмотрим факты, связанные с элементами документа (в данном случае счета, выставленного за товар).
Таблица фактов, как правило, содержит уникальный составной ключ, объединяющий первичные ключи таблиц измерений. Чаще всего это целочисленные значения либо значения типа «дата/время» — ведь таблица фактов может содержать сотни тысяч или даже миллионы записей, и хранить в ней повторяющиеся текстовые описания, как правило, невыгодно — лучше поместить их в меньшие по объему таблицы измерений. При этом как ключевые, так и некоторые неключевые поля должны соответствовать будущим измерениям OLAP-куба. Помимо этого таблица фактов содержит одно или несколько числовых полей, на основании которых в дальнейшем будут получены агрегатные данные.
Пример таблицы фактов, которая может быть построена на основе базы данных Northwind, приведен на рис. 2.
Рис. 2. Пример таблицы фактов

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

Отметим, что для многомерного анализа пригодны таблицы фактов, содержащие как можно более подробные данные (то есть соответствующие членам нижних уровней иерархии соответствующих измерений). В данном случае предпочтительнее взять за основу факты продажи товаров отдельным заказчикам, а не суммы продаж для разных стран — последние все равно будут вычислены OLAP-средством. Исключение можно сделать, пожалуй, только для клиентских OLAP-средств (о них мы поговорим чуть позже), поскольку в силу ряда ограничений они не могут манипулировать большими объемами данных.

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

Таблицы измерений
Таблицы измерений содержат неизменяемые либо редко изменяемые данные. В подавляющем большинстве случаев эти данные представляют собой по одной записи для каждого члена нижнего уровня иерархии в измерении. Таблицы измерений также содержат как минимум одно описательное поле (обычно с именем члена измерения) и, как правило, целочисленное ключевое поле (обычно это суррогатный ключ) для однозначной идентификации члена измерения. Если будущее измерение, основанное на данной таблице измерений, содержит иерархию, то таблица измерений также может содержать поля, указывающие на «родителя» данного члена в этой иерархии. Нередко (но не всегда) таблица измерений может содержать и поля, указывающие на «прародителей», и иных «предков» в данной иерархии (это обычно характерно для сбалансированных иерархий), а также дополнительные атрибуты членов измерений, содержавшиеся в исходной оперативной базе данных (например, адреса и телефоны клиентов).
Каждая таблица измерений должна находиться в отношении «один ко многим» с таблицей фактов.
Отметим, что скорость роста таблиц измерений должна быть незначительной по сравнению со скоростью роста таблицы фактов; например, добавление новой записи в таблицу измерений, характеризующую товары, производится только при появлении нового товара, не продававшегося ранее.
Пример таблицы измерений приведен на рис. 3.

Рис. 3. Пример таблицы измерений

Одно измерение куба может содержаться как в одной таблице (в том числе и при наличии нескольких уровней иерархии), так и в нескольких связанных таблицах, соответствующих различным уровням иерархии в измерении. Если каждое измерение содержится в одной таблице, такая схема хранилища данных носит название «звезда» (star schema). Пример такой схемы приведен на рис. 4.

Рис. 4. Пример схемы «звезда»

Если же хотя бы одно измерение содержится в нескольких связанных таблицах, такая схема хранилища данных носит название «снежинка» (snowflake schema). Дополнительные таблицы измерений в такой схеме, обычно соответствующие верхним уровням иерархии измерения и находящиеся в соотношении «один ко многим» в главной таблице измерений, соответствующей нижнему уровню иерархии, иногда называют консольными таблицами (outrigger table). Пример схемы «снежинка» приведен на рис. 5.

Рис. 5. Пример схемы «снежинка»

Отметим, что даже при наличии иерархических измерений с целью повышения скорости выполнения запросов к хранилищу данных нередко предпочтение отдается схеме «звезда».
Однако не все хранилища данных проектируются по двум приведенным выше схемам. Так, довольно часто вместо ключевого поля для измерения, содержащего данные типа «дата», и соответствующей таблицы измерений сама таблица фактов может содержать ключевое поле типа «дата». В этом случае соответствующая таблица измерений просто отсутствует.
В случае несбалансированной иерархии (например, такой, которая может быть основана на таблице Employees базы данных Northwind, имеющей поле EmployeeID, которое одновременно является и первичным, и внешним ключом и отражает подчиненность одних сотрудников другим (см. рис. 1) в схему «снежинка» также следует вносить коррективы. В этом случае обычно в таблице измерений присутствует связь, аналогичная соответствующей связи в оперативной базе данных.
Еще один пример отступления от правил — наличие нескольких разных иерархий для одного и того же измерения. Типичные примеры таких иерархий — иерархии для календарного и финансового года (при условии, что финансовый год начинается не с 1 января), или с различными способами группировки членов измерения (например, группировать товары можно по категориям, а можно и по компаниям-поставщикам). В этом случае таблица измерений содержит поля для всех возможных иерархий с одними и теми же членами нижнего уровня, но с разными членами верхних уровней (пример такой таблицы приведен на рис. 3).
Как мы уже отмечали выше, таблица измерений может содержать поля, не имеющие отношения к иерархиям и представляющие собой просто дополнительные атрибуты членов измерений (member properties). Иногда такие атрибуты могут быть использованы при анализе данных.
Более подробно о проектировании хранилищ данных и одном из CASE-инструментов, способных упростить процесс их создания, — CA ERwin, рассказано в статье Сергея Маклакова «Хранилища данных и их проектирование с помощью CA ERwin», КомпьютерПресс, CD-ROM № 1’2001).
Следует сказать, что для создания реляционных хранилищ данных нередко применяются специализированные СУБД, хранение данных в которых оптимизировано с точки зрения скорости выполнения запросов. Примером такого продукта является Sybase Adaptive Server IQ, реализующий нетрадиционный способ хранения данных в таблицах (не по строкам, а по столбцам). Однако создавать хранилища можно и в обычных реляционных СУБД.
Итак, обсудив типичную структуру хранилища данных, на основе которых обычно строятся OLAP-кубы, вернемся к созданию OLAP-кубов и поговорим о том, какими бывают OLAP-инструменты.

OLAP на клиенте и на сервере
Многомерный анализ данных может быть произведен с помощью различных средств, которые условно можно разделить на клиентские и серверные OLAP-средства.
Клиентские OLAP-средства представляют собой приложения, осуществляющие вычисление агрегатных данных (сумм, средних величин, максимальных или минимальных значений) и их отображение, при этом сами агрегатные данные содержатся в кэше внутри адресного пространства такого OLAP-средства.
Если исходные данные содержатся в настольной СУБД, вычисление агрегатных данных производится самим OLAP-средством. Если же источник исходных данных — серверная СУБД, многие из клиентских OLAP-средств посылают на сервер SQL-запросы, содержащие оператор GROUP BY, и в результате получают агрегатные данные, вычисленные на сервере.
Как правило, OLAP-функциональность реализована в средствах статистической обработки данных (из продуктов этого класса на российском рынке широко распространены продукты компаний StatSoft и SPSS) и в некоторых электронных таблицах. В частности, неплохими средствами многомерного анализа обладает Microsoft Excel 2000. С помощью этого продукта можно создать и сохранить в виде файла небольшой локальный многомерный OLAP-куб и отобразить его двух- или трехмерные сечения.
Многие средства разработки содержат библиотеки классов или компонентов, позволяющие создавать приложения, реализующие простейшую OLAP-функциональность (такие, например, как компоненты DecisionCube в Borland Delphi и Borland C++Builder). Помимо этого многие компании предлагают элементы управления ActiveX и другие библиотеки, реализующие подобную функциональность.
Отметим, что клиентские OLAP-средства применяются, как правило, при малом числе измерений (обычно рекомендуется не более шести) и небольшом разнообразии значений этих параметров, — ведь полученные агрегатные данные должны умещаться в адресном пространстве подобного средства, а их количество растет экспоненциально при увеличении числа измерений. Поэтому даже самые примитивные клиентские OLAP-средства, как правило, позволяют произвести предварительный подсчет объема требуемой оперативной памяти для создания в ней многомерного куба.
Многие (но не все!) клиентские OLAP-средства позволяют сохранить содержимое кэша с агрегатными данными в виде файла, что, в свою очередь, позволяет не производить их повторное вычисление. Отметим, что нередко такая возможность используется для отчуждения агрегатных данных с целью передачи их другим организациям или для публикации. Типичным примером таких отчуждаемых агрегатных данных является статистика заболеваемости в разных регионах и в различных возрастных группах, которая является открытой информацией, публикуемой министерствами здравоохранения различных стран и Всемирной организацией здравоохранения. При этом собственно исходные данные, представляющие собой сведения о конкретных случаях заболеваний, являются конфиденциальными данными медицинских учреждений, которые ни в коем случае не должны попадать в руки страховых компаний и тем более становиться достоянием гласности.
Идея сохранения кэша с агрегатными данными в файле получила свое дальнейшее развитие в серверных OLAP-средствах, в которых сохранение и изменение агрегатных данных, а также поддержка содержащего их хранилища осуществляются отдельным приложением или процессом, называемым OLAP-сервером. Клиентские приложения могут запрашивать подобное многомерное хранилище и в ответ получать те или иные данные. Некоторые клиентские приложения могут также создавать такие хранилища или обновлять их в соответствии с изменившимися исходными данными.
Преимущества применения серверных OLAP-средств по сравнению с клиентскими OLAP-средствами сходны с преимуществами применения серверных СУБД по сравнению с настольными: в случае применения серверных средств вычисление и хранение агрегатных данных происходят на сервере, а клиентское приложение получает лишь результаты запросов к ним, что позволяет в общем случае снизить сетевой трафик, время выполнения запросов и требования к ресурсам, потребляемым клиентским приложением. Отметим, что средства анализа и обработки данных масштаба предприятия, как правило, базируются именно на серверных OLAP-средствах, например, таких как Oracle Express Server, Microsoft SQL Server 2000 Analysis Services, Hyperion Essbase, продуктах компаний Crystal Decisions, BusinessObjects, Cognos, SAS Institute. Поскольку все ведущие производители серверных СУБД производят (либо лицензировали у других компаний) те или иные серверные OLAP-средства, выбор их достаточно широк и почти во всех случаях можно приобрести OLAP-сервер того же производителя, что и у самого сервера баз данных.
Отметим, что многие клиентские OLAP-средства (в частности, Microsoft Excel 2000, Seagate Analysis и др.) позволяют обращаться к серверным OLAP-хранилищам, выступая в этом случае в роли клиентских приложений, выполняющих подобные запросы. Помимо этого имеется немало продуктов, представляющих собой клиентские приложения к OLAP-средствам различных производителей.
OLAP-серверы могут хранить многомерные данные разными способами, которые мы и обсудим в следующем разделе.

Технические аспекты многомерного хранения данных
В многомерных хранилищах данных содержатся агрегатные данные различной степени подробности, например, объемы продаж по дням, месяцам, годам, по категориям товаров и т.п. Цель хранения агрегатных данных — сократить время выполнения запросов, поскольку в большинстве случаев для анализа и прогнозов интересны не детальные, а суммарные данные. Поэтому при создании многомерной базы данных всегда вычисляются и сохраняются некоторые агрегатные данные.
Отметим, что сохранение всех агрегатных данных не всегда оправданно. Дело в том, что при добавлении новых измерений объем данных, составляющих куб, растет экспоненциально (иногда говорят о «взрывном росте» объема данных). Если говорить более точно, степень роста объема агрегатных данных зависит от количества измерений куба и членов измерений на различных уровнях иерархий этих измерений. Для решения проблемы «взрывного роста» применяются разнообразные схемы, позволяющие при вычислении далеко не всех возможных агрегатных данных достичь приемлемой скорости выполнения запросов.
Как исходные, так и агрегатные данные могут храниться либо в реляционных, либо в многомерных структурах. Поэтому в настоящее время применяются три способа хранения данных:
  • MOLAP (Multidimensional OLAP) — исходные и агрегатные данные хранятся в многомерной базе данных. Хранение данных в многомерных структурах позволяет манипулировать данными как многомерным массивом, благодаря чему скорость вычисления агрегатных значений одинакова для любого из измерений. Однако в этом случае многомерная база данных оказывается избыточной, так как многомерные данные полностью содержат исходные реляционные данные.
  • ROLAP (Relational OLAP) — исходные данные остаются в той же реляционной базе данных, где они изначально и находились. Агрегатные же данные помещают в специально созданные для их хранения служебные таблицы в той же базе данных.
  • HOLAP (Hybrid OLAP) — исходные данные остаются в той же реляционной базе данных, где они изначально находились, а агрегатные данные хранятся в многомерной базе данных.
Некоторые OLAP-средства поддерживают хранение данных только в реляционных структурах, некоторые — только в многомерных. Однако большинство современных серверных OLAP-средств поддерживают все три способа хранения данных. Выбор способа хранения зависит от объема и структуры исходных данных, требований к скорости выполнения запросов и частоты обновления OLAP-кубов.
Отметим также, что подавляющее большинство современных OLAP-средств не хранит «пустых» значений (примером «пустого» значения может быть отсутствие продаж сезонного товара вне сезона).

Заключение
В данной статье мы рассмотрели типичную структуру реляционных хранилищ данных. Итак, теперь мы знаем, что:
  • типичная структура хранилища данных существенно отличается от структуры обычной реляционной СУБД — как правило, она денормализована;
  • основными составляющими структуры хранилищ данных являются таблица фактов (fact table) и таблицы измерений (dimension tables);
  • таблица фактов является основной таблицей хранилища данных. Обычно она содержит сведения об объектах или событиях, совокупность которых будет в дальнейшем анализироваться; таблица фактов, как правило, содержит уникальный составной ключ, состоящий из первичных ключей таблиц измерений. При этом как ключевые, так и некоторые неключевые ее поля должны соответствовать будущим измерениям OLAP-куба. Помимо этого таблица фактов содержит одно или несколько числовых полей, на основании которых в дальнейшем вычисляются агрегатные данные; таблицы измерений содержат неизменяемые либо редко изменяемые данные — как правило, по одной записи для каждого члена нижнего уровня иерархии в измерении;
  • таблицы измерений содержат как минимум одно описательное поле и, как правило, целочисленное ключевое поле для однозначной идентификации члена измерения;
  • каждая таблица измерений должна находиться в отношении «один ко многим» с таблицей фактов;
  • если каждое измерение содержится в одной таблице измерений, такая схема хранилища данных носит название «звезда». Если же хотя бы одно измерение содержится в нескольких связанных таблицах, такая схема хранилища данных носит название «снежинка».
Далее мы обсудили особенности клиентских и серверных OLAP-средств. Мы узнали, что:
  • клиентские OLAP-средства представляют собой приложения, осуществляющие вычисление агрегатных данных (сумм, средних величин, максимальных или минимальных значений) и их отображение, при этом сами агрегатные данные содержатся в кэше внутри адресного пространства такого OLAP-средства;
  • в серверных OLAP-средствах сохранение и изменение агрегатных данных, а также поддержка содержащего их хранилища осуществляются отдельным приложением или процессом, называемым OLAP-сервером;
  • в случае применения серверных средств вычисление и хранение агрегатных данных происходят на сервере, что позволяет в общем случае снизить требования к ресурсам, потребляемым клиентским приложением, а также сетевой трафик и время выполнения запросов.
  • наконец, мы рассмотрели различные технические аспекты многомерного хранения данных. Мы узнали, что в настоящее время применяются три способа хранения данных:
    • MOLAP (Multidimensional OLAP) — и детальные, и агрегатные данные хранятся в многомерной базе данных. В этом случае многомерные данные полностью содержат исходные детальные данные;
    • ROLAP (Relational OLAP) — детальные данные остаются в той же реляционной базе данных, где они находились изначально. Агрегатные же данные помещаются в специально созданные для их хранения служебные таблицы в той же самой базе данных;
    • HOLAP (Hybrid OLAP) — детальные данные остаются в той же реляционной базе данных, где они и находились изначально, а агрегатные данные хранятся в многомерной базе данных.
Мы также узнали, что подавляющее большинство современных OLAP-средств не хранит «пустых» значений.
В следующей статье данного цикла мы рассмотрим архитектуру Microsoft Analysis Services — OLAP-сервера фирмы Microsoft, входящего в комплект поставки Microsoft SQL Server 2000 Enterpise Edition.

среда, 29 апреля 2009 г.

Восстановление D-Link DIR-130 после не удачной прошивки

Музыка: I.N.I - Desimal Tribute Mix (Скачать)

Пару недель назад установил я на свой DIR-130 новую прошивку с ftp://ftp.dlink.ru/, после чего аппарат скоропостижно скончался. Времени отнести его в сервис (благо роутер пока ещё на гарантии) в рабочее время всё как-то не находилось, вот и решил попробовать решить проблему своими силами.
Оказалось, что для восстановления DIR-130 после не удачной прошивки, нужно совершить всего лишь несколько простых телодвижений:
  1. Качаем с ftp://ftp.dlink.ru/ прошивку.
  2. Втыкаем витую пару от компьютера в любое LAN гнездо роутера.
  3. Настраиваем вручную параметры соединения на компьютере:
    • IP-адрес: 192.168.0.2
    • Маска подсети: 255.255.255.0
  4. Выключаем питание роутера.
  5. Зажимаем кнопку Reset (например зубочисткой).
  6. Включаем питание роутера и держим Reset зажатым 5 секунд.
  7. В браузере переходим по адресу http://192.168.0.1/.
  8. На открывшейся страничке указываем файл с прошивкой из п.1 и нажимаем Send.
  9. Ждём, пока прошивка установится (~2 минуты).
  10. После этого DIR-130 перезагрузится и запустится с новой прошивки.

среда, 15 апреля 2009 г.

SyntaxHighlighter 2.0. Подсветка синтаксиса программного кода в блоге

Музыка: LTJ Bukem - Earth Volume 1 >> LTJ Bukem - Earth Volume 2

Обустраивая свой блог, в предыдущей статье столкнулся с необходимостью подсветки кода исходников в блоге. Google находит много всяких разных подсветчиков по запросу "подсветка кода в blogger", но мне понравился скрипт SyntaxHighlighter.
SyntaxHighlighter - это полнофункциональный самостоятельный скрипт подсветки синтаксиса (code syntax highliter) поддерживающий кучу языков, имеющий удобный небольшой тулбарчик с кнопками, позволяющими выводить исходник в отдельном окне и копировать его в буфер обмена. Скрипт абсолютно мультиплатформенный и может работать в любом блоге хоть в WordPress, хоть в Joomla!, хоть в Blogger.com.
Итак, хватит о том, какой SyntaxHighlighter хороший и красивый, далее о том, как его установить в свой блог на blogger.com.
  1. Зайди на страничку своего блога, далее Настроить -> Макет -> Изменить HTML
  2. Добавь в код своей странички, непосредственно перед закрывающим тэгом </head> следующий код:

    <link href='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
    <script src='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Scripts/shCore.js' type='text/javascript'/>
    <script src='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Scripts/shBrushPhp.js' type='text/javascript'/>
    <script src='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Scripts/shBrushXml.js' type='text/javascript'/>
    <script src='http://bitbucket.org/alexg/syntaxhighlighter/raw/8815b7f713eb/Scripts/shBrushCSharp.js' type='text/javascript'/>
    <script type='text/javascript'>
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.all();
    </script>
    Если ты обратишь внимание, на текст свойства src тэга script, то увидишь, что в 4, 5 и 6-й строках мы подключаем необходимые нам языки (PHP, HTML и C#). Для подключения любого другого языка нужно, всего лишь, скопировать любую из этих трёх строк и изменить имя подключаемого файла на необходимое. Полный список поддерживаемых языков, их алиасов и файлов, необходимых для их подсветки, можно найти на сайте разработчика.

  3. Сохрани изменённый шаблон.

  4. Теперь, чтобы исходники в блоге отображались с помощью SyntaxHighlighter, тебе необходимо заключать куски кода в тэги <pre class="brush: php"></pre>, заменяя значение свойства brush на алиас языка, синтаксис которого необходимо подсвечивать. Список поддерживаемых алиасов можно посмотреть на сайте разработчика. Например, в этой статье я использовал нижеприведённый код:

    <pre class="brush: html">
    &lt;p&gt;Пример HTML-кода&lt;/p&gt;
    </pre>
Всё хорошо, но есть одно НО, для того, чтобы всё корректно работало, необходимо внимательно следить, чтобы в исходниках, которые ты вставляешь в блог, символ "<" был заменён на "&lt;".

среда, 8 апреля 2009 г.

Классы, их наследование и объекты "на пальцах"

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

Итак, что же такое классы и их наследники и чем они отличаются от объектов.

Возьмём, к примеру, класс Стол. Этот класс обладает свойствами: Длина, Ширина, Высота. И имеет метод, например: Стоять.
У класса Стол есть наследники (дочерние классы). Например, класс ПисьменныйСтол и КомпьютерныйСтол. Эти классы наследуют от родительского класса Стол все его свойства (Длина, Ширина, Высота) и методы (Стоять), но класс ПисьменныйСтол, по мимо унаследованных от родительского класса Стол свойств и методов, может иметь дополнительное своство КоличествоЯщиков и метод ВыдвинутьЯщик. Также и класс КомпьютерныйСтол может иметь свойство КоличествоСекцийДляCD и метод ВыдвинутьСтолешницу.
Стол
, КомпьютерныйСтол и ПисьменныйСтол -- это классы.
Почему?
Потому что это некоторые сущности, которые описывают некий набор свойств и поведений характерных для всех столов (класс Стол) или только для компьютерных столов (класс КомпьютерныйСтол) или только для письменных столов (класс ПисьменныйСтол).
Но тогда что же такое объект?
Объект -- это стол за которым ты сейчас сидишь (причём скорее всего это объект класса КомпьютерныйСтол). Объект -- это (в большинстве случаев) экземпляр некоторого класса. Также как твой компьютерный стол является экземпляром класса КомпьютерныйСтол.

Перенося всё это в PHP код получим:

<?php

/**
* Стол
*/
class Table {
/**
* Длина стола
* @var float
*/
public Length;

/**
* Ширина стола
* @var float
*/
public Width;

/**
* Высота стола
* @var float
*/
public Height;

/**
* Осуществляет стояние стола
*/
public function Stand() {

}
}

/**
* КомпьютерныйСтол
*/
class ComputerTable extends Table {
/**
* Количество секций для CD
* @var int
*/
public CDSectionsCount;

/**
* Выдвигает столешницу с клавиатурой
*/
public function MoveOutTabletop() {

}
}

/**
* ПисьменныйСтол
*/
class Desk extends Table {
/**
* Количество ящиков
* @var int
*/
public DeskDrawerCount

/**
* Выдвигает ящик с указанным номером
* @param int $DeskDrawerNumber Номер выдвигаемого ящика
*/
public function MoveOutDeskDrawer($DeskDrawerNumber) {

}
}

$MyTable = new Table(); // а вот $MyTable -- это уже объект класса Table
$MyTable->Width = 1;
$MyTable->Height = 0.7;
$MyTable->Length = 3;

$MyComputerTable = new ComputerTable(); // $MyComputerTable -- тоже объект
$MyComputerTable->Width = 0.8; // и так как класс ComputerTable является
$MyComputerTable->Height = 0.7; // наследником класса Table, то он имеет
$MyComputerTable->Length = 0.5; // все теже свойства что и объект $MyTable
$MyComputerTable->CDSectionsCount = 5; // плюс новое свойство CDSectionsCount

$MyComputerTable->Stand(); // Аналогично свойствам наследуются и методы
$MyComputerTable->MoveOutTabletop();

?>


P.S.: PHP -- не лучший выбор для начала освоениея ООП, но сейчас я пишу в основном на нём.

вторник, 17 марта 2009 г.

JPATH_ROOT, JPATH_BASE и JPATH_SITE в чём разница?

Итак, в чём же разница меж этими константами в Joomla? Этим вопросом я задавался достаточно длительное время, но на поиски различий времени никогда не было, хотя эти самые различия несомненно должны были быть! =)
Сегодня наконец-то руки дошли погуглить по данному сабжу. И вот результат:

JPATH_ROOT -- всегда содержит путь установки (куда на web-сервере была установлена) Joomla!, только его и ничто другое.
JPATH_SITE -- всегда содержит путь к приложению (экземпляру класса JApplication) JSite, то есть путь где находится корень front-end'а Joomla. Аналогично JPATH_ADMINISTRATOR -- содержит путь к корню back-end'а Joomla.
JPATH_BASE -- всегда содержит путь к корню текущего приложения, то есть когда вы находитесь в back-end константа JPATH_BASE == JPATH_ADMINISTRATOR, а когда находитесь во front-end -- JPATH_BASE == JPATH_SITE.

Вот такие вот они константы в Joomla...