Результати пошуку
ITVDN: курси програмування
Відеокурси з
програмування
Підписка

300+ курсів за популярними IT-напрямками

Вибери свою IT спеціальність

Підписка
Підписка

300+ курсів за популярними IT-напрямками

Результати пошуку за запитом: c
Введення в розробку програм під iOS. Частина 3

Автор: Volodymyr Bozhek

Здравствуйте, дорогие читатели. В этом уроке мы: создадим форму редактирования товара; рассмотрим понятие делегата и удобство его использования; добавим действия редактирования / удаления товара в списке товаров. Откройте проект Warehouse. В первую очередь, давайте изменим цвет View входа в систему с “Light Green” на “White”, я явно перестарался с выбором цвета в самом начале :). В будущих уроках, когда разберем, как пользоваться Assets, мы заменим фон на красивую картинку, подходящую по смыслу к этому приложению, а пока сделаем нейтральный цвет, не бросающийся в глаза. Для этого в панели навигатора откройте модуль “Main.storyboard”, выделите “View Controller”, затем в панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Background” и установите значение “White”. Теперь найдите в библиотеке компонентов компонент “Table View Controller” и перетащите его в свободную область дизайнера рядом с “Supplies View Controller”, созданным в прошлом уроке. Выделите только что добавленный компонент. Найдите кнопку в дизайнере “Show Document Outline”, нажмите на нее, откроется панель документов. На этой панели разверните компонент “Table View Controller” и выделите компонент “Table View”. Затем в панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Content”. По умолчанию у этого свойства установлено значение “Dynamic Prototypes”, установите значение “Static Cells”, в дизайнере вы увидите, что интерфейс контроллера изменился и отобразилось 3 строки. Разберем значения этого свойства. Значение “Dynamic Prototypes” используется, если вам необходимо иметь динамический набор данных, который будет постоянно изменяться. Установив это значение, обязательно необходимо переопределить методы протокола “UITableViewDataSource” для корректной работы контроллера. Значение “Static Cells” используется, если вам необходимо иметь статические данные, которые не будут меняться. Установив это значение, вам не нужно переопределять методы протоколы “UITableViewDataSource”. В данном примере мы устанавливаем это значение с целью удобства размещения элементов управления на нашей View. У нас будут ячейки с таким содержимым: ячейка под картинку, идентификатор товара, название товара, описание товара. Сейчас у нас 3 ячейки, надо чтобы было 4. В первой ячейке будет компонент “Image View”, в остальных 2 ячейках будут элементы управления “Label” и “Text Field”, в последней 4-й ячейке будут элементы управления “Label” и “Text View”. На панели документов для “Table View Controller”  выделите компонент “Table View Section”. В панели свойств откройте вкладку “Show the Attributes inspector”. Найдите свойство “Rows”. Сейчас у этого свойство установлено значение “3”. Измените значение на “4”, у вас появится 4 ячейка. В панели документов раскройте компонент “Table View Sections”, вы увидите список ячеек типа “Table View Cell”. Выделите первую ячейку. В панели свойств откройте вкладку “Show the Size inspector”. На этой вкладке можно управлять размерами компонента. Найдите свойство “Custom” и отметьте его галочкой. Затем найдите свойство “Row Height”. Установите значение этого свойства “144”, высота ячейки изменится. Перетащите на эту ячейку из библиотеки компонентов  компонент “Image View” и растяните его на всю область ячейки. Выделите компонент “Image View” и нажмите кнопку “Pin”. В открывшемся диалоговом окне снимите галочку с поля “Constrain to margin” и отметьте позиционирование относительно всех стенок ячейки. Нажмите кнопку “Add 4 Constraints”. В панели документов выделите вторую ячейку. Перетащите из библиотеки компонентов компонент “Label” на эту ячейку. Поместите его с левого края ячейки и растяните по высоте ячейки. В панели свойств откройте вкладку “Show the Size inspector”, установите свойство “Width” в значение “120”. Откройте вкладку “Show the Attributes inspector”, установите безымянное свойство с текстом “Label” на текст “Идентификатор”. Найдите свойство “Font”, нажмите на кнопку со значком “T”, откроется диалоговое окно задания свойств шрифта. Установите свойство “Style” в значение “Bold”, свойство “Size” в значение “12”. Нажмите кнопку “Done”. Представление должно выглядеть так: Из библиотеки компонентов перетащите компонент “Text Field” и расположите рядом с компонентом “Label”. Растяните компонент “Text Field” на оставшуюся ширину ячейки. Выделите элемент управления “Label”, нажмите кнопку “Pin”. Снимите галочку с поля “Constrain to margin”, отметьте позиционирование относительно верхней и левой стенок ячейки. Отметьте галочкой поле “Height”. Нажмите кнопку “Add 3 Constraints”. Выделите элемент управления “Text Field”, нажмите кнопку “Pin”. В диалоговом окне снимите галочку с поля “Constrain to margin”, установите позиционирование относительно левой, верхней, правой стенок ячейки, отметьте галочкой поле “Height”. Нажмите кнопку “Add 4 Constraints”. В панели документов выделите 3 ячейку. Повторите для нее все операции, которые были применены ко второй ячейке. Измените текст элемента управления “Label” на “Название”. Должно получиться вот так: В панели документов выделите последнюю ячейку, на вкладе “Show the Size inspectors”  установите в поле “Row Height” значение “144”, предварительно отметив поле “Custom” галочкой. Перенесите на ячейку два компонента “Label” и “Text View”. В          Установите ограничения для элемента управления “Label”, как мы устанавливали для предыдущих элементов управления “Label”, а для элемента управления “Text View” такие же ограничения, как для “Text Field”. Для элемента управления “Label” установите текст “Описание”, для элемента управления “Text View” уберите текст по умолчанию. Должно получиться вот так: В панели навигатора, добавьте новый модуль “Swift File” с именем “ProductViewController.swift”. Измените код, как показано ниже: Перейдите снова в дизайнер , выделите “Table View Controller”, с которым проводили изменения, в панели свойств, откройте вкладку “Show the Identity inspector”. Установите свойство “Class” значением “ProductViewController”, свойство “Storyboard ID” значением “ProductViewController”. В панели инструментов нажмите кнопку “Show the Assistant editor”. Для элемента управления “Image View” создайте переменную с именем “imageView”.       Во второй ячейке, для элемента управления “Text Field”, создайте переменную с именем “idTxt”. В третьей ячейке, для элемента управления “Text Field”, создайте переменную с именем “nameTxt”. В четвертой ячейке, для элемента управления “Text View”, создайте переменную с именем “descriptionTxt”. Должно получиться вот так: В панели навигатора, добавьте новый модуль “Swift File” с именем “ProductModel.swift”. Добавьте в него следующий код: Разберем добавленный код построчно. На 9 строке мы подключили пространство имен “Foundation” для класса “NSObject”. На 11 строке мы объявили класс с именем “ProductModel”, который наследуется от класса “NSObject” для того, чтобы считаться типом данных. На 12 строке мы объявили переменную с именем “productId” типа “Int” и инициализировали ее значение по умолчанию “-1”. На 13 строке мы объявили поле с именем “productImage” типа “String” и инициализировали ее значение по умолчанию “”. На 14 строке мы объявили поле с именем “productName” типа “String” и инициализировали ее значение по умолчанию “”. На 15 строке мы объявили поле с именем “productDescription” типа “String” и инициализировали ее значение по умолчанию “”. На 17 строке мы объявили параметризированный инициализатор класса “ProductModel” (это тоже самое, что и конструктор в языке программирования C#). Инициализатор - это метод, который вызывается при создании нового экземпляра класса. Данный инициализатор принимает аргументы с такими же именами, как имена полей в классе. Для того, чтобы инициализировать внутренние поля класса значениями полей аргументов. Мы левым операндом обращаемся к самому себе, через ключевое слово “self” и обращаемся к нужному нам полю, а правым операндом задаем значение аргумента. Мы плавно подходим к созданию делегата. В панели навигатора добавьте новый модуль “Swift File” с именем “ProductProtocol.swift”. Добавьте в него следующий код: Разберем добавленный код. На 11 строке мы объявили протокол с именем “ProductProtocol”. Протокол - это тоже самое, что и интерфейс в языке программирования C#. Экземпляр протокола через инициализатор создать нельзя, поскольку это только прототип, который не содержит реализации и используется в качестве описания и задания соглашений, которые разработчик должен реализовать сам в будущем. На 12 строке мы объявили метод прототип с именем “changeProduct”,  который принимает аргумент типа “ProductModel” с именем “model”. Откройте модуль “ProductViewController.swift”, добавьте поле с именем “delegate” типа “ProductProtocol?” и поле с именем “id” типа “Int” со значением по умолчанию “-1”. Должно получиться вот так: Добавьте после метода “viewDidLoad”, новые методы с именами “initNavigationButtons”, “backToParent”, “saveData”, которые ничего не принимают и ничего не возвращают. Код: Разберем построчно добавленный код. На 21 строке мы вызываем метод “initNavigationButtons”, когда View находится в процессе загрузки, чтобы инициализировать кнопки навигации. На 24 строке мы объявили метод с именем “initNavigationButtons”. На 25 строке мы переопределяем левую кнопку навигации, задаем ей текст “Отмена” и обработчик события на нажатие, метод “backToParent”. На 26 строке мы создаем кнопку с именем “saveButton” и текстом “Сохранить”, добавляем для нее обработчик событие на нажатие, метод “saveData”. На 27 строке мы обращаемся к экземпляру панели навигации контроллера “navigationItem” и вызываем от него метод “setRightBarButton”, который принимает два аргумента. Первый аргумент - это экземпляр добавляемой на панель навигации кнопки, второй аргумент - это стиль добавления кнопки, добавить с анимацией или без. Сам метод, как видно из названия, добавляет кнопку справа на панель навигации. Это вариант, как добавить правую кнопку из кода. На 30 строке мы объявили метод с именем “saveData”. На 31 строке мы обращаемся к нашему делегату с именем “delegate” и проверяем, если он инициализирован, тогда вызываем у него метод “changeData” и передаем туда модель данных, заполненную данными собранными с элементов управления. На 32 строке мы создаем экземпляр типа “ProductModel” с именем “model”. На 33 строке мы вызываем у делегата метод “changeData” и передаем туда экземпляр “model”. Данный метод будет реализован в классе “SuppliesViewController”. На 35 строке мы возвращаемся на предыдущую View (SuppliesViewController) в стеке иерархий вызовов View. На 38 строке мы объявляем метод с именем “backToParent”. Данный метод делает переход на предыдущую View (SuppliesViewController) в стеке иерархий вызовов View. Теперь откройте модуль “SuppliesViewController.swift”. Нам необходимо обновить его реализацию: Разберем обновленный код построчно. На 12 строке в классе SuppliesViewController мы наследуемся от протокола “ProductProtocol”. На 13 строке мы заменили тип данных для поля “supplies”. Тип данных был “[String]”, стал “[ProductModel]”. И сделали это поле статическим для того, чтобы была возможность доступа к нему из контроллера “ProductViewController”. На 29 строке мы реализовываем метод “changeProduct” протокола “ProductProtocol”. Именно этот метод будет вызываться при нажатии кнопки “Сохранить” в контроллере “ProductViewController”. На 30 строке мы проверяем идентификатор продукта, если “-1” - это означает, что это новый продукт. Иначе существующий продукт, и мы его обновляем. На 32 строке мы правым операндом генерируем идентификатор продукта путем вызова метода “makeNewProductId”. Данный метод возвращает значение типа “Int”, которое мы присваем левому операнду. Левый операнд - это поле “productId” экземпляра “ProductModel”. На 33 строке мы добавляем новый продукт в коллекцию продуктов. На 36 строке мы объявляем переменную с именем “changedIndex” типа “Int” со значением по умолчанию “-1”. В эту переменную мы запишем найденную ниже в цикле позицию продукта в коллекции “supplies”. На 37 строке мы в цикле проходимся по элементам коллекции “supplies” и ищем продукт, который нужно обновить. На 38 строке описано условие поиска продукта. На 39 строке, когда продукт был найден, мы сохраняем его позицию в переменную “changedIndex”. На 40 строке выходим из цикла. На 43 строке проверяем, если продукт был найден , тогда обновляем этот продукт. С 44 по 46 строку мы обновляем свойства продукта , значениями свойств модели, переданной аргументом метода “changeProduct”. На 49 строке мы запускаем переинициализацию “DataSource” для табличного представления, чтобы данные в ячейках обновились и добавились/удались обновленные данные. На 52 строке мы объявили метод с именем “makeNewProductId”, который ничего не принимает и возвращает значение типа “Int”. На 53 строке левым операндом мы объявили переменную с именем “sortProducts” типа “[ProductModel]”. Правым операндом мы на экземпляре коллекции “supplies” вызываем метод “sorted”, который принимает лямбда метод сортировки коллекции объектов и возвращает отсортированную коллекцию. У лямбда метода есть два аргумента, в них находятся экземпляры сравниваемых объектов из коллекции “suppliers”. Данный метод возвращает значение типа “Bool”. На 54 строке мы возвращаем условие сортировки по возрастанию. Сортировка производится по свойству “productId” класса “ProductModel”. На 56 строке мы обращаемся к последнему элементу отсортированной коллекции, тем самым получаем максимальный идентификатор продукта в коллекции и увеличиваем его на единицу. Теперь надо обновить реализацию метода “cellForRowAt indexPath”: Разберем код построчно. На 69 строке мы изменили вид обращения к коллекции “supplies”. На 73 строке мы изменили для экземпляра ячейки тип стиля. Был “.plain”, стал “subtitle”. На 74 строке мы левым операндом объявили константу с именем “model” типа “ProductModel”. Правым операндом мы инициализируем константу значением из коллекции “supplies”. На 75 строке мы записываем в свойство “tag” идентификатор продукта для этой ячейки. На 76 строке в элемент управления “Label”, который находится в верхней области ячейки, мы записываем название продукта. На 77 строке в элемент управления “Label”, который находится в нижней области ячейки, мы записываем описание продукта. На 78 строке мы активируем в ячейке информационную кнопку справа. При нажатии на эту кнопку мы будем редактировать продукт. Теперь нам надо подвязаться на событие нажатия на информационную кнопку в ячейке. Для этого необходимо переопределить метод протокола “UITableViewDelegate” ,реализованного в классе “UITableViewController” с именем “accessoryButtonTappedForRowWith”. Разберем код построчно. На 83 строке мы получаем экземпляр типа “ProductModel”, привязанный к ячейке, и сохраняем его в константу с именем “model”. На 84 строке мы производим поиск контроллера с именем “ProductViewController” в модуле “Main.storyboard”. На 85 строке на найденном экземпляре контроллера обращаемся к свойству “delegate” типа “ProductProtocol” и инициализируем его ссылкой на самого себя, тем самым говоря, что в этом классе уже реализован метод этого протокола с именем “changeProduct” и вызывать метод надо именно из этого класса. На 86 строке мы на найденном экземпляре контроллера обращаемся к свойству “id” и инициализируем его идентификатором продукта, привязанного к текущей ячейке. На 87 строке мы открываем контроллер “ProductViewController”. Редактирование мы почти сделали, осталось добавить инициализацию редактируемых данных в контроллере “ProductViewController”. Давайте реализуем еще в этом контроллере удаление данных. Для этого надо переопределить два метода объявленных в протоколе “UITableViewDelegate” и реализованных в классе “UITableViewController”. Эти методы называются “canEditRowAt IndexPath” и “commit editingStyle”. Обновите свой код в соответствии с представленным ниже: Разберем код построчно. На 90 строке мы переопределили метод “canEditRowAt IndexPath”, данный метод возвращает значение , которое говорит о том, активировать удаление строк или нет. На 91 строке возвращаем значение активировать. На 94 строке мы переопределили метод “commit editingStyle”, данный метод вызывается, когда мы нажали кнопку удалить на ячейке. На 95 строке мы удаляем продукт из коллекции “supplies”. На 96 строке обновляем содержимое таблицы. Теперь добавим кнопку добавления нового товара. Для этого обновим код метода “initNavigationButtons”.   Разберем код построчно. На 100 строке мы создали экземпляр кнопки с текстом “Новый продукт” и обработчиком события на нажатие - метод “newProduct”. На 101 строке мы добавили выше созданную кнопку в панель навигации контроллера в область справа. На 104 строке мы объявили метод “newProduct”, которые ничего не принимает и ничего не возвращает. На 105 строке мы производим поиск контроллера “ProductViewController” в модуле “Main.storyboard”. На 106 строке мы на найденном экземпляре контроллера обращаемся к свойству “delegate” и инициализируем его ссылкой на самого себя. На 107 строке мы  на найденном экземпляре контроллера обращаемся к свойству “id” и говорим, устанавливая значение “-1”, что мы создаем новый продукт. Теперь откройте модуль “Main.storyboard”, в нем на контроллере “ProductViewController” выделите элемент управления с идентификатором “idTxt”. В панели свойств на вкладке “Show the Attributes inspector” найдите свойство “User Interaction Enabled” и снимите галочку. Тем мы самым мы запретили редактирование значения этого поля. Теперь перейдите в модуль “ProductViewController.swift”. Обновите в нем код, как это показано ниже: Разберем добавленный код построчно. На 19 строке мы добавили метод с именем “initData”, который ничего не возвращает и принимает аргумент с именем “id” типа “Int”. На 20 строке мы проверяем идентификатор продукта, если он больше значения “-1”, значит продукт уже существует и содержит внутри себя данные, которые можно отобразить на текущей View. На 22 строке мы ищем продукт по идентификатору продукта, переданному аргументом в методе в коллекции продуктов “supplies”. С 23 по 25 строку мы заполняем элементы управления на пользовательском интерфейсе данными найденного продукта. На 33 строке в методе “viewDidLoad” мы добавили вызов метода “initData” и передали ему аргумент поле “id”, которое мы задаем в контроллере “SuppliesViewController”. Запустите приложение. На анимации выше видно, что мы вошли в систему, открыли товар на редактирование, откредактировали товар и изменения сохранились. Затем удалили товар. Теперь давайте проверим добавление нового товара: Проверили, добавление нового товара работает хорошо. Но все равно есть один нюанс, наше приложение на русском языке. А когда выполняли на ячейки жест справа на- лево, то показывалась кнопка удалить “Delete” на английском, давайте исправим это, чтобы показывалось русское название “Удалить”. Откройте модуль “SuppliesViewController.swift”, нам необходимо переопределить метод, объявленный в делегате “UITableViewDelegate” c именем “titleForDeleteConfirmationButtonForRowAt” и реализованный в классе “UITableViewController”. Добавьте следующий код, после метода “backToParent”: Я думаю, этот метод не стоит разбирать построчно, тут и так все понятно. Запустите приложение. На этом завершим наш урок. В следующем уроке мы разберем технологию 3D Touch и применим ее к нашему приложению для предварительного просмотра товаров. Добавим поле поиска в заголовок контроллера со списком товаров, реализуем поиск товаров. Реализуем протокол “UITextFieldDelegate”, чтобы скрывать клавиатуру при нажати кнопки “Ввод” на клавиатуре мобильного устройства. Разберем, как добавить собственную панель интрументов с кнопками.
Як створити веб-сайт за допомогою AJAX

Автор: Редакція ITVDN

Создания простого чата Для начала создадим простой чат с помощью HTML&CSS и PHP&MySQL Проектирование Базы Данных Переходим к phpMyAdmin. Создаем новую базу данных, называем “chatdb”. Создаем новую таблицу, называя “Posts”, включая в себя 4 столбца: “id” тип колонки INT, автоматическое увеличение на 1 (задаем A_I в ячейку с флажком) основной ключ (index); “nick” тип колонки VARCHAR и длина 100; “post_text” тип колонки TEXT; “post_dt” тип колонки DATETIME по умолчанию является CURRENT_TIMESTAMP. Создание веб-сайта. Во-первых, создадим главную страницу. Список комментариев и отправка формы, используя кнопку. Всё будет находится в файле “index.php” .  Давайте создадим этот файл и напишем что-то вроде этого:  <html> <head> head> <body> php $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb"); /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */ /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */ /* "chatdb" is DB's name. */ /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */ $result = $mysqli->query("SELECT * FROM posts;"); ?> <style> /* All CSS is very simplified. I provide it for example and no more.  * In Chrome it works tolerably, but in IE and Firefox it works very poorly.  */ .content {   display: table;   width: 50%;   min-width: 400px;   height: 80%;   /* Center horizontally and vertically */   position: absolute;   left: 0; right: 0;   top: 0; bottom: 0;   margin: auto;   /* Design */   border: 1px solid;   background-color: silver;   padding: 5px; } /* For mobile devices */ @media (max-width: 400px) {   .content {     width: 100%;     min-width: 0;     padding: 0px;   } } style> <div class="content"> <div id="comments" style="overflow-y: scroll; height: 100%;"> php if ($result) {   while ($post = $result->fetch_object()){     $nick = $post->nick;     $post_dt = $post->post_dt;     $post_text = $post->post_text;         echo "<b>$nickb> ($post_dt):<br>";     echo "$post_text<br>";     echo "<br>";   }   $result->close(); } ?> div> php $mysqli->close(); ?> <form action="post.php" method="post" style="height: 0; display: table-row;">   Nick:<br>   <input type="text" name="nick" style="width: 100%;">input><br>   <br>   Text:<br>   <textarea name="text" style="width: 100%;">textarea><br>   <br>   <input type="submit">input> form> div> <script type="text/javascript">     var divComments = document.getElementById('comments');     divComments.scrollTop = divComments.scrollHeight; script> body> html> 2. Дальше давайте создадим “post.php” файл и напишем такое:  php $nick = $_POST['nick']; $post_text = $_POST['text']; $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb"); $nick = $mysqli->real_escape_string($nick); $nick = htmlspecialchars($nick); $post_text = $mysqli->real_escape_string($post_text); $post_text = htmlspecialchars($post_text); $mysqli->query("INSERT INTO posts (nick, post_text) VALUES ('$nick', '$post_text');"); $mysqli->close(); /* Redirect To Main Page */ header('Location: ' . $_SERVER['HTTP_REFERER']); ?> 3. Откроем ваш чат в любом продвинутом браузере. Вся работа:  4. Напишите ник и текст, а потом нажмите на кнопку отправки.  Когда отправили форму, сразу же происходит перенаправление формы главной страницы в “post.php”. “Post.php” моментально наполняет данными таблицу и перенаправляет на главную страницу. Также “post.php” содержит начальный XSS и SQL защищенный вход. Для упрощения не отправляем клиентам время с JS на “post_dt” на внесения данных, а указываем значение по умолчанию – CURRENT_TIMESTAMP, который предоставляет нынешнюю дату и время на сервер. Когда количество комментариев больше, чем экран может вместить, то комментарии   переполнены в div, используется вертикальный скроллбар. Во время загрузки страницы JS автоматически опускает скроллбар вниз к недавнему комментарию. Что тут не так? Проблема номер 1. Новый непрочитанный комментарий от пользователя не загружается в базу данных автоматически, без ручной перезагрузки страницы. Это очень, очень серьезная проблема для любого чата. Как это исправить? Очевидно, один из путей сделать это - использовать HTTP-запрос к фоновой работе автоматически (с помощью JS) и асинхронно, то есть это один из способов обеспечить выполнение AJAX в любой form. Проблема номер 2. Также неправильно то, что кнопка отправки перезагружает страницу (перенаправляет на вторую страницу и следующим шагом возвращает назад). При перезагрузке страницы сбрасывает “Nick” в  поле (также, как любые другие изменения, те, что сделали с пользователем) Как это исправить? Конечно, можно обеспечить выполнение обхода для сохранения изменений и перезагрузки на перезагружаемой странице. Но не эффективнее ли устранить причину, чем последствие? Можно только убрать перезагружаемую страницу и эта проблема будет решена автоматически. Проблема номер 2.1. Видите ли что-то необычное тут? Это слишком быстро? Дело с чатом очень простое – загружаем только два маленьких текстовых параметра. Что делать, если нужно улучшить чат с помощью добавления присоединения, а конкретно - изображений и видео? Видео может иметь объем в размере нескольких мегабайт, что тогда в этом случае? Давайте попробуем.  Давайте немного изменим “post.php”, после $mysql->query() добавив это:  for ($i = 0; $i < 1000000000; $i++) { } Старайтесь размещать какие-либо комментарии. Что мы видим? Нет, UI не остановилось (заморозилось), но браузер ждет до того, как закончится подключение:   Да, если “post.php” вызывает какую-то необработанную ошибку, то чат исчезает, и пользователь видит пустое окно с сообщением о непонятной ошибке. Чтобы вернуться к чату, пользователю стоит нажать кнопку “Back” в браузере. И это проблема номер 2.2. Давайте уберем петлю с “post.php” и исправим эти проблемы. Реализация легкого AJAX в простой чат Автоматическое обновление комментариев Эта веб-страница без AJAX? Это веб-страница, которая полностью перезагружается. Эта веб-страница c AJAX? Это веб-страница, что перезагружается частично. Где же взять части этих страниц? Стоит разделить нашу страницу на части, в этом случае сервер генерирует страницу частично. Страница будет состоять из двух частей – блок комментариев и другой контент страницы. Комментарии будут загружаться и перезагружаться отдельно от другой страницы. Давайте сделаем первую часть, то есть блок комментариев. Для начала создадим пустой файл, назовем “getcomment.php”. Дальше переходим в “index.php” для того, чтобы вырезать комментарии и далее отделить его. 1. Вырезаем инициализированный блок MySQL с “index.php"  php $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb"); /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */ /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */ /* "chatdb" is DB's name. */ /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */ $result = $mysqli->query("SELECT * FROM posts;"); ?> вставляем в “getcomments.php”. 2. Следующее, вырежем контент div c комментариями с “index.php”: php if ($result) {   while ($post = $result->fetch_object()){     $nick = $post->nick;     $post_dt = $post->post_dt;     $post_text = $post->post_text;         echo "<b>$nickb> ($post_dt):<br>";     echo "$post_text<br>";     echo "<br>";   }   $result->close(); } ?> И вставим (добавим) в “getcomments.php” после инициализации MySQL. 3. Дальше, вырежем недалекий блок MySQL с “index.php”: php $mysqli->close(); ?> Вставим его в конец файла “getcomments.php”. 4. Наконец-то, убираем JS-скрипт, который опускает скролл в самый низ. <script type="text/javascript"> var comments = document.getElementById('comments'); comments.scrollTop = comments.scrollHeight; script> Не переживай, это только временно. 5. Сделано. Теперь имеем что-то наподобие этого:  <html> <head> head> <body> <style> /* All CSS is very simplified. I provide it for example and no more.  * In Chrome it works tolerably, but in IE and Firefox it works very poorly.  */ .content {   display: table;   width: 50%;   min-width: 400px;   height: 80%;   /* Center horizontally and vertically */   position: absolute;   left: 0; right: 0;   top: 0; bottom: 0;   margin: auto;   /* Design */   border: 1px solid;   background-color: silver;   padding: 5px; } /* For mobile devices */ @media (max-width: 400px) {   .content {     width: 100%;     min-width: 0;     padding: 0px;   } } style> <div class="content"> <div id="comments" style="overflow-y: scroll; height: 100%;"> div> <form action="post.php" method="post" style="height: 0; display: table-row;">   Nick:<br>   <input type="text" name="nick" style="width: 100%;">input><br>   <br>   Text:<br>   <textarea name="text" style="width: 100%;">textarea><br>   <br>   <input value="Submit" type="submit">input> form> div> body> html> getcomments.php:  php $mysqli = new mysqli("127.0.0.1", "root", "", "chatdb"); /* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */ /* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */ /* "chatdb" is DB's name. */ /* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */ $result = $mysqli->query("SELECT * FROM posts;"); ?> Вероятно, теперь наша страница разделена. Давайте проверим её. Переходим http (точнее ССЫЛКА для локального сервера). Дальше, переходим на главную страницу, http:///index.php Это удивительно! Всё удачно получилось, разделив страницу на части за пару минут! Не останавливаемся на этом. Теперь “glue” эти части с помощью AJAX. Как это сделать? 1. Для начала стоит создать пустой JS-скрипт на главной странице: <script type="text/javascript"> alert('Test'); script> Добавив это после тега div, перед закрывающимся тегом . 2. Сделаем HTTP GET запрос от JS к “getcommet.php” Для этого используем XMLHtttpRequest (XHR) класс: <script type="text/javascript"> var xhr = new XMLHttpRequest(); xhr.open('GET', '/getcomments.php', false); xhr.send(null); if (xhr.status == 200) {   alert(xhr.responseText); } script> Это работает, но не читает старые версии IE те, что не поддерживают такую инициализацию. Для получения более кросс-браузерного пути переходим в и добавляем это: <script type="text/javascript"> function getXmlHttp(){   var xmlhttp;   try {     xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");   } catch (e) {     try {       xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");     } catch (E) {       xmlhttp = false;     }   }   if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {     xmlhttp = new XMLHttpRequest();   }   return xmlhttp; }; script> И главный скрипт (в конце) <script type="text/javascript"> var xhr = getXmlHttp(); xhr.open('GET', '/getcomments.php', false); xhr.send(null); if (xhr.status == 200) {   alert(xhr.responseText); } script> Как видно, теперь JS получает контент со страницы “getcomments.php” и показывает это в предупреждении.   2.1. Вопрос: «Это на самом деле AJAX (Asynchronous Javascript And Xml)?» Это AJAX, потому что запрос сервера отформатирован в HTML (который основан на XML). Но действительно ли это AJAX, это асинхронно? Проверим. Добавим эти уже знакомые строки в любое место между в “getcomments.php”: for ($i = 0; $i < 1000000000; $i++) { } Что теперь видно на загружаемой странице? Вначале страница зависает, его замораживает UI (становится не реагирующим на нажатие левой/правой кнопки мыши): Дальше Chrome показывает навязчивое всплывающие окно, сообщающее об удалении страницы: Это не AJAX! Это JAX! Как его сделать асинхронным? К счастью, ХHR также поддерживает асинхронный режим: <script type="text/javascript"> var xhr = getXmlHttp(); xhr.open('GET', '/getcomments.php', true); /* true for asynchronous */ xhr.onreadystatechange = function() {   if (xhr.readyState == 4) {     if(xhr.status == 200) {       alert(xhr.responseText);     }   } }; xhr.send(null); script> В этом случае браузер не ждет ответа с главного потока пользовательского интерфейса, он запускает в другом (асинхронно) и вызываемым событием “onreadystatechange” в главном контексте UI.  Теперь всё в порядке, страница полностью доступна, пока запрос запущен, и после ответа получит предупреждение. for ($i = 0; $i < 1000000000; $i++) { } И продолжаем работу. 3. Добавляем этот контент в div  вместо предупреждения. Заменить это: alert(xhr.responseText);  C этим: var divComments = document.getElementById('comments'); divComments.innerHTML = xhr.responseText; Возвращаем назад, клиент видит “glued” страницу с блоком комментариев. 4. Дальше следует установить интервал для автоматической проверки новых комментариев время от времени… и также восстановить удаленный сценарий автоматической прокрутки.  <html> <head> <script type="text/javascript">     function getXmlHttp() {         var xmlhttp;         try {             xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");         } catch (e) {             try {                 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");             } catch (E) {                 xmlhttp = false;             }         }         if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {             xmlhttp = new XMLHttpRequest();         }         return xmlhttp;     }; script> head> <body> <style> /* All CSS is very simplified. I provide it for example and no more.  * In Chrome it works tolerably, but in IE and Firefox it works very poorly.  */ .content {   display: table;   width: 50%;   min-width: 400px;   height: 80%;   /* Center horizontally and vertically */   position: absolute;   left: 0; right: 0;   top: 0; bottom: 0;   margin: auto;   /* Design */   border: 1px solid;   background-color: silver;   padding: 5px; } /* For mobile devices */ @media (max-width: 400px) {   .content {     width: 100%;     min-width: 0;     padding: 0px;   } } style> <div class="content"> <div id="comments" style="overflow-y: scroll; height: 100%;"> div> <form action="post.php" method="post" style="height: 0; display: table-row;">   Nick:<br>   <input type="text" name="nick" style="width: 100%;">input><br>   <br>   Text:<br>   <textarea name="text" style="width: 100%;">textarea><br>   <br>   <input value="Submit" type="submit">input> form> div> <script type="text/javascript">     var divComments = document.getElementById('comments');     function loadComments() {         var xhr = getXmlHttp();         xhr.open('GET', '/getcomments.php', true);         xhr.onreadystatechange = function () {             if (xhr.readyState == 4) {                 if (xhr.status == 200) {                     if (xhr.responseText !== divComments.innerHTML) {                         divComments.innerHTML = xhr.responseText;                         divComments.scrollTop = divComments.scrollHeight;                     }                 }             }         };         xhr.send(null);     };     loadComments();     setInterval(loadComments, 1000) script> body> html> Теперь проблема исправить это. Новые комментарии с другого пользовательского чата (другие вкладки браузеров, окон и экземпляров) получают каждые 1000 миллисекунды (1 секунду) автоматически. Но отправка комментариев уже вызывает перезагрузку нашей страницы. Отправка комментариев без перезагрузки Как написано выше, XHR помогает отправлять HTTP GET-запросы без перезагрузки страницы и GUI заморозки (асинхронно). Теперь отправляем HTTP-запрос асинхронно, но на этот раз POST запрос, а не GET. И, естественно, XHR позволяет это. Используем метод send(). Для GET указываем null. Для POST устанавливаем запрос “body”.Также нужно добавить “Content-Type:application/x-www-from-urlencoded” в header  для того, чтобы разрешить серверу знать, какой формат использовать для отправки данных. Заметка: если не знаете, что отправлять, то можно захватить регулярный запрос с помощью “Fiddler” или же любой другой HTTP-перехватчик и только просимулировать запрос. HTTP-перехватчик — это незаменимый инструмент для работы с HTTP/HTTPS. Это позволяет увидеть все headers и bodies по всем HTTP(S)-запросам, что отправляются в систему. Лучше использовать “Fiddler”, это бесплатное, современное и очень простое приложение, что может поддерживать HTTP/HTTPS и оба Win x86/x64. 1. Для начала создадим пустой JS скрипт в HTML. Разместить до самого тега, потому что этот скрипт будет использован для отправки формы комментария (форма будет вызывать этот скрипт при отправке).2. В этом скрипте, реализуем функцию, что будет отправлять ник и комментарии в “post.php”  <script type="text/javascript"> function postComment(nick, text) {   var xhr = getXmlHttp();   xhr.open('POST', '/post.php', true);   xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');   xhr.onreadystatechange = function() {     if (xhr.readyState == 4) {       if (xhr.status == 200) {         /* it isn't required to add comment to DOM manually, it will done automatically on next refresh via AJAX */       }     }   };   xhr.send('nick=' + nick + '&text=' + text); /* joining the data in format simulates form */ }; script> 3. Следующие, перезагружая страницу при отправке:  ... onsubmit="return false;"> Также добавим вызов “postComment’s”: action="post.php" method="post" style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;"> 4. Наконец, необязательно, но можно убрать “action” и “method” с формы:  <form style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;"> 5. Результат: <html> <head> <script type="text/javascript">     function getXmlHttp() {         var xmlhttp;         try {             xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");         } catch (e) {             try {                 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");             } catch (E) {                 xmlhttp = false;             }         }         if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {             xmlhttp = new XMLHttpRequest();         }         return xmlhttp;     }; script> head> <body> <style> /* All CSS is very simplified. I provide it for example and no more.  * In Chrome it works tolerably, but in IE and Firefox it works very poorly.  */ .content {   display: table;   width: 50%;   min-width: 400px;   height: 80%;   /* Center horizontally and vertically */   position: absolute;   left: 0; right: 0;   top: 0; bottom: 0;   margin: auto;   /* Design */   border: 1px solid;   background-color: silver;   padding: 5px; } /* For mobile devices */ @media (max-width: 400px) {   .content {     width: 100%;     min-width: 0;     padding: 0px;   } } style> <div class="content"> <div id="comments" style="overflow-y: scroll; height: 100%;"> div> <script type="text/javascript">     function postComment(nick, text) {         var xhr = getXmlHttp();         xhr.open('POST', '/post.php', true);         xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');         xhr.onreadystatechange = function () {             if (xhr.readyState == 4) {                 if (xhr.status == 200) {                     /* it isn't required to add comment to DOM manually, it will done automatically on next refresh via AJAX */                 }             }         };         xhr.send('nick=' + nick + '&text=' + text);     }; script> <form style="height: 0; display: table-row;" onsubmit="postComment(this.nick.value, this.text.value); return false;">   Nick:<br>   <input type="text" name="nick" style="width: 100%;">input><br>   <br>   Text:<br>   <textarea name="text" style="width: 100%;">textarea><br>   <br>   <input value="Submit" type="submit">input> form> div> <script type="text/javascript">     var divComments = document.getElementById('comments');     function loadComments() {         var xhr = getXmlHttp();         xhr.open('GET', '/getcomments.php', true);         xhr.onreadystatechange = function () {             if (xhr.readyState == 4) {                 if (xhr.status == 200) {                     if (xhr.responseText !== divComments.innerHTML) {                         divComments.innerHTML = xhr.responseText;                         divComments.scrollTop = divComments.scrollHeight;                     }                 }             }         };         xhr.send(null);     };     loadComments();     setInterval(loadComments, 1000) script> body> html>  Теперь простая реализация AJAX подошла к концу. Это ещё не конец, это только начало. Есть ещё достаточно всего для изучения и улучшения.
Framework у С# для перевірки відбитків пальців

