Ad-social Bot

Smmok Bot

Vkserfing Bot

Vkstorm Bot

Vktarget Bot

Все программы

Запись опубликована: 13.12.2018

Осенние митапы по мобильной разработке в офисе Туту.ру

Осенние митапы по мобильной разработке в офисе Туту.ру

В календаре начало декабря, а значит самое время подводить итоги осенних мобильных митапов, которые прошли у нас в офисе. А прошло их ровно два: CocoaHeads по iOS-разработке и Mosdroid по Android.

Устраивайтесь поудобнее, начнем с CocoaHeads

Максим Смирнов из нашей команды рассказал, что такое на самом деле рефакторинг, а что им не является, а самое главное, как подходить к этому вопросу правильно. Получился одновременно простой, но при этом полезный рассказ даже для опытных разработчиков. Бонусом идет demo рефакторинга.

Константин Шакуров из SimbirSoft рассказал о том, что такое нефункциональные требования, а также разобрал процессы, в которых мы соблюдаем нефункциональные требования.

На GoogleIO обсуждали новинки и улучшения gradle plugin. На данном этапе alpha уже доступна, но описания api еще нет. Я поэкспериментировал и хочу рассказать вам, насколько кардинальны изменения, почему они произошли и как это повлияет на сборку и написание плагинов.

API, структуры данных и модели БД — неотъемлемая часть любого мобильного клиент-серверного приложения. Как заниматься разработкой проекта в гармонии с коллегами с backend? Как поддерживать актуальную документацию по проекту? Как эффективно гонять данные между клиентом и сервером? Как защитить модели данных от «исследователей»?
Легко! Использовать Protobuf!

На круглом столе менеджеры команд совместно с HR-ами обсудили подробности набора, удержания, а также увольнения людей. Все, что вы хотели, но боялись спросить 🙂

На этом все, приходите в гости на митапы по мобильной разработке и не только 😉

Source: habr1

Метки:





Запись опубликована: 12.12.2018

[Перевод] Джон Ромеро: рефлексия по DOOM

Джон Ромеро: рефлексия по DOOM

image

1993 год выдался более щедрым на чудеса, чем все предыдущие. Это был единственный раз, когда мы поставили перед собой задачу создать игру, которая была бы настолько хорошей, насколько это было возможно в то время. Мы не ставили перед собой такие задачи ни до DOOMa, ни после. Это было идеальное время, чтобы совершить невозможное.

Мы наивно составили неправдоподобный список технологических чудес, которые мы планировали создать, и смело заявили в пресс-релизе в январе 1993 года, что DOOM станет основным источником падения рабочих показателей во всем мире. Мы действительно верили в это и усердно работали в том году, чтобы это стало реальностью. Я не рекомендую писать пресс-релиз на старте вашего проекта, особенно такого.

Мы сделали так много нового, создавая DOOM. Это была наша первая 3D-игра, в которой использовался движок, отошедший от 2D-парадигмы, которая использовалась с самого основания компании. Она использовалась даже в Wolfenstein 3D и Spear of Destiny, по крайней мере, для макетов карт. Мы хотели, чтобы в игре была видеокамера для сканирования оружия и монстров, потому что на этот раз мы использовали настоящие рабочие станции — мощные компьютеры NeXTSTEP и операционную систему Стива Джобса.

Создание DOOMа было трудным. Мы создавали мрачную тёмную игру вместе с нашим креативным директором Томом Холлом, который был всецело позитивным парнем, и это шло вразрез с его представлением об идеальном дизайне. Он заложил основы дизайна, создав «библию» DOOMа, в которой изложены некоторые концепции, которые мы так никогда и не реализовали — некоторые из них вошли в перезагрузку 2016 года.

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

В течение всего года мы дорабатывали, добавляли и удаляли элементы игры, чтобы сделать ее такой, как нужно. Исчезли счет и жизни — пережитки аркадных игр, на которых мы выросли. Предметы, которые добавляли очки, были удалены. Благодаря этому игра стала намного лучше, и эти решения повлияли на наши будущие разработки.

Применение двоичного разбиения пространства Брюса Нейлора помогло значительно ускорить процесс 3D-рендеринга, а абстрактное оформление уровней вывело игры из 90-градусного лабиринта из стен, который повсеместно использовался как дизайн для уровней на протяжении 20 лет. Это было чем-то новым, с текстурированными полами и потолками, лестницами, платформами, дверями и мигающими огнями. Нам нравилось работать с этой дизайнерской палитрой. Она хорошо сочеталась с основной темой игры: ад.

Мы играли в Dungeons & Dragons в течение многих лет. Планы нашей основной кампании были разрушены демонами, телепортирующимися на материальный план и уничтожающими все в нем. Это натолкнуло нас на мысль о демоническом вторжении. Однако мы решили, что действие будет происходить в будущем, когда у человечества предположительно имеется действительно мощное оружие. Кроме того, сочетание ада и научной фантастики было слишком удачным, чтобы его не использовать. Мы чувствовали, что даже сюжетная линия выглядела новаторской из-за этого.

Написание редактора карт DoomEd для создания уровней было мечтой. Наконец-то я использовал настоящую операционную систему с прекрасным языком программирования Objective-C и начал программировать так, как никогда прежде. У нас были мониторы с разрешением 1024×768, которые позволили нам увидеть нашу игру так, как мы не могли бы это сделать в DOS. Использование таких «инструментов будущего» нам очень помогло.

Мы сделали так много нового, что это немного ошеломляло. Мы использовали рабочие станции высокого класса, совершенно новый 3D-движок, обеспечивающий невероятную графику и выразительность дизайна, графическое сканирование наших игровых спрайтов. Мы впервые добавили многопользовательский режим в нашу игру с модом, который я назвал Deathmatch, просто потому что это имело смысл.

Включение сетевого режима, позволяющего нескольким пользователям играть вместе и Deathmatch изменили игры. Мы знали, что такой быстрый и выходящих за рамки привычного геймплей, как в DOOMе, возвестит о начале новой эры. Я представлял себе, как бы выглядело E1M7, если два игрока будут обстреливать друг в друга ракетами через большую комнату, и эта идея понравилась мне больше, чем что-либо со времен аудиодорожки для пулемёта в Wolfenstein 3D.

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

Наша небольшая команда сразу приняла эти огромные изменения и попыталась использовать их на пределе их возможностей. Технические натяжки, которые мы делали, были похожи дизайнерским натяжкам, которые мы пробовали. Я чувствовал, что мы часто оказывались в тупике и просто перелезали через него. Когда Том Холл ушел в августе 1993 года, мы быстро наняли Сэнди Петерсен, чтобы помочь нам на последнем этапе. Дейв Тейлор также присоединился, чтобы помочь нам доделать игру.

Мы были сплоченной командой из шести разработчиков. Адриан и Кевин уверенно придерживались художественной части, в то время как Джон Кармак работал над основой кода. Мне нравилось обрабатывать всё то, что выходило в итоге у каждого из них. Я добавлял много собственного кода к игровому окружению для дополнения моего дизайна уровней и дизайна уровней, который сделала Сэнди. Под конец работы над игрой мы все знали, что создали что-то очень качественное. Мы не могли дождаться, когда все остальные увидят это.

Это были удивительные 25 лет, и я должен прежде всего поблагодарить фанатов, которые сделали это возможным и поддерживали нас всё это время, а также игровую прессу, которая всегда поддерживала DOOM в течение всех его стадий. Ваша оценка нашей работы означает для нас всё. Я также должен поблагодарить Джона, Адриана, Тома, Сэнди, Дейва и Кевина. Это была наша безумная мечта, которая претворила DOOM в жизнь. Наконец, я хочу поблагодарить нынешнюю команду DOOM за отличную работу над последней игрой (я вообще не имею дело с ней, кроме как в качестве игрока). Как и все остальные, я очень рад, что игра DOOM Eternal стала успешной.

Вот уже четверть века мы Rip and Tear!

Еще

Перевод выполнен при поддержке компании EDISON Software, которая занимается реинжинирингом и поддержкой, а так же портированием и миграцией.

Source: habr1

Метки:





Запись опубликована: 12.12.2018

[Перевод] Первоисточник: «закон Конвея»

Первоисточник: «закон Конвея»

image

Примечание автора спустя 42 года после публикации:

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

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

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

Предлагаю вам ознакомиться с материалом, а потом оглянуться и поискать его в других сферах.

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

Как комитеты создают новое?

Мелвин Конвей (Melvin E. Conway)
Оригинал PDF.

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

