Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

23.02.2017

Google
WWW CITForum.ru
С Новым годом!
2005 г.

Обзор: первое знакомство с Delphi 2005

Алексей Вуколов, Елена Филиппова, Игорь Шевченко, «Королевство Delphi»

Содержание
  1. Первая страница
  2. Редактор кода
  3. Рефакторинг
  4. Unit-тестирование
  5. Компилятор
  6. Отладка
  7. Встроенный Data Explorer

Первая страница

После загрузки среды перед нами возникает приветственная страница "Welcome Page". Это новый аналог того самого окошка новостей, которое выглядело довольно неказисто, если ваш компьютер не был подключен к интернету во время работы. Однако не стоит так же сбрасывать со счетов и новый вариант. Кроме ленты новостей (RSS), "Welcome Page" содержит немало полезных ссылок. Во-первых, в самом верху страницы перечислен список проектов, которые вы уже открывали некоторое время назад, с указанием даты последней модификации. Каждая ссылка, естественно, открывает выбранный проект.

Показать скриншот в отдельном окне

В левой части страницы подобраны ссылки на справочную информацию, документацию, которая устанавливается на ваш компьютер при инсталяции Delphi2005. Далее идут ссылки в интернет, на страницы компаний-разработчиков, чьи продукты встроены в среду. Например, на страницу Rave Reports, IntraWeb и так далее. И, наконец, ссылки на новостные группы в интернете, BDN и другие страницы Borland-ресурсов. То есть, "Welcome Page", действительно содержит полезную информацию. Может быть, не часто придется ею пользоваться, но и забывать о ней не стоит, может пригодиться.

Среда предоставляет возможнсть работать как в классическом стиле предыдущих версий Delphi (с отдельными окнами для дизайнера форм, инспектора объектов и т.д.), так и в стиле, максимально приближенном к MS Visual Studio, когда все окна пристыковываются к центральному, в котором можно заниматься дизайном формы или редактированием кода.

Для того, чтобы привести окна редактирования и палитры компонентов к привычному виду, поэкспериментируйте с настройками Tools | Environment Options | Delphi Options | VCL Designer | Embedded designer и Tools | Environment Options | Tool Pallete.

В Delphi2005 изменилась справочная система. Изменился не только внешний вид, но внутренняя структура предлагаемой информации.

На мой взгляд, пользоваться справкой стало намного удобнее.

Показать скриншот в отдельном окне

Появилась возможность настраивать цвета для Object Inspector, смотритеTools | Environment Options | Object Inspector.

[ К содержанию ]

Редактор кода

С редактором кода стало работать намного удобнее.

Комментирование блока текста

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

В новой IDE это делается легким движением руки. Выделяем текст, нажимаем клавиши [Ctrl+/] и весь выделенный код оказался закомментирован. Обратная операция делается точно так же. На всякий случай напомню, почему это лучше, чем обычные скобки {} в начале и конце куска кода. В случае использования в начале каждой строки двойного слеша нет никакой нужды заботиться о вложенных комментариях, которые могут уже быть в выделенном тексте. Этот способ "устранения" части кода бывает удобен при отладке.

Очень удобна новая возможность редактора показывать соответствующие пары скобок (см. рисунок).

[ К содержанию ]

Сворачивание части кода

Как и в Delphi8, в редакторе Delphi2005 реализовано частичное скрытие (сворачивание кода). Это позволяет работать с большими текстами, не прокручивая многостраничный экран. Достаточно оставить развернутым сейчас только тот код, который используется. Для того чтобы свернуть или развернуть нужный блок, специально предусмотрены значки [-] и [+] в левой части редактора. Если нажать на значок [-], например, возле определения метода, код этого метода будет свернут, то есть, убран из видимости. Но, кроме этого, есть возможность применить эту операцию ко всему коду, а не только к текущему месту.

В меню по правой кнопке мыши есть два пункта Fold и UnFold. Это, соответственно, операции "свернуть" и "развернуть". Для каждой из них нужно указать место действия. Например, свернуть все методы в коде или все определения типов. Хочется заметить, что "свернутая" часть кода никуда не девается, а лишь уходит из видимой части редактора. Так что, если при компиляции или во время работы "Error Insight", ошибка окажется в свернутом коде, он прекрасным образом будет развернут автоматически в нужном месте. Так что никакой путаницы не возникнет.

Кроме этих возможностей, введены две директивы, которые по синтаксису аналогичны директивам компилятора, но оказывают влияние на поведение редактора, а не на генерируемый код. Это директивы $REGION и $ENDREGION. Они задают начало и конец сворачиваемого региона кода. Можно задать имя региона, в этом случае, когда регион свернут, вместо многоточия отображается имя региона (см. рис).

