Лампа Ergolux из магазина Светофор: хуже некуда

В магазинах Светофор продаются очень дешёвые светодиодные лампочки — 34 рубля 60 копеек за штуку. Я купил одну такую лампу в марте, а вторую в июне. Оказалось, что они радикально отличаются.


На коробке лампы указано много всего хорошего: мощность 15 Вт, световой поток 1425 лм, аналог лампы накаливания 120 Вт, индекс цветопередачи 80+, коэффициент пульсации <5%, допустимое напряжение 230В±10% (207-253 В).

К сожалению в новых лампах всё это не соответствует действительности.

У лампы, купленной в марте (код EL0512007, дата выпуска 07.2020), измеренная мощность была 7.7 Вт, световой поток 699 лм (эквивалент 70 Вт), но светодиоды там были хорошие (CRI 81) и при напряжении сети 230В пульсации не было. Несмотря на линейный драйвер, лампа более-менее выдерживала указанный диапазон напряжения: при 207В яркость падала на 7%, пульсация не превышала 15%. Вот результаты измерений этой лампы на Lamptest: https://lamptest.ru/review/03775-ergolux-led-a60p-15w-e27-4k-promo.

Лампа, купленная в июне (код 3L1162012, дата выпуска 12.2020), при включении удивила стопроцентной пульсацией, хорошо заметной визуально.

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

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

Я измерил параметры света старой и новой ламп с помощью спектрометра Uprtek MK350D. У новой лампы измеренный индекс цветопередачи низкий — CRI(Ra) 72, а коэффициент пульсации 100%.

Измеренная потребляемая мощность у новой лампы оказалась 6.3 Вт, а световой поток всего 494 лм (эквивалент лампы накаливания 50 Вт). Мощность измерялась прибором Robiton PM-2, световой поток в интегрирующей сфере 50 см с помощью того же спектрометра Uprtek MK350D.

При снижении напряжения сети до 225В яркость лампы падает на 5%, при 221В на 10%, при 213В на 20%, при 207В (нижний уровень диапазона, указанный производителем) яркость лампы падает на 30%, при 202В на 40%, при 197В на 50%, при 190В на 60%, при 183В на 70%.

Это означает, что при использовании в реальной сети с напряжением 210-220 В, лампа будет светить, как 40-ваттная лампа накаливания.

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

Сравню обещания производителя и результаты измерений:

Обещали пульсацию < 5%, измерено 100%;
Обещали 15 Вт, измерено 6.3 Вт;
Обещали замену лампы накаливания 120 Вт, измерено 40-50 Вт в зависимости от напряжения в сети;
Обещали 1425 лм, измерено 346-494 лм (при напряжении 207-230В);
Обещали индекс цветопередачи 80+, измерено 72.

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

© 2021, Алексей Надёжин

ссылка на оригинал статьи https://habr.com/ru/company/lamptest/blog/565512/

Видеочат с возможностью совместного редактирования текста при помощи Twilio Sync

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


Подготовка

Что вам будет нужно:

  • Бесплатная учётная запись Twilio. Если вы зарегистрируетесь здесь, вы получите 10 долларов в качестве кредита Twilio при переходе на платную учётную запись.

  • Node.js (версия 14.16.1 или выше) и npm.

  • Код из этого репозитория.

Скачайте и запустите код видеоблокнота

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

git clone -b start https://github.com/adjeim/video-note-collab.git

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

cd video-note-collab npm install

Скопируйте файл .env для переменных среды такой командой:

cp .env.template .env 

Затем откройте файл .env в редакторе кода и замените значения переменных своими учётными данными:

TWILIO_ACCOUNT_SID TWILIO_SYNC_SERVICE_SID TWILIO_API_KEY_SID TWILIO_API_KEY_SECRET

Найти свои учётные данные вы можете в консоли Twilio, на странице Twilio Sync Service и на странице Twilio API Keys. В качестве значения переменной TWILIO_SYNC_SERVICE_SID можно использовать SID по умолчанию. Теперь, когда вы ввели свои учётные данные, запустите сервер Express:

npm start

Если вы перейдёте по адресу http://localhost:3000/ в своём браузере, то увидите заметку:

Протестируйте приложение, набрав несколько слов в блокноте. При вводе пробела, клавиши ввода или знаков препинания запускается синхронизация. Если вы откроете второе окно браузера по адресу http://localhost:3000/ и одновременно посмотрите на них, вы должны увидеть, что текст, который вы вводите в одном окне, отображается и в другом:

Как это происходит? Это приложение использует Twilio Sync для синхронизации состояния и данных между браузерами и устройствами в режиме реального времени. Здесь у вас есть документ Sync, который называется notepad. Когда страница загружается, создаётся новый токен доступа, который передаётся Sync клиенту. Если документ существует, его содержимое загружается в <textarea>. Приложение отслеживает обновления документа, обновляя положение курсора и содержимое блокнота. Если вы откроете инструменты разработчика своего браузера, вы также сможете увидеть изменения в контенте, который записывается в консоль.

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