Проектная организация может быть или не быть задействована в воплощении в жизнь спроектированной системы. Зачастую в государственных начинаниях существуют нормы, препятствующие группе действовать в соответствии с собственными рекомендациями, в то время как в частном секторе преобладает обратная ситуация. Будет резонно предположить, что это условие будет влиять на процесс проектировки системы, наравне с другими мыслями разработчика о собственном будущем. Как мы увидим далее, существующие в традиционной управленческой среде побудительные мотивы могут противоречить целям заказчика. [1]

Этапы проектирования

Первоначальный этап проектирования относится скорее к структурированию самого процесса, чем к разработке системы [2]. Полноценной разработке предшествуют определенные предварительные действия, а именно:

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

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

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

Процессу проектирования системы присущи следующие стадии:

  1. Определение границ в соответствии с базовыми правилами.
  2. Выработка предварительной концепции системы.
  3. Организация проектировочной работы и делегирование заданий в соответствии с концепцией.
  4. Координация на уровне делегированных заданий.
  5. Объединение подсистем в систему.

В отдельно взятой работе по проектированию могут не прослеживаться все стадии. Может так случится, что в процессе работы будет найдена новая, более совершенная концепция проекта. Это, конечно, не совсем благоприятный момент, так как последующее прекращение работы будет болезненным и дорогостоящим. Безусловно, с точки зрения историка все повторяется.

В таком случае, почему вечно не хватает времени сделать все правильно, однако всегда хватает времени что-то переделывать?

Проектирование системы

Любая последовательная система состоит из взаимосвязанных подсистем. Описание внутреннего устройства системы должно отображать ее связи с внешней средой и взаимосвязь ее подсистем. Спускаясь на уровень ниже, можно то же самое сказать о подсистеме, рассматривая ее как систему. И так далее, вплоть до такой подсистемы, которая будет предельно проста и неделима.

Примеры

Государственная трансконтинентальная транспортная система состоит из автобусов, поездов, самолетов, такси, парковок, терминалов и т.д. Это очень разнородная система, что значит, ее подсистемы довольно разнообразны. Спускаясь на уровень ниже, на уровень самолета, например, мы увидим его подсистемы: каркас, двигатель, распределение мощности, связь, полезная нагрузка. К системе двигателя относятся такие подсистемы как топливо, зажигание и пр.

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

Схемы

На Рис. 1 система изображена в виде схемы — похожей на погремушку — со связями (branches) в виде линий и основными узлами (nodes) в виде окружностей. Каждый узел символизирует подсистему, которая сообщается с другими подсистемами, которые могут быть изображены аналогичным образом. Термин интерфейс (interface), который набирает популярность среди разработчиков, относится к взаимодействию подсистем, обозначенному линиями.

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

  1. «систему» на «комитет»
  2. «подсистему» на «подкомитет»
  3. «интерфейс» на «координатор»

Также как в случае с системами мы видим, что проектные организации могут быть рассмотрены с учетом нескольких уровней сложности. Федеральное правительство являет собой прекрасный пример проектной организации с таким уровнем сложности, который может удовлетворить любого инженера. Это особенно интересный пример, показывающий схожесть двух рассматриваемых нами концепций, потому что Федеральное правительство является одновременно и проектной организацией (разрабатывает законы, договоры, политику) и проектируемой организацией (с Конституцией в качестве первичной проектной документации).

Основное взаимодействие

Сейчас мы готовы для основного вопроса данной статьи. Существует ли предсказуемая взаимосвязь между структурой проектной организации и проектируемой ею системой? Правильный ответ: да, и эта связь настолько проста, что зачастую постоянна. Рассмотрите следующее «доказательство».
Давайте произвольно выберем систему и разработавшую ее организацию и выберем случайным образом уровень сложности спроектированной системы, изобразим его схематично (наш выбор произволен, потому что в случае наблюдения интересных взаимосвязей, мы сможем распространить их на любую проектную организацию и уровень сложности). На Рис. 2 изображена (для наглядности) структура, для которой нижеуказанное утверждение верно.
image
Для любого узла х в системе мы можем идентифицировать рабочую группу проектной организации, которая его разработала (обозначим ее Х). Таким образом,
обобщая этот процесс, для любого узла системы у нас есть правило по поиску соответствующей рабочей группы. Обратите внимание, что здесь не обязательно сохраняется пропорция 1:1, т.е. две подсистемы могут быть спроектированы одной и той же проектной организацией.
Занимательно, что мы можем сделать похожее утверждение относительно связей (branches). Возьмите два любых узла одной системы, х и у. Они могут быть связаны, а могут и не быть (т.е. либо они взаимодействуют друг с другом каким-либо важным для функционирования системы образом, либо нет). Если между ними есть связь, тогда две рабочих группы Х и У, которые разработали два данных узла, должны были договориться об особенностях интерфейса для реализации возможности связи между узлами. Если же между х и у нет связи, то подсистемы не сообщаются между собой, а значит и рабочие группы не взаимодействовали друг с другом (т.к. между Х и У нет связи). [3] Что мы только что показали? Говоря простыми словами, мы продемонстрировали, что есть тесная связь между структурой системы и структурой организации, которая занимается ее проектировкой. Когда у каждой подсистемы есть своя отдельная рабочая группа, мы можем наблюдать что структуры (схемы) рабочей группы и подсистемы идентичны. В случае, когда несколько рабочих групп разрабатывают одну подсистему, структура проектной организации выглядит как структура системы, но с меньшим количеством подсистем (узлов на схеме).
Подобная сохраняющая структуру взаимосвязь между двумя объектами называется гомоморфизм. Говоря математическим языком, наблюдается гомоморфизм между схемой системы и схемой проектирующей ее организации.

Система является отражением проектирующей ее организации

Многие опытные разработчики систем верят, что любой проект системы когда-нибудь кто-нибудь сможет сделать лучше. Другими словами, ошибочно и не корректно говорить о проектировочном задании кроме как в контексте места, времени, уровня знаний и технологий. Об этом должны помнить те, кто читает историю о работе по проектированию какого-либо объекта или вспоминает и анализирует свою работу.
Ход разработки компьютерных переводчиков таких языков программирования, как FORTRAN и COBOL отличный тому пример. В середине 50-х годов, когда появились прототипы этих языков, их компиляторы были еще более громоздкими, чем сами компьютеры, гигантские в те времена, которые должны были выполнять команды. Сегодня эти переводчики лишь исторические диковины, которые не имеют ничего схожего с современными компиляторами. (Стоит отметить, что огромный рывок в разработке компиляторов ассоциировался с появлением новых групп людей в области, ранее считавшейся вотчиной производителей компьютеров, — это была сначала небольшая сплоченная университетская группа исследователей, вслед за которой потянулись независимые разработчики программного обеспечения).
Если мы допускаем, что для любого системного требования есть ряд системных проектов, которые будут отвечать данному требованию, мы также должны задастся вопросом, влияет ли выбор организации-проектировщика на процесс выбора системного проекта из этого ряда. Если мы верим в наш гомоморфизм, то мы согласимся с тем, что влияет. Учитывая, что в организации не гибкая коммуникационная структура, эта организация будет штамповать копию себя в любом проектном продукте. Чем больше организация, тем менее она гибкая и тем сильнее проявляется это свойство.

Примеры

В одной исследовательской организации было восемь человек, которые должны были сделать компиляторы COBOL и ALGOL. После первичной оценки сложности и возможных сроков, пять из них были определены на работу с COBOL, а трое были назначены работать с ALGOL. В результате компилятор COBOL работал в пяти проходах, а компилятор ALGOL — в трех.

Две военные службы под руководством своих главнокомандующих разработали систему вооружений для своих нужд. После, не без усилий, они сделали копию своей организационной структуры (см. Рис. 3а)

image

Обратите внимание на операционную систему компьютера, задействованную в решении этой задачи. Детально ее изучив, видим, что она состоит из трех частей: оборудование, программное обеспечение и приложения (см. Рис. 3b). Этим подсистемам соответствуют их разработчики: инженеры производителя компьютеров, его системные программисты и разработчики пользовательских приложений (тот редкий случай, когда специалисты оборудования и программного обеспечения сотрудничают, а не просто с трудом терпят друг друга).

Управление системой

Структура больших систем имеет тенденцию распадаться по мере развития. Это наблюдение особенно очевидно при рассмотрении крупных военных информационных систем последних десяти лет. Они являются самыми сложными объектами из всех ранее созданных человеком. Деятельность под названием «управление системой» возникла, в том числе по причине тенденции систем разделяться на составные элементы. Давайте рассмотрим практичность управления системами в разрезе основной идеи данной статьи.

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

  1. Во-первых, разработчики, осознав размер проектируемой системы, не могут противостоять соблазну нанять как можно больше людей для ее создания.
  2. Во-вторых, при применении привычной управленческой модели для реализации столь масштабного проекта распадается на отдельные части ее коммуникационная структура.
  3. В-третьих, дезинтеграционные процессы, происходящие в структуре организации-проектировщике, происходят и в структуре системы, в соответствии с явлением гомоморфизма.