[ К содержанию ]

Help Insight

Если в привычном "Code Insight" показывался тип идентификатора (переменной, функции и т.д.) и модуль, в котором он определен, то "Help Insight" представляет собой всплывающее окно-подсказку, с кратким описанием этого идентификатора и дополнительными ссылками (см. рис). Достаточно подвести мышку к нужному идентификатору, чтобы получить такой "маленький help". Использовать "Help Insight" можно в комбинации с "Code Completion". Если в окне "Code Completion" выбрать определенное свойство или метод, то справа появится окно с подсказкой.

Открыть скриншот в отдельном окне

Эта возможность реализована не только для стандартных, но и для собственных классов и переменных. Использование "Help Insight" включено по умолчанию. Местонахождение в настройках: Tools->Options->Editor Options->Code Insight

[ К содержанию ]

Error Insight

В левой части экрана есть окно "Structure". Оно используется для показа визуальных компонент, лежащих на форме, переменных и констант, списка модулей, которые подключены и так далее. Но, кроме этого окно "Structure" может показывать список синтаксических ошибок, которые определяются до момента компиляции с помощью "Error Insight".

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

[ К содержанию ]

Sync Edit

При выделении части кода в редакторе, на левой полосе, вслед за выделяемыми строками, передвигается маленькая иконка (на рисунке она отмечена красным). Это включение режима "Sync Edit". Если нажать на эту иконку, то выделенный текст подкрасится (при цветовых настройках по умолчанию) голубым цветом и будет выделен первый в блоке идентификатор.

Открыть скриншот в отдельном окне

Суть режима "Sync Edit" в том, что он позволяет показать в выделенном тексте все повторяющиеся идентификаторы, их может оказаться несколько групп. Самая первая считается текущей.

Для текущей группы все дубли помечены рамочкой, для остальных групп просто подчеркнуты. Переход между группами повторяющихся идентификаторов осуществляется клавишей TAB. Если начать изменять текущий идентификатор, то вслед за ним будут синхронно изменены все его дубли в этом выделенном блоке. Это похоже на "Рефакторинг: переименование идентификатора".

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

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

Повторное нажатие на иконку на левой полосе редактора кода, выключает "Sync Edit" и возвращает обычный режим редактирования.

[ К содержанию ]

История изменений

По мере редактирования и сохранения кода в проекте, средой автоматически ведется история этих изменений. Для каждого модуля, включенного в проект, можно просмотреть историю изменений, сравнить разные версии файлов и, если необходимо, возвратиться к любому из промежуточных изменений кода проекта. Смотрите закладку History в редакторе кода и тему "History Manager" в документации.

Открыть скриншот в отдельном окне

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

[ К содержанию ]

Но, есть и неприятные моменты.

Русские буквы в комментариях к коду

Поначалу неприятно удивило открытие файлов кода с комментариями в заголовке, написанными русскими буквами в кодировке Win1251. Часть таких файлов открываются, как двоичные. После небольшого исследования оказалось, что портит все маленькая буква "я" в тексте комментариев в начале модуля. Если в новой среде написать такой комментарий в начале модуля, то он редактируется нормально. Но, если его закрыть, то вновь откроется он в двоичном виде. По-видимому, проблема связана с тем, что редактор кода по первой порции фиксированного объема определяет формат файла. Встречая в этой порции букву "я" (ее код $FF), редактор некорректно определяет формат файла. При переносе текста с буквой "я" в конец файла или в середину файла большого размера, его формат определяется корректно.

Сходная ситуация обсуждалась в Подводных камнях.

Проблема с открытием таких файлов решается или удалением слов из заголовка модуля, содержащих маленькую букву "я", или замена ее на букву "Я" в верхнем регистре. Кому что нравится.

Русские буквы в названиях каталогов проекта

Проекты VCL.NET и WinForms не запускаются из-под среды, если в полном имени каталога проекта есть русские буквы. Среда сообщает "Unable to create process".

К сожалению, ссылки в окне "Help Insight" не будут работать, если у вас в названии каталогов используются русские буквы.

[ К содержанию ]

Рефакторинг

Рефакторинг "переименование символа" — при позиционировании курсора на нужном идентификаторе и выборе пункта меню Refactoring | Rename Field, среда показывает все строки, где встречается выбранный идентификатор, и предлагает выбрать новое имя. Очень удобная возможность, как тут не вспомнить Мартина Фаулера:

