Архив рубрики: Programming

С чего начать изучение программирования, общее.

     Много народа хочет стать программистами. Хороших в итоге немного. Сам не то чтобы профессионал топ-класса, но с учетом набитых ошибок захотелось немного систематизировать набранный опыт. Куда податься новеньким, как учить. В общем, что бы делал я «с белого листа».

   — Где учить. 

Тут достаточно просто. Профильный университет, который соверемнный, «дышит» в ногу — идеал. Университет дает базу и дает навыки самостоятельного обучения. Это идеальный ВУЗ в вакууме. Теперь о непростом — такой универ практически нереально найти на территории эксСССР, насколько я понимаю. Это не MIT. В моем универе 80% преподавателей были ну очень старой закалки. Один из них как то зарубил мой курсовой, так как в качестве CPU был выбран PIC, который преподаватель не знал. Зато он знал КР580ВМ80А, который мне и надо было использовать. Другой пример — рассказывали, что наши ребята ездили в США для обмена опытом. Поехали крутыми перцами, приехали —  а там только BSD системы, которые наши тогда в глаза не видели. 

В итоге — в универе надо параллельно учитсья самому. Благо, для этого есть все возможности. Вообще, это хорошая практика — учиться самостоятельно параллельно, постоянно. Учите основной предмет — учите параллельно что то еще. Пусть не в полную силу, но учите. Я какое о время назад изучал вопросы цифровой фильтрации сигналов. Математика. Казалось бы, но в недавнем прошлом это пригодилось. Исправлял в проекте. Удачно ввернул пару умных сдлв про IIR и FIR в общении с работодателем = ко мне совершенно другое отношение.

Курсы / учить самостоятельно — второе / третье по предпочтению. Но! Курсы — выбираются внимательно. Обычно хорошие курсы — это достаточно дорого. Но тут, как говорится, или по 5 но большие, или по 3 на маленькие 🙂 Правильные курсы вам здорово сократят время на изучение. Дадут работу в группе, общение.

     —  Что учить

Вопрос на самом деле неоднозначный. Тут есть два варинта. С одной стороны, можно изучать что то, что не востребовано на рынке особо, но вам ОЧЕНЬ нравится. Например, программирование QNX, скалу или что то подобное. Из профитов — когда вы станете крутым профессионалом (это не один год) — вы найдете очень высокооплачиваему работу. Предложений мало — но спрос, хоть и небольшой, есть. Небольшая конкуренция — вы на коне. Но кто вас будет кормить все это время? Поэтому вариант два, он же правильный — учить надо мейнстрим. Находим что то, где работу найти легче — и изучаем. C#, VB.NET, Java — без разницы, выберете, что нравится. И учите. Ищите опенсорсные проекты и делайте с кем то, делайти сами. Лучше — в команду с кем то, то есть опенсорс. Это научит читать чужой код, писать понятный код для других людей. Опыт работы с разными системами контроля версий и прочее. Кстати, в качестве такой системя я использую Mercurial, который меня вполне устраивает.

Отдельной строкой — не учите то, что используется ТОЛЬКО у вас. Классический пример — 1С. Если вы планируете пожить в другой стране или поработать на забугор — забывайте о таком сразу. Потерянное время, которое — ваш самый ценный капитал.

     — Как учить

Для начала находим хорошую базовую книгу с азов. Читаем и делаем примеры. Хорошо, если в книге написано, как собрать ваше приложение без использования IDE. Это позволит вам понять, что происходит на самом деле при сборке. То есть командная строка и блокнот (Notepad++ / Sublime Text). Заодно найчитесь правильно настраивать переменные среды, очень часто без этого ваша программа просто не скомпилируется. После того, как станет ясно, что происходит, работаете из чистой IDE без решарперов или других улучшайзеров. Используете мейнстирм. Для .NET это Visual Studio (спокойно можно использовать Express). Для Java — Eclipse. Лучше Indigo, Juno имеет какие то странные для меня проблемы. Для С++ сложнее — тут или VS Professional, или Qt, или DevExpress ИМХО. В порядке предпочтения. Единственное — в VS 2010 был сломан autocomplete для C++, починили или нет — не знаю.

Не забываем, что кроме платформы и языка, надо понимать, как писать эффективно и правильно. Для этого есть книги по алгоритмам и шаблонам проектирования. В интернете полно обзоров по данным книгам, повторяться не буду. Читать обязательно.

Какие платформы будут перспективны в будущем — думаю, Java и .NET никуда не денутся. Мир вовсю скатывается в облака и мобильный платформы — то есть копая туда, вы буз работы точно не останетесь. Насчет HTML5 — будет точно, но наверняка будет допиливаться очень быстро. JavaScript — тоже. Этот язык для меня тяжелый. Не как сам язык (он на самом деле имеет простой синтаксис) — я не предсталяю, как на нем писать сложное корпоративное ПО. 

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