Для начала рассмотрим ситуацию с «перенаселением». Вполне понятно естественное стремление разработчика делегировать задания, когда уровень сложности системы приближается к границам его понимания. Это поворотный момент в процессе разработки. Либо он борется за упрощение системы и побеждает, либо он теряет контроль над ней. Итог почти предсказуем, учитывая давление временных рамок и бюджета.

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

Или другой пример, демонстрирующий схожий случай конфликта управляющего и целостности проектируемой системы. Управляющий должен отдать на реализацию критичную и сложную часть работы. Выбрать он может одного из двух исполнителей: новая маленькая компания, которая отличается творческим подходом и низкой оплатой, либо зарекомендовавшая себя уважаемая контора, у которой более «реалистичные» расценки. Он знает, что если светлая молодая компания не справится с заданием, он будет виновен в срыве проекта. Если же известная организация не справится, то это будет лишь свидетельствовать о том, что задача и вправду трудная.

В чем же здесь загвоздка? В основном, в способе оценки и распределении ресурсов, который традиционно используется. Так, единицей ресурса выступает доллар, поэтому все ресурсы выражаются в долларовом выражении. Если ресурсом является человеческий труд, единицей измерения будет стоимость одного часа работы помноженная на количество работников.

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

Закон Паркинсона [4] имеет большое значение при перераспределении трудовых ресурсов в проектной деятельности. До тех пор, пока репутация управляющего зависит от размера бюджета, он будет заинтересован в расширении своей организации. Это не подходящая мотивация при решении задач по разработке систем. Раз организация существует, то, конечно, она будет использоваться. Возможно, наиболее веская причина существования сегодня такого количества плохо проработанных систем кроется в наличии организаций-проектировщиков, ищущих работу.

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

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

Заключение

Основной тезис данной статьи — организации, занимающиеся разработкой и проектированием систем (здесь трактуется в широком смысле) обречены создавать проекты, которые копируют их коммуникационную структуру. Мы увидели, что данное свойство оказывает серьезное влияние на управление процессом проектирования. Мы определили важный критерий организационной структуры проектных организаций: ресурсы, направленных на решение задачи, следует увеличивать только в соответствии с коммуникационными возможностями структуры организации. Этот критерий создает трудности, так как потребности в коммуникации зависят от концепции системы в определенное время. В связи с тем, что оценка задачи на начальном этапе никогда не бывает оптимальной, концепция системы может потребовать изменений, что, в свою очередь, напоминает о таком важном для компании-проектировщика качестве, как гибкость.

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

Примечания

[1] С намного более понятной дискуссией о поведении проектных компаний можно ознакомиться в материале Джона К. Галбрайта «Новое индустриальное государство» (John Kenneth Galbraith’s The New Industrial State). Особенно обратите внимание на Главу VI, «Техноструктура».

[2] Для более детального обсуждения превращения проектной деятельности в проект в функциональной среде смотрите у C. Мидлтона «Как основать проектную организацию» (С.J. Middleton, «How to Set Up a Project Organization,» 1967, стр. 73).

[3] Это утверждение можно рассматривать с разных сторон. Оно может быть тривиальным, тесно связанным с определением важных переговоров. Или оно может быть результатом наблюдения того, что одна группа разработчиков никогда не согласится с изменением собственной разработки в угоду другой группе, без приказа на то.

[4] С.Н. Паркинсон «Закон Паркинсона» (C. Northcote Parkinson, Parkinson’s Law and Other Studies in Administration, 1957)

Перевод: Сергей Даньшин

Ещё

О проекте «Энгельбарт»

Гуглдок с хабрапереводом «Augmenting Human Intellect:
A Conceptual Framework» тут
, можно дополнять.

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

Ближайшие действия — переводы и сбор в одном месте ключевых концептуальных документов и поиск единомышленников (проснись, Нео! То что ты ищешь, тоже ищет тебя.) Под прицелом — Ванневар Буш, Джозеф Ликлайдер, Пол Отлет, Алан Кей, Дуглас Энгельбарт, Глушков, Лебедев, Ершов, WikiPedia, Web Archive, Knol, Quora, Cybersyn, Xanadu, DARPA, IARPA.

подробнее — 50 лет спустя. The Mother of All Demos

Если вы действительно хотите понять NLS, вы должны забыть сегодняшнюю реальность. Забудьте всё, что знаете о компьютерах. Представьте, что вы ещё не знаете, что такое компьютер. Вернитесь в 1962 год. А затем прочитайте, что он задумал.
— Брет Виктор, Несколько слов о Дугласе Энгельбарте

Source: habr1

Метки:





Запись опубликована: 12.12.2018

[Из песочницы] Загрузчик с шифрованием для STM32

В данной статье хотел бы написать о своем опыте создания загрузчика для STM32 с шифрованием прошивки. Я являюсь индивидуальным разработчиком, поэтому нижеприведенный код может не соответствовать каким-либо корпоративным стандартам

В процессе работы ставились следующие задачи:

  • Обеспечить обновление прошивки пользователем устройства с SD-карты.
  • Обеспечить контроль целостности прошивки и исключить запись некорректной прошивки в память контроллера.
  • Обеспечить шифрование прошивки для исключения клонирования устройства.

Код писался в Keil uVision с использованием библиотек stdperiph, fatFS и tinyAES. Подопытным микроконтроллером был STM32F103VET6, но код может быть легко адаптирован под другой контроллер STM. Контроль целостности обеспечивается алгоритмом CRC32, контрольная сумма расположена в последних 4 байтах файла с прошивкой.

В статье не описано создание проекта, подключение библиотек, инициализация периферии и прочие тривиальные этапы.

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

Шифрование прошивки производится алгоритмом AES128 и реализовано при помощи библиотеки tinyAES. Она представляет из себя всего два файла, один с расширением .c, другой с расширением .h, поэтому проблем с её подключением возникнуть не должно.

После создания проекта следует определиться с размерами загрузчика и основной программы. Для удобства размеры следует выбирать кратно размеру страницы памяти микроконтроллера. В данном примере загрузчик будет занимать 64 Кб, а основная программа займет оставшиеся 448 Кб. Загрузчик будет размещаться в начале Flash-памяти, а основная программа сразу после загрузчика. Это следует указать в настройках проекта в Keil. Загрузчик у нас начинается с адреса 0x80000000 (именно с него STM32 начинает выполнение кода после запуска) и имеет размер 0x10000, указываем это в настройках.

Основная программа будет начинаться с 0x08010000 и заканчиваться на 0x08080000 для удобства сделаем define со всеми адресами:

#define MAIN_PROGRAM_START_ADDRESS 0x08010000
#define MAIN_PROGRAM_END_ADDRESS 0x08080000

Так же внесем в программу ключи шифрования и инициализационный вектор AES. Данные ключи лучше сгенерировать случайным образом.

static const uint8_t AES_FW_KEY[] = {0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF};
static const uint8_t AES_IV[] = {0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA};

В данном примере вся процедура обновления прошивки построена в виде конечного автомата. Это позволяет в процессе обновления отображать что-то на экране, сбрасывать Watchdog и выполнять любые другие действия. Для удобства сделаем define с основными состояниями автомата, чтобы не путаться в числах:

#define FW_START 5
#define FW_READ 1000
#define FW_WRITE 2000
#define FW_FINISH 10000
#define FW_ERROR 100000

После инициализации периферии нужно проверить необходимость обновления прошивки. В первом состоянии производится попытка чтения SD-карты и проверка наличия файла на ней.

uint32_t t; /* Временная переменная */
uint32_t fw_step; /* Индекс состояния конечного автомата */
uint32_t fw_buf[512]; /* Буфер для считанного блока прошивки */
uint32_t aes_buf[512]; /* Буфер для расшифрованного блока прошивки равен */
/* Буферы равны размеру страницы Flash-памяти*/
uint32_t idx; /* Текущий адрес в памяти */
char tbuf[64]; /* Временный буфер для sprintf */
FATFS FS; /* Структура библиотеки fatFS - файловая система */
FIL F; /* Структура библиотеки fatFS - файл */
case FW_READ: /* Чтение прошивки */
{
 if(f_mount(&FS, "" , 0) == FR_OK) /* Пробуем смонтировать SD-карту*/
 { /* Проверяем, есть ли файл с прошивкой. */
  if(f_open(&F, "FIRMWARE.BIN", FA_READ | FA_OPEN_EXISTING) == FR_OK)
  {
   f_lseek(&F, 0); /* Переходим в начало файла */
   CRC_ResetDR(); /* Сбрасываем аппаратный счетчик CRC */
   lcd_putstr("Обновление прошивки", 1, 0); /* Выводим сообщение на экран */
   /* Устанавливаем адрес чтения на начало основной программы */
   idx = MAIN_PROGRAM_START_ADDRESS;
   fw_step = FW_READ + 10; /* Переходим к следующему состоянию */
  } else {fw_step = FW_FINISH;} /* Если файла нет - завершаем загрузчик */
 } else {fw_step = FW_FINISH;} /* Если нет SD-карты - завершаем загрузчик */
 break;
}

