-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Основные возможности Dell EMC Cloud для Microsoft Azure

Воскресенье, 04 Июня 2017 г. 16:27 + в цитатник
Около месяца назад компания Dell EMC представила Dell EMC Cloud для Microsoft Azure Stack — платформу, которая позволит оптимизировать внедрение гибридных облачных решений на базе Microsoft Azure Stack. И пока она еще не доступна для заказа, мы вкратце расскажем о ее основных преимуществах и о том, что она даст клиентам.





Dell EMC Cloud для Microsoft Azure Stack представляет собой гибридную облачную платформу для предоставления инфраструктуры (IaaS) и платформы (PaaS) в качестве сервисов. Она поддерживает функциональность Azure, которая доступна как в облаке, так и в локальном центре обработки данных. С ее помощью можно безопасно получать, создавать и обмениваться сервисами приложений в Azure и Azure Stack. Доступно это как для традиционных, так и для облачных приложений.

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

Dell EMC Cloud для Microsoft Azure Stack позволяет предприятиям автоматизировать доставку ИТ-услуг для всех приложений в экосистеме Azure. Происходит это через портал самообслуживания, при этом поддерживается оперативный контроль за работой инфраструктуры. Например, доступен выбор дополнительных параметров для защиты данных и шифрования, обеспечивается резервное копирование и восстановление данных приложений. Эти и многие функции и возможности позволяют клиентам уверенно перейти на гибридную модель облака.

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

При развертывании платформы специалисты специалисты Dell EMC оказывают поддержку на каждом этапе, начиная от планирования. Сначала клиенты получают рекомендации относительно оптимизации и расширения гибридных облачных платформ. Сюда относятся разработка и настройка сервисов, систем и систем идентификации и доступа, а также расширение систем мониторинга и учета для Azure Stack. Все это поможет быстро и безболезненно внедрить Dell EMC Cloud для Microsoft Azure Stack в ИТ-инфраструктуру любого предприятия.

Если говорить вкратце, то пользователи получают такие возможности:

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

Новая платформа будет доступна к заказу во II квартале 2017 года.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330180/


Метки:  

[Из песочницы] Когда 2 + 2 = «4»

Воскресенье, 04 Июня 2017 г. 15:17 + в цитатник
Во время отдыха от отладки JavaScript, я читал статью про особенности PHP и неожиданно задумался каковы же будут результаты сравнения 2 + 2 = «4» для разных языков программирования. И вот что из этого получилось.
Итоговая таблица для тех кто не хочет много читать
Результат Ошибка компиляции False True
Языки C++
Pascal
FORTRAN-95
Java
C#
Go
Rust
Haskel
C
Lisp
Python
Lua
Ruby
JavaScript
PHP
Perl

Компилятор C выдаёт предупреждение, компилятор C++ ошибку которая превращается в предупреждение если указать флаг -fpermissive.

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

Бонусом — функции вывода на консоль для этих языков.

Ошибка компиляции


Самый простое и неинтересное поведение — это ошибка компиляции, происходит во всех строго типизированных языках.

C++

cout << (2 + 2 == "4") << endl; 

error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

Если указать флаг -fpermissive то произойдёт сравнение указателя на строку и числа 4 которое скорее всего вернёт 0.

Pascal

writeln((2 + 2) = "4");

Fatal: illegal character "'"'" ($22)

Сообщение об ошибке довольно непонятное

FORTRAN-95

Print *, 2 + 2 == "4"

Error: Operands of comparison operator '==' at (1) are INTEGER(4)/CHARACTER(1)

Забавно что в этом тексте нет собственно сообщения о том, что сравнение невозможно, просто констатация факта.

Java

System.out.println((2 + 2) == "4");

error: incomparable types: int and String

В сообщение об ошибке всё хорошо кроме того, что не указана какая операция вызвала ошибку.

C#

Console.WriteLine((2 + 2) == "4");

error CS0019: Operator `==' cannot be applied to operands of type `int' and `string'

Тут всё хорошо.

Go

fmt.Printf(2 + 2 == "4")

cannot convert «4» to type int
invalid operation: «4» == 2 + 2 (mismatched types string and int)


А тут еще лучше

Rust

println!("{:?}", 2 + 2 == "4");

error: the trait `core::cmp::PartialEq<&str>` is not implemented for the type `_` [E0277]

Логичное, но честно говоря далеко не самое понятное сообщение об ошибке

Haskel

main = putStrLn (show ((2 + 2) == "4"))

