понедельник, 5 августа 2013 г.

В тюрьму из-за ошибки в программе?

BBC сообщило о том, что несколько из частных сотрудников (подрядчиков, почтмейстеров) почты UK были отправлены в тюрьму из-за ошибки в программном обеспечении (ПО), которое занимается их бухгалтерией. Причина — дефект в центральной компьютерной системе Horizon. Ранее известен опыт многих ошибок, из-за которых погибали люди, но как много из нас рассматривало ситуацию, что из-за ошибки в обычном ПО может так сказаться на каждом из нас?

Почта UK, работающая с ~11500 отделениями, в которых задействовано ~68000 сотрудников, по результатам ожесточенного спора с некоторыми из них признала то, что имеется дефект в её центральной системе. Более сотни людей говорили о том, что их преследовали по ошибке в судебном порядке для того, чтобы они выплатили деньги за то, что компьютер выполнил несуществующие транзакции. Часть из них потеряла репутацию, а несколько из них попало по этой причине в тюрьму.

В течение последнего года независимые расследователи, которые были наняты Почтой UK, проверяли несколько претензий от сотрудников. Несмотря на то, что они не нашли свидетельств систематических проблем в ядре ПО, они нашли баги (программные ошибки) в нем. Но вместе с этим было отмечено два проишествия в 2011 и 2012 годах, когда сам почтампт идентифицировал сбои (и полагаю, исправлял баланс) на сумму 9000 фунтов в 76 разных узлах.

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

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

Картина из новости №1: Jo Hamilton по итогам недели рассчитал, что должен оплатить 2000 фунтов по обороту. Звонит в офис, а ему говорят, что вы должны 4000. После выяснения оплачивает, и тут оказывается, что он должен уже 9000!

Картина из новости №2: один из сотрудников проработал на королевскую почту 40 лет, а сейчас ему 60 и он празднует свой день рождения за решеткой.

Независимые расследования продолжаются, а народ требует справедливости.


воскресенье, 4 августа 2013 г.

Fatal Defect & Computer Related Risks

Читаю сейчас книги Fatal Defect и Computer Related Risks. Сначала планировал по отдельности, но придется читать вместе.

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

Книги написаны в одно время и на одну тему, и, более того, основаны на очень похожем материале. Однако внутри имеют разные приближения к одной и той же проблематике. Computer Related Risks — весьма научная, где изложено все по полочкам и темам, по большей части сухая статистическая информация и тематический и факторный анализ. Fatal Defect — напротив, это книга для рядового читателя, где рассказывается множество различных случаев и историй, а сама книга читается как детектив и является хорошим кандидатом на то, чтобы вдохновить людей в или на данную область (Safety-Critical Systems).

Источники для книг основаны в первую очередь на Computer Risks Forum — это онлайновый ресурс, действующий с 1985 года. Его назначение — оповещение и обсуждение любых проблем, связанных с компьютерными рисками, но в первую очередь фокус ставится на больших системах автоматизации процессов, на системах, проблемы в которых могут приводить к большим экономическим потерям и угрожать здоровью и жизни людей. C самого начала существования форума его модератором является активист Peter G. Neumann (Harvard ph.D., длительное время работал в Bell Labs и ACM), занимающийся им в свое свободное время, — он же автор второй книги на моей картинке.

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

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

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


суббота, 3 августа 2013 г.

ПМО ИУС — Разное

Здесь две разные, последние темы, которые не вошли в предыдущие.

Разные 10 лет

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

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

В связи с этим за все время все изложение и построение предмета изменялось от фокуcа на всех (должен быть какой-то минимум, он должен быть сделан и сдан, правила одинаковые для всех) к фокусу на отдельных студентах, когда информация дается как есть, без каких-либо жестких требований и указаний, а за первые занятия выделяются те студенты, которые проявляют интерес или являются по крайней мере сознательными. Таких на потоке получалось порядка 10-20%, а на лабораторных где-то 2-3 на группу-подгруппу. Соответственно на занятиях я уделял уже большую часть времени в общении с ними, а остальная часть потока проходила по линии наименьшего сопротивления мимо ПМО ИУС.