Теперь нам нужно провести проверку прошивки на корректность. Здесь сначала идет код проверки контрольной суммы, выполняющийся при окончании чтения файла, а потом само чтение. Возможно, так писать не следует, напишите в комментариях что вы об этом думаете. Чтение производится по 2 Кб для удобства работы с Flash-памятью, т.к. у STM32F103VET6 размер страницы памяти 2 Кб.

case FW_READ + 10: /* Проверка корректности файла с прошивкой */
{
 /* В процессе показываем на экране, сколько байт считано */
 sprintf(tbuf, "Проверка: %d", idx - MAIN_PROGRAM_START_ADDRESS);
 lcd_putstr(tbuf, 2, 1);
 if (idx > MAIN_PROGRAM_END_ADDRESS) /* Если прочитаи весь файл прошивки */
 {
  f_read(&F, &t, sizeof(t), &idx); /* Считываем 4 байта контрольной суммы */
  /* Записываем считанные 4 байта в регистр данных периферийного блока CRC */
  CRC->DR = t;
  if(CRC->DR == 0) /* Если результат 0, то файл не поврежден */
  {
   /* Устанавливаем адрес записи на адрес начала основной программы */
   idx = MAIN_PROGRAM_START_ADDRESS;
   f_lseek(&F, 0); /* Переходим в начало файла */
   fw_step = FW_READ + 20; /* Переходим к следующему состоянию */
   break;
  } else
  {
   lcd_putstr("Файл поврежден", 3, 2); /* Выводим сообщение на экран */
   fw_step = FW_ERROR; /* Переходим к шагу обработки ошибки обновления */
   break;
  }
 }
 f_read(&F, &fw_buf, sizeof(fw_buf), &t); /* Считываем 2 Кб из файла в буфер */
 if(t != sizeof(fw_buf)) /* Если не получилось считать */
 {
  lcd_putstr("Ошибка чтения", 3, 2);
  fw_step = FW_ERROR; /* Переходим к шагу обработки ошибки обновления */
  break;
 }
 /* Расшифровываем считанный блок прошивки */
 AES_CBC_decrypt_buffer((uint8_t*)&aes_buf, (uint8_t *)&fw_buf, sizeof(fw_buf), AES_FW_KEY, AES_IV);
 for(t=0;t<NELEMS(aes_buf);t++) /* Записываем блок в регистр CRC */
 {
  CRC->DR = aes_buf[t]; /* Запись ведем по 4 байта */
 }
 idx+=sizeof(fw_buf); /* Сдвигаем адрес на следующие 2 Кб */
 break;
}

Теперь, если прошивка не повреждена, то нужно её снова прочитать, но на этот раз уже записать во Flash — память.

case FW_READ + 20: // Flash Firmware
{
  /* В процессе показываем на экране, сколько байт записано */
 sprintf(tbuf, "Запись: %d", idx - MAIN_PROGRAM_START_ADDRESS);
 lcd_putstr(tbuf, 4, 2);
 if (idx > MAIN_PROGRAM_END_ADDRESS) /* Когда записали всю прошивку */
 {
  lcd_putstr("Готово", 7, 3); /* Выводим сообщение на экран */
  f_unlink("FIRMWARE.BIN");  /* Удаляем файл прошивки с SD-карты */
  fw_step = FW_FINISH; /* Завершаем загрузчик */
  break;
 }
 f_read(&F, &fw_buf, sizeof(fw_buf), &t); /* Считываем блок 2 Кб */
 if(t != sizeof(fw_buf)) /* Если не получилось считать */
 {
  lcd_putstr("Ошибка чтения", 3, 3); /* Выводим сообщение на экран */
  fw_step = FW_ERROR; /* Переходим к шагу обработки ошибки обновления */
  break;
 }
 /* Расшифровываем считанный блок прошивки */
 AES_CBC_decrypt_buffer((uint8_t*)&aes_buf, (uint8_t *)&fw_buf, sizeof(fw_buf), AES_FW_KEY, AES_IV);
 FLASH_Unlock(); /* Разблокируем FLash-память на запись */
 FLASH_ErasePage(idx); /* Стираем страницу памяти */
 for(t=0;t<sizeof(aes_buf);t+=4) /* Записываем прошивку по 4 байта */
 {
  FLASH_ProgramWord(idx+t, aes_buf[t/4]);
 }
 FLASH_Lock(); /* Блокируем прошивку на запись */
 idx+=sizeof(fw_buf); /* Переходим к следующей странице */
 break;
}

Теперь для красоты создадим состояния для обработки ошибки и успешного обновления:

case FW_ERROR:
{
 /* Можно что-то сделать при ошибке обновления */
 break;
}
case FW_FINISH:
{
 ExecMainFW(); /* Запускаем основную программу */
 /* Дальнейший код выполнен не будет */
 break;
}

Функцию запуска основной программы ExecMainFW() стоит рассмотреть подробнее. Вот она:

void ExecMainFW()
{
 /* Устанавливаем адрес перехода на основную программу */
 /* Переход производится выполнением функции, адрес которой указывается вручную */
 /* +4 байта потому, что в самом начале расположен указатель на вектор прерывания */
 uint32_t jumpAddress = *(__IO uint32_t*) (MAIN_PROGRAM_START_ADDRESS + 4);
 pFunction Jump_To_Application = (pFunction) jumpAddress;
 /*Сбрасываем всю периферию на APB1 */
 RCC->APB1RSTR = 0xFFFFFFFF; RCC->APB1RSTR = 0x0;
/*Сбрасываем всю периферию на APB2 */
 RCC->APB2RSTR = 0xFFFFFFFF; RCC->APB2RSTR = 0x0;
 RCC->APB1ENR = 0x0; /* Выключаем всю периферию на APB1 */
 RCC->APB2ENR = 0x0; /* Выключаем всю периферию на APB2 */
 RCC->AHBENR = 0x0; /* Выключаем всю периферию на AHB */
 /* Сбрасываем все источники тактования по умолчанию, переходим на HSI*/
 RCC_DeInit();
 /* Выключаем прерывания */
 __disable_irq();
 /* Переносим адрес вектора прерываний */
 NVIC_SetVectorTable(NVIC_VectTab_FLASH, MAIN_PROGRAM_START_ADDRESS);
 /* Переносим адрес стэка */
  __set_MSP(*(__IO uint32_t*) MAIN_PROGRAM_START_ADDRESS);
  /* Переходим в основную программу */
  Jump_To_Application();
}

Сразу после запуска startup файл все переинициализировал, поэтому основная программа должна вновь выставить указатель на вектор прерывания внутри своего адресного пространства:

__disable_irq();
 NVIC_SetVectorTable(NVIC_VectTab_FLASH, MAIN_PROGRAM_START_ADDRESS);
__enable_irq();

В проекте основной программы нужно указать правильные адреса:

Вот, собственно, и вся процедура обновления. Прошивка проверяется на корректность и шифруется, все поставленные задачи выполнены. В случае потери питания в процессе обновления устройство, конечно, закирпичится, но загрузчик останется нетронутым и процедуру обновления можно будет повторить. Для особо ответственных ситуаций можно заблокировать на запись страницы, в которых находится загрузчик через Option bytes.

Однако, в случае с SD-картой можно организовать для самого себя в загрузчике одно приятное удобство. Когда тестирование и отладка новой версии прошивки завершена, можно заставить само устройство по какому-то особому условию (например, кнопка или джампер внутри) зашифровать и выгрузить на SD-карту готовую прошивку. В таком случае останется только извлечь SD-карту из устройства, вставить в компьютер и выложить прошивку в интернет на радость пользователям. Сделаем это в виде ещё двух состояний конечного автомата:

