Унити Дасхбоард - научене лекције скалирањем наших граница, развојне културе и процеса

У Унити-у смо недавно кренули да побољшамо наше контролне табле - подухват који је драматично променио не само наш предњи технолошки стек, већ и начине на који радимо и сарађујемо.

Развили смо најбоље праксе и алате који ће нам помоћи да прилагодимо нашу предњу архитектуру, изградимо производе са одличним УКС и перформансама и да испоручимо нове функције пре.

Овај чланак окупља ове праксе и има за циљ да пружи што више образложења иза сваке одлуке. Али прво, неки контекст.

Наслеђе

Гледајући број инжењера, Унити је више него учетворостручио број запослених у последње 4 године. Како је компанија расла и органски и кроз аквизиције, расла је и њена понуда производа. Иако су производи који су првобитно развијени у Унитиу углавном били једнообразни у погледу технологије и језика дизајна, новонабављени природно нису.

Као резултат тога, имали смо више визуелно различитих контролних плоча које су радиле и понашале се другачије и које нису имале заједничке навигационе елементе. То је резултирало лошим корисничким искуством и фрустрираним корисницима. У врло дословном смислу, стање наших производа коштало нас је прихода.

Након анализе портфеља наших производа, извукли смо три различита одељка која ће се поделити на Унити Дасхбоард: Развити, управљати и набављати, сваки удовољава различитим пословним потребама и намењен је различитим групама купаца, што садржи скупове карактеристика који су углавном неовисни једни од других .

Ова нова структура и увођење уобичајених навигационих елемената имали су за циљ да реше прво главно питање са којим су се суочили наши корисници - где пронаћи информације и опције конфигурације које траже, а иако је све то изгледало добро на папиру, путовање како стићи тамо били су далеко од очигледних.

Разматрања

Многи од наших програмера били су веома узбуђени због могућности преласка на Реацт и његову модернију технологију. Будући да су ова решења тестирана у великим апликацијама и да су њихове најбоље праксе и конвенције углавном испеглане, ствари су изгледале врло обећавајуће.

Ипак, оно што су наши програмери најбоље знали и у чему је написана већина наших активно развијених апликација био је АнгуларЈС. Одлука да се све покрене у једном потезу била би катастрофа која чека да се догоди. Уместо тога, кренули смо да прво тестирамо наше претпоставке у много мањем обиму.

Можда најнераздвојена група производа коју смо имали биле су контролне табле за монетизацију . Ови пројекти, који би на крају завршили под кишобраном контролне табле Операте, били су увелико различити на готово сваки могући начин: коришћене технологије, приступ УИ / УКС, развојне праксе, конвенције кодирања - како ви кажете.

Ево како је отприлике изгледала ситуација:

Након неке мождане памети идентификовали смо главна подручја на којима ћемо морати порадити како бисмо повезали све производе:

1. Један производ

Требале су нам ове контролне табле (подељене на више апликација, домена и технолошке стекове) да бисмо:

  • Осећате се као један производ (ниједна цела страница не преусмерава док корисник пролази кроз странице свих различитих апликација)
  • Имајте доследан изглед и осећај
  • Укључите уобичајене навигационе елементе увек су видљиви и изгледају исто, без обзира који део контролне табле корисник посећује

2. Наслеђена подршка

Иако смо имали чисти приступ када је реч о технолошком избору нашег новог фронтенд решења, морали смо да се прилагодимо наследним пројектима који су требали бити интегрисани у нови систем. Решење, које није подразумевало велике напоре за рефакторирање и које не би зауставило развој карактеристика нити вукло месецима без краја.

3. Вежбе и алати

Док су скоро сви тимови користили АнгуларЈС, различити алати су коришћени за решавање истог скупа изазова. Различите тест верзије и библиотеке тврдњи, решења за управљање стањем или недостатак истих, јКуери у односу на бираче изворних прегледача, САСС вс ЛЕСС, библиотеке графикона итд.

4. Продуктивност програмера