Автор: Редакція ITVDN

Введение В наше время распознавание отпечатков пальцев является активным направлением исследований. Важным компонентом в системе распознавания отпечатков является алгоритм. В связи с проблемой данной сферы алгоритмы распознавания отпечатков пальцев делятся на две категории: алгоритмы проверки и идентификации. Цель алгоритмов проверки отпечатков пальцев является – определить, какой из двух отпечатков сделан одним пальцем, а какой нет. С другой стороны, алгоритмы идентификации делают поиск запроса отпечатка пальца в базе данных, ища отпечаток, сделанный одним и тем же пальцем. Насколько мы знаем, существуют сотни документов, касающихся проверки отпечатков пальцев, но нет ни одного фреймворка, позволяющего проверять отпечатки в сети. Поэтому вы должны осуществлять ваши личные настройки, тестировать выполнения алгоритмов распознавания ваших отпечатков. Более того, вы должны потратить много времени, выполняя алгоритмы других авторов, для сравнения с собственными. FVC-onGoing – наиболее связанный с работой нашего фреймворка в веб-системе. Данная система имеет такие ограничения: У вас нет доступа к другим алгоритмам, кроме своих. Это не фреймворк, поэтому вы не можете использовать другие компоненты программного обеспечения. Система не может быть использована с целью обучения, так как ученик не может посмотреть, как работают алгоритмы. После выполнения опыта используется база данных (стандартная или жесткая), вам необходимо ждать 30 дней для, того чтобы сделать следующий эксперимент, используя ту же базу данных. Вы не можете управлять базой данных. Таким образом, вы не можете использовать собственную базу данных либо редактировать существующую. Отсутствует доступ к тем отпечаткам, для которых ваш алгоритм не выполнился. Следовательно, вы не сможете проанализировать, почему ваш алгоритм не выполнился для того, чтобы исправить код. Вы не сможете создать эксперимент с помощью обычного протокола, для оценки выполнения Если в любом из указанных выше ограничениях для вас возникли проблемы, тогда используйте наш фреймворк. Наш фреймворк реализован на С# с использованием .Net Framework по двум главным причинам. Во-первых, С# стал одним из самых популярных языков программирования. Вторая причина в том, что инструменты, библиотеки и классы, доступные в .Net Framework, экономят много времени написания кода. Наш фреймворк позволяет экспериментировать в базах данных типа B от FVC2000, FVC2002 и FVC2004, и в базах данных типа А от FVC2002 и FVC2004. В этих экспериментах мы выполняем индикаторы the Fingerprint Verification Competitions (EER(%), FMR100(%), FMR1000(%), ZeroFMR(%), Time(ms) и ROC curves).  Кроме того, вы можете делать опыты даже с обычным протоколом и разными базами данных. Мы реализовали алгоритмы распознавания отпечатков пальцев, предложенный Tico и Kuosmanen, Jiang и Yau, Medina-Pérez и Qi. Важно обратить внимание на то, что вопреки алгоритму Qi - это набор шаблонов отпечатков пальцев, основывающийся на алгоритмах, мы реализовали только алгоритмы, сопоставимые протоколами ввода отпечатка пальца. Мы также сделали алгоритмы выделения признаков, предложенный Ratha, и ориентацию на получение изображения предложенную Sherlock. Данный фреймворк позволяет вам добавлять, как новые алгоритмы распознавания отпечатков, так и новые алгоритмы выделения признаков с минимальными усилиями и без перекомпиляции фреймворка. Одна из целей, которую мы преследовали, когда разрабатывали данный фреймворк, была сделать классы интерфейсов простыми и доступными. Таким образом, процесс добавления новых алгоритмов очень прост. В этой статье мы вкратце объясняем, как: экспериментировать над распознаванием отпечатков пальцев; увидеть шаблон отпечатка пальца после выполнения алгоритма; высчитать и вывести на дисплей отпечаток пальца; интегрировать ваши алгоритмы в фреймворк. Расширения данного фреймворка с целью исследований появились в https://sites.google.com/site/miguelmedinaperez/software/fprframework В данной статьей мы вкладываем следующие файлы: FingerprintRecognition_v2.2.zip: исходные файлы нашего фреймворка. Help.zip: Исходный код документации. Запуск исследования для распознавания отпечатков пальцев Извлеките файл “FingerprintRecognition.zip” и постройте решение. Далее вы можете отлаживать проект “FR.FVCExperimenter” или можете запустить “FR.FVCExperimenter.exe” в директорию, которая содержит сгенерированный узел. Данное окно откроет: В строке “Resources” записан путь к базе данных, которую вы собираетесь использовать, к примеру: “D:\PR Databases\Fingerprints\FVC2004\DB1_B”. Выберите подходящий вам тип опыта в всплывающем меню с названием “Experiment”. Используйте меню с названиями “Minutia Extractor”, “Orientation Image Extractor” и “Skeleton Image Extractor“ для выбора алгоритма, который будет использоваться для нахождения основных особенностей (отпечаток, ориентированное изображение и его образ). Используйте поле “Matcher” для выбора алгоритма распознавания отпечатков пальцев и поле “Feature Provider” для выбора алгоритма, который будет хранить и извлекать черты выбранных совпадений. Несмотря на то, что мы реализовали только одну черту распознавания для каждого совпадения, существуют сценарии, где вы используете несколько признаков для одного совпадения. Поле с названием “Properties” позволяет изменять параметры выбранного алгоритма. Кликните на кнопку “Execute Experiment” для запуска исследования. Данный опыт использует протокол оценки от the Fingerprint Verification Competitions. В этом опыте мы высчитали такие индикаторы: EER(%), FMR100(%), FMR1000(%), ZeroFMR(%), Время(мс) и  ROC-кривая. Эти индикаторы сохранены в файле с именем, сформированным в зависимости от выбранного вами алгоритма и окончанием ".Summary.csv". Этот файл сохраняется в папке с названием "Results" в той же папке, где хранятся отпечатки пальцев. Также сохранены еще два файла, один хранит в себе ложные соответствия отпечатков пальцев, другой – ложные несоответствия отпечатков. Если вы хотите сравнить 2 отпечатка и проверить их совпадение, кликните на кнопку “Visual Match”, после которой откроется форма “Visual Fingerprint Matching”. Загрузите отпечатки, которые вы хотите сравнить и нажмите кнопку “Match”. Экстрактор признаков и выбранный в “FVC Experimenter” режим также здесь используются для того, чтобы выполнить сравнение отпечатков пальцев. Ниже пример сравнения двух отпечатков. Визуализация очертаний отпечатка пальца Если вы хотите вывести картинку очертания отпечатка, тогда вам нужно использовать проект “FR.FeatureDisplay”. В поле “Fingerprint Feature Display” вы можете изменять экстрактор признаков и их изображение. В фреймворке мы используем классы для визуализации отпечатка, ориентированное изображение и скелет картинки. В следующем примере вы можете увидеть визуализацию приблизительного изображения отпечатка: Соответствие отпечатков вне фреймворка В данном разделе представлен пример использования фреймворка для сравнения двух изображений отпечатков в обычном пользовательском приложении. Он складывается из 3 шагов для сравнения 2 изображений отпечатков: загрузить картинку, извлечение признаков и их сравнение. В этом случае пользователям нужно добавить ссылки из их приложения к сборке FR.Core и FR.Medina2012. Сборки SHullDelaunayTriangulation и ImageProcessingTools должны быть добавлены в папку вывода, где появится бинарный файл. // Loading fingerprints var fingerprintImg1 = ImageLoader.LoadImage(fileName1); var fingerprintImg2 = ImageLoader.LoadImage(fileName2); // Building feature extractor and extracting features var featExtractor = new MTripletsExtractor() { MtiaExtractor = new Ratha1995MinutiaeExtractor() }; var features1 = featExtractor.ExtractFeatures(fingerprintImg1); var features2 = featExtractor.ExtractFeatures(fingerprintImg2); // Building matcher and matching var matcher = new M3gl(); double similarity = matcher.Match(features1, features2); Пример использования M3gl  показывает, как легко использовать фреймворк, и как хорошо сложен и не требует пояснений код. Правила хорошего дизайна применены в фреймворке и дают возможность пользователю легко заменить или изменить любой компонент. Добавление новых алгоритмов в фреймворк Первое, что вы должны знать - это то, что вам не нужно модифицировать приложение фреймворка для распознавания собственных алгоритмов, потому что мы используем Рефлекцию, для того чтобы загрузить все динамические алгоритмы во время выполнения. Вы можете создать столько приложений, сколько хотите в директории, которая содержит фреймворк. Для каждого нового приложения зайдите в настройки и укажите путь вывода со значением “..\bin\Release\”. Для добавления новой функции определения вам нужно наследовать с базового класса FeatureExtractor и реализовать метод ExtractFeatures(Bitmap image). Например, предположим, что вы хотите создать функцию определения типа MyFeature, дальше вы можете реализовать класс по примеру:  public class MyFeatureExtractor : FeatureExtractor {     public override MyFeature ExtractFeatures(Bitmap image)     {         // Place here your code to extract features     } } В случае, если новая функция была построена на некоторых существующих, вы можете поступить следующим образом: public class MyFeatureExtractor : FeatureExtractor {     public FeatureExtractor<List> MtiaExtractor { set; get; }     public FeatureExtractor OrImgExtractor { set; get; }     public override MyFeature ExtractFeatures(Bitmap image)     {         try         {             var mtiae = MtiaExtractor.ExtractFeatures(image);             var orImg = OrImgExtractor.ExtractFeatures(image);             return ExtractFeatures(mtiae, orImg);         }         catch (Exception e)         {             if (MtiaExtractor == null)                 throw new InvalidOperationException("Cannot extract MyFeature: Unassigned minutia list extractor!", e);             if (OrImgExtractor == null)                 throw new InvalidOperationException("Cannot extract MyFeature: Unassigned orientation image extractor!", e);             throw;         }     }     public MyFeature ExtractFeatures(List mtiae, OrientationImage orImg)     {         // Place here your code to extract features     } } Для каждой функции определения вы должны создать поставщик ресурса. Поставщик ресурса позволяет сохранять (полученный) в (выходной) файл ресурс, связанный с отпечатком. Фреймворк включает в себя поставщик ресурса для извлекания отпечатков (MinutiaListProvider), ориентированное изображение (OrientationImageProvider) и скелет картинки (SkeletonImageProvider). В следующем примере поставщика ресурсов для функции извлекания определены ниже. public class MyFeatureProvider : ResourceProvider {     public MinutiaListProvider MtiaListProvider { get; set; }     public OrientationImageProvider OrImgProvider { get; set; }     public override string GetSignature()     {         return "myf";     }     public override bool IsResourcePersistent()     {         return true;     }     protected override MyFeature Extract(string fingerprint, ResourceRepository repository)     {         try         {             var mtiae = MtiaListProvider.GetResource(fingerprint, repository);             var orImg = OrImgProvider.GetResource(fingerprint, repository);             return featureExtractor.ExtractFeatures(mtiae, orImg);         }         catch (Exception e)         {             if (MtiaListProvider == null)                 throw new InvalidOperationException("Unable to extract MyFeature: Unassigned minutia list provider!", e);             if (OrImgProvider == null)                 throw new InvalidOperationException("Unable to extract MyFeature: Unassigned orientation image provider!", e);             throw;         }     }     private MyFeatureExtractor featureExtractor = new MyFeatureExtractor(); } Пришло время создать новый алгоритм совпадения отпечатков пальцев. Предположим, вы хотите сравнить функции типа MyFeature, для этого вам необходимо создать «сравнитель» такой как: public class MyMatcher : Matcher {     public override double Match(MyFeature query, MyFeature template)     {         // Place here your code to match fingerprints     } } В случае, если вы реализовали алгоритм сравнения отпечатков, дальше вам необходимо изменить в коде ниже следующее: public class MyMatcher : Matcher, IMinutiaMatcher {     public override double Match(MyFeature query, MyFeature template)     {         List matchingMtiae;         return Match(query, template, out matchingMtiae);     }     public double Match(object query, object template, out List matchingMtiae)     {         // Place here your code to match fingerprints     } } Интегрированные встроенные алгоритмы в фреймворке Пользователям не нужно изменять фреймворк для интеграции обычных алгоритмов, так как Рефлекция загружает динамически, во время выполнения программы. В этом случае пользователи должны добавить новые алгоритмы к их собственным обычным сборкам. Для того, чтобы использовать существующие алгоритмы сравнения в фреймворке, первое, что необходимо сделать, создать поставщик ресурсов. Поставщик ресурсов позволяет сохранять (полученный) в (выходной) файл ресурсы, связанные с отпечатками пальцев. К примеру, предположим, что пользователи хотят интегрировать SourceAFIS SDK (http://www.sourceafis.org/) в фреймворк, следующая функция обеспечения может использоваться как: public class SourceAFISFeatureProvider : ResourceProvider {     protected override Person Extract(string fingerprint, ResourceRepository repository)     {         Fingerprint fp = new Fingerprint();         fp.AsBitmap = imageProvider.GetResource(fingerprint, repository);         Person person = new Person();         person.Fingerprints.Add(fp);         Afis.Extract(person);         return person;     }     public override string GetSignature()     {         return string.Format("sAFIS");     }     public override bool IsResourcePersistent()     {         return true;     }     private static AfisEngine Afis = new AfisEngine(); } А сейчас алгоритм сравнения отпечатков может быть записан в следующие классы: public class SourceAFISMatcher : Matcher {     public override double Match(Person query, Person template)     {         return Afis.Verify(query, template);     }     private static AfisEngine Afis = new AfisEngine(); } Результаты эксперимента Мы выполнили обширный эксперимент с алгоритмами сравнения отпечатков пальцев, пользуясь фреймворком. Выводы В данной статье продемонстрировали фреймворк в C# для распознавания отпечатков пальцев. Мы коротко объяснили, как выполнить опыты по распознаванию отпечатков и как интегрировать собственные алгоритмы в фреймворк. Мы предоставили несколько алгоритмов сравнения отпечатков пальцев и алгоритмов извлечения признаков, с помощью которых вы можете не только делать эксперименты, но и создать собственные приложения. Мы показали исходные коды всех алгоритмов, поэтому пользователь может использовать любую часть кода так же, как и любой компонент программного обеспечения. Источник: http://www.codeproject.com/Articles/97590/A-Framework-in-C-for-Fingerprint-Verification
4 причини навчатися за відео курсами на ITVDN