"Важной частью пропагандируемого мною стиля программирования является разложение сложных процедур на небольшие методы. Если делать это неправильно, то придется изрядно помучиться, выясняя, что же делают эти маленькие методы. Избежать таких мучений помогает назначение методам хороших имен. Методам следует давать имена, раскрывающие их назначение. Хороший способ для этого - представить себе, каким должен быть комментарий к методу, и преобразовать этот комментарий в имя метода. Жизнь такова, что удачное имя может не сразу придти в голову. В подобной ситуации может возникнуть соблазн бросить это занятие - в конце концов, не в имени счастье. Это вас соблазняет бес, не слушайте его. Если вы видите, что у метода плохое имя, обязательно измените его. Помните, что ваш код в первую очередь предназначен человеку, а только потом - компьютеру. Человеку нужны хорошие имена. Вспомните, сколько времени вы потратили, пытаясь что-то сделать, и насколько проще было бы, окажись у пары методов более удачные имена. Создание хороших имен - это мастерство, требующее практики; совершенствование этого мастерства - ключ к превращению в действительно искусного программиста. То же справедливо и в отношении других элементов сигнатуры метода. Если переупорядочивание параметров проясняет суть - выполните его."

Раньше для подобных действий использовался метод переименования идентификатора в месте, где он объявлен, и инкрементная компиляция до выяснения всех мест, в которых этот идентификатор использовался.

Рефакторинг "Выделение метода" оказался вторым из удобных нововведений, в выделенном методе автоматически объявляются необходимые параметры и локальные переменные. К сожалению, пока остается мечтой автоматический поиск аналогичного кода выделенного метода в других местах и замена его вызововом выделенного метода.

Рефакторинг: процесс выделения метода

После выделения метода

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

[ К содержанию ]

Unit-тестирование

"Мой опыт показывает, что создав хорошие тесты, можно значительно увеличить скорость программирования"
(с) Мартин Фаулер.

Delphi 2005 располагает встроенными средствами для организации тестирования работы отдельных модулей программы, основанными на известных open-source проектах DUnit и NUnit (.NET). Среда позволяет создать проект-оболочку для тестов и шаблоны тестирующих модулей. Рассмотрим возможности Delphi 2005 на примере тестирования простого класса, осуществляющего перевод чисел из двоичной формы в символьную по заданному основанию системы счисления и, наоборот, из символьной в двоичную.

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

Реализация метода ToString будет содержать ошибки, которые мы будем обнаруживать тестированием. Первая реализация выглядит так:

unit Convertor;

interface

type
  TNumericConvertor = class
  private
    FBase: Integer;
  public
    constructor Create (const ABase: Integer);
    property Base: Integer read FBase;
    function ToString (const Value: Integer): string;
    function ToNumber (const Value: string): Integer;
  end;

implementation

{ TNumericConvertor }

constructor TNumericConvertor.Create(const ABase: Integer);
begin
  Assert ((ABase > 1) and (ABase <= 36), 'Illegal Base specfied');
  FBase := ABase;
end;

function TNumericConvertor.ToNumber(const Value: string): Integer;
var
  I, Digit: Integer;
begin
  Result := 0;
  for I:=1 to Length(Value) do begin
    if Value[I] > '9' then
      Digit := Ord(Value[I]) - Ord('A') + 10
    else
      Digit := Ord(Value[I]) - Ord('0');
    Assert ((Digit >= 0) and (Digit < Fbase), 'Illegal character');
    Result := Result * FBase + Digit;
  end;
end;

function TNumericConvertor.ToString(const Value: Integer): string;
var
  Rem, Quot: Integer;
begin
  Assert (Value >= 0, 'Only positive numbers can be converted');
  Result := '';
  Quot := Value;
  while Quot <> 0 do begin
    Rem := Quot mod FBase;
    if Rem >= 10 then
      Result := Result + Char(Rem + Ord('0'))
    else
      Result := Result + Char(Rem + Ord('A') - 10);
    Quot := Quot div Fbase;
  end;
  if Result = '' then
    Result := '0';
end;

end.

Создадим проект-оболочку для тестов командой File|New|Other выбрав в категории Unit Tests элемент Test Project (см. рис. 1 и 1-1).

Показать скриншоты в отдельном окне: рисунок 1 и рисунок 1-1

После этого группа проектов принимает вид:

Добавим в эту оболочку первый тестирующий модуль командой File|New|Other выбрав в категории Unit Tests элемент Test Case.

Показать скриншоты в отдельном окне:

В результате этих действий в IDE открывается окно с кодом сгенерированного класса для тестирования методов выбранного класса.

unit TestConvertor;
{

  Delphi DUnit Test Case
  ----------------------
  This unit contains a skeleton test case class generated by the
  Test Case Wizard.
  Modify the generated code to correctly setup and call the methods
  from the unit being tested.

}

interface

uses
  TestFramework, Convertor;
type
  // Test methods for class TNumericConvertor
  TestTNumericConvertor = class(TTestCase)
  strict private
    FNumericConvertor: TNumericConvertor;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestToString;
    procedure TestToNumber;
  end;

implementation

procedure TestTNumericConvertor.SetUp;
begin
  FNumericConvertor := TNumericConvertor.Create;
end;

procedure TestTNumericConvertor.TearDown;
begin
  FNumericConvertor.Free;
  FNumericConvertor := nil;
end;

procedure TestTNumericConvertor.TestToString;
var
  ReturnValue: string;
  Value: Integer;
begin
  // TODO: Setup method call parameters
  ReturnValue := FNumericConvertor.ToString(Value);
  // TODO: Validate method results
end;

procedure TestTNumericConvertor.TestToNumber;
var
  ReturnValue: Integer;
  Value: string;
begin
  // TODO: Setup method call parameters
  ReturnValue := FNumericConvertor.ToNumber(Value);
  // TODO: Validate method results
end;

initialization
  // Register any test cases with the test runner
  RegisterTest(TestTNumericConvertor.Suite);
end.

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

В методе Setup пишем код для вызова корректного конструктора

procedure TestTNumericConvertor.SetUp;
begin
  FNumericConvertor := TNumericConvertor.Create (10);
end;

Метод TestToString принимает вид:

procedure TestTNumericConvertor.TestToString;
var
  ReturnValue: string;
  Value: Integer;
begin
  Value := 10;
  ReturnValue := FNumericConvertor.ToString(Value);
  Assert (ReturnValue = '10', 'Expect ''10'',
               receive '''+ReturnValue+'''');
end;

И последний метод - TestToNumber

procedure TestTNumericConvertor.TestToNumber;
var
  ReturnValue: Integer;
  Value: string;
begin
  Value := '10';
  ReturnValue := FNumericConvertor.ToNumber(Value);
  Assert (Returnvalue = 10, 'Expect 10,
          receive '+IntToStr(ReturnValue));
end;

Компилируем и запускаем тестовый проект, его окно выглядит так.

После запуска тестов видно, что один из методов исходного класса работает некорректно, так как полученный результат не соответствует ожидаемому (Ожидается '10' получен 'AB')

Показать скриншот в отдельном окне

Анализируя исходный код метода, видно, что при переводе очередного знака числа, условия then и else необходимо поменять местами:

if Rem >= 10 then
      Result := Result + Char(Rem + Ord('A') - 10)
    else
      Result := Result + Char(Rem + Ord('0'));

Перекомпилировав проект после исправления, снова запускаем тесты.

Видно, что ошибка исправлена, но метод все работает не так, как ожидается (Ожидается '10', получено '01').

Показать скриншот в отдельном окне

Дальнейший анализ кода метода показывает, что при переводе числа в строку старшие цифры записываются после младших, исправляем эту ошибку, часть кода метода ToString теперь выглядит так:

if Rem >= 10 then
      Result := Char(Rem + Ord('A') - 10) + Result
    else
      Result := Char(Rem + Ord('0')) + Result;

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

Показать скриншот в отдельном окне

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

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

unit TestConvertor1;
{

 Delphi DUnit Test Case
 ----------------------
 This unit contains a skeleton test case
 class generated by the Test Case Wizard
 Modify the generated code to correctly
 setup and call the methods from the unit
 being tested.

}

interface

uses
  TestFramework, Convertor;
type
  // Test methods for class TNumericConvertor
  TestTNumericConvertor1 = class(TTestCase)
  strict private
    FNumericConvertor: TNumericConvertor;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestToString;
    procedure TestToNumber;
  end;

implementation
uses
  SysUtils;

procedure TestTNumericConvertor1.SetUp;
begin
  FNumericConvertor := TNumericConvertor.Create(2);
end;

procedure TestTNumericConvertor1.TearDown;
begin
  FNumericConvertor.Free;
  FNumericConvertor := nil;
end;

procedure TestTNumericConvertor1.TestToString;
var
  ReturnValue: string;
  Value: Integer;
begin
  Value := 11;
  ReturnValue := FNumericConvertor.ToString(Value);
  Assert(ReturnValue = '1011', 'Expect ''1011'',
         receive '''+ReturnValue+'''');
end;

procedure TestTNumericConvertor1.TestToNumber;
var
  ReturnValue: Integer;
  Value: string;
begin
  Value := '1011';
  ReturnValue := FNumericConvertor.ToNumber(Value);
  Assert(ReturnValue = 11, 'Expect 11,
         receive '+IntToStr(ReturnValue));
end;

initialization
  // Register any test cases with the test runner
  RegisterTest(TestTNumericConvertor1.Suite);
end.

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

Показать скриншот в отдельном окне

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

Спасибо фирме Borland, что такие нужны и удобные средства уже встроены в их новый продукт — Delphi 2005.

[ К содержанию ]

Компилятор

Предопределенный символ для идентификации компилятора - VER170 (выяснено опытным путем, в Help информация отсутствует).

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

for..in..do

В язык Delphi добавлена конструкция for..in..do для перебора всех членов массива, строки, множества или коллекции.

  • for Element in ArrayExpr do Stmt;
  • for Element in StringExpr do Stmt;
  • for Element in SetExpr do Stmt;
  • for Element in CollectionExpr do Stmt;

То есть, в цикле перебираются все элементы некоего множества и для каждого выполняется тело цикла. Например, теперь ничего не стоит перевернуть строку наоборот (см. рис)

Полная и весьма понятная информация находится в справке, смотрите раздел "Declarations and Statements"

Наиболее интересным применением циклов такого вида является их использование с коллекциями для перебора элементов. Для того, чтобы класс можно было использовать с циклами for..in, класс должен реализовать предопределенный паттерн коллекции. А именно, класс должен удовлетворять следующим требованиям:

  • содержать public метод экземпляра с именем GetEnumerator, который должен возвращать экземпляр класса, ссылку на интерфейс или запись (record).
  • экземпляр класса, ссылка на интерфейс или запись, возвращенные методом GetEnumerator, должны содержать public метод экземпляра с именем MoveNext, возвращающий значение типа boolean.
  • экземпляр класса, ссылка на интерфейс или запись, возвращенные методом GetEnumerator должны содержать public свойство экземпляра с именем Current, тип которого должен соответствовать типу элементов контейнера.

Экземпляр, возвращенный методом GetEnumerator, автоматически разрушается после окончания цикла for..in.

Следующий пример показывает реализацию паттерна коллекции

program Project1;

{$APPTYPE CONSOLE}

type
  TMyIntArray = array of Integer;

  TMyEnumerator = class
    Values: TMyIntArray;
    Index:  Integer;
  public
    constructor Create;
    function GetCurrent: Integer;
    function MoveNext:   Boolean;
    property Current:    Integer read GetCurrent;
  end;

  TMyContainer = class
  public
   function GetEnumerator: TMyEnumerator;
  end;

constructor TMyEnumerator.Create;
begin
  inherited Create;
  Values := TMyIntArray.Create(100, 200, 300);
  Index := -1;
end;

function TMyEnumerator.MoveNext: Boolean;
begin
  if Index < High(Values) then
    begin
      Inc(Index);
      Result := True;
    end
  else
    Result := False;
end;

function TMyEnumerator.GetCurrent: Integer;
begin
  Result := Values[Index];
end;

function TMyContainer.GetEnumerator: TMyEnumerator;
begin
  Result := TMyEnumerator.Create;
end;

var
  MyContainer: TMyContainer;
  I: Integer;

  Counter: Integer;
  ar: TMyIntArray;

begin
  MyContainer := TMyContainer.Create;

  Counter := 0;
  for I in MyContainer do
    Inc(Counter, I);
  WriteLn('Counter = ', Counter);
end.

Поддержка синтаксиса for...in уже встроена в ряд классов VCL, например, TList, TComponent, TCollection, и т.д. - в общей сложности около 15 классов. Так, например, перечисление имен компонентов формы может выглядеть следующим образом (хотя и непривычно):

var
  I: TComponent;
begin
  for I in Self do
    ListBox.Add (I.Name);
end;

[ К содержанию ]

Модификаторы области видимости

Для большей совместимости исходного кода с Delphi for .NET введены два новых модификатора области видимости членов класса.

strict private

Члены класса с видимостью strict private доступны только самому классу.

strict protected

Члены класса с видимостью strict protected доступны только самому классу и его непосредственным наследникам.

Отличие новых модификаторов от традиционных private и protected заключается в том, что члены с новыми модификаторами не доступны постороннему коду, находящемуся в том же модуле.

Class property

Раньше, хотя компилятор и позволял использовать методы класса в качестве аксессоров свойств, обращение к таким свойствам в форме TSomeClass.PropName было невозможно. Теперь, с введением свойств класса такое обращение разрешено. Однако, в отличие от Delphi for .NET, свойства класса могут работать только через методы, т.к. понятие полей класса для компилятора Delphi for Win32 отсутствует.

type
  TTestClass = class
    class function GetClassProp: integer;
    class procedure SetClassProp(value: integer);
    class property ClassProp: integer read
                   GetClassProp write SetClassProp;
  end;

TestClass.ClassProp := ...;

[ К содержанию ]

Вложенные типы данных и константы

Эта возможность также является новшеством только для компилятора Delphi for Win32. Теперь, как и в случае с Delphi for .NET, можно объявлять типы данных и константы внутри других классов.

type
  TOuterClass = class
   public
      const
         x = 12;
         i: integer = 1;
      type
         TInnerClass = class
         public
            myInnerField: Integer;
            procedure innerProc;
         end;

     procedure outerProc;
   end;

Обращение ко вложенным типам и константам производится через имя типа, в который они вложены, например, TOuterClass.TInnerClass или TOuterClass.x. Для вложенных типов и констант действуют те же модификаторы видимости, что и для остальных членов классов.

Существует одна интересная особенность. Хотя компилятор для Win32 не поддерживает полей класса, их в какой-то мере можно заменить вложенными типизированными константами при условии, что включена опция компилятора $J (она же $WRITEABLECONST).

[ К содержанию ]

Ненаследуемые классы

Если по каким-то причинам разработчик хочет запретить создание наследников класса, это можно сделать используя модификатор sealed.

type
  TMyFinalClass = class sealed(TObject)

  end;

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

Например, компиляция кода

type
  TClass1 = class
  private
  ....
  public
    constructor Create;
    destructor Destroy; override; final;
....
end;

TClass2 = class(TClass1)
....
 public
    destructor Destroy; override;
end;

приведет к ошибке - E2352 Cannot override a final method.

[ К содержанию ]

XML Documentation

Для компилятора Delphi for .NET эта возможность существует с версии Delphi 8. Теперь эта возможность доступна и в компиляторе для Win32. Компилятор умеет различать в исходном тексте специальным образом оформленные комментарии и генерировать на их основе XML файлы. Формат комментариев во многом похож на XML. Каждый комментарий, который будет анализироваться на наличие тегов XML документации предшествовует документируемому объекту и должен начинаться с комбинации из трёх символов "/". Существует набор тегов, которые рекомендуется применять при оформлении комментариев. Он описан в справке .NET SDK. К сожалению для тех, кто не любит писать всякие теги руками, IDE никак не облегчает оформление таких комментариев.

Примитивный пример оформления документации:

type
  ///<summary> Test comment
  ///</summary>
  TForm3 = class(TForm)
  private
    { Private declarations }
    ///<summary> Test comment 1
    ///</summary>
    procedure Test;
  public
    { Public declarations }
  end;

Примерный вид XML документации, генерируемой компилятором:

<?xml version="1.0" encoding="utf-8"?>
<namespace name="Unit3">
  <class name="TForm3">
    <devnotes>
      <summary> Test comment
      </summary>
    </devnotes>
    <ancestor name="TForm" namespace="Forms">
      <methodref name="ArrangeIcons" visibility="public" />
      <methodref name="Cascade" visibility="public" />

      здесь перечисляются предки и все их члены

    </ancestor>
    <members>
      <procedure name="Test" visibility="private">
        <devnotes>
          <summary> Test comment 1
          </summary>
        </devnotes>
      </procedure>
    </members>
  </class>
  <variable name="Form3" type="TForm3" />
</namespace>

[ К содержанию ]

Inline

В новой версии компилятора Delphi появилась возможность использования inline кода. Для этого наполнена новым смыслом директива inline. Теперь, если процедура или функция имеют директиву inline, это заставит компилятор попытаться вставить в место, где эта процедура используется, не вызов, а код тела процедуры. Само наличие директивы inline ещё не гарантирует того, что попытка будет удачной. Существуют определенные ограничения. Согласно справочной системе, эти ограничения таковы:

  • inline не работает для любых видов методов позднего связывания (virtual, dynamic, message)
  • inline не работает для процедур содержащих код на языке ассемблера,
  • inline не работает для конструкторов и деструкторов
  • inline не работает для главного блока программы и секций инициализации и финализации модулей
  • inline код может быть использован внутри пакетов, но inline не работает через границы пакетов
  • inline не работает в модулях, связанных кольцевой зависимостью. Это ограничение включает и неявные кольцевые ссылки между модулями. Например, если модуль A использует модуль B, модуль B использует C, а C, в свою очередь, использует A, то при компиляции модуля A не будет производиться inline-подстановка кода из модулей B и C.
  • inline-подстановка в модулях, входящих в кольцевые зависимости, может быть произведена, если подстановка производится из модуля, не входящего в кольцо зависимостей. Например, если в предыдущем примере модуль A использует также модуль D, то в модуле A возможна inline-подстановка кода из модуля D.
  • inline не работает, если процедура объявлена в секции interface модуля и обращается к символам, объявленным в секции implementation.
  • inline не работает для методов в классах, если они обращаются к членам классов, имеющим более низкую видимость, чем сам метод. Например, если public метод обращается к private методу, то для такого метода inline-подстановка осуществляться не будет.
  • если процедура, помеченная как inline использует процедуры или переменные из внешних модулей, то все эти модули должны быть перечислены в списке uses того модуля, где inline процедура будет использована, иначе inline-подстановка не производится.
  • inline-подстановка не осуществляется для процедур и функций, которые используются в выражениях проверки условия циклов while и repeat.

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

Также для контроля использования inline-подстановок введена директива компилятора {$INLINE}. Она может принимать следующие значения:

  • {$INLINE ON} - Процедуры, с директивой inline будут помечены, как процедуры, для которых возможна inline-подстановка. При вызове таких процедур будет сделана попытка inline подстановки кода. Действует по умолчанию.
  • {$INLINE AUTO} - Процедуры, с директивой inline будут помечены, как процедуры, для которых возможна inline-подстановка только в том случае, если код процедуры будет размером меньше 32 байт.
  • {$INLINE OFF} - Процедуры, не смотря на наличие директивы inline, никогда не будут помечены, как процедуры, для которых возможна inline-подстановка. При вызове процедур попытка inline подстановки кода не будет сделана.
Unsafe Code

Для компилятора Delphi for .NET добавлена возможность включения небезопасного кода в приложения .NET. Для этого введена локальная директива компилятора {$UNSAFECODE}, которая может принимать значения ON и OFF а также добавлено ключевое слово unsafe, которое применяется к процедурам и функциям. Приложения, использующие небезопасный код не проходит проверку при помощи утилиты PEVerify. Подробнее о небезопасном коде смотрите в документации .NET SDK.

procedure unsafeProc; unsafe;
begin
end;

[ К содержанию ]

Unicode-идентификаторы

Появилась возможность использовать в именах типов и переменных символы Unicode.

Запись вида

type
  Работник = record
    Фамилия: string;
    Имя: string;
    Отчество: string;
    ДатаРождения: TdateTime;
    Должность: string;
  end;

выглядит понятнее, чем

Rabotnik = record
   Familija: string;
   Imya: string;
   Ochestvo: string;
   DataRogdenija: TdateTime;
   Dolgjnost: string;
 end;

Разумеется, такой код будет многим непривычен и вызовет недовольные нарекания в духе "настоящий программист должен писать имена переменных/типов/методов на английском языке", но давайте помнить, что программа пишется в первую очередь для человека, компилятору абсолютно все равно, какие имена будут объявлены в программе.

Пример компилирующегося и работающего кода:

type
  Целое = Integer;

procedure TfMain.BtnCountClick(Sender: TObject);
var
  Счетчик: Целое;
begin
  for Счетчик:=0 to 5 do begin
    btnCount.Caption := IntToStr(Счетчик);
    Sleep(500);
    Application.ProcessMessages;
  end;
end;

[ К содержанию ]

Расширенный синтаксис объявления и инициализации массивов

Delphi для Win32

Теперь можно делать задание размеров массива и инициализацию одной строкой

type
  TMyIntArray = array of Integer;

var
  Ints: TMyIntArray;

begin
  Ints := TMyIntArray.Create(1,2,3,4,5);

Delphi for .NET

Новый расширенный синтаксис позволяет объявлять массивы в форме

array[, ..., ] of baseType;

Также возможна инициализация массивов при помощи стандартной процедуры new.

var
  a: array [,,] of integer;  // 3 dimensional array
  b: array [,] of integer;   // 2 dimensional array
  c: array [,] of TPoint;    // 2 dimensional array of TPoint

begin
  // New taking element type and size of each dimension.
  a := New(array[3,5,7] of integer);
  // New taking the element type and initializer list.
  b := New(array[,] of integer, ((1,2,3), (4,5,6)));
  // New taking an initializer list of TPoint.
  c := New(array[,] of TPoint, (((X:1;Y:2), (X:3;Y:4)),
                               ((X:5;Y:6), (X:7;Y:8))));
end.

[ К содержанию ]

Отладка

Понравилось поведение системы при возникновении Exception — появляется окно с уведомлением об Exception и с возможностью поставить галочку "Игнорировать этот тип Exception", вместо того, чтобы открывать окно Tools | Debugger..

Изменилась работа с точками останова. Появилась очень удобная возможность, не удаляя точку останова, отключить ее, пометив как "disable". Это можно сделать в редакторе кода по правой кнопке на точке останова, и прямо в списке "Breakpoint list". В этом списке можно включать/выключать все точки или определенные группы (меню по правой кнопке). Так же, теперь прямо в окне "Breakpoint list" можно изменять значение Condition и принадлежность к определенной группе для каждой точки.

[ К содержанию ]

Встроенный Data Explorer

В IDE интегрирован Data Explorer, который содержит как средства просмотра базы данных, так и ряд инструментов для редактирования. Окно Data Explorer можно найти на одной из закладок окна Project Manager справа от редактора кода (при умолчанных настройках среды) или в меню View | Data Explorer

Выбираете провайдера для вашей БД, настраиваете коннекцию к базе и получаете список ее объектов:

[ К содержанию ]

Таблицы

Для таблиц определены следующие операции:

Просмотр данных

Это операция по умолчанию — двойной клик по имени таблицы в списке. Открывается отдельное окно с содержимым таблицы. Возможно редактировать все поля, даже identity и computed column. Диагностика производится в момент сохранения изменений (правая кнопка мыши | Update/Rollback), так что испортить таблицу затруднительно.

Изменение структуры

Визуальный аналог команды "Alter table".

В этом окне по правой кнопке мыши доступны команды Save changes/Show DDL/ Exeсute DDL

DDL (Data definition language) — текст SQL-скрипта, который отражает сделанные визуально изменения в структуре таблицы.

Удаление таблицы

Выполнение команды "Drop table"

Копирование таблицы

Копирование существующей таблицы в новую. Происходит, как создание новой таблицы с такой же структурой (имя новой таблицы запрашивается при выполнении paste) и заполнении ее данным из копируемой таблицы.

[ К содержанию ]

Хранимые процедуры

Доступные операции Refresh/View Parameters. Окно просмотра параметров открывается при двойном клике на имени процедуры. В этом окне можно указать значения всех входных параметров и, выполнив процедуру, получить заполненные значениями выходные параметры (см. рис). Для выполнения процедуры можно воспользоваться иконкой в верхнем левом углу окна или по правой кнопке мыши (команда Execute).

Если хранимая процедура в качестве результата возвращает еще и (или только) набор данных, необходимо поставить галочку "Stored procedure has one or more cursors" и выполнить процедуру снова.

Просмотр скриншотов в отдельном окне:

Окно просмотра параметров

Окно с настройкой параметров процедуры и получением результатов

Результат работы хранимой процедуры, которая возвращает набор данных

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

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

[ К содержанию ]

SQL Window

Это привычное окно для выполнения SQL-запросов. Так как тестирование проходило только для MS SQL Server, то возможно, некоторые странности связаны с конкретным драйвером.

Сами SQL-запросы любой сложности (UNION, вложенные подзапросы и т.п.) выполняются без проблем. Странности начались после попытки исполнить в этом окне процедуру ("execute имя_процедуры"), которая в качестве результата возвращает набор данных. В качестве результата было получено сообщение "-1 row(s) affected". И этот результат был одинаков для всех процедур одного сервера. Тест на другом сервере дал иной результат, возможно этот эффект зависит от настроек на сервере (или от настроек конкретной базы), но такого иследования не проводилось. Итак, на другом сервере после выполнения процедуры было получено окошко с сообщением, например, таким: "192 row(s) affected", что само по себе верно, но никакого результата, то есть набора данных, все равно не было выведено. Если в тексте процедуры был оператор "Insert Into имя_таблицы exec имя_процедуры", то в качестве nколичества обработанных строк в результирующем сообщении выдавалось количество строк этого insert'а, а вовсе не nпоследнего select'а процедуры.

Можно предположить, что проблема кроется в ADO.NET, на котором реализован Data Explorer.

И, все же, несмотря на это, Data Explorer добавляет в среду разработки функционал, который реально может облегчить жизнь разработчику клиентских приложений для баз данных.

* * *

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

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

К материалу прилагаются файлы:
Пример для раздела "Unit-тестирование" (565.5 K)

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...