Будући да је сваки тим имао своје решење за развој, тестирање и изградњу своје апликације, развојно окружење је често било прожето грешкама, ручним корацима и неефикасношћу.

Поред тога, многи наши тимови раде на локацијама одвојеним разликама од 10 сати (Хелсинки, Финска и Сан Франциско), што ефикасно доношење одлука о било ком дељеном комаду представља прави изазов.

Нови

Наше главне области фокусираности биле су:

  1. Охрабрите и сачувајте агилне начине рада у нашим тимовима и омогућите тимовима да буду у великој мери независни једни од других
  2. Искористите и развијте заједничке алате и конвенције што је више могуће како бисте их документовали и учинили лако доступним и употребљивим

Веровали смо да ће постизање ових циљева значајно побољшати наше време за тржиште и продуктивност програмера. Да би се то догодило, тражили смо решење које би:

  • Изградите карактеристике производа са бољим корисничким искуством
  • Побољшајте квалитет кода
  • Омогућите бољу сарадњу без блокирања било чијег напретка у раду у том процесу.

Такође смо желели да подстакнемо и олакшамо прелазак на савремени технолошки стек како би наши програмери били задовољнији својим радом и да би се временом одмакнули од наших застарелих оквира и алата.

Резултат нашег рада који се непрестано развија је СПА базиран на Реацту, уграђен у монорепозиторијум, где се све странице и веће функције уграђују у углавном независне снопове кода учитане на захтев и које истовремено може да развија и примењује више тимова .

Као средство за тестирање заштићених окружења свих застарелих апликација, али и даље њихово приказивање у контексту исте нове апликације, учитавамо их у унутарњи оквир из којег могу да комуницирају са главним СПА-ом помоћу сабирнице порука имплементиране помоћу postMessage()АПИ-ја.

Монорепозиторијум

Ево структуре директоријума са којом смо започели:

/src /components /scenes /foo /components package.json foo.js /bar /components package.json bar.js package.json index.js

У package.jsonосновном директоријуму налази се скуп devDependencies одговорних за развој, тестирање и изградњу окружења целе апликације, али такође садржи dependenciesи језгро апликације (о томе мало касније).

Сви већи делови корисничког интерфејса називају се сценама . Свака сцена садржи package.jsonгде dependenciesсу дефинисане компоненте те сцене. Ово омогућава две ствари:

  1. Имплементација ажурира само датотеке које су се промениле

    Корак градње компајлира засебне снопове добављача и апликација за сваку сцену, именујући сваку помоћу хеша који ће се променити само када се промени садржај датотеке. То значи да наши корисници преузимају само датотеке које су се промениле од њихове последње посете, и ништа више.

  2. Сцене се учитавају само по потреби

    Све сцене учитавамо асинхроно и на захтев, што драстично побољшава време учитавања целе апликације. Овде „на захтев“ обично подразумева посету одређеној рути или извршавање радње корисничког интерфејса која врши динамички увоз модула.

Ево како такво подешавање изгледа у пракси (поједностављено ради читљивости):

// In src/routes.jsconst FooLoader = AsyncLoadComponent( () => import(‘src/scenes/foo/foo’), GenericPagePreloader,);
// In src/scenes/foo/foo.js 

То AsyncLoadComponentје танки омотач около React.lazy(), који додатно прихвата компоненту предоптерећивача, ону исту која је прошла кроз резервни систем React.Suspense(), и кашњење након којег би се предопремач требао приказати ако сцена није завршила са учитавањем.

Ово је корисно када се осигурава да наши корисници виде исти претходни учитавач без икаквих прекида или блица садржаја од тренутка када се тражи сцена до тренутка када су преузете све њене датотеке, завршени сви критични АПИ захтеви и компонента је завршио са приказивањем.

Слојеви компонената

Како свака апликација расте, њена структура директорија и апстракције еволуирају заједно са њом. Након отприлике пола године изградње и премештања функција у нову базу кодова, поседовање једног директоријума компонената показало се недовољним.

