Back to "Legacy Codebases (tai urakoitsijan elämä)"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

Legacy Code

Legacy Codebases (tai urakoitsijan elämä)

Wednesday, 06 November 2024

Johdanto

Freelance-kehittäjänä yksi taitokokonaisuuksista, joka sinun on opittava nopeasti, on se, miten voit työskennellä tehokkaasti olemassa olevien koodikantojen parissa. Olen ollut onnekas, kun olen rakentanut joukon scratch-järjestelmiä; tämä on JOY kokeneena kehittäjänä, mutta se ei aina ole niin.

Haasteet

Legacy-järjestelmissä on merkittäviä haasteita, etenkin kun keskeiset kehittäjät / arkkitehdit (jos olet onnekas, että olet saanut ne) ovat siirtyneet eteenpäin.

Dokumentaatio

Tämä unohdetaan usein erityisesti pienemmissä yrityksissä. Yleensä tarvitset neljä keskeistä asiakirjatyyppiä:

  1. Uudet kehittäjäoppaat miten siis pyörität projektia paikallisesti (enemmän tässä hetkessä) mitä huomioita on olemassa (jos esimerkiksi tarvitset toisenlaiset puitteet kuin nykyinen, erityisesti se pitää valitettavan paikkansa solmukohdassa).
  2. Käyttöönottolääkärit Näinä päivinä, kun CI/CD:tä pidetään käyttöönoton kultanormina, usein unohdetaan, että pitää osata ottaa järjestelmä käyttöön manuaalisesti. Tämä pitää erityisesti paikkansa, jos työstää järjestelmää, joka on ollut olemassa jo jonkin aikaa ja jossa on paljon manuaalisia vaiheita.
  3. OngelmanratkaisumenettelytMitä teet, kun järjestelmä kaatuu? Kenelle soitat? Mitkä ovat tärkeimmät tarkistettavat asiat? Tämä jätetään usein huomiotta, mutta se on CRUCIAL tuotantojärjestelmässä.
  4. Arkkitehti / System-Design Docs; Miten järjestelmä toimii? Mitkä ovat keskeiset osat? Mitkä ovat tärkeimmät riippuvuudet? Ajattele tätä etenemissuunnitelmanasi, kun opettelet uutta järjestelmää. Se tarjoaa korkean tason katsauksen järjestelmän toimintaan, joka voi olla kriittinen (erityisesti suuremmissa, hajautetuissa järjestelmissä). Tähän tulisi sisältyä, mitä lähdekoodivarastoja käytetään, mitä CI/CD-järjestelmiä käytetään, mitä tietokantoja käytetään sovelluksen jokaiselle osalle. Tämä voi käsittää mitä tahansa yksinkertaisesta diagrammista järjestelmän jokaisen osan täyteen UML-diagrammiin. Esimerkiksi React-sovelluksessa tämä sisältäisi tyypillisesti kaavion komponenteista ja siitä, miten ne ovat vuorovaikutuksessa keskenään ja mahdollisten taustapalveluiden kanssa. .NET Core -sovelluksessa tämä sisältäisi kaavion palveluista ja siitä, miten ne ovat vuorovaikutuksessa keskenään (ja etupään ja muiden backend-järjestelmien) sekä mahdollisesti ASP.NET-näkymistä ja mitä palveluja ne voivat käyttää.

Dokumentaatio on yksi niistä asioista, joita kehittäjinä usein vihaamme (se EI ole koodia), mutta se on ratkaisevan tärkeää. Kuten näet, rakastan Markdownia, merenneidon ja Plantumlin kaltaisilla laitteilla voit luoda todella hienoja kaavioita ja vuokaavioita, jotka voidaan sisällyttää asiakirjoihin.

Sen pitää olla CURRENT, kehittäjät puhuvat usein bittirotista, jossa projektin riippuvuudet vanhentuvat / suorastaan turvallisuusriskeistä. Tämä pätee myös asiakirjoihin; jos se ei ole ajankohtaista, siitä ei ole hyötyä.

Dokumentaatiot vaihtelevat, mutta yleisesti ottaen milloin tahansa muutat asiakirjassa mainittua koodia, sinun tulee päivittää kyseinen asiakirja.

Järjestelmän käyttö paikallisesti

