• Управление памятью в C++

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

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

      Читать дальше →
    • Зачем опаздывают проекты?

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

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

        Некоторые методологии просто предлагают принять это за данность и как-то приноровиться (например, планировать только ближайший этап), другие пытаются навести армейскую строгость, проводя Deadline и вводя «реакцию на отклонения».

        Я хочу поговорить о другом. Не о том, почему проекты опаздывают, и как этого избежать, а о том, зачем они опаздывают. Ведь если так подумать – ну неужели можно все сбросить на ошибки планирования? Ведь, вроде взрослые, опытные люди, ну не могут же они все время ошибаться? А раз не могут – значит делают это намеренно, не так ли?

        Приведу на ваш суд три возможных ситуации.

        Ситуация первая. Швейцарский нож или «а еще кружок по фото, а еще нам петь охота»

        Читать дальше →
      • Почему компьютерное зрение очень мало используется на практике

        На самом деле правильнее было бы назвать «машинное зрение», но так я думаю понятнее будет, если кто не знает то это не охранное видеонаблюдение, а распознавание или измерение чего либо c помощью камер. Существует много задач и областей, где компьютерное зрение было бы очень востребовано и могло бы использоваться повсеместно, но на практике оно используется очень редко.

        Я реализовал несколько проектов в этой области для решения разных задач, конкретно это вычисление и подсчет площадей, контроль качества продукции, причем разной и в разных отраслях таких как: фигурная порезка и раскрой листов ДСП, ДВП, МДФ, измерение площадей шкурок животных на производства изделий из кожи и др.

        Задача вычисления площади может показаться довольно сложной. Если подходить строго математически, то да, например, посчитать площадь квадрата или прямоугольника очень просто умножаем длину на ширину и готово, если треугольника чуть сложнее, а вот других криволинейных фигур может быть очень сложно.
        Мой алгоритм подсчета площади настолько прост, что его можно реализовать без всяких библиотек и т.п. буквально в десять строк кода, по сути это простейший детектор движения только с калибровкой камеры. Камера жестко фиксируется над местом, куда подается продукция, делается снимок фона (без продукции), например, белый стол, цвета пикселей загоняются в массив. Далее на стол подается или кладется образец, например какая-то коробка. Далее делается второй снимок с коробкой, цвета второго кадра пишутся в другой массив и затем сравниваются значения цветов, количество отличающихся пикселей суммируется. Затем этот образец измеряется рулеткой, вводится в программу его площадь и вычисляется площадь одного пикселя, т.е. площадь делится на число пикселей. Вот и вся калибровка. Далее достаточно подавать любую продукцию, любого размера и формы, определятся число изменившихся пикселей, и умножается на площадь одного пикселя, найденного при калибровке, надеюсь все понятно. Причем продукция может двигаться, например, на конвейере, площадь будет измеряться правильно, нужно только захват
        Читать дальше →
      • О дизайне. Часть 2. Практические примеры

          Как мы обсудили в прошлый раз, дизайн штука не простая; постоянно приходится держать в голове кучу всяких вариантов и стараться найти компромисс среди множества разных требований, раздирающих ваше элегантное решение на части. С одной стороны, хочется, чтобы решение было простым в сопровождении, хорошо расширяемым, с высокой производительностью, при этом оно должно быть понятным не только его автору, но еще как минимум одному человеку; хочется, чтобы решение ело мало памяти и не нарушало ни одного из 100 500 принципов ООП, ну и, самое главное, мы хотим его закончить хотя бы в этом году, хотя менеджер постоянно твердит, что оно должно было быть готово еще месяц назад.

          Многие из названных критериев являются не очень совместимыми друг с другом, поэтому рано или поздно мы приходим к выводу, что хороший дизайн – он как уж, который старается протиснуться между десятков противоречивых требований, и найти разумный компромисс, максимально удовлетворяющий наиболее весомым требованиям, не забывая, что вес этих требований может еще и меняться с течением времени.
          Читать дальше →
          • +21
          • 2,8k
          • 3
        • Джоэль Спольски: производственные запасы в разработке ПО

          • Перевод
          Представьте на минутку, что вы оказались на хлебозаводе. Сначала всё выглядит совершенно непонятно: куча оборудования неизвестного назначения, вокруг него суетятся люди. Затем вы немного осваиваетесь и замечаете более простые и привычные вещи. Вот контейнеры с кунжутом. Вот большие чаны с тестом. Вот маленькие шарики из этого теста. Вот уже выпеченные булочки.

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

          Хранение запасов стоит денег. Предположим, что на хлебозаводе есть шесть 50-тонных силосов для хранения муки. Это значит, что в среднем каждый день в них находится около 150 тонн муки. По сегодняшним ценам это 73000$ мёртвого капитала.

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

          Зачем тогда вообще хранить запасы? Затем что есть ещё и расходы связанные с их нехваткой. Если на заказ новой партии булочек с кунжутом уходит два дня, то, если они вдруг закончатся в вашей закусочной, ваш бизнес по продаже гамбургеров остановится на двое суток. Запасы — это буфер, который предотвращает непредвиденные остановки. Сейчас придумано множество алогоритмов для вычисления оптимального объёма этих буферов (для начала: бережливое производство, теория ограничений).

          Зачем я вам всё это рассказываю? Затем, что в производстве ПО тоже существуют места, где накапливаются «производственные запасы». И хранение этих запасов может стоить кучу времени и денег.
          Читать дальше →
        • Первые шаги с OpenCL или сказ о том как одинаковый код на GPU и CPU запускать

            Итак, прошел почти год с момента моего первого поста о программировании видеокарт и страшилок о том, как это все сложно. Теперь настала пора показать, что все не так плохо и как пользоваться этой странной штукой по имени OpenCL, да еще и использовать его главное преимущество, то есть возможность запускать один и тот же код на разных девайсах. А еще я покажу как можно получить на порядок большую производительность обычного процессора практически бесплатно.
            За деталями под кат...
          • Тесты и БД. Как откатить изменения, сделанные тестом?

            Формулировка задачи


            Если юнит-тесты работают с базой и меняют её — что сделать, чтобы результаты прогона были повторимы?
            Ответ — чистить базу перед тестом. Но хочется иметь какой то набор данных в базе, чтобы каждый раз его туда не записывать из тестов (будем называть такие данные “базовым набором”). Таким образом мы упростим сами тесты и их setup во много раз.
            Читать дальше →
          • Грязное программирование с чистой душой: разработка эвристических систем (часть 1)

              Химики любят говорить, что химия занимается исследованием грязных веществ чистыми методами, физика — чистых веществ грязными методами, а физическая химия, дескать, исследует грязные вещества грязными методами. В областях, традиционно относящихся к искусственному интеллекту или смежных с ними (распознавание образов, решение NP-трудных задач, обработка текста и т.д.), большинство задач являются грязными. Т.е. плохо поддающимися формальному описанию и не имеющими четких критериев правильности решения. Не знаю, как выкручиваются химики, а программистам редко удается порешать такие задачи, не запачкавшись. Программирование грязных задач тоже грязно, и здесь грязное — не значит плохое. Эта статья не о том, как сохранить чистоту и стерильность. Эта статья о том, как, вооружившись ломом мужеством и терпением, погрузиться в глубинные литосферные слои и выжить.

              Итак, предположим, что вам необходимо разработать систему, демонстрирующую сложное поведение (например, переводящую бабушек через дороги, или, в порядке экзотики, распознающую текст на изображении). Если вам кажется, что задача недостаточно грязная, попытайтесь написать работающую систему, улучшить качество ее работы, насколько это возможно, а затем улучшить еще сильнее. Желательно, если при этом не ухудшится быстродействие, идеально — если улучшится.
              Читать дальше →
            • Прототипная модель данных

                В прототипной модели данных объекты создаются на основе других объектов. В этом случае у объекта имеется прототип, его ещё можно назвать эталоном или наследуемым объектом. В такой модели данных отсутствуют типы и классы. Объекты можно различать по тому, кого прототипируют, но эта задача второстепенная. Прототипирование, в первую очередь, применяется для повторного использования существующих структур из объектов.


                Читать дальше →
              • Портрет Нуба

                • Перевод
                Чем старше я становлюсь, тем менее важной становится запятая. Пусть читатель сам решает, где ему ставить паузы. — Elizabeth Clarkson Zwart


                Примерно так я комментировал свой код двадцать лет назад (внимание, чуток драмы):

                /*
                 * Когда мы дойдем сюда, наша структура уже будет готова. 
                 * К тому же, мы создали достаточно большой буфер, в который 
                 * можно засунуть все входные данные, плюс есть немного места
                 * про запас. Я не уверен, понадобится ли оно, но хуже не будет. 
                 * Теперь нам надо обновить счетчик, предполагая, что клиент 
                 * уже прочитал значение, но еще не использовал его. Сначала 
                 * я хотел переложить обязанность инкремента на плечи вызывающего
                 * кода. С другой стороны, это означает, что инкремент нужно делать всем, 
                 * поэтому я решил, что будет лучше перенести его сюда. Но мы можем 
                 * пересмотреть это решение позже, если вдруг кому-то из внешних функций 
                 * захочется делать инкремент самому.
                */
                counter++; // инкрементировать счетчик для потребляемого значения
                
                /*
                 * Теперь нужно просмотреть весь буфер с данными. Для этой 
                 * операции нам понадобится еще один индекс, иначе перед 
                 * выходом из функции мы потеряем начальное значение. 
                 * Я хотел назвать эту переменную ‘ref’, потому что в некотором
                 * смысле мы будем обращаться с ней как со ссылкой на данные. 
                 * В конце концов я пришел к выводу, что самым лучшим  
                 * названием для нее будет ‘pos’. Если что, я не против обсудить
                 * это решение.
                */
                char* pos = buffer; // начинаем наш обход данных
                
                /*
                Теперь, мы...
                */


                Ну что, узнаете? А должны! Если быть предельно невежливым, весь код выше написал нуб. (Между прочим, если вы не знаете, кто такой нуб, значит вы — нуб).

                Читать далее
              • Assert DSL на примере .Net

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

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

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

                  В общем, все должно быть направлено на максимальную ясность и четкость тестов, чтобы явно было видно все взаимосвязи. Чтобы можно было восстановить логику программы по одним лишь тестам. В дело читабельности пойдет не только Assert DSL (Domain Specific Language), но и именование файлов, подход Arrange Act Assert. Все это не новые подходы как оказывается, но широкой известности пока не получившие, судя по тому, что я вижу в окружающих меня проектах. Да и сам я натолкнулся на новые темы случайно, изучая исходные коды StructureMap.

                  Чтобы не томить, сразу расскажу какие основные шаги предлагаются для улучшения тестов:
                  • Именовать тестовые файлы по основному методу, который тестируется.
                  • Использовать DSL  для создания объектов, чтобы методы делать максимально лаконичными.
                  • Стараться писать тесты в стиле «один тестовый метод – один assert».
                  • Структурировать внутренности теста.
                  • Создать и использовать Assert DSL.

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

                  Раскрытие темы с примерами и в картинках
                • Умные эксепшены

                  Недавно ковырял паттерны проектирования и попутно пытался переделать один проект на эксепшены. Из этого коктейля родилось несколько мыслей, которыми хочется поделиться с общественностью.
                  Читать дальше →
                • Приводя в порядок POSTs в ASP.NET MVC

                  • Перевод
                  В топике описывается один из профессиональных приёмов разработки ASP.NET MVC приложений, который позволяет значительно сократить количество повторяющегося кода в обработчиках POST действий форм. Несмотря, на то, что я узнал о нём ещё во времена первого издания ASP.NET MVC In Action и первой mvcConf, стиль изложения Jimmy Bogard мне показался очень простым и я решил опубликовать вольный перевод для тех, кто ещё не использует этот подход на практике.

                  Если вы это не используете, тогда мы идем к вам!
                • Паттерны поведения

                    (Эта заметка является завершением серии постов, в которую вошли «Технический долг», «Синдром рефакторинга» и «Эффект второй системы»)

                    В чем польза паттернов проектирования? (*) Это, прежде всего, повторное использование проверенных архитектурных решений, а также упрощение коммуникаций между разработчиками. Но ведь помимо паттернов проектирования существует и масса других паттернов: существуют паттерны кодирования, тестирования, модификации кода (a.k.a. рефакторинг), существуют архитектурные паттерны и многие другие. Поскольку мы, на самом деле, редко делаем что-либо по-настоящему новое, то проверенные типовые решения существуют для огромного количества областей. И поскольку большинство проблем, с которыми сталкиваются команды разработчиков, также не отличаются разнообразием, то и поведение этих людей также весьма однообразно.

                    «Технический долг», «синдром рефакторинга» и «эффект второй системы» — это типовые ситуации, с которыми периодически сталкивается команда разработчиков. И главная польза от них как раз и заключается в том, чтобы увидеть проблему и доказать ее существование нужным людям. Если вы сами поняли, что технический долг проекта слишком велик, то используя денежную метафору будет уже значительно проще доказать важность этой проблемы менеджеру или заказчику. А затем взвешенно показать ему альтернативные пути развития событий: (1) оставить все, как есть; (2) уменьшить технический долг путем разумного рефакторинга или (3) переписать все нафиг.
                    Читать дальше →
                    • +14
                    • 5,2k
                    • 8
                  • А не спеть ли мне песню…

                      Введение


                      Много слов уже было сказано о разработке и программном коде. Некоторым уже начали приедаться такие слова как: рефакторинг, гибкие методологии, тестирование. Большая часть сообщества смотрит на код через призму идеального мира. При этом основная масса разработчиков не может четко ответить на вопрос: «Когда стоит переписывать код?»
                      Читать дальше →
                    • О «достаточно хорошем» ПО

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

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

                        И, конечно же, я сразу же вспомнил концепцию о достаточно хорошем (good enough) ПО. Итак, вот её основной постулат: мы не стремимся сделать идеально, мы не пишем как попало, мы делаем достаточно хороший продукт.
                        Читать дальше →
                      • Extension methods: stop the madness!

                          Давным-давно, когда компьютеры были большими, программисты — бородатыми, а код — процедурным, на Земле царила идиллия. Программисты писали простой и понятный код, не задумываясь о соответствии его догмам. Да и не было тогда никаких догм. Каждый из этих одиноких ковбоев был творцом в своём собственном мире. Каждый выражал свою мысль элегантно и ёмко; каждая строка кода была произведением искусства, достойным безграничного восхищения. Иначе и быть не могло: вычислительные ресурсы были настолько скудны, что никому и в голову не приходило потратить их только на то, чтобы код выглядел красиво.

                          Однако время шло, и непобедимая машина технического прогресса неумолимо наращивала производительность железа. В один прекрасный день люди поняли, что они могут писать неоптимизированный код, и им за это ничего не будет! Вычислительные мощности выросли настолько, что компьютерам было уже всё равно, что выполнять: выверенный до последней машинной инструкции код, или код, написанный студентом-первокурсником за сосиску в тесте. Это был поистине переломный момент, после которого, как грибы после дождя, стали появляться новые концепции и методики программирования.
                          Читать дальше →
                        • Синдром рефакторинга

                            image
                            Бытует мнение, что программные системы, будучи объектом не совсем материальным, не поддаются старению. И если говорить о старении физическом, то действительно, шансы на то, что буковка “o” в имени класса вдруг от старости ссохнется и превратится в букву “c” – действительно малы. Но вместо старения физического, программные системы стареют морально.  Со временем накапливается груз ошибок за счет неточностей в исходных требованиях, непонимания требований самим заказчиком, архитектурных ошибок или неудачных компромиссных решений; да и ошибки поменьше, типа слабопонятного кода, его высокой связности, отсутствия юнит-тестов и комментариев делают свое черное дело. Все это приводит к накоплению технического долга (о котором шла речь в прошлый раз), из-за которого при добавлении новой возможности в систему приходиться платить «проценты» в виде более высокой стоимости реализации и более низкого качества получаемого результата.
                            Читать дальше →