Структура именика нам је требала да нас обавести о:

  • Да ли су компоненте развијене тако да су генеричке или су намењене само за одређени случај употребе?
  • Да ли су довољно генерички за употребу у свим апликацијама или би их требало користити само у одређеном контексту?
  • Ко је одговоран за код и најбоље га познаје?

На основу тога дефинисали смо следеће нивое компонената :

1. Специфично за апликацију (срц / апп)

Компоненте за једнократну употребу које удовољавају одређеним случајевима употребе у овој апликацији и којима није предвиђено да се поново користе или издвоје у библиотеку компонената (руте, подножје, заглавље странице итд.).

2. Генерички (срц / компоненте)

Генеричке вишенаменске компоненте које ће се користити у целој апликацији и на њеним сценама. Када дођемо до стабилног АПИ-ја за ове компоненте, оне би могле бити премештене у заједничку библиотеку компонената (више о томе у наставку)

3. Компоненте једне сцене (срц / сцене / ми-сцене / цомпонентс)

Компоненте развијене са посебним случајем употребе; није намењен за употребу у било којим другим сценама. У случајевима када компоненту из једне сцене треба користити у другој, користили бисмо:

4. Компоненте за више сцена (срц / сцене / цомпонентс / ми-феатуре)

Компоненте које се користе у више сцена, али нису намењене да буду довољно генеричке за употребу било где другде. Да илуструјемо зашто једноставно премештање на њих src/componentsније довољно добро:

Замислите да сте до сада имали једну сцену која је садржала компоненте коришћене за изградњу неких прилично специфичних графикона података. Ваш тим сада прави другу сцену која ће користити различите податке за графиконе, али визуелно ће та два изгледати приближно исто.

Увоз компонената из једне сцене у другу прекинуо би енкапсулацију сцене и значио би да више не можемо бити сигурни да ли промене направљене на компонентама једне сцене утичу само на ту једну сцену.

У ту сврху, било која компонента или група компонената, која се грубо назива особина, биће постављена src/scenes/componentsодакле је може увести и користити било који други тим, међутим:

Кад год би тим желео да почне да користи компоненте сцене које је други тим развио, најбоља пракса би била да се прво обратите том тиму да бисте утврдили да ли случај употребе за који намеравате ове компоненте може сигурно да буде подржан у будућности. Давање информација тиму који је првобитно развио код спречиће испоруку покварених карактеристика у будућности када се код који сте користили неизбежно промени на начине на које нисте очекивали (јер, наравно, како бисте могли!), И што можда неће увек бити обухваћено јединственим тестовима.

5. Заједничка библиотека

Компоненте које смо тестирали у производњи и желимо да их издвојимо у нашу заједничку библиотеку компонената, које користе други тимови контролних табли у Унити-у.

Ода заједничким зависностима

Иако би било врло згодно да можемо да изградимо и применимо сваки део наше апликације у потпуно изолованом окружењу, одређене зависности - и спољне библиотеке и интерни код апликације - једноставно ће се користити широм базе података. Ствари попут самог Реацт-а, Редук-а и свих везаних за редук логику, уобичајене навигационе компоненте итд.

Увођење промена

Тренутно потпуно инкапсулирање сцена није практично и у многим случајевима једноставно немогуће. Било би потребно или испоручивање многих зависности више пута и у процесу успоравање учитавања страница, или израда апстракција чији је циљ да одређене библиотеке раде онако како нису предвиђене.

Како се веб развој и његов екосистем еволуирају, чини се да библиотеке постају све више самосталне и затворене, што се надамо да ће у будућности значити мало или нимало заједничких зависности и истинска изолација између свих модула.

Можда је највећи недостатак стварања великих апликација извршавање промена кода и ажурирање зависности без прекида у процесу

Коришћење монорепозиторија омогућава (мада није обавезно) увођење промена и ажурирања кода на поступнији и сигурнији начин - ако промена изазове проблеме, ти проблеми ће утицати само на мали део апликације, а не и на цео систем.