Tämä on usein haasteellista, etenkin jos järjestelmä on ollut olemassa jo jonkin aikaa. Sinun täytyy tietää, mikä versio Nodesta /.NETistä jne., mikä versio tietokannasta, mikä versio kehyksestä jne. Tämä jätetään usein huomiotta, mutta se on CRUCIAL, jotta se käynnistyisi ja toimisi nopeasti.

Olen usein nähnyt kehittäjien sanovan, että tällä ei ole merkitystä näinä pilvijärjestelmien ja laajalevikkisten sovellusten aikoina, mutta olen eri mieltä. Järjestelmää pitää pystyä ohjaamaan paikallisesti, jotta ongelmat voidaan selvittää nopeasti ja tehokkaasti.

  1. Profilointi - tästä näyttää tulleen "vain kehittyneen kehittäjän" taito, mutta on tärkeää pystyä profiloimaan koodinsa nähdäkseen, missä pullonkaulat ovat. Tämä pitää erityisesti paikkansa perinnöllisessä järjestelmässä, jossa ei välttämättä ole ylellisyyttä kirjoittaa järjestelmää uudelleen tyhjästä. Työkalut kuten dotTrace sekä DotMemoryovat korvaamattomia täällä. Erityisesti ASP.NET-sovelluksissa suurimmat ongelmat ovat yleensä järjestelmän "vuotoja", muistivuotoja, yhteysvuotoja jne. Vaikka sovelluksesi näyttää pyörittävän FINEä jonkin aikaa, huomaat yhtäkkiä sen kaatuvan / käyttävän kaikki palvelimen muistit.
  2. Ongelmien löytäminen debuggerista - pidit siitä tai et Response.Write Classicissa ASP on ohi. Vaatimattoman monimutkaisessa sovelluksessa (etenkin niissä, joita et kirjoittanut) koodin läpivieminen on ratkaisevan tärkeää. Seuratakseen sen alusta palvelun kautta esittämää pyyntöä selvittää, mitä MIGHT-tapahtumassa tapahtuu, mitä poikkeuksia ei ehkä saada kiinni jne.
  3. Logging - Usein ohitettu (anteeksi, mutta ei ASP.NET Core -poikkeussuodatinta pinon yläosassa ei riitä). Viittaaminen omaan edellinen virka, puunkorjuu on kriittinen osa koodityötä PAIKALLISESTI. Muista, että voit käyttää asiakkaan kirjautumistyyppejä (esimerkiksi Kirjauslähdegeneraattorit) ASP.NET Coressa. Sen jälkeen voit määrittää, mitkä tapahtumatyypit pitäisi kirjautua ja mitkä eivät. Tämä on ratkaisevan tärkeää perinnöllisessä järjestelmässä, jossa ei välttämättä ole varaa kirjoittaa järjestelmää uudelleen tyhjästä. Application Insightsille voit haluta Käyttäjämatkat ja muut ominaisuudet, mutta ole kuitenkin tietoinen tästä tulee kallista nopeasti jos käytät LogInformation jokaisesta pyynnöstä. Voit ehkä haluta käyttää mukautettua telemetriaprosessoria suodattamaan pyyntöjä, joita et halua kirjata.
  4. Testaaminen - Liian usein näen kehittäjien "testaavan preprodissa" tai ajattelevan, että Unit Test kirjautuu sisään, mikä riittää testaamiseen. Sen RARLY IS -testillä on paljon arvoa siinä, että molemmat käyttävät Resharper / NCrunchin kaltaista työkalua automaattisesti yksikkötestien tekemiseen. Muista kuitenkin, että Unit Tests -testit ovat juuri sitä; he testaavat koodin "yksikköä". Sinun täytyy säilyttää näkyvyys siinä, miten järjestelmä todella toimii yhdessä muiden osien kanssa. Integraatiotestit tulevat tässä mukaan, ne testaavat, miten järjestelmä toimii kokonaisuutena. Voit käyttää työkalua kuten SpecFlow kirjoittaa nämä testit ihmisen luettavassa muodossa. Jälleen kerran, ratkaisevaa perinnöllisessä järjestelmässä, jossa ei ehkä ole ylellisyyttä pystyä kirjoittamaan järjestelmää uudelleen tyhjästä.