Автор: Влад Сверчков

Величезна база знань. Гнучкий та зручний формат навчання. Якісний контент. Низька ціна. Висновки. ITVDN – це освітня онлайн платформа, яка дозволяє опановувати затребувані на ІТ-ринку мови програмування, бібліотеки, фреймворки, інші супутні технології, а також цілі ІТ-спеціальності. Український навчальний простір багатий на проєкти освітнього характеру, але на їхньому фоні ITVDN вирізняється своєю унікальністю та має декілька ключових переваг. І сьогодні ми пропонуємо вам ознайомитися з ними. 1. Величезна база знань Перша головна особливість ITVDN – це доступ до величезної бази знань, котра є аналогом сучасної бібліотеки. Тут зібрано понад 250 відео курсів з найпопулярніших напрямків вивчення інформаційних технологій, які ми накопичили за останні 10 років: FrontEnd; BackEnd мовами Python, Java, C#, PHP, Ruby та іншими; мобільна розробка; вебдизайн; тестування; розробка ігор; технології для роботи з базами даних тощо. Звісно, ІТ – дуже динамічна галузь: постійно оновлюються мови програмування, бібліотеки й фреймворки, з’являються нові інструменти. Ми уважно стежимо за трендами та релізами й підтримуємо актуальність наших матеріалів за рахунок регулярного випуску нового навчального контенту. Сюди входять не тільки відео курси, а й навчальні програми за спеціальностями, онлайн тренінги та вебінари зі спеціалістами з Meta, Google, EPAM, GlobalLogic тощо.  Ви можете заглибитися у вивчення однієї конкретної сфери, наприклад у FrontEnd розробку, де є десятки курсів від різних авторів. Або ж можете вивчати різні напрямки одночасно і стати універсальним FullStack спеціалістом. Даний підхід дозволяє отримати всебічні знання і розширити професійний кругозір, що виділить вас серед інших кандидатів на перегрітому ринку ІТ. Такі спеціалісти привертають значно більше уваги зі сторони рекрутерів, і мають вищі шанси на успішне працевлаштування. 2. Гнучкий та зручний формат навчання На ITVDN ви можете вивчати програмування і технології в зручному для вас темпі: Можливість навчатися 24/7. Відео курси дозволяють опановувати матеріал у будь-який час і з будь-якої точки світу, оскільки уроки вже записані. Це вигідно відрізняє їх від онлайн курсів, де необхідно бути присутнім на уроці в зазначений час. Зручне поєднання з іншими активностями. У вас є робота, ви навчаєтесь у школі/університеті, активно займаєтеся сім’єю, але прагнете розвиватися в ІТ? Формат відео курсів дозволить вам з легкістю поєднувати різні види діяльності і проводити час ефективно. Регулювання інтенсивності. Ви самі визначаєте, коли і скільки часу виділити на навчання з огляду на вашу зайнятість, продуктивні години, самопочуття тощо. Займайтеся в тому темпі, який для вас найбільш зручний та ефективний. Повторення тем. Ви можете переглядати складні теми стільки разів, скільки вам потрібно для належного розуміння матеріалу, а прості – пропускати або переглядати в прискореному режимі. Додаткові матеріали для збагачення знань та навичок. В ході навчання вам будуть доступні: конспекти з кожного уроку; д/з, які можна відправити на перевірку (з отриманням фідбеку); консультації із сертифікованим розробником; Інтерактивний практикум, де ви зможете відточити свої навички написання програмного коду; тестування для перевірки засвоєного матеріалу з подальшим отриманням сертифікату. Навчання під час блекаутів. На ITVDN доступний пакет підписки «Преміум Plus», котрий дозволяє завантажувати відео уроки на ваші девайси і переглядати їх навіть за умов повного зникнення світла та інтернету. 3. Якісний контент Авторами відео курсів є сертифіковані розробники з профільною освітою та комерційним досвідом роботи. Кожен відео урок ґрунтується на унікальному авторському досвіді, який він заробив, пройшовши складний шлях проб і помилок. В результаті це дозволило йому успішно здійнятися кар’єрною драбиною в ІТ. А ще це дозволяє впевнитися, що ви отримуєте не «воду», а саме прикладні знання, котрі використовуються на реальних проєктах. Також ми регулярно оновлюємо курси, враховуючи останні тенденції та новинки у світі технологій, завдяки чому ви отримуєте актуальну інформацію і вивчаєте саме те, що користується попитом на нинішньому ринку ІТ. 4. Низька ціна Навчання на ITVDN за відео курсами є значно дешевшим, ніж інші формати отримання знань на інших ресурсах. На це впливає одразу декілька факторів: один курс може бути проданий тисячам студентів без додаткових витрат на викладачів чи інфраструктуру. Це дозволяє окупити загальні витрати на створення навчального контенту; процеси реєстрації, перевірки знань та сертифікації студентів автоматизовані, що знижує потребу в персоналі для адміністративної підтримки; ви навчаєтесь у власному темпі з можливістю повторного перегляду складних тем без потреби у додаткових заняттях або постійних консультаціях з викладачами в реальному часі. Це зменшує навантаження на викладацький персонал; наша головна аудиторія – українці. Ми прагнемо бачити нашу країну серед передових технологічних держав, а для цього ІТ-освіта має бути доступною для кожного нашого співвітчизника. Зазначимо, що ми не надаємо послуги громадянам росії та білорусі. Крім того, на ITVDN існує можливість оплати частинами через monobank та ПриватБанк – коли ви розбиваєте платіж на більш дрібні та сплачуєте невеликі суми щомісяця без комісії. Це робить навчання ще більш доступним для широкого кола людей. Ви можете інвестувати у своє навчання без відчутного фінансового навантаження, отримуючи при цьому якісні знання та навички. Висновки Навчання на ITVDN у форматі відео курсів – це унікальна можливість отримати якісну ІТ-освіту, яку може дозволити собі кожен. Проєкт, створений в Україні українськими розробниками, що пропонує величезну базу знань, яка дозволяє заглибитися в обраний напрямок або вивчати різні аспекти інформаційних технологій: від FrontEnd та BackEnd розробки до тестування, вебдизайну, створення ігор на Unity тощо. Крім того, наш проєкт не має аналогів і є дійсно унікальним для українського ринку. Гнучкий та зручний формат навчання за відео курсами забезпечує комфортний процес засвоєння матеріалу, а якісний контент, створений сертифікованими ІТ-спеціалістами з досвідом, гарантує актуальність матеріалів, відсутність зайвого та високу віддачу від навчання. Крім того, доступна ціна та можливість оплати частинами роблять платформу ITVDN найкращим вибором для тих, хто прагне професійного розвитку в ІТ-сфері за максимально дружньою ціною. Навчайтеся з ITVDN та досягайте намічених висот в ІТ!
Онлайн навчання програмуванню: підводні камені та поради