И док би се некима могућност извођења ажурирања на више неповезаних подручја базе кодова у исто време показала као предност, стварност да више тимова ради на истој бази кодова и не познају све функције осталих тимова значи да потребна је велика пажња приликом израде скеле за апликације и предузимања мера да се ризик од лома сведе на минимум.

Како избећи ломљење ствари

Можда је најосновнија стратегија која нам помаже у томе, осим изолације сцене, велико покривање јединичним тестом .

  1. Тестирање

Јединствени тестови наравно нису све - многи зрели производи, чак и у умереним размерама, ипак улажу у пакете интеграције и е2е тестове који чине бољи посао у верификовању да ли апликација функционише онако како се очекује. Међутим, како расте број карактеристика, тако расте и трошак одржавања и време потребно за њихово покретање - трошак који не може увек бити оправдан за мање кључне, али ипак важне карактеристике.

Неке лекције које смо научили из различитих стратегија тестирања:

  • Покушајте да тестирате што више кода, посебно: условна логика, трансформација података и позиви функција
  • Уложите у интеграционе тестове и искористите их у потпуности, пре него што се одлучите да напишете било који е2е тест. Почетна цена интеграционих тестова је много већа, али бледи у поређењу са ценом одржавања пакета е2е
  • Покушајте да не реагујете претјерано тако што ћете почети да пишете е2е тестове за ствари које нису захваћене јединственим или интеграционим тестовима. Понекад су криви процеси или алати
  • Нека тестови објасне понашање корисничког интерфејса, а не детаље имплементације
  • Аутоматизовани тестови не могу у потпуности заменити ручно тестирање

2. Минимизирајте површину дељеног кода

Поред тестирања, код који се поново користи у целој апликацији сведен је на разумни минимум. Једна од најкориснијих стратегија до сада била је премештање најчешће коришћених компоненти и кода у заједничку библиотеку компонената, одакле се користе као зависности у сценама којима су потребне. То нам омогућава да већину промена уводимо поступно, по тиму или на страници.

3. Одговорност

И на крају, али не најмање важно, огроман фактор у томе што више тимова може сарађивати у истој бази кодова потиче од охрабривања и налажења програмера да преузму личну одговорност и одговорност за производ , уместо да преузму одговорност за правилно тестирање да све функционише на КА, тестере или аутоматизација.

То се преноси и на прегледе кода. Обавезно пажљиво прегледати сваку промену теже је него што би могло изгледати на површини. Како тим блиско сарађује, међу члановима се развија здрав степен поверења. Ово поверење, међутим, понекад може довести до тога да људи буду мање вредни промена које су направили искуснији или на било који други начин поуздани програмери.

Да бисмо подстакли марљивост, истичемо да су аутор ПР-а и рецензент подједнако одговорни за обезбеђивање да све функционише .

Библиотека компонената

Да бисмо постигли исти изглед и осећај на свим страницама наших контролних плоча, развили смо библиотеку компонената. Оно што стоји у нашем приступу је да се нове компоненте готово никада не развијају у тој библиотеци.

Свака компонента, након што се развије унутар базе кодова надзорне табле, прво се користи у гомили функција унутар те базе података. Обично након неколико недеља почињемо да се осећамо сигурније да би компонента могла да се пребаци с обзиром на то да:

  • АПИ је довољно флексибилан да подржи предвидљиве случајеве употребе
  • Компонента је тестирана у разним контекстима
  • Учинак, одзив и УКС су узети у обзир

Овај поступак следи Правило три и има за циљ да нам помогне да ослободимо само компоненте које се заиста могу поново употребити и које су коришћене у разним контекстима пре него што су премештене у нашу заједничку библиотеку.

Неки од примера компоненти које бисмо пребацили укључују: подножје, заглавље странице, бочне и горње навигационе елементе, грађевинске блокове распореда, банере, покренуте верзије дугмади, елементе типографије итд.

У раним данима библиотека компонената некада се налазила у истој бази кодова као и сама апликација. Од тада смо га издвојили у засебно спремиште како бисмо развојни процес учинили демократизованијим за друге тимове у Унити-у - што је важно када се тражи његово усвајање.