Jokaisessa projektissa teen työtä sen eteen, että saamme järjestelmän (tai suuren osan siitä) toimimaan paikallisesti. Näkemällä koodin, käyttämällä koodia, vioittamalla koodia saat tuntuman järjestelmän toimintaan.

Koodipohja

Jokaisessa järjestelmässä tämä on sinun totuuden lähdeSanovatpa lääkärit mitä tahansa, mitä muut kertovat siitä, miten sen pitäisi toimia, näin se toimii.

Näin usein haastavaa on se, että löytää tiensä uuteen kaupunkiin, jossa ei ole etenemissuunnitelmaa. Onneksi sovelluksissa on hakupiste (sivun lataus / etupään API-puhelu jne.) Valitse piste ja aloita sieltä.

Käytä sen kanssa vuorovaikutukseen mitä tahansa, oli se sitten Postimies, Rider's HttpClient tai jopa nettisivu. Koputa vianetsintään, soita puhelu ja seuraa sitä. Huuhtele ja toista järjestelmän jokainen osa.

Uusintakerroin

Yleensä jätät tämän väliin, kunnes ymmärrät järjestelmän. On aina houkuttelevaa "heittää se pois ja aloittaa alusta" mutta vastustaa kuitenkin tätä houkutusta. Varsinkin käyttöjärjestelmän osalta Se toimii Järjestelmän uudelleenrakentaminen / jopa uusiminen on HUGE-riski. Kyllä se on hauskaa, mutta jokaiselle koodiriville, jota vaihdat, on riski ottaa käyttöön uusia kiinnostavia vikoja.