No instance for (Num Char) arising from a use of `+'

Сперва я не понял сообщение, потом немного подумал и понял. Но стал понимать Haskel еще меньше чем раньше.

Результат False


Следующие на очереди языки которые позволяют сравнивать число и строку, при этом возвращая false (или что-то похожее), скорее всего из-за несовпадения типов переменных.

C

printf("%i\n",(2 + 2 == "4"));

результат — 0. Сравнение указателя на строку и числа 4 скорее всего вернёт 0. При этом выводится предупреждение, почти такое же как в C++:

warning: comparison between pointer and integer [enabled by default]

Lisp

(write (eq "123" 123))

результат — NIL

Python

print (2 + 2 == "4")

результат — False

Lua

print(2 + 2 == "4")

результат — false

Ruby

puts 2 + 2 == "4";

результат — false

Результат True


И наконец языки которые вернут true для сравнения.

JavaScript

console.log(2 + 2 == "4");

К счастью есть операция строгого сравнения (тройное равенство ===), которая вернёт false

PHP

echo (2 + 2 == "4");

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

Perl

print 2 + 2 == "4";

Операции строгого сравнения нет, кроме того для шестнадцатеричной записи (а почему бы и нет)

print 0x2 + 0x2 == "0x4";

Perl интерпретирует строку «0x4» как 0 (в отличие от JavaScript и PHP, которые разбирают шестнадцатеричные строки) и вернёт FALSE, при выводе на консоль так же будет пустая строка.

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

Для изучения вопроса использовался сайт, используемые версии компиляторов и интерпретаторов соответствуют предоставленным на сайте.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330176/


Метки:  

Как наука о данных помогает развитию медицины. Лекция в Яндексе

Воскресенье, 04 Июня 2017 г. 15:09 + в цитатник

Введение в Pixi.js или пишем мини-игру за 20 минут

Воскресенье, 04 Июня 2017 г. 13:35 + в цитатник
Здравствуй, Хабр!

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




Итак, вкратце о движке. Pixi.js — это 2D фреймворк с поддержкой WebGL. Авторы фреймворка утверждают, что движок можно использовать для создания любой графики на странице, но первое, что приходит на ум видя его возможности — это разработка игр. Главные преимущества движка, это доступный API и конечно же, скорость. Вот для примера, известные в узких кругах зайчики, для оценки производительности:

www.goodboydigital.com/pixijs/bunnymark

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

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

npm install pixi.js

Ждем когда установятся все пакеты и после этого, как это обычно бывает, создаем файл index.html и main.js
подключаем в шапку index.html наш фреймворк. В зависимости от способа установки, будут разные source. Если вы устанавливали с библиотеку с помощью npm путь будет такой:

node_module/pixi.js/dist/pixi.js

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

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

var width = window.innerWidth; //получаем ширину экрана
var height = window.innerHeight; // получаем высоту экрана
var app; //создаем глобальную переменную нашей игры

var model = {
    createCanvas: function() {
        app = new PIXI.Application(width, height); //создаем холст
        document.body.appendChild(app.view); //выводим его в тело страницы
    }

}


если вы все сделали правильно, то при вызове из консоли браузера:

model.createCanvas();

У вас сгенерируется canvas на всю ширину страницы. Сразу создадим объект view, в котором будет функция которая выводит нашу игру на экран:


var view = {
	loadGame: function(){
		model.createCanvas();
	}
}

view.loadGame(); //запускаем игру



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

var width = window.innerWidth; //получаем ширину экрана
var height = window.innerHeight; // получаем высоту экрана
var app; //создаем глобальную переменную нашей игры
var colors = [0xFFFF0B, 0xFF700B, 0x4286f4, 0x4286f4, 0xf441e8, 0x8dff6d, 0x41ccc9, 0xe03375, 0x95e032, 0x77c687, 0x43ba5b, 0x0ea3ba]; //массив цветов, 0x вместо #

var model = {
    createCanvas: function() {
        app = new PIXI.Application(width, height); //создаем холст
        document.body.appendChild(app.view); //выводим его в тело страницы
    },
    drawCircle: function() {
        rand = Math.floor(Math.random() * colors.length); //генерим рандомное число(в промежутке от 0 до количества цветов в массиве цветов)
        var radius = 50; //радиус круга
        var inAreaX = width - 100; //возможные координаты по оси X, которые может занимать круг, ширина страницы минус его диаметр
        var circleY = -50; //круг должен создаваться за пределами холста(чтобы глянуть, отрисовался ли круг, измените отрицательное значение на положительное)
        var circleX = Math.floor(Math.random()* inAreaX); //создаем круг в рандомном месте по оси X
        var circle = new PIXI.Graphics(); //создаем новый графический элемент
        circle.lineStyle(0); //начинаем рисовать
        circle.beginFill(colors[rand], 1); //задаем рандомный цвет
        circle.drawCircle(circleX, circleY, radius); //рисуем кружок, ведь он наш дружок
        circle.endFill(); //закончили отрисовку
        circle.interactive = true; //делаем круг интерактивным
        circle.buttonMode = true; //меняем курсор при наведении
        app.stage.addChild(circle); //выводим круг на холсте
        circle.on('pointerdown', controller.clearFigure); //добавляем возможность при клике на фигуру удалить её
    }
}
var view = {
    loadGame: function() {
        model.createCanvas();
        model.drawCircle();//отрисовываем кружок, пока один раз
    }
}


var controller = {
	clearFigure: function(){
		this.clear(); //удаляем фигуры по которой кликнули
	}
}

view.loadGame();


app.stage.addChild(circle); — это очень важная команда в Pixi, так как в этом фреймворке, чтобы на холсте что-то появилось, кроме создания объекта, его нужно обязательно вывести. В 70% процентах случаев, если вы все сделали правильно, а объект на холсте не отображается, то скорее всего вы забыли его вывести с помощью этой команды.

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

Для этого в начале страницы добавляем переменную gravity(сразу после массива colors), которая отвечает за гравитацию, по умолчанию ставим силу притяжение 4. Так же добавляем переменную figuresAmount с значение 0(количество фигур при запуске игры) и создаем пустой массив figure, куда мы будем отправлять все ново созданные шарики. В функции drawCircle добавляем два действия(я не буду вставлять весь код, только строку предшествующую новонаписанному, и строку которая была написана ранее и будет после новонаписанного):

var colors = [0xFFFF0B, 0xFF700B, 0x4286f4, 0x4286f4, 0xf441e8, 0x8dff6d, 0x41ccc9, 0xe03375, 0x95e032, 0x77c687, 0x43ba5b, 0x0ea3ba]; //массив цветов
var gravity = 4;
var figuresAmount = -1; //количество созданных фигур(не ноль, потому как с нуля мы начинаем считать фигуры)
var figure = []; //массив хранящий нашу фигуру

 {
— наши добавленные переменные.

И новые действия в функции drawCircle:

circle.buttonMode = true; //меняем курсор при наведении
figuresAmount++; //увеличиваем количество созданных шариков
figure.push(circle); //обратиться на прямую к объекту circle мы не можем, поэтому отправляем его в массив
app.stage.addChild(circle); //выводим круг на холсте


Ну и во view.loadGame добавляем отрисовку шарика каждую секунду, сразу после первой отрисовки и запускаем функцию, которая постоянно обновляет холст с внесением изменений. В Pixi за это отвечает такая цепочка:

app.ticker.add();


у нас так:

model.drawCircle(); //рисуем круг в первый раз
setInterval(model.drawCircle, 500); //рисуем шарик каждые пол секунды

app.ticker.add(function() { //постоянное обновление холста
       for (var i = 0; i < figuresAmount; i++) {
             figure[i].position.y += gravity; //заставляем гравитацию работать
       }        
    });
 } //закрываем функцию loadGame();


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

Для этого нужно в первую очередь для нашего шарика создать два состояния, существует он или уничтожен. Внутри drawCircle добавляем новое свойство circle.live, которое по умолчанию true(когда мы только создали шарик, по другому быть и не может), так же нужно задать ему порядковые номер, чтобы при попадании по шарику именно тот шарик в который мы попали стал false:)
Для этого у нас есть переменная figuresAmount, которая увеличивается при каждом новом шарике. В общем пишем в drawCircle:

circle.buttonMode = true; //меняем курсор при наведении
circle.live = true; //указываем что наш шарик жив и не пал жертвой выстрела
figuresAmount++;
circle.num = figuresAmount; //даем нашему кругу порядковый номер
figure.push(circle); //обратиться на прямую к объекту circle мы не можем, поэтому отправляем его в массив


Далее создаем функцию в модели которая выводит текст(что да как в комментариях):

gameOver: function() {
        var style = new PIXI.TextStyle({ //стили для текста
            fill: '0xffffff',
            fontSize: 36,
        }); 
        var gameOverText = new PIXI.Text('Game Over', style); //собственно выводимый текст
        gameOverText.x = width / 2; //центрируем относительно экрана
        gameOverText.y = height / 2; //центрируем относительно экрана
        gameOverText.pivot.x = 50; //выравниваем по оси х
        gameOverText.pivot.y = 50; // выравниваем по оси y
        app.stage.addChild(gameOverText); //выводим на холсте
}


в clearFigure указываем, что при каждом попадании по шарику, состояние circle.live меняется на false. Мы делаем это действие по той простой причине, что функция clear() не удаляет объект, а просто стирает его сanvasa(по сути шарик продолжает падать, поэтому надо указать что этот шарик уничтожен и его можно пропустить никак не реагируя).

Пример кода:

clearFigure: function() {
        this.clear();
        figure[this.num].live = false;
}


И запускаем проверку столкновения и вызов gameOver в случае необходимости при каждом обновлении сцены:

app.ticker.add(function() { //постоянное обновление холста
            for (var i = 0; i < figuresAmount; i++) {
                figure[i].position.y += gravity; //заставляем гравитацию работать
                if (figure[i].position.y > height && figure[i].live == true) {//проверяет столкнулся ли шарик с низом страницы и если он жив, не пропускает его, а отменяет выводит на экран "игра окончена и завершает действие гравитации"
                    model.gameOver();
                    return false;
                } 
            }


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

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

Всем спасибо!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330174/


Метки:  

Старые технологии на новый лад. FreeBSD Jails + CBSD Project

Воскресенье, 04 Июня 2017 г. 11:24 + в цитатник

Предисловие


Примерно 9 лет назад, когда в моем городе появились первые безлимитные тарифы (что-то вроде 128 кбит/сек за 500 руб.), я принял решение держать в квартире собственный «сервер» для решения различных задач. Одной из первых идей было поднятие зеркала для проекта FreeBSD.org. Проработало оно где-то 2 года. Далее в этом уже не было смысла, ввиду расширения каналов и других причин.

Помимо этого, сервер принимал на себя в разные периоды времени и другие задачи:
  • Хранение резервный копий данных, документов и дистрибутивов;
  • Закачка торрентов;
  • Раздача торрентов по DLNA и SMB на различные устройства;
  • VPN-клиент к провайдеру (был даже период, когда сервер держал два PPTP соединения через MPD – для работы локального трафика и медленного безлимита);
  • VPN-сервер и подключение до офисного шлюза (канал до работы);
  • Asterisk сервер для IP-телефонии (в дальнейшем в доме появились всякие SPA-3112, радио-трубки и т.д.);
  • FTP-служба для получения данных с IP-камеры, для сброса бекапов с Mikrotik-ов скриптами;
  • И т.д. и т.п.


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


Операционная система


В качестве операционной системы первые 4-5 лет у меня была FreeBSD. В определенный момент, когда я сменил работу и стал усиленно погружаться в технологии Microsoft – мне стало абсолютно некогда заниматься своим домашним сервером. Еще помню, что мне здорово надоело тратить время на portupgrade. Может и другие причины были, точно не помню. Но итогом был переезд на Debian (полдня) и сервер оказался надолго заброшен (использовал, но не модифицировал – лишь изредка обновлял).

И вот совсем недавно, в январские праздники, состоялся очередной возврат к истокам – сервер был вновь переустановлен – уже на FreeBSD 11. И причина тому – мое знакомство и восхищение проектом CBSD (www.bsdstore.ru).

Причины полюбить проект CBSD


Для этого нужно вспомнить причины, по которым я ушел с FreeBSD лет 5 назад – отсутствие свободного времени, устаревшая система установки бинарных пакетов (pkg_*), неудобное управление Jails. Сложно точно сказать почему я перешел с FreeBSD на Linux тогда. Но в чем я уверен сейчас – использование проекта CBSD вместе с FreeBSD на моем сервере позволяет мне наконец то совместить и удобство, и безопасность.

Все прошлые инсталляции были у меня настроены по принципу – все яйца в одной корзине. Компрометация одного сервиса автоматически означала компрометацию всех. С приходом CBSD на мой сервер я взял за правило каждый сервис размещать в своей клетке, ограничивая взаимодействие и оставляя только самый необходимый минимум.
Итак – мои причины:
  • Простота инсталляции (установить пакет cbsd, запустить начальный мастер и ответить на типовые вопросы – это 2 минуты);
  • Скорость создания новых клеток (1 минута уходит на то, чтобы, выполнив всего одну команду получить новую клетку, с выделенным IP-адресом, назначенными квотами, размещенную в своей FS на ZFS и с уже проинициализированным pkgng, которым к работе);
  • Простота переноса клеток со всеми настройками между серверами (это очень удобно и важно – так как на текущий момент у меня есть уже 5 серверов на базе FreeBSD (дома, у родителей, у тещи, на работе парочка) – и мне достаточно сделать и настроить клетку только один раз – а в дальнейшем я могу переносить ее куда угодно через export/import либо clone/migrate;
  • Безопасность и удобство. Обычно слабо совместимые вещи. Но – тут кажется это удалось совместить:

  1. Можно делать клетки с Read-Only корневой системой. Что на порядок усложняет внедрение в клетку RootKit-инструментария (подменяющего базовые утилиты);
  2. Просто ограничить взаимодействие клетки с другими клетками и с сетью интернет – в CBSD встроено управление PF/IPFW;
  3. За счет простоты и скорости создания новых окружений нет соблазна новое ПО поставить в базовую систему (лень лень…);
  4. Клетки просто резервировать export/import – значит можно чаще и по расписанию делать копии;
  5. Клетки просто обновлять, управляя ими из основной системы (обновлять world и обновлять установленное ПО). При этом не нужно поднимать SSH службу и настраивать Ansible и ему подобные;
  6. Безопасность контента. В CBSD есть встроенная возможность размещать контент и сам Jail в разных местах. И при старте клетки монтировать каталог с контентом в Jail в указанный каталог через mount_nullfs. Причем можно в режиме Read-Write, а можно в Read-Only. Это очень удобно – так как позволяет, например, написать скрипт, останавливающий клетку, производящий бекап (экспорт), и снова запускающий клетку. В итоге в архиве будет только ПО и настройки (в сжатом виде 200-300 мбайт), а контент будет отдельно и в экспорт не пойдет (например, у меня это 1 Тб торрентов). Аналогично и с OwnCloud. Серверами Samba. И т.д.


Наконец то pkgng


Отдельное огромное спасибо хочу сказать создателям pkgng. Без разработки новой современной системы пакетного(бинарного) менеджмента проект CBSD не был бы настолько удобным как сейчас.

Появление pkgng повод «почти полностью» отказаться от /usr/ports – а точнее рассматривать его как дополнение к pkg. Я пользуюсь следующими принципами:
1. Все возможное ПО устанавливаю через pkg. При этом обновления получаю из ветки latest (правка файла /etc/pkg/FreeBSD.conf);
2. Если я понимаю (pkg info ), что какое-то ПО собрано в репозитории pkg с флагами, которые меня не устраивают, я монтирую /usr/ports внутрь клетки (причем не руками, а через фреймворк CBSD — cbsd jset mode=quiet jname=dokuwiki mount_ports=«1»), и собираю данное ПО из портов с нужными USE флагами;
3. С помощью pkg lock данное ПО, собранное с уникальными опциями, закрывается от дальнейшего автоматического обновления через pkg upgrade;

Итог – на любом количестве клеток я могу обновить 99% программ одним скриптом и с вероятностью 99% не сломаю при этом работу сервисов. Увы – 1 % всегда остается. НО – есть автоматизированные бекапы клеток. А также есть каталог с кэшем предыдущих установленных пакетов. Поэтому есть два варианта отката (откатить пакет либо откатить всю клетку). Напомню – у меня одна клетка – одна служба/сервис.

Примеры скриптов и настроек, написанных в ходе изучения CBSD:


Тестируем наличие в клетках уязвимого ПО:
#!/bin/sh

echo «Checking local SYSTEM»
pkg audit -F
echo ""
echo «Checking DokuWiki JAIL»
/usr/local/bin/cbsd jexec jname=dokuwiki pkg audit -F
echo ""
echo «Checking OwnCloud JAIL»
/usr/local/bin/cbsd jexec jname=owncloud pkg audit -F
echo ""
echo «Checking FTP Backup JAIL»
/usr/local/bin/cbsd jexec jname=ftpbackup pkg audit -F
echo ""
echo «Checking SAMBA JAIL»
/usr/local/bin/cbsd jexec jname=samba pkg audit –F


Вывод скрипта после запуска:
Checking local SYSTEM
vulnxml file up-to-date
0 problem(s) in the installed packages found.

Checking DokuWiki JAIL
vulnxml file up-to-date
0 problem(s) in the installed packages found.

Checking OwnCloud JAIL
vulnxml file up-to-date
0 problem(s) in the installed packages found.

Checking FTP Backup JAIL
vulnxml file up-to-date
0 problem(s) in the installed packages found.

Checking SAMBA JAIL
vulnxml file up-to-date
0 problem(s) in the installed packages found.


Выводим список доступных для обновления пакетов:
#!/bin/sh

echo «Checking local SYSTEM»
pkg upgrade -n
echo ""
echo «Checking DokuWiki JAIL»
/usr/local/bin/cbsd jexec jname=dokuwiki pkg upgrade -n
echo ""
echo «Checking OwnCloud JAIL»
/usr/local/bin/cbsd jexec jname=owncloud pkg upgrade -n
echo ""
echo «Checking FTP Backup JAIL»
/usr/local/bin/cbsd jexec jname=ftpbackup pkg upgrade -n
echo ""
echo «Checking SAMBA JAIL»
/usr/local/bin/cbsd jexec jname=samba pkg upgrade –n


Запуск обоих предыдущих скриптов и отсылка на почту по расписанию:
#!/bin/sh

sleep 1
echo «To: vershinin.e@gmail.com» > /root/Scripts/audit-pkg.mail
echo «Subject: Audit PKG on MAIN and JAILed systems!!!» >> /root/Scripts/audit-pkg.mail
echo "" >> /root/Scripts/audit-pkg.mail
echo "" >> /root/Scripts/audit-pkg.mail
sleep 1
`/root/Scripts/pkg-audit-all-sys.sh >> /root/Scripts/audit-pkg.mail`
sleep 1
`/root/Scripts/pkg-upgrade-all-sys.sh >> /root/Scripts/audit-pkg.mail`
sleep 1
`cat /root/Scripts/audit-pkg.mail | /usr/local/bin/msmtp vershinin.e@gmail.com`
sleep 1


Правила PF, ограничивающие доступ к клеткам и из клеток:
###### JAIL RULES ######

###### DokuWiki ########
# Default block rule
block from $dokuwiki to any
block from any to $dokuwiki
# Pass from ANY to Dokuwiki Apache HTTP
pass proto tcp from any to $dokuwiki port 80 keep state

###### FTP BACKUP ######
# Default block rule
block from $ftpbackup to any
block from any to $ftpbackup
# Pass from LAN to FTP Ports:
pass proto tcp from $mylans to $ftpbackup port 21
pass proto tcp from $mylans to $ftpbackup port {20000><20100}

###### OwnCloud ########
# Default block rule
block from $owncloud to any
block from any to $owncloud
# Pass from LAN to OwnCloud HTTP port
pass proto tcp from $mylans to $owncloud port 80 keep state
# Pass from WAN to OwnCloud HTTPS port
pass proto tcp from any to $owncloud port 443 keep state

###### ALL Rules for JAILs #######
pass proto icmp from $mylans to $mylans
pass proto udp from $mylans to {$dns_local $dns_google} port 53 keep state
pass proto tcp from $mylans to {$pkg_mirror1 $pkg_mirror2 $pkg_mirror3 $pkg_mirror4} keep state


Пример команды, выводящий список всех клеток и их статусов со всех подключенных серверов:
cbsd jls alljails=1 shownode=1 (alias jall)

Ее вывод:



Скрипт для регулярного экспорта клеток:
#!/bin/sh

jailname=$1

CBSDPATH=/CBSD

JAILBACKUPTARGET=/data/JAILS

backupdate=`/bin/date "+%Y-%m-%d"`

jstatus=`/usr/local/bin/cbsd jstatus $jailname`

if [ $jstatus -ne «0» ]; then
/usr/local/bin/cbsd jstop $jailname
sleep 15
fi

jstatus2=`/usr/local/bin/cbsd jstatus $jailname`

if [ $jstatus2 -eq «0» ]; then
/usr/local/bin/cbsd jexport jname=$jailname compress=0
sleep 15
fi

if [ -f $CBSDPATH/export/$jailname.img ]; then
cp $CBSDPATH/export/$jailname.img $JAILBACKUPTARGET/$jailname-$backupdate.img
sleep 5
fi

jstatus3=`/usr/local/bin/cbsd jstatus $jailname`

if [ $jstatus3 -eq «0» ]; then
/usr/local/bin/cbsd jstart $jailname
sleep 5
fi

jstatus4=`/usr/local/bin/cbsd jstatus $jailname`

if [ $jstatus4 -ne «0» ]; then
echo «Backup JAIL Finish Successfull! Jail restarted!»
fi

Резюме:


CBSD весьма интересный проект, с которым я рекомендую познакомиться поближе и иметь его в своем «портфеле готовых и удачных решений».
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330168/


Метки:  

Ваш бренд — на EuroPython 2017

Воскресенье, 04 Июня 2017 г. 11:16 + в цитатник
Прошлой осенью я опубликовал здесь свой топик Как устроен парсер Python, и как втрое уменьшить потребление им памяти. Весной я предложил эту тему организаторам EuroPython 2017, и неделю назад я узнал, что мой доклад принят на конференцию.



Мой нынешний работодатель равнодушен к Python и к питоноводам, так что на конференцию я поеду либо как частное лицо, либо как представитель вашей компании. В последнем случае ваш бренд будет у меня в слайдах, на футболке, на крышке ноутбука, и т.д. — где скажете, там и будет. Его увидят примерно полторы тысячи самых хардкорных Python-энтузиастов Европы! Взамен я ожидаю (полного или частичного) покрытия затрат на конференцию (входной билет, авиаперелёт, жильё).
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330166/


Метки:  

[Из песочницы] Уменьшение операций чтения/записи на Raspberry Pi

Воскресенье, 04 Июня 2017 г. 06:20 + в цитатник
Введение

Итак, в интернете можно найти статьи о том что в Raspberry флешки «живут» 2-3 месяца, после чего приходят в негодность. Предложенные решения — заменить стандартную microSD карточку на USB HDD. Решение простое, надёжное, плюс повышается скорость чтения/записи. Но почему флешки так быстро «умирают»? Могут ли те же факторы навредить жёсткому диску? И так приступим!

Матчасть
У флеш-накопителей есть ограниченное количество циклов записи. Значит если linux будет постоянно что то на неё писать — она может выйти из строя раньше времени. Жёсткие диски работают по другому принципу. Но для них мелкие операции чтения/записи тоже не особо полезны. Головка жёсткого диска может парковаться если он не используется определённый промежуток времени, это может делать система, а так же может быть заложенно в железе. В случае мелких операций чтения/записи, жёсткий диск постоянно не может запарковать головку (не критично) или паркует головку, и тут же начаинает что то читать/писать (вот это уже хуже).

Информация пишется страницами. Обычный размер страниы 4 кБ. Так что если мы хотим записать один байт, то или он поместится в буфер, или будет записанно 4 кБ. Если буфер заполнен, то страница записывается и дальнейшая запись идёт в следующую страницу, которая находится в ОЗУ.

Запись маленьких порций информации используется при журналировании файловой системы (даёт возможность не потерять информацию при сбое, например выключении питания), а так же функции логирования (сохрняют информацию о тех или иных системных событиях, или событиях программ). В raspberry логирование выполняет rsyslog[1]

В Raspbian есть два демона, которые можно отключить для уменьшения нагрузки на корневой носитель информации. Отключив их можно выиграть в операциях записи, но проиграть в надёжности и возможности востановления. Это демон журналирования файловой системы и rsyslog. Так что если есть ценные данные которые будут храниться в корневом диске, то службу журналирования лучше не отключать. Если же raspberry используется как игрушка или есть возможность быстро заменить основной диск, то журналирование файловой системы можно отключить. Насчёт логирования аналогично, если вы не знаете зачем оно нужно, то достаточно сказать что если что то не работает, то неисправность нужно искать изначально в логах. Если захотите задать вопрос кому то на форуме, то скорее всего попросят скинуть логи. Так что если всё работает или вам проще переустановить систему чем разбираться что «посыпалось» — можете смело отключать логи.

Для просмотра обращений к накопителям можно использовать утилиту iotop. Для этого нужно запустить её с параметрами:

sudo iotop -o -a

Установка iotop
sudo apt-get install iotop

Отключение логирования

Для отключения логирования открываем:

sudo nano /etc/rsyslog.conf

и коментируем в нём две сткроки в секции MODULES:

$ModLoad imuxsock # provides support for local system logging
$ModLoad imklog   # provides kernel logging support

Должно получиться так:

#  /etc/rsyslog.conf	Configuration file for rsyslog.
#
#			For more information see
#			/usr/share/doc/rsyslog-doc/html/rsyslog_conf.html


#################
#### MODULES ####
#################

#$ModLoad imuxsock # provides support for local system logging
#$ModLoad imklog   # provides kernel logging support
#$ModLoad immark  # provides --MARK-- message capability

# provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514

# provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514


###########################
#### GLOBAL DIRECTIVES ####
###########################

#
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
#
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

#
# Set the default permissions for all log files.
#
$FileOwner root
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022

#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog

#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf


###############
#### RULES ####
###############

#
# First some standard log files.  Log by facility.
#
auth,authpriv.*			/var/log/auth.log
*.*;auth,authpriv.none		-/var/log/syslog
#cron.*				/var/log/cron.log
daemon.*			-/var/log/daemon.log
kern.*				-/var/log/kern.log
lpr.*				-/var/log/lpr.log
mail.*				-/var/log/mail.log
user.*				-/var/log/user.log

#
# Logging for the mail system.  Split it up so that
# it is easy to write scripts to parse these files.
#
mail.info			-/var/log/mail.info
mail.warn			-/var/log/mail.warn
mail.err			/var/log/mail.err

#
# Logging for INN news system.
#
news.crit			/var/log/news/news.crit
news.err			/var/log/news/news.err
news.notice			-/var/log/news/news.notice

#
# Some "catch-all" log files.
#
*.=debug;\
	auth,authpriv.none;\
	news.none;mail.none	-/var/log/debug
*.=info;*.=notice;*.=warn;\
	auth,authpriv.none;\
	cron,daemon.none;\
	mail,news.none		-/var/log/messages

#
# Emergencies are sent to everybody logged in.
#
*.emerg				:omusrmsg:*

#
# I like to have messages displayed on the console, but only on a virtual
# console I usually leave idle.
#
#daemon,mail.*;\
#	news.=crit;news.=err;news.=notice;\
#	*.=debug;*.=info;\
#	*.=notice;*.=warn	/dev/tty8

# The named pipe /dev/xconsole is for the `xconsole' utility.  To use it,
# you must invoke `xconsole' with the `-file' option:
# 
#    $ xconsole -file /dev/xconsole [...]
#
# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
#      busy site..
#
daemon.*;mail.*;\
	news.err;\
	*.=debug;*.=info;\
	*.=notice;*.=warn	|/dev/xconsole



После перезагрузки система прекратит логирование. Проверяем:

sudo iotop -o -a

В выводе больше нет rsyslog.

Отключение журналирования

Тут есть небольшая сложность — раздел должен быть отмонтирован. Для этого можно использовать:

  • другой компьютер с линуксом
  • другой накопитель в качестве основного (например обычную флешку)
  • другой компьютер + LifeCD с линуксом

В случае когда у вас microSD карта — раздел на котором стоит система будет определятся как mmcblk0p2.

Тут mmcblk0 — это сама карточка, а p2 — второй раздел на ней (первый по умолчанию boot). Eсли же вы используете USB накопитель, то раздел определиться как sda2. Если вы загружаетесь с другого компьютера то скорее всего он определиться как sdb2.

Далее выполняем:

sudo umount /dev/sdb2
sudo tune2fs -O ^has_journal /dev/sdb2
sudo e2fsck -f /dev/sdb2

После этого проверяем:

dmesg | grep EXT4

Выдаёт:

[ 5890.967580] EXT4-fs (sdb2): mounted filesystem without journal. Opts: (null)

Загружаемся с нашего накопителя, вводим:

sudo iotop -o -a

И видим что к жёсткому диску только изредка обращается LXDE. В виду того что эти обращения не систиматичны (понаблюдаем минут 5-10) можно сказать что нагрузка на накопитель уменьшилась практически до нуля.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330160/


Метки:  

[Перевод] Как снизить количество брошенных корзин в онлайн продажах

Воскресенье, 04 Июня 2017 г. 01:38 + в цитатник
Почему пользователи бросают корзины? — вот главный вопрос, который задают себе все онлайн-предприниматели. Даже если у вас есть задатки Менделеева, вряд ли вам приснится универсальное средство от этой напасти. Да и чёткого ответа на этот вопрос, понятное дело, никто не даст. Appdynamics (производитель решения для Application Performance Monitoring (APM) — мониторинга производительности приложений) в своём блоге опубликовал статью, которая может дать некоторое представление о природе брошенных корзин и методах борьбы с этим. В одной из следующих статей я расскажу, какие средства аналитики могут предложить современные APM-решения. А пока вот этот перевод, который, возможно, покажет точки, где ваш онлайн-проект мог бы быть более эффективным.

featured_ux.jpg



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

Если ваш бизнес не сохраняет темп в развитии пользовательского интерфейса онлайн-магазина — не ожидайте стремительного роста — вы рискуете потерять часть аудитории вашего проекта. В 2016 году, согласно исследованиям, покупатели сделали 51% покупок в интернете, по сравнению с предыдущими годами (48% в 2015-м и 47% в 2014-м). Независимости от выбранной стратегии вам следует в первую очередь ориентироваться на удобство пользователей. Статья рассказывает о ключевых особенностях и лучших практиках UX, основанных на серьёзном опыте в отрасли электронной торговли. Независимо от того, покупают ли ваши покупатели со смартфона или настольного компьютера, основные идеи, описываемые в статье, применимы в любом случае. Начнем с некоторых важных моментов в элементах интерфейса, а затем более глубоко рассмотрим подходы к UX в каждом случае.

Итак, существует 4 вещи, на которые стоит обратить пристальное внимание (прошу прощения за кустарную локализацию картинок, простые белые квадраты с текстом показались не очень интересными. — прим. переводчика):


Навигация


Инвестируйте в интуитивную навигацию


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

Публикуйте контент, руководствуясь стратегией


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

Избегайте тупиковых поисковых ответов


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

Используйте навигационную цепочку


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


Страницы с товарами


Размещайте высококачественные информативные иллюстрации


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

Помогайте пользователям эффективно перемещаться между страницами при помощи быстрого просмотра



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

Используйте пользовательский контент


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

Уточните цены и скидки


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

Предоставьте понятный механизм для привлечения помощи


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

Оформление покупки (Checkout)


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


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

Сделайте навигационную цепочку шагов оформления заказа


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

Не забывайте о безопасности



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


Оптимизация


Оптимизация времени загрузки


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

Верстайте страницу с учётом наилучшего восприятия клиентами


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

Заключение


Обеспечение простоты покупки должно быть вашим приоритетом. Поскольку непрерывное улучшение интерфейса является вашим фокусом, для ваших клиентов будет позитивным опытом совершение покупки в вашем проекте. Уделяя большое внимание интуитивной навигации, понятным деталям и простому процессу оформления, вы можете значительно увеличить шансы того, что посетители станут покупателями.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330158/


Метки:  

[recovery mode] Выпуск бета-версии многолинейного TAPI драйвера для Terminal Services и анонс презентации 3CX v15.5

Воскресенье, 04 Июня 2017 г. 00:44 + в цитатник
На этой неделе мы поговорим о новом многолинейном TAPI драйвере, который используется для интеграции со многими CRM системами, и пригласим вас на онлайн-презентацию релиза 3CX v15.5.

Многолинейный TAPI драйвер 3CX  для Windows Terminal Services


По многочисленным просьбам партнеров и клиентов мы выпустили Multi Line TAPI Driver для TAPI-совместимых CRM систем, установленных на терминальном сервере Windows.

Для работы Multi Line TAPI драйвера необходим последний клиент 3CX для Windows (будет входить в поставку 3CX v15.5) и редакция 3CX Pro.

Установка многолинейного TAPI драйвера 3CX


  1. Скачайте дистрибутив и запустите установку драйвера.
  2. Во время установки появится окно, в котором следует указать добавочные номера и имена пользователей. В нем вы можете добавить до 5 пользователей (линий). Остальные линии добавляются после установки через конфигурационный файл C:\ProgramData\3CXMultiLineTapi\3CXTAPI.ini.
  3. После установки 3CX Multiline TAPI драйвера, скачайте и установите последнюю версию клиента 3CX для Windows.
  4. Запустите клиент. На этом установка завершена.

Добавление дополнительных линий


2.png

Как было сказано, дополнительные линии добавляются в файле

C:\ProgramData\3CXMultiLineTapi and edit 3CXTapi.ini

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



Обратите внимание: если вы регистрируете пользователя 1,100,James, клиент 3CX для Windows также должен быть настроен и зарегистрирован на добавочном номере 100. Если конфигурации TAPI и клиента 3CX не соответствуют, возникнет ошибка Unknown Session.

Добавив линии, сохраните файл и перезапустите службу Telephony Windows.

Онлайн-презентация выпуска 3CX v15.5


После того, как тысячи пользователей протестировали 3CX V15.5 Alpha и Beta, — мы готовы к запуску финальной версии!

Чтобы отметить это замечательное событие и рассказать вам о всех возможностях V15.5, мы проводим онлайн-презентацию и сессию вопросов и ответов 7 июня 2017 г. в 17 часов по восточноевропейскому времени (+2 UTC).

На ваши вопросы ответят: CEO компании Ник Галеа (Nick Galea), менеджер продукта Ник Борг (Nick Borg) и руководитель Отдела поддержки и обучения пользователей Стефан Вальтер (Stefan Walther). Вопросы можно задать на английском языке через YouTube Live Chat и Twitter с хэштегом #3CXv15.5. Перед самим вопросом указывайте ваше имя и партнерский статус. Большая просьба формулировать вопросы кратко и в позитивном ключе – так мы сможем ответить на максимальное число вопросов в отведенное время.

Фото 3CX.

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

Ждем вас в гости, чтобы поделиться секретами новых технологий 3CX!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330156/


[recovery mode] JSF 2 + Maven + Jetty. CDI, форма и AJAX

Суббота, 03 Июня 2017 г. 23:39 + в цитатник
В этот раз у нас появится Java-код. Будем писать форму и логику обработки введенных данных.
Пост НЕ для тех, кто знает что такое JSF 2 и/или JSF 1.2, а faces-config.xml — не просто файл в проекте. Смотрите, я предупреждал…

CDI


С версии JSF 2.3.0 стандартная аннотация @ManagedBean признана устаревшей. Т.е. чтобы обратиться к своему Java-коду из формы нам потребуется добавить в проект CDI (Context and Dependency Injection) — Weld.
В файл pom.xml добавляем:
    
        ...
        
            org.jboss.weld.servlet
            weld-servlet
            2.4.3.Final
        
    

Создадим файл /src/main/webapp/WEB-INF/beans.xml:




Вредный совет
В комментариях к прошлому посту заметили:
Там прям особая специфика в регистрации listener'а?

ОК! В файл /src/main/webapp/WEB-INF/web.xml добавляем:

        org.jboss.weld.environment.servlet.Listener
    
    ...


Запускаем: mvn jetty:run
Читаем traceback почему не работает.

Создадим файл /src/main/webapp/WEB-INF/jetty-env.xml:



    
        -org.eclipse.jetty.server.handler.ContextHandler
    

    
        -org.eclipse.jetty.servlet.FilterHolder
    

    
        -org.eclipse.jetty.servlet.ServletContextHandler
    

    
        -org.eclipse.jetty.servlet.ServletHolder
    

    
        
            
        
        BeanManager
        
            
                javax.enterprise.inject.spi.BeanManager
                org.jboss.weld.resources.ManagerObjectFactory
                
            
        
    


В файл /src/main/webapp/WEB-INF/web.xml добавляем:

        BeanManager
        javax.enterprise.inject.spi.BeanManager
    
    ...


Теперь вместо @ManagedBean будет работать @Named.
Учитывая что CDI штука хорошая, а с версии JSF 2.3.0 — критичная, стоит понимать что CDI в JSF используется по своему прямому назначению и к JSF непосредственно отношения не имеет.
Больше к CDI мы возвращаться не будем!

Классы FormData и FormCtrl


Теперь давайте напишем немного кода. Нам потребуется 2 класса — в 1-ом мы будем передавать данные, во 2-ом будет функция обработки этих данных.
Отступление
С точки зрения реализации — не обязательно выделять логику формы в 2 отдельных класса, но это «правильно» как с точки зрения тестирования, так и сточки зрения архитектуры.

Класс-данных /src/main/java/ru/habr/FormData.java:
package ru.habr;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class FormData {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Класс-обработчик /src/main/java/ru/habr/FormCtrl.java:
package ru.habr;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@RequestScoped
public class FormCtrl {

    @Inject
    FormData formData;

    public String doAction() {
        // Очень полезные действия с данными...
        System.out.println(formData.getUsername());
        System.out.println(formData.getPassword());
        return null;
    }
}


Если с FormData все понятно, то на FormCtrl стоит взглянуть пристальней:
  1. Благодаря @Inject, данные формы будут доступны в классе-обработчике в поле formData.
  2. Рекомендую придерживаться тезиса «метод-обработчик должен возвращать строку» хоть это и не обязательно. Строка в дальнейшем используется в навигации, но об этом позже.


Форма


Тут все просто!
В файл /src/main/webapp/index.xhtml добавляем:

    ...
    
        


Запускаем: mvn jetty:run
Проверяем: http://127.0.0.1:8080/

AJAX


На дворе 2017 год, а формы все еще без AJAX?!
В файл /src/main/webapp/index.xhtml внесем пару правок:

...

    ...
        


Что изменилось:
  1. Добавилось определение библиотеки тегов xmlns:f="http://xmlns.jcp.org/jsf/core". Без этого можно реализовать AJAX, но обрабатывать придется ручками, что долго и неблагодарно.
  2. Внутри h:commandButton появился . В execute — указываем что необходимо отправить на сервер (всю форму/все поля формы), в render — что необходимо обновить с сервера после выполнения AJAX.

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

Послесловие


Проект все еще очень скромен в своих возможностях, но я буду продолжать!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330146/


Метки:  

Запуск систем без тестовой эксплуатации

Суббота, 03 Июня 2017 г. 21:16 + в цитатник
Запуск систем по «каскадной модели» имеют такие этапы проекта, как предпроектное обследование, разработка системы, тестовая эксплуатация и промышленная эксплуатация. По усмотрению сторон допускается детализация проекта на множество субуровней и, например, использование не как «разработка системы», а «разработка технического задания» и «программирование в среде разработки». В любом случае, согласно модели выполнение этапов возможно только последовательно и только после завершения предыдущего этапа.
Процедуры тестирования каскадной модели

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




Требования к качеству системы/программной продукции


Самое главное при пропуске этапа — это не потерять качество разрабатываемого продукта. Для этого разберём раздел требований к качеству в ГОСТ Р ИСО/МЭК 25010-215. В нем приводятся основные характеристики качества системы (программной продукции):
  • функциональная пригодность,
  • уровень производительности,
  • совместимость,
  • удобство пользования,
  • надежность,
  • защищенность,
  • сопровождаемость,
  • переносимость.


Качество систем программной продукции ГОСТ Р ИСО 25010-215

В ГОСТе представлен полный список требований, поэтому ответ на каждый из них даёт полное представление о целесообразности и экономической эффективности проекта без этапа тестовой эксплуатации.

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


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

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

ТТХ БМП-1

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

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

Удобство использования. Если вернуться к выявлению замечаний на предпроектном обследовании, то можно заметить наличие не только критических замечаний, но и «вносящих неудобство». К примеру, отсутствие сервиса по заполнению сумм в документе не является критическим, поскольку всегда можно посчитать на калькуляторе и внести вручную.
Не забывайте про обратную сторону луны: тестовый период увеличивает нагрузку на сотрудника, работающего в двух системах (новой и старой), что вызывает ещё больше неудобств, нежели вручную вводить сумму документа.

Надёжность. Это способность системы продолжительное время сохранять рабочее состояние. Если рассматривать проект автоматизации на базе технологической платформы «1С Предприятие 8», то надежность обеспечивается рядом условий:
  • надёжностью технологических платформ 1С, СУБД (зависит от разработчиков).
  • квалифицированном построении технической и программной архитектуры системы.
  • квалифицированной настройкой.

Со стороны любого вендора встречаются ошибки. Повторюсь, любого. Будь то корпорация Тойота с численностью 350 тыс.чел., отзывающая свои автомобили из-за ошибок производства, будь то платформа 1С, выпускающая обновление с целью устранения ошибок.
Ошибки бываю разные, некоторые увлекательные :)
Ошибка 1С

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

Следует ещё отметить, что любая техническая структура ломается (пишу этот текст на фоне новостей о глобальном сбое Мегафона), и под надёжностью понимается, в том числе, сохраняемость данных и скорость восстановления архитектуры.
В продолжение примера 1С отмечу, что в практике делаю ежедневную архивацию. На текущий рабочий день должны быть архивы за последние 90 дней, далее 1 копия за каждый месяц.
Надо ли тестировать надёжность? Если это сложная архитектура, то нагрузочное тестирование необходимо вплоть до падения для определения максимальной возможности системы (задача — уронить базу).

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

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

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

Резюме


Проанализируйте все пункты описанные выше, составьте SWOT-анализ и принимайте решение о целесообразности. Но в любом случае, если запускаете без тестовой эксплуатации, обязательно включите в реестр рисков этот пункт и опишите реакцию на него.
Получить шаблон реестра рисков можно по почте «doc@ingraf.su» с указанием темы «Риски».
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330154/


Метки:  

[Из песочницы] Работа в команде. Как помирить дизайнера и верстальщика

Суббота, 03 Июня 2017 г. 20:14 + в цитатник
image

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

Эти жалобы взаимодополняемы. Если начать разбираться в корне проблемы, то виноватыми окажутся оба. Как помирить этих двух работников фронта?

Необходимо понять, что в большинстве случаев меняться нужно обоим.

Дизайнеры:



1. Используйте сетку


Удивительно, как много людей, называющих себя „веб-дизайнерами“ игнорируют этот базовый элемент работы. Сетка задает строгую горизонтальную иерархию вашего макета. Большинство верстальщиков используют готовые сетки или делают свои, что даёт им высокую точность и скорость вёрстки.
Изучите принцип работы сетки, например Bootstrap.

Если вам сложно самому рассчитать размеры колонок, используйте специальный онлайн-калькулятор.
Возьмите на вооружение 10, 8 или 4-пиксельную сетку. В изучении 8px сетки отлично помогает изучение концепции Material Design и этой статьи.

2. Изучите основы вёрстки


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

3. Показывайте состояния объектов в различных состояниях


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

Не заставляйте думать верстальщика за вас. Показать состояния объектов можно вот так:

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

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

4. Типизируйте


Типизируйте все объекты на макете. Если это заголовок Open Sans 1.2em, то пусть он везде будет Open Sans 1.2em. Аналогично поступите с кнопками, абзацами, интерлиньяжем и отступами. Мы не говорим, что всё должно выглядеть одинаково — нет. Вы должны понимать, что чем больше у вас типизированных объектов, тем проще верстальщику с ними работать. Если вы хотите полностью сработаться с верстальщиком, изучите связку Атомарный дизайн + БЭМ.

5. Переименуйте слои


Об этом пункте не говорил разве что ленивый, но слишком уж часто верстальщику приходят макеты с хаотично накиданными слоями, название которых ни о чём не говорит. Переименуйте слои согласно их смыслу и сгруппируйте по типам. Вы можете использовать в названиях как БЭМ-синтаксис, так и общие термины вроде button, header, footer и так далее.

image

6. Соберите изображения и иконки


Соберите все иконки и изображения из вашего макета и разместите в папку проекта согласно смыслу. Например вот так: img/photos/photo1.jpg, img/icons/facebook.svg и так далее. Этот простой шаг поможет верстальщику гораздо быстрее и эффективнее работать с макетом при вставке графики.

7. Создайте Kit


Под Kit’ом я имею виду отдельный лист, в котором прописаны все типизированные элементы системы: например заголовки всех уровней и разновидностей, кнопки и их вариации, разделительные линии и так далее. Если вы ранее типизировали объекты, то вы легко можете перенести их в Kit на отдельный лист. Благодаря этому верстальщик может спокойно подготовить базу с помощью методологии БЭМ и собирать сайт словно кубики лего.

8. Комментируйте


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

image

Верстальщики:



1. Посмотрите на макет глазами дизайнера


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

2. Попробуйте нарисовать дизайн


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

3. Не принимайте решений за дизайнера


Очень часто рисуя по макету, верстальщики пренебрегают какими-то “мелочами” и не верстают их. Они считают, что дизайнер просто увлёкся, и нарисовал ненужные “красотульки”. Нет! Хороший дизайнер изучает продукт, для которого будет рисовать дизайн, продумывает элементы, композицию, размещает все на это макете и создаёт единую картину. Если у вас возникают какие-то сомнения относительно изменений в дизайне, обязательно согласуйте их с дизайнером.

4. Поддерживайте диалог


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

5. Обсудите общие инструменты для работы


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

Заключение


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

Над статьёй работали Григорий Мочалин и Илья Дзенски.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330144/


Метки:  

[Из песочницы] 3 cпособа нарушить Single Responsibility Principle

Суббота, 03 Июня 2017 г. 17:47 + в цитатник
Single Responsibility Principe достаточно прост для понимания и его не сложно придерживаться.
Но в работе я достаточно часто сталкиваюсь нарушением этого принципа. В этой статье я собрал самые больные из способов нарушить SPR из тех, что я встречал.

Первый способ: Singleton


Singleton — подразумевает, что помимо своих основных обязанностей класс занимается еще и контролированием количества своих экземпляров, чем нарушает Single Responsibility Principle.

Очень просто создать Singleton. Достаточно скопировать из википедии пару строк кода в вашу любимую IDE. Singleton есть везде, не нужно заморачиваться с передачей объекта в нужное место и управлять памятью тоже не обязательно, экземпляр один, к тому же он вечный. Эта легкость возможно и является причиной применения Singleton-а не по назначению.

Singleton повышает связность кода


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

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

Экземпляр Singleton-а невозможно подменить без танца с бубном


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

Singleton может хранить свое состояние


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

Есть более безопасные порождающие паттерны


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

Несмотря на все описанные выше ужасы есть места где уместно использовать Singleton


Singleton уместен в тех случаях, когда не может логически существовать более одного экземпляра объекта. Например NSApplication.

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

Второй способ: смешение архитектурных слоев


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

Бизнес-логика в модели.


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

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

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

Неправильное использование паттернов MVC, MVP, MVVM


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


Но у каждого из этих паттернов один общий недостаток — разрастание Controller-а, Presenter-а или View-Model-и. Суть проблемы кроется в неправильном понимании компонента View и компонента хранящего бизнес-логику (Controller, Presenter или View-Model).

View должна содержать логику, для отображения пользовательского интерфейса, Controller, Presenter или View-Model должны содержать бизнес-логику. Отдельных слов заслуживает MVC iOS SDK навязывает использование MVC. Но UIViewController не является MVC-шным Controller-ом, так как в большинстве случаев содержит логику для отображения пользовательского интерфейса.
Этот факт делает практически невозможным реализовать правильный MVC. В лучшем случаев UIViewController становится частью View, бизнес логика выноситься в другие слои.

С другой стороны, после отделения логики, необходимой для отображения интерфейса, в Controller-е, Presenter-е или View-Model-и все-равно может остаться слишком много кода. Это очень часто связано с тем, что для одного экрана создается один объект содержащий бизнес-логику, при этом он может реализовывать несколько пользовательских сценариев, что опять нарушает SRP.

Каждый объект содержащий бизнес логику должен реализовывать не больше одного пользовательского сценария.

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

Решением проблемы “разрастающегося контроллера” будет грамотное использование архитектурных паттернов. Если придерживаться SRP при написании кода и выносить из Controller-а, Presenter-а или View-Model-и весь код не относящийся к его основной ответственности, логика станет прозрачнее, пользовательские сценарии понятнее и их будет проще читать.

Третий способ: NSNotificationCenter


Нотификации в iOS — отличный способ связать все со всем!

NSNotificationCenter является частным, но достаточно ярким представителем Singleton-а. Не смотря на то, что нотификации — паттерн взаимодействия (Communication Pattern), а Singleton — порождающий паттерн (Creational Pattern), нотификации сохраняет все недостатки Singleton-а.

Начиная обсервить нотификацию не связанную с основными обязанностями классы мы нарушаем SRP.

Основные проблемы возникающие при использовании нотификаций:

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

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

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

Решение описанных проблем — отказаться от использования нотификаций в пользу более удобных механизмов.

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

Формальные признаки нарушения SRP:

  • Одним из самых заметных признаков является разрастание размера класса или метода.
  • Наследование класса от большего количества протоколов (при условии соблюдения ISP).
  • Использование Singleton-ов может свидетельствовать о нарушении SRP.
  • Передача информации о изменении состояния конкретного объекта с использованием NSNotificationCenter (можно нотификациями сообщать об изменении глобального состояния)
  • Скапливание в объектах утилитных методов.
  • Большее количество публичных методов класса, также может свидетельствовать о нарушении SRP.
  • Большее количество приватных методов, которые можно разбить на группы. В этом случае каждая группа скорее всего имеет свою зону ответственности.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330142/


Метки:  

Задачка: найти треугольник с меньшим периметром

Суббота, 03 Июня 2017 г. 17:15 + в цитатник
Наткнулась на эту задачу совершенно случайно. У меня знакомая через год после окончания магистратуры снова решила учиться и начала готовиться к поступлению. А значит что-то нужно просто повторить и вспомнить, ну и разобраться с чем-то новым. Вот сидела она над какой-то задачей, я проходила мимо. Задача показалась весьма простой (школьного уровня), но надо немного подумать.

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

Задачка является частью доказательства задачи Фаньяно.

Сама задача Фаньяно звучит следующим образом:
Рассматриваются всевозможные треугольники $DEF$, вершины $D$, $E$ и $F$ которых лежат на сторонах $BC$, $AC$ и $AB$ остроугольного треугольника $ABC$ соответственно. Доказать, что из всех треугольников DEF наименьшим периметром обладает ортоцентрический треугольник треугольника $ABC$.


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

Первые мысли, которые приходят в голову, это, наверное, построить перпендикуляры (как кратчайшее расстояние до сторон). Отображаем точку $D$ симметрично относительно $AC$ и $AB$ (получаем точки $D_1$ и $D_2$).

У некоторых сразу же может возникнуть искушение соединить точки пересечения перпендикуляров и сторон угла $BAC$. После чего появляется ложное впечатления «я сделяль», и кажется, что $KDL$ — это тот самый треугольник.

Всё не так. Тот факт, что две стороны треугольника — кратчайшие (перпендикуляры до прямой), еще не делает периметр треугольника минимальным.

На самом деле поиск треугольника с наименьшим периметром использует утверждение: кратчайшее расстояние между двумя точками – прямая. Дополнительные построения должны привести к тому, чтобы все длины сторон искомого треугольника оказались на прямой. Соединяем точки $D_1$ и $D_2$. Точки пересечения прямой $D_1D_2$ со сторонами угла и есть оставшиеся искомые вершины треугольника.



$FK$ и $EL$ являются медианами и высотами(точка $D$ симметрично отображена относительно сторон угла) треугольников $D_2DF$ и $DD_1E$ соответственно, значит треугольники $D_2DF$ и $DD_1E$ — равнобедренные. Видно, что периметр треугольника $DEF$ равен длине отрезка $D_1D_2$. Треугольник с меньшим периметром найден.

Возьмем какие-нибудь другие точки($F$ и $E$) на сторонах угла.


Периметр этого треугольника $DEF$ оказывается больше, чем длина отрезка $D_1D_2$.

Вот и все. Удачи всем поступающим!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330130/


Метки:  

Решение транспортной задачи в среде моделирования Python

Суббота, 03 Июня 2017 г. 17:11 + в цитатник

Постановка задачи


Стандартная транспортная задача приведена в следующей таблице [1].



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

Для открытой задачи запасы поставщиков и потребности равны — Для закрытой задачи они разные —

Математическая модель открытой задачи состоит из целевой функции и балансовых уравнений.


Для закрытой задачи. В математической модели для закрытой задачи целевая функция та же что и в открытой, а условий два.
Для условия — :
— целые числа; (3)

Для условия — ;

— целые числа; (4)

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

Ограничения на грузоподъемность транспорта определяется следующим условием.



Такие модели не всегда имеют решение. Условием решаемости является наличие хотя бы одного допустимого решения.

Ограничение по задержке на таможне однородного груза объёмом d.



где натуральное число d, удовлетворяет условию:



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

Если или , то модель (6) принимает вид (1, 3) или (1, 4), соответственно.

Приоритеты


При условии в соотношении (3) для некоторых значений индекса i, пробегаемых переменной I, добавляются ограничения .

При условии в соотношениям (4) для некоторых значений индекса j, пробегаемых переменной J, добавляются ограничения.



Ограничения (7, 8) появляются тогда, когда торговые отношения с каким-либо поставщиком или потребителем ограничены по времени, например, при покупке или продажи энергоносителей сезонного потребления. То, что в определенный срок не вывезено – будет продано другим. То, что не завезено – позже восполнить нельзя, а значит, такие пункты должны быть обязательно закрыты.

Паритет


При условии в (1, 3) для некоторых значений i, k добавляется ограничение то есть из пунктов и вывозятся равные объемы груза.

При условии в (1, 4) для некоторых значений j, r добавляются ограничения то есть в пункты и завозятся равные объемы груза.

Об особенностях решателя CVXOPT в среде моделирования Python [2]


CVXOPT обеспечивает возможность задавать элементы модели в матричном виде, что очень удобно. Переменные модели могут быть заданы при помощи класса cvxopt. modeling. variable. Например, так x = variable (9, 'x').

Для класса variable ограничения могут определяться как логические выражения с одним из операторов “<=”, “==”, “>=”, операндами которого являются линейные выражения относительно объектов variable. В том числе, могут использоваться и векторные операции. Например, для скалярных выражений применительно к транспортной задаче:



Функция cvxopt. modeling. op по переданым в качестве параметров целевой функции переменным и набору ограничений создает объект модели, например, применительно к транспортной задаче.

problem =op(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8], [mass1, mass2, mass3, mass4, mass5, mass6,x_non_negative])

Пример исходных данных для моделирования




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

  1. Модель закрытой транспортной задачи минимизации расходов на закупку товаров
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import numpy
    from cvxopt.modeling import variable, op
    def count(mass1, mass2, mass3, mass4,mass5,mass6,z):         
             x_non_negative = (x >= 0) #общее условие для всех х      
             problem =op(z,[mass1,mass2,mass3,mass4 ,mass5,mass6, x_non_negative])
             problem.solve(solver='glpk')  
             problem.status
             print("Минимальная стоимость закупки -",problem.objective.value()[0])
             print("Матрица закупок:")
             for i in [1,4,7]:
                      print("|",x.value[i-1],"|", x.value[i],"|", x.value[i+1],"|")
    x = variable(9, 'x')
    z=(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8])# целевая функция
    mass1 = (x[0] + x[1] +x[2] <= 74)# условие для первой строки матрицы закупок
    mass2 = (x[3] + x[4] +x[5] <= 40)#условие для второй строки матрицы закупок
    mass3 = (x[6] + x[7] + x[8] <= 36)# #условие для третьей строки матрицы закупок
    mass4 = (x[0] + x[3] + x[6] == 20)# условия для столбца
    mass5 = (x[1] +x[4] + x[7] == 45)#условия для столбца
    mass6 = (x[2] + x[5] + x[8] == 30)#условия для столбца
    count (mass1, mass2, mass3, mass4, mass5,mass6,z)
    

    Решение:

    Минимальная стоимость закупки — 215.0
    Матрица закупок:

    | 0.0 | 45.0 | 0.0 |
    | 0.0 | 0.0 | 30.0 |
    | 20.0 | 0.0 | 0.0 |

  2. Вносим небольшие изменения в предыдущую программу – добавляем переменную mass7 = (x[1] == 30).

    Торговые ограничения для второго поставщика в 30 условных единиц
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import numpy
    from cvxopt.modeling import variable, op
    def count(mass1, mass2, mass3, mass4,mass5,mass6,mass7,z):         
             x_non_negative = (x >= 0)       
             problem =op(z,[mass1,mass2,mass3,mass4 ,mass5,mass6 ,mass7,x_non_negative])
             problem.solve(solver='glpk')  
             problem.status
             print("Минимальная стоимость закупки -",problem.objective.value()[0])
             print("Матрица закупок:")
             for i in [1,4,7]:
                      print("|",x.value[i-1],"|", x.value[i],"|", x.value[i+1],"|")
    x = variable(9, 'x')
    z=(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8])
    mass1 = (x[0] + x[1] +x[2] <= 74)
    mass2 = (x[3] + x[4] +x[5] <= 40)
    mass3 = (x[6] + x[7] + x[8] <= 36)
    mass4 = (x[0] + x[3] + x[6] == 20)
    mass5 = (x[1] +x[4] + x[7] == 45)
    mass6 = (x[2] + x[5] + x[8] == 30)
    mass7 = (x[1] == 30)
    count(mass1, mass2, mass3, mass4,mass5,mass6,mass7,z)
    


    Решение:

    Минимальная стоимость закупки — 245.0
    Матрица закупок:

    | 0.0 | 30.0 | 0.0 |
    | 0.0 | 0.0 | 30.0 |
    | 20.0 | 15.0 | 0.0 |

  3. Ограничение по пропускной способности таможни на общий товарооборот в 80 условных единиц
    Для этого в программе п.1 заменим строку:
    mass5 = (x[1] +x[4] + x[7] == 45)
    на
    mass5 = (x[1] +x[4] + x[7] == 30)

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import numpy
    from cvxopt.modeling import variable, op
    def count(mass1, mass2, mass3, mass4,mass5,mass6,z):         
             x_non_negative = (x >= 0)    
             problem =op(z,[mass1,mass2,mass3,mass4 ,mass5,mass6, x_non_negative])
             problem.solve(solver='glpk')  
             problem.status
             print("Минимальная стоимость закупки -",problem.objective.value()[0])
             print("Матрица закупок:")
             for i in [1,4,7]:
                      print("|",x.value[i-1],"|", x.value[i],"|", x.value[i+1],"|")
    x = variable(9, 'x')
    z=(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8])
    mass1 = (x[0] + x[1] +x[2] <= 74)
    mass2 = (x[3] + x[4] +x[5] <= 40)
    mass3 = (x[6] + x[7] + x[8] <= 36)
    mass4 = (x[0] + x[3] + x[6] == 20)
    mass5 = (x[1] +x[4] + x[7] == 30)
    mass6 = (x[2] + x[5] + x[8] == 30)
    count(mass1, mass2, mass3, mass4,mass5,mass6,z)
    

    Решение:

    Минимальная стоимость закупки — 170.0
    Матрица закупок:

    | 0.0 | 30.0 | 0.0 |
    | 0.0 | 0.0 | 30.0 |
    | 20.0 | 0.0 | 0.0 |

  4. Ограничения на поставку товара у второго поставщика
    Для этого в программе п.1 заменим строку:

    mass2 = (x[3] + x[4] +x[5] <= 40)
    на
    mass2 = (x[3] + x[4] +x[5] == 40)

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import numpy
    from cvxopt.modeling import variable, op
    def count(mass1, mass2, mass3, mass4,mass5,mass6,z):         
             x_non_negative = (x >= 0)    
             problem =op(z,[mass1,mass2,mass3,mass4 ,mass5,mass6, x_non_negative])
             problem.solve(solver='glpk')  
             problem.status
             print("Минимальная стоимость закупки -",problem.objective.value()[0])
             print("Матрица закупок:")
             for i in [1,4,7]:
                      print("|",x.value[i-1],"|", x.value[i],"|", x.value[i+1],"|")
    x = variable(9, 'x')
    z=(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8])
    mass1 = (x[0] + x[1] +x[2] <= 74)
    mass2 = (x[3] + x[4] +x[5] == 40)
    mass3 = (x[6] + x[7] + x[8] <= 36)
    mass4 = (x[0] + x[3] + x[6] == 20)
    mass5 = (x[1] +x[4] + x[7] == 45)
    mass6 = (x[2] + x[5] + x[8] == 30)
    count(mass1, mass2, mass3, mass4,mass5,mass6,z)
    


    Решение:

    Минимальная стоимость закупки — 245.0
    Матрица закупок:

    | 0.0 | 45.0 | 0.0 |
    | 10.0 | 0.0 | 30.0 |
    | 10.0 | 0.0 | 0.0 |

  5. Паритеты на поставки второго и третьего поставщиков
    Для этого в программе п.1 заменим строки:
    mass2 = (x[3] + x[4] +x[5] <= 40)
    mass3 = (x[6] + x[7] + x[8] <= 36)

    на
    mass2 = (x[3] + x[4] +x[5] == 30)
    mass3 = (x[6] + x[7] + x[8] == 30)


    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import numpy
    from cvxopt.modeling import variable, op
    def count(mass1, mass2, mass3, mass4,mass5,mass6,z):         
             x_non_negative = (x >= 0)    
             problem =op(z,[mass1,mass2,mass3,mass4 ,mass5,mass6, x_non_negative])
             problem.solve(solver='glpk')  
             problem.status
             print("Минимальная стоимость закупки -",problem.objective.value()[0])
             print("Матрица закупок:")
             for i in [1,4,7]:
                      print("|",x.value[i-1],"|", x.value[i],"|", x.value[i+1],"|")
    x = variable(9, 'x')
    z=(7*x[0] + 3*x[1] +6* x[2] +4*x[3] + 8*x[4] +2* x[5]+x[6] + 5*x[7] +9* x[8])
    mass1 = (x[0] + x[1] +x[2] <= 74)
    mass2 = (x[3] + x[4] +x[5] == 30)
    mass3 = (x[6] + x[7] + x[8] == 30)
    mass4 = (x[0] + x[3] + x[6] == 20)
    mass5 = (x[1] +x[4] + x[7] == 45)
    mass6 = (x[2] + x[5] + x[8] == 30)
    count(mass1, mass2, mass3, mass4,mass5,mass6,z)
    


    Решение:

    Минимальная стоимость закупки — 235.0
    Матрица закупок:

    | 0.0 | 35.0 | 0.0 |
    | 0.0 | 0.0 | 30.0 |
    | 20.0 | 10.0 | 0.0 |


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

Анализ интерфейса решателя Excel Solver при решении данной закрытой транспортной задачи.


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

Анализ интерфейса решателя Minimize Mathcad при решении данной закрытой транспортной задачи.



Для работы функции Minimize необходимо устанавливать условия x>=0 для каждой переменной отдельно и вручную вычислять затраты по полученным значениям –x. В решателе CVXOPT для указанных действий предусмотрены следующие функции:
x_non_negative = (x >= 0)
problem. objective.value () [0]


Вывод


На простом примере приведено решение закрытой транспортной задачи с ограничениями средствами решателя CVXOPT среды моделирования Python.

Ссылки


  1. А. В. Кузнецов, Н. И. Холод, Л. С. Костевич. Руководство к решению задач по математическому программированию. — Минск: Высшая школа, 1978. — С. 110.
  2. CVXOPT Modeling.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330138/


Метки:  

[Из песочницы] Синхронизация структуры базы данных между приложениями

Суббота, 03 Июня 2017 г. 16:56 + в цитатник

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

Чаще всего используется простой подход — создание набора SQL-скриптов для модификации структуры БД от версии к версии. Конечно, есть такой мощный инструмент, как Red gate, но он во-первых небесплатный, во-вторых не решает проблему полной автоматизации обновления.


Технология migrations, впервые появившаяся в ОРМ Hibernate и реализованная в Linq, очень хороша и удобна, но подразумевает стратегию разработки структуры БД code first, что весьма трудоемко для уже существующих проектов, а использование в БД триггеров, хранимых процедур и функций делает задачу перехода на code first практически невыполнимой.


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


Генерация XML-файла со структурой БД


Для экспериментов будем использовать БД DbSyncSample. Скрипт для создания БД приведен ниже.


USE [DbSyncSample]
GO
/****** Object:  Table [dbo].[Orders]    Script Date: 06/01/2017 10:37:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Orders](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[OrderNumber] [nvarchar](50) NULL,
	[OrderTime] [datetime] NULL,
	[TotalCost] [decimal](18, 2) NOT NULL,
 CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_Orders_OrderNumber] ON [dbo].[Orders] 
(
	[OrderNumber] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[Details]    Script Date: 06/01/2017 10:37:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Details](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Descript] [nvarchar](150) NULL,
	[OrderId] [int] NULL,
	[Cost] [decimal](18, 2) NOT NULL,
 CONSTRAINT [PK_Details] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Trigger [Details_Modify]    Script Date: 06/01/2017 10:37:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[Details_Modify]
   ON  [dbo].[Details] 
   AFTER INSERT,UPDATE
AS 
BEGIN
	UPDATE Orders
	SET TotalCost = s.Total
	FROM (
		SELECT i.OrderId OId, SUM(d.Cost) Total
		FROM Details d
		JOIN inserted i ON d.OrderId=i.OrderId
		GROUP BY i.OrderId
	) s
	WHERE Id=s.OId
END
GO
/****** Object:  Trigger [Details_Delete]    Script Date: 06/01/2017 10:37:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[Details_Delete]
   ON  [dbo].[Details] 
   AFTER DELETE
AS 
BEGIN
	UPDATE Orders
	SET TotalCost = s.Total
	FROM (
		SELECT i.OrderId OId, SUM(d.Cost) Total
		FROM Details d
		JOIN deleted i ON d.OrderId=i.OrderId
		GROUP BY i.OrderId
	) s
	WHERE Id=s.OId
END
GO
/****** Object:  Default [DF_Details_Cost]    Script Date: 06/01/2017 10:37:43 ******/
ALTER TABLE [dbo].[Details] ADD  CONSTRAINT [DF_Details_Cost]  DEFAULT ((0)) FOR [Cost]
GO
/****** Object:  Default [DF_Orders_TotalCost]    Script Date: 06/01/2017 10:37:43 ******/
ALTER TABLE [dbo].[Orders] ADD  CONSTRAINT [DF_Orders_TotalCost]  DEFAULT ((0)) FOR [TotalCost]
GO
/****** Object:  ForeignKey [FK_Details_Orders]    Script Date: 06/01/2017 10:37:43 ******/
ALTER TABLE [dbo].[Details]  WITH CHECK ADD  CONSTRAINT [FK_Details_Orders] FOREIGN KEY([OrderId])
REFERENCES [dbo].[Orders] ([Id])
GO
ALTER TABLE [dbo].[Details] CHECK CONSTRAINT [FK_Details_Orders]
GO

Для экспериментов создаем консольное приложение. Подключаем к нему nuget-пакет Shed.DbSync.


Структуру БД в виде XML получаем следующим образом:


class Program
    {
        private const string OrigConnString = "data source=.;initial catalog=FiocoKb;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";
        static void Main(string[] args)
        {
            //  получаем XML со структурой БД
            var db = new Shed.DbSync.DataBase(OrigConnString);
            var xml = db.GetXml();
            File.WriteAllText("DbStructure.xml", xml);
        }
    }

После запуска программы в файле DbStructure.xml видим следующее:




  0
  
    
        
          1
          int
          4
          false
          true
          false
        
        
          2
          nvarchar
          100
          true
          false
          false
        
        
          3
          datetime
          8
          true
          false
          false
        
        
          4
          decimal
          9
          false
          false
          false
        
      
        
          1
          CLUSTERED
          true
          true
          false
          
            
              1
              1
              false
            
          
        
        
          2
          NONCLUSTERED
          false
          false
          false
          
            
              2
              1
              false
            
          
        
      
        1
      
        
          4
          ((0))
        
      
1 int 4 false true false 2 nvarchar 300 true false false 3 int 4 true false false 4 decimal 9 false false false 1 CLUSTERED true true false 1 1 false 1 2137058649 1 3 1 NO_ACTION NO_ACTION 4 ((0))
CREATE TRIGGER [dbo].[Details_Modify] ON dbo.Details AFTER INSERT,UPDATE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN inserted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END SQL_TRIGGER CREATE TRIGGER [dbo].[Details_Delete] ON dbo.Details AFTER DELETE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN deleted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END SQL_TRIGGER

Разворачивание/обновление структуры БД при помощи полученного XML.


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


    class Program
    {
        private const string OrigConnString = "data source=.;initial catalog=DbSyncSample;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";
        private const string TargetConnString = "data source=.;initial catalog=DbSyncSampleCopy;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework";

        static void Main(string[] args)
        {
            //  получаем XML со структурой эталонной БД
            var dborig = new Shed.DbSync.DataBase(OrigConnString);
            var xml = dborig.GetXml();
            File.WriteAllText("DbStructure.xml", xml);

            //  если нужно предварительно очистить структуру целевой БД, используем
            //  Shed.DbSync.DataBase.ClearDb(TargetConnString);

            //  обновляем структуру целевой БД
            var dbcopy = Shed.DbSync.DataBase.CreateFromXml(xml);
            dbcopy.UpdateDb(TargetConnString);
            //  на самом деле можно обойтись одной строкой:
            //  dborig.UpdateDb(TargetConnString);
            //  dbcopy создаем только для демонстрации создания объекта базы из XML
        }
    }

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


В сценариях тестирования может понадобиться создание тестовой БД каждый раз с нуля. В этом случае будет полезно использовать функцию Shed.DbSync.DataBase.ClearDb(string connString)


Автоматическое слежение за структурой БД.


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


        static void SyncDb()
        {
            // автоматическое слежение за структурой БД
            Shed.DbSync.DataBase.Syncronize(OrigConnString, 
                @"Struct\DbStructure.xml",      //  путь к файлу структуры
                @"Struct\Logs",                 //  путь к папке логов синхронизации
                @"Struct\update_script.sql"     //  (необяз.) в случае определения этого параметра
                                                //  в него будет записан скрипт, сгенерированный 
                                                //  для обновления БД
            );
        }

Слежение производится при помощи параметра (тега) Version в XML. Сценарий использования процедуры такой:

  1. Назначить версию БД. В Microsoft SqlServer Management Studio на узле нужной базы данных правой кнопкой выбрать Properties.
  2. Далее Extended Properties и в таблице свойств добавить свойство Version со значением 1. При каждой последующей модификации структуры это свойство следует наращивать на 1.
  3. При запуске приложения, если XML-файла нет или его версия меньше, чем у БД, он создается.
  4. Если версия XML-файла больше, чем у БД, генерируется скрипт на обновление БД и исполняется.
  5. Если в процессе исполнения скрипта возникли ошибки, все изменения откатываются.
  6. Результаты синхронизации пишутся в log-файл, создаваемый в папке, указанной параметром logDitPath.
  7. Если указан параметр SqlScriptPath, создается файл со скриптом из п.4.

Эксперименты оставляю читателям. Успехов вам!

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330134/


Метки:  

«Интересная тема для обсуждения — относительность тестового покрытия»: T-Systems о тестировании

Суббота, 03 Июня 2017 г. 16:48 + в цитатник

Метки:  

[Из песочницы] Электронная подпись в Битрикс24. Теория и опыт внедрения

Суббота, 03 Июня 2017 г. 14:55 + в цитатник

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

В этой статье поговорим о видах, плюсах, минусах ЭЦП, возможностях интеграции и как на практике происходит внедрение ЭЦП на корпоративный портал Битрикс24.


Про работу и терминологию


ЭЦП инструмент удобный и давно знакомый почти каждому, кто работает с удаленным документооборотом. Однако реализовать ЭЦП на Корпоративном портале Битрикс24 оказалось задачей нетривиальной. Наше знакомство с подобной интеграцией началось с двух клиентских задач:


  1. Стандартной — внедрить подпись документации удаленно.
  2. Нестандартной — дать возможность сотрудникам, разбросанным по всей территории России, отлажено и вовремя сдавать авансовую отчетность.

Однако вначале давайте разберёмся «что это такое — ЭЦП» и «с чем её едят».


Личная подпись — один из идентификаторов человека. Законодательно и безнаказанно повторить её может только этот человек, только его рука. А если она (рука) не дееспособна, а важная сделка не должна сорваться — проводится специальная нотариальная процедура и подпись ставит доверенный человек.


Не будем скрывать — подпись подделывают. Дело мастерства и привычки. Хоть и выработаны технологии сверки — по нажиму, толщине, линиям — гарантом является только обладатель подписи. Любая непонятная другим закорючка признаётся легитимной со слов её автора.


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


Но участники процесса не всегда находятся в досягаемости друг от друга. Есть почта, но это затратно и долго.


