Ad-social Bot

Smmok Bot

Vkserfing Bot

Vkstorm Bot

Vktarget Bot

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

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

Привет, меня зовут Pavel Germanika

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


 

Может ли человек, проживая в унылом бесперспективном городе, чего-то добиться, имея под рукой лишь старый ноутбук и интернет? Можно ли без всяких офисов, начальных капиталов построить компанию, приносящую неплохую прибыль? Ответ на этот вопрос вы сможете узнать в моем блоге. Я Pavel Germanika, добро пожаловать!

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

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

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

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

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

Любой из вас может связаться со мной. Я рад каждому! Пишите на мой Telegram.

Метки: ,





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

Методология оценки знаний инженера. Путь архитектора и путь эксперта

Можно ли на одной картинке представить уровень знаний и навыков инженера или даже команды?
Параметров, на самом деле, много. Но у нас есть замечательный пример, как сложное можно визуализировать достаточно простым и наглядным способом.

Я говорю про (думаю всем известный) квадрант Гартнера.

Эта статья о том, как был применен подобный подход визуализации для оценки уровня знаний и навыков сетевых инженеров в одной российской компании.

Двумерный подход

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

Конечно, важно изначально ограничить круг рассматриваемых тем, в соответствии с требованиями компании. В нашем случае это были темы темы R&S, Security, Service Provider.

image

Оценка как «широты», так и «глубины» идет по 10-ти бальной шкале.

Можно выделить 4 квадранта, которые мы условно назовем:

  • начинающий инженер – квадрант I, серая зона
  • тех. менеджер – квадрант II, голубая зона
  • профессионал широкого профиля или архитектор – квадрант III, зеленая зона
  • узкий специалист или эксперт – квадрант VI, желтая зона

Так же в каждом квадранте можно выделить подзоны. Так, например, можно считать, что если знание инженера находится в зоне «широта» 7 – 10, «глубина» 7 – 10, то это инженер, обладающий фундаментальными, экспертными знаниями по многим технологиям, с большим опытом и навыками, способный выполнять фактически любые задачи.

На этом графике так же можно учесть такие характеристики как

  • уровень мотивации
  • коммуникативные качества
  • способность к обучению
  • аналитические способности

Так, хорошие коммуникативные качества, как нам кажется, являются плюсом к «широте», т.к. помогают инженеру получать информацию по смежным направлениям. Остальные 3 качества являются плюсом как для “глубины”, так и для “широты”.

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

Одномерный подход

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

Мы можем выделить как минимум две цели:

  • архитектор

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

  • эксперт в узкой области знаний

Инженер сосредотачивается на одном направлении. Знает детали, нюансы, теорию, возможно вплоть до уровня программирования, математики, знания комплектующих …

Есть еще так же третья цель (IT менеджер), которую мы не будем рассматривать в данной статье, т.к. она не является инженерной целью.

Как нетрудно заметить, эти цели соответствует III (архитектор), IV (узкий специалист) и II (IT менеджер) квадрантам двумерной схемы визуализации.

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

  • Путь архитектора
  • Путь эксперта

Путь архитектора

image

Можно выделить 4 стадии в развитии, которые условно назовем

  1. Начальное знание
    Не требует пояснений.
  2. Узкий профиль (или “Операционное знание”)
    Инженер освоил теорию и овладел набором навыков на достаточном для выполнения своих операционных задач уровне. Он является специалистом в определенной области телекома, но его знания ограничены либо определенной технологией, либо тем, что от него требуется в компании. Такой инженер хорошо справляется с текущими, операционными задачами, но такой инженер не обладает квалификацией, необходимой для принятия архитектурных решений.
  3. Архитектор
    Инженер освоил на хорошем уровне несколько направлений в телекоме. Он обладает хорошим кругозором. Разбирается в различных вендорах, типах оборудования, знает “best practices”, различные рекомендованные дизайны,…
    Это знание позволяет инженеру выбрать для каждой конкретной задачи правильный подход, дизайн, вендоров, оборудование, …
    Но такой инженер пока не обладает достаточными навыками для определения тренда развития отрасли или отдельных направлений телекома.
  4. Звезда
    Инженер обладает полнотой знаний. Это результат как углубления, так и расширения знания ступени архитектор.
    Такие инженеры определяют развитие индустрии.

Путь эксперта

image
Его стадии похожи на стадии “Пути архитектора”, но только не в области всей индустрии (или большой области знаний, связанной с телекомом), а в каком-то одном, довольно узком направлении. То, что этот путь выходит за границы шкалы говорит о том, что чтобы достичь «уровня звезд» и таким образом быть способным определять направление развития данной узкой области, обычно требуется не только отличный уровень инженерного знания, но и специфическое знание (например, знание комплектующих, радиоэлектроника, программирование, математика …)

Несколько дополнительных замечаний

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

Пример формализированного (объективного) подхода

У вас есть опросник, состоящий из 100 вопросов. Опросник соответствует 10 темам – по 10 вопросов на каждую тему. Все вопросы и темы равнозначны с точки зрения важности.

После выполнения теста вы будете иметь распределение баллов (количество отвеченных вопросов в каждой теме) по 10 темам. Например, это может быть что-то типа:

Q1: 9
Q2: 7
Q3: 4
Q4: 6
Q5: 0
Q6: 3
Q7: 6
Q8: 1
Q9: 1
Q10: 3

Хорошо. И какое место в нашей двумерной визуализации займет оценка этого инженера?
Мы видим, что на 4 вопроса уровень выше среднего, а на 6 – ниже. В принципе можно предположить, что инженер находится, в верхней части квадранта IV или … в нижней части квадранта III. Куда добавить баллы за знания – в “ширину” или “глубину”? Неоднозначность. И, не очень понятно, как правильно.

Могут быть выбраны разные алгоритмы. Я для примера написал простой python script и настроил его (меняя параметр factor) в соответствии со своим интуитивным восприятием.
Так, например, для этого случая этот скрипт дает результат

x = 8, y = 5

То есть это верхняя часть квадранта IV.

Это значит, что на пути архитектора этот инженер находится на грани между 2-ой и 3-ей ступенью.

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

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

Теги:

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

Source: habr1

Метки:





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

SamsPcbGuide, часть 8: Как получить правильную осциллограмму

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

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

Я думаю, распространённый сценарий использования осциллографа в цикле разработки печатной платы следующий: если плата не заработала (КЗ, микросхема перегревается, микроконтроллер не прошивается, команды управления не проходят и т.п.), начинаем искать проблему, взяв щуп осциллографа в руки, а если заработала – то и хорошо (рис. 1).

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

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

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

Вернёмся к использованию осциллографов. При описании их места в разработке печатных плат был неявно сформулирован важный принцип измерений (и измерений с помощью осциллографа в частности), о котором часто в своих лекциях говорит Эрик Богатин.

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

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

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

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

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

На рис. 3 изображена эквивалентная схема измерительной цепи с использованием наиболее распространённого типа щупа «1X/10X», который в большинстве случаев входит с стандартный комплект осциллографа.

Сопротивление щупа в положении «10X» по постоянному току составляет около 9 МОм – это последовательно включённый резистор, который образует с входным сопротивлением осциллографа 1 МОм делитель напряжения 1:10. Отсюда и название щупа «10X», который в этом режиме уменьшает измеряемый сигнал в 10 раз (а наводки и привнесённые системой шумы шумы — нет). В положении переключателя «1X» этот резистор закорачивается и сопротивление щупа – это сопротивление коаксиального кабеля щупа. Рекомендую измерить это сопротивление – от кончика щупа до центрального контакта BNC-разъёма – и убедиться, что оно не «нулевое», как у обычного 50-омного коаксиального кабеля, а составляет несколько сотен Ом. Если разрезать кабель (рис. 4), то можно увидеть тонкий нихромовый проводник, окружённый вспененным изолирующим материалом с низкой диэлектрической проницаемостью εr ~ 1. Это линия с потерями, т.е. кабель спроектирован таким образом, чтобы ослабить высокочастотные отражения, возникающие в связи с несогласованностью измерительной сигнальной линии.

Подстроечный конденсатор CEQ1 предназначен для компенсации в режиме «10X» полюса фильтра нижних частот (рис. 5) с частотой среза порядка всего 1,5 кГц! Теперь должно быть понятно, почему эта компенсация необходима. Подстроечный конденсатор иногда располагается не в рукояти щупа, а на дальнем конце, у соединительного разъёма – тогда CEQ1 фиксированного номинала ~15 пФ, а подстройка осуществляется конденсатором CEQ2. Индуктивность LP – это индуктивность петли возвратного тока.

С учётом сказанного выше можно получить рабочую модель измерительной цепи осциллографа для положений переключателя «10X» и «1X». Численные значения параметров должны браться из документации на соответствующие щупы и осциллографы. При этом, скорее всего, параметры различных производителей не должны значительно отличаться для заданной полосы пропускания. В представленных на рис. 6 и 7 моделях LTSpice использовались данные на осциллограф TDS2024B и щуп P2200.

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

1. Полоса пропускания щупа в режиме «1X» более чем на порядок меньше, чем в режиме «10X» и составляет порядка 6…8 МГц. Это соответствует минимальной измеримой длительности фронта сигнала tR = 0,35 / BWPROBE ~ 45…55 нс. Преимуществом режима «1X» является увеличенное на 20 дБ отношение сигнал/шум, так как при том же уровне помех измерительной системы сигнал на входе осциллографа больше в 10 раз.