case FW_WRITE:
{
 if(f_mount(&FS, "" , 0) == FR_OK) /* Пробуем смонтировать SD-карту*/
 {
  /* Пробуем создать файл */
  if(f_open(&F, "FIRMWARE.BIN", FA_WRITE  FA_CREATE_ALWAYS) == FR_OK)
  {
   CRC_ResetDR(); /* Сбрасываем блок CRC */
   /* Устанавливаем адрес чтения на начало основной программы */
   idx = MAIN_PROGRAM_START_ADDRESS;
   fw_step = FW_WRITE + 10; /* Переходим к следующему состоянию */
  } else {fw_step = FW_ERROR;} /* Переходим к шагу обработки ошибки */
 } else {fw_step = FW_ERROR;} /* Переходим к шагу обработки ошибки */
 break;
}
case FW_WRITE + 10:
{
 if (idx > MAIN_PROGRAM_END_ADDRESS) /* Если выгрузили всю прошивку */
 {
  t = CRC->DR;
  f_write(&F, &t, sizeof(t), &idx); /* Дописываем в конец файла контрольную сумму */
  f_close(&F); /* Закрываем файл, сбрасываем кэш */
  fw_step = FW_FINISH; /* Завершаем зарузчик */
 }
 /* Считываем 2 Кб прошивки из Flash-памяти в буфер */
 memcpy(&fw_buf, (uint32_t *)idx, sizeof(fw_buf));
 for(t=0;t<NELEMS(fw_buf);t++) /* Вычисляем CRC для считанного блока */
 {
  CRC->DR = fw_buf[t];
 }
 /* Шифруем прошивку */
 AES_CBC_encrypt_buffer((uint8_t*)&aes_buf, (uint8_t *)&fw_buf, sizeof(fw_buf), AES_FW_KEY, AES_IV);
 /* Записываем зашифрованный блок в файл */
 f_write(&F, &aes_buf, sizeof(aes_buf), &t);
 idx+=sizeof(fw_buf); /* Сдвигаем адрес считываемого блока */
 break;
}

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

Ссылки

tinyAES
FatFS

Теги:

Похожие публикации

Source: habr1

Метки:





Запись опубликована: 12.12.2018

Новый браузер Edge от Microsoft будет поддерживать расширения Chrome

Корпорация Microsoft сделает свой новый браузер Edge, базирующийся на Chromium, совместимым с расширениями Chrome. Эта возможность значительно расширит функциональность Edge, хотя с другой стороны, оставит пользователей браузера уязвимыми для зловредных расширений, которых тоже немало.

Не так давно корпорация Microsoft заявила о намерении перестроить Microsoft Edge, чтобы сделать его более удобным и безопасным для пользователей. Решение этой проблемы стало несколько неожиданным — заявлено, что обновленный Edge будет базироваться на Chromium. Сразу после этого анонса у многих появился вопрос о поддержке расширений Chrome браузером Edge. И сейчас он решился, причем положительно.

Заявление о нововведении сделал Кайл Пфлаг, Senior Product Manager команды Edge. Он рассказал обо всем на Reddit, подчеркнув, что в намерениях команды — добавить поддержку расширений.

Поскольку многие пользователи Chrome используют расширение, то решение Microsoft вполне логичное — ведь те, кто решит перейти на Edge, смогут почувствовать себя в родном окружении. Но это же означает и вероятность того, что пользователи Edge будут подвергаться опасности заражения со стороны зловредных расширений Chrome. Каждый день появляются десятки новых зловредов.

Желающих атаковать Edge не так много — в настоящий момент доля рынка браузера исчезающе мала. Именно поэтому количество киберпреступников, выпускающих зловреды под Edgr также минимально. Но вот у Chrome доля рынка превышает 60%, а это значит, что и желающих выпускать зловреды под него огромное количество.

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

У Google никак не получается обуздать злоумышленников — на одно удаленное расширение приходится несколько новых. Есть целые команды «специалистов», которые работают исключительно над расширениями для Chrome, загружая новые взамен ликвидированных.

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

Стоит напомнить, что новый браузер предназначается, в первую очередь, для ARM-систем. Если браузер не является нативным, то его приходится запускать в режиме эмуляции, что влияет на производительность системы и самого браузера. На днях представители Microsoft заявили, что новый браузер будет установлен на всех устройствах Microsoft. Интересно, будет ли работать браузер на очках Microsoft Hololens.

Теги:

Похожие публикации

Source: habr1

Метки:





Запись опубликована: 11.12.2018

PlayStation Classic взломали, теперь игры можно запускать с флешки


Фрагмент материнской платы включенной консоли
На Хабре уже писали о PlayStation Classic, представляющую собой аппаратный эмулятор PlayStation One. К сожалению, количество игр, вшитое разработчиками приставки в ее память, ограничено 20 тайтлами. Но уже нашлись умельцы, которые убрали этот лимит и научили приставку работать с флешкой — игры можно загружать прямо с накопителя.
Оказалось, что криптографическая защита девайса слабая, так что взломать приставку оказалось несложно. Взломщики — профессионалы в сфере модификации и хака консолей, получили дамп приставки через UART-порт и стали его анализировать. Программная часть приставки защищена ключом, который, по странному совпадению, хранится не где-то, а в самой консоли.

Stream in an hour. It’ll just be me laughing for the whole night. pic.twitter.com/nUrYmvCG4E

— Yifan (@yifanlu) December 6, 2018

Так что ни о каких приватных ключах, которые хранятся у Sony, и речи нет. Возможно, компания просто не слишком заморачивалась проблемой защиты, понимая, что аппаратный эмулятор взломать не слишком сложно. Это не PS Vita и не PS4 Pro.

Более того, приставка при выполнении какого-либо кода не выполняет проверку подписи, так что умельцам удалось запустить собственные файлы. Загружать их можно с USB-устройства, процесс продемонстрировал хакер (в положительном значении этого слова) с ником yifanlu.

Благодаря open-source проектам, созданным для PlayStation Classic, теперь пользователи этой консоли могут загружать игры с USB-носителя. Последний распознается приставкой и позволяет запускать практически неограниченный набор игр. Правда, необходимо редактировать некоторые INI файлы, плюс некоторые региональные версии приставки могут не работать с хаком.

Есть и сообщения о том, что неправильно отформатированный и сконфигурированный накопитель «окирпичивает» приставку. Так что при модификации устройства стоит быть осторожным.

Стоит отметить, что подход к модификации консолей от Nintendo, включая NES и SNES Classic, примерно такой же. Программное содержимое приставки загружается на ПК, модифицируется, а затем заливается обратно, после чего консоль получает новые возможности.

Source: habr1

Метки:





Запись опубликована: 11.12.2018

Как повысить эффективность изучения английского и начать писать лучше: выбираем онлайн-помощник



По статистике, в мире 1,5 млрд человек изучают английский язык. Далеко не у всех из них есть возможность заниматься с преподавателем офлайн, поэтому они используют разнообразные онлайн-сервисы. Кроме того, существуют исследования, показывающие, что использование веб-помощников позволяет повысить эффективность изучения английского.

Однако сегодня количество различных инструментов довольно велико, и составить свой стек образовательных технологий может быть нелегко. Поговорим о том, на что следует обращать внимание при их выборе на примере онлайн-помощника по улучшению письменного английского Textly.ai.

Наличие бесплатной версии

Инструмент должен приносить пользу сразу, а не обещать сделать это за деньги. Поэтому, если какой-либо сервис не предлагает бесплатной версии или она ограничена по времени, оценить его качество будет трудно, поскольку обучение – это длительный процесс.

И напротив: наличие бесплатной версии и четко прописанные плюсы премиум-варианта программы – это преимущество. Такая конфигурация позволит понять, что именно можно взять от сервиса сразу и как улучшить свои знания потом.

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

Фокус на приватности

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

У этого подхода есть ряд минусов. Во-первых, пользователь может лишиться своих данных, если не оплатит подписку, а во-вторых, если сервис использовался для работы с чувствительным контентом (вроде личных сообщений), то эта информация навсегда останется в нем.

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

К примеру, в Textly есть специальный Pastebin-режим, который работает аналогично секретным чатам в мессенджере: все материалы, которые созданы в нем, проходят проверки на наличие ошибок, а после закрытия окна полностью удаляются.

Удобный интерфейс

По статистике ученых Стенфордского университета, на то, чтобы выучить английский язык на хорошем уровне, требуется от 3 до 7 лет. Помимо прочего, это означает, что выбранными инструментами обучения вы будете пользоваться достаточно долго. И если у них устаревший и неудобный интерфейс, то эффективность обучения будет снижаться.
И напротив: для повышения продуктивности изучения языка интерфейс образовательного сервиса должен быть продуманным и задействовать именно нужные в рамках конкретных задач элементы.

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

Эти возможности встроены в редактор Textlу – и недавно эксперты платформы-директории софта для бизнеса FinancesOnline отметили соответствующую версию Textly наградой Premium Usability Reward.