Здесь и перейдем к электронной подписи. Она бывает трех видов (ФЗ от 06.04.2011 № 63-ФЗ «Об электронной подписи»).


  1. Простая электронная подпись (ПЭП). Это привычная для нас пара «логин-пароль». Явные недостатки ПЭП начинаются с низкой надежности и заканчиваются отсутствием механизма защиты от изменений. Иногда её применение возможно даже в суде (например, документ, переданный по электронной почте, там ведь есть логин-пароль), но это сложно и далеко не во всех случаях срабатывает.


  2. Неквалифицированная электронная подпись. Часто используют приставку «усиленная», но в законодательстве такого определения нет. Она, в отличие от ПЭП:


    • результат криптографии;
    • содержит идентификатор подписанта;
    • позволяет определить внесены ли изменения в электронный документ.

  3. Квалифицированная электронная подпись. Также используют приставку «усиленная». Это то же самое, что и неквалифицированная, но с двумя важными дополнениями:


    • Сертификат выдан Аккредитованным удостоверяющим центром (далее УЦ). УЦ проверяет все нужные документы и выступает гарантом подлинности данных. Информация об авторе подписи хранится в УЦ. В случае спора, недопонимания личные данные проверяют, поэтому в каждом сертификате находится информация об удостоверяющем центре, который его выдал.
    • ПО для подписи сертифицировано ФСБ России.

info

Везде по тексту под ЭЦП понимается именно усиленная квалифицированная или усиленная неквалифицированная подпись.


Подведём промежуточный итог. Неквалифицированная подпись будет действительна только между лицами, которые заключили соглашение и признают подпись действительной. Квалифицированной подписью можно заверить практически любые документы. Они будут легитимны. Работа с УЦ — это аналог нотариального заверения. Исключение составляют счет-фактуры для зачета НДС. Электронные счет-фактуры передаются только через операторов электронного документооборота. Даже счет-фактура, подписанная по всем правилам ЭЦП, отправленная по электронной почте, не будет легитимной.


Вопрос выбора того или иного вида подписи зависит только от потребностей бизнес-процессов.


Что на выходе? Форматы документов с ЭЦП


Следующий вопрос — что мы получаем на выходе? Документ с факсимиле, с водяным знаком? Какой формат документа с ЭЦП можно получить?


Есть два возможных исхода:


  1. Контейнер («обычная» подпись). Как правило, это архив формата «*.sig». Там находятся подписанные документы, данные о сертификате, с помощью которого сделана подпись и сама подпись. Файл такого формата открывается только с помощью специального ПО. Использовать привычные Adobe Reader или MS Office не получится — они не приспособлены для работы с криптографией. Кроме самих данных, подписи и сертификата, пользователь может сохранить неподписанную копию документа.


    image

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


    • PDF. Подпись невидима в теле документа, но отображается на панели подписей. По желанию, её можно визуализировать, например, в виде штампа. При клике на него видны данные о подписи. Кстати, именно в таком виде, как правило, подписывают и присылают документы ИФНС (также используется вариант xml).


      image

    • MS Office. Подпись размещается в специальной области документа и видна на панели подписей или в свойствах файла.


      image

    • XML. Подпись вместе с данными о ней содержится в области значений XML и встраивается в тот же XML-конверт, не изменяя начальные данные.


info

Вариант «встроенной подписи» наиболее удобен в использовании. Именно о нем пойдет речь в материале.


Неочевидные тонкости ЭЦП


  1. Один документ разные стороны могут подписать исключительно единообразно: либо только ЭЦП, либо только в бумажном виде (например, договор между Заказчиком и Исполнителем). Подпись в бумажном виде не действительна в электронном, а подпись в электронном виде не действительна в бумажном. Это два разных документа.


  2. Документ можно подписать сколько угодно раз. То есть сначала подписал сотрудник, потом бухгалтер, потом Генеральный директор.


  3. Несколько документов, подписанных ЭЦП, можно в одном пакете (архиве) подписать общей совершенно другой ЭЦП. Другие же документы в пакете с ЭЦП также остаются легитимными.


  4. Документы можно подписывать ЭЦП в автоматическом режиме. Предположим, сформировали счет на оплату в CRM — он автоматически подписался. Можно его отправлять клиенту, счет легитимен.


Про инструменты и возможности


С видами подписей и вариантами результата разобрались. Теперь перейдем к выбору инструментов. Держим в уме, что есть конкретная задача — интегрировать ЭЦП на корпоративном портале Битрикс24.


Важный шаг — выбор компании поставщика ПО для реализации ЭЦП. Выбор пал на признанного лидера отрасли с широким инструментарием, которому нет аналога в РФ — КриптоПро. Для решения нашей задачи поставщик предложил несколько инструментов.


КриптоПро CSP (СКЗИ)


Криптопровайдер КриптоПро CSP устанавливается на ПК пользователя локально. Он подписывает документы, обращаясь к сертификату в реестре, на eToken или RuToken, смарт-картах и других носителях.


image

Процесс подписи


  1. «Автоматический» режим (т.е. встроив в портал). При загрузке файла на сервер и нажатии на «Подписать» с помощью плагина для браузера будет сделан вызов к КриптоПро CSP. Он подпишет файл выбранными ключами, которые записаны в реестре, либо на eToken клиента. В таком режиме можно сделать только «обычную» (контейнер) и XML подпись, так как передается только хэш документа. Подписать внутрь PDF или документ MS Office не получится.


  2. В «ручном» режиме (т.е. выйдя из портала) подпись генерирует сам клиент с помощью того ПО, которым он пользуется. Например, для подписи документа MS Office должны быть установлены MS Office, КриптоПро CSP и КриптоПро Office Signature. В интерфейсе MS Office пользователь добавляет подпись к документу, используя КриптоПро в качестве криптопровайдера. После этого подписанный файл загружается в личный кабинет функцией «приложить документ».


Плюсы


  • Не требуется подключение к интернету.
  • Можно использовать переносной usb-Token.
  • Самый дешевый вариант с точки зрения ПО КриптоПро, но не интеграции.

Минусы


  • Документы MS Office или pdf подписать внутрь файла можно только вручную, в «автоматическом» режиме можно получить только контейнер.
  • Подпись происходит с помощью плагинов, что создает неудобства. Они менее надежны. Многие браузеры отказываются от технологий, на которых пишут плагины, усложняется интеграция. Это существенно увеличивает стоимость технической реализации и поддержки работы ПО в будущем.
  • Пользователь сам отвечает за рабочее состояние CSP. Требуется актуальная версия всех программ, компонентов. Обновления происходят часто, следовательно, процедуру «настройки» придется проходить каждый раз заново, что создает неудобства.

КриптоПро DSS


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


image

В КриптоПро DSS можно настроить способ аутентификации пользователя:


  • по логину и паролю;
  • с использованием кода доступа к сертификату (ПИН-код, 4-5 цифр);
  • с использованием цифровых сертификатов, usb-Token или смарт-карт (в режиме DSS lite, подробности ниже)
  • с дополнительным вводом одноразового пароля, доставляемого пользователю посредством SMS (OTP-via-SMS)

Как происходит процесс подписи документа


Пользователь нажимает «Подписать». Генерируется запрос к КриптоПро DSS на подпись. Портал просит ввести ПИН-код доступа к сертификату (если установлено такое требование), и пользователь получает одноразовый пароль по SMS. После правильного ввода документ будет подписан и сохранён на портале, соответственно, отправлен далее по запланированному маршруту. Клиент видит только конечный результат, переходить в другое окно ему не требуется. Что важно и удобно, результат приходит в том же формате pdf -> pdf, docx -> docx.


Плюсы


  • Поддержка системы (работоспособность, обновления и т.д.) на плечах КриптоПро. Отдали запрос — получили результат, остальное не ваши заботы.
  • Поддержка подписи pdf и MS Office, т.е. для просмотра не требуется специализированных инструментов в отличие от контейнера.
  • Самый удобный для пользователя и стабильный способ интеграции, а также беспроблемный для техподдержки и администрирования.
  • Преимущество — подписывать документы можно с мобильного телефона.

Минусы


  • Для подписи требуется подключение к интернету.
  • Относительная дороговизна и более сложная процедура подключения к DSS. Используется схема с оператором. Подключение оператора на данный момент 39 000 руб./год плюс стоимость сертификатов. Говорят, что скоро использовать операторов при работе не придется. Очень ждем.

КриптоПро DSS lite


Это «облегчённая» версия КриптоПро DSS. Она предназначена для подписания документов ЭЦП в браузере с использованием ПО. Отличие от DSS — в качестве криптопровайдера используется ПО установленное на ПК пользователя, что позволяет использовать usb-Token и Смарт-Карты для подписи.


image

DSS lite — «режим» DSS (т.е. идет в составе продукта DSS). Процесс подписи происходит аналогично DSS. Нажатие «подписать» отправляет файл на сервер DSS lite, тот формирует хэш документа и запрашивает доступ к криптопровайдеру (CSP, установленный на ПК пользователя) с помощью плагина. Выгодное отличие — вы получаете pdf и документы MS Office в исходном виде со встроенной в сам документ подписью, а не в контейнере.


Плюсы


  • Поддержка подписи pdf и MS Office. Для просмотра подписанного документа не требуется специализированных инструментов.
  • С DSS lite подключать оператора не нужно, достаточно «купить» доступ к DSS lite.
  • Можно использовать переносный usb-Token.

Минусы

  • Подпись происходит с помощью плагинов, что создает неудобства (о них говорили выше).
  • Поддержка работоспособности лежит на плечах пользователя — та же проблема, что и с CSP.
  • Для подписи требуется подключение к интернету.
  • DSS lite требует нового сертификата или перевыпуска старого, что, по сути, равносильно. Прежний сертификат, пусть и от КриптоПро, невозможно вшить в программу.

info

Кстати, функциональность DSS и DSS lite позволяет добавлять визуальный штамп/печать/подпись по вашему выбору на документ. Сама ЭЦП невидима, а штамп — инструмент визуализации.


Практический опыт внедрения


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


Такую задачу поставили и нам — реализовать подпись на корпоративном портале 1С-Битрикс24. Нужен правильный функционал, удобство в использовании и грамотное вложение бюджета.


Но, как известно, теория часто не сопоставима с практикой. Решение реальных задач оказывается сложнее, но интереснее.


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


  1. Автоматизировать бизнес-процесс согласования документов.


    Особенность — возможность выбора определенных участников согласования, его последовательность. Реализовать проект требовалось на стандартном модуле бизнес-процессов корпоративного портала «1С-Битрикс24». Для заказчика было важно разработать наглядный, простой и интуитивный интерфейс.


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


  2. Реализовать ЭЦП на корпоративном портале «1С-Битрикс24» для ведения авансовой отчетности.


Предпроектные работы


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


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


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


  1. Генеральный директор подписывает приказ о направлении сотрудника в командировку. Часто эти приказы подписываются после командировки задним числом, но это не меняет дальнейший юридический ход процесса.


  2. Командированный сотрудник получает денежные средства под отчет. Так он становится должником перед компанией.


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


  4. Сотрудник по возвращению из командировки составляет авансовый отчет, чтобы с него «списали» долг. К авансовому отчету сотрудник прикладывает все подтверждающие документы: чеки, билеты и прочее.


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


  6. После сдачи авансового отчета, сотрудник обязан вернуть остаток средств или получить недостающие.


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


  1. Сотрудники находятся в командировках перманентно — все рабочее время. Даже посещение главного офиса — командировка, ведь сотрудники имеют постоянное место жительства, как правило, не в Москве.

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


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

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


Внедрение


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


Так как данный бизнес-процесс планировалось реализовать на корпоративном портале Битрикс24, мы изучили вопрос интеграции ЭЦП в портал. Что важно, весь процесс должен проходить в режиме одного окна, т.е. из портала.


info

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


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


В итоге автоматизированный бизнес-процесс авансовой отчетности работает следующим образом:


  1. Каждому торговому представителю, выдается сертификат ЭЦП, его личный, именной (в принципе, он другим быть и не может).


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


    image

  3. Там он создает новый авансовый отчет, пошагово заполняя все строчки. Расходы он записывает с чеков, которые находятся в его руках. Параллельно агент фотографирует чеки на тот же iPad, и прикрепляет их к онлайн авансовому отчету.


    image

    image

    В этот момент в 1С создаётся черновик авансового отчета, которому присваивается порядковый номер, это очень важный момент.


  4. Когда все заполнено, форма авансового отчета создается автоматически. Она типовая, поэтому вероятность, что форма будет меняться — минимальна.


  5. Сотрудник проверяет форму и подписывает её ЭЦП. Сам процесс подписи происходит по следующему алгоритму:


    • Пользователь на корпоративном портале жмет кнопку «подписать ЭЦП».

    • Документ через SOAP протокол без открытия дополнительных окон отправляется в КриптоПро DSS. КриптоПро DSS идентифицирует пользователя тремя шагами:

      • Логин/пароль от сервиса DSS — для удобства они совпадают с логин/паролем от портала. Получается, что вводить ничего не надо, пользователь сразу переходит ко второму шагу проверки.

      • ПИН-код, состоящий из 4 или 5 цифр (на выбор пользователя). Теперь сервис DSS может использовать сертификат, который хранится в его реестре на сервере.

      • Одноразовый пароль — SMS на мобильный телефон. Один документ – одно SMS.


        image

        Кстати, КриптоПро позволяют оставить в качестве проверки только ПИН-код или только SMS для экономии времени. Бухгалтеры заказчика так и поступили, оставив лишь ПИН-код.


    • Подписанный документ отправляется к руководителю сотрудника. Он проверяет форму отчета, лимиты, сверяет с фотографиями чеков. Если что-то не так — возвращает на доработку сотруднику с комментариями. Всё в порядке — подписывает документ с помощью облачного ЭЦП и отправляет на следующий шаг согласования.

    • Бухгалтер также подписывает документ ЭЦП и отправляет генеральному директору. На этом этапе бухгалтеру остается только провести уже заполненный и сохраненный авансовый отчет в 1С. С этого момента может выдаваться новый транш.

    • Генеральный директор подписывает отчет ЭЦП. На самом деле подпись директора уже формальность, необходимая по законодательству — отчет проверен руководителем, бухгалтером и документы для новой командировки могут уже готовиться.

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

    • Сотруднику приходит уведомление, что авансовый отчет подписан. Он отправляет оригиналы чеков в головной офис, и бухгалтер сверяет их с отчетом. Как правило, все совпадает, но если вскрываются факты жульничества и чека не хватает (хотя на фото он есть), авансовый отчет в 1С правится, а к сотруднику применяются меры воздействия.


info

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


Результат


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

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330126/


Метки:  

Orange Pi на автомойке ч.3

Суббота, 03 Июня 2017 г. 13:07 + в цитатник
Продолжение статей Arduino на автомойке и Arduino на автомойке ч.2.

Как понятно из заголовка перешли на использование Orange Pi One. Машинка гораздо поинтереснее Arduino. Выбран среди себе подобных в основном из-за цены. По сравнению в Arduino лучше решает следующие задачи:
— сеть (проблем пока нет)
— подключение монитора вместо табло
— возможность использования тач-панели
— возможность использования базы данных
— возможность установки на «себя» веб-сервера

В качестве операционной системы выбрана DietPi. Программирование в QT.
Купюроприёмник подключен через последовательный порт. Монитор в HDMI. Тач панель в USB. Выходы на реле 29, 31, 33, 35, 37. Подключен жетоноприёмник на 22 ногу через делитель напряжения.

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

Некоторые лайф-хаки апельсина:

Останавливаем консоль на UART для купюрника
sudo systemctl stop serial-getty@ttyS0.service
sudo systemctl mask serial-getty@ttyS0.service


Поворот экрана (файл /etc/X11/xorg.conf)
Section "Device"
Identifier "default"
Driver "fbdev"
Option "Rotate" "CW"
EndSection


Включаем поддержку некоторых тач-панелей (файл /etc/modules)
hid_multitouch

Запрещаем спать ( файл /etc/X11/xorg.conf.d/10-dpms.conf)
Section "ServerFlags"
Option "blank time" "0"
Option "standby time" "0"
Option "suspend time" "0"
Option "off time" "0"
EndSection


Выставляем режим работы выхода.
void pinMode(int  pin, int mode)
{
    FILE *file;
    char path[80];
    file=fopen("/sys/class/gpio/export" , "w");
    fprintf(file, "%d", pin);
    fclose(file);
    sprintf(path, "/sys/class/gpio/gpio%d/direction", pin);
    file=fopen(path , "w");
    fprintf(file, "%s", mode ? "out" : "in");
    fclose(file);  
}


Включение/выключение реле.
void digitalWrite(int pin, int value)
{
    FILE *file;
    char path[40];
    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    file=fopen(path , "w");
    fputc(value?'1':'0', file);
    fclose(file);
}


Краткие выводы на текущий момент:
— Orange пока работает стабильно, вылетов флеш-памяти не зафиксировано.
— От тач-панелей устойчивой работы не добились, переходим на кнопки.

Планы на будущее:
— подключение индуктивных петель для фиксации наличия машины
— создание личного кабинета клиента с возможностью запоминания и дальнейшего использования остатка денежных средств на любом аппарате сети автомоек.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330124/


Метки:  

Восстановление данных с внешнего жесткого диска Seagate FreeAgent Go

Суббота, 03 Июня 2017 г. 11:01 + в цитатник
Внешний жесткий диск Seagate FreeAgent Go 500Gb верой и правдой служил своей владелице, но в один из не самых лучших для него дней стал жертвой человеческих эмоций, когда владелица в пылу семейной драмы швырнула устройство в объект, вызывающий у нее сильное раздражение – в своего мужа. Муж серьезно не пострадал, а вот с накопителем дела обстояли хуже. При подключении в USB порт компьютера накопитель издавал тихие жужжащие звуки и не начинал вращение вала.


рис. 1

В таком состоянии внешний жесткий диск поступил в нашу лабораторию восстановления данных. Визуальный осмотр не выявляет каких-либо деформаций самого бокса. Учитывая, что в предыстории значится удар, такой накопитель подлежит обязательному вскрытию в условиях ламинарного бокса без каких-либо попыток включения во избежание дальнейших разрушений. Из бокса извлекается жесткий диск Seagate ST9500325AS (Momentus 5400.6), представитель семейства Wyatt. Корпус винчестера без деформаций и вмятин на крышке. Проводим мероприятия по удалению пыли из всех возможных мест и отправляемся в ламинарный бокс. Сняв крышку, обнаруживаем, что блок магнитных головок находится вне парковочной рампы.


рис. 2

С использованием съемников осуществляем вывод БМГ на рампу. Далее извлекаем БМГ и тщательно осматриваем все 4 слайдера и подвески под микроскопом на предмет деформаций и наличия посторонних частиц. Также осматриваем рециркуляционный фильтр и поверхность верхней пластины в месте залипания БМГ. В нашем случае установлено, что деформаций подвесок нет, загрязнения слайдеров отсутствуют. На поверхности пластины присутствует «пятно» с повреждением, которое невозможно увидеть невооруженным глазом. На рециркуляционном фильтре отсутствуют металлические частицы. Повреждений пластиковой парковочной рампы нет, перекоса пакета дисков нет.

По результатам данного осмотра установлено, что допустимо осуществить попытку чтения оригинальным блоком магнитных головок, но необходимо учитывать наличие повреждений у внешнего края пластин. Устанавливаем блок магнитных головок обратно в накопитель и производим сбор. Зная, что накопитель подвергся ударной нагрузке, выполним замену оригинальной печатной платы 100536286 Rev E, на заведомо исправную плату накопителя-донора с переносом ПЗУ. Данная мера рекомендуема, чтобы не получить неприятных сюрпризов из-за потенциально возможных микротрещин.

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


рис. 3

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

Rst 0x08M
(P) SATA Reset

Сразу же в ОЗУ накопителя необходимо найти модуль конфигурации HDD (ID=0x2A) и убрать оттуда все ключи, которые ответственны за запуск процедур оффлайн сканирования, автономного и отложенного скрытия дефектов, а также отключить процедуры автореаллокации при чтении и записи. Эта мера необходима, чтобы накопитель при обнаружении проблем не пытался запускать процедуры обслуживания дефектов, так как они приведут к длительной задержке БМГ над проблемным участком, что может спровоцировать лавинообразное разрушение (запиливание пластины). Структура модуля 0x2А (system file FC36608F) достаточно проста (порядок записи параметров достаточно очевиден). При исследовании (исследования проводились и продолжают проводиться для всех накопителей F3 архитектуры) главной сложностью было установление назначения каждого из параметров и допустимые значения. Использование современных версий комплекса PC3000 существенно упрощает процедуру правки значений.

Резервируем микропрограмму накопителя (ПЗУ, модули, “system files”). Проверяем на тестовых модулях, которые не важны для функционирования накопителя, способность записи и чтения записанного каждой из головок. Удостоверившись в корректной работе всех головок, перейдем к оценке качества их чтения в пользовательской зоне. Для этого построим карту зонного распределения в границах всего логического пространства (от 0 до 976 773 167 сектора LBA диапазона). Оценив размер мини-зон, можно сделать вывод, что для оценки читабельности головок в данном экземпляре достаточно непрерывно прочесть около 300 000 секторов в конце логического пространства, около 450 000 секторов в середине и около 600 000 в начале диска (зная о наличии повреждения пластин, начало диска не тестируем).
Удостоверившись в возможности чтения всеми головками, настроим параметры чтения: UDMA режим, таймаут операции чтения не более 500 миллисекунд, при отсутствии готовности программный сброс и пропуск мини-зоны. Построив список мини-зон в обратном порядке, приступим к последовательному чтению мини-зон (созданию посекторной копии).


рис. 4

99% логического пространства были прочитаны без каких-либо затруднений. Начиная с LBA 6 541 ххх по головке №1, обнаружилась первая задержка. Чтение было немедленно прервано и накопитель отправлен в sleep режим (парковка головок на рампу, остановка вала, но микропрограмма остается загруженной в ОЗУ жесткого диска. Перестроим список зон в прямой порядок и приступим к последовательному чтению.


рис. 5

С LBA 2 518 ххх также обнаружилась задержка чтения по головке №1. Также быстро отправляем накопитель в спящий режим. Проводим грубую оценку границ дефектной зоны и размер 6 541 000 – 2 518 000= 4 023 000, что примерно равно 2 GB.
Дальнейший анализ проводим исключительно копии на исправном накопителе. Оценим содержимое LBA 0.


рис. 6

Значение 0x07 по смещению 0x1C2 сообщает нам о том, что тип раздела NTFS (или ExFAT).

Значение 0x00000800 по смещению 0x1C6 информирует о том, что раздел начинается с сектора 2 048.

Значение 0x3A384800 по смещению 0x1CA говорит, что длина раздела 976 766 976 секторов.
Перейдем к сектору 2 048


рис. 7

Из параметров NTFS видим, что сектор 512 байт, секторов в кластере 8, размер кластера 512*8=4096 байт. MFT располагается с кластера 0x00000000000C0000 (786 432) или с сектора 6 293 504 (786 432*8+2048). MFT Mirror находится в кластере 0x0000000000000002 (2) или берет начало с сектора 2 064 (2*8+2048).

Зная границы дефектообразования, можем заметить, что с высокой вероятностью на область с MFT придутся дефекты. Для этого оценим первую запись MFT (в MFT Mirror, которая дублирует первые 4 записи MFT так как она прочитана). В нашем случае этот файл расположен в виде одного фрагмента, начиная с сектора 6 293 504 и протяженностью 277 092 сектора.


рис. 8

Обратим внимание, что основные затруднения в чтении были зафиксированы по головке №1, поэтому начнем чтение с зоны по головке №0. Пробудим накопитель из спящего режима и прочитаем фрагмент MFT по нулевой головке. В данном случае это не вызвало затруднений и позволило получить более 75% важнейшей структуры. Далее используем PIO режим для лучшего контроля операций чтения и попытаемся прочесть оставшиеся 68 400 секторов из проблемной зоны. Манипулируя размерами прыжков, таймаутами ожидания готовности, размером блока при чтении в несколько проходов, производим чтение проблемного участка. В области MFT остается 18 непрочитанных секторов, которые по расположению повторяются (цикличность соответствует SPT для этих зон), что свидетельствует о царапине на этой пластине.

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

При чтении заметим, что кроме проблем на поверхности, читаемой первой головкой, обнаруживаются проблемы по поверхности, читаемой головкой №3. Исключим чтение цепочек по проблемным поверхностям и прочитаем участки по поверхностям 0 и 2.

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

Отправляемся в ламинарный бокс и осматриваем произошедшее. Верхняя поверхность выглядит идеально, но под микроскопом обнаруживается начавшийся лавинообразный процесс разрушения пластины (запил). Наличие металлических частиц на слайдерах №1 и №3 уточняет диагноз.
Из посекторной копии создаем файловую копию с переносом файлов, имеющих недочитанные фрагменты, в отдельную папку (с оригинальной иерархией). Также уточненно проводим анализ MFT, чтобы понимать, к чему привела потеря 18 секторов. Из анализа повреждений можно однозначно установить, что утеряно не более 7 файлов. К сожалению, Bitmap также находится в дефектной зоне, и его содержимое не может быть использовано для анализа.

При приемке результата владелица диска осталась довольна результатом (более 99,9% нужных данных) и посчитала, что нет нужды проводить дополнительный анализ регулярных выражений для поиска пропавших файлов из-за повреждений MFT.

В качестве заключения хочу обратить внимание многих пользователей, что не все так просто в случае накопителей у которых «головки» залипли вне парковочной рампы. И насколько порой опасны предложения людей, далеких от понимания принципов работы накопителя на жестких магнитных дисках, самостоятельно вскрыть устройство и вывести головки, а далее используя dd из Linux или WinHex под Windows выполнить «безопасную» посекторную копию. Если бы к накопителю, описанному в публикации, были бы применены подобные меры, то он бы превратился в труп без возможности восстановления данных при чтении второго гигабайта.

Предыдущая публикация: Немного реверс-инжиниринга USB flash на контроллере SK6211
Публикация вне habrahabr: Восстановление данных с неисправного HDD WD4000FYYZ-01UL1B1
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330120/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 991 990 [989] 988 987 ..
.. 1 Календарь