Площадь экрана любого смартфона значительно меньше экрана ноутбука или настольного компьютера. А значит и информации помещается намного меньше. Рассмотрим пример приложения типа "лента новостей" ниже:
Здесь используется стандартный шрифт Helvetica. Видно, что в заголовок новости целиком умещается всего-лишь 2-3 слова, что явно слишком мало, чтобы понять о чем новость. Как можно улучшить ситуацию? Один из вариантов — это уменьшить размер шрифта. Но я в работе использую другой подход: размер шрифта остается тот же самый, но используется другая гарнитура, которая имеет зауженное начертание букв. На рисунке ниже показана та же самая программа, которая использует шрифт PT Sans Narrow Bold:
Таким образом, с сохранением размера шрифта, в заголовок новости уже умещается 3-4 слова.
Я предпочитаю использовать шрифты Paratype, потому что они включают кириллические буквы. На рисунке ниже показано что произойдет, если в программу загрузить шрифт, в котором авторы позаботились только о латинице:
Здесь только слово Windows узкое, все же остальные символы взяты из стандартного шрифта Helvetica.
Выигрыш в количестве информации на экране становится заметным тогда, когда загловок выводится в две строки:
Современные смартфоны Эпла имеют экраны с превосходным разрешением. Этим нужно пользоваться, чтобы повышать плотность подачи информации.
Стаковерфлоу — это сайт, на котором люди из кожи вон лезут, чтобы помочь другим людям найти ответы на вопросы по программированию. Коллеги не дадут соврать, что большую половину вопросов можно решить поиском по этому сайту. Идея создания такого сайта оказалась настолько успешной, что авторами была запущена платформа Stack Exchange c многочисленными сайтами по другим темам. Например, об английском языке и его использовании, для сисадминов, о фотографии, христианстве и многих других, в общем количестве 101 штук. Но Стаковерфлоу остается самым популярным: 5 млн вопросов, 10 млн ответов, 6 млн визитов в сутки.
Существует специальный сайт Area 51 (названный по аналогии с американской военной базой в штате Невада, где происходит испытание секретных технологий). На этом сайте обсуждаются и культивируются новые сайты, которые можно было бы запустить на платформе Stack Exchange. Среди прочих сайтов любителей пива и специалистов по пикапу, обсуждается заявка создания сайта Stack Overflow на русском языке.
Было уже много сказано "за" и "против" создания подобного сайта на русском языке. Мол, программисты должны все поголовно знать английский язык. Или что согласно старой русской традиции, на сайте вместо конкретных ответов будут убеждать топикстартера в том, какой он мудак.
Я же считаю, что заниматься изучением программирования всегда лучше на родном языке. Таким образом понижается порог вхождения в профессию. Известно, что профессия программиста позволяет достойно жить, дает надежду.
Так вот русскоязычный сайт с вопросами и ответами про программирование — это отличное место, где, например, школьники и студенты могли бы задавать вопросы и что самое главное — получать на них ответы от опытных коллег.
Но вернемся к заявке. Чтобы запустили подобный сайт нужно собрать минимум 200 желающих задавать вопросы или на них отвечать, при этом из этих 200 желающих должно найтись 100 пользователей, у которых есть рейтинг 200 или более очков на любом другом сайте на платформе Stack Exchange. Понятно, что речь идет про англоязычный Stack Overflow. На момент написания этих строк под заявкой подписалось 145 пользователей, из которых 41 имеют существенный рейтинг. Т. е. заявка подписана на 41 %. Нужно еще 59 пользователей с рейтингом 200+.
Казалось бы, какое благое дело: поддержать сайт, где твои же сограждане, коллеги, могли бы быстро решать текущие профессиональные вопросы на родном для них языке. Тем не менее, некоторые мои знакомые отказались (хоть и аргументированно) подписаться под этой заявкой.
Кроме этого есть еще другой вопрос: будет ли запущен сайт, если завяка все-таки наберет все необходимые показатели по пользователям? Давайте посмотрим на опыт других стран. На картинке ниже показаны заявки турков, китайцев, потругальцев и бразильцев, испанцев (эта заявка еще не набрала всех показателей, но уже скоро).
Если мы зайдем в эти заявки, то увидим следующее сообщение:
Вольный перевод: "Временно сайты не могут быть запущены, потому что теги не поддерживают буквы национального алфавита. О запуске сайта будет сообщено отдельно". Так вот, например, сайт на китайском мог бы быть запущен уже 16 декабря, когда собралось необоходимое количество пользователей. Прошло уже больше четырех месяцев, а сайт так запущен и не был. Как и не были запущены ни турецкий, ни португальские сайты.
Каждый уважающий себя PHP-программист должен знать как минимум два PHP-фреймворка. Это нужно для того, чтобы прийдя на существующий проект раскритиковать текущую реализацию и предложить все переделать на другом фреймворке. Но лучше знать три или даже четыре фреймоврка на тот случай, если на этом проекте уже успели поработать другие PHP-программисты.
Я вспоминаю те дни, когда мы с другом детства в середине девяностых писали компьютерную игру-бродилку для компьютера ZX Spectrum.
Среда разработки — это тетрадка и ручка. Левелы рисовали на бумаге, спрайты сначала рисовали в тетрадке в клеточку, а потом в виде битовых масок вводили в компьютер. На Спектруме не было никакой операционной системы, при включении компьютер сразу входил в режим интерпретации команд языка Бейсик, где можно было построчно вводить программу.
Первым разочарованием было то, что оперативной памяти на Спектруме достаточно мало: всегод 48 КБ. А если еще вычесть видеопамять (около 6 КБ), системные переменные (около 2 КБ) и знакогенератор (около 1 КБ), то остается и того меньше 40 КБ. Программа хранилась в памяти в виде определенного байт-кода, имеется в виду, что одна команда кодировалась одним или двумя байтами. Отчетливо помню, когда я сидел и вбивал уровни, после очередной строчки кода у меня слетел знакогенератор: объем программы достиг того уровня, что байт-код начал затирать знакогенератор. Тогда мы поняли, что что-то серьезное мы на Бейсике не напишем. Мы знали, что существует язык ассемблера микропроцессора Z80, но у нас совершенно не было представления, как это работает. Я напомню, что это середина 90-х, никакого интернета с Википедией еще не было. Т. е. интернета ни у кого не было, а вообще он конечно где-то был. А Википедии точно не было нигде.
И вот мы с другом узнали, что есть специальная книга Как написать игру на ассемблере для ZX Spectrum. Денег ни у кого тогда не было, и мой друг попросил у мамы денег на то, чтобы купить футболку, и мы тайно поехали и купили на эти деньги книжку по программированию. Времена были суровые, демократия уже вовсю шагала по Украине, поэтому признаться, что ты потратил деньги не на еду, ни на одежду, а на книжку — было делом опасным.
Повторюсь, что интернета не было, да и книг тоже было не очень много. Поэтому в таком состоянии информационного голода книги прочитывались неоднократно.
Одно из первых ощущений написания игры на ассемблере по сравнению с Бейсиком — это то, что все работало намного быстрее и естественно занимало меньше памяти. К сожалению, программирование на ассемблере требует больших знаний и усидчивости, не все моменты были до конца понятны, и из-за этого разработка шла медленно. А потом компьютер вообще сломался, и на этом моя карьера спектрум-программиста окончилась. Игра так и осталась незавершенной.
Тогда мы выжимали максимум из тех немногочисленных источников информации, что имели. А вот сейчас смотрю и компьютеры с интернетом у всех есть, и книг много, и форумов, где быстро ответят на нужные вопросы, тоже много, а молодежь все равно в каком-то ступоре. Интернет для инженера — это как экскаватор для землекопа. За эти десятки лет информатизация нашей страны вырасла на порядки. Уже все есть. Препятствия к успеху остались только внутренние.
Я бы попрограммировал сейчас на Спектруме, да не вернешь годы.
Самый главный гайдлайн при написании кода это отбивать реализации методов несколькими пустыми строчками и строкой-комментарием. Несмотря на возможности современных IDE по поиску и структуризации исходного кода, визуальное ориентирование все еще играет важную роль.
Рассмотрим пример ниже. Есть реализация класса на языке Objective-C. Методы отбиты всего-лишь одной строкой. Также отбивка одной строкой встречается не только между методами, но и между логическими блоками кода внутри методов. Длинна названия метода не может служить хорошим ориентиром начала нового метода. Например, название метод stopProgressAnimating короче любой строки предыдущего метода loadCommentsFailure. Глазу не за что зацепиться.
Тот же самый код, но методы отбиты пустыми строками и комментарием. Теперь место между концом одного метода и началом следующего образует однородный узор, который постоянно повторяется. Такой узор легко обнаружить даже при быстром скролировании.
Я еще не успел воспользоваться всеми преимуществами интегрированной среды разработки «Затмение» версии 3.7.1, артикул M20110909-1335, потому что вот уже как два часа подряд не могу поставить в нее Google AppEngine Toolkit. Тем не менее, уже при установке расширений я начал замечать интересные особенности пользовательского интерфейса.
На рисунке ниже показано окно прогресса установки расширения в IDE Eclipse 3.7. Мы видим линейку прогресса, видим описание текущей операции. Нам доступны следующие команды: выполнить установку в фоне, отменить установку, показать подробную информацию.
Классика жанра: любой процесс установки сразу прыгает до 50% в момент запуска, висит в этом состоянии бесконечно долго, а затем мгновенно прыгает до 100%. Таким образом, линейка прогресса в этом случае полностью теряет весь тот смысл, который в ней был заложен.
В надежде найти индикатор, указывающий на оставшееся время до завершения, пользователь может нажать кнопку «Подробнее». Но там его будет ждать разочарование.
Здесь мы видим тот же самый индикатор прогресса и описание выполняемой команды. Еще можно отметить фразу «Installing Software», которая в столь маленьком окне упоминается аж четыре раза. Кнопка «Подробнее» также не выполняет ту функцию, которая следует из ее названия. Никакой новой информации для пользователя здесь нет. Сложно себе представить программиста, настолько отрешенного от объекта своего труда, способного запрограммировать такую ахинею. Но как показано выше, в команде разработчиков Эклипса такой есть как минимум один.
На мой взгляд, причина подобной дегенерации заключается в следующем: в нашем мире все еще слишком мало качественного программного обеспечения. С глубокого детства мы пользуемся плохим программным обеспечением. И много ошибочных шаблонов уже зашиты у нас глубоко в сознании. В примере таким ошибочным шаблоном является наличие кнопки «Подробнее». Но если нечего больше показать, может эта кнопка и не нужна? Даже если показать больше нечего, программист все равно делает эту кнопку, не отдавая себе отчет, потому что он привык к этой кнопке с детства. Или задумайтесь, например, что значат символы << и >> на этой кнопке? Мы этого никогда не узнаем, потому что тот человек, который первый начал их применять, уже давно не с нами.
Можно привести еще несколько примеров. В любой даже самой простой программе должны быть настройки (Options, Settings). А должны ли они быть? В любой программе должно быть меню с обязательными разделами File, Edit, Window, Help. А нужно ли это меню? В каждой программе должен быть тулбар. А должен ли он быть? И так далее.
Вопрос: Почему вы используете русских программистов? Разве они не просто кучка хакеров?
Ответ: Из-за различий в русской системе образования, русские разработчики очень дисциплинированные и очень талантливые. Возможно вы заметили, что каждый раз, когда софтверная компания выпускает новый механизм «защиты контента» или «защиты авторских прав», например, как Adobe e-Book, то за короткий промежуток времени русские программисты взламывают защиту. В области сетевой безопасности и защиты контента эти парни ну очень хороши. Вместо того, чтобы разрабатывать здесь что-то, что будет взломано русскими через три дня, мы решили сразу работать с русскими программистами, чтобы убедиться, что наши программы надежны и защищены. Более того, оба основателя Ораган имеют русские корни.
В моей практике бывали такие случаи: попросишь программиста сделать какую-нибудь фичу, а он отвечает: «Сделать её невозможно». Я спрашиваю: «Почему?», а он в ответ: «Я прочитал такую-то документацию, посмотрел такой-то пример, попробовал вот этим способом и вон тем способом, и понял, что сделать её невозможно». А иногда говорят: «Ну ты бы ещё попросил слетать на Луну и вернуться» намекая на то, что я прошу невозможного.
Я заметил такую особенность с решением задач. Вот есть задача. Если её кто-то решил, то это является доказательством того, что эта задача разрешима за конечное время. Но обратное утверждение «никто не решил, значит задачу невозможно решить» неверно. Зачастую, поручив решение «невозможной» задачи более способному исполнителю, оказывалось, что он её успешно решал. Конструктивный же подход это разбить задачу на более простые и указать, где ты запнулся.
Для себя я сразу делал отметочку: ага, тот первый программист или неспособен, или не имеет желания. Когда вам кто-то говорит «это невозможно», интерпретировать фразу следует так: «я не пробовал это делать, да и не хочу».
Долго не мог понять в чем проблема, но только что разобрался и тороплюсь доложить вам. Заметил, что читая документацию в MSDN’е на душе становится как-то хорошо и спокойно, а когда читаю в doxygen’е, то как-то подташнивает.
Никто не будет спорить, что документация очень важна, особенно если нужно разбираться в новом большом проекте. И не в последнюю очередь важно качество документации, каким образом она составлена и подана читателю. Вещь непростая, измерить, кажется, трудно. Хотя можно было бы взять группу людей, дать им задачу найти перечень фактов в документации с разным дизайном, и измерить время считывания, поиска информации.
Так вот, если меня интересует какой-либо класс из библиотеки .NET, то в MSDN’е описание выглядит так:
Здесь четко видно: секция «конструкторы» — один метод, секция «методы» — пять. Плотность подачи информации равна шести единицам. Давайте посмотрим на документацию в дефолтовом стиле doxygen’а:
Секции всё также видны, но так легко считать отдельные методы уже не получается. Визуально толстые синие ссылки доминируют над декларациями методов, и отвлекают внимание. Более того, на одном экране мы видим описание только трёх методов. Значит условная плотность равна трём.
Обратите внимание, как doxygen заботливо тип «unsigned» сделал ссылкой. Если вы забудете, что такое unsigned, то вы всегда сможете пройти по ссылке и узнать.
Важная часть документации — это не только описание, но и примеры исходного кода. В MSDN’е мы видим исходники в таком оформлении:
Раз, два, три, четыре — и всё. Четыре цвета. Исходный код в doxygen’е выглядит так:
Здесь же мы видим такие классы подсветки: 1) директивы; 2) ссылки; 3) ключевые слова раз; 4) ключевые слова два; 5) комментарии; 6) встроенные типы; 7) идентификаторы, пунктуация. Итого семь разных цветов. Понятно, что подкраска — это дело вкуса, но если пользователь и так знает, что на любой идентификатор можно кликнуть и перейти в место определения, то зачем лишний раз выделять ссылки синим цветом?
Ну и на последок уменьшенная в пять раз collaboration diagram из doxygen’а. Реально кто-то будет ей пользоваться будучи в реальном размере (3600 на 1500 пикселей, смотреть оригинал)?
В комментариях приветствуются ссылки на мануалы и личный опыт ведения документации, настройки doxygen’а и прочее.
Часто при изучении новой библиотеки нужно посмотреть иерархию классов или список методов конкретного класса. Прыгать из файла в файл по ссылкам “Show Declaration” в Визуал Студии не всегда удобно. Есть утилита Doxygen, которая разбирает проекты, написанные на разных языках, и генерирует гипертекстовый сайт. На этом сайте можно просмотреть список всех классов, иерархию в UML-виде, список методов с описанием.
К сожалению, реализация библиотеки SystemC с официального сайта не имеет встроенной документации в формате Doxygen, поэтому описания методов и классов не доступны.
Очередной конкурс от Интела. На этот раз ничего не нужно программировать. Конкурс называется «Объясни на пальцах 2.0». Задача конкурса — дать простые определения для различных терминов параллельного программирования. Например, что такое SIMD и MIMD? Не пытайтесь бросаться в Гугл или Википедию за определениями. Лучше представьте такую ситуацию. Вы делаете лабораторную работу по оптимизации, подходит ваша бабушка, заглядывает в окно VTune Thread Profiler и спрашивает: «Внучок, а што это»? Объясните вашей бабушке, что такое thread pool и context switching, да так, чтобы она поняла и смогла пересказать другим бабкам на лавочке перед подъездом.
Конкурс проводится во второй раз. Вот как определил термин deadlock участник dnafigator:
«заходя в ванную, Анжелла забыла взять с собой халат. обычно, она может выйти в комнату и в неодетом виде, но пока она была в ванной, в гости зашёл Антон, которому Анжелла должна отдать флэшку, которая лежит у неё в сумочке. сам Антон в сумочку лезть отказывается, и требует, чтобы флэшку отдала ему Анжелла, и без флэшки он не уйдёт. Анжелла не может выйти в комнату пока там Антон. Антон ждёт, пока ему отдадут флешку, Анжела ждёт ухода Антона, после которого она может выйти и отдать»
А не задумывались ли вы, что узкое место при разработке чего-либо — это программист? Как бы вы быстро не печатали на клавиатуре, всё равно современные компиляторы компилируют намного быстрее. Мало кто знает, что оптимизация программ заключается не в том, чтобы программы быстро работали на процессоре, а в том, чтобы конечному пользователю было комфортно работать за компьютером. Предлагаю вам прототип параллельного компилятора, который компилирует исходный текст в тот самый момент, когда вы его пишите.
Изначально исходный файл пуст (см. рис. ниже), точно также объектная модель тоже пуста.
По мере того, как вы набираете текст программы, в параллельных потоках компилятор анализирует введенный текст, проверяет синтаксис, создает необходимые внутренние объекты (см. рис. ниже). Например, подключение заголовочных файлов — это вполне самостоятельный фрагмент программы, и компилятор сразу подключает необходимые пространства имен, идентификаторы и прочее. Это отражается в консоли сообщением «Библиотеки успешно включены», а соответствующие строки в редакторе имеют зелененький фон — «всё ок».
В процессе написания кода компилятор делает различные подсказки. В этом примере, в момент ввода последней строки компилятор встретил неизвестный идентификатор. Сразу же пишется сообщение в консоль с предложением задекларировать этот объект локально, глобально или как параметр. Также компилятор сообщает, что определение функции f1 ещё не завершено. Соответствующие строки кода подсвечиваются красненьким. На рисунке ниже показан результат автоматического определения объекта.
В момент написания последних строк программы (см. рис. ниже), компилятор определил, что текущий исходный файл не содержит ошибок и является завершенным. В консоли сообщается, что файл не содержит ошибок, а также информация о том, что функция f1 успешно определена.
Такой компилятор не нуждается в кнопке «Компилировать», потому что синтаксический анализ, построение внутренних объектов и генерация объектного кода происходит в фоновых параллельных потоках. Раз уж сейчас так популярны 2-, 4-ядерные процессоры, то почему бы не сделать такой подарок программистам.
Ответы на некоторые вопросы.
Вопрос: а не будет ли это тормозить, не будет ли трещать постоянно винчестер? Ответ: если грамотно спроектировать и реализовать, то не будет. Речь идет не о полной перекомпиляции всего файла при вводе очередного символа, а об инкрементальной компиляции, когда перекомпилируется (или докомпилируется) блок, строчка или даже выражение исходного файла. Эти фрагменты достаточно малы, чтобы быть обработанными за считанные миллисекунды.
Вопрос: а как же быть, если мне попался уже готовый проект? Ответ: при открытии проекта начать его компилировать в фоне, показывая прогресс в консоли.
Вопрос: где можно скачать такой компилятор или среду разработки? Ответ: мне такие компиляторы не известны. Это только идея, как было бы удобно со стороны пользователя. Частично такая функциональность реализована в IntelliSence в Microsoft Visual Studio, когда на лету анализируются объекты, подчеркиваются неизвестные идентификаторы.
Вопрос: а если нет программы, то где ты делал скриншоты? Ответ: скриншоты сделаны в Визио 2007.
Если ещё будут вопросы в комментариях, то обновлю пост и допишу ответы.
Дата: 27 мая 2009 (среда).
Время: 11:30—14:30 (три часа).
Место: 318 ауд. ХНУРЭ
Вход свободный.
От участников лекции ожидается хорошее знание языка С++, основ компьютерной графики, базовых терминов и принципов. Для участия необходимо заранее выслать ФИО, контактный телефон и номер группы на адрес volodymyr.obrizan@dnt-lab.com.
Этой статьей мы начинаем цикл публикаций «Параллельное программирование для самых маленьких». Ожидаемая аудитория проекта: школьники, а также студенты, начинающие изучать параллельное программирование.
Преимущество многопоточного приложения перед последовательным заключается в том, что несколько потоков делают тот же самый объем работы в несколько раз быстрее. Единицей работы в частном случае может служить одна итерация цикла. Студенты допускают типичную ошибку при параллельном программировании: создают несколько потоков, каждый из которых делает тот же объем работы, что и последовательная программа. Это не приводит к желаемому ускорению, а даже иногда замедляет работу приложения. Здесь работает очень простое правило: каждый поток в параллельном приложении должен делать в N раз меньше работы, чем последовательная программа, где N — количество запущенных потоков.
Рассмотрим простой способ статического разделения итераций одномерного цикла между несколькими потоками. На рисунке показан простой цикл, состоящий из 10 итераций. Пространство итераций описывается интервалом [0; 10). В последовательной программе начальное значение счетчика итераций равно нулю, инкремент цикла равен единице, т. е. тело цикла выполняется для каждой итерации.
Как было сказано выше, ошибочным является запуск двух и более потоков, которые бы выполняли тот же самый код, показанный на рисунке. В этом случае объем работы для одного потока останется таким же, а для целой программы вырастет в несколько раз. Необходимо разделить работу — итерации цикла — между потоками. На рисунке ниже схематически показано статическое поочередное распределение для двух потоков.
Нетрудно заметить, что поток номер 0 начинает свою работу с нулевой итерации и выполняет только четные итерации (инкремент равен 2): 0, 2, 4, 6, 8, а поток номер 1 начинает с итерации 1 и делает нечетные: 1, 3, 5, 7, 9. Таким образом, каждый поток делает в два раза меньше работы, чем последовательная программа. Теоретическое ускорение равно двум. Рассмотрим вариант разделения работы на три потока (см. рис. ниже).
Здесь поток номер 0 также начинает с нулевой итерации, но обрабатывает каждую третью итерацию: 0, 3, 6, 9. Поток номер 1 начинает с итерации 1, а поток номер два начинает с итерации 2. У всех потоков инкремент счетчика цикла равен трём. Теоретическое ускорение равно 3. В конкретном случае баланс загрузки нарушен и фактическое ускорение равно 10/4 = 2,5. Следует отметить, что с ростом количества итераций дисбаланс будет нивелироваться, и будет приближаться к теоретическому ускорению.
Можно проследить закономерность, что каждый поток начинает выполнять итерацию, номер которой совпадает с номером потока, а инкремент равен количеству потоков. Таким образом, можно записать общий случай для произвольного количества потоков (см. рис. ниже).
Достоинства статического поочередного распределения итераций заключаются в: а) простоте программной реализации; б) отсутствии накладных расходов на планирование итераций; в) хорошем балансе загрузки при большом количестве итераций и одинаковом времени выполнения тела цикла для разных итераций. Недостаток подхода заключается в отсутствии возможности балансировать нагрузку, если для различных итераций тело цикла выполняется различное время.
Этот недостаток был исправлен в библиотеке OpenMP. Для статического поочередного разделения итераций цикла может быть использована директива, показанная на рисунке ниже.
Для плохо сбалансированных объемов работы, когда тело цикла выполняется различное время для разных итераций, может быть использован динамический алгоритм балансирования нагрузкой.
К недостаткам OpenMP можно отнести ограничение на тип переменной итерации цикла. Библиотека OpenMP версии 2.5 поддерживает только signed int.