Автор: Влад Сверчков

Двадцать первый век знаменует “бум” информационных технологий. Научно-технические достижения за последние двадцать лет достигли значительных высот и позволили человечеству выйти на новый уровень жизни. Прогресс не обошел стороной и сферу образования - с развитием персональных компьютеров, сети Интернет и других приспособлений обработки информации практически у каждого человека появилась возможность обучаться не выходя из дома. Возможность получения знаний в онлайн-режиме - одно из главных достижений нашего века. На сегодняшний день особый спрос на онлайн-обучение прослеживается в связи со сложившимися карантинными условиями. Зачем зря терять время и сидеть сложа руки, если можно извлечь из ситуации максимум выгоды, прокачав свои знания? Образовательная платформа ITVDN предлагает вам использовать свой потенциал и технологию онлайн-обучения, чтобы сделать первый шаг навстречу одной из наиболее востребованных профессий нашего времени - профессии программиста.    Возможно ли стать программистом, обучаясь онлайн? Конечно! Просторы интернета полны различных образовательных ресурсов. Если рассматривать англоязычные платформы с доступом к IT-курсам, стоит отметить: MIT OpenCourseWare - онлайн-курсы от Массачусетского института технологий - одного из самых престижных технических учебных заведений мира;  edX - платформа, которая содержит курсы от более чем 140 ведущих ВУЗов мира; Coursera - проект для публикации образовательных материалов, основанный профессорами математики Стэнфордского университета; Pluralsight -  онлайн-платформа с большим количеством всевозможных видео курсов. Если говорить о русскоязычных онлайн-ресурсах: Hexlet - проект, содержащий программы по обучению 6 IT-специальностям; JavaRush - онлайн-курс по программированию на Java; ITVDN - образовательная онлайн-платформа, содержащая полноценные программы обучения по 12 самым популярным специальностям. В каталоге ITVDN свыше 180 видео курсов по различным языкам программирования и информационным технологиям; другие онлайн-ресурсы. Наиболее качественными являются англоязычные курсы, так как английский - интернациональный язык и преимущественное количество форумов с полезной информацией ведется именно на нем. Если ваше владение языком Туманного Альбиона не является столь продвинутым и вы предпочитаете русскоязычные платформы, мы советуем вам ITVDN. Это один из лидирующих образовательных IT-ресурсов в СНГ, который начал свою работу в 2014-м году и на данный момент имеет в своем распоряжении огромную базу видео уроков, которая помогает всем, кто изучает программирование и информационные технологии, обучаться и становиться профессионалами выбранной IT-специальности.    Какой язык программирования учить? Зависит от IT-сферы, в которой вы хотите себя реализовать. Если это FrontEnd разработка (создание внешнего вида веб-сайта), то не обойтись без JavaScript + языки верстки HTML и CSS. Если BackEnd (создание всего, что находится “под капотом” сайта), то здесь выбор шире -  PHP, Java, C#, Python, Ruby, Go, JavaScript (Node.js). В мире машинного обучения очень важен Python и его библиотеки. Компьютерные игры крупных масштабов и с высокой производительностью создают на С++, рангом поменьше - на движке Unity. Это очень поверхностные описания того, какие языки надо учить для овладения определенной IT-специальностью, поскольку каждая профессия в IT имеет целый перечень требуемых к изучению технологий. С полным списком требований к некоторым профессиям вы можете ознакомиться в наших статьях, перейдя по ссылке. Как учиться онлайн самостоятельно? Как правильно спланировать свое обучение? Планировка - очень важный и ответственный момент в онлайн-обучении. Вы находитесь дома под воздействием множества отвлекающих факторов - будь то ваши сожители, домашний питомец, сосед с перфоратором, вкусно пахнущая еда из кухни, открытый ютуб или интересная компьютерная игра. Важно не только избавиться от всех помех, но и следовать составленному под себя учебному плану. После определения желаемой IT-профессии и выбора образовательной онлайн-платформы необходимо запастись мотивацией. Но одной только мотивации будет мало, причем она быстро иссякает. Следует составить расписание, в котором будет органично сочетаться теория, практика, выполнение домашнего задания и тестирование (проверка знаний). Мы предлагаем следующее:   Прежде всего выделите время на онлайн-учебу и организуйте регулярные занятия. К примеру, с 19:00 до 21:00 каждый день вы занимаетесь онлайн-обучением и ничем иным (небольшие перерывы допускаются, естественно). Работа короткими интенсивными интервалами улучшит общую продуктивность урока. Учебный процесс не должен прерываться готовкой пищи, выгулом собаки, разговорами по мессенджеру и прочими делами, для которых также находится место в вашей жизни. Все образовательные интернет-ресурсы используют схожую тактику: вначале вам дается теория, затем предлагается решить несколько практических задач, а для закрепления знаний - домашнее задания по теме. Придерживайтесь ее. Распределите ваше учебное время на ознакомление и изучение материала, а также для последующей практики (включая прохождение тестов). Домашнее задание лучше оставить на следующий день либо сделать длительный перерыв перед ним, чтобы дать вашему мозгу спокойно обработать новую информацию.   Проходите тесты, предусмотренные выбранной образовательной платформой. Помимо проверки усвоения материала тестирование способствует развитию навыков эффективного написания кода. На ITVDN для усовершенствования навыков создания кода был разработан специальный интерактивный тренажер, а для подтверждения знаний и получения соответствующего сертификата мы предлагаем testprovider.com.    Разрабатывайте собственный интересный проект в специально отведенные дни: придумайте себе задачу (либо поищите в интернете) и занимайтесь  ее постепенной реализацией, используя изученные темы - так вы и освежите знания, и попрактикуетесь в написании кода. Если выйдет неплохой проект, добавите его в свое портфолио. Используйте гугл и форумы для программистов. Профессия программиста предусматривает широкое использование сети Интернет в процессе поиска решения возникающих проблем. Вам очень пригодятся такие сайты как stackoverflow.ru, quora.com и прочие, где вы найдете ответы на программистские “как?” и “почему?”. Какие подводные камни у онлайн-обучения?   Потеря мотивации. Изучение программирования - это длительный и кропотливый процесс. Именно на мотивацию делают ставку большинство новичков и именно поэтому большинство очень быстро “выгорают” и прекращают обучение. Регулярные занятия, выполнение домашних заданий, закрепление новых тем через тестирование, разработка собственного проекта, участие в различных событиях, касающихся выбранной IT-профессии (хакатоны, тренинги и прочие активности) создадут благоприятные условия для подпитывания ваших сил и будут давать вам уверенность для продвижения вперед. Отсутствие ментора и контроля. В среде онлайн-обучения отсутствует жесткий контроль, поскольку вы сам себе хозяин. Вы можете поддаваться лени, ничего не учить, не практиковаться и вовсе “забросить” учебу. Это главный камень преткновения в интернет-обучении. Над вами нет никого, перед кем вы бы несли ответственность за свои результаты и кто вами курировал бы.  Сколько стоит онлайн-обучение? Есть три варианта онлайн-обучения: С использованием сервиса YouTube и документаций, которые свободно распространяются в интернете. Выбрав эту опцию, вы будете обучаться бесплатно. Но эффективность данного варианта оставляет желать лучшего. Приобретение видео курсов. Здесь вам придется потратить небольшую сумму денег. Взамен вы получите доступ к видео базе, над которой трудились профессионалы, домашним заданиям, дополнительным обучающим материалам, конспектам по рассмотренным темам, онлайн-тестам. Онлайн-обучение в мини группе с тренером. Данный вариант самый дорогостоящий, но и эффективность его максимально высока, так как вы получаете возможность дистанционно общаться с ментором и небольшой группой учащихся через специальные программы (Skype, Zoom и т. д.), задавать вопросы и получать развернутые ответы, просматривать видеозаписи уроков. Проблема с мотивацией также решена - вы вложили свои деньги и над вами есть куратор, который следит за вашими успехами и выполнением домашних заданий. Таким образом, если вы не хотите тратить много денег либо и вовсе желаете освоить программирование бесплатно, подумайте над выбором одного из первых двух вариантов. Если же вам нужно больше общения с ментором, обратите внимание на третью опцию. На ITVDN она представлена новым форматом обучения -  Live Online. Занятия проходят в небольшой группе в форме регулярных онлайн встреч, на которых объясняется новый материал, обсуждаются нюансы выполнения практических заданий, есть проверка ДЗ и чат для общения с одногруппниками, а также доступ ко всем видео курсам ITVDN по выбранной специальности. Опция онлайн-обучения с тренером доступна на ITVDN по 3-м специальностям: .NET Developer, FrontEnd Developer и Java Developer. Параллельно процессу обучения вы также создаете собственный курсовой проект, который украсит ваше портфолио и станет неплохим подспорьем во время дальнейшего трудоустройства. Надеемся, что наши советы помогли вам составить целостную картину онлайн-обучения.   Желаем вам здоровья и успехов в прокачке знаний! Оставайтесь на ITVDN!
Факторизація цілих чисел