Модуларни дизајн компонената

Најдуже време је израда компонената за вишекратну употребу значила суочавање са вишеструким изазовима, од којих многи често нису имали добра решења:

  • Како лако увести компоненту заједно са њеним стиловима и само то
  • Како надјачати задане стилове без ратова специфичности селектора
  • У већим компонентама које се састоје од више мањих, како заменити стил мање компоненте

Наша контролна табла, као и библиотека компонената у великој мери зависе од корисничког интерфејса материјала и користе га. Оно што је јединствено убедљиво у стилском решењу Материал УИ-а јесте потенцијал који доноси ЈСС и њихов обједињени језик за обликовање (вреди прочитати), који омогућавају развој корисничких интерфејса енкапсулираних дизајном, као у случају ЦСС модула, и решавање горе поменутог издаје корак по корак.

Ово се значајно разликује од приступа попут БЕМ-а који омогућавају инкапсулацију по договору који је обично мање проширив и мање инкапсулиран.

Ливинг стилегуиде

Библиотека компонената не би била комплетна без начина да се прикажу компоненте које садржи и ако се могу видети компоненте док се мењају током издања.

Имали смо прилично добро искуство са Сторибоок-ом, које је било смешно лако подесити и започети, али након неког времена схватили смо да је потребно робусније решење од краја до краја. Прилично близу онога што Стилегуидист нуди, али више прилагођен нашим потребама.

Постојећи документи о дизајну

Документација која служи као главни извор информација о најновијим спецификацијама дизајна налазила се у насељу Цонфлуенце, где су дизајнери одржавали ажурну спецификацију за сваку компоненту користећи снимке екрана који илуструју дозвољене случајеве употребе, стања и варијације у којима би компонента могла бити наведена. најбоље праксе, као и детаљи попут димензија, коришћених боја итд. Следећи тај приступ суочили смо се са низом изазова:

  • Спецификација дизајна материјала се непрестано развија и због тога смо се често нашли или трошимо време на ажурирање свих снимака екрана и смерница, или смо оставили да наше смернице за дизајн застаревају
  • Откривање шта је тачније: примена или спецификација није увек био лак задатак. Пошто смо објављивали демонстрације Сторибоок-а сваке компоненте и за сваку верзију библиотеке, могли смо да видимо шта и како се променило. Нисмо могли учинити исто за спецификације дизајна.
  • Снимке екрана и видео снимци могу да комуницирају само толико . Да бисмо обезбедили компоненте високог квалитета и које могу да користе више тимова, потребно је прегледати да ли свака компонента ради у свим резолуцијама, не садржи грешке и има добар УКС - ово је било тешко а да дизајнер не седи буквално поред вас да види демонстрација имплементације која се приказује на екрану

Апликација за документацију компонената

Наша апликација за документацију има за циљ да обезбеди средства за ефикасну сарадњу између дизајнера и инжењера како би обе стране учиниле једноставнијим и мање дуготрајним за документовање, преглед и развој компонената. Да бисмо били прецизнији, требало је да:

  • Имајте једну референтну тачку која приказује компоненте , какода ли би требало да изгледају, понашају се и користе - предвиђено за свако издање - замењујући детаљне описе живим демонстрацијама
  • Олакшајте дизајнерима и програмерима да сарађују на компонентама и њиховим документима и то пре него што компоненте изађу - без потребе за дељењем видео записа, снимака екрана или физичког боравка на истој локацији
  • Одвојите дизајн од онога што планирамо да урадимо од онога што је урађено

Слично као и раније, свако издање библиотеке компонената доводи до објављивања нове верзије живог стилског водича. Међутим, овог пута постоји неколико разлика:

  1. Дизајнери директно доприносе документацији компонената уређивањем датотека документације кроз Гитхуб УИ, извршавајући измене у најновијем издању.
  2. Демонстрације компонената као ВИСИВИГ - исти код који видите као пример примене компоненте користи се за приказивање демонстрације, укључујући било који увоз средње датотеке, декларације променљивих итд. Као додатни бонус, компоненте умотане withStyles()се правилно приказују (издање присутно тренутно у Сторибоок-у).
  3. Промене у документима и коду су готово тренутно видљиве без локалног проверавања гране и покретања апликације за документацију - апликација се поново гради и објављује за свако урезивање.

