Hogyan építi fel a Google a webes kereteket

Köztudott, hogy a Google egyetlen adattárat használ a kód - mind a 2 milliárd sor - megosztásához, és hogy a törzsalapú fejlesztési paradigmát használja.

Sok, a vállalaton kívüli fejlesztő számára ez meglepő és ellentmondásos, de nagyon jól működik. (A fent hivatkozott cikk jó példákat mutat be, ezért itt nem ismétlem meg őket.)

A Google kódbázisát több mint 25 000 Google szoftverfejlesztő osztja meg a világ országainak tucatnyi irodájából. Egy tipikus munkanapon 16 000 változtatást hajtanak végre a kódalapon. (forrás)

Ez a cikk a nyílt forráskódú webkeret (AngularDart) felépítésének sajátosságairól szól ebben az összefüggésben.

Csak egy verzió

Ha a trunk-alapú fejlesztést egyetlen hatalmas repóban alkalmazza, akkor mindennek csak egy verziója van. Ez valahogy nyilvánvaló. Mégis jó itt rámutatni, mert ez azt jelenti, hogy - a Google-nél - nem lehet a FooBar alkalmazás, amely AngularDart 2.2.1-t használ, és egy másik, a BarFoo alkalmazást, amely a 2.3.0-t használja. Mindkét alkalmazásnak ugyanazon a verzión kell lennie - a legújabbon.

Ezért a Google munkatársai néha azt mondják, hogy a Google összes szoftvere a vérző élen él.

Ha az egész lelked sikoltozik: most ez érthető. A könyvtár törzsétől (a git terminológiában „master”) függően a termelési kód biztosan veszélyesnek hangzik. De előttünk van egy cselekmény.

74 ezer teszt elkövetésenként

Az AngularDart 1601 tesztet határoz meg (itt). De amikor az AngularDart kód módosítását hajtja végre a Google adattárában, akkor a teszteket a Google minden olyan személyének futtat, aki a kerettől függ . Jelenleg ez körülbelül 74 ezer teszt (attól függően, hogy mekkora a változásod - egy heurisztika kihagyja azokat a teszteket, amelyeken a rendszer tudja, hogy nem érinti).

Jó, hogy több teszt van.

Éppen most hajtottam végre egy olyan módosítást, amely csak az idő 5% -ában nyilvánul meg, olyasmit szimulálva, mint egy faj && random.nextDouble() >. Ez nem mutatkozott meg az 1601-es tesztek egyikében sem, amikor egyszer futtattam őket. De egy csomó kliens tesztet megszakított.

A valódi érték azonban itt az, hogy ezek a tényleges alkalmazások tesztjei . Nem csak számtalan, hanem azt is tükrözik, hogy a keretrendszert hogyan használják a fejlesztők (nem csak a keretrendszer szerzői). Ez jelentős: a keretrendszer-tulajdonosok nem mindig becsülik meg helyesen a keretrendszer használatát.

Az is segít, hogy ezek az alkalmazások gyártás alatt állnak, és havonta dollármilliárdok áramlanak rajtuk keresztül. Nagy különbség van a demóalkalmazások között, amelyeket a keretrendszer szerző szabadidejében összerak, és a valódi produkciós alkalmazások között, amelyekbe több tíz vagy száz emberévet fektettek be. Ha a web releváns lesz a jövőben, jobban támogatnunk kell az utóbbi fejlesztését.

Tehát mi történik, ha a keretrendszer megtöri a rá épülő alkalmazások egy részét?

Megtöröd, kijavítod

Amikor az AngularDart szerzői áttörő változást akarnak bevezetni, meg kell javítaniuk a felhasználók számára . Mivel a Google-nél minden egyetlen repóban él, elenyésző kideríteni, hogy kit törnek meg, és azonnal megkezdhetik a javítást.

Az AngularDart minden törésváltozása magában foglalja a változás minden javítását az összes Google-alkalmazásban, amely attól függ. Tehát a törés és a javítás egyszerre kerül a repóba, és természetesen - miután az összes érintett fél átnézte a kódot.