2. Увеличение индуктивности петли возвратного тока снижает полосу пропускания. Именно поэтому при измерении высокочастотных сигналов для обеспечения возвратного тока рекомендуется использовать на «крокодил» с индуктивностью ~200 нГн, а специальную насадку на щуп, на порядок снижающую значение индуктивности (рис. 8).

3. Влияние подстроечного конденсатора в режиме «10X» на передаточную функцию нарастает, начиная с частот 200…300 Гц, до максимума на частотах в 2…3 кГц. Именно поэтому в качестве калибровочного сигнала на осциллографах обычно используется сигнал с тактовой частотой 1 кГц, фронты которого искажаются при подстройке (рис. 9). Полезная привычка – выполнять подстройку как при смене щупа или канала осциллографа, так и периодически перед проведением измерений.

Помимо электрических характеристик щупа и входной цепи осциллографа в модель на рис. 3 как параметры входят следующие величины: напряжение источника сигнала – его спектр, выходное сопротивление источника RS, импеданс сигнальной линии Z0, импеданс нагрузки ZLOAD – именно импеданс, с учётом емкостной составляющей. Эти и другие параметры представлены в таблице 1, именно они определяют достоверность результатов измерения. Основных критериев при этом заключается в том, чтобы исследуемая часть спектральной полосы сигнала входила в полосу пропускания системы «щуп + осциллограф», при этом амплитуда сигнала не превышала допустимых значений (это особенно важно в случае, когда входное сопротивление осциллографа составляет 50 Ом). Остальное: захват сигнала и измерение его параметров – дело техники.

Последний момент, на котором хочется остановиться – это полоса пропускания системы «щуп + осциллограф». Тут стоит избегать заблуждения, заключающегося в том, что если взять осциллограф и щуп с полосой пропускания 150 МГц, то полоса пропускания измерительной системы будет 150 МГц (это так только при наличии программной компенсации). Кроме того, тот факт, что на щупе «написано» 150 МГц, не всегда означает, что это реальные 150 МГц. Поэтому рекомендую с помощью генератора синусоидального сигнала экспериментально исследовать полосу пропускания. Частота, на которой амплитуда сигнала уменьшиться до 0,707 от значения на низких частотах, это и будет нужное значение. При этом стоит обратить внимание на то, есть ли локальные максимумы в передаточной функции. Я это проделал с помощью генератора Г4-107 для нескольких измерительных систем, при этом использовалось соединение с помощью «пружинки» (рис. 10). Перед каждым измерением выполнялась компенсация, при этом всегда приходилось делать подстройку, хоть и небольшую. Также проводились измерения без щупа с помощью короткого 50-омного коаксиального BNC-кабеля. Результаты представлены в таблице 2. Удивил щуп PP510 с заявленной полосой в 100 МГц.

В общем, если подводить итог, то хочется сказать, что следует внимательно относиться к измерениям с помощью осциллографа, и в качестве опоры использовать корреляцию между ожидаемыми и полученными результатами. Что касается области более высоких частот, то для измерения сигналов, полоса пропускания которых превышает 500 МГц, пассивные щупы типа «1X/10X» не применимы. Для этого используют прямое коаксиальное соединение при 50-омном входе осциллографа или активные щупы, ещё больше минимизируют индуктивность соединения (в т. ч. за счёт использование паяных соединений, размещения на плате миниатюрных коаксиальных разъёмов и т.п.). Тема очень широкая – есть изолированные осциллографы, изолированные щупы, дифференциальные и специализированные щупы, но всё это уже отдельный разговор, выходящий за рамки данной статьи.

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

Теги:

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

Source: habr1

Метки:





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

[Перевод] Новости из мира OpenStreetMap №437 (27.11.2018-03.12.2018)

  • Перевод

Поверочный объект для мобильных устройств 1 | Kanton Zürich, Baudirektion, Amt für Raumentwicklung

Карты

  • Справочник OpenStreetBrowser теперь имеет новую категорию в разделе «Отдых, спорт и покупки» (Leisure, Sport and Shopping). Согласно сообщению в блоге, новая категория «Плавание и Купание»(Swimming and Bathing) включает в себя все виды плавательных и банных сооружений и саун.

О нас

Картографирование

  • PoliMappers, подразделение YouthMappers’ в Политехническом институте Милана (Италия), организуют второе мероприятие PoliMappers Adventures. В течение декабря вы можете выполнять ежедневные квесты, связанные с миром OpenStreetMap. Квесты варьируются: картирование, помощь гуманитарной команде и многих другие. Следите за ними в Твиттере, чтобы быть в курсе.
  • CartoRoute («MapRoad») — это сотрудничество между Michelin и сообществом OSM в Кот-д’Ивуар, цель которого — нанести на карту главную дорожную сеть по всей стране: состояние дорог, поверхность, ограничения скорости, дорожные знаки, столовые, отели и заправочные станции и т. д. Первоначальная фаза проекта началась в коммуне Плато (Абиджан), где 11 местных участников OSM в течение двух дней собирали данные с использованием OsmAnd, о том как идёт работа читайте в момент Twitter.
  • Тег cycleway:surface уже использовался в OSM более 500 раз, но только сейчас его надлежащим образом задокументировали в OSM Wiki. Тег позволяет указать поверхность только велосипедной дорожки, например, для велосипедной дорожки на дороге, где поверхности различаются.
  • Новое Руководство по организованному редактированию было одобрено на предыдущем заседании совета OSMF 15 ноября. Руководство были разработано Рабочей группой по данным и направлено на улучшение прозрачности и практики организованных картографических инициатив.
  • Отсутствие актуализации избирательных границ в Германии привело к предложению (de) (автоматический перевод) удалить эти данных. Предложение получило большую поддержку, но также и несколько замечаний.
  • Голосование за картирование трамвая на шоссе ‘tramtrack on highway’ не состоялось. Тем не менее, автор сообщения Юкка Никулайнен (Jukka Nikulainen) готовит новое предложение на основе отзывов, которые он получил.

Cообщество

  • Участник Кан Юнен (Can Ünen) (OSM unen), преподаватель университета в Стамбуле, Турция, является новым «Картографом месяца». Как обычно, OSM Belgium опубликовала интервью с ним.
  • Южнокорейский участник GPIOIPG провёл опрос о том, должны ли названия станций общественного транспорта в OSM иметь суффикс -역 (то есть станция). Обычно официальные названия записывают без суффикса. Но очевидно, что суффикс широко используется людьми, и даже некоторые знаки показывают суффикс, но слово «станция» не добавляется после названий в других странах. В своём дневнике GPIOIPG пишет о результатах своего опроса, которые он собирал на форуме и в почтовой рассылке, и даёт дополнительную справочную информацию.
  • Участник Nakaner загрузил в базу данных все электронные письма из всех общедоступных списков рассылки lists.openstreetmap.org и проанализировал их.
    Две записи (1, 2) вариантов в его блоге содержат информацию о количестве сообщений за год и по отдельным спискам рассылки, а также список самых активных авторов.
  • Участник SunCobalt отмечает, что незадолго до нынешних и прошлых выборов число членов OSMF сильно увеличивается, и визуализирует это с помощью графика. «Пусть будет стыдно тому, кто начнёт из-за этого что-то подозревать» (Honi soit, qui mal y pense.)