В конце можно напомнить, что быть специалистом мало. Надо уметь себя продать на рынке труда правильно и грамотно. Я в этом не спец, к сожалению. Можете посмотреть доклад Якова Фаина, там есть по теме — http://jeeconf.com/materials/java-developer/

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

Delphi vs Java

Привлекает меня разработка под платформу Android. Как известно, основной язык программирования под нее — Java. Можно, конечно, использовать NDK (C C++) но в моем случае в этом нет никакой необходимости. Заодно появилась возможность поизучать Java. Кстати, минута рекламы — если есть желание изучать, крайне рекомендую купить книгу Якова Фаина «Java Programming, 24-Hour Trainer». Книга написано максимально сжато, но как по мне объясняет многое. Из замеченных недостатков — достаточно сухое, академическое изложение, но для меня оно cамое то, так как до этого много писал на Delphi и C#, рюшечки не нужны. Если хотите с рюшечками — «Head first Java». Да, не забудьте заглянуть в errata книги Якова, есть несколько достаточно важных опечаток.

Минута рекламы закончилась. Изучаю Java, в общем. Все пишут, что Java — тормоз. Виртуальная машина, проверки, сборка мусора когда не надо, все дела. Куда, в общем, с такой мордой в наш ряд. Ну пока сам не проверишь — не поверишь, дело такое. Нашел в интернете интересный примерчик, набросал его на Java и Delphi XE2. Delphi — 32 бита, все оптимизации включены, все поверки отключены. 

Итак, код Java:

import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
 
public class Main {
    private static double func(double x){
        double y = x*x;
        return y;
    }
    public static void main(String[] args) throws IOException {
        double vp=50000, np=0, snp=np, step=0.0001, sum=0;
        DateFormat df = DateFormat.getDateTimeInstance();
        
        System.out.println("Integral calculations...");
        Date cnt1 = new Date();
        while (np+step < vp) {
            sum = sum + (func(np) + func(np+step)) / 2*step;
        	//sum = sum + (np*np + (np+step)*(np+step)) / 2*step;
            np = np + step;
        }
        Date cnt2 = new Date();
        System.out.println("Integral from " + snp + " to " + vp + " step "+ step +" is equal " + sum);
        System.out.println("Begin time: "+df.format(cnt1));
        System.out.println("End time: " + df.format(cnt2));
        System.out.println("Difference: "+(cnt2.getTime()-cnt1.getTime())/1000 + " seconds");
        
    }
}

Как видите, ничего военного. В цикле вызывается простейшая функция. Для проверки написан расчет «на месте» без вызова (сейчас закомментирован) Теперь то же самое на Delphi:

program Project2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

function itg (x : Double) : Double;
begin
  Result := x*x;
end;

var
  vp, np, snp, step,sum : Double;
  cnt1, cnt2, cnt3 : TDateTime;
begin
  vp := 50000;
  np := 0;
  snp := np;
  step := 0.0001;
  sum := 0;
  Writeln('Integral calculations...');
  cnt1 := Now();
  while (np + step < vp) do begin
    sum := sum + (itg(np) + itg(np + step)) / 2*step;
    //sum := sum + ((np*np + (np + step)*(np + step))) / 2 * step;
    np := np + step;
  end;
  cnt2 := Now();
  cnt3 := cnt2 - cnt1;
  Writeln('Integral from ' + FloatToStr(snp) + ' to ' + FloatToStr (vp) +
                    ' step ' + FloatToStr(step) + ' is equal ' + FloatToStr(sum)+ #13 +
                    'Begin time: ' + FormatDateTime('hh:mm:ss',cnt1) + #13 +
                    'End time: ' +  FormatDateTime('hh:mm:ss',cnt2)+ #13+
                    'Difference: ' + FormatDateTime('ss', cnt3) + ' seconds');



end.

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

Барабанная дробь — смотрим результаты.

Delphi:

 

WTF? Вариант с вызовом функции отрабатывает в 4 раза медленнее чем инлайн — 13 секунд! И это простейшая функция, подставлять подобное компиляторы научились уже 100 лет назад. Даже не хочется писать на C#, подставит — 100%. Про С++ молчу.

Ладно, посмотрим на результаты «тормозной» джавы:

У меня комментариев по поводу тормознутости в расчетах нет. Чистая математика — 1 секунда. Причем в обоих вариантах, Java умеет делать то, что не умеет Delphi. 

Я охотно поверю, что у Java могут быть другие затыки. Еще больше поверю, что 90% затыков — кривые руки программистов. Не раз видел в C# использование String вместо StringBuilder, к примеру.

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

В Java пока огорчает GUI — она изначально была создана для другого. Найти пока красоты не могу для гуев, но особо и не искал. Вот, намалевал на Java морду к калькулятору для изучения вопроса — честный копипаст с майкрософта 🙂

Иду по книге Якова. Заодно у него есть (были) курсы по Java, как теперь — не знаю. Язык интересный, нравится. Непонятно пока только, как писать без парамеров методов by ref. Делать все через приватные члены классов муторно. Пожелайте мне удачи 🙂

Irrlicht 3D

По работе пришлось осваивать 3D движки. Грубо говоря, например, есть такая текстура:

Заодно будем считать, что карта глубин (depth map) такая же. Задача – получить на выходе 3D изображение. Например, такое:

Google

Процесс гугления вывел на прекрасную библиотеку Irrlicht3D, в которой оказалось все, что мне было нужно. Работает стабильно, если ее правильно готовить Smile Один хороший человек написал под нее готовый враппер на Delphi, который оказалось совсем недолго допилить до состояния отсутствия утечек памяти в моем конкретном использовании. К сожалению, готовые скриншоты привести не могу, но там полноценная 3D поверхность с кучей мелких деталей. FPS – от 20 до 300. На примере в этой записи FPS>1000.

Уже писал про библиотеку ранее, просто очень нравится -)

Кто говорил, что Delphi прост — 2

Напишу ответ насчет того, что делает кусок кода из позапрошлого поста.
Изначально Irrlicht не имел враппера под Delphi. Человек, писавший враппер,
решил, что простого вызова DLL функций недостаточно, поэтому решил модифицировать
вызовы через исправление таблицы виртуальных функций (VMT) Именно это мы и видим в
данном коде — явно вирусоподобное действие =)

Сегодня нашел странный глюк с Delphi 2007. TOpenDialog открывается по Execute
у меня на машине (Win7) моментально, но после выбора файла (или отмены выбора)
программа зависает на 1-5 секунд в зависимости от фазы луны. Замечено только при
запуске билда, под отладчиком все работает идеально. Я в растерянности, но вроде бы это
персональная моя бага. На других ПК не заметил.  

Кто говорил, что Delphi прост?

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

 

procedure PatchVMTbyVMT{_backup}(const vmt, VMCount: DWORD; const bToThisCall: Boolean; const pCustom: Pointer = nil);
const
//  t2s: array[0..3] of Byte = ($58, $51, $50, $E9);
  t2s: array[0..12] of Byte = ({ $CC,} $81, $3C, $24, $00, $00, $00, $10, $72, $03, $58, $51, $50, $E9);
  s2t: array[0..12] of Byte = ({ $CC,} $81, $3C, $24, $00, $00, $00, $10, $73, $03, $58, $59, $50, $E9);
var
  pcode: PDWORD;
  addr:  DWORD;
  vi:    PPointer;
  vp:    DWORD;
  i:     DWORD;
  pwrap: PDWORD;
  wsize: DWORD;
begin
  // unlock vmt
  if VirtualProtect(Pointer(vmt), 4 * VMCount, PAGE_READWRITE, vp) then begin
    // choose wrap
    if bToThisCall then begin
      pwrap := @t2s[0];
      wsize := SizeOf(t2s);
    end else begin
      pwrap := @s2t[0];
      wsize := SizeOf(s2t);
    end;
    // patch
    for i := 0 to VMCount - 1 do begin
      vi := Pointer(vmt + i * 4);
      if not Assigned(vi^) then
        Continue;
      // replace vmt
      if Assigned(pCustom) then
        vi^ := pCustom
      else begin
        // check alredy patched
        if (PDWORD(vi^)^ <> pwrap^) then begin
          // alloc mem for code
          GetMem(pcode, wsize + 4);
          VirtualProtect(pcode, wsize + 4, PAGE_EXECUTE_READWRITE, vp);
          // write wrapper
          CopyMemory(pcode, pwrap, wsize);
          // near jump
          addr := DWORD(pcode) - PDWORD(vi)^ + wsize + 4;
          // insert irr imagebase
          PDWORD(DWORD(pcode) + 3)^ := IRR_IMAGEBASE;
          // write jump to original vmt
          PDWORD(DWORD(pcode) + wsize)^ := -addr;
          // replace vmt
          vi^ := pcode;
        end;
      end;
    end;
  end;
end;

 

Кто разобрался, что код делает – тому печенька =) Потом напишу, как это понял я. В любом случае не стоит говорить, что Delphi для дебилов. Delphi — уникальный язык в плане уровня вхождения и возможного уровня освоения. Лично мне очень жаль, что ему почти все.

Case-sensitive Delphi

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

Утром накидал небольшой класс, важное тут:

akFoo= class(TObject)

  public

    constructor create(akOwner: TForm);
    destructor  destroy(); override;

.......

На что компилятор невозбранно ругнулся — 

[DCC Warning] : H2365 Override method akFoo.destroy should match case of ancestor TObject.Destroy

Если честно, думал что Delphi все равно на регистры в принципе. Ан нет. Немного гугления и нашел, что это сделано для более простого перехода в будущем на .NET (прямо Back to the feature в 2011 -) )

Поменял destroy на Destroy — все, никаких предупрежденией )

В общем, кто еще юзает Delphi — бдите!