Mondjunk konkrét példát. Amikor valaki az AngularDart csapatából olyan módosítást hajt végre, amely hatással van az AdWords alkalmazás kódjára, az alkalmazás forráskódjához lép, és kijavítja azt. Futtathatják az AdWords meglévő tesztjeit és felvehetnek újakat. Ezután mindezt felveszik a változáslistájukba, és felülvizsgálatot kérnek. Mivel a változáslistájuk az AngularDart repóban és az AdWords repóban egyaránt érinti a kódot, a rendszer automatikusan megköveteli a kód felülvizsgálatának jóváhagyását mindkét csapat részéről. Csak ezután nyújtható be a változás.

Ennek nyilvánvaló hatása van, hogy megakadályozza a keretrendszer fejlesztését vákuumban. Az AngularDart keretrendszer fejlesztői milliónyi kódsorhoz férhetnek hozzá, amelyeket a platformjukkal építenek, és rendszeresen maguk is megérintik ezt a kódot. Nem kell feltételezniük, hogy a keretrendszerüket hogyan használják. (A nyilvánvaló figyelmeztetés az, hogy csak a Google kódját látják, és nem a világ összes Workiva, Wrike és StableKernel kódját, amely szintén AngularDart használ.)

A felhasználói kód frissítése szintén lelassítja a fejlesztést. Nem annyira, mint gondolnád (nézd meg az AngularDart októberi fejlődését), de ez mégis lelassítja a dolgot. Ez jó és rossz is, attól függően, hogy mit akarsz egy keretrendszerből. Erre még visszatérünk.

Egyébként is. Amikor legközelebb valaki a Google-nál azt mondja, hogy valamely könyvtár alfa verziója stabil és gyártás alatt áll, most már tudja, miért.

Nagy léptékű változások

Mi van akkor, ha az AngularDart-nak jelentős megtörést kell végrehajtania (mondjuk 2.x-ről 3.0-ra), és ez a változás 74 ezer tesztet szakít meg? Megy a csapat és kijavítja mindet? Változtatnak-e több ezer forrásfájlban, amelyek nagy részét nem írták meg?

Igen.

A hangtípusú rendszer egyik legjobb tulajdonsága, hogy a szerszámok sokkal hasznosabbak lehetnek. A hangos Dartban az eszközök biztosak lehetnek abban, hogy például egy változó bizonyos típusú. A refaktorozásnál ez azt jelenti, hogy sok változás teljesen automatikus lehet, a fejlesztő megerősítéséhez nincs szükség.

Amikor a Foo osztály egyik módszere átáll a bar()helyett baz(), létrehozhat egy eszközt, amely végigveszi az egyetlen Google adattárat, megtalálja az adott Foo osztály és annak alosztályainak összes példányát , és megváltoztatja bar()a baz(). A Dart hangtípusú rendszerével biztos lehet benne, hogy ez nem tör meg semmit. Hangtípusok nélkül még egy ilyen egyszerű változtatás is bajba sodorhatja.

Egy másik dolog, amely segít a nagy léptékű változtatásokban, a dart_style, a Dart alapértelmezett formázója. A Google összes Dart-kódját ezzel az eszközzel formázza. Mire a kód eljut az ellenőrökhöz, a dart_style segítségével automatikusan formázta, így nincsenek viták arról, hogy az új sort ide vagy oda tegye-e. És ez vonatkozik a nagyméretű refaktorokra is.

Teljesítmény adatok

Ahogy fentebb említettem, az AngularDart profitál az eltartottak tesztjeiből. De nem csak tesztekről van szó. A Google nagyon szigorúan méri alkalmazásai teljesítményét, ezért a legtöbb (az összes?) Produkciós alkalmazás rendelkezik benchmark-csomagokkal.

Tehát amikor az AngularDart csapata bevezet egy olyan változást, amely miatt az AdWords 1% -kal lassabban töltődik be, akkor tudják, mielőtt a változás megtörténik. Amikor a csapat októberben közölte, hogy az AngularDart alkalmazások augusztus óta 40% -kal kisebbek és 10% -kal gyorsabbak voltak, nem néhány szintetikus apró TodoMVC példaalkalmazásról beszéltek. Valós, misszió szempontjából kritikus, gyártási alkalmazásokról beszéltek, több millió felhasználóval és megabájt üzleti logikai kóddal.

Mellékjegyzet: Hermetikus építő eszköz

Kíváncsi lehet: honnan tudta ez a srác, hogy melyik teszteket kell lefuttatni a hatalmas belső adattárban, miután bemutatta a pelyhes hibát az AngularDart-ban? Bizonyára nem ő választotta ki kézzel a 74 ezer tesztet, és ugyanolyan biztosan nem a Google-nál is végzett minden tesztet. A válasz Bazel nevű dologban rejlik.

Ebben a léptékben nem lehet egy sor shell parancsfájl, amellyel dolgokat készíthet. A dolgok pelyhesek és rendkívül lassúak lennének. Amire szüksége van, az egy hermetikus építési eszköz.

A „hermetikus” ebben az összefüggésben nagyon hasonlít a „tiszta” -ra a funkciók összefüggésében. A build lépéseinek nem lehetnek mellékhatásai (például temp fájlok, PATH változások stb.), És meghatározóaknak kell lenniük (ugyanaz a bemenet mindig ugyanahhoz a kimenethez vezet). Ebben az esetben bármikor futtathatja a buildeket és a teszteket bármely gépen, és következetes kimenetet kap. Nem kell make clean. Ezért elküldheti a buildjeit / tesztjeit szerverek felépítésére és párhuzamosítására.

A Google évek óta fejleszt egy ilyen összeépítési eszközt. Tavaly Bazel néven nyitották meg.

Ennek az infrastruktúrának köszönhetően a belső tesztelő eszközök meghatározhatják, hogy az egyes változtatások melyik építkezéseket / teszteket befolyásolják, és adott esetben futtathatják azokat.

Mit jelent ez az egész?

Az AngularDart kifejezett célja, hogy a kategóriájában legjobb legyen a termelékenység, a teljesítmény és a megbízhatóság terén a nagy webes alkalmazások felépítéséhez. Ez a bejegyzés remélhetőleg kitér az utolsó részre - a megbízhatóságra - és miért fontos, hogy a misszió szempontjából kritikus Google-alkalmazások, például az AdWords és az AdSense használják a keretrendszert. Nem csak a csapat dicsekszik a felhasználóival - amint azt a fentiekben kifejtettük, a nagy belső felhasználók birtokában az AngularDart kevésbé valószínű, hogy felszínes változásokat vezet be. Ez megbízhatóbbá teszi a keretet.

Ha olyan keretrendszert keres, amely jelentős átalakításokat végez, és néhány hónaponként bevezeti a főbb funkciókat, az AngularDart biztosan nem az Ön számára. Még akkor is, ha a csapat ilyen módon akarta felépíteni a keretrendszert, szerintem ebből a cikkből egyértelműen kiderül, hogy nem tudtak. Őszintén hiszünk abban, hogy van hely egy kevésbé divatos, de megbízható keret számára.

Véleményem szerint a nyílt forráskódú technológiai verem hosszú távú támogatásának legjobb előrejelzése az, hogy ez az elsődleges fenntartói tevékenység nagy része. Vegyük példaként az Android, a tőr, a MySQL vagy a git alkalmazást. Ezért örülök, hogy a Dartnak végre van egy előnyben részesített webes keretrendszere (AngularDart), egy előnyben részesített komponens könyvtár (AngularDart Components) és egy előnyben részesített mobil keretrendszer (Flutter) - ezeket mind az üzleti szempontból kritikus Google-alkalmazások felépítésére használják.

[Matan Lurey és Kathy Walrath hozzájárultak a cikk elkészítéséhez.]

[Vita a Reddit, HN, Twitter oldalakon.]