Фонд OpenStreetMap

  • Официальные манифесты и ответы кандидатов на выборы в совет Фонда OSM в этом году уже опубликованы. Кристоф Хорманн (Christoph Hormann) написал резюме, а Пол Норман (Paul Norman) написал руководство по оценке. Есть обсуждения на форуме, а также в почтовой рассылкеosmf-talk.
  • Рабочая группа по участникам (The Membership Working Group (MWG) сообщает о своей деятельности. MWG в настоящее время занята новой программой для возврата внесённых членских взносов и имеет дело со странами, у которых нет подходящих вариантов перевода денег для оплаты членского взноса. Как и Еженедельник OSM и другие рабочие группы Фонда OSMF, MWG ищет добровольцев.
  • Микель Марон (Mikel Maron), член совета Фонда OSM, объявил о запуске инициативы Добро пожаловать Мэт (Welcome Mat). Сайт Welcome Mat был создан для того, чтобы помочь сторонним организациям понять сложную структуру OSM, объяснить, как работает OSM, как и где можно принять участие.

События

  • Конференция FOSS4G Италия анонсировала (автоматический перевод)
    приём докладов и предложений тем семинаров для третьего итальянского FOSS4G 2019, который состоится в Падуе с 20 по 24 февраля. Предложения принимаются до 13 декабря.

Гуманитарный OSM

  • Участники проекта OpenGovHub 4 декабря провели картопати с участниками HOT в офисе OpenGov Hub в Вашингтоне, округ Колумбия.
  • Гуманитарная команда HOT разместила обновлённую информацию о своей программе Микрогранты 2018, которая была запущена в апреле 2018 года. Восемь участников программы получили микрогранты в целях улучшения OSM и оказания помощи в минимизации последствий стихийных бедствий.

Переходим на OSM (switch2OSM)

  • Поисковик Qwant, созданный в Франции, теперь показывает векторную карту на освнове OSM, а также использует OSM для работы других своих сервисов.

Программирование

  • Исследовательская группа GIScience Университета Гейдельберга представила API Playground, которое позволяет изучать службы API OpenRouteService и экспериментировать с параметрами и ответами сервиса.
  • Маттиас сделал прототип внешнего голосового контроллера для JOSM. Инструмент speech2JOSM доступен на GitHub.

Релизы

  • Вышла новая стабильная версия JOSM. Версия 18.11 сохраняет высоту каждой панели справа, когда JOSM закрывается, панель снабжена специальной кнопкой Download as new layer вместо флажка. Улучшено множество других функций. Наиболее заметным изменением, вероятно, является исправление отображения GPS трэков, вызванных изменением API веб-сайта OSM.

А вы знаете …

  • что число созданных карт через сервис MapOSMatic на сайте osm-baustelle.de недавно превысило 40,000 штук. А также он расширил свою функциональность за счёт улучшений пользовательского интерфейса и поддержки гиперссылок в многостраничных документах PDF.
  • что Стефан Келлер(Stefan Keller), профессор компьютерных наук в Университете прикладных наук Рапперсвиль, создал Карту Тумана. На карте показано, как найти дорогу к солнцу в серые, туманные ноябрьские дни. На сайте Bluewin.ch опубликована (de) (автоматический перевод) краткая справочная информация и тесты, если карта работает. К сожалению, карта охватывает только Швейцарию.
  • … о сайте kinderkiez.net? Сервис, доступный на английском и немецком языках, позволяет создавать детский игровой коврик с картой на основе OSM.
  • … про длинный список ссылок на страницы, где вы можете найти подходящий тег, если вы не можете найти его в пресетах вашего редактора?

Другие “гео” события

  • 1В Швейцарии старый международный пограничный пост был перемещён на территорию Швейцарского национального музея в Цюрихе. Теперь он предоставляет собой первую опорную точку для мобильных устройств (автоматический перевод) через QR-код или ссылку на точку отмеченную в OSM.
  • Компания iXpoint победила (de)(автоматический перевод)
    в Европейском конкурсе спутниковой навигации (ESNC) 2018 с проектом по маршрутизации движения пешеходов на основе данных OSM.
  • Гаэль Муске (Gaël Musquet), основатель и бывший представитель OpenStreetMap Франция (французское местное отделение Фонда OSM), был награждён (автоматический перевод) Национальным орденом за заслуги, вместе с одним из разработчиков VLC. Он считает эту награду как признание заслуг всего сообщества и ведущих французских участников open-source.
  • Свен Грегори (Sven Gregori) объясняет как получить публичные данные ADS-B о местоположении с самолётов и отобразить их на карте с подложкой OSM, используя Python и библиотеку Cartopy.

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

Прошу прощения за возможные опечатки, неработающие ссылки или несуразности.
Если вы заметили проблему — напишите пожалуйста в личку, обязательно исправлю.

Теги:

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

Source: habr1

Метки:





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

Снежинки в стилистике StarWars своими руками (upd. 2018)

A long time ago in a galaxy far, far away… И вот опять наступил конец года… декабрь… Думаете Антонио Эррера решил нас порадовать новыми паттернами снежинок, выполненных в стилистике StarWars? И вы абсолютно правы. В прошлом году Антонио сделал всего два паттерна с Поргами (кстати в подборку этого года они так же вошли).

Новые паттерны от Антонио:

B/SF-17 Heavy
Bomber and A-Wing
Vice Admiral Holdo Luke Skywalker
Porg Porg Praetorian Guard
Princess Leia —
General Solo
Rose Tico

Что может понадобиться (копипаст с прошлых лет)

Для изготовления снежинок вам потребуется:

1. Файл со схемой.
2. Принтер (думаю лазерный будет предпочтительней).
3. Ножницы.
4. Скальпель.
5. Бумага.
5.1. Лично мое мнение — при печати на стандартной офисной бумаге плотностью 80г/м2 становится не очень удобно вырезать (все-таки при складывании бумаги получается толстый слой). Поэтому лично я использую бумагу потоньше. И снежинки получаются «воздушнее».

Как складывать получившиеся схемы и вырезать их можно увидеть ознакомившись с видео (от автора схем):

Статьи на Хабре прошлых лет (в прошлогодней есть паттерны не от Антонио)

P.S. Так же в прошлом году камрад mozgosteb запилил примитивный редактор снежинки. Кто хочет поиграться — пожалуйста.

May the Force Scissors be with you…

Теги:

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

Source: habr1

Метки:





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

[Из песочницы] Усложняя стандартный пример

Стандартная библиотека С++ предлагает не только набор классов, но также определяет способ написания программ. В рамках данной статьи рассматриваются общие требования к реализации программ при помощи STL.

Рассмотрим следующую задачу:

Считать из файла input.txt массив целых чисел, разделенных пробельными символами. Отсортировать их и записать в файл output.txt

Можно написать следующее решение:

#include <vector>
#include <algorithm>
#include <fstream>
int main(){
    // открываем input.txt для чтения
    std::ifstream fin("input.txt");
    // открываем output.txt для записи
    std::ofstream fout("output.txt");
    // объявление и инициализация пустого целочисленного вектора
    std::vector<int> v;
    // сложная магия, благодаря которой из потока чтения вставляются элементы в конец вектора
    std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::inserter(v, v.end()));
    // алгоритм сортировки
    std::sort(v.begin(), v.end());
    // сложная магия, благодаря которой элементы из вектора копируются в поток записи
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(fout, " "));
    return 0;
}

Несколько слов о «магии» в коде:

  • Одной из основ библиотеки являются итераторы, а также полуинтервалы, ими определяемые. По семантике (читай — по поведению) они совпадают с указателями. То есть, опреатор разыменования * вернет вам элемент, на который ссылается итератор, ++ переведет итератор на следующий элемент. В частности, любой контейнер представляется его концевыми итераторами [begin, end), где begin указывает на первый элемент, end — за последний;
  • Алгоритмы, работающие с контейнерами, в качестве параметров принимают начало и конец контейнера (или его части);
  • Алгоритм копирования copy просто переписывает элементы из одного полуинтервала в другой. Если в целевом контейнере не выделена память, то поведение непредсказуемо [copy];
  • Функция inserter вставляет значение в контейнер перед указанным итератором [inserter]
  • istream_iterator и ostream_iterator предоставляют доступ к потокам в стиле контейнеров [istream_iterator, ostream_iterator]

Этот пример, на самом деле, довольно прост. Однако он может нам помочь в решении следующей задачи:

В файле input.txt хранится список, содержащий информацию о людях: фамилия, имя, возраст (каждая строка это запись, данные разделены пробелом). Считать эти данные в массив, отсортировать их по возрасту и записать в файл output.txt. Вывести на экран информацию о человеке, чей возраст более 20, но менее 25 лет.

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

  1. Объявить структуру данных. — можно определить что-то служное, но в конкретном случае достаточно struct:
    struct man{
        std::string firstname, secondname;
        size_t age;
    };
    

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

  2. Перегрузить операторы ввода / вывода — этими операторами манипулируют итераторы над потоками. Да и вообще, ими привычнее пользоваться.
    std::ostream& operator << (std::ostream& out, const man& p){
        out << p.firstname << " " << p.secondname << " " << p.age;
        return out;
    }
    std::istream& operator >> (std::istream& in, man& p){
        in >> p.firstname >> p.secondname >> p.age;
        return in;
    }
  3. Определить правила упорядочивания объектов — Здесь уже большое раздолье: можно переопределить оператор <, можно описать функцию, функтор или лямбда-выражение. В данном случае воспользуемся функцией.
    bool comparator(const man& p1, const man& p2){
        return p1.age < p2.age;
    }
    
  4. Определить правило выборки объектов — Опять же, довольно большой выбор реализации. На этот раз пусть будет функтор (объект класса, в котором определен оператор круглые скобки [функтор]), которому можно передавать возрастной промежуток:
    struct predicate{
        size_t begin, end;
        predicate(int p1, int p2): begin(p1), end(p2) {}
        bool operator ()(const man& p){
            return (p.age > begin) && (p.age < end);
        }
    };

    Обратите внимание на конструктор у функтора — таким образом мы можем настраивать его поведение.

Ну и, собственно, точка входа в программу:

int main(){
    std::ifstream fin("input.txt");
    std::ofstream fout("output.txt");
    std::vector<man> v;
    std::copy(std::istream_iterator<man>(fin), std::istream_iterator<man>(), std::inserter(v, v.end()));
    std::sort(v.begin(), v.end(), comparator);
    std::copy_if(v.begin(), v.end(), std::ostream_iterator<man>(std::cout, "n"), predicate(20, 25));
    std::copy(v.begin(), v.end(), std::ostream_iterator<man>(fout, "n"));
    return 0;
}

Как можно заметить, изменения функции main минимальные, касаются только типа элементов вектора. Плюс добавлен вызов алгоритма copy_if. Этот полезный алгоритм появился со стандартом С++11, он копирует элементы из одного контейнера в дргой только те элементы, которые удовлетворяют условию.

Какие можно сделать из этого выводы?

  1. Знание и активно использование алгоритмов стандартной библиотеки существенно ускоряет разработку (точнее говоря, доводит до автоматизма).
  2. Полезным является объявление различных конструкторов и операторов копирования для структур данных. Они используются в различных ситуациях, в частности, при вставке элементов в контейнеры.
  3. Для удобства можно перегрузить операторы ввода и вывода, а также оператор сравнения и оператор упорядочения.
  4. Функторы — мощный инструмент, который позволяет реализовать функции с «памятью» или дополнительным поведением
  5. … возможно, еще каккие-либо…

Спасибо, что дотерпели!

Весь код программы:

an_example.cpp