Заключение

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

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

Source: habr1

Метки:





Запись опубликована: 11.12.2018

[Перевод] Внутренняя и внешняя линковка в C++

Внутренняя и внешняя линковка в C++

Всем добрый день!

Представляем вам перевод интересной статьи, который подготовили для вас рамках курса «Разработчик C++». Надеемся, что она будет полезна и интересна для вас, как и нашим слушателям.
Поехали.

Сталкивались ли вы когда-нибудь с терминами внутренняя и внешняя связь? Хотите узнать, для чего используется ключевое слово extern, или как объявление чего-то static влияет на глобальную область? Тогда эта статья для вас.

В двух словах

В единицу трансляции включены файл реализации (.c/.cpp) и все его заголовочные файлы (.h/.hpp). Если внутри единицы трансляции у объекта или функции есть внутреннее связывание, то этот символ виден компоновщику только внутри этой единицы трансляции. Если же у объекта или функции есть внешнее связывание, то компоновщик сможет видеть его при обработке других единиц трансляции. Использование ключевого слова static в глобальном пространстве имен дает символу внутреннее связывание. Ключевое слово extern дает внешнее связывание.
Компилятор по умолчанию дает символам следующие связывания:

  • Non-const глобальные переменные — внешнее связывание;
  • Const глобальные переменные — внутреннее связывание;
  • Функции — внешнее связывание.



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

  • Разница между объявлением и определением;
  • Единицы трансляции.

Также обратите внимание на названия: мы будем использовать понятие “символ”, когда речь идет о любой “сущности кода”, с которой работает компоновщик, например с переменной или функцией (или с классами/структурами, но на них мы не будем акцентироваться).
Объявление VS. Определение

Кратко обсудим разницу между объявлением и определением символа: объявление (или декларация) говорит компилятору о существовании конкретного символа, и позволяет обращение к этому символу в случаях не требующих точного адреса памяти или хранилища символа. Определение говорит компилятору, что содержится в теле функции или сколько памяти нужно выделить переменной.
В некоторых ситуациях компилятору недостаточно объявления, например, когда элемент данных класса имеет тип ссылки или значения (то есть не ссылка, и не указатель). В то же время, разрешен указатель на объявленный (но неопределенный) тип, так как ему нужен фиксированный объем памяти (например, 8 байт в 64-битных системах), не зависящий от типа, на который указывает. Чтобы получить значение по этому указателю, потребуется определение. Также для объявления функции нужно объявить (но не определить) все параметры (не важно взятые ли по значению, ссылке или указателю) и возвращаемый тип. Определение типа возвращаемого значения и параметров необходимо только для определения функции.

Функции
Разница между определением и объявлением функции весьма очевидна.

int f();               // объявление
int f() { return 42; } // определение

Переменные

С переменными все немного иначе. Объявление и определение обычно не разделяются. Главное, что это:

int x;

Не только объявляет x, но и определяет его. Происходит это благодаря вызову дефолтного конструктора int. (В C++ в отличие от Java, конструктор простых типов (таких как int) по умолчанию не инициализирует значение в 0. В примере выше х будет иметь равен любому мусору, лежащему в адресе памяти, выделенном компилятором).

Но вы можете явно разделить объявление переменной и ее определение при помощи ключевого слова extern.

extern int x; // объявление
int x = 42;   // определение

Однако, при инициализации и добавлении extern к объявлению, выражение превращается в определение и ключевое слово extern становится бесполезным.

extern int x = 5; // то же самое, что и
int x = 5;

Предварительное Объявление

В C++ существует концепция предварительного объявления символа. Это значит, что мы объявляем тип и имя символа для использования в ситуациях, не требующих его определения. Так нам не понадобится включать полное определение символа (обычно — заголовочный файл) без явной необходимости. Тем самым, мы снижаем зависимость от файла, содержащего определение. Главное преимущество — при изменении файла с определением, файл, где мы предварительно объявляем этот символ, не потребует повторной компиляции (а значит, и все прочие файлы его включающие).

Пример

Предположим, у нас есть объявление функции (называемое прототипом) для f, принимающее объект типа Class по значению:

// file.hpp
void f(Class object);

Сразу включить определение Class — наивно. Но так как мы пока только объявили f, достаточно предоставить компилятору объявление Class. Таким образом, компилятор сможет узнать функцию по ее прототипу, а мы сможем избавиться от зависимости file.hpp от файла, содержащего определение Class, скажем class.hpp:

// file.hpp
class Class;
void f(Class object);

Допустим, file.hpp содержится в 100 других файлах. И, допустим, мы меняем определение Class в class.hpp. Если вы добавим class.hpp в file.hpp, file.hpp и все 100 содержащих его файла будут должны перекомпилироваться. Благодаря предварительному объявления Class единственными файлами, требующими повторной компиляции, будут class.hpp и file.hpp (если считать, что f определен там).

Частота использования

Важное отличие объявления от определения состоит в том, что символ может быть объявлен много раз, но определен только однажды. Так вы можете предварительно объявить функцию или класс сколько угодно раз, но определение может быть только одно. Это называется Правилом Одного Определения. В C++ работает следующее:

int f();
int f();
int f();
int f();
int f();
int f();
int f() { return 5; }

А это не работает:

int f() { return 6; }
int f() { return 9; }

Единицы трансляции

Программисты обычно работают с заголовочными файлами и файлами реализации. Но не компиляторы — они работают с единицами трансляции (translation units, кратко — TU), которые иногда называют единицами компиляции. Определение такой единицы довольно простое — любой файл, переданный компилятору, после его предварительной обработки. Если быть точным, это файл, получаемый в результате работы препроцессора расширяющего макрос, включающего исходный код, который зависит от #ifdef и #ifndef выражений, и копипасты всех файлов #include.

Есть следующие файлы:

header.hpp:

#ifndef HEADER_HPP
#define HEADER_HPP
#define VALUE 5
#ifndef VALUE
struct Foo { private: int ryan; };
#endif
int strlen(const char* string);
#endif /* HEADER_HPP */

program.cpp:

#include "header.hpp"
int strlen(const char* string)
{
	int length = 0;
	while(string[length]) ++length;
	return length + VALUE;
}

Препроцессор выдаст следующую единицу трансляции, которая затем передается компилятору:

int strlen(const char* string);
int strlen(const char* string)
{
	int length = 0;
	while(string[length]) ++length;
	return length + 5;
}

Связи

Обсудив основы, можно приступить к связям. В целом, связь — это видимость символов для компоновщика при обработке файлов. Связь может быть либо внешней, либо внутренней.

Внешняя связь

Когда символ (переменная или функция) обладает внешней связью, он становится видимым компоновщикам из других файлов, то есть “глобально” видимым, доступным всем единицами трансляции. Это значит, что вы должны определить такой символ в конкретном месте одной единицы трансляции, обычно в файле реализации (.c/.cpp), так чтобы у него было только одно видимое определение. Если вы попытаетесь одновременно с объявлением символа выполнить его определение, или поместить определение в файл к объявлению, то рискуете разозлить компоновщик. Попытка добавить файл больше чем в один файл реализации, ведет к добавлению определения больше чем в одну единицу трансляции — ваш компоновщик будет плакать.

Ключевое слово extern в C и C++ (явно) объявляет, что у символа есть внешняя связь.

extern int x;
extern void f(const std::string& argument);

Оба символа имеют внешнюю связь. Выше отмечалось, что const глобальные переменные по умолчанию имеют внутреннее связывание, non-const глобальные переменные — внешнее. Это значит, что int x; — то же самое, что и extern int x;, верно? Не совсем. int x; на самом деле аналогичен extern int x{}; (используя синтаксис универсальной/скобочной инициализации, для избежания самого неприятного синтаксического анализа (the most vexing parse)), так как int x; не только объявляет, но и определяет x. Следовательно, не добавить extern к int x; глобально настолько же плохо, как определить переменную при объявлении ее extern:

int x;          // то же самое, что и
extern int x{}; // скорее всего приведет к ошибке компоновщика.
extern int x;   // а это только объявляет целочисленную переменную, что нормально

Плохой Пример

Давайте объявим функцию f с внешней связью в file.hpp и там же определим ее:

// file.hpp
#ifndef FILE_HPP
#define FILE_HPP
extern int f(int x);
/* ... */
int f(int) { return x + 1; }
/* ... */
#endif /* FILE_HPP */

Обратите внимание, что добавлять здесь extern не нужно, так как все функции явно extern. Разделения объявления и определения тоже не потребуется. Поэтому давайте просто перепишем это следующим образом:

// file.hpp
#ifndef FILE_HPP
#define FILE_HPP
int f(int) { return x + 1; }
#endif /* FILE_HPP */

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