Автор: Редакція ITVDN

Введение Факторизация целых чисел позволяет раскладывать на множители (факторинг) большие числа (Int64) и проверять простоту целых чисел [1,2]. Приведем пример больших (14 ... 18-ти значных) простых чисел, которые можно использовать для тестирования или оценки. biggest 18-digit primes 999999999999999989 999999999999999967 999999999999999877 biggest 17-digit primes  99999999999999997 99999999999999977 99999999999999961 biggest 16-digit primes 9999999999999937 9999999999999917 9999999999999887 biggest 15-digit primes 999999999999989 999999999999947 999999999999883 biggest 14-digit primes 99999999999973 99999999999971 99999999999959 Кодовый модуль демонстрирует практическое использование алгоритма, написанного в C# (4.0). using System; using System.Collections.Generic; namespace Infosoft.MathShared {        /// Integers: Properties and Operations        public  static partial class Integers        { #region Prime Numbers <100              private static readonly int[] Primes =              new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23,              29, 31, 37, 41, 43, 47, 53, 59,              61, 67, 71, 73, 79, 83, 89, 97 }; #endregion              // starting number for iterative factorization              private const int _startNum = 101; #region IsPrime : primality Check              ///              /// Check if the number is Prime              ///              /// Int64              /// bool              public static bool IsPrime(Int64 Num){                     int j;                     bool ret;                     Int64 _upMargin = (Int64)Math.Sqrt(Num) + 1;;                     // Check if number is in Prime Array                     for (int i = 0; i < Primes.Length; i++){                            if (Num == Primes[i]) { return true; }                     }                     // Check divisibility w/Prime Array                     for (int i = 0; i < Primes.Length; i++) {                            if (Num % Primes[i] == 0) return false;                     }                     // Main iteration for Primality check                     _upMargin = (Int64)Math.Sqrt(Num) + 1;                     j = _startNum;                     ret = true;                     while (j <= _upMargin)                     {                            if (Num % j == 0) { ret = false; break; }                            else { j = j + 2; }                     }                     return ret;              }              ///              /// Check if number-string is Prime              ///              /// string              /// bool              public static bool IsPrime(string StringNum) {                     return IsPrime(Int64.Parse(StringNum));              } #endregion #region Fast Factorization              ///              /// Factorize string converted to long integers              ///              /// string              /// Int64[]              public static Int64[] FactorizeFast(string StringNum) {                     return FactorizeFast(Int64.Parse(StringNum));              }              ///              /// Factorize long integers: speed optimized              ///              /// Int64              /// Int64[]              public static Int64[] FactorizeFast(Int64 Num)              { #region vars                     // list of Factors                     List _arrFactors = new List();                     // temp variable                     Int64 _num = Num; #endregion #region Check if the number is Prime(<100)                     for (int k = 0; k < Primes.Length; k++)                     {                            if (_num == Primes[k])                            {                                   _arrFactors.Add(Primes[k]);                                   return _arrFactors.ToArray();                            }                     } #endregion #region Try to factorize using Primes Array                     for (int k = 0; k < Primes.Length; k++)                     {                            int m = Primes[k];                            if (_num < m) break;                            while (_num % m == 0)                            {                                   _arrFactors.Add(m);                                   _num = (Int64)_num / m;                            }                     }                     if (_num < _startNum)                     {                            _arrFactors.Sort();                            return _arrFactors.ToArray();                     } #endregion #region Main Factorization Algorithm                     Int64 _upMargin = (Int64)Math.Sqrt(_num) + 1;                     Int64 i = _startNum;                     while (i <= _upMargin)                     {                            if (_num % i == 0)                            {                                   _arrFactors.Add(i);                                   _num = _num / i;                                   _upMargin = (Int64)Math.Sqrt(_num) + 1;                                   i = _startNum;                            }                            else { i = i + 2; }                     }                     _arrFactors.Add(_num);                     _arrFactors.Sort();                     return _arrFactors.ToArray(); #endregion              } #endregion        } } Точки обзора Тест на проверку простоты 18-ти значного числа (999999999999999989), т.е. процедура, которая определяет, являются ли целые числа простыми, это лучший способ проверки факторинга программного обеспечения. Если вычисления занимают слишком много времени (например, когда используется мобильная платформа с низким уровнем обработки большого количества численных данных), возьмите меньшее число, но тоже 18-ти значное: 324632623645234523. Чтобы получить не такую тривиальную запись, как i = i + 2, или i + = 2, необходимо исходный код увеличить в два раза. i ++; i ++; Даный фрагмент кода был использован для сравнения производительности трех методов возрастания целых чисел:  using System; using System.Diagnostics; namespace IncrementEfficiencyTest {        class Program        {              private const Int64 _max = 1000000000; // 1 billion              private const int _cycles = 5;              static void Main(string[] args)              {                     Stopwatch sw = new Stopwatch();                     Console.Write("{0} on {1}", "i++;i++:", String.Concat(_cycles, " cycles with ", _max, " max: "));                     sw.Restart();                     for (int count = 0; count < _cycles; count++)                     {                            Int64 i = 0;                            while (i < _max) { i++; i++; }                     }                     sw.Stop();                     Console.WriteLine("{0} elapsed.", sw.Elapsed);                     Console.Write("{0} on {1}", "i=i+2", String.Concat(_cycles, " cycles with ", _max, " max: "));                     sw.Restart();                     for (int count = 0; count < _cycles; count++)                     {                            Int64 i = 0;                            while (i < _max) { i = i + 2; }                     }                     sw.Stop();                     Console.WriteLine("{0} elapsed.", sw.Elapsed);                     Console.Write("{0} on {1}", "i+=2", String.Concat(_cycles, " cycles with ", _max, " max: "));                     sw.Restart();                     for (int count = 0; count < _cycles; count++)                     {                            Int64 i = 0;                            while (i < _max)  { i += 2; }                     }                     sw.Stop();                     Console.WriteLine("{0} elapsed.", sw.Elapsed);                     Console.ReadKey();              }        } Чтобы минимизировать потенциальные побочные эффекты теста, следует работать в нескольких циклах (5 циклов) с последующей апроксимацией нескольких результатов тестирования и не нужно реализовывать вызовы функций , потому что оценка синхронизации может искажаться. Основываясь на статистических данных, самый быстрый способ увеличения числа Int64 в 2 раза можно достичь через составленное уравнение: i = i + 2 (5,589 сек для всей процедуры тестирования), вместе с i + = 2 (5,625 сек) и удвоением и ++; i ++;  "leading from behind" с оценкой производительности в 11,907 сек. Соответствующая поправка была сделана в факторизации первичных чисел (теперь выводится i = i + 2). Параллельный алгоритм для факторинг-теста При использовании параллельных алгоритмов факторизации можно значительно увеличить производительность теста. Параллельне алгоритмы факторизации region GetFirstFactorParallel(Int64 Num) algorithm internal static Int64 GetFirstFactorParallel(Int64 Num) {        // use concurrent stack to store non-trivial factor if found        ConcurrentStack _stack = new ConcurrentStack();        // object to specify degrees of parallelism        ParallelOptions _po = new ParallelOptions();        try        {              // return value initially set to 1              Int64 _ret = 1;              // step 1: try to factor on base 2, return if OK              if (Num % 2 == 0) return 2;              // step 2: try to factor on base 3, return if OK              if (Num % 3 == 0) return 3; #region parallel algo to find first non - trivial factor if exists              // set upper limit              Int64 _upMargin = (Int64)Math.Sqrt(Num) + 1;              // number of CPU cores              int _countCPU = System.Environment.ProcessorCount;              // max degree of parallelism set equal to _cpuCount              _po.MaxDegreeOfParallelism = _countCPU;              Parallel.For(0, 2, _po, (i, _plState) = >              {                     // starting number for inner loops (5 and 7)                     int _seed = 5 + 2 * i;                     // inner loops running in parallel;                     // notice that because input Num was already tested for factors 2 and 3,                     // then increment of 6 is used to speed up the processing,                     // thus in dual core CPU it looks like:                     // 5, 11, 17, 23, 29, etc. in first thread                     // 7, 13, 19, 25, 31, etc, in second thread                     for (Int64 j = _seed; j < _upMargin; j += 6)                     {                            // exit loop if stack contains value                            if (_stack.Count != 0) { break; }                            // check divisibility                            if (Num % j == 0)                            {                                   // push non-trivial factor to ConcurrentStack and exit loop                                   if (_stack.Count == 0) { _stack.Push(j); }                                   break;                            }                     }              }); #endregion              // return the value in ConcurrentStack if exists, or 1              return (_stack.TryPop(out _ret)) ? _ret : 1;        }        catch { throw; }        finally { _po = null; _stack = null; } } #endregion Источник: http://www.codeproject.com/Tips/155308/Fast-Prime-Factoring-Algorithm
Основи AngularJS на практиці

Автор: Редакція ITVDN

Введение AngularJS – фреймворк-библиотека Javascript, разработанная для создания одностраничных приложений на основе MVC (Model-View-Controller) шаблона. Будем осваивать данную технологию на практике. Создадим HTML страничку со стандартной структурой. Далее нам нужно преобразовать ее в одностраничное приложение. Для этого подключим AngularJS к своей странице, добавив в тег с данным кодом: <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> script> Следующим шагом мы явно укажем на то, что наша страница является AngularJS приложением. Нужно добавить ng-app директиву, которой мы обозначим корневой элемент приложения. Зачастую таким элементом выступает тег или же тег . Добавим эту директиву к :  <!DOCTYPE html> <html ng-app=""> <head>     <title>title>     <meta charset="utf-8">     <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">     script> head> <body> body> html> Проверим,  все ли работает, добавив небольшое выражение для подсчета произведения чисел 123 и 45. В AngularJs все выражения записываются в двойных скобках. Добавим в параграф со следующим содержимым: <p>Результат произведение чисел 123 и 45 равен : {{ 123 * 45 }}p> Запустим в браузере:  Теперь у нас есть готовый шаблон приложения, который мы будем использовать во всех последующих примерах. AngularJS позволяет разработчику легко взаимодействовать с пользовательским вводом. Для этого есть соответствующая директива ng-model, которая связывает значения HTML элементов контроля (teaxtarea, input etc.) с приложением. Использовать эти данные поможет директива ng-bind, добавив эти данные во View (элемент MVC) и отобразив их на странице. Применим полученные знания на практике. В созданный ранее шаблон добавим поле для ввода <input> с директивой ng-model и параграф для вывода данных c директивой ng-bind. Код странички: <!DOCTYPE html> <html ng-app=""> <head>     <title>title>     <meta charset="utf-8">     <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">     script> head> <body>     <p>Ввведте свое имя:p>     <input type="text" ng-model="yourName">     <p>Здравствуй, <span ng-bind="yourName">span>p> body> html> Откроем в браузере: Теперь попробуйте ввести свое имя в поле для ввода. Давайте добавим в данный пример дефолтное значение имени, к примеру Анна. Сделаем это, конечно же, с помощью директивы ng-init, которая позволяет инициализировать любую переменную AngularJS приложения. В строку  добавим директиву ng-init. <input type="text" ng-model="yourName" ng-init="yourName='Aнна'"> Посмотрим изменения в браузере: Теперь мы имеем значение по дефолту – Анна, но все так же можем изменять его: Вывод данных в этом примере можно сделать еще одним способом, а именно, использовав выражение. Заменим на {{yourName}}. <p>Здравствуй, {{ yourName }}p> Открыв страницу, мы не увидим абсолютно никаких изменений, а все потому, что выражения в AngularJS связывают данные со страничкой точно так же, как и ng-bind директива. Как упоминалось в статье ранее, AngularJS строит приложения на основе MVC. Часть модель – представление (Model - View) определяется с помощью директивы ng-app. Контроллер в свою очередь определяется директивой ng-controller. Рассмотрим пример с использованием контроллера страницы. Создадим страничку со списком гостей, которых Вы пригласите на свой день рождения. К созданному ранее шаблону добавим контроллер, а так же установим имя для приложения. В тег внесем следующие изменения: <html ng-app="firstApp" ng-controller="firstController"> Далее добавим с типом text для введения имени гостя и еще один с типом submit для добавления гостя в список. Также добавим с полем для вывода списка и чекбоксом с типом checkbox для того, чтобы можно было удалять тех, кто не придет на ваш праздник. В данный добавим директиву ng-repeat, отвечающую за повторение данных в обозначенном контейнере. <!DOCTYPE html> <html> <head>     <title>title>     <meta type="utf-8">     <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js">script> head> <body ng-app="firsApp" ng-controller="firstController">     <h2>Мои гости:h2>     <form ng-submit="addGuest()">         <input type="text" ng-model="guestsInput" size="50" placeholder="Введите имя гостя">         <input type="submit" value="Добавить гостя">     form>     br>     <div ng-repeat="guest in listOfGests">         <input type="checkbox" ng-model="guest.come"> <span ng-bind="guest.guestName">span>     div>     <p><button ng-click="remove()">Удалить гостя button>p> body> html> Осталось добавить скрипт, который будет содержать функции для работы с элементами нашего приложения. Замечу, что все функции будут расположены в контроллере приложения. Скопируйте и добавьте после закрывающегося тега параграфа с кнопкой <p><button ng-click="remove()">Удалить гостя button>p> следующий код: <script>         var app = angular.module('firsApp', []);         app.controller('firstController', function($scope) {             $scope.listOfGests = [{guestName:'Я любимый', come:false}];             var countOfGuests = 1;             $scope.addGuest = function() {                 $scope.listOfGests.push({guestName:$scope.guestsInput, come:false});                 $scope.guestsInput = "";                 countOfGuests++;                 checkNumberOfGuests();             };             $scope.remove = function() {                 var oldGuests = $scope.listOfGests;                 $scope.listOfGests = [];                 angular.forEach(oldGuests, function(guest) {                     if (!guest.come) $scope.listOfGests.push(guest);                     countOfGuests--;                 });                 checkNumberOfGuests()             };             function checkNumberOfGuests(){                 if(countOfGuests <= 2){                     alert("Маленькая вечеринка тоже не плохо! Не печалься! Лучших друзей не бывает много!");                 }else if(countOfGuests >= 9){                     alert("Праздник?! ВЕЧЕРИНИЩЕ!");                 }else{                     alert("Узкий круг самых близких, это всегда хорошо!");                 }             } script> В данном коде у нас есть три функции: добавление и удаление гостя и проверка количества гостей. В функции добавления мы берем введенные данные guestsInput и добавляем их в лист listOfGests. Устанавливаем значение чекбокса в false (в нашем случае, это значит, что человек придет / если значение true, то есть галочка стоит - значит не придет), после чего очищаем поле ввода. Далее увеличиваем счетчик гостей и вызываем функцию проверки их количества. В функции удаления мы берем список гостей listOfGests и проверяем значение чекбокса каждого гостя, определяя, кто придет, а кто нет. Удаляем тех, кто отмечен галочкой (не пойдет) и уменьшаем счетчик элементов. Функция проверки количества гостей очень проста, поэтому подробнее мы ее разбирать не будем. Давайте откроем пример в браузере и поработаем с ним: Добавим несколько гостей: С изменением количества гостей содержимое оповещений будет меняться. Когда вы добавите больше 9 друзей, тогда увидите такое оповещение: Поздравляем, вот Вы и создали свое первое одностраничное приложение с помощью AngularJS!
ТОП помилок S'ales-менеджерів

Автор: Андрій Афанасьєв

Введение Приходилось ли Вам, работая в интернет-агенстве или веб-студии, сталкиваться с ситуациями, когда у Вас возникали разногласия с S’ales-менеджерами (менеджерами по продажам услуг компании)? Лично у меня они возникают чуть ли не ежедневно. Вроде бы и цели у нас общие – выстраивать мощный бизнес и зарабатывать хорошие деньги. Но технари и менеджеры по продажам , оказывается, настолько разные по своему мышлению, и идем мы к этим глобальным целям разными дорогами. В данной статье я хочу  разобрать психотип технического специалиста и продажника. Исходя из этого мы сможем понять: Почему возникают спорные ситуации между отделом продаж и отделами по производству; Какие стандартные “косяки” допускают менеджеры по продажам, которые в дальнейшем существенно вредят производственникам; Как попытаться избавиться от этих ошибок раз и навсегда. Основные особенности психотипа технаря Техническими специалистами в такой структуре, как веб-студия, являются SEO-специалисты, PPC-специалисты, программисты, маркетологи, аккаунт-менеджеры, менеджеры проектов, руководители отделов и другие позиции, которые в этом перечне я случайно мог пропустить. Основная цель технаря – максимально качественно закрывать вопросы разработки стратегии и реализации работ для достижения максимального результата, будь то контекстная реклама, поисковое продвижение или разработка сайтов. Мышление и построение работы данных категорий сотрудников построено преимущественно на: Систематичности; Педантичности; Четкой последовательности действий, которые формируются на составлении четких дедлайнов (сроков) по каждой задаче и процессу; Тайм-менеджменте (детальном планировании всего рабочего времени); Отсутствии какого-либо хаоса и утверждение всех нюансов с заказчиком. По моему мнению, это идеальная схема построения рабочего процесса технического специалиста, который сможет четко и слаженно, как часовой механизм, решать свои задачи в рамках той компании, в которой работаю сейчас я. С большой вероятностью, у других компаний и фирм данный секрет успеха отличается от того, что приведен выше. Рассмотрим теперь особенность настроев S’ales-менеджеров. Настрои сейлзов Как бы гениально это не прозвучало, но основная задача продажника – много продавать. Продавец должен быть стрессоустойчивым, уметь подать продукты компании в такой упаковке, чтобы покупатель, не раздумывая, хотел стать клиентом компании. Исходя из этого, менеджеры по продажам пользуются следующими векторами в своей работе: Нагенерировать как можно больше лидов (людей, которые проявили хотя бы минимальный интерес к продукту) путем обработки, например, входящих обращений или холодных звонков; Постоянно контактировать с лидами до момента, пока клиент все-таки не подпишет договор и не заплатит деньги; Назначить как можно больше встреч, где убедить клиента в целесообразности и необходимости услуг проще, чем по телефону; Выполнить план продаж путем заключения как можно большего количества договоров. Такие настроения оправданы, потому что зачастую мотивация S’ales-менеджера состоит из небольшой ставки + хорошего процента от суммы бюджетов подписанных договоров. Поэтому основной кусок пирога заложен именно в этой процентной части. А теперь про типичные «косяки» продажников Настоящий менеджер по продажам – это охотник за процентами. На этом я уже поставил акцент в предыдущем пункте. Когда я наблюдаю за своими коллегами-сейлзами, порой у меня возникает ощущение, что они готовы на все ради продажи. Извините, я без критики и осуждения. Просто такое рвение доставляет нам неприятности и проблемы следующего характера: Продажа ради продажи. Иногда к нам на стол попадает такой проект, с которым ты просто не знаешь, что делать, либо который со старта обречен на провал. Проходит месяц-два, и клиент отказывается от услуги, потому что, к примеру, SEO на первых порах не тот тип рекламы, который нужен проекту. Несогласованный или весьма заниженный бюджет на проект. Бывают такие ситуации, что ко мне подходят и говорят что-то типа: “Клиент очень «горячий». Можем подписать прямо сейчас, если ты дашь добро. У него бюджет 3500 грн., из которых на ссылки 1000 грн.”. И это при среднем чеке компании, например, в 6000 грн. и очень конкурентной тематике проекта типа котлов или окон. Увы, с таким бюджетом нет смысла заходить на рынок. Да и коммерческий интерес компании-исполнителя невелик. Не доходит  ключевая информация. Для лучшего понимания проблематики смоделирую ситуацию. Например, у нового клиента компании есть два сайта A и B одной тематики. Сайт A клиент хочет продвигать, а сайт B – старый, который он трогать не хочет. Сайт B имеет уже какую-то видимость и позиции, но является аффилиатом по отношению к A, поэтому отдел SEO предлагает клиенту склеить 301 редиректом непродвигаемый сайт с продвигаемым. Когда поступает такое предложение, клиент возмущенно говорит, что сайт B уже продвигался ранее другой компанией и попал под текстовый фильтр Panda, и основная идея появления нового сайта A и его дальнейшей раскрутки связана именно с этим. И немаловажно то, что заказчик утверждает, что вся эта информация была донесена до менеджера, который подписывал договор. Чья недоработка и в чем она заключается, я думаю, понятно… Обещание золотых гор. Ради подписанного договора сейлз на эмоциях может пообещать клиенту четкие сроки и даже гарантии на вывод в ТОП. Это большая ошибка, которую потом придется разгребать аккаунт-менеджерам. Клиента нужно обязательно ориентировать на какие-то примерные сроки, но давать 100% гарантии на вывод в ТОП никак нельзя. Гарантировать можно только максимально внимательный и профессиональный подход и перечень работ, прописанных  в договоре. Включение в общий бюджет дополнительных доработок. Иногда те лиды, которые являются «горячими» или «теплыми» манипулируют до безумия заинтересованным в продаже менеджером. Это может заключаться в том, что заказчик обещает долгосрочное сотрудничество по SEO-оптимизации или продвижению, если в общий бюджет будут включены некоторые доработки по сайту. И очень часто заказчики почему-то считают, что все они весьма простые типа CTRL+C и CTRL+V и все готово. То ли от незнания специфики правок, то ли от желания докрутить клиента до продажи как можно быстрее, менеджеры часто обещают: ”Все просто. Все будет. Все сделаем!” И в 80% случаев эти доработки оказываются такого масштаба, что в рамках лояльности их не сделаешь и нужно оценивать отдельными сроками и бюджетами. На эти грабли менеджеры наступают регулярно и до тех пор, пока их не заставляют самостоятельно выруливать такие ситуации. Такое нужно мгновенно искоренять! Это далеко не весь список казусов, которые происходят с менеджерам по продажам. Это золотая классика, которая, я уверен, повторяется у многих компаний и фирм данного сегмента бизнеса. Как искоренить весь этот бардак? Это намного проще, чем может показаться на первый взгляд. Для этого всего лишь нужно:  Ввести обязательную систему брифования со стандартным списком вопросов, которые еще на этапе переговоров помогут получить важную информацию для составления более-менее прозрачой картины о проекте будь-то SEO, контекст или веб; Внедрить многоуровневое утверждение проектов через руководителей отдела продаж,  отдела по производстенной части и аккаунтинга. Пока каждый руководитель детально не изучит условия договора и особенности заказа, ничего подписано быть не должно! Использовать систему передачи проекта в письменном виде руководителям отделов со стоимостями по проектам. (Как, сколько, за что клиент заплатил и что должен в итоге получить); Проведение периодических ликбезов и занятий, на которых менеджеры по продажам могут задавать вопросы техническим специалистам, тем самым повышать свой уровень до уверенной компетенции в продукции. Ну, и как резюме… Подытожить данный материал, над которым я работал не один вечер, хочется следующим обращением: Уважаемые менеджеры по продажам. Мы Вас очень ценим и уважаем. Вы - локомотив нашего бизнеса и от Вас зависит многое. Но, пожалуйста, согласовывайте с нами каждый нюанс и мелочи и прислушивайтесь к производственникам Вашей компании. Давайте жить дружно ;)
Подарунки на День народження ITVDN. Вітаємо переможців акції!

Автор: Редакція ITVDN

14 января 2017 года ITVDN отметил свой третий День Рождения! Благодарим всех участников акции за ответы на вопросы анкеты, а главное - за добрые слова и пожелания в адрес создателей проекта. Как и было обещано, все клиенты ITVDN в честь Дня Рождения получили в подарок бонусы (см. В Личном кабинете), а трое счастливчиков выиграли подписку ITVDN на три месяца. Имена победителей: Руслан Коваль Анатолий Спивакин Артем Соляр Видео запись розыгрыша. Подарочные сертификаты будут отправлены победителям на адреса электронной почты, указанные в анкете. А мы хотим поделиться со вами отзывами участников акции о нашем ресурсе. Ответы на вопрос: Что ITVDN значит лично для Вас? «ITVDN для меня - лучший русскоязычный образовательный ресурс по технологиям Microsoft. Я прошел здесь много курсов, даю отзывы о вашей работе, чтобы вы могли становиться лучше!», Геннадий Чурсов.   "Благодаря ITVDN я стал front-end разработчиком! Процветания всей команде! Новых курсов по Spring!" Олег Жихарев.   «Я очень благодарен, что есть такой замечательный ресурс на русском языке! Очень понятные объяснения и за это отдельное большое спасибо. Очень важно, что у вас такие грамотные преподаватели, и речь даже не о знании программирования (в чем я тоже ни капельки не сомневаюсь), но и в умении грамотно и понятно объяснить ученикам материал», Руслан Сайфуллин.   «Jump-start в технологиях. Удобный способ выйти из своей технологической ниши и посмотреть на соседние технологии. Эффективнее по времени и деньгам, нежели покупка книг», Антон Касьянов.   «Замечательный ресурс, который помог и продолжает помогать постигать C#», Дмитрий Старцев.   "Я изучала только JavaScript / Frontend Developer и могу сказать, что более подробного и понятного изложения материала нигде нет. Очень нравится что есть тренажёр, помимо теории ты проверяешь, что запомнил," Анастасия Бутылова.   «ITVDN для меня – это обучающий ресурс с высочайшим качеством курсов, которые позволяют в кратчайшие сроки погрузится в IT технологии и пройти сложный путь от самого зеленого новичка до гуру разработки!», Юрий Дмитрин.    «Это возможность быстро и в короткие сроки разобраться в новых для себя темах. Отличный формат подачи материала», Алексей Глущенко.   «ITVDN помог мне с выбором направления, а именно .net developer, и дал чёткий план в своём развитии», Михаил Розенберг.   «ITVDN - это возможность сменить профессию, и начать зарабатывать деньги», Юрий Манин.   «Много новой и полезной информации. Открытие новых горизонтов для профессионального роста», Александр Веред.   «Я решил стать свитчером. Скоро сдаю экзамен по .NET и начинаю поиски работы. Оглядываясь назад понимаю, что без ITVDN мне вряд ли бы удалось продвинуться так далеко. Великолепный ресурс. И Шевчук - преподаватель от Бога (жаль, что перестал начитывать лекции, забросил С# Prof Express). Хотелось бы увидеть более широкую программу поддержки выпускников, в том числе иногородних. Всего Вам наилучшего и не забросить ресурс." Сергей Дмитрук.   "Лучший онлайн сервис по изучению информационных технологий компании Microsoft! Начинал с него свое изучение ООП, БД, алгоритмов и т.д. Каждый раз слежу за новостями, и появление нового курса вдохновляет меня как начинающего разработчика," Максим Давлетчин.   "Ваш ресурс стал меня большим открытием. Именно благодаря ему я наконец-то определился для себя с планом обучения по выбранной специальности. Ваши видеокурсы очень легки в восприятии и помогают заполнить все пробелы в той или иной предметной области. Отдельная благодарность лекторам за качественное преподавание материала." Андрей Донченко.   "Один из самых толковых, содержательных и прорывной проект в онлайн образовании  Украины, а главное ДОСТУПНЫ многим ! Это настоящий шанс для всех, кто желает стать программистом! Отрадно, что это у нас! Лично мне сильно помогли Ваши курсы: полнотой и содержательностью уроков, доступностью, удобством в пользовании! Надеюсь, ваше дело будет маяком и надёжной гаванью, доступной для всех, ищущих знаний." Андрей Щёткин.   "ITVDN - очень хороший ресурс с качественными курсами. Материал объясняется понятно, упражнений ровно столько, сколько нужно для понимания и запоминания информации," Анна Кузнецова.   "Это уникальная возможность удалённого обучения, возможность просмотреть интересующий материал в любое удобное время, а также возможность просмотреть повторно видео по тому или иному уроку после очного обучения на курсах. Также дополнительно хочу подчеркнуть о возможности закрепления материала и прокачки знаний в "Тренажере", который очень удобен и в который хотелось бы, чтобы добавлялись новые курсы," Артем Петрук.   "Для меня ITVDN - это ресурс неисчерпаемых знаний, охватывающих практически всю IT сферу. Благодаря ему, я могу совершенствовать свои навыки в программировании, тем самым одновременно продвигаясь по карьерной лестнице, что является очень важным для меня," Даниил Округ.   "Качественные курсы, после которых можно сразу применять полученные знания на практике," Игорь Безруков.   "Для мене ITVDN - це крок вперед. Як на мене -  це одні з найкращих курсів по програмуванню. Кваліфіковані викладачі роблять курс цікавим і захоплюючим.  ITVDN  - це те, що робить тебе більш спроможним. Дякую вам." Васьків Василь.   "Отличные курсы по разработке игр, которые очень помогли в создании своего игрового проекта," Иван Туманов. "Очень классные видеокурсы, хорошо структурированы и собраны по отдельным специальностям." Vsevolod Gonchar.   "ITVDN лично для меня - это ресурс, который помогает от новичков (как я) и до професионала, которым я планирую стать вместе с вами. У вас собран лучший контент по програмированию. И это очень удобно что он в одном месте. Поздравляю!" Андрей Вакулюк.   "ITVDN придает мне силы и уверенность в завтрашнем дне! Без курсов ITVDN я бы забросил обучение программированию. Спасибо всей команде! Здравия желаю!" Денис Гаев.   "Отличный сайт для обучения, приемлемые цены и одни из лучших, на мой взгляд, преподавателей." Гуменяк Дмитрий.   "Лично для меня ITVDN ассоциируется со Знаниями именно с большой буквы, к которым стремлюсь, и которых лично мне так не хватает." Сергей Скрипник.   "Возможность пройти качественную переквалификацию для начала карьеры в IТ-сфере." Геннадий Шпинёв.   "Один из лучших образовательных online ресурсов для IT-специалистов." Андрей Грандюк.   "Для меня ITVDN это № 1 русскоязычный образовательный онлайн портал! Он даже на много  лучше распиаренного "GeekBrains". Во-впервых, потому что там очень дорого, во-вторых, Ваши специалисты очень хорошо подают материал. Огромное  спасибо за Ваш труд! Я желаю Вам миллион учеников и процветания!" Андрей Грачев.   "Короткі та змістовні уроки від справжніх професіоналів. Ніякої води. Можливість швидко розвиватися. Вивчати те, що подобається." Юрій Тураш.   "Очень хороший ресурс. Помог мне начать изучение ASP.NET MVC. Хорошее доступное объяснение непонятного с первого взгляда материала." Дмитрий Анисько.   "Единственные уроки по Java, которые подробнейшим образом дали ответы на интересующие меня вопросы." Татьяна Корчинова.   "Лучший ресурс для самообучения." Андрей Багрий.   "ITVDN выпускает лучшие рускоязычные видеокурсы для IT специалистов. Больше всего нравится подача материала от Александра Шевчука, Дмитрия Охрименко и Александра Марченко. Очень понравилась серия видео "Карьера в IT". Владимир Долгий.   "ITVDN - один из лучших и современных сервисов обучения web-технологиям." Руслан Галиев.   "Полезный, познавательный и интересный контент, отлично подходящий для саморазвития. Работаю в сфере helpdesk, хочется развиваться и двигаться дальше, Ваш проект отлично помогает в этом," Dmitry Mazur.   "ITVDN - очень интересный ресурс. Видео уроки и учебный материал сыграли важную роль в моей учебе. С их помощью я смог освоить много новых технологий и начать карьеру программиста. Надеюсь на дальнейшее обновление видеокурсов и создание новых, так как они помогают постоянно развиваться и совершенствовать свои навыки, понять некоторые моменты в простом виде," Федор Петренко.   "Очень полезный ресурс, который позволяет мне удобно а главное качественно обучаться в сфере IT-технологий. Очень нравится читать интересные публикации в блоге,слушать новые бесплатные IT-вебинары. Спасибо Вам ребята!" Гурина Анастасия.   "Качественные уроки от специалистов,  которые учат лучше, чем моём ВУЗе." Наталия Проскурничая.   "Для меня ITVDN -  это новая возможность учиться, совершенствовать свои навыки, получать новые знания от лучших специалистов в своих областях, и все это в удобном формате и в удобное для меня время!" Екатерина Морозова.   "Для меня этот портал открыл путь в новый мир, с него началась моя карьера программиста, за что я выражаю огромную благодарность Александру Шевчуку, его курсы были отправной точкой для меня." Эдуард Степанов.   Благодарим всех за приятные отзывы! Оставайтесь с нами!
Співбесіда з DevOps. 300+ питань для Junior, Middle, Senior

Автор: Влад Сверчков