Обновите макет приложения

Первое, что вам нужно сделать, — это немного обновить макет вашего приложения. Если вы прямо сейчас откроете public/index.html в редакторе кода, то увидите, что Tailwind CSS и Twilio Sync уже подключены в проект. Обновите элемент <head>, добавив в него библиотеку Twilio Video, как показано в приведённом ниже коде:

<html>   <head>     <meta name='viewport' content='width=device-width, initial-scale=1.0' />     <link href='https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css' rel='stylesheet'>     <script type="text/javascript" src="https://media.twiliocdn.com/sdk/js/sync/v2.0/twilio-sync.min.js"></script>     <script src='https://sdk.twilio.com/js/video/releases/2.15.0/twilio-video.min.js'></script>     <title>Video Collaboration with Notes</title>   </head>

Обновите элемент <body>. Сначала добавьте элемент <form>, в котором пользователь может ввести своё имя и нажать кнопку, чтобы присоединиться к комнате.

  <body class='bg-grey-100 p-10 flex flex-wrap container'>     <form id='login' class='w-full max-h-20 flex items-center py-2'>         <input class='appearance-none bg-transparent border-b border-green-500 mr-3 py-1 px-2 focus:outline-none'             id='identity' type='text' placeholder='Enter your name...' required>         <button id='joinOrLeaveRoom' class='bg-green-500 hover:bg-green-700 text-white py-1 px-4 rounded' type='submit'>           Join Video Call         </button>     </form>     <textarea id='notepad' class='h-44 w-full shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea> 

Замените элемент <textarea>. В этом проекте вы отключите взаимодействие с документом и установите для него серый цвет фона при первой загрузке приложения.

    </form>     <textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>

Затем чуть ниже <textarea> добавьте элемент <div> для вывода видео  участников:

    <textarea disabled id='notepad' class='bg-gray-200 h-140 w-6/12 shadow-lg border rounded-md p-3 sm:mx-auto sm:w-1/2'></textarea>     <div id='container' class='w-5/12  bg-green-100'>       <div id='participantsContainer'>         <div id='localParticipant'>           <div id='localVideoTrack' class='participant'></div>         </div>         <div id='remoteParticipants'>           <!-- Remote participants will be added here as they join the call -->         </div>       </div>     </div> 

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

Обновите генерацию токена доступа

Если вы откроете index.js в своём редакторе кода, вы увидите, что у вас уже есть код для предоставления токена доступа и что к этим токенам доступа будет добавлен SyncGrant. Чтобы задействовать видео, вам также понадобится VideoGrant.

Под вашей константой для SyncGrant также укажите константу для VideoGrant. Пока вы в этой части кода, убедитесь, что ваше приложение может парсить JSON из тела запроса при помощи функции express.json():

const AccessToken = require('twilio').jwt.AccessToken; const SyncGrant = AccessToken.SyncGrant; const VideoGrant = AccessToken.VideoGrant;  app.use(express.json());

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