#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include <iostream>
#include <iterator>
struct man{
    std::string firstname, secondname;
    size_t age;
};
std::ostream& operator << (std::ostream& out, const man& p){
    out << p.firstname << " " << p.secondname << " " << p.age;
    return out;
}
std::istream& operator >> (std::istream& in, man& p){
    in >> p.firstname >> p.secondname >> p.age;
    return in;
}
bool comparator(const man& p1, const man& p2){
    return p1.age < p2.age;
}
struct predicate{
    size_t begin, end;
    predicate(int p1, int p2): begin(p1), end(p2) {}
    bool operator ()(const man& p){
        return (p.age > begin) && (p.age < end);
    }
};
int main(){
    std::ifstream fin("input.txt");
    std::ofstream fout("output.txt");
    std::vector<man> v;
    std::vector<man>::iterator i;
    std::copy(std::istream_iterator<man>(fin), std::istream_iterator<man>(), std::inserter(v, v.end()));
    std::sort(v.begin(), v.end(), comparator);
    std::copy_if(v.begin(), v.end(), std::ostream_iterator<man>(std::cout, "n"), predicate(20, 25));
    std::copy(v.begin(), v.end(), std::ostream_iterator<man>(fout, "n"));
    return 0;
}

Библиография:

  1. Stepanov Al. Lee Meng, The Standard Template Library, 1995
  2. CPP Reference, copy
  3. CPP Reference, inserter
  4. CPP Reference, istream_iterator
  5. CPP Reference, ostream_iterator
  6. Wiki, функтор
Теги:

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

Source: habr1

Метки:





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

[Перевод] Сделал редизайн — потерял миллиард

Изобретаем успех: софт и стартапы

Сделал редизайн — потерял миллиард

  • Перевод
Исследуем эпичные провалы редизайна и мотаем на ус.

image

Менеджер по продукту заходит в отдел дизайна и заказывает редизайн сайта. «Наш сайт выглядит таким старым! У всех наших конкурентов есть более яркие сайты. Давайте перепроектируем его. Кнопки с разноцветными тенями — это будущее!»
Дизайнер: «Хорошо, давайте начнем с тестирования юзабилити»
ПМ: «У вас есть 3 недели, и я хочу, чтобы все цвета были заменены на ярко-розовый, ярко-синий или оранжевый».

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

image

Skype Redesign 2018

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

Но чаще всего редизайн кажется довольно нежелательным, с падением конверсий, сердитыми пользователями и отрицательными отзывами о приложении. Будь то мелкие игроки, такие как Snapchat или такие большие, как Microsoft с Windows 8 и Skype — кажется, никто не застрахован от неудачи редизайна.

Почему редизайн проваливается

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

Редизайн навигации Snapchat’a

image

Давайте проанализируем, как Snapchat переработал одну из своих основных пользовательских функций- просмотр историй от друзей.

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

Продвигаемые истории знаменитостей и СМИ были частью этой страницы. Они появились рядом с историями ваших друзей.

image

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

image

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

image

Были изменены как минимум два практических правила: структура навигации и область, которую нужно нажать, чтобы просмотреть историю. Излишне говорить, что пользователям не очень понравились эти изменения. В течение недели средний рейтинг Snapchat снизился с 3,1 до 2,4.

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

image

image

image

Этот твит стоил Snapchat миллиард долларов

Редизайн Snapchat был катастрофой. Ежедневная посещаемость сократились на 2% до 188 миллионов с 193 миллионов. Показы рекламы и доход снизились на 36%. Многие издатели контента поменяли платформу и стали называть Instagram своим новым домом.

Через 6 месяцев после внедрения редизайна Snapchat внес изменения и объявил об перестановке. Истории друзей перемещены вправо вместе с историями издателей. Цитата:

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

Редакция меню Пуск в Windows 8

Теперь давайте посмотрим, как Microsoft перепроектировала их меню «Пуск» в Windows 8. Давайте попробуем открыть панель управления в Windows 7 и 8.

Чтобы открыть панель управления в Windows 7, вам нужно нажать на кнопку «Пуск», чтобы вывести список всех приложений. И тогда вы нажимаете на панель управления.

image

В Windows 8 вы уже начинаете с меню «Пуск». Хороший старт, верно? Неправильно. В перечисленных приложениях нет панели управления. Также нет возможности перечислить все программы.

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

image

Этот основанный на жестах процесс доступа к панелям был совершенно чужд пользователям при запуске Windows 8. Windows не предоставляла никакой дополнительной информации, чтобы помочь пользователям открыть меню чудо-кнопок. Даже после того, как пользователи обнаружили Charms меню, прибегая к помощи Google или своих друзей, им все равно было неудобно с ним. Жесты и зависания были новыми понятиями для ОС.

Все ли редизайны плохие?

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

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

Редизайн навигации в Facebook

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

image

И Android, и iOS реализовывали навигацию одинаково с одинаковыми панелями действий.

image

Но база мобильных пользователей подтягивалась, и пользователи, начинающие с мобильного, понемногу затеняли пользователей, использующих десктопную версию. Мобильные социальные сети, такие как Instagram, Snapchat и Vine (rip) набирали популярность. Было совершенно очевидно, что в будущем люди будут проводить больше времени за своими телефонами, чем за компьютерами.

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

image

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

Разделение вкладок Facebook в Android и iOS сыграло для них очень хорошую ро. Вскоре они стали отраслевым стандартом. Большинство приложений реализуют подобную навигацию.

Уроки

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

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

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

image

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

Редизайн — это процесс, а не пункт назначения
Дизайн продукта — это циклический процесс создания прототипа, тестирования, анализа и усовершенствования продукта или процесса. Редизайн не означает, что продукт завершен. Это просто означает, что он «достаточно выполнен», чтобы удовлетворить любые текущие требования. Ни один продукт или пользовательский интерфейс никогда не «готов».

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

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

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

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

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

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

Теги:

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

Source: habr1

Метки:





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

Пишем торговых роботов с помощью графического фреймворка StockSharp. Часть 2

Пишем торговых роботов с помощью графического фреймворка StockSharp. Часть 2

  • Tutorial


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

Создание панели портфелей

По аналогии с панелью инструментов создадим панель логов. Для этого в папку XAML добавляем еще один UserControl. Дадим ему имя PortfolioGridControl. В него добавим элемент PortfolioGrid.

<UserControl
	x:Class="ShellNew.XAML.PortfolioGridControl"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:xaml="http://schemas.stocksharp.com/xaml"
	mc:Ignorable="d"
	d:DesignHeight="450" d:DesignWidth="800">
	<xaml:PortfolioGrid x:Name="PortfolioGrid" />
</UserControl>

В конструкторе PortfolioGridControl нам надо подписаться на события появления нового портфеля и событие появления новой позиции у Connector.

public PortfolioGridControl()
{
	InitializeComponent();
	MainWindow.Instance.Connector.NewPortfolio += PortfolioGrid.Portfolios.Add;
	MainWindow.Instance.Connector.NewPosition += PortfolioGrid.Positions.Add;
}

Таким образом при создании нового портфеля, он появится на панели портфелей, а при появлении новой позиции на панели портфелей – она будет обновлена.

В центральную части MainWindow добавляем созданную панель PortfolioGridControl:

<dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs">
	<!-- центральная часть-->
	<dxlc:LayoutGroup  Header="Securities">
		<myxaml:SecurityGridControl x:Name="SecurityPanel" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Portfolios">
		<myxaml:PortfolioGridControl x:Name="PortfolioGridControl" />
	</dxlc:LayoutGroup>
</dxlc:LayoutGroup>

Запускаем для проверки:



У нас появилась вкладка с портфелями.

Создание панели ордеров

Панель ордеров в S#.API имеет возможность выставления заявок, снятия заявок и перерегистрации. По аналогии с панелью инструментов создадим панель ордеров, в папку XAML добавляем еще один UserControl. Дадим ему имя OrderGridControl. В него добавим элемент OrderGrid:

<UserControl
	x:Class="ShellNew.XAML.OrderGridControl"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:xaml="http://schemas.stocksharp.com/xaml"
	mc:Ignorable="d"
	d:DesignHeight="450" d:DesignWidth="800">
	<xaml:OrderGrid x:Name="OrderGrid" />
</UserControl>

OrderGrid имеет событие регистрации заявки OrderRegistering, событие перерегистрации заявки OrderReRegistering и событие отмены заявки OrderCanceling.

Создадим их обработчики:

<UserControl
	x:Class="ShellNew.XAML.OrderGridControl"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:xaml="http://schemas.stocksharp.com/xaml"
	mc:Ignorable="d"
	d:DesignHeight="450" d:DesignWidth="800">
	<xaml:OrderGrid x:Name="OrderGrid"
	                OrderRegistering="OrderGrid_OnOrderRegistering"
	                OrderReRegistering="OrderGrid_OnOrderReRegistering"
	                OrderCanceling="OrderGrid_OnOrderCanceling" />
</UserControl>

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

После чего мы вызываем OrderWindow методом ShowModal. Если в этом окне была нажата кнопка ОК, то мы через коннектор методом RegisterOrder регистрируем заявку:

private void OrderGrid_OnOrderRegistering()
{
	var newOrder = new OrderWindow
	{
		Title = "Order registering",
		Order = new Order(),
		SecurityProvider = MainWindow.Instance.Connector,
		MarketDataProvider = MainWindow.Instance.Connector,
		Portfolios = new PortfolioDataSource(MainWindow.Instance.Connector),
	};
	if (newOrder.ShowModal(this))
		MainWindow.Instance.Connector.RegisterOrder(newOrder.Order);
		}

