| | |
| Хороший технический специалист практически никогда не бывает хорошим программистом. Живым подтверждением тому является бесчисленное множество ужасающих библиотек, сложных в реализации с технической точки зрения. В качестве примера таких библиотек можно рассмотреть математические библиотеки, библиотеки для кодирования и обработки изображений, кодирование потокового видео и аудио, криптографические библиотеки, и так далее. К сожалению, большинство технических специалистов (включая самых матерых экспертов) живут с иллюзией того, что для того, чтобы написать хорошую техническую библиотеку, достаточно быть хорошим техническим специалистом. К сожалению, этого недостаточно. | |
| Технический специалист сосредотачивает свои усилия на вопросах, непосредственно связанных с результатом работы библиотеки, а именно — на производительности и, если это имеет место, качестве выходных данных. При этом качество кода и вообще культура программирования нещадно приносятся в жертву результату, подобно тому, как крестоносцы вырезали половину Константинополя под предлогом «освобождения Гроба Господня». | |
| Новички в программировании ошибочно полагают, что они еще не доросли до некоторого SDK, если им не удалось понять, как этим SDK пользоваться. Новички, не расстраивайтесь — в действительности причина здесь ровно обратная — авторы SDK еще не доросли до того, чтобы писать SDK. | |
| Современные технические библиотеки — это грустно и печально. Обойдите все технические SDK, предоставляемые самыми крупными компаниями и организациями, от GNU до Microsoft, от NVIDIA до Intel, от Daz 3D до Autodesk — нигде, нигде вы не найдете ни одного SDK, ни одной библиотеки, ни одного модуля, хотя бы отдаленно напоминающего по качеству тот же Boost. Все что вы найдете — это брутальный говнокод, представляющий собой кровавый замес из процедурного C, недообъектного и недотипизированного C++, полнейшего непонимания паттернов проектирования, полного отсутствия вообще какой-либо культуры программирования и хотя бы элементарной заботы о собственном пользователе. | |
| | |
| Intel | |
| Компания Intel очень гордится своей библиотекой «Integrated Performance Primitives». Библиотека предоставляет функциональность по кодированию видео, обработке изображений, трехмерному рендерингу, и так далее. То есть популярные задачи, требующие хороших вычислительных мощностей. Казалось бы, кому как не Intel лучше всех справиться с этой задачей? | |
| Зайдя в папку «samples», мы увидим, что Intel любезно предоставила аж пять примеров работы с форматом JPEG/JPEG2000. Однако, наша радость становится полной, когда мы обнаружим, что размеры исходников примеров варьируются от 850-ти килобайт до 2-х мегабайт. Для сравнения — библиотека Boost.GIL, решающая гораздо более широкий круг задач, снабжена примерами размером в несколько сот байт, коротко и по сути объясняющими суть предоставляемой функциональности. | |
| | |
| Пример кричащего говнокода из библиотеки «Intel IPP», свидетельствующий о полнейшем дилетантстве технаря как программиста: | |
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| template<class T,int N> struct IMG {
private:
T *img_mem;
protected:
T *img;
public:
int wstep;
IPSize imgSize;
IPSize roiSize;
IppStatus lastStatus;
IMG(int width, int height) :
imgSize(width,height),
roiSize(width,height),
lastStatus(ippStsNoOperation)
{
wstep = imgSize.width * N * sizeof(T);
img = img_mem = (T*)ippiMalloc_8u_C1(wstep,imgSize.height,&wstep);
}
virtual void border(int wpixels,int hpixels)
{
img = (T*)((Ipp8u*)img+wstep*hpixels+wpixels*(N*sizeof(T)));
roiSize.resize(-wpixels,-hpixels);
}
void roiRect(int addl, int addt, int addr, int addb)
{
border(addl, addt);
roiSize.resize(addr, addb);
}
virtual void restoreRect()
{
img = img_mem;
roiSize = imgSize;
}
virtual ~IMG() { ippiFree(img_mem); }
inline T *ptr() const { return img; }
}; | |
| | |
| LEADTOOLS | |
| Компания LEADTOOLS со своего сайта заявляет, что она — «The World Leader in Imaging Development SDKs». Действительно, чем только они не занимаются — даже обслуживают такую серьезную отрасль как медицина. На деле же качество кода в SDK от LEADTOOLS точно также бросает в дрожь — точно такой же говнокод, такие же примеры использования в сотни килобайт, такое же отсутствие вообще какого-либо понимания о культуре программирования. | |
| Все примеры использования библиотеки LEADTOOLS представляют собой MFC-приложения, в которых 99,9% кода — это код MFC и 0,1% кода — это код самих LEADTOOLS (то есть именно тот код, ради которого пользователь и полез в пример). Без хороших познаний в области архитектуры построения MFC-проектов (кстати та еще трава), пользователь лишен всяких шансов научиться работать с изображением из примеров LEADTOOLS. | |
| | |
| Одни только заголовочные файлы LEADTOOLS не оставят равнодушным даже самого видавшего виды программиста: | |
| | |
| NVIDIA | |
| Библиотека PhysX от NVIDIA является еще одним живым подтверждением основного тезиса данной статьи. Конечно, непосредственно NVIDIA тут не при чем — PhysX был куплен компанией NVIDIA у компании AGEIA вместе с самой компанией AGEIA, и существует чуть более чем стопроцентная вероятность того, что PhysX был точно таким же говнокодом еще до его приобретения компанией NVIDIA. | |
| | |
| Работа над ошибками | |
| Если попытаться понять и разобраться, почему пример использования, скажем, кодера и декодера JPEG в исходниках занимает полтора мегабайта заглянув в эти самые исходники, то большая часть вещей встанет на свои места. | |
| Во-первых, каждых технарь в каждом примере пишет свой трехкилометровый класс для парсинга командной строки. Почему? Потому что он не знает про Boost.Program Options. | |
| Во-вторых, каждых технарь в каждом примере пишет свой парсер заголовков изображений в BMP-формате. Почему? Потому что он не знает про Boost.GIL. | |
| В третьих, каждых технарь в абсолютно каждом своем приложении изобретает еще очень много разных велосипедов с квадратными колесами, потому что он не знает про STL, контейнеры, итераторы, алгоритмы, функциональные объекты, а также библиотеки Boost, решающие огромный спектр задач. | |
| В четвертых, каждый технарь считает, что просто так взять и написать краткий и лаконичный консольный пример из 50-ти строк нельзя. Нужно обязательно создать MFC-приложение из нескольких десятков файлов и размазать по нему тонким слоем демонстрируемую функциональность, тем самым затруднив понимание сути предоставляемой функциональности на порядки. Видимо, технарям платят за строки кода. | |
| В пятых, технарь слишком сильно увлечен производительностью и качеством выходных данных, чтобы успевать думать о пользователях с их проблемами. | |
| В итоге 50 строк кода, которые могли бы наглядно продемонстрировать возможности библиотеки, превращаются в 50 000 строк абсолютно бессмысленной мешанины. Развитие среднестатистического технаря как программиста останавливается в тот момент, когда он научился писать программу, которая работает. | |
| Для того, чтобы написать хорошую библиотеку, недостаточно просто хорошо разбираться в предметной области. Хорошая библиотека — это не просто решение задачи. Хорошая библиотека — это удобное решение задачи. Практически ни один технарь не представляет себе, какая бездонная пропасть лежит между этими двумя понятиями. Интеграция удобной библиотеки в хороший проект — это редко минуты, чаще часы, редко дни. Интеграция неудобной библиотеки в хороший проект — это редко часы, чаще дни или недели. При этом на саму интеграцию тратятся все те же минуты или часы, а дни и недели уходят на изучение, сборку и адаптацию неудобной библиотеки под нужды проекта. | |
| Основная задача любого разработчика библиотеки (если не считать производительность и прочие очевидные вещи) — придумать удобный публичный интерфейс, то есть точку соприкосновения человека и библиотеки. Зачастую эта задача оказывается сложнее, нежели сама тематика предметной области задач, решаемых библиотекой. К сожалению, практически никто из технарей этого не понимает. | |
| | |
| Правило | |
| Хорошему технарю нужен хороший программист. | |