miten ikävät ympyräriippuvuusongelmat korjataan kertaheitolla JavaScript-ja Konekirjoituksessa

  1. index.js vaatii AbstractNode.js
  2. moduulikuormaaja alkaa ladata AbstractNode.js ja suorittaa moduulikoodia. Asia, jonka se ensimmäisenä kohtaa, on vaatimus (tuonti) lauseke Leaf
  3. , joten moduulilataaja alkaa ladata Leaf.js tiedostoa. Joka puolestaan alkaa vaatimalla Abstractnode.js.
  4. AbstractNode.js on jo ladattu, ja se palautetaan välittömästi moduulivälimuistista. Koska kyseinen moduuli ei kuitenkaan vielä kulkenut ensimmäistä riviä pidemmälle (Leaf vaatimus), AbstractNode – luokan esitteleviä lausumia ei ole vielä toteutettu!
  5. niinpä Leaf – Luokka pyrkii ulottumaan undefined – arvosta kelvollisen luokan sijaan. Joka heittää runtime poikkeus yllä. Pum!

Fix-yritys 1

niin, käy ilmi, että ympyräriippuvuutemme aiheuttaa ikävän ongelman. Kuitenkin, jos katsomme tarkasti on melko helppo määrittää, mitä lastausjärjestys olisi:

  1. kuormaa AbstractNode Luokka ensin
  2. kuormaa Node ja Leaf Luokka sen jälkeen.

toisin sanoen määritellään ensin AbstractNode luokka ja sen jälkeen vaaditaan Leafja Node. Sen pitäisi toimia, sillä Leaf ja Node ei tarvitse olla vielä tiedossa AbstractNode luokkaa määriteltäessä. Kunhan ne määritellään ennen kuin AbstractNode.from kutsutaan ensimmäistä kertaa, pitäisi olla kunnossa. Joten kokeillaan seuraavaa muutosta:

osoittautuu, on olemassa muutamia ongelmia tämän ratkaisun:

ensimmäinen, tämä on ruma eikä skaalaa. Suuressa koodikannassa tämä johtaa siihen, että tuonti liikkuu satunnaisesti, kunnes tavara vain sattuu toimimaan. Joka on usein vain väliaikaista, koska pieni refactoring tai muutos tuonti lausuntoja tulevaisuudessa voi hienovaraisesti säätää moduulin lastausjärjestys, uudelleen käyttöön ongelma.

toiseksi se, toimiiko tämä, riippuu suuresti moduulin niputtajasta. Esimerkiksi codesandboxissa, kun niputamme sovelluksemme pakettiin (tai Webpackiin tai Rollupiin), tämä ratkaisu ei toimi. Kuitenkin, kun ajetaan tätä paikallisesti solmulla.js ja commonJS moduulit tämä kiertotapa saattaa toimia aivan hyvin.

ongelman välttäminen

, joten ilmeisesti tätä ongelmaa ei voida korjata helposti. Olisiko se voitu välttää? Vastaus on kyllä, on olemassa useita tapoja välttää ongelma. Ensinnäkin, olisimme voineet pitää koodin yhdessä tiedostossa. Kuten näkyy meidän alkuperäinen esimerkki, näin voimme ratkaista ongelman, koska se antaa täyden määräysvallan, jossa moduulin alustuskoodi toimii.

toisekseen jotkut käyttävät edellä mainittua ongelmaa argumenttina esittääkseen lausuntoja, kuten “ei pidä käyttää luokkia”tai” ei saa käyttää perintöä”. Tämä on kuitenkin ongelman liiallista yksinkertaistamista. Vaikka olen samaa mieltä siitä, että ohjelmoijat turvautuvat usein perintöön liian nopeasti, joillekin ongelmille se on vain täydellinen ja saattaa tuottaa suuria etuja koodin rakenteen, uudelleenkäytön tai suorituskyvyn suhteen. Mutta mikä tärkeintä, tämä ongelma ei rajoitu luokan perintöön. Täsmälleen sama ongelma voidaan ottaa käyttöön, kun moduulin muuttujien ja moduulin alustuksen aikana suoritettavien toimintojen väliset riippuvuudet ovat ympyränmuotoisia!

voisimme järjestää koodimme uudelleen siten, että hajotamme AbstractNode – luokan pienempiin osiin, jolloin AbstractNode: llä ei ole riippuvuuksia Node: stä tai Leaf: stä. Tässä hiekkalaatikossa from – menetelmä on vedetty pois AbstractNode – luokasta ja laitettu erilliseen tiedostoon. Tämä kyllä ratkaisee ongelman, mutta nyt projektimme ja API rakentuu eri tavalla. Suurissa hankkeissa voi olla hyvin vaikea määritellä, miten tämä temppu tehdään, tai jopa mahdotonta! Kuvitelkaa esimerkiksi, mitä tapahtuisi, jos print menetelmä riippuisi Node tai Leaf sovelluksemme seuraavassa iteraatiossa…

Bonus: ylimääräinen ruma temppu, jota käytin aiemmin: palauta perusluokat funktioista ja vipufunktion nostaminen, jotta asiat ladattaisiin oikeassa järjestyksessä. En osaa edes selittää sitä kunnolla.

sisäinen moduulikuvio pelastukseen!

olen taistellut tämän ongelman kanssa useita kertoja monissa projekteissa muutamia esimerkkejä ovat työni Mendix, MobX, MobX-state-tree ja useat henkilökohtaiset projektit. Jossain vaiheessa, muutama vuosi sitten olen jopa kirjoitti käsikirjoituksen concatenate kaikki lähdetiedostot ja poistaa kaikki tuonti lausunnot. Köyhän miehen moduulin Niputtaja vain saadakseen otteen moduulin latausjärjestyksestä.

tämän ongelman muutaman kerran ratkettua ilmaantui kuitenkin kuvio. Yksi, joka antaa täyden control moduuli lastaus järjestyksessä, tarvitsematta uudistaa hankkeen tai vetämällä outo hakata! Tämä kuvio toimii täydellisesti kaikkien työkalu-ketjut olen kokeillut sitä (Rollup, Webpack, paketti, solmu).

tämän kuvion ydin on ottaa käyttöön index.js ja internal.js tiedosto. Pelin säännöt ovat seuraavat:

  1. internal.js moduuli sekä tuo että vie kaiken projektin jokaisesta paikallisesta moduulista
  2. joka toisesta moduulista vain tuo internal.js – tiedostosta, eikä koskaan suoraan muista projektin tiedostoista.
  3. index.js tiedosto on tärkein maahantulopiste ja tuo ja vie kaiken internal.js: stä, jonka haluaa paljastaa ulkomaailmalle. Huomaa, että tämä vaihe on merkitystä vain, jos olet julkaisemalla kirjasto, joka kuluttaa muut. Joten ohitimme tämän vaiheen esimerkissämme.

huomaa, että edellä mainitut säännöt koskevat vain paikallisia riippuvuuksiamme. Ulkoinen moduulien tuonti jätetään sellaisenaan. He eivät sittenkään ole mukana kiertoliittymäongelmissamme. Jos käytämme tätä strategiaa demosovellukseemme, koodimme näyttää tältä:

kun soveltaa tätä mallia ensimmäistä kertaa, se voi tuntua hyvin teennäinen. Mutta sillä on muutamia erittäin tärkeitä etuja!

  1. ensinnäkin me ratkaisimme ongelmamme! Kuten tässä on osoitettu, sovelluksemme on jälleen onnellisesti käynnissä.
  2. syy siihen, että tämä ratkaisee ongelmamme, on: meillä on nyt täysi kontrolli moduulin latausjärjestykseen. Olipa internal.js: n tuontitilaus mikä tahansa, tulee olemaan moduulin lataustilaus. (Haluat ehkä tarkistaa alla olevan kuvan tai lukea uudelleen yllä olevan moduulin tilausselityksen nähdäksesi, miksi näin on)
  3. meidän ei tarvitse käyttää refaktoreita, joita emme halua. Emme myöskään pakota käyttämään rumia temppuja, kuten muutto vaatii lausuntoja tiedoston pohjalle. Meidän ei tarvitse tinkiä koodikantamme arkkitehtuurista, API: sta tai semanttisesta rakenteesta.
  4. Bonus: tuontilausunnot tulevat paljon pienemmiksi, koska tuomme tavaraa pienemmistä tiedostoista. Esimerkiksi AbstractNode.js on vain tuontilausekkeessa nyt, kun sillä oli aiemmin kaksi.
  5. Bonus: index.js: llä meillä on yksi totuuden lähde, joka antaa hienorakeisen kontrollin sille, mitä paljastamme ulkomaailmalle.

Vastaa

Sähköpostiosoitettasi ei julkaista.