В обработчике события перерегистрации заявки мы делаем все аналогичным образом. Только в этом случае в событие нам приходит объект Order – это заявка, которую надо перерегистрировать. Поэтому в OrderWindow мы указываем Order = order.ReRegisterClone(newVolume: order.Balance), чтобы заполнить поля окна OrderWindow.

После чего мы вызываем OrderWindow методом ShowModal. Если в этом окне была нажата кнопка ОК, то мы через коннектор методом ReRegisterClone перерегистрируем заявку. В него мы передаем старую заявку, которую надо отменить, и новую, которую надо выставить.

private void OrderGrid_OnOrderReRegistering(Order order)
{
	var window = new OrderWindow
	{
		Title = "Order re-registering",
		SecurityProvider = MainWindow.Instance.Connector,
		MarketDataProvider = MainWindow.Instance.Connector,
		Portfolios = new PortfolioDataSource(MainWindow.Instance.Connector),
		Order = order.ReRegisterClone(newVolume: order.Balance)
	};
	if (window.ShowModal(this))
		MainWindow.Instance.Connector.ReRegisterOrder(order, window.Order);
}

В обработчике события отмены заявки достаточно вызвать метод CancelOrder и передать в него ордер, который необходимо отменить:

private void OrderGrid_OnOrderCanceling(Order order)
{
	MainWindow.Instance.Connector.CancelOrder(order);
}

Чтобы заявки отображались в OrderGrid, необходимо в конструкторе OrderGridControl подписаться на события появления новой заявки и на событие ошибки регистрации, а затем передавать эти события в OrderGrid:

public OrderGridControl()
{
	InitializeComponent();
	MainWindow.Instance.Connector.NewOrder += OrderGrid.Orders.Add;
	MainWindow.Instance.Connector.OrderRegisterFailed += OrderGrid.AddRegistrationFail;
}

В центральную части MainWindow добавляем созданную панель OrderGridControl:

<dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs">
	<!-- центральная часть-->
	<dxlc:LayoutGroup  Header="Securities">
	<myxaml:SecurityGridControl x:Name="SecurityPanel" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Portfolios">
		<myxaml:PortfolioGridControl x:Name="PortfolioGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Orders">
		<myxaml:OrderGridControl x:Name="OrderGridControl" />
	</dxlc:LayoutGroup>
</dxlc:LayoutGroup>

Запускаем для проверки:

Создание панели собственных сделок

По аналогии с панелью инструментов создадим панель собственных сделок. В папку XAML добавляем еще один UserControl. Дадим ему имя MyTradeGridControl. В него добавим элемент MyTradeGrid:

<UserControl
	x:Class="ShellNew.XAML.MyTradeGridControl"
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
	xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
	xmlns:xaml="http://schemas.stocksharp.com/xaml"
	mc:Ignorable="d"
	d:DesignHeight="450" d:DesignWidth="800">
	<xaml:MyTradeGrid x:Name="MyTradeGrid" />
</UserControl>

В конструкторе MyTradeGridControl нам надо подписаться на события появления новой собственной сделки и передать ее в MyTradeGrid:

public MyTradeGridControl()
{
	InitializeComponent();
	MainWindow.Instance.Connector.NewMyTrade += MyTradeGrid.Trades.Add;
}

В центральную части MainWindow добавляем созданную панель OrderGridControl:

<dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs">
	<!-- центральная часть-->
	<dxlc:LayoutGroup  Header="Securities">
		<myxaml:SecurityGridControl x:Name="SecurityPanel" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Portfolios">
		<myxaml:PortfolioGridControl x:Name="PortfolioGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Orders">
		<myxaml:OrderGridControl x:Name="OrderGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="MyTrades">
		<myxaml:MyTradeGridControl x:Name="MyTradeGridControl" />
	</dxlc:LayoutGroup>
</dxlc:LayoutGroup>

Запускаем для проверки:

Создание панели со стратегией

Панель стратегий мы будем создавать так же, как и все предыдущие панели. В папку XAML добавляем еще один UserControl. Дадим ему имя StrategyControl. С помощью LayoutControl разобьём экранную форму на две части. В левой части будут вкладка с свечным графиком и вкладка статистикой стратегии:

<dxlc:LayoutGroup Orientation="Vertical">
	<dxlc:LayoutGroup View="Tabs" Name="StatistisAndChartLayoutGroup">
		<dxlc:LayoutGroup Header="Chart">
			<xaml:Chart x:Name="Chart" />
		</dxlc:LayoutGroup>
		<dxlc:LayoutGroup Header="Statistic">
			<dxlc:LayoutItem VerticalAlignment="Stretch" 								 dxlc:LayoutControl.AllowHorizontalSizing="True" >
				<xaml:StatisticParameterGrid
					x:Name="StatisticParameterGrid" MaxHeight="2000"/>
			</dxlc:LayoutItem>
			<dxlc:LayoutItem VerticalAlignment="Stretch" >
				<xaml:EquityCurveChart x:Name="EquityCurveChart" />
			</dxlc:LayoutItem>
		</dxlc:LayoutGroup>
	</dxlc:LayoutGroup>
</dxlc:LayoutGroup>

Здесь для отображения статистики стратегии использована StatisticParameterGrid, а для отображения графика прибыли и убытка – EquityCurveChart. У StatisticParameterGrid необходимо задать какое-нибудь значение MaxHeight, иначе приложение не будет запускаться.

В правой части будет проводиться настройка свойств стратегии в PropertyGridEx. А также будут расположены кнопки запуска и остановки стратегии:

<dxlc:LayoutGroup View="Group" dxlc:LayoutControl.AllowHorizontalSizing="True"
                  dxlc:DockLayoutControl.Dock="Right" Orientation="Vertical">
	<dxlc:LayoutItem VerticalAlignment="Stretch">
		<xaml:PropertyGridEx x:Name="PropertyGridEx" />
	</dxlc:LayoutItem>
	<dxlc:LayoutItem VerticalAlignment="Stretch" Height="20">
		<dx:SimpleButton x:Name="StartStrategyButton" Content="Start strategy" ToolTip="Start strategy" Click="StartStrategyButton_Click" />
	</dxlc:LayoutItem>
	<dxlc:LayoutItem VerticalAlignment="Stretch" Height="20">
		<dx:SimpleButton x:Name="StopStrategyButton" Content="Stop strategy" ToolTip="Stop strategy" Click="StopStrategyButton_Click" />
	</dxlc:LayoutItem>
</dxlc:LayoutGroup>

Полный код:

<UserControl x:Class="ShellNew.XAML.StrategyControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"
             xmlns:xaml="http://schemas.stocksharp.com/xaml"
             xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
             mc:Ignorable="d">
	<dxlc:LayoutControl>
		<dxlc:LayoutGroup Orientation="Vertical">
			<dxlc:LayoutGroup View="Tabs" Name="StatistisAndChartLayoutGroup">
				<dxlc:LayoutGroup Header="Chart">
					<xaml:Chart x:Name="Chart" />
				</dxlc:LayoutGroup>
				<dxlc:LayoutGroup Header="Statistic">
					<dxlc:LayoutItem VerticalAlignment="Stretch"
									 dxlc:LayoutControl.AllowHorizontalSizing="True" >
						<xaml:StatisticParameterGrid
							x:Name="StatisticParameterGrid" MaxHeight="2000"/>
					</dxlc:LayoutItem>
					<dxlc:LayoutItem VerticalAlignment="Stretch" >
						<xaml:EquityCurveChart x:Name="EquityCurveChart" />
					</dxlc:LayoutItem>
				</dxlc:LayoutGroup>
			</dxlc:LayoutGroup>
		</dxlc:LayoutGroup>
		<dxlc:LayoutGroup View="Group" dxlc:LayoutControl.AllowHorizontalSizing="True"
		                  dxlc:DockLayoutControl.Dock="Right" Orientation="Vertical">
			<dxlc:LayoutItem VerticalAlignment="Stretch">
				<xaml:PropertyGridEx x:Name="PropertyGridEx" />
			</dxlc:LayoutItem>
			<dxlc:LayoutItem VerticalAlignment="Stretch" Height="20">
				<dx:SimpleButton x:Name="StartStrategyButton"
								 Content="Start strategy" ToolTip="Start strategy"
				                 Click="StartStrategyButton_Click" />
			</dxlc:LayoutItem>
			<dxlc:LayoutItem VerticalAlignment="Stretch" Height="20">
				<dx:SimpleButton x:Name="StopStrategyButton"
								 Content="Stop strategy" ToolTip="Stop strategy"
				                 Click="StopStrategyButton_Click" />
			</dxlc:LayoutItem>
		</dxlc:LayoutGroup>
	</dxlc:LayoutControl>
</UserControl>

В конструкторе StrategyControl задаем Connector как источник данных для PropertyGridEx, почти в каждом контроле мы выполняли подобные действия:

public StrategyControl()
{
	InitializeComponent();
	PropertyGridEx.SecurityProvider = MainWindow.Instance.Connector;
	PropertyGridEx.Portfolios =
		new PortfolioDataSource(MainWindow.Instance.Connector);
}

Нам необходимо как-то передать стратегию в наш контрол. Для этого в StrategyControl создаем метод BindStraregy, который будет принимать стратегию, сохранять ссылку на нее в локальной переменной, а также задавать стратегию в PropertyGridEx и StatisticParameterGrid.