Junior 1.1 Общие вопросы и Linux. 1.2 Networks, Clouds. 1.3 Automation, Information Security. 1.4 Виртуализация, CI/CD, Development. 1.5 Monitoring/Logging. 1.6 Практические задания. Middle 2.1 Linux. 2.2 Networks. 2.3 Container orchestration. 2.4 Виртуализация и контейнеризация. 2.5 CI/CD, Clouds and Automation. 2.6 Monitoring/Logging. 2.7 Information Security. 2.8 Development, Databases. 2.9 Практические задания. Senior 3.1 Linux. 3.2 Networking, Разное. 3.3 Container orchestration, Clouds and Automation. 3.4 CI/CD, Information Security. 3.5 Observability, Databases. 3.6 Практические задания.     Дорогие друзья! Предлагаем вашему вниманию перевод статьи, опубликованной на DOU.ua 7 декабря 2021 года. Оригинальная версия на украинском языке доступна по ссылке. Можно спорить о популярности DevOps, а можно просто готовиться к собеседованию и получить желанные 9K :) Чтобы помочь вам сориентироваться в вопросах, которые задают на интервью, мы поговорили с теми, кто их проводит, и составили список возможных вопросов.   Junior   Общие 1. Что такое DevOps? 2. Вы набираете google.com в браузере. Расскажите как можно подробнее, что происходит в это время? 3. Как работает HTTPS? 4. Объясните концепцию Infrastructure as Code, зачем это нужно и какие проблемы решает?   Linux 5. Опишите общую архитектуру операционной системы. 6. Опишите основное предназначение операционной системы. 7. Зачем нужны файловые системы? Какие существуют? 8. В чем разница между виртуализацией и контейнеризацией? 9. В чем преимущества контейнеров? 10. Какова файловая структура в Linux (UNIX) системах, расположенных в /etc, /dev, /proc, /sys, /lib, /var (несколько директорий на выбор)? 11. Что такое Load Average? 12. В чем разница между soft и hard symlink? 13. Как работают file permissions, зачем директории права исполнения (+x)? 14. Что такое zombie process? 15. С помощью чего можно собрать информацию о текущем состоянии процессора, памяти, диска, сети? 16. Что такое swappiness? 17. Как посмотреть свободное место на диске? 18. Что такое inode? 19. Расскажите поэтапно процесс загрузки Linux с момента включения питания компьютера. 20. Что произойдет при выполнении команд: 1. cat file1 > file2 2. cat file1 >> file2 21. В чем разница между Ctrl+C и Ctrl+Z? 22. Как перенаправить одновременно stderr и stdin? 23. Как убить процесс? Какие есть типы сигналов? 24. Что делает команда grep? 25. Что такое скрипт bash? 26. Какие типы переменных используются в bash? 27. Что выведут команды: 1. echo ${hostname}; 2. echo $(hostname);   Networks 28. Что такое модель OSI, TCP/IP? 29. Для чего нужны network masks? 30. Структура IP-пакета. Из чего состоит? Что такое фрагментация и почему она происходит? 31. Что такое коллизия? Почему возникает? 32. Что такое прокси? 33. Что такое firewalls и зачем они нужны? 34. Что такое NAT и для чего он нужен? 35. Какие типы IP-адресов вы знаете? 36. По какому порту и протоколу работают Ping и Traceroute?   Clouds 37. В чем разница между IaaS, PaaS и SaaS? 38. Что такое VPC и из каких компонентов должно состоять? 39. Что такое cloud-init? init/systemd/upstart configs?   Automation 40. Что такое IaaC и зачем он нужен? 41. Что такое Terraform? 42. Какие инструменты автоматизации вы знаете?   Information Security 43. В чем разница между аутентификацией и авторизацией? 44. Сертификаты. Как работает HTTPS? Что такое certificate ciphers? 45. Как безопасно передать данные своему коллеге? 46. ​​Что такое MFA, TOTP?   Виртуализация 47. В чем разница между виртуализацией и контейнеризацией? В чем плюсы и минусы? 48. Как при запуске Docker-контейнера «повесить» его из 80-го порта в контейнере на 8081 на хост? 49. Как передать в виртуальную машину USB device? 50. Docker-контейнер потребляет многие SWAP. Что делать?   CI/CD 51. Что такое Continuous Integration и Continuous Deployment? В чем разница между Continuous Deployment и Continuous Delivery? 52. Опишите основные этапы CI/CD. 53. Опишите пример процесса CI (и/или CD), который начинается с момента, когда разработчик запушил изменения/PR в Git? 54. Расскажите о разновидностях тестов, которые мы можем использовать в CI пайплайне. 55. Какие инструменты CI вы использовали? Есть ли опыт работы с Jenkinsfile? 56. Какие виды тестов вы знаете и зачем они нужны?   Development 57. Git. Как решить merge conflict? Что такое rebase, cherry-pick? 58. В чем разница между git merge и git rebase? 59. Какие UI использовали? 60. Какая разница между GitLab/GitHub/Bitbucket? 61. Какая разница между Git pull/Git fetch? 62. Что такое Git-Flow? 63. Версионирование. Какая разница между SemVer и CalVer? 64. Тестирование. Какие существуют виды? Как писать тесты, TDD? 65. В чем разница между компилируемыми и интерпретационными языками программирования?   Monitoring/Logging 66. Какие метрики нужно собирать? Разница между infrastructure и application monitoring. 67. Какая разница между pull и push model в системах мониторинга? 68. Какая разница между Black box и White box monitoring? 69. Расскажите о подходах к сбору application логов.   Практические задания 71. Напишите простую программу на ваш выбор. Программа должна получать сообщения из сервиса очередей и печатать его в stdout. Сервис очередей — по вашему усмотрению. 72. Разберите структуру сервиса (на примере Docker-Compose). 73. Практическая сессия работы с Git (Git command line: fetch, push, pull, rebase, checkout, submodules).   Middle   Linux 1. Опишите архитектуру ядра Linux. 2. Что такое ядро ​​и каково его предназначение? 3. Опишите общие части файловой системы Unix/Linux, архитектуру файловой системы. 4. В чем разница между RedHat и Debian? 5. В чем разница между /proc и /sys? 6. Ситуация: указывает, что на диске занято 50% места, а сделать файл даже под root юзером не можем. В чем проблема? 7. Мы удалили файл, открывший приложение. Как нам его восстановить? 8. Как найти PID процесса, его стартовые параметры? 9. Как проверить, открыт ли порт на удаленном хосте, локальном хосте? 10. Как искать файл по его содержимому? 11. Что такое SSH, как организовать доступ на сервер без пароля или с определенных хостов? Как ограничить доступные для выполнения команды? 12. Как проверить потреблённые ресурсы во время сеанса SSH? 13. Что означает разрешение на файл 755? 14. Что такое SELinux и зачем он нужен? 15. Как определить PCI-устройство в системе, например, RAID controller? 16. Как переименовать устройство, например, сетевую карту или диск? 17. Что такое LVM? Какие знаете примеры использования? 18. Что такое root reserved space? 19. Что такое exit code и как его узнать? 20. Почему вывод df -h указывает, что на диске занято мало места, но система не дает записать файл с сообщением “no space left on device”? 21. В чем разница между command1 & command2 и command1 && command2, а также command1 && command2 || command3? 22. Из сети резко вырос исходящий трафик на 25-й порт. Как, имея доступ на гейтвей, обнаружить вредителя из внутренней сети? 23. Как затюнить параметры Linux Kernel? 24. Что такое ulimits? 25. В чем разница между символическими и hard links? 26. Что такое фрагментация ext3 и ext4? 27. Зачем файловые системы ext* резервируют 5% места? 28. Как увеличить размер файловой системы? 29. Можем ли мы уменьшить размер файловой системы? 30. Что такое chroot и для чего он нужен? 31. У нас есть Linux box с 2 Гб оперативной памяти и Java-приложение, которое пытается выделить 4 Гб во время запуска. Удастся ли это? 32. Есть приложение, которое читает файл, который пользователь пытается удалить. Что случится? Можно ли удалить этот файл? Можно ли восстановить этот файл? 33. Какие механизмы создания процессов в Linux вы знаете? 34. Сравните systemd и init system. 35. У вас есть папка с большим количеством файлов, и вы хотите удалить все файлы с именами, начинающимися на A (прописная буква). Но команда rm –f A* выдает Argument list too long. Как удалить эти файлы? 36. Вы начинаете удалять файлы первым методом из предыдущего вопроса, но каждый rm запрашивает подтверждение. Это очень долго. Как можно ускорить эту операцию?   Networks 37. Расскажите о модели OSI. Опишите функции и назначение каждого уровня. 38. Какие сетевые топологии вы знаете? Опишите разницу между ними. 39. Зачем нужен IP-адрес, если MAC-адрес уникален? Разве мы не можем общаться только по MAC-адресу? 40. В чем разница между концентратором и коммутатором L2 в сетях Ethernet? 41. Что такое VLAN и для чего существует разделение на виртуальные локальные сети? 42. Какой номер порта используется для PING-коммуникации? 43. Что такое сеанс связи? Какой алгоритм использует TCP для доставки? 44. В чем основное отличие между TCP и UDP? 45. Зачем нам маршрутизатор по умолчанию? 46. Как хост решает DNS по умолчанию? 47. Компьютер начал получать IP-адрес из другой сети (есть подозрение, что в сети работает другой DHCP-сервер): как его найти и отключить? Какие методы защиты от такой проблемы? 48. Мы будем мигрировать сайт на новый IP-адрес. Как сделать, чтобы пользователи этого практически не заметили? 49. Что такое socket? 50. Как узнать, какие удаленные хосты подключаются к хосту через порт 8888? (с помощью команд и не используя /proc или /sys). 51. У нас есть несколько сетевых карт. Как увеличить пропускную способность сервера? 52. Как проверить открытые порты на удаленном сервере без команд Netcat или Nmap Linux?   Container orchestration 53. В чем преимущества Kubernetes как платформы? 54. Что такое control plane и из каких компонентов состоит? 55. Какие CNI вы использовали и чем они отличаются? 56. Чем отличается managed Kubernetes от self-deployed? 57. Как можно контролировать размещение подов в кластере? (taints/tolerations, affinities, topologies etc.) 58. Скейлинг кластера. Cluster autoscaler vs HPA vs VPA? Как сделать zero-downtime node decommission/cluster upgrade? PDB? Lifecycle hooks? 59. Какие способы для внешнего доступа к кластеру? ingress, node port, port-forward и т. д. 60. С каким PID запускается процесс в контейнере? 61. Что лучше использовать для изоляции окружения – Vagrant или Docker? 62. Какой инструмент оркестрирования контейнеров использовали? (Swarm, Kubernetes, Openshift, Rancher и т. д.) 63. Что происходит в Kubernetes после запуска kubectl (API, ReplicaSet Controller, storage back-end, scheduler, kubelet, worker node, pod)? 64. Какая разница между pod и контейнером в K8s? 65. Как мы можем сделать любой микросервис, работающий на K8s, доступным из внешней среды?   Виртуализация и контейнеризация 66. Какие типы виртуализации вы знаете? 67. Как работает Docker на macOS/Windows? 68. Что такое Docker-image и Docker-контейнер? Как они между собой связаны? 69. Каковы основные отличия между контейнерами докеров и виртуальными машинами? 70. Что такое image layer? Какое максимальное количество layers возможно? Почему нужно пытаться иметь малое количество layers? Какое оптимальное количество? 71. Как в виртуальной машине изменить размер диска после создания? Что нужно сделать с гостевой ОС? 72. Как в Docker реализовано ограничение ресурсов? 73. Существует виртуальная машина, к которой потерян доступ. Как, имея доступ к диску, восстановить root пароль/SSH-ключ? 74. Оптимизировать Dockerfile, объяснить, что и почему так: FROM golang RUN apt install -y pkg1 pkg2 pkgN # Dependencies for app COPY. . RUN go build -o app main.go CMD ./app 75. Что такое IPVS и какой у него функционал? 76. Какова структура API в Kubernetes? 77. Что такое operators и зачем они нужны?   CI/CD 78. Какие стадии должны быть в любом пайплайне (lint, test, build, deploy etc.)? 79. Как и где хранить build artifacts? 80. Что такое артефакт? 81. Есть два бренча: dev и stage. Мы забросили Dockerfile в dev, а затем сбилдили в dev и stage. Это будет одним артефактом или разными? 82. Что вы использовали для автоматизации настройки Jenkins и GitLab CI? 83. Сравните CI инструментов: Jenkins, GitLab CI, AWS Code Pipeline, GCP cloudbuild, GitHub actions, Circle CI. 84. Deployment strategies. Какие существуют и чем отличаются (recreate, blue-green, canary etc.)? 85. Как реализовать СI/CD для программы, которая зависит от нескольких других программ? 86. GitOps. В чем его преимущества и недостатки?   Clouds and Automation 87. Какова роль и преимущества облачных сервисов для DevOps? 88. Что такое immutable infrastructure? Как достичь? В чем преимущества и недостатки? Packer, AMI и т. д. 89. Структура Terraform. Как организовать multi-environment project? Terraform workspaces? 90. Лучшие практики по использованию многих Terraform states. 91. Как организовать доступ команде разработчиков к AWS/GCP/Azure? Role-based access, assume role, SSO. 92. Что такое Terraform provider, module? 93. Как версионировать Terraform modules? 94. Когда нужно использовать local-exec и remote-exec? 95. Что такое golden image и как его создать?   Monitoring/Logging 96. Как мониторинг помогает поддерживать всю архитектуру системы? 97. Какие инструменты мониторинга вы использовали? 98. Что такое медиана и процентиль? 99. Что такое SLI, SLO, SLA? Зачем это нужно? 100. Архитектура системы для сбора логов, ELK, EFK etc. Как сохранить логи при отказе хранилища? Нужно ли использовать для этого брокер сообщений? Нужно ли делать throttling/rate limits? 101. Prometheus long-term storage. Какие варианты? 102. Как работает Prometheus? 103. В чем принципиальное отличие между Grafana и Kibana? 104. В чем главное отличие между Ansible and Terraform? 105. Что такое SAAS monitoring и какие виды знаете? 106. Если вы используете Datadog/NewRelic, то как нам отслеживать падение инструментов мониторинга? 107. Что такое distributed tracing и error tracking systems? Как вы думаете, когда следует их использовать?   Information Security 108. В чем разница между RBAC и ABAC? 109. В чем заключается XSS атака? SQL injection? Что такое CSP? 110. Какие базовые меры можно предпринять для защиты SSH-соединения? 111. Root-пароль неизвестен или потерян. Какова процедура восстановления? 112. Как управлять правами на файловой системе в Linux? 113. Что такое Firewall? 114. Чем отличается stateless от stateful фаерволов? 115. Сколько таблиц в iptables? 116. Можно ли настроить трансляцию NAT с помощью iptables? Какую таблицу следует использовать? 117. Какую таблицу используют для смены заголовков пакетов? 118. Если вам ломают Linux-сервер, то как более эффективно блокировать трафик с IP-адресов? 119. Принцип работы GCP Firewall: можем ли мы профильтровать трафик на Load Balancer? 120. Что такое SELinux? 121. Можно ли полностью отключить SELinux на лету? 122. С какими secrets management systems вы работали? 123. У нас есть сервер NAT, и мы хотим обеспечить доступ по IP к серверу снаружи. Как нам это реализовать? 123. Чтобы попасть на сервер клиента, нужно залогиниться на 4+ jump хоста. Как автоматизировать? Где мы будем хранить наш SSH-ключ?   Development 125. Что такое cookies? Зачем нужны? JWT? 126. Что такое feature toggles и зачем они? 127. Что такое TDD (Test Driven Development) и BDD (Behaviour Driven Development)?   Databases 128. Что такое индекс и что такое ключ? 129. Каковы преимущества и недостатки индексов? 130. Представьте, что вы разрабатываете систему биллинга, которая должна обрабатывать тысячи счетов. Какую стратегию обновления данных вы бы выбрали? 131. Какие методы чаще всего используют для масштабирования реляционных баз данных? 132. Опишите механизм транзакций БД. 133. Как мы можем удалить таблицу или базу данных? 134. Как найти медленные запросы в MySQL/PostgreSQL? 135. Какие SQL-операторы манипулирования данными вы знаете? 136. Можно ли вывести список баз данных/таблиц через CLI? Как мы можем переключаться между базами данных MySQL/PostgreSQL? 137. Какие storage engines в MySQL вы знаете? Какие отличия? 138. Как реализована репликация MySQL master-master? Сколько серверов MySQL может быть задействовано в таком взаимодействии? 139. Как работает репликация MySQL/PostgreSQL? Какие параметры должны быть настроены для репликации? 140. Сравните SQL и NoSQL. 141. Sharding vs replication? 142. Какие есть виды индексов? Когда и зачем использовать? 143. Требования к схеме БД. Character sets, collations, default, not null и т. д. 144. Мы мигрируем MySQL/PostgreSQL из on-prem в облако. Как нам это сделать с минимальным даунтаймом? 145. Зачем и как тестировать перформанс баз данных?   Практические задания 146. Напишите Terraform module для инфраструктуры тестового сервиса в AWS. 147. Напишите hello-world программу на ваш выбор и сформируйте для нее helm chart/kustomize. 148. Как организовать деплой без downtime? 149. Опишите способы troubleshooting для Docker-контейнера. 150. Разобрать и объяснить структуру CI/CD pipeline (на примере gitlab.yml). 151. Продемонстрируйте навыки работы с GitOps, опишите деплоймент простенькой программы. 152. Как организовать деплой веб-приложения, запущенный на нескольких серверах без (или с минимальным) downtime? 153. Как с помощью Ansible узнать default gateway для пула серверов, и, если он отличается от желаемого, записать строчку «hostname: gateway» в файл на локальной машине?   Senior   Linux 1. Что может создавать высокую нагрузку на CPU (процессы приложений потребляют очень мало ресурсов CPU)? 2. У нас нет команд ifconfig, ip, и поставить мы их не можем. Как нам узнать ip address, mask, network, routes? 3. Что такое suid, sgid и sticky? 4. Что тюнилось с системой для нагрузки трафика 1GB, 10G, 40G+? 5. Что тюнилось с системой для высокой нагрузки на диск? 6. Что такое Linux namespaces? 7. Что такое Ceph, как работает? 8. Что нужно тюнить для Ceph? 9. Что произойдет, если /dev/sda1 перенесем в /root? 10. Мы удалили /dev/sda1. Как нам его восстановить? Что такое pseudo-devices? 11. Нам хакнули сервер, и в директории /var/www создали два миллиона файлов небольшого размера. Если использовать команду cd /var/www и затем rm -rf*, то у нас зависнет терминал. Как удалить файлы? 12. На каком уровне работает iptables? 13. Что такое eBPF и зачем нужен? 14. У вас есть файл, содержащий IP-адреса серверов (по одному в строке). Есть SSH доступ к этим машинам, и вам нужно выполнить задание (например, установить список пакетов на все узлы). Объясните, как можно это сделать.   Networking 15. В чем отличия между IPv4 и IPv6? Зачем мы мигрируем на IPv6? 16. Сосуществование IPv4 и IPv6: что это значит? 17. Действительно ли работают межсетевые экраны с поддержкой IPv6? 18. Как работает DHCPv6? Чем она отличается от DHCPv4? 19. Как фрагментируются пакеты IPv6 и чем это отличается от IPv4? 20. Нужно ли с IPv6 больше использовать NAT? 21. Что такое DPDK? 22. Что такое SR-IOV? В чем разница между DPDK и SR-IOV? 23. Что такое NetFlow и зачем нужен? 24. Что такое OpenFlow? 25.Что такое SDN и какие контроллеры вы знаете? Сравните контроллеры.   Разное 26. Что такое SDLC? 27. Расскажите о последнем опыте реализации архитектуры для сервиса. 28. Какой самый тяжелый скрипт писали? 29. Что такое configuration drift? Почему это происходит и как это усложняет жизнь инженерам\SRE\Ops? 30. Расскажите об архитектуре, за которую вы отвечаете, и укажите, как она масштабирована и отказоустойчива. 31. Назовите три важных KPI для DevOps-специалиста. 32. Как работает Kafka (clusters(brokers, controllers), topics, partitions)? 33. GitOps: Rancher Fleet vs Flux vs Argo? 34. Как использовать GitOps для обновления документации DevOps-приложений? 35. Расскажите об особенностях проектирования Kubernetes on-premise. 36. Как организовать On-call процесс для команды DevOps? 37. Опишите главные шаги загрузки операционной системы Linux.   Container orchestration 38. Service mesh. Что это такое и зачем нужно? 39. Cluster federation. Что это такое и зачем нужно? 40. Pod fine-grained access. Как реализовать? IRSA vs kube2iam vs kiam? 41. Как реализованы услуги в кубернетах? 42. Как дебажить трафик контейнера? 43. Что такое unikernel и зачем он нужен? 44. Почему коммьюнити переезжает из Docker containerd?   Clouds and Automation 45. Какие преимущества и недостатки cloud-провайдеров? 46. Cost оптимизация. Какие инструменты? Spot/preemptible instances, reservations? 47. Как организовать multi-account, multi-region cloud setup? 48. В чем разница между частными и публичными сетями в AWS? 49. AWS Lambda: имели ли опыт работы? 50. Когда следует переходить на AWS Lambda? Когда не стоит? Аналогичные решения в GCP или Kubernetes? 51. Когда лучше использовать CloudFormation, а когда Terraform?   CI/CD 52. Что такое state в контексте использования Terraform? 53. Какие существуют branching strategy? На что опираться при выборе? 54. Как реализовать feature/dynamic environments? 55. Как сделать эмуляцию ресурсов cloud-провайдера для локального тестирования и ускорения разработки? 56. Что такое MultiCloud? 57. Что такое Cloud-Agnostic и когда он потребуется? 58. Что такое Hybrid-Cloud и с какими решениями вы работали?   Information Security 59. Как должны храниться пароли в базах данных (Salt&Pepper, Rainbow Tables, Adaptive Hashing)? 60. Как передавать секреты в application (Secrets management)? 61. Сравните CI/CD SAST и DAST? 62. Какие вы знаете Kubernetes security practices? RBAC? OPA? Какие недостатки RBAC и какие кейсы знаете? 63. Расскажите о защите от DDOS атак, WAF. 64. Что такое Rootless containers и для чего он нужен? 65. Что такое AppArmor и Seccomp и зачем они нужны? 66. Приходилось ли работать с Falco? Если да, то что реализовывали? 67. HashiCorp Vault и как правильно передать нам секреты в контейнере и CI pipeline? 68. Что такое Admission Controllers и какие вы использовали? 69. Как хранятся секреты etcd? Как просмотреть ресурсы в etcd? 70. Чем проверяете на уязвимости ваш Kubernetes cluster? 71. Что такое Secure SDLC? 72. Что вы знаете о Cloud Infrastructure Attack via a Pull Request и как этого избежать?   Observability 73. Что такое observability и чем отличается от обычного мониторинга? Какие особенности необходимо учитывать в микросервисной архитектуре (tracing)? 74. Что такое SLI, SLO, SLA и зачем они нужны? Для чего используют error budget?   Databases 75. Что такое теорема CAP? Зачем это нужно? 76. Как работать с миграциями? Что делать в случае rollback? Как проверить, что миграция backward-compatible? 77. Опишите, как бы вы оптимизировали работу базы данных? (БД по выбору кандидата) Slow queries, buffers, thread pools? 78. Зачем нужно тестировать перформанс базы данных и какими инструментами?   Практические задания 79. Представьте, что вы CTO Booking или Airbnb. Какие бы вы принимали решения касательно: языков программирования. Infrastructure as a Code. архитектуры инфраструктуры. настройки CI/CD. 80. У вас есть файл, содержащий патчи в директории. Например: /var/tmp/temp/file1.c /var/tmp/file.ext /var/tmp/temp/ etc... один путь в строке. Если путь заканчивается на '/' — это путь в каталог. Вам нужно восстановить это дерево каталогов с пустыми файлами в другой файловой системе. Напишите bash-скрипт. 81. Представьте, что вам нужно убедить Spotify, использующего AWS, перейти на GCP. Как вы будете мотивировать Spotify мигрировать на GCP? 82. Есть сервисная компания, предоставляющая сервис трекинга перевозок. Есть клиенты, которые не желают, чтобы их данные процессировались в AWS. Как нам реализовать multi-cloud solution?   Редакция DOU выражает благодарность за помощь в подготовке статьи: Владу Волошину, Павлу Петриченко, Виталию Гарбулинскому (BrightLocal), Евгению Думе, Сергею Яремчуку, Вадиму Шкилю, Александру Билюку, Александру Нежинскому, Владиславу Граму, Станиславу Коленкину, Олегу Миколайченку, Антону Гаврилову.
Notification success