В начале для сдачи финального зачета была собрана достаточно жесткая для двоешников и списывателей схема. Во-первых, объявлялось, что своими конспектами можно пользоваться на зачёте несколько минут. Т.е. конспект должен быть свой и это может значительно помочь — формировалась обратная связь что конспект нужно писать. На зачете конспектом можно пользоваться, но только 1 раз (Read Only, без переписывания) — идея взята у Буя М.. Факт наличия своего проверялся совпаданием почерка в ответе на зачет и почерка конспекта. Во-вторых, схема зачета взята с приемных тестов абитуриентов. 10 человек сдают, больше никого, все вещи лежат отдельно, на столе у каждого только билет, бумага и ручка. Малое кол-во людей легко контролируется. В-третьих, принимается только то, что написано. Потому как устно что-то доказывать бесполезно. В-четвертых, время на зачет полчаса, что быстро. Плюс условие — по вопросам и задаче должно быть что-то написано, не обязательно все правильно, не обязательно много, но если человек разбирался и готовился, он должен хоть что-то написать. Т.е. требования были здесь низкие. Именно эта форма зачета сразу стала страшной для всех — т.е. когда все было сделано против списываний, а порог прохождения минимизирован, но по всем темам.

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

Ещё в самом начале я отмечал посещение на каждой паре всех студентов. Сначала это было по журналам, потом группами. Потому, что декан требовал отмечать и вообще отмечать — это правильно. Но в дальнейшем я полностью забил на отмечание (но об этом никому не говорил). На вопрос декана «вы отмечаете?» говорил «старосты отмечают». В начале (тотальное отмечание) посещали все, и выбор между вариантами преподавания был либо все пишем в тишине, либо говорим, ни никто меня не слышит. В последние годы получался другой эффект. Первые лекции тихие потому что они первые, а в дальнейшем студенты сами понимают, что не отмечают, и кому не интересно или те, кто не сознательные, на пару просто не приходят. Где-то к 3-4 лекции из ~120 человек оставалось ~30, из которых слушала только половина, чего мне было достаточно. Пока не зашел декан, поругал тех, кто отсутствует и пообещал выговор старостам, которые тоже отсутствовали (;

Мое положение изменялось и отличалось от других преподавателей тем, что с 2006-2007 года я начал работать в «Интервэйле». Это означало, что в первые годы мне декан прямым текстом говорил, что «либо вы выпускаете N-х студентов, либо мы вам перестаем платить зарплату», а на факультет приходили кандидатуры мне на замену. После этого рубежа что-то изменилось — пугать увольнением стало бесполезно и даже череповато, но и с другой стороны, времени и сил бороться с системой у меня уже было меньше, постепенно приближаясь к нулю. Ситуация такая, что верхи не могут, а низы не хотят. Университет не может отчислять студентов, потому что каждый студент — это $ в казну ВУЗа (минус платник, а минус бюджет означает что один из платников станет бюджетником), и этот блок стоит на уровне ректора. Хотя думаю ещё один блок стоит выше — так как «каждый гражданин РБ имеет право на высшее образование». Кроме того, уменьшение числа студентов на факультете означает, что у декана заберут зама и дадут нагрузку на кафедре. Второе: грубо говоря, студентам невозможно оценить качество материала и уровень преподавания по определению (образно говоря это ключевые последние технологии или русские народные сказки) — содержание курса мог сократить раза в 2, никто бы ничего не заметил. Кроме того, по моему впечатлению, студенты приходят учиться в ВУЗ как в школу — посещение и движение по линии наименьшего сопротивления. Третье: сотрудникам ВЦ все равно, как идет обучение, главное чтобы на них это никак не отражалось. 90% софта, который ставился на ВЦ для ПМО ИУС, ставился лично мной во всех аудиториях. Любое обновление — бумагу, только летом, ставь сам, и делай в выходные в свое личное время. Четвертое: Социального заказа со стороны «Интервэйла» или любых других организаций ни разу не слышал, хотя можно было часть содержимого курса перенаправить в конкретно ориентированную сторону. Последнее: качество содержания курса имело значение только для двух людей — преподавателя (как ответственность за то, что преподается) и зав. кафедры (потому что потом необученные студенты приходят писать диплом и лучше, чтобы они что-то знали).

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

Пару лет мы пытались использовать систему тестирования, когда сдача л.р. проходила методом ответов на определенный тест (5 вопросов случайных, 4 правильно — сдано). От этой практики отказался, так как студенты на занятиях гоняли тесты, тратили время на это вместо того, чтобы программировать и разбираться в предмете, а также учились отвечать на вопросы, а не понимать их смысл.

С точки зрения написания лабораторных работ и отбработки практических навыков также было несколько разных форм реализаций. Сначала — теория и готовые примеры. Как результат — студенты теряли значительную часть теории (так как она напрямую не связана конкретными действиями с практикой), а примеры копировали и немного изменяя под себя. как показала практика, копипаст не способствует обучению, — он очень близок к тому, когда за студента делает кто-то, или к тому, когда необходимо самому сделать re-engineering (понять почему в примере сделано именно так и что означают эти конструкции). Следующим шагом было предоставление видео по л.р., когда можно видеть как собирается работа и смотреть комментарии к действиям. Это оказалось гораздо эффективнее, однако тут две проблемы — с видео надо переписывать (много времени и мало смысла), плюс видео надо смотреть (его нельзя быстро просмотреть или быстро найти что-то). Последним самым эффективным вариантом было изложение примера step-by-step. Лаборатоная работа разбивалась на пару десятков шагов, каждый из которых описывался словами (что делаем, почему, особенности) и примером текстового кода, который изменялся, и каждая итерация должна была быть осмысленной и компилируемой в итоге. Т.е. на каждом шаге можно было понимать и усваивать малый кусочек материала, сразу видеть результат работы и в случае ошибок быстро их найти.

Система выдачи автоматов также постоянно изменялась. Это был проходной балл (предел), определенное кол-во работ, сданных вовремя, верхняя треть списка и др.. Автоматы хороши в случае, когда надо стимулировать массы, но в последнем варианте я сосредотачивался на отдельных людях, и вся система стимулирования всех просто отключилась. У меня в последние годы вообще пропало желание кого-то что-то заставлять делать или учить. Если есть желание — добро пожаловать, всегда и всего помногу. Иначе смысла нет.

Смайлики

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

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

Пример последней из таблицы рекордов: общая(+группы) и запасная ссылки.

По завершению каждого занятия преподаватель заходил на сервер через web-интерфейс и отмечал птицами кто что сдал (работа и отчет). Если работа сдавалась вовремя, то система давала одно кол-во баллов, если не во-время, то поменьше. Кроме того, преподаватель отмечал тех, кто отсутствовал на паре; тех, кто отрабатывал занятия; тех, кто был инициативным (по мнению преподавателя), и тех кто плохо себя проявил (опоздал на занятие например). На основании этой информации формировалось все остальное. Система контролировала выдачу заданий (не более 2-х несданных работ в одни руки), строила таблицы рекордов, формировала список автоматов и рассчитывала оценки контрольных сроков.

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

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

Данное положение изменялось, и это изменение за последнюю неделю показывалось рядом стоящими стрелками ( ). Т.е. если поднялся на 5 мест вверх, то стрелка вверх и число 5.

Далее рядом с каждым из них были смайлики. Это прописанные картинки, которые распределяются исходя из числа баллов равномерно от 2-го места к последнему, первое всегда один и тот же победитель. Смайлики были найдены ещё в 2003-м году, и тогда студенты ещё нас спрашивали, де их нашли (тогда найти было трудно). Кроме того, часть смайликов собственноручно нарисовал Андрей Логвиненко, так как они были слишком жестокими по отношению к девушкам либо не смотрелись женственно. Таким образом, у нас было две линейки смайликов — женские и мужские.

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

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

Кроме всего этого, имелась система наград, которая включала много разных отличительных значков:

Черная метка — выдается тем, у кого самый худший вариант в группе. Мы долго думали как отображать награду, Андрей даже предлагал сапоги, но все таки остановились на метке. Значок баллов не дает, переходящий приз.
Кубок самому лучшему в специализации на потоке (микропроцессорщики, телемеханики, связисты — три таких кубка.). Баллов не дает, переходящий приз.
Награда за то, что все лабораторные выполнены, а отчеты сданы. +5 если все вовремя, +3 если хотя бы одна не вовремя.
Лучший студент на потоке, переходящий приз, баллов не дает.
Лучшая студентка на потоке, переходящий приз, баллов не дает.
Утешительный приз. Первый из тех, кто остался вообще без звезд или наград. Баллов не дает, переходящий приз.
Первооткрыватель лабораторных работ. Приз получает тот, кто первый выполняет лабораторную работу, но при этом не более одной в руки (такую звезду если уже получил, то больше за первооткрывательство не дадут). +3 балла.
Double, triple, tetris, … приз за сдачу нескольких работ в один день (дубль — две в день). +1/+2/+3/… баллов.
Приз за сданные 1, 6, 10, 13, 28, 100, 153, 200, 256, 300, 370, 371, 400, 407, 496, 500, 555, 600, 666, 700, 800, 900, 1000, 1024 работы. Система помнит, в каком порядке работы сдаются на потоке, и если это работа номер как в списке, то выдается приз. +2 балла.
Выдается тем, кто набрал больше всего баллов в соответствующем месяце. Баллов не дает.
Блуждающая звезда (планета, переходящая). Первый вариант — за активность. Первые 10 студентов, имеющие самую большую активность, получали эти звезды. Первые 5 — +3 балла, вторые 5 — +2 балла.
Второй тип планеты — выдается за массовую сдачу л.р.. Система вычисляет день, когда было сдано больше всего работ, и всем, кто сдавал в этот день, выдает награду. +2 балла.

Таблицы рекордов сохранившихся годов: 2003-2004, 2004-2005, 2005-2006, 2006, 2007, 2010, 2011, 2013.

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


пятница, 2 августа 2013 г.

ПМО ИУС — Структуры данных и STL

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

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

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

Удержание фокуса

Каждая структура данных — это объект какого-то общего класса, который описывает данный тип структур данных. Интерфейс полностью инкапсулирует внутреннее состояние структуры.

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

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

Подробности

Структуры данных и STL слайды.

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

Одну структуру данных мы уже знаем — массив. У нас в массиве всегда хранятся элементы одного типа, доступ в С++ через оператор [] по индексу, внешний пользователь использует массив не думая о том, как и где он хранится. Хотя пользователь может рассчитывать, что элементы в массиве хранятся последовательно и доступ к ним по индексу очень быстр (например в Perl массивы хранятся не последовательно, а организованы через хэш). Элементы могут быть любого, но одного типа. Взаимодействие с ними жестко определено интерфейсом. Внешний пользователь может создавать столько массивов, сколько ему захочется, и практически для любых типов (тип должен иметь фиксированный размер или гарантию того, что по размеру не выйдет за установленный предел).

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

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

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

Очередь. Аналогично — есть HEAD и TAIL, можно вставлять в один хвост, а извлекать только из другого. FIFO. Аналогично реализуется статически и динамически.

Списки. Как двусторонние стеки или двусторонние очереди. С каждым из хвостов можно делать операции извлечения и вставки.

Двусторонне-связанные списки. Картинка динамической реализации. Аналогично односторонне-связанные. Преимущества и недостатки.

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

Кольцевые списки.

Как организуется структура данных — основные правила.

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

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

Бинарное дерево — количество потомков не более 2. Это имеет свои преимущества. Например в данном случае дерево отсортировано и можно простыми операциями сравнения найти нужный элемент, ища из корня.

Сбалансированное дерево — такое дерево, в котором все кроме одного последнего уровня обязательно заполнены. Такое дерево позволяет осуществить гарантированный поиск за log2(N) операций.

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

Виды проходов деревьев (pre-order, in-order, post-order, level-order).

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

Мультимножество.

Карта (отображение, map). Мультикарта (multimap).

Хэш. Сначала разбор понятия хэш функции (функция, возвращающая элемент, который имеет конечное число состояний). Данное число состояний в хэше ассоциируется с хэш-таблицей.

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

Понятий коллизий. Коллизии это плохо. как избежать коллизий (хорошая хэш-функция и изменение размеров хэш-таблицы).

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

Пример экзотической структуры данных — sparse array и варианта его реализации.

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

STL. Базовые (но это не все) элементы — контейнеры, итераторы, алгоритмы.

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

Каждый контейнер представляет собой упорядоченную последовательность элементов. Т.е. все элементы можно выстроить в одну цепочку друг за другом. Если мы хотим перебрать все элементы контейнера (распечатать их, найти какой-то и др.), что является типичной операцией, то это делается через итерационный перебор. Пример перебора. Понятие end-of-sequence (элемент за последним, но не последний).

Vector. Это — массив, но только в отличие от него мы можем изменять его размер во время выполнения программы. Сам вектор имеет всегда какой-то запас по размеру в памяти, и поэтому мы можем его расширять быстро.

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

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

List. В STL — динамический двусвязный список со всеми вытекающими. Удаление и добавление элементов в список. Пример.

Образование контейнеров из list'a в STL: стек, очередь и приоритетная очередь сделаны на основании list'a.

Deque.

Множества и мультимножества как деревья в STL.

Карты и мультикарты в STL. Пример.

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

Типичные методы контейнеров, характерные для всех.

Разбор алгоритмов STL. Алгоритмов много. Они безопасны, проверены и быстры. Работают как с контейнерами, так и с массивами. Нужно знать.


четверг, 1 августа 2013 г.

ПМО ИУС — Исключения

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

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

Кроме общего изучения механизмов исключений были сформулированы два дополнительных акцента: создание собственных классов исключений (опционно с задействованием std::exception), задействование исключений других библиотек (VCL C++Builder, другие библиотеки также могут использовать стратегию обработки исключительных ситуаций через исключения, и это мы понимаем и используем).

Удержание фокуса

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

Смысловое и функциональное значение своих классов исключений.

Подробности

Слайды.

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

Итак, ошибочная ситуация. Суть стартует с простейшего примера — необходимо написать функцию деления двух чисел A на B. Пример функции:

int
func( int a, int b )
{
    return a / b;
}

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

С точки зрения обязательств все понятно. Однако здесь может получится так, что параметр B равен 0. В этом случае разработчик находится в затруднительном положении — он может понять и проанализировать, что B=0 (через if например), но этот случай не может быть обработан, так как возвращаемый функцией результат как число будет неверным. Если такое происходит (мы понимаем, что сами разрулить ситуацию не можем из-за особенностей функции или состояния системы, но делать что-то надо), то это называется ошибочной ситуацией.

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

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

Останов программы.
Останов в надежде, что придет человек и все решит. Человек действительно может все решить, но на это может потребоваться много времени. Резкий останов позволяет быстро диагностировать факт проблемы (останов не заметить крайне сложно) и заняться её устранением (fail-fast), но например в системах реального времени, от которых многое зависит (ПО на борту самолета), прийти и разобраться будет поздно. Кроме того, может получится так, что проблема на самом деле проста, и решить её можно программной логикой.
Вернуть что-то, как будто ничего не произошло.
Самый страшный способ. Внешний пользователь не сможет узнать, что система работает некорректно, соответственно ошибку сложнее будет обнаружить, из-за чего мы будем думать, что все в порядке, а на самом деле все плохо. Однако в крайне редких случаях, например когда нет другого способа, а система должна работать, это может применяться, но при этом надо отдавать себе отчет и пытаться сделать все возможное для диагностики (страшная запись в лог) и попытки решения проблемы.
Вернуть код ошибки (некоторое.
Традиционный способ обработки ошибочных ситуаций, встречающийся во многих системах нижнего уровня. Может быть обработан широкий спектр ошибок (с добавлением кодов в документацию). Однако у него есть ряд недостатков. Во-первых, не всегда можно вернуть код ошибки (как например в нашей функции делания A на B, нет ни одного зарезервированного значения для возврата кода ошибки). Во-вторых, в случае большого числа кодов ошибок и большой вложенности функций становится сложно все это сопровождать. Фактически каждая функция должна быть проверена на возвращаемое значение (вы часто проверяете возвращаемое значение printf?), и зачастую то не делается. А если делается, то код резко разрастается, и при этом логика обработки ошибок смешивается с бизнес-логикой приложения.
Вызвать некоторую общую функцию, которая решит все проблемы.
Общая функция — это логическая обработка, которая потенциально может все. Однако здесь есть ряд проблем: не каждую ошибочную ситуацию можно обработать; в больших системах такая функция начинает на себя брать все, а это ведет её разрастанию и глобализации (зависимость в случае сохранения внутреннего состояния функции; многопоточность и пр., очень похожее на синглтон и глобальные переменные), что череповато; не всегда есть возможность вызова такого рода функции из всех контекстов.

Как видим варианты решения есть, их много, и у каждого из них свои особенности.

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

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

Рассмотрение аналогичного примера, только уже с использованием механизма исключений.

Разбор синтаксиса исключений.

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

Обработка множественных catch (только один из, выбор сверху вниз по типу исключения).

Собственные классы исключений и их иерархии. Выбор блока обработки исключительной ситуации в случае иерархии исключений.

Повторная генерация (отсутствие копии и сохранение оригинала).

Исключения std::exception, их рекомендация к использованию, почему они не обязательные как в других языках (исторически), уже готовые стандартные, наследование от них.

Исключения C++ Builder как пример исключений со сторонних библиотек. Другие библиотеки также могут использовать исключения и соответственно их функции бросать их.

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