С помощью метода SetChart в стратегию предаём график свечей Chart, после этого в стратегии Chart можно будет получить с помощью метода GetChart. Также задаем Connector для стратегии.

private Strategy _strategy;
public void BindStraregy(Strategy strategy)
{
	_strategy = strategy;
	PropertyGridEx.SelectedObject = strategy;
	StatisticParameterGrid.Parameters.
	AddRange(_strategy.StatisticManager.Parameters);
	_strategy.SetChart(Chart);
	_strategy.Connector = MainWindow.Instance.Connector;
} 

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

После чего подпишемся на событие изменения PnL у стратегии и в обработчике этого события отрисовываем новое значение на графике прибыли/убытков EquityCurveChart:

private void ResetEquityCurveChart()
{
	EquityCurveChart.Clear();
	var pnl = EquityCurveChart.
		CreateCurve("PNL", Colors.Green, ChartIndicatorDrawStyles.Area);
	var unrealizedPnL = EquityCurveChart.
		CreateCurve("unrealizedPnL", Colors.Black, ChartIndicatorDrawStyles.Line);
	var commissionCurve = EquityCurveChart
		.CreateCurve("commissionCurve", Colors.Red, ChartIndicatorDrawStyles.Line);
	_strategy.PnLChanged += () =>
	{
		var data = new ChartDrawData();
		data.Group(_strategy.CurrentTime)
			.Add(pnl, _strategy.PnL)
			.Add(unrealizedPnL, _strategy.PnLManager.UnrealizedPnL ?? 0)
			.Add(commissionCurve, _strategy.Commission ?? 0);
		EquityCurveChart.Draw(data);
	};
}

В обработчике события нажатия на кнопку Старт будем вызвать этот метод. А также будем сбрасывать состояние стратегии и запускать ее:

private void StartStrategyButton_Click(object sender, RoutedEventArgs e)
{
	ResetEquityCurveChart();
	_strategy.Reset();
	_strategy.Start();
}

В обработчике события нажатия на кнопку Стоп будем останавливать стратегию.
private void StopStrategyButton_Click(object sender, RoutedEventArgs e):

{
	_strategy.Stop();
}

В центральную части MainWindow добавляем созданную панель StrategyControl:

<dxlc:LayoutGroup HorizontalAlignment="Stretch" View="Tabs">
	<!-- центральная часть-->
	<dxlc:LayoutGroup  Header="Securities">
		<myxaml:SecurityGridControl x:Name="SecurityPanel" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Portfolios">
		<myxaml:PortfolioGridControl x:Name="PortfolioGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="Orders">
		<myxaml:OrderGridControl x:Name="OrderGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="MyTrades">
		<myxaml:MyTradeGridControl x:Name="MyTradeGridControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="MarketDepth">
		<myxaml:MarketDepthControl x:Name="MarketDepthControl" />
	</dxlc:LayoutGroup>
	<dxlc:LayoutGroup  Header="SimpleStrategyControl">
		<myxaml:StrategyControl x:Name="SimpleStrategyControl" />
	</dxlc:LayoutGroup>
</dxlc:LayoutGroup>

Создание стратегии

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

Создадим еще одну папку в проекте – в ней будем хранить все наши стратегии. В этой папке создаем новый класс, назовем его SimpleStrategy. Все стратегии S# должны наследоваться от базового класса стратегии Strategy.

public class SimpleStrategy : Strategy	{}

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

public class SimpleStrategy : Strategy
{
	public CandleSeries Series { get; set; }
	public SimpleStrategy()
	{
		Series = new CandleSeries(typeof(TimeFrameCandle), new Security(), TimeSpan.FromSeconds(15))
		{
			BuildCandlesMode = MarketDataBuildModes.Build
		};
	}
}

Здесь мы указали, что свечи в CandleSeries будут TimeFrameCandle, с интервалом 15 секунд (TimeSpan.FromSeconds(15)). Для CandleSeries можно указать режим создания свечей BuildCandlesMode. Мы указали, что свечи будут построены (MarketDataBuildModes.Build). По умолчанию они будут строиться из тиков, но можно указать и другие типы данных.

Так как CandleSeries мы сделали публичным свойством, то CandleSeries можно будет дополнительно настроить из PropertyGridEx описанном в предыдущем пункте. Все стратегии имеют методы который можно переопределить, нам понадобиться переопределить метод OnStarted. Он вызывается перед запуском стратегии и позволяет предварительно задать ей стартовое состояние.

protected override void OnStarted()
{
	_connector = (Connector)Connector;
	Series.Security = Security;
	_connector
		.WhenCandlesFinished(Series)
		.Do(ProcessCandle)
		.Apply(this);
	_connector.SubscribeCandles(Series);
	base.OnStarted();
}

Здесь мы для CandleSeries задаем инструмент, который указывается в PropertyGridEx. После чего создаем правило обработки законченной свечи. В правиле указываем метод, который будет обрабатывать каждую законченную свечу – в нашем случае это метод ProcessCandle. Он будет описан позже. После того, как все задано, подписываемся на появление свечей по CandleSeries в коннекторе через метод SubscribeCandles. В нашем случае метод ProcessCandle и содержит основную логику стратегии:

private void ProcessCandle(Candle candle)
{
	if (!IsRealTime(candle)) return;
	if (candle.OpenPrice < candle.ClosePrice && Position <= 0)
	{
		RegisterOrder(this.BuyAtMarket(Volume + Math.Abs(Position)));
	}
	else
	if (candle.OpenPrice > candle.ClosePrice && Position >= 0)
	{
		RegisterOrder(this.SellAtMarket(Volume + Math.Abs(Position)));
	}
}

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

private bool IsRealTime(Candle candle)
{
	return (Connector.CurrentTime - candle.CloseTime).TotalSeconds < 10;
}

Далее смотрим на то, какая это свеча, и какая текущая позиция у стратегии. Если свеча растущая, то при позиции равной 0 мы откроем позицию рыночной заявкой на объём, заданный нами в PropertyGridEx. Если свеча растущая и позиция меньше 0, то мы «переворачиваем» позицию:

if (candle.OpenPrice < candle.ClosePrice && Position <= 0)
{
	RegisterOrder(this.BuyAtMarket(Volume + Math.Abs(Position)));
}

Противоположные действия делаем для убывающей свечи:

else
if (candle.OpenPrice > candle.ClosePrice && Position >= 0)
{
	RegisterOrder(this.SellAtMarket(Volume + Math.Abs(Position)));
}

На данный момент наша стратегия готова к работе. Ее необходимо передать в SimpleStrategyControl, который мы создали в предыдущем пункте с помощью метода BindStraregy. Это мы делаем в конструкторе MainWindow сразу после инициализации компонентов MainWindow.

SimpleStrategyControl.BindStraregy(new SimpleStrategy());

Запустим для проверки:

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

Добавление свечей и сделок на график из стратегии

В пункте про панель стратегий с помощь метода SetChart в стратегию мы предали график свечей Chart. В методе OnStarted стратегии проверяем установлен ли График у стратегии и если он установлен, то инициализируем график, а также подписываемся на события появления новой собственной сделки и изменения свечи.

protected override void OnStarted()
{
	_connector = (Connector)Connector;
	if (this.GetChart() is Chart chart)
	{
		InitChart(chart);
		NewMyTrade += DrawMyTrade;
		_connector.CandleSeriesProcessing +=
			CandleSeriesProcessing;
	}
	Series.Security = Security;
	_connector
		.WhenCandlesFinished(Series)
		.Do(ProcessCandle)
		.Apply(this);
	_connector.SubscribeCandles(Series);
	base.OnStarted();
		}

Метод инициализации графика InitChart:

private ChartCandleElement _chartCandleElement;
private ChartTradeElement _tradesElem;
private Chart _chart;
private void InitChart(Chart chart)
{
	_chart = chart;
	_chart.GuiSync(() =>
	{
		_chart.ClearAreas();
		var candlesArea = new ChartArea();
		_chart.AddArea(candlesArea);
		_chartCandleElement = new ChartCandleElement();
		_chart.AddElement(candlesArea, _chartCandleElement);
		_tradesElem = new ChartTradeElement { FullTitle = "Trade" };
		_chart.AddElement(candlesArea, _tradesElem);
	});
}

Здесь мы сохраняем ссылку на Сhart в локальной переменной. Очищаем график. Также создаем и передаем на график элементы графика для свечей и сделок. Конструкция _chart.GuiSync(() =>{… }); нужна для того чтобы инициализация графика выполнилась в главном потоке.

Метод отрисовки свечей на графике CandleSeriesProcessing:

private void CandleSeriesProcessing(CandleSeries candleSeries,
	Candle candle)
{
	var data = new ChartDrawData();
	data.Group(candle.OpenTime)
		.Add(_chartCandleElement, candle);
_chart.Draw(data);
}

Здесь мы получаем свечу из события CandleSeriesProcessing коннектора, создаем ChartDrawData для отображения его на графике. Указываем время data.Group(candle.OpenTime), указываем что свечу надо добавить в свечной элемент графика .Add(_chartCandleElement, candle);. И указываем что графику надо прорисовать новые данные.

Аналогичные действия выполняем для сделок:

public void DrawMyTrade(MyTrade myTrade)
{
	var data = new ChartDrawData();
	data.Group(myTrade.Trade.Time)
		.Add(_tradesElem, myTrade);
	_chart.Draw(data);
}

Запустим для проверки:

Краткий вывод

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

Автор: Иван Залуцкий

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

Source: habr1

Метки:





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

Виртуальная память в ARMv7

Здравствуйте!

В статье обзорно описана система виртуальной памяти архитектуры ARMv7.

Заголовок спойлера

Здесь не рассмотрены тонкости кэширования, DMA, LPAE и подобное. За более подробным описанием можно обратиться к литературе в конце статьи.

Введение

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

Определения

Далее в статье используются следующие определения:
Виртуальный адрес — адрес, используемый ядром процессора. Указатель стека, счетчик команд, регистр возврата используют виртуальный адрес.
Физический адрес — выходной адрес на шине процессора.
Страница — единица адресации виртуальной памяти.
Секция — аналог страницы, имеет больший размер.
Фрейм — единица адресации физической памяти.
Таблица страниц — массив записей для трансляции адресов.
ASID — идентификатор адресного пространства.
TLB — буфер быстрой трансляции адресов.
MMU — блок управления памятью.

TLB

TLB — это очень быстрый аппаратный буфер, содержащий в себе результаты последних трансляций адресов. Запрос ядра на трансляцию адреса страницы и текущий ASID поступает в TLB. Если там есть валидная запись, то проверяется разрешения на доступ к этой памяти, способ доступа и соответствующий адрес фрейма возвращается в блок MMU. Если доступ к памяти запрещен, то генерируется аппаратное исключение. Если произошел TLB miss(записи не нашлось), то дальнейшее поведение зависит от регистра TTBCR. Может быть выполнен поиск в таблицах страниц или сгенерировано исключение.

Важно отметить, что при манипуляциях с таблицами страниц необходимо корректно сбрасывать TLB, т.к. там может сохраниться неактуальная информация.

Обновление записей в TLB происходит прозрачно для программиста по алгоритму round-robin.
Так же есть возможность загрузить и закрепить некоторые записи в TLB для предотвращения их вытеснения.

image
Рис 1. TLB

Таблицы страниц

ARMv7 — 32-битная архитектура, поэтому нам доступно 4ГБ адресуемой виртуальной памяти.
Таблицы страниц разделены на 2 уровня — L1 и L2.

Таблица L1 описывает все 4Гб адресного пространства. Она состоит из 4096 записей длиной 32бит, каждая из которых описывает 1Мб. Записи в таблице выбираются старшими 12 битами виртуального адреса.

image
Рис. 2 Поиск записи в таблице L1

Таблица L1 расположена в физической памяти и выровнена на границу 16Кб. Есть 4 варианта этих записей: для описания страниц, секций и суперсекций. Ну и пустая запись, для памяти, которая еще не замаплена.

image
Рис. 3 Типы записей в L1

Биты 0 и 1 указывают на тип записи 00b-Fault, 01b — описатель страниц, 10b — описатель секций (и суперсекций).

Если физическая память разбивается на страницы, то в таблице L1 хранится адрес таблицы L2(физический, выровненный на 1Кб). Бит 9 определяется производителем(Implementation defined), биты [8:5] — для механизма доменов(Deprecated в ARMv7),SBZ — нули.

Если мы решим разбить память на секции, то в L1 необходимо записать соответствующий физический адрес. Секция напрямую ссылается на выровненную область физической памяти в 1Мб. Нет необходимости в таблице L2. Суперсекция это частный случай разбиения на секции, запись в L1 таблице должна повториться 16 раз, выравнивание выделенных блоков физической и виртуальной памяти так же 16Мб.

Таблица L2 состоит из 256 записей по 32бит. Она должна быть выровнена на 1Кб.

image
Рис. 4 Поиск записи в таблице L2

Индексы в таблице L2 формируются из средних 8 бит [19:12] виртуального адреса. Каждая запись таблицы содержит адрес фрейма.

image
Рис. 5 Типы записей в L2

Страницы могут быть двух размеров: 64Кб(Large page) и 4Кб(Small page).
Биты AP и APX устанавливают разрешения на чтение/запись в привилегированном/непривилегированном режиме (kernel/user). Биты TEX, C, B, S отвечают за тип памяти, ее кэширование и буферизацию чтения-записи. Бит nG — nonGlobal разрешает доступ к странице для всех процессов или же только для одного конкретного ASID’a.

Использование больших страниц позволяет сократить количество записей в TLB. Вместо 16 записей (4Кб*16=64Кб), там будет храниться всего одна. Однако в таблицу L2 надо внести 16 одинаковых записей.

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

Регистры

Для управления системой(в т.ч. блоком MMU) в архитектуре ARM предназначен специальный сопроцессор CP15. К управлению памятью относятся полтора десятка его регистов. Нас интересуют несколько из них — Control, TTBR0/1, TTBCR, ContextID.

В регистре Control младший бит отвечает за вкл/выкл MMU, все просто.

Пара регистров TTBR0/1 содержат физические адреса таблиц первого уровня. По этим адресам блок MMU начинает поиск нужной страницы.

Регистр TTBCR позволяет поделить всё адресное пространство на 2 части между TTBR0 и TTBR1. Каждый из них будет транслировать свою часть адресов. Для задания размера используются биты [2:0]. Записаное число (от 0 до 7 десятичных) маскирует старшую часть виртуальных адресов. Если его значение «0» — все адреса транслируются через TTBR0. Если «1» — маскируется 31бит адреса и нижние 2Гб виртуального пространства проходят через TTBR0, верхние — через TTBR1. «2» — маскируются 31 и 30бит и получается деление на 1Гб и 3Гб соответственно. Таким образом, нижнюю часть адресов можно использовать для пользовательских приложений, перегружая регистр TTBR0 для нового процесса, а верхнюю часть оставить для системных нужд.

image
Рис. 6 Разделение адресного пространства

Биты [5:4] отвечают за поведение при TLB miss — поиск в таблицах страниц или исключение.
Регистр ContextID содержит поле ASID для текущего процесса. Его нужно менять совместно с содержимым регистра TTBR0 при смене контекста.

Address Translation

Алгоритм преобразования виртуальных адресов в физический следующий:

  • Поиск запрошенного виртуального адреса и ASID в буфере TLB
  • Если в TLB нет необходимого адреса, то происходит аппаратный поиск в таблицах страниц

Если ранее ядро уже запрашивало виртуальную страницу, то она сохраняется в TLB. В этом случае блок MMU достает ее из кэша и не требуется ничего делать. Если же страница запрашивается первый раз(или ее вытеснили оттуда — TLB не очень большой), то просходит поиск в таблицах L1-L2. Таким образом сопоставление виртуального и физического адреса происходит следующим образом:

  • В регистре TTBR0TTBR1 ищется адрес таблицы L1.
  • Старшие 10 бит виртуального адреса образуют индекс в таблице.
  • а)Если запись соответствует секции(суперсекции), то проверяются атрибуты секции и, если все Ок, результирующий физический адрес составляется из базового адреса секции(суперсекции) и младших 20(24) бит виртуального адреса.
    Заголовок спойлера

    image
    Рис. 7 Трансляция адресов в суперсекции

    б)Если запись это таблица L2, то поиск продолжается в ней. Средняя часть виртуального адреса страницы образует индекс таблицы.

    Заголовок спойлера

    image
    Рис. 8 Трансляция адресов в таблице L2

  • Происходит обновление TLB

Итого, подсистема виртуальной памяти состоит из следующих частей:

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

Литература

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
ARM Cortex-A Series Programmer’s Guide

Теги:

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

Source: habr1

Метки:





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

Сбор требований к программному проекту — без купюр

Компания

Сбор требований к программному проекту — без купюр

Разработка… она как наркотик — систему пишут, пишут, ведь «прет» же. А потом, вдруг оказывается — «алименты» нужно платить. А любое изменение системы влечет гору ошибок. А ведь еще в начале прошлого века великий Курт Гёдель предвидел это и строго доказал, что даже в арифметике у нас не хватает ума, чтобы выразить все ее законы без противоречий. А в программировании и подавно — мы начнем наступать себе на ноги и запутываться. Что, в общем-то, и происходит: то ноутбук ночью включается и перезагружается, то мобильные приложения сыпят ошибками так, что они из кармана начинают выпадать и разбегаться, бранясь и попискивая, по полу.

А как вам модные нынче бета-версии всего и вся? Cкоро самолеты начнут выходить в альфа-бета версиях, похоже.

Но ведь можно же программировать без ошибок, чтобы душа радовалась и пиво попить с клиентом было не только приятно, но и безопасно!

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

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

За примерами далеко ходить не нужно — модели открытой разработки и их успешность (не обязательно некоммерческие) убедительно показывают:

  • ясность, открытость, смелость
  • обсуждение с сообществом и клиентом
  • быстрое выявление и решение проблем

а также максимально справедливые коммуникации, основанные на доверии и уважении друг ко другу — ведут программное решение, например, веб-сайт, к успеху.

Мир активно меняется. Горизонтальные коммуникации происходят со скоростью света и если мы не научимся использовать это новое оружие — точно проиграем. Но вначале немного оглянемся вокруг.

Откуда же взялась «священные войны» в программировании?

Все просто. Достаточно вспомнить школьный курс геометрии. Научное понимание мира, в котором мы живем, базируется на… вере в «непреложные истины» = аксиомы, например в то, что «параллельные прямые не пересекаются» или в количество простых чисел в диапазоне (хотя это, правда, теорема, но она, собака, работает, но никто не понимает почему).

Доказать аксиому — невозможно, остается только верить, что она работает всегда. А слетать к горизонту событий Черной Дыры и проверить — мы пока не можем. И объяснить, почему между фотонами взаимодействие передается гораздо быстрее скорости света, тоже.

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

Даже в, казалось бы, ну что может быть проще, арифметике, неоднократно принимались попытки привести аксиомы в порядок — но воз и ныне там…

Аналогично, языки программирования и технологии, на которых мы с вами создаем веб-сайты, мобильные приложения и информационные системы, по сути, также представляют собой набор аксиом или точек отсчета, в которые также нужно сначала «поверить» и на которых строится фундамент технологии, но доказать, что они верные — нельзя (хотя, иногда, все же можно: попробуйте написать веб-сайт на C++ и увидите, сколько потеряете времени и денег).
Например, в мире Java/C# и других авторитетных и солидных, современных, строго типизированных языках со статической типизацией нужно только один раз взять и «поверить», что мир состоит из психопатов, склонных к насилию и потери самоидентификации, и поэтому «набор аксиом» делает все, чтобы защитить разработчика не только от коллег, но и от него же самого (конечно, я шучу).

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

В мире динамических языков со строгой/нестрогой типизацией (PHP, JavaScript, Python, Ruby) набор аксиом совершенно, от слова «совсем», другой:

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

В мире функциональных языков, типа Haskell/OCaml, требуется поверить в то, что:

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

В результате, вместо простых скриптов-костылей «сделал, проверил, решил и забыл» на рабочем месте начинается настоящая научная деятельность и поиски «функции Бога» — очень ведь интересно выразить веб-сайт… набором функций без переменных, вау!

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

«Крестовые походы» в управлении программными проектами

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

  • понять, чего хочет клиент
  • привлечь специалистов и оценить объем работ
  • написать код

в реальности, почему-то, не работает 🙂

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

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

Злоупотребления, обычно, активно эксплуатируются очень уверенными в себе людьми, умеющими хорошо убеждать, которые никогда в руках «кода» не держали (да, я про неправильно приготовленный Agile).

Говорят, в некоторых командах перед спринтом даже, особо ярые поклонники, принуждают нас, инженеров, к, простите, уринотерапии 🙂 Однако сами эти «практики», нередко создаются очень опытными разработчиками, которые, как никто другой, могут ими правильно пользоваться.

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

Еще один миф — взаимозаменяемость

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

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

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

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

Что же делать? Рекомендуемые ценности для выживания

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

Играли раньше в онлайн-игры и хорошо получалось — вот и продолжайте, только вместо боссов у вас будут программные проекты, а вместо багов — зерги!

Всегда можно и нужно трезво управлять рискам и, по опыту, если делать «системно и научно», программный проект либо взлетит в оговоренные сроки, либо быстро станет понятно, почему ракета не заводится и в чем/ком, конкретно, проблема.

С учетом вышесказанного рекомендуется как можно раньше начать придерживаться нижеперечисленных ценностей близко-научно-эмпирического подхода, которые тесно пересекаются с широко известным гимном здравому смыслу — «дзеном питона» и «agile-манифестом«:

  1. Искать самое простое и ясное решение
  2. Чем яснее, тем правильнее
  3. Стало сложно — значит где-то косяк и нужно продолжать дальше искать
  4. Высокоумие — от неуверенности или трудного детства
  5. Способности человеческого мозга — ограничены, особенно под действием гормонов, а в некоторые периоды даже слишком
  6. От алкоголя и курения — мы интенсивно тупеем
  7. Мы — склонны быстро забывать даже то, в чем хорошо разбирались и даже совсем недавно
  8. Стремиться к максимальной прозрачности и открытости
  9. Уважать друг друга
  10. Поощрять максимально быстрое всплытие и обсуждение проблем в как можно более широком кругу — идеально сразу во всеми
  11. Делать выводы и не наступать на грабли 3.14 раза подряд 🙂

Рекомендации по сбору требований

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

Способен ли заказчик — думать в принципе?

Ничего смешного — вполне таки штатная ситуация. Да и заказчик в этом контексте — понятие собирательное. Прежде всего постарайтесь оценить уровень логического мышления и способности концентрироваться представителей клиента. С кем вы собираетесь работать и кто вам будет помогать? Возможные варианты:

  1. Политическая тусовка. Нужно сделать, к примеру, веб-проект к дате потому-что кто-то чего-то хочет/обещал… Требования размыты, детали не знает никто, а кто знал — давно уволится. Проект пилила команда, которая ушла и понять, что они напилили — практически невозможно. На стенах — высохшие мозги от, возможно, суицида ведущего программиста. Код — плохой и хрупкий, пахнет так, что глаза режет. Часто в такой ситуации пытаются найти, простите, «сакральную жертву», на которую можно будет свалить следующие полгода и… начать искать новую. Ощущение страха, депресняка и подавления открытости процесса с примесью крови на губах. Вероятность вовремя сделать программное решение, правда небольшая, тут все таки имеется — если делать заново на готовом фреймворке с готовой документацией. Обычно только так и никак иначе.
  2. Вы общаетесь с представителями клиента и понимаете, что людям искренне трудно непротиворечиво/формально излагать собственные мысли, которые путаются после третьего предложения, повторяются и ходят по кругу. Через 15 минут диалога начинаются жалобы на головную боль. Слышится смех, атмосфера тусовки, селфи, жизнь удалась… Но желания, в целом, понятны и искренние — нужно просто чуточку помочь их оформить строго. Вероятность взлететь тут обычно повыше, чем в п.1, но опять таки, обычно помогает использование как можно более готового, коробочного решения с готовой документацией и типовыми сценариями.
  3. Клиент хорошо понимает, чего хочет и пытается логически непротиворечиво излагать собственные мысли и желания. В этом ему помогает аналитик, который не путается, излагая мысли менеджмента и выдавая их за свои. В команде клиента также есть минимум один эксперт в его предметной области (забавно, но это довольно таки редкая ситуация). В этом случае вероятность помочь и программно решить задачу — весьма высока. Тут можно ввязываться в проектирование, совместное обсуждение глоссария, модели объектов, модели данных, потоков данных, сценариев нагрузочного тестирования. Скорее всего собрать требования вы сможете и в разумные сроки.

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

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

Тревожные сигналы, которые будут свидетельствовать о надвигающихся проблемах в сборе требований:

  • представители заказчика переводят «стрелки» друг на друга и не могут двух слов связать, при этом очень много эмоций — тут рекомендуется как можно быстрее эскалировать проблему и выходить на уровень выше — иначе вас, как «сакральную жертву», принесут в дар культу бардака и выхода на пенсию/в декрет. Работать в таких условиях по Agile — крайне опасно, лучше писать строгое ТЗ и двигаться небольшими этапами
  • представители клиента отвечают в стиле: ой, голова болит, а ты же умный, «программист», вот и разбирайся. Тут нужно требовать найти эксперта в предметной области, несущего ответственность за ответы от лица заказчика и как можно быстрее. Или см. пункт выше.
  • о проблемах (нечитаемый код, отсутствие документации к основным бизнес-процессам) предпочитают не говорить, т.к. деньги были потрачены, должности получены, премии озвучены и проговаривание рисков может привести к интенсивной прочистке кадрового состава (все же все «понимают», а тут инженеры бочку катят) — тут сложно дать совет, действуйте по фактической погоде

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

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

  • веб-сайт на PHP с фреймворком, коробочным решением
  • предиктивная аналитика на Python
  • мобильное приложение либо на единой платформе, работающей везде, либо пишем под каждое устройство

Не тяните время!

Если 2-3 недели, в крайнем случае месяц-полтора, не проходит ощущение, что вы участвуете в спектакле «поболтаем с умными видом и потянем время и свалим все на кого-нибудь», дергайте стоп-кран, поджигайте поезд и громко кричите в рупор: «расходимся по домам, дети! представление окончено».

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

Чеклист

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

  1. Глоссарий, в котором перечислены 50-150 терминов предметной области
  2. Логическая модель данных со связями терминов из глоссария
  3. Сценарии использования с терминами из глоссария
  4. Для сложных алгоритмов — блок-схемы или диаграммы активности UML
  5. Интерфейсы программной системы, логически не противоречащие вышеперечисленным пунктам
  6. Вы определились с набором аксиом, описывающих ваше отношение к миру = выбрали программную технологию. Тут многих, по причине любви к творчеству, тянет к садо-мазохизму и желанию заново изобрести велосипеды — боритесь с этим желанием. Определитесь: или весь мир полон подвохов и психопатов и делаем бункер, выдерживающий атаку НЛО, или разработчики искренне хотят вам помочь. Лучшая технология и набор аксиом: развитый фреймворк или готовое коробочное решение — риски не взлететь снизятся на порядки (по опыту, взлетает 95% и выше проектов)
  7. Вы пропустили программную систему через заказчика, себя, через свой мозг и нигде не осталось мутных мест или эмоциональной жижи. Если такие потенциально протухающие места имеются (а это, как правило, происходит всегда) — включите их в план управления рисками и озвучивайте на каждом проектном совещании. И ждите, что вас подставят и обязательно спросят, как же вы это пропустили

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

Для достижения настоящего успеха очень, очень важно по-настоящему любить программные системы, отдаваться сбору требований и проектированию на полную катушку, желать ракетам скорейшего старта, пить пиво с заказчиком, доверять друг другу и постоянно повторять про себя слова Эдсгера Дейкстры: «простота — залог надежности»!

С Наступающим всех и искренне желаю удачи в реализации программных проектов.

Теги:

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

Source: habr1

Метки: