Честно реално време на React и Redux като основа на автоматичен търг

честно

За тези, които не знаят, CarPrice създаде аукционна услуга за физически лица, за да продават своите употребявани автомобили на търговци на автомобили. Собственикът на колата идва в един от многобройните ни клонове, наш служител проверява колата му, съставя карта, която се предлага на търг на търговец. За тази кола търговците търгуват половин час, като постепенно повишават цената. В края на търга собственикът решава дали е доволен от предложената сума и или си тръгва с парите, или спокойно отказва да продаде.

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

Какво се промени в новата версия?

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

Когато щракнете върху някой от аукционите, се отваря карта за автомобил:

react

време

честно

време

време

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

Разкажете ми повече за техническата страна на проекта.

Това е уеб приложение, написано на React/Redux и следващо парадигмата на тази технология: състои се от отделни функционални компоненти. Дори потребителският интерфейс е сглобен отиндивидуални компонентни карти. Всъщност всяка карта е отделно приложение, което работи самостоятелно. Може да бъде безболезнено отстранен и поставен на друго място в общото приложение. Тоест нещо като архитектура на микросервизи, само че от страна на клиента и на ниво потребителски интерфейс.

Всичко това работи абсолютно независимо от сървърната страна. Тоест приложението за търг се състои от статични файлове, които се събират от WebPack и след това се разпространяват от Nginx.

Какво е взаимодействието между предния и задния край на приложението? Кои модули комуникират с кои системи, какви данни се предават?

Ние използваме интегриран подход, в приложението имаме както HTTP REST API комуникация, така и дуплексна комуникация в реално време чрез WebSocket (pub / sub шаблон). Това се дължи както на исторически фактори (приложението работи по този начин от самото начало), така и на функционални изисквания (имаме места, където не е необходимо предаване на реално време и събития от сървъра и обратното). За нас беше много важно да приложим точно честно в реално време, тъй като това е търг и имаме интензивно наддаване, особено в последните минути. Изоставихме схемите, когато актуализациите се предават от сървъра от време на време (например на секунда, както често се прави в месинджърите), нашият клиент получава актуализации от сървъра възможно най-бързо. Беше много важно да се запази удобството на интерфейса: когато започне активна търговия за автомобил, събитията летят много бързо и потребителят вече няма време да въвежда нов курс ръчно. Полетата и бутоните (имаме възможност да търгуваме от различни места в приложението и видът на залога е различен) сами актуализират информацията, когато се получават събития от сървъра, или например могат да станат неактивни, ако дилърът няма права да продължи да търгува по-нататък. Това е от съществено значениеулеснява работата с интерфейса, но не беше толкова лесен за изпълнение, тъй като в такива сценарии свързването на компонентите се увеличава значително.

Разкажете ми повече за инструментите, използвани в разработката.

Умишлено изоставихме „велосипедите“ в полза на най-популярните решения за уеб приложения, които в момента са на пазара. Като рамка, идеология и основа се използва React / Redux. Проектът е изграден с помощта на Webpack, използваме Yarn като мениджър на зависимости, NodeJS и Express за dev/mock сървъра. В производството докеризираният Nginx разпространява статика.

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

Използвахте ли компонентите на предишното приложение или новото беше създадено от нулата?

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

Били ли са „отсеяни“ някакви технологии или инструменти, които са счетени за неподходящи за използване в приложението?

Нашата архитектура позволява доста гъвкава работа с различни инструменти, без да се нарушават основните принципи на приложението. Например ниеекспериментира с CSS модули и именуване на BEM CSS клас, използвайки LESS. В резултат на това първият беше избран като по-удобен вариант. Същото се случи с внедряването на горещо презареждане на сървъра за разработка, технологията все още не е напълно установена и ние опитахме няколко опции за внедряване. Коя беше най-трудната част от прилагането на това приложение?

Приложението въвежда доста поведенческа логика, често нетривиална. Нашата задача беше компетентно да го разложим на модули, да осигурим всички потребителски взаимодействия и да обмислим всички сценарии на използване. Когато всички компоненти са тясно взаимосвързани и взаимодействат много активно помежду си, е важно да се предвиди до какво води всяко действие на потребителя (или други потребители), какво въздействие оказва върху приложението. От страна на клиента, Redux архитектурата ни помогна много. Нашият търг е екосистема в реално време и беше важно събитията, които пристигат от други потребители, да не са в конфликт с тези, генерирани от самия потребител.