Kuten kaikki muukin (etenkin hankittaessa) sinun täytyy perustella tekemäsi työ järjestelmällä. Joko tämä perustelu on keskitettävä johonkin seuraavista:

  1. Suorituskyky - järjestelmä on hidas ja sitä on nopeutettava (ole taas varovainen, se mitä huomaat hitaaksi voi olla se, miten järjestelmä on suunniteltu toimimaan). Yhden osan polttaminen nopeasti voi tuoda ongelmia syvemmälle järjestelmään. Aiotko "tappaa" tietokantapalvelimen, jos teet liikaa pyyntöjä, onko sinulla mekanismi, joka ei aiheuta murtuvia poikkeuksia?
  2. Turvallisuus - järjestelmä on epävarma, ja se on turvattava. Tämä on hankalaa, erityisesti perinnöllisessä järjestelmässä. Bit-rotin avulla saatat huomata, että järjestelmä käyttää vanhoja versioita kirjastoista, joissa on tunnettuja tietoturvaongelmia. Tämä on hyvä peruste työlle, mutta ole kuitenkin tietoinen siitä, että sinun täytyy ehkä uudelleenlaatia paljon järjestelmää saadaksesi sen ajan tasalle, mikä taas johtaa "uusiin vikoihin".
  3. Säilytettävyys - järjestelmää on vaikea ylläpitää ja sitä on helpotettava. Yleisesti ottaen tästä tulee paljon työtä, perusteleeko koodiston nykyinen käyttöikä tämän? Jos käytät enemmän aikaa näiden muutosten tekemiseen parantaaksesi säilyvyyttä kuin mitä koskaan säästäisit asiakkaalle, niin se ei ole sen arvoista (ja taas, muutti koodia SubFinland.org
  4. Käyttäjäkokemus - Yleensä priorisoin nämä asiat. ää nt ä nt ä nt ä nt ö nt ä nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö nt ö ö nt ö n käyttäjä Sillä ei ole väliä, onko koodisi yhden prosentin parempi; he ovat niitä, jotka maksavat työstä, jota lopulta teet. Jos voit tehdä heidän kokemuksestaan paremman kuin se yleensä on sen arvoista. Ole kuitenkin tietoinen siitä, että tämä voi olla muutosten "lipsuva rinne", sillä saatat huomata, että muutat paljon järjestelmää tehdäksesi pienen muutoksen käyttäjälle.

Perintöjärjestelmien parissa työskenteleminen

Tämä jää usein huomiotta, erityisesti kehittäjiltä. Sinun täytyy pystyä perustelemaan työ, jota teet järjestelmän parissa. Tämä pätee erityisesti sopimusympäristössä, jossa palkkaa maksetaan tunnilta. Loppujen lopuksi se ei ole sinun koodisi eikä sinun rahasi. Miksi olet tekemässä muutosta, on usein tärkeämpää kuin itse muutos.

Olen työskennellyt urakoitsijana jo yli vuosikymmenen, eikä se ole helppoa, vaan urakoitsijana jokainen tunti ajastasi on asiakkaalle "hinta". Sinun täytyy lisätä siirtoarvoa järjestelmään enemmän kuin maksat. Jos et ole, etsit nopeasti uutta sopimusta.

Kehittäjinä olemme yleensä surkeita bisnesihmisiä, jotka keskittyvät "täydellisyyteen" joka käänteessä. Todellisuudessa ei tarvitse tehdä järjestelmästä "täydellistä" (mikäli väittäisin, ettei sellaista ole), vaan asiakkaalle pitää vain antaa arvoa.

Pidemmällä aikavälillä tämä sisältää myös sen, että uutta koodi on ylläpidettävä ja kustannustehokas pyöritettäväksi. Perintöjärjestelmissä tämä on paljon pahempaa. Usein on kahlattava suon läpi ja oltava huolissaan siitä, että kun oppii järjestelmän, ei voi tarjota paljonkaan arvoa. I'm not making any changes luulet, että I'm just learning the system. Tämä on harhaluuloa; opettelet järjestelmää parantamaan sitä. Opettelet järjestelmää tehostamaan sitä. Opettelet järjestelmää tekemään siitä huollettavamman. Jos asiakas ei voi hyväksyä tätä askelta, sinun on oltava hyvin varovainen sen suhteen, miten viestit tästä (tai etsit uutta sopimusta).

Kansa

Usein unohdetaan, että usein sinut otetaan mukaan urakoitsijaksi, koska joku avainhenkilö on lähtenyt (älä sekaannu tämän politiikkaan, se ei ole sinun huolesi). Projektin tavoitteiden saavuttamiseksi pitää pystyä työskentelemään siellä olevien ihmisten kanssa. Sopimuksessa on yleensä määritelty kihlauksen ehdot (nykyisessä sopimuksessani se on "luotettavuuden parantaminen ja juoksevien kustannusten alentaminen"). Keskity tähän. Jos et ole varma, mitä tämä tarkoittaa, kysy.

Muista, kuka on suora kontaktisi, erityisesti parin ensimmäisen kuukauden aikana. Pidä heidät ajan tasalla (todennäköisesti sinulla ei ole uusia ominaisuuksia, joilla kehuskella, kun innostut järjestelmän toiminnasta). Lähetän yleensä viikoittain/kahden viikon välein tiivistetyn sähköpostin suoralle kontaktilleni. Tämä on hyvä tapa pitää heidät ajan tasalla siitä, mitä olet tekemässä ja mitä olet löytämässä.

Muista, että tämä on se, joka hyväksyy laskusi; laskun aikaan ei pitäisi tulla yllätyksiä. Kun alat tarkistaa koodia säännöllisesti, kyseessä ei ole niinkään ongelma; sinulla on tieto siitä, mitä teit ja millainen vaikutus sillä oli. Siihen asti on pidettävä heidät ajan tasalla. Heidän täytyy tietää, mitä teit ja miksi he maksaisivat siitä.

Luotettavuus

Takaisin perintökoodiin: jos teet muutoksen yleensä, sinun on otettava se käyttöön.Vaikka parhaatkin meistä joskus munaavat THE UP:n, varsinkin perintökoodijärjestelmissä tulee olemaan jotain. Et voinut tietää kun sijoitat. Tämä palautuu kirjautumiseen - jos sinulla on lavastuspalvelin, se kirjautuu LOT (mutta säilytetään lyhyen aikaa) niin kun laitat THEn käyttöön, voit kerätä lisää tietoa siitä, mikä epäonnistui.

Vaikka olisit kuinka hyvä, kuinka paljon paikallisia testejä olet tehnyt, olemme kaikki ihmisiä. Tämä on keskeinen osa "älä ota käyttöön perjantaina" -sääntöä; odota, että käyttöönotto aiheuttaa uuden ongelman järjestelmässä. Ole valmis tekemään töitä, kunnes asia on ratkaistu. Jos et tiedä, miksi se epäonnistui, lisää lisää testejä ongelman uusimiseksi ja lisää puunkorjuuta, jotta saat vastaavat ongelmat tulevaisuudessa.

Erityisesti tuotantojärjestelmissä pysähdysjärjestelmäsi ei välttämättä ole 1:1 (varsinkaan kuorman osalta), kuten k6 Se voi auttaa simuloimaan kuormaa (ja vielä paremmin paikallisesti, missä voit tehdä oikean profiloinnin kuten aiemmin mainittiin).

Käyttöönotto

CI/CD:n kiihko on usein jäänyt huomaamatta. Yksinkertaista, sinä mokaat. Hyvin nopea ja tehokas tapa ottaa järjestelmä käyttöön tarkoittaa, että kun rikot sen, voit myös korjata sen nopeammin. Jos CI-koodin tarkistusjärjestelmä tarkoittaa, että PR:n yhdistäminen kestää kaksi päivää, se on nopeinta, mitä järjestelmää voi kohtuullisesti käyttää. Jos CD-järjestelmäsi tarkoittaa, että poistat juoksujärjestelmän, totu pitkiin iltoihin.

Tehokas mekanismi koodin korjaamiseksi ja käyttämiseksi on välttämätön tehokkaan kehitysputken kannalta. Jos korjauksen käyttö kestää kauemmin kuin sen löytäminen ja toteuttaminen koodilla, niin todennäköisesti korjaaminen on epätodennäköisempää.

"Tulossa perintösovellukset"

Sanon tämän lainauksin, koska tämä on ongelma. Perinnöllisissä sovelluksissa (varsinkin silloin, kun laajamittainen uudelleentyö on rajatonta) on kaksi päälähestymistapaa.

  • Suoritettavat täplät

Tämä on yksinkertaisesti olemassa olevan koodin kiinnittämistä. Varmista jälleen, että testaat perusteellisesti ja sinulla on käytössäsi prosessit, joiden avulla mahdolliset korjaukset voidaan palauttaa / siirtää nopeasti. En valehtele, että tällainen kehitys on harvoin hauskaa, koska olet edelleen todennäköisesti kahlaamassa olemassa olevan koodipohjan suolla. Monissa tapauksissa se on kuitenkin välttämätön paha.

Kuten tavallista, sinun tulisi varmistaa, että sinulla on jonkinlainen testimuoto nykyisen koodin selvittämiseksi. Ihannetapauksessa sen pitäisi myös testata epäonnistumista asiassa, jota yrität ratkaista, ennen kuin teet korjauksen. . He haluavat, että heille tehdään yksikkötesti, joka kohdistaa tarkasti koodialueen, joka sinun on korjattava, mutta tämä ei useinkaan kuulu suurten, hajautettujen järjestelmien työskentelyn piiriin.

Käytän yleensä testijärjestelmää tässä järjestyksessä:

  1. Unit Tests - jälleen nämä ovat mieluisia, koska voit kohdistaa ne vain käyttääksesi koodia, jonka parissa työskentelet. Perinnöllisessä järjestelmässä nämä eivät kuitenkaan useinkaan ole erittäin vaikeita jälkiasennusta varten (esimerkiksi järjestelmässä, jossa on paljon ulkopuolisia puheluita, mikä on sotkuista sen rakentamisessa, ei esimerkiksi DI:n käytössä).
  2. Integraatiotestit - Tämä on ylikuormitettu termi, koska se voi kattaa mitä tahansa yksikön testistä, joka läpäisee useita kerroksia koodia (näitä on parasta välttää) käyttääkseen erinomaisten Varmista läpi jopa Selenium-testeihin. Yleisesti ottaen haluat testata koko järjestelmää, mutta tiedosta, että nämä testit voivat olla hitaita ja hauraita. Verifyn käyttö voi usein olla hyvä lähestymistapa perinteisiin järjestelmiin, koska voit ainakin "varmentaa", ettet riko järjestelmän API-pintaa.
  3. Manuaalitestit - JOKAisen kehittäjän tulisi yrittää tehdä manuaalisia testejä koodin tarkistamiseksi. Näin varmistetaan vain, että se, mitä odotat "käyttäjältä" (tämä voi olla todellinen käyttäjä tai jokin muu koodisi kanssa vuorovaikutuksessa olevan järjestelmän osa), on se, mitä he todella näkevät. Tämä voi olla yhtä yksinkertaista kuin järjestelmän pyörittäminen paikallisesti ja sivun ulostulon tarkistaminen tai yhtä monimutkaista kuin kokonaisten testien suorittaminen lavastuspalvelimella.
  • Sipulin nylkeminen Perinnöllisten järjestelmien parissa työskentelyyn ei yleensä liity täydellisen uudelleenkäsittelyn ylellisyyttä. Tässä käytän "sipulin nylkemiseen" perustuvaa lähestymistapaa.

Jotta voit päivittää järjestelmän osia, voit tunnistaa osia, jotka voidaan erottaa olemassa olevasta monoliittista mikropalveluksi (jostakin'mikron' arvosta). Tämä voi olla hyvä tapa aloittaa järjestelmän uudenaikaistaminen ilman, että vaarana on täyskäännös. Yleisiä esimerkkejä voivat olla API-päätteiden jakaminen uusiin projekteihin, joissa käytetään päivitettyjä elementtejä. DRY:n kauhu voi kuitenkin tulla kuvioihin tässä asiassa. Huonosti jäsennetyssä ratkaisussa on usein paljon "auttaja" tai "palvelu" -komponentteja, joiden pitäisi todella olla eri projekteissa (tai jopa sankoissa paketeissa, joissa käytetään enemmän globaalia uudelleenkäyttöä).

Käsittelen tätä lähestymistapaa tarkemmin tulevassa artikkelissa, koska se on keskeinen osa sitä, miten työskentelen perintöjärjestelmien parissa ja se ei ole monelle kehittäjälle itsestään selvää.

Maksetaan

Nyt kun olemme saaneet tämän kaiken ulos, tulee kinkkinen maksuongelma. Minulla on yleinen sääntö:

Kaikki maksuongelmat, joita haluan jatkaa

Jos he ovat myöhässä maksamisesta, riippuu sopimuksestasi, mutta LEASissa 30 päivän kuluessa, mutta yleensä lähempänä seitsemää, tämä on huono merkki. Jos laskustasi on riitelyä, mieti, pystyykö yhtiö jatkuvasti maksamaan palveluistasi.

Älä pelleile tämän kanssa; jos olet tehnyt työsi, sinulle pitää maksaa ajallaan. Sillä ei ole väliä, kuinka paljon nautit siitä; jos huono asiakas voi käyttää sinua hyväkseen, he käyttävät. Se ei ole koskaan sen arvoista.

Ole rehellinen; veloita vain ajasta, jonka olet todella työskennellyt; varmista, että on selvää, mitä teit ja miksi teit sen.

Olen johtanut kehittäjien tiimiä ja ollut kehittäjä; olen ollut urakoitsija ja olen ollut asiakas. Olen nähnyt kaikki puolet tästä ja voin kertoa, että jos et saa palkkaa ajoissa, sinun on jatkettava eteenpäin. Jos kääntöpuolella on urakoitsija (tai kokoaikainen urakoitsija), joka ei toimita, tähän on puututtava nopeasti. Kaikilla on henkilökohtaisia kamppailuja, mutta etenkin sopimusympäristössä pitää tuottaa arvoa tai olla veloittamatta aikaa, kun ei ole.

Mitä korkoon tulee, löydät tasosi; henkilökohtaisesti veloitan enemmän hankkeista, joissa minulla on enemmän vastuuta (tai jotka eivät näytä hauskoilta). Veloitan vähemmän projekteista, joissa opettelen uutta teknologiaa, tai aloittelevista yrityksistä. Olen myös tehnyt vähemmän töitä, mutta pitänyt kurssini tasaisena. Mutta älä hyväksy matalaa hintaa; olet ammattilainen ja sinulle pitäisi maksaa sellaisenaan.

Johtopäätöksenä

Siinä kaikki. Olen tänään ja huomenna poissa töistä isoäitini hautajaisissa ja suoraan sanottuna panikoin hieman, että minulla on HUGE-perintöjärjestelmä opeteltavana, joten ajattelin oksentaa ajatukseni siitä, mitä työskentely näissä järjestelmissä on ja mitä haasteita.

logo

©2024 Scott Galloway