четверг, 28 июля 2011 г.

Деградация справочных систем

Давно прошли те времена, когда можно было нажать F1, например, на имени функции и сразу же попасть на страницу справки, посвящённой этой функции. Системы справок всё деградируют и деградируют. Но вершиной (или, скорее, дном) этого процесса по праву можно считать справчную систему Adobe Flash & Co. Найти в ней ничего нельзя не только ткнув F1, но и вообще, даже применяя средства поиска. Обилие различных языков и платформ, которые они наплодили, довершает совершенную картину полного идиотизма.

четверг, 9 сентября 2010 г.

Один метод в нескольких классах

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

С другой стороны, объект, по отношению к которому вызван метод, это ни что иное, как первый (или нулевой) параметр функции, который передан в неё по ссылке.

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

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

Некузявость этой модели проявляется в определении оператора сложения в C++. Действительно, с одной стороны, сложение --- это одна из операций, которая может характеризовать класс (например, вектора или матрицы), то есть, это метод. С другой стороны, сложение требует двух равноправных аргументов, а, следовательно, оно не может только к одному из них относиться особенно.

Посему в Си+ сделано два способа определения таких операторов -- и как функции-члена и как функции-друга.

В Джаве операторов нет, но всё равно те же самые проблемы возникают, например, с методом Equals.

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

Например, я сейчас пытаюсь понять, как в библиотеке HttpClient устанавливать прокси. Я нашёл класс HttpProxyHost extends HttpHost (в версии 4, я так понимаю, оставили только HttpHost). С точки зрения ООП это логично -- данные определённого вида инкапсулированы в свой объект.

И вот теперь мне надо найти, где же эта прокся устанавливается? Наверняка это один-единственный метод, в одном-единственном классе, который принимает эту HttpProxyHost. То есть, этот метод находится в особых отношениях с классом HttpProxyHost и должен был бы быть его членом... Но, он больше подошёл к другому классу и всё -- теперь не поймёшь, как устанавливать прокси...

среда, 10 марта 2010 г.

Исключение работает в 30 тысяч раз медленнее!

Вот такой результат

Test1
Start Value: 48570986229
End Value: 48570988285
QueryPerformanceCounter minimum resolution: 1/3579545 seconds.
Increment time: 0,00057437467611107 seconds.
Test2
Start Value: 48570989868
End Value: 48627848797
QueryPerformanceCounter minimum resolution: 1/3579545 seconds.
Increment time: 15,8844012297652 seconds.
First was 27655,12 faster

Press Enter to finish ...

Выдаёт вот такая программа:



static class Program
{

[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);

const int count = 5000;

static bool IsEven1(int value)
{
if ((value % 2) == 0)
{
return true;
}
else
{
return false;
}
}

static void IsEven2(int value)
{
if ((value % 2) == 0)
{
return;
}
else
{
throw new Odd();
}
}

static void Test1()
{
int c1 = 0;
int c2 = 0;

for (int i = 0; i < count; ++i)
{
if (IsEven1(i))
{
c1++;
}
else
{
c2++;
}
}
}

static void Test2()
{
int c1 = 0;
int c2 = 0;

for (int i = 0; i < count; ++i)
{
try
{
IsEven2(i);
c1++;
}
catch (Odd)
{
c2++;
}
}
}


static void Main()
{
long ctr1 = 0, ctr2 = 0, freq = 0;
double itime1 = 0, itime2 = 0;

QueryPerformanceFrequency(ref freq);

Console.WriteLine("Test1");
if (QueryPerformanceCounter(ref ctr1) != 0) // Begin timing.
{

Test1();


QueryPerformanceCounter(ref ctr2); // Finish timing.
Console.WriteLine("Start Value: " + ctr1);
Console.WriteLine("End Value: " + ctr2);

Console.WriteLine("QueryPerformanceCounter minimum resolution: 1/" + freq + " seconds.");
itime1 = (ctr2 - ctr1) * 1.0 / freq;
Console.WriteLine("Increment time: " + itime1 + " seconds.");
}
else
Console.WriteLine("High-resolution counter not supported.");

Console.WriteLine("Test2");
if (QueryPerformanceCounter(ref ctr1) != 0) // Begin timing.
{

Test2();

QueryPerformanceCounter(ref ctr2); // Finish timing.
Console.WriteLine("Start Value: " + ctr1);
Console.WriteLine("End Value: " + ctr2);

Console.WriteLine("QueryPerformanceCounter minimum resolution: 1/" + freq + " seconds.");
itime2 = (ctr2 - ctr1) * 1.0 / freq;
Console.WriteLine("Increment time: " + itime2 + " seconds.");
}
else
Console.WriteLine("High-resolution counter not supported.");


Console.WriteLine("First was " + (itime2/itime1).ToString("#.00") + " faster");


// Make the console window wait.

Console.WriteLine();
Console.Write("Press Enter to finish ... ");
Console.Read();

}
}

public class Odd : Exception
{
}