Доколкото разбирам, основното предимство на новото приложение е неговият модулен интерфейс. Бихте ли ни разказали повече за развитието му?

Днес има два популярни подхода за разделяне на приложение на модули:

Каква е разликата между контейнер и компонент, защо пренебрегнахте този модел?

Контейнерът е компонент, който работи директно със хранилището, прави заявки към сървъра и т.н. Един прост компонент може да приема данни само от родителя и да рендира на конкретно място. Често те са разделени в различни папки на ниво приложение. Този подход изглеждаше излишен за нас, мисля, че един плосък списък от компоненти е това, към което се стреми цялото развитие на предния край през последните пет години.Самият разработчик разбира, че компонентът става по-сложен (става контейнер) и това може да се види при отваряне на входната точка на компонента, тъй като за това трябва да внедрите няколко метода Redux.

Чух, че Redux използва практики за функционално програмиране за изграждане на приложението, така ли е? Но какво да кажем за ООП?

Да, Redux е написан под влияние на функционални езици, подходи и идеи. Например, всички редуктори са чисти функции, а store е неизменен обект. Всички набори от действия и редуктори са само функции, които импортираме във входните точки на компонента, практически няма класове, практически няма инстанции (само в React и самостоятелно написани модули). OOP подходите се справят добре с постоянно нарастваща логика, но в този случай успява да запази приложението компактно, въпреки факта, че носи много функционалност.

Повторното използване и изолиране на компоненти е едно от основните предимства на този подход.

Какви инструменти се използват в работата?

Redux DevTools и React Developer Tools се добавят към Chrome в допълнение към стандартните инструменти за разработчици. Първият е много мощен инструмент за отстраняване на грешки, който ви позволява да преглеждате магазина, действията за връщане назад и съответно какво е направено в приложението във времето (нарича се машина на времето). Вторият ви позволява да работите с XML-подобно дърво на React компоненти, подобно на това, което пишем в JSX, а не с обичайния DOM. Това ви позволява да работите с по-големи части от приложението, отколкото с прости HTML елементи. Ние също така използваме ESLint със стандартна, леко модифицирана конфигурация на AirBnb, за да приведем кода на различни разработчици до приблизително същия вид.

Какъв е пътят на приложението от разработването на някаква нова функционалност до пускането му за потребителите?

Разработчикът внедрява приложението локално, стартира сървъра Webpack Dev и сървъра с фалшиви версии на различни портове (или настройва конфигурации за производствена или етапна среда) и започва да работи. След като премине прегледа на кода, тестерът в CI изгражда Docker контейнер с необходимия клон и го проверява. След това се стартира Drone (ще говорим за него скоро в отделна публикация), CI изгражда контейнер за производство и го стартира на производствен сървър. В бъдеще планираме да изградим един контейнер както за тестване, така и за внедряване.

Как се промени подходът към front-end и back-end разработката през последните 2-3 години? Какви идеи/концепции, които преди са били считани за нормална практика, днес смятате за остарели и какво е заело тяхното място? Какви техники сте възприели и вероятно сте използвали, когато създавате това приложение?

Бих обхванал по-дълъг период. През последните 4-6 години изискванията към интерфейсите в мрежата сериозно се увеличиха, в повечето нови сложни продукти основната версия е направена за браузъра, някои от старите също мигрираха. Приложенията станаха много по-сложни и монолитната архитектура, която преобладаваше, отстъпва място на микроуслугите в задната част и компонентите в предната част. Backend и frontend в типичен голям проект първо се отделиха един от друг, намалявайки сложността и ентропията, а след това започнаха да споделят области на отговорност вътре в себе си. Ако по-рано, дори когато отидете на популярен посещаван сайт, човек можеше да разбере, че вътре работят прост механизъм за вградени HTML шаблони, база данни, уеб сървър и малко логика, свързваща всичко това, сега „под капака“ най-често е система от множество компоненти, с хитра комуникационна система и купчина различни технологии.

И последният въпрос. Купуването на кола едоста отговорна стъпка дори за хора, които го правят професионално. Как дилърите реагираха на новия интерфейс?

Дори успешният редизайн винаги е, до известна степен, болка за потребителите, които са свикнали с познати модели на поведение, дори ако те могат да бъдат значително опростени и имат грешки. Постепенно въведохме нови страници и свързахме потребители в групи към актуализирания интерфейс. Имаме система за обратна връзка и нашите мениджъри анализираха желанията и отзивите на потребителите. Вярваме, че се справихме успешно с тази трудна задача.