Давайте посмотрим, почему так делать не стоит. Теперь у нас есть два файла реализации: a.cpp и b.cpp, оба включены в file.hpp:

// a.cpp
#include "file.hpp"
/* ... */
// b.cpp
#include "file.hpp"
/* ... */

Теперь пусть поработает компилятор и сгенерирует две единицы трансляции для двух файлов реализации выше (помните что #include буквально означает копировать/вставить):

// TU A, from a.cpp
int f(int) { return x + 1; }
/* ... */

// TU B, from b.cpp
int f(int) { return x + 1; }
/* ... */

На этом этапе вмешивается компоновщик (связывание происходит после компиляции). Компоновщик берет символ f и ищет определение. Сегодня ему повезло, он находит аж два! Одно в единице трансляции A, другое в B. Компоновщик замирает от счастья и говорит вам примерно следующее:

duplicate symbol __Z1fv in:
/path/to/a.o
/path/to/b.o

Компоновщик находит два определения для одного символа f. Поскольку у f есть внешнее связывание, он виден компоновщику при обработке и A, и B. Очевидно, это нарушает Правило Одного Определения и вызывает ошибку. Точнее это вызывает ошибку повторяющегося символа (duplicate symbol error), которую вы будете получать не реже, чем ошибку неопределенного символа (undefined symbol error), возникающую, когда вы объявили символ, но забыли определить.

Использование

Стандартным примером объявления переменных extern являются глобальные переменные. Предположим, вы работаете над самовыпекаемым тортом. Наверняка есть глобальные переменные, связанные с тортом, которые должны быть доступны в разных частях вашей программы. Допустим, тактовая частота съедобной схемы внутри вашего торта. Это значение естественно требуется в разных частях для синхронной работы всей шоколадной электроники. (Злой) C-способ объявления такой глобальной переменной имеет вид макроса:

#define CLK 1000000

Программист C++, испытывающий к макросам отвращение, лучше напишет настоящий код. Например такой:

// global.hpp
namespace Global
{
	extern unsigned int clock_rate;
}
// global.cpp
namespace Global
{
	unsigned int clock_rate = 1000000;
}

(Современный программист C++ захочет использовать разделительные литералы: unsigned int clock_rate = 1’000’000;)

Внутренняя Связь

Если у символа есть внутренняя связь, то он будет виден только внутри текущей единицы трансляции. Не путайте видимость с правами доступа, например private. Видимость означает, что компоновщик сможет использовать этот символ только при обработке единицы трансляции, в которой был объявлен символ, а не позже (как в случае символов с внешней связью). На практике, это значит, что при объявлении символа с внутренней связью в заголовочном файле, каждая единица трансляции, включающая в себя этот файл, получит уникальную копию этого символа. Как если бы вы предопределили каждый такой символ в каждой единице трансляции. Для объектов это значит, что компилятор будет буквально выделять совершенно новую, уникальную копию для каждой единицы трансляции, что, очевидно, может привести к высоким расходам памяти.

Для объявления символа с внутренней связью, в C и C++ существует ключевое слово static. Такое использование отличается от применения static в классах и функциях (или, в целом, в любых блоках).

Пример

Приведем пример:

header.hpp:

static int variable = 42;

file1.hpp:

void function1();

file2.hpp:

void function2();

file1.cpp:

#include "header.hpp"
void function1() { variable = 10; }

file2.cpp:

#include "header.hpp"
void function2() { variable = 123; }

main.cpp:

#include "header.hpp"
#include "file1.hpp"
#include "file2.hpp"
#include <iostream>
auto main() -> int
{
	function1();
	function2();
	std::cout << variable << std::endl;
}

Каждая единица трансляции, включающая header.hpp получает уникальную копию переменной, в силу наличия у нее внутренней связи. Есть три единицы трансляции:

  1. file1.cpp
  2. file2.cpp
  3. main.cpp

При вызове function1 копия переменной file1.cpp получает значение 10. При вызове function2 копия переменной file2.cpp получает значение 123. Однако, значение, которое выдается в main.cpp, не меняется и остается равным 42.

Анонимные пространства имен

В С++ существует другой способ объявления одного и более символов с внутренней связью: анонимные пространства имен. Такое пространство гарантирует, что символы, объявленные внутри него, видны только в текущей единице трансляции. По сути, это просто способ объявить несколько символов static. Какое-то время от использования ключевого слова static в целях объявления символа с внутренней связью отказались в пользу анонимных пространств имен. Однако, им снова стали пользоваться в силу удобства объявления одной переменной или функции с внутренней связью. Есть еще несколько незначительных отличий, на которых я не буду останавливаться.

В любом случае, это:

namespace { int variable = 0; }

Делает (почти) то же самое, что и:

static int variable = 0;

Использование

Так в каких же случаях пользоваться внутренними связями? Использовать их для объектов — плохая идея. Расход памяти больших объектов может быть очень высок из-за копирования под каждую единицу трансляции. Но, в основном, это просто вызывает странное, непредсказуемое поведение. Представьте, что у вас есть синглтон (класс, в котором вы создаете экземпляр только одного инстанса) и неожиданно появляется несколько инстансов вашего “синглтона” (по одному на каждую единицу трансляции).

Однако, внутреннюю связь можно использовать для скрытия из глобальной области локальных хелпер-функций единицы трансляции. Допустим, есть хелпер-функция foo в file1.hpp, которую вы используете в file1.cpp. В то же время у вас есть функция foo в file2.hpp, используемая в file2.cpp. Первая и вторая foo отличаются друг от друга, но вы не можете придумать другие имена. Поэтому вы можете объявить их static. Если вы не будете добавлять и file1.hpp, и file2.hpp в одну и ту же единицу трансляции, то это скроет foo друг от друга. Если этого не сделать, то они будут неявно иметь внешнюю связь и определение первой foo столкнется с определением второй, вызвав ошибку компоновщика о нарушении правила одного определения.

THE END

Вы всегда можете оставить свои комментарии иили вопросы тут или зайти к нам на день открытых дверей.

Source: habr1

Метки:





Запись опубликована: 11.12.2018

[Перевод] Интеграция Cake и TeamCity

Cake — замечательный инструмент для создания конвеера доставки для ваших приложений. Я люблю его, поскольку он позволяет мне писать этот конвеер на языке C#, который я знаю хорошо. Прекрасным свойством Cake, PSake и дургих подобных фреймворков является то, что они создают скрипт, который можно выполнять как на локальной машине разработчика, так и на CI серверах. Здесь я объясню, как организовать взаимодействие скрипта Cake с TeamCity.

Требования

Я буду полагать, что вы уже имеете начальные знания по Cake и TeamCity. В противном случае можете начать с чтения следующих ресурсов:

Для Cake:

Для TeamCity:

Теперь давайте поговорим о взаимодействии Cake и TeamCity.

Логирование

Конвеер Cake обычно состоит из нескольких задач (task). Было бы здорово иметь для каждой такой задачи отдельную секцию в журнале (build log) TeamCity. Я бы хотел получить сворачиваемую секцию для каждой задачи Cake в журнале:

Журнал

Cake API имеет методы TeamCity.WriteStartBuildBlock и TeamCity.WriteEndBuildBlock. Хотя и возможно использовать их в каждой задаче, но это можно автоматизировать. В Cake есть методы TaskSetup и TaskTeardown, которые вызываются перед и после каждой задачи. Они могут открывать и закрывать блоки журнала TeamCity:

TaskSetup(setupContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteStartBuildBlock(setupContext.Task.Name);
   }
});
TaskTeardown(teardownContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteEndBuildBlock(teardownContext.Task.Name);
   }
});

Здесь свойство TeamCity.IsRunningOnTeamCity используется чтобы определить, выплняется код на TeamCity или нет.

Теперь в нашем журнале есть сворачиваемые блоки для каждой задачи. Но можно добавить еще одно улучшение.

Обычно задачи в Cake имеют короткие имена: Build, Test, Clean. Так их легче запускать из командной строки. Но в журнале TeamCity я бы предпочел иметь более развернутые описания задач Cake. И это возможно сделать. Чтобы дать задаче описание, используйте метод Description:

Task("Clean")
.Description("Create and clean folders with results")
.Does(() => { ... });

Теперь эти описания можно использовать для формирования блоков в журнале:

TaskSetup(setupContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteStartBuildBlock(setupContext.Task.Description ?? setupContext.Task.Name);
   }
});
TaskTeardown(teardownContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteEndProgress(teardownContext.Task.Description ?? teardownContext.Task.Name);
   }
});

Это позволяет повысить его читаемость.

Прогресс выполнения

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

Индикация прогресса

Этого можно достичь с помощью методов TeamCity.WriteStartProgress и TeamCity.WriteEndProgress. Их вызовы можно вставить в те же TaskSetup и TaskTeardown:

TaskSetup(setupContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteStartBuildBlock(setupContext.Task.Description ?? setupContext.Task.Name);
      TeamCity.WriteStartProgress(setupContext.Task.Description ?? setupContext.Task.Name);
   }
});
TaskTeardown(teardownContext =>
{
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.WriteEndProgress(teardownContext.Task.Description ?? teardownContext.Task.Name);
      TeamCity.WriteEndBuildBlock(teardownContext.Task.Description ?? teardownContext.Task.Name);
   }
});

Результаты тестов

Если вы выполняете тесты в задаче Cake, то TeamCity способна показать вам их результаты.

Это можно сделать с помощью метода TeamCity.ImportData. Он принимает два параметра: строковое описание типа данных и путь к файлу, эти данные содержащему. Например, есть вы используете MSTest, вот как сообщить TeamCity о результатах выполнения тестов:

Task("Run-Tests")
.Description("Run tests")
.IsDependentOn("Clean")
.IsDependentOn("Build")
.Does(() => {
   var testDllsPattern = string.Format("./**/bin/{0}/*.*Tests.dll", configuration);
   var testDlls = GetFiles(testDllsPattern);
   var testResultsFile = System.IO.Path.Combine(temporaryFolder, "testResults.trx");
   MSTest(testDlls, new MSTestSettings() {
      ResultsFile = testResultsFile
   });
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.ImportData("mstest", testResultsFile);
   }
});

TeamCity поддерживает несколько типов тестов. Кроме mstest вы можете использовать nunit, vstest и некоторые другие.

Анализ покрытия кода тестами

TeamCity способен показать результат анализа покрытия кода тестами.

На данный момент TeamCity поддерживает интеграцию с DotCover. Позвольте показать, как использовать DotCover в скрипте Cake. Сначала DotCover нужно установить:

#tool "nuget:?package=JetBrains.dotCover.CommandLineTools"

После этого его можно использовать в задачах:

Task("Analyse-Test-Coverage")
.Description("Analyse code coverage by tests")
.IsDependentOn("Clean")
.IsDependentOn("Build")
.Does(() => {
   var coverageResultFile = System.IO.Path.Combine(temporaryFolder, "coverageResult.dcvr");
   var testDllsPattern = string.Format("./**/bin/{0}/*.*Tests.dll", configuration);
   var testDlls = GetFiles(testDllsPattern);
   var testResultsFile = System.IO.Path.Combine(temporaryFolder, "testResults.trx");
   DotCoverCover(tool => {
         tool.MSTest(testDlls, new MSTestSettings() {
            ResultsFile = testResultsFile
         });
      },
      new FilePath(coverageResultFile),
      new DotCoverCoverSettings()
         .WithFilter("+:Application")
         .WithFilter("-:Application.*Tests")
      );
   if(TeamCity.IsRunningOnTeamCity)
   {
      TeamCity.ImportData("mstest", testResultsFile);
      TeamCity.ImportDotCoverCoverage(coverageResultFile);
   }
});

Как видите, здесь так же прогоняются и тесты. Поэтому мы сразу можем сообщить TeamCity о результатах тестов и результатах анализа покрытия ими кода. Метод TeamCity.ImportDotCoverCoverage именно и делает это последнее.

Публикация артефактов

В TeamCity вы можете опубликовать некоторые артефакты, созданные в процессе работы скрипта Cake. Хорошим кандидатом на эту роль являются NuGet пакеты:

Чтобы сделать это, положите все артефакты, которые хотите опубликовать, в одну папку. Затем можно выполнить публикацию методом TeamCity.PublishArtifacts:

Task("Publish-Artifacts-On-TeamCity")
.Description("Publish artifacts on TeamCity")
.IsDependentOn("Create-NuGet-Package")
.WithCriteria(TeamCity.IsRunningOnTeamCity)
.Does(() => {
   TeamCity.PublishArtifacts(artifactsFolder);
});

Заключение

Надеюсь, эти простые примеры кода сэкономят вам время и усилия, если вы хотите, чтобы ваш скрипт Cake работал на TeamCity. Полную версию скрипта и обрабатываемого им приложения можно найти на GitHub. Удачи!

Вопросы и ответы

Source: habr1

Метки:





Запись опубликована: 11.12.2018

Обзор 3D-сканера Shining 3D EinScan Pro 2X Plus

Обзор 3D-сканера Shining 3D EinScan Pro 2X Plus

image

Компания Shining 3D представила новое поколение многофункциональных портативных 3D-сканеров EinScan Pro 2X Plus. По заверению производителей, девайс получил значительные улучшения в скорости, точности и функциональности сканирования, по сравнению с предыдущей моделью линейки.

О сканере

Характеристики

  • Операционные системы: Win 7, Win 8, Win 10, 64 bit
  • Вес: 1,13 кг
  • Форматы файлов:OBJ, STL, ASC, PLY, P3
  • Возможность захвата текстуры: да (с модулем цветного сканирования)
  • Время сканирования: < 0.5 с
  • Глубина резкости: ±100 мм
  • Зона сканирования: 208х136 мм — 312х204 мм
  • Интерфейс: USB 3.0
  • Источник света: LED
  • Минимальные системные требования:
  • видео: NVIDIA GTX770 и выше; видеопамять: от 4 Гб;
  • ЦПУ: i7 и выше;
  • RAM: от 16 Гб
  • Объемная точность: 0,3 мм
  • Рабочая дистанция: 510 мм
  • Расстояние до точки: 0,2-3 мм
  • Скорость сканирования: 20-30 fps, 1100 000 точек/с
  • Специализация
  • Образование;
  • Реверс-инжинеринг;
  • Метрологический контроль;
  • Энергетическая отрасль;
  • Сканирование людей;
  • Архитектура
  • Точность сканирования: до 0,05 мм
  • Цена: 427 314 руб. (на 10.12.2016, текущую уточняйте на сайте)

Описание

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



Вес 3D-сканера — чуть больше килограмма. EinScan Pro 2X Plus способен ежесекундно сканировать и обрабатывать до 1,5 миллионов точек при 30 кадрах в секунду — скорость в полтора раза больше, чем у предшественника. Передача данных осуществляется по высокоскоростному интерфейсу USB 3.0.

3D-сканер поддерживает несколько режимов сканирования: быстрое ручное, ручное высокоточное, автоматическое — с использованием поворотного столика, и стационарное. Также разработчики предусмотрели несколько режимов совмещения: автоматический, по маркерам, по меткам на поворотном столе и ручной.



Точность сканирования EinScan Pro 2X Plus в автоматическом и стационарном режимах составляет 0,04 мм, а при использовании маркеров в режиме ручного сканирования — 0,05 мм + 0,3 мм/м. Минимальное расстояние между сканируемыми точками — 0,2 мм. Это позволяет получать данные с высокой детализацией, даже если в модели присутствуют очень мелкие элементы. Рабочая дистанция при работе с 3D-сканером составляет 510 мм.

Для EinScan Pro 2X Plus предусмотрены несколько полезных опций, которые помогают улучшить качество сканирования по многим показателям. Среди доступных наборов есть модуль цветного сканирования с дополнительной камерой Color Pack.

Промышленный набор с поворотным столом и штативом Industrial Pack.

HD Prime Pack — еще одна дополнительная камера, для увеличения точности и захвата деталей.

В стандартном комплекте с 3D-сканером идут: калибровочная панель, маркеры, кабель для подключения к компьютеру, блок питания, а также USB-флешка с новейшим программным обеспечением.

Производство и реверсивная разработка, 3D-моделирование персонализированных продуктов, искусство и реставрация, дизайн, здравоохранение, исследования и образование, виртуальная визуализация — сканер EinScan Pro 2X Plus найдет применение во многих областях.

Для работы с устройством понадобится компьютер или ноутбук с операционной системой Windows 7 или новее, минимум 16 Гб оперативной памяти и видеокарта NVIDIA GTX770 с 4 Гб видеопамяти. Минимальные требования к процессору — Intel Core i7.

Итого

Сканер EinScan Pro 2X Plus представляет собой профессиональный сканер, который может использоваться в образовании, реверс-инжиниринге, метрологическом контроле, энергетической отрасли, сканировании людей и архитектуре.

Выбираете сканер для профессионального сканирования? Напишите нам на sales@top3dshop.ru и мы подберем оптимальный аппарат для вашего производства.

Хотите больше интересных новостей из мира 3D-технологий?
Подписывайтесь на нас в соц. сетях:

Source: habr1

Метки: