Услуги Сертификаты Новости Статьи База знаний Алгоритмы Портфолио Скачать Ссылки Поиск
Услуги arrow Новости
Code Usability: оптимальность заполнения кода на странице Версия для печати Отправить на e-mail
13.07.2009

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

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

Например: вы пишете код, выполняете рефакторинг, проверяете его не оптимальность. Ваш код вам нравится. Сегодня нравится.

Но, взглянув на него через несколько месяцев, вам он уже не понравился.

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

На мой взгляд, хороший код должен обладать следующими качествами:

  1. Должен быть читаем и однозначен для понимания, должен быть краток и лаконичен.
  2. Должен иметь оптимальное заполнение на одной экранной странице монитора со среднестатистическим разрешением (например, 1024х768). Не должен содержать излишние пустые строки и пробелы.
  3. Размер кода метода класса не должен по возможности превышать одного экрана вашего монитора. Это улучшит его восприятие.
  4. Если условный оператор содержит одну строку кода в исполняемой секции и строка небольшой длины (не превышает ширину экрана в 1,5 раза), можно записать условие и выполняемый код в одну строку. При условии, что код не станет от этого нечитаемым.
  5. Сложный код нужно выделять пустыми строками впереди и позади участка кода. Это улучшит его понимание.
  6. Однотипные операции можно объединять в блоки, которые в общем коде можно выделять пустыми строками впереди и позади блока кода.
  7. Условные операторы многих языков позволяют не выделять исполняемый по условию код оператором начала и конца блока кода. Но я считаю, что даже одну строку кода нужно выделять признаками начала и конца блока. Лучше записать код условия и выполняемый код в одну строку, чем записать в две строки, но не выделить исполняемый блок кода. Причина - если вы пишете код в среде разработки, среда автоматически проставляет табуляцию и код корректно отобразится после условного оператора. Но если ваш код будут просматривать в любом текстовом редакторе, знаки табуляции не везде корректно отобразятся и произойдет сдвиг секции кода, не выделенного операторами начала и конца кода. Попробуйте в Delphi использовать табуляцию в оболочке и потом откройте код в блокноте. Думаю, после этого вы согласитесь со мной.
  8. Как продолжение п.6 - если вы используйте табуляцию для отступа - используйте только её. Если пробелы (как в Delphi зачастую), то лучше не использовать табуляции. Это сохранит однородность оформления кода и его читаемость.
  9. Придерживайтесь одного стиля именования методов, полей, свойств классов. Это относится и к выбору языка именования: либо английский, либо уже транслитерация вашего языка.
  10. В коде не нужно писать комментарии к каждой строке. Я разделяю мнение М.Фаулера, который считает, что код, нуждающийся в комментариях - это код, который нуждается в рефакторинге. Код должен быть понятен с первого взгляда.
  11. Код не должен быть очень подробным и там, где возможно, нужно производить свертку кода.
  12. Повторяющийся код должен быть оформлен в виде методов (функций, процедур и т.д.). В этом одна из основ рефакторинга.
  13. Имена методов, свойств и полей должны быть информативны и однозначны в понимании их функционала.
  14. К методам, полям, свойствам должны быть комментарии. Это нужно для того, чтобы собранный в библиотеку класс мог иметь XML-описание.
  15. Код, как ни лениво вам их писать, должен иметь тесты, которые позволят вам же не запутаться в коде, пока вы не выполнили рефакторинг кода. Заодно, тесты помогают понять, как работает код. Когда вы поставляете библиотеку вашей команде, ваш коллега должен быстро понять, как должна работать ваша библиотека.

Желаю хорошего кодинга!

Последнее обновление ( 13.07.2009 )
 
.NET Application Updater: разработка модуля авто-обновления приложения Версия для печати Отправить на e-mail
10.07.2009

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

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

Для реализации нам понадобится:

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

web-служба автообновлений

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

Подробнее я хочу рассмотреть приложение на стороне клиента, которое сможет подключаться к web-службе и получать обновления. Примеры кода приводятся на C#.

Клиентское приложение службы автообновления версий

Задачи, которые требуется реализовать для обновления приложения:

  1. проверка уже существующей у клиента версии;
  2. если версия нуждается в обновлении, обновление версии;
  3. перезапуск уже работающего приложения.

Проверка существующей версии приложения

Сравнить версии приложения с информацией, которая предоставляется службой автообновления можно следующим образом.

Пример 

string ExistingFileName = "c:\\MyApp\\MyApp.exe"; // Версия 1.0.1.9
string appNewVersion = "1.0.1.10";
Assembly myAssembly = Assembly.LoadFrom(ExistingFileName);
AssemblyName assemName = myAssembly.GetName();
Version oldVersion = assemName.Version;
Res = ((new Version(appNewVersion)).CompareTo(oldVersion) > 0);

Предполагается, что значение appNewVersion будет получено из web-службы, а наш модуль, который требует обновления имеет имя "c:\MyApp\MyApp.exe".

Переменная Res содержит результат проверки: true - версия существующего файла нуждается в обновлении.

Обновление запущенного приложения

Чтобы обновить запущенное приложение, нужно:

  • переименовать файлы приложения;
  • записать под прежним именем файлы новой версии;
  • запустить новый поток, в котором нужно стартовать новую версию приложения, а старую версию приложения завершить;
  • при повторном запуске приложения проверить наличие прежних переименованных версий приложения и удалить старые файлы.

Удаление прежней версии

Пример

try
{
    foreach (FileInfo FI in (new DirectoryInfo("<Рабочий каталог>")).GetFiles("*.old")) { if (FI.Exists) { FI.Delete(); } }
}
catch (Exception ex)
{
  MessageBox.Show(String.Format("Ошибка удаления старой версии {0}", ex.Message));
}

Переименование прежней версии, запись новых файлов на её место

Пример

private bool UpdateUpdaterRobot()
{
    bool Res = true;
    try
    {               
        // Создается временная папка в папке приема обновлений
        string DirTmp = Path.Combine(config.FolderTemp, Guid.NewGuid().ToString());
        DirectoryInfo tmpDI = Directory.CreateDirectory(DirTmp);
        if (Directory.Exists(DirTmp))
        {
            // Обновление файлов
            foreach (FileInfo fi in tmpDI.GetFiles())
            {
                string srcFileName = Path.Combine(<Каталог, где хранится принятый файл новой версии>, fi.Name);
                if (File.Exists(srcFileName))
                {
                    string newName = srcFileName + ".old";
                    try
                    {
                        // Переименовать старый файл в файл с расширением "old"
                        File.Move(srcFileName, newName);
                    }
                    catch (Exception ex)
                    {
                        Res = false;
                        ErrorMessage = String.Format("Ошибка переноса обновляемого файла: {0}", ex.Message);
                    }
                }
                // В целевую папку перемещается из временной папки принятый файл
                File.Move(Path.Combine(DirTmp, fi.Name), srcFileName);
            }
            // Удаление файла обновления и временной папки
            if (Res)
            {
                try
                {
                    File.Delete(<Имя файла обновления>);
                    Directory.Delete(DirTmp);
                }
                catch (Exception ex)
                {
                    ErrorMessage = String.Format("Ошибка удаления временного файла или папки: {0}", ex.Message);
                }
            }
        }
    }
    catch (Exception ex)
    {
        ErrorMessage = String.Format("Ошибка обновления {0}", ex.Message);
    }
    return Res;
}

Перезапуск приложения

Пример 

string UpdateAppFile = <Файл приложения, который запускаем>
string WorkFolder = <Рабочкий каталог приложения>
if (File.Exists())
{
    ProcessStartInfo myProcess = new ProcessStartInfo(UpdateAppFile);               
    myProcess.WorkingDirectory = WorkFolder;
    myProcess.UseShellExecute = false; // Здесь не нужно запускать отдельный сеанс системной оболочки 
    try
    {
        // Старт процесса
        Process.Start(myProcess);
    }
    catch (Exception ex)
    {
        Messagebox.Show("Ошибка перезапуска приложения : " + ex.ToString(), "Результат операции", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

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

Последнее обновление ( 21.07.2009 )
 
Импорт данных из Excel в двумерный динамический массив Версия для печати Отправить на e-mail
24.06.2009

Импорт данных из Microsoft Excel в динамический массив

type
  TSArray = array of array of string;

{ Import data from Excel into dynamic array }
function TUtil.Xls_To_Array(var a: TSArray; AXLSFile: string): Boolean;
const
  xlCellTypeLastCell = $0000000B;
var
  XLApp, Sheet: OLEVariant;
  RangeMatrix: Variant;
  x, y, k, r, i: Integer;
begin
  Result := False;
  // Create Excel-OLE Object
  XLApp := CreateOleObject('Excel.Application');
  try
    // Hide Excel
    XLApp.Visible := False;

    // Open the Workbook
    XLApp.Workbooks.Open(AXLSFile);

    // Sheet := XLApp.Workbooks[1].WorkSheets[1];
    Sheet := XLApp.Workbooks[ExtractFileName(AXLSFile)].WorkSheets[1];

    // In order to know the dimension of the WorkSheet, i.e the number of rows
    // and the number of columns, we activate the last non-empty cell of it

    Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate;
    // Get the value of the last row
    x := XLApp.ActiveCell.Row;
    // Get the value of the last column
    y := XLApp.ActiveCell.Column;

    // Set Stringgrid's row &col dimensions.

    // Reserve array size for import operation
    SetLength(a, x + 2);
    for i := Low(a) to High(a) do
      SetLength(a[i], y + 2);

      
    // Assign the Variant associated with the WorkSheet to the Delphi Variant
    RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X, Y]].Value;

    //  Define the loop for filling in the TStringGrid
    k := 1;
    repeat
      for r := 1 to y do
        a[(k - 1), (r - 1)] := RangeMatrix[K, R];
      Inc(k, 1);
    until k > x;

    // Unassign the Delphi Variant Matrix
    RangeMatrix := Unassigned;

  finally
    // Quit Excel
    if not VarIsEmpty(XLApp) then
    begin
      // XLApp.DisplayAlerts := False;
      XLApp.Quit;
      XLAPP := Unassigned;
      Sheet := Unassigned;
      Result := True;
    end;
  end;
end;

(c) Пример взят частично из DelphiWorld (с доработкой)
Последнее обновление ( 24.06.2009 )
 
Модуль синхронизации списков Sharepoint Версия для печати Отправить на e-mail
10.06.2009

2008 г.

Описание проекта: Разработка модуля синхронизации содержимого двух списков Microsoft Sharepoint (MOSS to WSS 3.0).

Управление работой с помощью конфигурационных файлов.

Принцип: синхронизация списков с помощью подключения к web-службам MOSS и WSS.

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

Функции: Разработка кода.

Используемые технические средства: Microsoft Visual Studio 2008, Microsoft SQL Server 2005.

 

Последнее обновление ( 27.01.2012 )
 
Ошибки проектирования или впустую потраченное время Версия для печати Отправить на e-mail
03.06.2009

К ошибкам первого этапа можно отнести:

1.     Неверное понимание первоначальной задачи, стоящей перед командой разработчиков, либо неясное её видение заказчиком, либо обе причины.

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

3.     Техническое задание в идеале должен предоставить заказчик. Но чаще он платит деньги и специально обученные люди, чаще всего далекие от разработки его пишут. Что в итоге получается - можете представить.

4.     Техническое задание должен писать квалифицированный менеджер проектов, либо системный аналитик, владеющий знаниями о проектировании подобных систем.

5.     Техническое задание помогает четче понять, что хочет заказчик. Очень редко заказчик внятно излагает свои пожелания и ожидания от будущего проекта.

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

7.     Чем больше тестов вы пишете, проверяющих ваш код, тем лучше. Со временем, через год работы, например, очень трудно вспомнить, что делает каждая конкретная строка вашего (даже!) кода, я не говорю уже о коде, который написан тем сотрудником, который уже несколько месяцев как уволился. А тесты помогут понять, как работает код, и даже то, как он ДОЛЖЕН работать.

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

9.     Никогда не беритесь за работу над большим проектом в одиночку. Это вредно по нескольким причинам: вы его никогда не напишете, так как у вас просто может не хватить терпения и сил; вы можете просто не смочь продумать все детали проекта; время работы над проектом может превысить все мыслимые сроки и проект закроют как нерентабельный; у вас может наступить такой момент, когда вы возненавидите проект и, в итоге, уволитесь с этой работы только чтобы сбежать куда подальше. И еще момент: делить ответственность за неудачу в команде проще, чем быть виноватым в одиночку. Увы, это жестокая правда.

10.   Неверная внутренняя модель - тоже немаловажное понятие при проектировании будущей системы. Подумайте прежде чем реализовывать проект по предложенному техническому заданию и услышав все пожелания вашего менеджера проекта и вашего руководителя, как вы будете писать то, что вам поручили сделать. Чтобы не переделывать код даже дважды, лучше сначала потратьте время на то, чтобы понять как сделать код оптимально. Я понимаю, что вероятность того, что можно найти САМЫЙ оптимальный алгоритм стремится к нулю, но попытаться стоит. Стоит вашего времени, нервов и здоровья.

Удачи вам и хороших, красивых и "правильных" проектов!

Последнее обновление ( 27.01.2012 )
 
Еще...
<< В начало < Предыдущая 1 2 Следующая > В конец >>

Всего 106 - 169 из 169