Развојно искуство

Један од главних циљева прегледа кода је осигуравање да се свака промена пажљиво прегледа, размотри и тестира пре спајања и примене.

Да бисмо овај задатак учинили што је могуће лакшим, развили смо Превиев Сервер способан да креира нову верзију наше апликације сваки пут када се ПР створи или ажурира.

Наши дизајнери, менаџери производа и инжењери могу тестирати сваку промену пре него што је споје, како у почетном тако иу производном окружењу и у року од неколико минута од промене.

Завршне речи

Прошло је скоро годину дана откако смо предузели консолидацију контролних табли. Провели смо то време учећи како да развијемо велики, али здрав софтверски пројекат, како да постанемо бољи у сарадњи и комуникацији и како да подигнемо траку квалитета за себе.

Скалирали смо фронтенд пројекат не само у смислу линија кода, већ и у смислу броја инжењера који раде у оквиру његове базе кода - броја који се од почетка учетворостручио.

Направили смо промену од 180 степени у суочавању са временским разликама између наших тимова, прелазећи са модела где су наши тимови радили у потпуној изолацији на модел где су блиска сарадња и комуникација свакодневна појава.

Иако је пред нама још дуг пут како бисмо осигурали да свој приступ можемо прилагодити већем броју тимова и већим изазовима, приметили смо већ низ побољшања:

  • Мапа пута и видљивост рада

    Због постојања једног места на коме се одвија сав посао, напредак се прати и скупљају се сви проблеми

  • Брзина развоја и време до изласка на тржиште

    Нове функције могу да се створе великим делом од већ постојећих и добро тестираних компонената - до којих се лако може доћи помоћу наше апликације за документацију

  • Квалитет кода и покривеност тестом

    Када се граде нове ствари, решење сличног проблема обично већ постоји и надохват руке, заједно са примерима како га тестирати

  • Свеукупни квалитет и УКС

    Тестирање карактеристика и осигуравање њиховог квалитета сада је лакше него икад, јер дизајнери, менаџери производа и друге заинтересоване стране могу тестирати сваку промену на својој машини, са својим рачунима и скуповима података

Наравно, током пута смо се сусретали са бројним изазовима које морамо решити или који ће бити решени у будућности:

  • Изградња и перформансе ЦИ

    Како број зависности, снопова пакета и тестова расте, тако расте и време потребно за примену. У будућности ћемо морати да развијемо алате који ће нам помоћи да само изградимо, тестирамо и применимо делове који су се променили.

  • Култура развоја

    Да бисмо изградили здрав софтвер, морамо континуирано радити на здравим начинима комуникације и размене идеја, а комуникација заснована на тексту чини овај задатак тежим. Радимо на решавању овог проблема кроз низ редовних тренинга за вођство и прихватање начина отворенијег рада, као и на организовању неколико сесија окупљања годишње како би се тимови упознали лицем у лице.

  • Изолација и ажурирања прекида

    Како број функција и страница расте, требат ће нам робуснији начин изолације наших апликативних модула како бисмо спријечили ширење штете када ствари пођу по злу. То се може постићи верзионисањем целокупног дељеног кода (редук логика, срц / компоненте) или у екстремним случајевима производњом самосталних верзија одређених карактеристика.

Држава тада, сада и у будућности

Миграција је подразумевала удаљавање од АнгуларЈС-а ка Реацт-у. Ево како се ситуација променила током протекле године:

То је готово! Хвала вам за читање! Можете ме пронаћи на ЛинкедИну овде.

Ако вам рад на сличним изазовима звучи занимљиво, увек тражимо талентоване инжењере који ће се придружити нашим тимовима широм света.