app.post('/token', async (req, res) => {   if (!req.body.identity || !req.body.room) {     return res.status(400);   }    // Get the user's identity from the request   const identity = req.body.identity;    // Create a 'grant' identifying the Sync service instance for this app.   const syncGrant = new SyncGrant({       serviceSid: process.env.TWILIO_SYNC_SERVICE_SID   });    // Create a video grant   const videoGrant = new VideoGrant({     room: req.body.room   })    // Create an access token which we will sign and return to the client,   // containing the grant we just created and specifying their identity.   const token = new AccessToken(       process.env.TWILIO_ACCOUNT_SID,       process.env.TWILIO_API_KEY_SID,       process.env.TWILIO_API_KEY_SECRET,   );    token.addGrant(syncGrant);   token.addGrant(videoGrant);   token.identity = identity;    // Serialize the token to a JWT string and include it in a JSON response   res.send({       identity: identity,       token: token.toJwt()   }); });

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

Подключение и вывод видео участников

Вернитесь в public/index.html в редакторе кода. Посмотрите на код в последнем теге <script> в конце файла. Вы увидите, что когда приложение загружается в браузере, этот код получает токен доступа из вашего запроса на токен, затем подключает клиент синхронизации и обновляет блокнот. Чтобы добавить видео в этот проект, нужно изменить этот код таким образом, чтобы приложение получило токен после того, как пользователь введёт своё имя и нажмёт кнопку «Join Video Call» в пользовательском интерфейсе. Затем этот токен будет использоваться для подключения пользователя к синхронизированному блокноту и видеозвонку. Чуть ниже вашей переменной notepad добавьте ещё несколько переменных, чтобы упростить обращение к другим элементам в вашем пользовательском интерфейсе:

<script>   const notepad = document.getElementById('notepad');   const localVideoTrack = document.getElementById('localVideoTrack');   const login = document.getElementById('login');   const identityInput = document.getElementById('identity');   const joinLeaveButton = document.getElementById('joinOrLeaveRoom');   const localParticipant = document.getElementById('localParticipant');   const remoteParticipants = document.getElementById('remoteParticipants');    let connected = false;   let room;   let syncDocument;   let twilioSyncClient;

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

  const addLocalVideo = async () => {     const videoTrack = await Twilio.Video.createLocalVideoTrack();     const trackElement = videoTrack.attach();     localVideoTrack.appendChild(trackElement);   };

Вызовите эту функцию в конце файла, непосредственно перед закрывающим тегом <script>:

  addLocalVideo(); </script>

Затем создайте новую функцию с именем connectOrDisconnect, которая будет обрабатывать событие, когда пользователь нажимает кнопку «Join Video Call». Если пользователь ещё не подключён к звонку, эта функция подключит их. Если пользователь уже подключён, эта функция отключит его. Добавьте следующий код чуть ниже функции addLocalVideo:

  const connectOrDisconnect = async (event) => {     event.preventDefault();     if (!connected) {       const identity = identityInput.value;       joinLeaveButton.disabled = true;       joinLeaveButton.innerHTML = 'Connecting...';        try {         await connect(identity);       } catch (error) {         console.log(error);         alert('Failed to connect to video room.');         joinLeaveButton.innerHTML = 'Join Video Call';         joinLeaveButton.disabled = false;       }     }     else {       disconnect();     }   };

Непосредственно перед закрывающим тегом <script> добавьте ещё один слушатель событий, на этот раз в форму входа. Этот слушатель будет вызывать connectOrDisconnect всякий раз, когда пользователь отправляет форму:

  // Add listener   notepad.addEventListener('keyup', (event) => {      // Define array of triggers to sync (space, enter, and punctuation)     // Otherwise sync will fire every time     const syncKeys = [32, 13, 8, 188, 190];      if (syncKeys.includes(event.keyCode)) {       syncNotepad(twilioSyncClient);     }   })    login.addEventListener('submit', connectOrDisconnect);

Затем замените блок fetch(‘/token’) следующей функцией подключения, которая примет идентификатор, переданный в форму, получит токен для этого пользователя с сервера, загрузит и включит документ и подключит этого локального пользователя в видеочат:

  const connect = async (identity) => {     const response = await fetch('/token', {       method: 'POST',       headers: {         'Content-Type': 'application/json',       },       body: JSON.stringify({'identity': identity, room: 'My Video Room'})     });      const data = await response.json();     const token = data.token;      // Set up sync document     twilioSyncClient = new Twilio.Sync.Client(token);     notepad.disabled = false;     notepad.classList.remove('bg-gray-200');      syncDocument = await twilioSyncClient.document('notepad');      // Load the existing Document     notepad.value = syncDocument.data.content || '';      // Listen to updates on the Document     syncDocument.on('updated', (event) => {        // Update the cursor position       let cursorStartPos = notepad.selectionStart;       let cursorEndPos = notepad.selectionEnd;        notepad.value = event.data.content;        // Reset the cursor position       notepad.selectionEnd = cursorEndPos;        console.log('Received Document update event. New value:', event.data.content);     })      // Set up the video room     room = await Twilio.Video.connect(token);      const identityDiv = document.createElement('div');     identityDiv.setAttribute('class', 'identity');     identityDiv.innerHTML = identity;     localParticipant.appendChild(identityDiv);      room.participants.forEach(participantConnected);     room.on('participantConnected', participantConnected);     room.on('participantDisconnected', participantDisconnected);     connected = true;      joinLeaveButton.innerHTML = 'Leave Video Call';     joinLeaveButton.disabled = false;     identityInput.style.display = 'none';   }; 

Как только локальный участник подключится к звонку, эта видеокомната будет назначена глобальной переменной для room. Видео локального пользователя будет отображаться в пользовательском интерфейсе, и слушатели событий будут отслеживать, когда другие участники присоединяются к видеовстрече или выйдут из неё. Кнопка «Join Video Call» также изменится на «Leave Video Call», а поле ввода для имени будет скрыто. Теперь, когда вы добавили функцию подключения, добавьте функцию отключения чуть ниже:

const disconnect = () => {     room.disconnect();      let removeParticipants = remoteParticipants.getElementsByClassName('participant');      while (removeParticipants[0]) {       remoteParticipants.removeChild(removeParticipants[0]);     }      joinLeaveButton.innerHTML = 'Join Video Call';     connected = false;     identityInput.style.display = 'inline-block';     localParticipant.removeChild(localParticipant.lastElementChild);          syncDocument.close();     twilioSyncClient = null;     notepad.value = '';     notepad.disabled = true;     notepad.classList.add('bg-gray-200');   }; 

Функция disconnect будет обрабатывать отключение участника от видеозвонка, когда он нажимает кнопку «Leave Video Call». Она также будет проходить через других участников видеозвонка и удалять видео из пользовательского интерфейса для отключённого участника. Состояние подключения снова устанавливается на false, поле ввода имени пользователя появляется снова, а кнопка «Leave Video Call» меняется на «Join Video Call». Кроме того, блокнот будет очищен и отключён для локального участника, как только кто-то отключится от видеозвонка, он также будет отключён от общего блокнота.

Затем вы захотите поработать с тем, что происходит, когда удалённые участники подключаются к звонку или отключаются от него. Начните с добавления функции ParticipantConnected, которая создаст новый <div> для подключённого участника, показывая имя пользователя участника в качестве его идентификатора и прикрепляя их видео и аудиодорожки к <div>, если локальный участник подписан на них.

Эта функция также создаёт обработчики событий для управления действиями по подписке, относящимися к аудио- и видеодорожкам участников. Если удалённый участник отключает свой аудио- или видеопоток, хочется иметь возможность реагировать на это событие и при необходимости подключать или отключать эти дорожки. Добавьте функцию participantConnected чуть ниже вашей функции отключения в public/index.html:

  const participantConnected = (participant) => {     const participantDiv = document.createElement('div');     participantDiv.setAttribute('id', participant.sid);     participantDiv.setAttribute('class', 'participant');      const tracksDiv = document.createElement('div');     participantDiv.appendChild(tracksDiv);      const identityDiv = document.createElement('div');     identityDiv.setAttribute('class', 'identity');     identityDiv.innerHTML = participant.identity;     participantDiv.appendChild(identityDiv);      remoteParticipants.appendChild(participantDiv);      participant.tracks.forEach(publication => {       if (publication.isSubscribed) {         trackSubscribed(tracksDiv, publication.track);       }     });     participant.on('trackSubscribed', track => trackSubscribed(tracksDiv, track));     participant.on('trackUnsubscribed', trackUnsubscribed);   }; 

Пришло время добавить функцию ParticipantDisconnected для ситуации, когда удалённый участник покидает видеозвонок. Это функция, которая находит участника по его sid (уникальному идентификатору) и удаляет его div из DOM. Добавьте функцию participantDisconnected сразу под вашей функцией ParticipantConnected:

  const participantDisconnected = (participant) => {     document.getElementById(participant.sid).remove();   };

А теперь добавим код для ситуации, когда локальный участник подписывается на аудио- или видеодорожки удалённого участника или отписывается от них. Добавьте следующие функции trackSubscribed и trackUnsubscribed в public/index.html чуть ниже вашего кода для participantDisconnected:

  const trackSubscribed = (div, track) => {     const trackElement = track.attach();     div.appendChild(trackElement);   };    const trackUnsubscribed = (track) => {     track.detach().forEach(element => {       element.remove()     });   };

У вас есть весь код проекта. Теперь протестируем блокнот с видео.

Тестирование вашего приложения

Перейдите по адресу http://localhost:3000/. Вы должны увидеть сайт, похожий на показанный ниже, с блокнотом слева и видеопотоком локального участника справа:

Введите своё имя в поле ввода и нажмите «Join Video Call». Вы увидите своё имя под видео. Если хотите, можете попробовать набрать текст в блокноте. Откройте другую вкладку браузера по адресу http://localhost:3000/ и присоединитесь к видеозвонку под другим именем. Как только вы это сделаете, вы увидите два изображения, а это означает, что вы можете общаться друг с другом и делиться блокнотом:

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

Что будет дальше с инструментом для совместной работы с заметками?

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

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

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы

ссылка на оригинал статьи https://habr.com/ru/company/skillfactory/blog/565450/

Y Combinator: редактирование мировоззрения основателей стартапов

image

В конце июня мы запустили нашу летнюю программу Y Combinator 2021 года — 33-ю по счету с момента основания акслератора в 2005 году. Сейчас мы финансируем сотни компаний каждые полгода, и я рефлексирую о том, как мы работаем с этими компаниями во время интенсива и потом, по мере того, как они строят свой бизнес.

За все годы я обнаружил, что существует распространенное заблуждение относительно того, чем мы занимаемся в Y Combinator. Люди часто считают, что смысл существования YC — это Demo Day и привлечение инвестиций, и что единственная цель учредителей при подаче заявки в YC и завершении нашей программы — повысить вероятность привлечения инвестиций.

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

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

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

Недавно я понял, что благодаря достижениям в биологии теперь есть способ расширить эту аналогию, чтобы лучше описать то, что делает YC. Благодаря нововведениям лауреатов Нобелевской премии Эммануэль Шарпантье и Дженнифер Дудна в биологии появилась эффективная техника редактирования генов под названием CRISPR. А YC — это CRISPR для стартапов.

Основатели стартапов с грандиозным потенциалом присоединяются к YC. Их стартапы имеют собственную ДНК, и мы ее модифицируем, редактируем, CRISPRизируем, если захотите, включаем ключевые аллели, которые, скорее всего, принесут успех. Какие это аллели?

  • Product-Market Fit: как думать о клиентах и ​​находить правильный способ предоставить им ценность.
  • Рост и продажи: как экономно и разумно увеличить клиентскую базу.
  • Строительство компании: как создать прочную, долгосрочную инфраструктуру компании. Особенно о том, как найти и нанять подходящего сотрудника.
  • Привелечение инвестиций: как наилучшим образом реализовать стратегию по привлечению нужного капитала в нужное время от правильных инвесторов.
  • Здоровье: как оставаться в здравом уме и оставаться сильным при создании стартапа.
  • Фокусировка: как быстро двигаться, оставаясь при этом полностью сфокусированным на цели.
  • Лидерство: как поверить в стартап настолько, чтобы основатель мог убедить других присоединиться к битве и выдержать неизбежные взлеты и падения.
  • Амбиции: это, пожалуй, наименее понятный, но самый важный эффект от того, что вы основатель YC и являетесь частью сообщества YC. Мы стремимся внушить уверенность в том, что любой, независимо от того, откуда он и кто он, может изменить мир и добиться следующего грандиозного успеха стартапа.

Сегодня к YC присоединяются основатели со всего мира. Хотя большинство из них в самом начале пути, наша цель состоит в том, чтобы к концу интенсива каждый из них обнаружил, что его траектория изменилась, чтобы дать им наилучшие шансы на выживание и процветание. «Редактирование генов» YC на этом не заканчивается. Мы продолжаем работать с основателями по мере того, как они создают свои компании, помогая им с наймом, проведения Раунда А и дальнейшим масштабированием.

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


Следите за новостями YC Startup Library на русском в телеграм-канале или в фейсбуке.

Полезные материалы

ссылка на оригинал статьи https://habr.com/ru/post/565524/

Оптимизации в вебе — дорого, сложно, и уже не нужно?

Кто знает, может Палпатин поэтому был таким злым

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

Если вы думаете именно так, мне есть что вам сказать.

Давайте начнем с простого. Конфигурация ноутбука, с которого я пишу эту статью — Сore-I5 7200U (2.5GHz-3.10GHz), 12GB оперативной памяти, SSD + нечто вроде 100 МБит сети, если мой провайдер не врет. И, честно говоря, я не часто вижу совсем уж медленные сайты и веб приложения, когда серфлю в интернете. Несмотря на это, каждый раз, когда я пишу код, я трачу некоторое время на обдумывание того, насколько сильно мои изменения повлияют на моих пользователей. И это вовсе не потому, что я такой красивый, а потому, что согласно данным аналитики, большинство клиентов используют наше веб-приложение с помощью мобильного телефона. Что, в свою очередь означает нестабильное хG соедениение (где x находится в пределах 2–4), меньший объем памяти (1–4 GB вместо моих 12) и процессор с условной частотой в 1.7GHz — 2GHz который и так чуточку занят десятком-другим вкладок и пятеркой приложений. Поэтому то, что у меня работает нормально — может подтормаживать и раздражать наших пользователей. А учитывая размер минимального чека моего пользователя — я очень не хочу никого раздражать. Да и по-человечески просто приятно, когда твое приложение работает быстро.

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

640kb хватит всем

Безусловно, мощность современных вычислительных систем просто поражает. Процессор моего смартфона в 16,(26) раз быстрее процессора моего первого компьютера с которого я вышел в интернет. И это, не говоря уже о том, что там было только одно ядро, а в телефоне их целых четыре плюс четыре. А ведь сайты по большому счету не изменились. HTML для содержимого, CSS для красивостей, и JS для взаимодействия. Из серебра не родилась молния, флеш не быстро, но тоже похоронили, а WebAssembly все еще в сборке. Да и пропускная способность современных сетей позволяет больше не требовать формат изображения, который бы рендерился снизу вверх. Расходимся? Увы, но нет.

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

Видимо на шестой секунде живут самые терпеливые

К выводам есть некоторые вопросы (в частности, очень любопытны причины роста конверсии на 6 и 9 секундах), но в целом идея логична. Чем дольше пользователь ждет контента, тем выше вероятность того, что он уйдет. За два года до этого, в далеком 2017, другая группа исследователей опубликовала еще одну статью согласно которой, для того чтобы успеть показать контент в перые пять секунд, размер загружаемых ресурсов не должен превышать 170KB (уже сжатых), если JavaScript-а "немного", или 130KB для сайтов/приложений построенных с помощью JS фреймоворках. Причины были названы следующие:

  • 45% мобильных соединений используют 2G
  • 75% всех соединений используют 2G или 3G
  • Усредненный телефоном — Motorola Moto G4 с процессором Octa-core (4×1.5 GHz Cortex-A53 & 4×1.2 GHz Cortex-A53)

В таких условиях разгуляться сложно, поэтому бюджет и выглядит так скромно. Однако с тех пор уже прошло четыре года и в поэтому в 2021 году исследование было повторено. Ситуация действительно улучшилась и теперь у нас есть 100Kb для HTML/CSS/Fonts и 300-350KB для пожатого JavaScript. Однако это произошло в основном благодаря улучшению качества связи. Вычислительные мощности устройств изменились не очень сильно. Взгляните на этот график и оцените прогресс с 2017 года.

Для мультикоров статистика получше, но JS в основном однопоточный

iPhone показывает стабильный рост, а вот остальные производители нажимают на педаль газа весьма осторожно. Но не iPhone-ом единым жив мобильный веб. Бюджетный сегмент ноутбуков тоже "не блещет". Вот несколько представителей в сегменте за 350 долларов:

А вы бы видели студенческие ноуты, какое там CPU, там одно АЛУ

Первая модель — всего 4GB DDR4, двухъядерный Intel Celeron N4020 (1.1–2.8 ГГц). Наверняка можно найти что-то и получше на этот бюджет, но если такие модели продаются, значит это кому-нибудь надо? А ведь еще есть огромное количество просто устаревшей, 10-и и даже 15-летней техники в офисах и домах. Можно сказать, что, игнорируя производительность своего сайта или приложения, добровольно отказываемся от части пользователей, и делаем жизнь остальных чуточку сложнее. Что и сказывается на конверсии.

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

import * as moment from "moment"; //... const date = moment(); const requestDuration = moment().diff(startMoment, "milliseconds");

Конечно, я все понимаю. Скорее всего в проекте у автора уже стоит moment, он к нему давно привык, поэтому он его и использовал. Но… это же учебный пример. Кто-то не посмотрел, как всегда, не подумал, скопировал и вот вам, в ваш любимый проект влетает от 18KB до 72KB JavaScript (и это уже после сжатия). А ради чего? Ради единственного метода diff. А потом, людям приходится даже писать спеицальные плагины что бы как-то это оптимизировать. И вот таких примеров, без предупреждений, без сносок о том, почему это может быть плохо — легион. Авторы статей, блогов и курсов, в погоне за простотой кода и аудиторией, приучают других разработчиков игнорировать производительность как класс.

А ведь помимо простого размера есть много других нюансов. У нас еще есть стили, которые парсятся хоть и быстро, зато умеют блокировать JS. Есть еще шрифты, которые могут заставить браузер вообще не показывать текст, пока не загрузятся. А самое мое любимое, так называемый холодный старт TCP, который просто игнорирует весь ваш 100МБит канал и позволяет отправить первый пакет не более чем в 14KB.

Поэтому, несмотря на весь прогресс, если мы не хотим терять/раздражать среднего пользователя, наш бюджет все еще довольно ограничен. Но, загрузка — ведь это тоже еще не все. Для SPA приложений просто загрузить ресурсы мало. Еще нужно выполнить JavaScript, и только потом, основываясь на вычислениях, отрисовать пользователю какой-то контент. На слабых устройствах это тоже будет вызывать проблемы. К примеру, вот сравнительный график загрузки нашего SPA приложения, написаного на React, без замедления CPU и с 6-кратным замедлением.

В пять секунд вложился, пронесло

Общий объем загруженого JavaScript — 253Kb, что не так и много. А время работы скриптов увеличилось с 362 милисекунд до 2102 милисекунд, т. е. в примерно в 5.8 раза. Largest-Contentful-Paint (не лучший ориентир, но подойдет) сдвинулся с 2.2 секунд до 4.7 секунд и немного подросли другие метрики.

Про Хабр

Хотел еще так же померять Хабр, но там сейчас какая-то совсем безумная мешанина скриптов для аналитики, пришлось отказаться. И, к тому же, для статики и рендера на стороне сервера (как раз наш Хабр) CPU менее важен, браузер DOM строит довольно быстро, если ему не мешать. Но если совсем интересно — вот моя статья как раз про Хабр.

Почему это важно? Потому что JavaScript язык в основном однопоточный и интенсивное его выполнение, блокирует основной поток и останавливает отрисовку HTML. Простыми словам, while(true){} установленный где-то в начале документа убивает все настолько качественно, что вы не то что на кнопку нажать не сможете, вы даже статический контент после этого кода не увидите даже на каком-нибудь Фугаку. Конечно, в здравом уме бесконечный цикл писать никто не будет, как и синхронно загружать его в страницу, но способов выстрелить в ногу в современном вебе все еще остается предостаточно. Тут и последовательные запросы вместо параллельных, и N+1 прямо с фронта, и тяжелые regex-ы во время рендера приложения, и чрезмерная работа с DOM-ом и многие, многие, многие. Да и сам фреймворк может вам подкинуть задачку.

Например, для меня до сих пор остается загадкой, почему, по умолчанию, функциональные компоненты в React вызываются всякий раз, когда вызывается их родитель. Да, это легко поменять, использовав React.memo или перейти на PureComponent, но библиотека, которая позиционируется быстрой (или уже нет?), почему-то решила пойти именно таким путем. Особенно проблемным это стало после популяризации хуков, что привело к усложнению функциональных компонентов. Кстати, раз уж речь зашла про React — вы конечно же знаете, что React встраивает изображения до 10kb в JS код?

Правда если вы думаете, что у Angular с этим всем легче то — не совсем. Утечки памяти из-за сложности Rx.JS, постоянный перерендер компонентов из-за дефолтной Change Detection Strategy и многое другое приводит к тому, что некоторые вообще отключают NgZone.

Резюмируя сказанное: несмотря на то что, мой смартфон может просчитать траекторию полета Теслы на Марс, с отображением «простого текста» у него могут быть проблемы.

Теперь перейдем к остальным аргументам.

Оптимизированный код сложнее поддерживать

В качестве обоснования этого аргумента часто приводят нечто вроде вот такого примера:

Нормальный код:

const names = users   .map((user) => user.name)   .filter((name) => name[0] === "a")   .join(" ");

Оптимизированный:

let names = ""; for (let i = 0; i < users.length; i++) {   const userName = users[i].name;   if (userName[0] === "a") {     names += `${userName} `;   } } const result = names.trimEnd();

— Мол, что тебе легче читать и поддерживать?

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

const TermsAndConditions = () => (   <ul>     {["Don't be evil"].map((term, i) => (       <li key={i}>{term}</li>     ))}   </ul> );

А это его совсем чуть-чуть "оптимизированная" версия:

import { rules } from "./settings"; const TermsAndConditions = () => (   <ul>     {rules.map((term, i) => (       <li key={term}>{term}</li>     ))}   </ul> );

Скажите, разве это плохо (~С)? Я бы так не сказал. Зато теперь у нас статический контент лежит в настройках, а бонусом мы не создаем новый массив на каждый вызов функции (а это время на аллокацию и время на уборку мусора). Конечно, можно и лучше "оптмизировать", но даже это лучше чем было. Спички, скажете вы? Спички, да. Но что насчет вот такой популярной ошибки?

Было:

const user = await fetch(userId); const car = await fetch(carId);

Стало:

const userRequest = fetch(userId); const carRequest = fetch(carId); const [user, car] = await Promise.all([userRequest, carRequest]);

Код не стал хуже. Просто теперь, где-то пользователь будет ждать немного меньше, а нам это почти ничего не стоило (кроме полифила для IE). И таких мест может быть много. Чего стоит один code-splitting. Почти никакой магии и куска бандла как небывало. Его больше не надо грузить, парсить, и вы ничего не потеряли — все просто стало немного быстрее. Или пресжать бандлы, что бы ваш сервер этим не занимался на лету. Тоже спички, но тут даже код менять не надо.

К чему я веду — код, который не написан чтобы быть медленным, вполне может работать быстро. Звучит как призыв Капитана Очевидность, но часть проблем с производительностью я исправлял именно так — не ускоряя код, а просто устраняя медленный. Возможно, с этим подходом вы и не попадете в топ 1 самых быстрых сайтов или приложений, но, как известно, 20% усилий приводят к 80% результату, а именно это нам и надо.

Мы не можем тратить на это время, нам уже в продакшн надо

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

Во-первых, многие "оптимизации" — это вовсе не оптимизации. Это просто корректно организованный код, который не тормозит. Да, есть сложные/не очевидные моменты, особенно на стыке приложение/инфраструктура, но, если мы будем грамотно использовать ресурсы которые у нас есть, все уже будет гораздо лучше. В конце концов JavaScript это основной инструмент в веб разработке и понимание того, что const really = () => ({}) создает в памяти новый объект на каждый вызов должно быть очевидно даже коту фронтенд программиста.

А во-вторых, (внимание, холивар) объяснять заказчику или ПМ-у что производительный веб нужен в первую очередь проекту это именно наша задача как специалиста. Я понимаю что вы можете со мной не согласиться, но заказчик то вообще не знает, что-такое эти ваши FCP, LCP, TTI, не знает, что можно уменьшить latency на 0.3 секунды и заработать на этом 8_000_000 фунтов стерлингов в год. У него в голове может просто не быть понимания того, что быстрый веб — это точно такая же фича как, например, список рекомендуемых товаров. Почему? Потому что они оба напрямую влияют на продажи, а значит и на доход. И вот этот аргумент заказчик понимает прекрасно.

Так что же делать

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

Ну а о том, как измерять есть не одна статья. Например, можно поставить в пайплайн lighthouse и замерять производительность прямо во время сборки/тестов. Можно на крон повесить ежедневные тесты прода с тем же lighthouse или perfrunner. Кстати, оба инструмента позволяют вам задать и параметры сети, и замедление процессора, чтобы понимать, как покажет себя ваш вебсайт в более сложных условиях. Можно подключить PageSpeed Insights. Можно даже написать свои тесты производительности на голом puppeteer, и мерять вообще все что хотите и как хотите, это тоже не так сложно. Главное, если ваш основной рынок это, например Северная Америка, то не пытайтесь тестировать ее из Киева, может неловко получиться.

Послесловие — преждевременная оптимизация — корень всех зол

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

Надеюсь, было полезно, всем доброй ночи.

ссылка на оригинал статьи https://habr.com/ru/post/564950/

Как RPA помогает Mary Kay экономить время и деньги

Руководитель центра компетенций по автоматизации бизнес-процессов Николай Бычков.

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

С платформой UiPath компания начала работать в 2019 году. Сегодня она использует решение UiPath Studio, unattended роботов и оркестратор.

Роботизация и новые возможности для сотрудников

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

Мы изучили разных вендоров RPA-сервисов и нам больше всего понравилось предложение компании UiPath. Использовали ее решения для запуска proof of concept на процессе, который существовал уже 8 лет, и перенес несколько неудачных попыток автоматизации — это сверка счетов с транспортными компаниями.

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

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

До внедрения RPA сверкой счетов занимался выделенный человек. Робот стал экономить до 5% бюджета всех доставок. В рамках огромного совокупного бюджета на доставку это очень значительная цифра.

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

Она предложила идею использовать сверочных роботов при изменении тарифов для просчета новой тарифной сетки: определять с помощью данных компании какие опции наиболее выгодны для сотрудничества с транспортниками. Mary Kay теперь корректирует тарифную сетку доставок на основе переговоров с транспортными подрядчиками. Один из впечатляющих результатов — мы смогли выиграть на переподписании контрактов на доставку — 17% от общего бюджета доставки по России.

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

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

Роботы и автоматизация высоконагруженных процессов

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

Вот его схема:

  • Сначала человек заносит данные в систему — Excel с MDS-надстройкой, синхронизирующей данные с MSSQL базой.

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

  • Далее робот вводит данные в централизованную систему управления жизненным циклом продукта и создает отложенные транзакции на последующую проверку статуса заявки.

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

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

Весь процесс — это каскад из 3 очередей, который перетекает из очереди в очередь и на выходе мы получаем гарантированно чистые и проверенные данные во всех системах.

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

Здесь мы сразу столкнулись с проблемой масштабирования, так как задача стояла роботизировать этот процесс для всех рынков Европы, где он работает, а это — целых 10 стран. Процесс в каких-то деталях отличался от страны к стране и пришлось закладывать достаточно степеней свободы, чтобы сделать его гибким, конфигурируемым и поддерживаемым. В итоге получилось создать универсального робота, у которого внутри 10 конфигураций и 10 мэппингов под каждую страну. На разработку этого робота мы потратили 4 месяца, зато сейчас можем новый рынок запустить без специальной разработки робота для него: надо лишь настроить мэппинг, конфигурацию, завести доступы и прописать их в оркестраторе. Таким образом, не требуется ничего программировать, задачу решает доводка low-code до zero-code подручными средствами.

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

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

Схема динамического масштабирования нагрузки с помощью робота-менеджера
Схема динамического масштабирования нагрузки с помощью робота-менеджера

Как снять барьеры роботизации

Основные сложности при внедрении роботизации – неунифицированные процессы, недоверие сотрудников, доступы в IT-системы и информационная безопасность.

Сложность #1 Доступы и информационная безопасность

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

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

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

Сложность #2 Старые паттерны поведения

Мы специализируемся на unattended автоматизации, наши роботы взаимодействуют с людьми, но коммуникация пока происходит через почту. У нас корпоративная система коммуникаций — Microsoft Teams и Outlook, в которой все привыкли работать, и пользователи настороженно относятся к появлению дополнительных. Мы планируем, что в ближайшем будущем взаимодействие сотрудников и роботов из mail-клиента будет переходить в более удобный формат, например какую-то часть коммуникации возьмут на себя чат-боты, а какую-то — будем пробовать реализовать через Action Center.

Сложность #3 Не унифицированные процессы

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

Статистика эффективности

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

Сильной стороной технологии RPA является быстрое создание решения под конкретную задачу. Тут можно привести отличный пример по соотношению затрат на разработку и эффекта от нее. В Германии у компании была разовая задача по формированию документов из системы, которые нельзя было создать массово без доработок самой системы. Необходимо было сформировать 14000 инвойсов в pdf и разложить в определённые папки с определенной логикой наименования файлов. Доработка системы под эту задачу была невозможна, а для выполнения ее человеком потребовалось бы 4,5 месяца рабочего времени. Поэтому для решения этой задачи решили использовать робота. Мы создали его за 1 день. За несколько ночей и одни выходные робот сформировал и загрузил все документы. 

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

Планы на будущее

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

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

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

ссылка на оригинал статьи https://habr.com/ru/company/uipath/blog/565532/