(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': data().getTime(),įvykis:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); Kaip nesunaikinti projekto dėl blogos kodavimo praktikos? - The Codest
The Codest
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Pramonės šakos
    • Fintech ir bankininkystė
    • E-commerce
    • Adtech
    • Sveikatos technologijos
    • Gamyba
    • Logistika
    • Automobiliai
    • IOT
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
Atgal rodyklė GRĮŽTI ATGAL
2019-04-24
Programinės įrangos kūrimas

Kaip nesunaikinti projekto dėl blogos kodavimo praktikos?

The Codest

Bartosz Slysz

Software Engineer

Daugelis karjerą pradedančių programuotojų mano, kad kintamųjų, funkcijų, failų ir kitų komponentų pavadinimų suteikimo tema nėra labai svarbi. Dėl to jų projektavimo logika dažnai būna teisinga - algoritmai veikia greitai ir duoda norimą efektą, o gali būti vos įskaitomi. Šiame straipsnyje trumpai pabandysiu apibūdinti, kuo turėtume vadovautis suteikdami pavadinimus įvairiems kodo elementams ir kaip nepulti iš vieno kraštutinumo į kitą.

Kodėl apleidus pavadinimų kūrimo etapą, projekto kūrimas užsitęs (kai kuriais atvejais - labai)?

Tarkime, kad jūs ir jūsų komanda perima kodas iš kitų programuotojų. Svetainė projektas jūs paveldite buvo sukurtas be jokios meilės - jis veikė puikiai, tačiau kiekvienas jo elementas galėjo būti parašytas daug geriau.

Kai kalbama apie architektūrą, kodo paveldėjimo atveju ji beveik visada sukelia neapykantą ir pyktį iš ją gavusių programuotojų. Kartais taip nutinka dėl mirštančių (arba išnykusių) technologijų naudojimo, kartais dėl neteisingo mąstymo apie programą kūrimo pradžioje, o kartais tiesiog dėl atsakingo programuotojo žinių stokos.

Bet kokiu atveju, projektui tęsiantis, galima pasiekti, kad programuotojai ims pykti ant architektūrų ir technologijų. Juk kiekvienai programai po kurio laiko reikia perrašyti kai kurias dalis arba tiesiog pakeisti tam tikras dalis - tai natūralu. Tačiau problema, nuo kurios programuotojams pasišiaušia plaukai, yra sunkumai skaitant ir suprantant paveldėtą kodą.

Ypač kraštutiniais atvejais, kai kintamieji įvardijami atskiromis, nieko nereiškiančiomis raidėmis, o funkcijos yra staigus kūrybiškumo proveržis, niekaip nederantis su likusia programos dalimi, jūsų programuotojai gali išprotėti. Tokiu atveju bet kokiai kodo analizei, kuri galėtų vykti greitai ir efektyviai, jei būtų teisingai įvardyti pavadinimai, reikia papildomai analizuoti algoritmus, atsakingus už funkcijos rezultato gavimą, pvz. O tokia analizė, nors ir nepastebima - sugaištama labai daug laiko.

Įgyvendinant naujas funkcijas skirtingose programos dalyse, tenka patirti košmarą analizuojant kodą, o po kurio laiko tenka grįžti prie kodo ir vėl jį analizuoti, nes jo ketinimai neaiškūs, o ankstesnis laikas, praleistas bandant suprasti jo veikimą, buvo iššvaistytas veltui, nes nebeprisimenate, kokia buvo jo paskirtis.

Taip mus įtraukia netvarkos tornadas, kuris viešpatauja programoje ir pamažu pasiglemžia kiekvieną jos kūrimo dalyvį. Programuotojai nekenčia projekto, projektų vadovai nemėgsta aiškinti, kodėl jo kūrimo laikas ima nuolat ilgėti, o klientas praranda pasitikėjimą ir pyksta, nes niekas nevyksta pagal planą.

Kaip to išvengti?

Pripažinkime - kai kurių dalykų negalima praleisti. Jei projekto pradžioje pasirinkome tam tikras technologijas, turime žinoti, kad laikui bėgant jos arba nustos būti palaikomos, arba vis mažiau programuotojų mokės naudotis prieš kelerius metus sukurtomis technologijomis, kurios pamažu sensta. Kai kurių bibliotekų atnaujinimai reikalauja daugiau ar mažiau susijusių kodo pakeitimų, kurie dažnai sukelia priklausomybių sūkurį, kuriame galima dar labiau įstrigti.

Kita vertus, tai nėra toks juodas scenarijus; žinoma, technologijos sensta, tačiau veiksnys, kuris neabejotinai lėtina su jomis susijusių projektų kūrimo laiką, dažniausiai yra negražus kodas. Ir, žinoma, čia reikia paminėti Roberto C. Martino knygą - tai biblija programuotojams, kurioje autorius pateikia daug gerosios praktikos ir principų, kurių reikėtų laikytis norint sukurti tobulumo siekiantį kodą.

  1. Pagrindinė kintamųjų pavadinimų reikšmė - aiškiai ir paprastai perteikti jų paskirtį. Tai skamba gana paprastai, tačiau kartais daugelis žmonių to nepaiso arba ignoruoja. Geras pavadinimas nurodys, ką konkrečiai kintamasis turi saugoti arba ką funkcija turi daryti - jis negali būti pavadintas pernelyg bendrai, bet, kita vertus, negali tapti ilgu šlamštu, kurio vien perskaitymas sukelia nemažą iššūkį smegenims. Po kurio laiko su gerais kokybės kodas, patiriame panardinimo efektą, kai galime pasąmoningai organizuoti vardų suteikimą ir perdavimą duomenys prie funkcijos taip, kad visa tai nepalieka iliuzijų, koks ketinimas ją skatina ir kokio rezultato tikimasi ją iškvietus.
  2. Kitas dalykas, kurį galima rasti JavaScript, be kita ko, bandoma pernelyg optimizuoti kodą, todėl daugeliu atvejų jis tampa neįskaitomas. Normalu, kad kai kuriems algoritmams reikia ypatingos priežiūros, o tai dažnai atspindi tai, kad kodo paskirtis gali būti šiek tiek painesnė. Vis dėlto atvejai, kai reikia pernelyg didelio optimizavimo, yra itin reti, arba bent jau tie, kai mūsų kodas yra nešvarus. Svarbu nepamiršti, kad daugelis su kalba susijusių optimizavimų vyksta šiek tiek žemesniame abstrakcijos lygmenyje; pavyzdžiui, V8 variklis, esant pakankamam iteracijų skaičiui, gali gerokai pagreitinti ciklus. Reikėtų pabrėžti tai, kad gyvename XXI amžiuje ir nerašome programų, skirtų "Apollo 13" misijai. Turime kur kas daugiau manevro laisvės išteklių tema - jie yra tam, kad būtų naudojami (pageidautina, kad protingai :>).
  3. Kartais kodo skaidymas į dalis tikrai daug duoda. Kai operacijos sudaro grandinę, kurios tikslas - atlikti veiksmus, atsakingus už konkretų duomenų pakeitimą, - lengva pasiklysti. Todėl paprastai, užuot viską atlikę vienoje grandinėje, atskiras kodo dalis, atsakingas už konkretų dalyką, galite suskaidyti į atskirus elementus. Tai ne tik leis aiškiai suprasti atskirų operacijų paskirtį, bet ir leis išbandyti už vieną dalyką atsakingus kodo fragmentus, kuriuos galima lengvai pakartotinai naudoti.

Keletas praktinių pavyzdžių

Manau, kad tiksliausiai kai kuriuos iš aukščiau pateiktų teiginių bus galima perteikti parodant, kaip jie veikia praktiškai - šioje pastraipoje pabandysiu apibūdinti kai kurias blogas kodo praktikas, kurias daugiau ar mažiau galima paversti geromis. Nurodysiu, kas kai kuriais momentais trikdo kodo skaitomumą ir kaip to išvengti.

Vienos raidės kintamųjų prakeiksmas

Baisi praktika, kuri, deja, gana paplitusi net universitetuose, yra kintamųjų pavadinimai iš vienos raidės. Sunku nesutikti, kad kartais tai gana patogus sprendimas - išvengiame nereikalingo galvojimo, kaip nustatyti kintamojo paskirtį, ir užuot naudoję kelis ar daugiau simbolių jam pavadinti, naudojame tik vieną raidę, pvz., i, j, k.

Paradoksalu, bet kai kurie šių kintamųjų apibrėžimai yra aprūpinti daug ilgesniu komentaru, iš kurio galima spręsti, ką autorius turėjo omenyje.

Geras pavyzdys būtų iteracija per dvimatį masyvą, kuriame stulpelių ir eilučių sankirtoje yra atitinkamos reikšmės.

const array = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];

// gana blogai
for (let i = 0; i < array[i]; i++) {
  for (let j = 0; j < array[i][j]; j++) {
    // čia yra turinys, bet kiekvieną kartą, kai naudojamos i ir j, turiu grįžti atgal ir analizuoti, kam jos naudojamos
  }
}

// vis dar blogai, bet juokinga
leiskite i; // eilutė
let j; // stulpelis

for (i = 0; i < array[i]; i++) {
  for (j = 0; j < array[i][j]; j++) {
    // čia yra turinys, bet kiekvieną kartą, kai naudojamos i ir j, turiu grįžti ir patikrinti komentarus, kam jos naudojamos
  }
}

// daug geriau
const rowCount = array.length;

for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
  const row = array[rowIndex];
  const columnCount = row.length;

  for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
    const column = row[columnIndex];

    // ar kam nors kyla abejonių, kas yra kas?
  }
}

Klastingas per didelis optimizavimas

Vieną gražią dieną susidūriau su labai sudėtingu kodu, kurį parašė programinės įrangos inžinierius. Šis inžinierius išsiaiškino, kad naudotojo leidimus siųsti kaip konkrečius veiksmus nurodančias eilutes galima labai optimizuoti naudojant kelias bitų lygio gudrybes.

Tikriausiai toks sprendimas būtų tinkamas, jei tikslas būtų "Commodore 64", tačiau šio kodo tikslas buvo paprastas žiniatinklio svetainė programa, parašyta JS. Atėjo laikas įveikti šią keistenybę:
Tarkime, kad naudotojas visoje sistemoje turi tik keturias turinio keitimo parinktis: kurti, skaityti, atnaujinti, ištrinti. Visiškai natūralu, kad šias teises siunčiame JSON forma kaip objekto su būsenomis raktus arba kaip masyvą.

Tačiau mūsų sumanus inžinierius pastebėjo, kad skaičius keturi yra stebuklinga dvejetainio pateikimo reikšmė, ir tai išsprendė taip:

blogi kodo įpročiai

Visą galimybių lentelę sudaro 16 eilučių, aš išvardijau tik 4, kad perteikčiau šių leidimų kūrimo idėją. Leidimų skaitymas vyksta taip:

const user = { leidimai: 11 };

const canCreate = Boolean(user.permissions & 8); // true
const canRead = Boolean(user.permissions & 4); // false
const canUpdate = Boolean(user.permissions & 2); // true
const canDelete = Boolean(user.permissions & 1); // true

Tai, ką matote pirmiau, nėra "WebAssembly" kodas. Nenoriu, kad mane neteisingai suprastumėte - toks optimizavimas yra įprastas dalykas sistemose, kuriose tam tikri dalykai turi užimti labai mažai laiko arba atminties (arba ir vieno, ir kito). Kita vertus, žiniatinklio programos tikrai nėra ta vieta, kur toks perteklinis optimizavimas yra visiškai prasmingas. Nenoriu apibendrinti, bet priekinės dalies kūrėjų darbe sudėtingesnės operacijos, pasiekiančios bitų abstrakcijos lygį, atliekamos retai.

Jis paprasčiausiai neįskaitomas, o programuotojas, galintis atlikti tokio kodo analizę, tikrai susimąstys, kokių nematomų privalumų turi šis sprendimas ir kas gali būti sugadinta, kai kūrimo komanda nori jį perrašyti į priimtinesnį sprendimą.

Dar daugiau - įtariu, kad siunčiant leidimus kaip paprastą objektą programuotojas galėtų perskaityti ketinimą per 1-2 sekundes, o viso šio dalyko analizė nuo pat pradžių užtruks bent kelias minutes. Projekte bus keli programuotojai, kiekvienam iš jų teks susidurti su šia kodo dalimi - jie turės ją analizuoti kelis kartus, nes po kurio laiko pamirš, kokia magija ten vyksta. Ar verta išsaugoti tuos kelis baitus? Mano nuomone, ne.

Skaldyk ir valdyk

Interneto svetainių kūrimas sparčiai auga ir nėra jokių požymių, kad greitai kas nors pasikeis. Tenka pripažinti, kad pastaruoju metu gerokai padidėjo priekinės dalies kūrėjų atsakomybė - jie perėmė logikos dalį, atsakingą už duomenų pateikimą naudotojo sąsajoje.

Kartais ši logika yra paprasta, o objektai, kuriuos pateikia API turi paprastą ir lengvai skaitomą struktūrą. Tačiau kartais, norint juos pritaikyti skirtingose puslapio vietose, reikia atlikti įvairius atvaizdavimo, rūšiavimo ir kitus veiksmus. Ir tai yra ta vieta, kur galime lengvai pakliūti į pelkę.

Daug kartų esu save pagavęs, kai mano atliekamų operacijų duomenys buvo beveik neįskaitomi. Nepaisant teisingo masyvų metodų naudojimo ir tinkamo kintamųjų pavadinimų suteikimo, operacijų grandinės kai kuriose vietose beveik prarado kontekstą to, ką norėjau pasiekti. Be to, kai kurias iš šių operacijų kartais reikėdavo naudoti kitur, o kartais jos būdavo pakankamai globalios arba sudėtingos, kad reikėtų rašyti testus.

const įrenginiai = [
  { id: '001', version: 1, owner: { location: 'Texas', age: 21 } },
  { id: '002', versija: 2, savininkas: { vieta: 'Teksasas', amžius: 27 } },
  { id: '003', versija: 3, savininkas: { vieta: 'Arizona', amžius: 27 } },
  { id: '004', versija: 2, savininkas: { vieta: 'Čikaga', amžius: 24 m. } },
  { id: '005', versija: 2, savininkas: { vieta: 'Arizona', amžius: 19 metų } },
  { id: '006', versija: 3, savininkas: { vieta: 'Teksasas', amžius: 42 m. } },
];

// gana sudėtinga
(() => {
  const locationAgeMap = devices
    .map(device => device.owner)
    .reduce((map, item) => {
      if (!map[item.location]) {
        map[item.location] = item.age;
      } else {
        map[item.location] += item.age;
      }

      return map;
    }, {});

  const locationLegalAgeOwnersMap = devices
    .map(device => device.owner)
    .filter(owner => owner.age >= 21)
    .reduce((map, item) => {
      if (!map[item.location]) {
        map[item.location] = [item];
      } else {
        map[item.location].push(item);
      }

      return map;
    }, {});

  console.log({ locationAgeMap, locationLegalAgeOwnersMap });
})();

// vis dar sudėtinga, bet kompaktiškiau
(() => {
  const locationOwnersMap = devices
  .map(device => device.owner)
  .reduce((map, item) => {
    if (!map[item.location]) {
      map[item.location] = [item];
    } else {
      map[item.location].push(item);
    }

    return map;
  }, {});

  const locationAgeMap = Object.fromEntries(
    Object.entries(locationOwnersMap).map(([vieta, savininkai]) => {
      const ownersAge = owners.map(owner => owner.age).reduce((a, b) => a + b);

      return [vieta, ownersAge];
    })
  );

  const locationLegalAgeOwnersMap = Object.fromEntries(
    Object.entries(locationOwnersMap).map(([vieta, savininkai]) => {
      const filteredOwners = owners.filter(owner => owner.age >= 21);

      return [vieta, filteredOwners];
    }).filter(([_location, owners]) => {
      return owners.length > 0;
    })
  );

  console.log({ locationAgeMap, locationLegalAgeOwnersMap });
})();

Žinau, žinau - tai nėra triviali kodo dalis, kuri lengvai iliustruoja tai, ką noriu pasakyti. Taip pat žinau, kad šių dviejų pavyzdžių skaičiavimo sudėtingumas šiek tiek skiriasi, o 99% atvejų mums dėl to jaudintis nereikia. Skirtumas tarp algoritmų yra paprastas, nes abu jie parengia vietovių ir įrenginių savininkų žemėlapį.

Pirmasis šį žemėlapį parengia du kartus, o antrasis - tik vieną kartą. Ir paprasčiausias pavyzdys, kuris rodo mus kad antrasis algoritmas yra labiau perkeliamas, slypi tame, kad mums reikia pakeisti šio žemėlapio kūrimo logiką pirmajam algoritmui ir, pavyzdžiui, padaryti tam tikrų vietų išbraukimą ar kitus keistus dalykus, vadinamus verslo logika. Antrojo algoritmo atveju keičiame tik žemėlapio gavimo būdą, o visi kiti vėlesnėse eilutėse vykstantys duomenų pakeitimai lieka nepakitę. Pirmojo algoritmo atveju turime koreguoti kiekvieną bandymą gauti žemėlapį.

Tai tik pavyzdys - praktikoje yra daugybė tokių atvejų, kai reikia transformuoti arba pertvarkyti tam tikrą duomenų modelį visoje programoje.

Geriausias būdas išvengti įvairių verslo pokyčių - parengti visuotinius įrankius, kurie leistų gana paprastai išgauti dominančią informaciją. Net ir tų 2-3 milisekundžių, kurias galime prarasti deoptimizacijos sąskaita, kaina.

Santrauka

Programuotojo profesija yra tokia pati kaip ir bet kuri kita - kasdien mokomės naujų dalykų ir dažnai darome daug klaidų. Svarbiausia iš šių klaidų pasimokyti, tapti geresniu savo profesijos specialistu ir ateityje tų klaidų nebekartoti. Negalima tikėti mitu, kad mūsų atliekamas darbas visada bus nepriekaištingas. Tačiau galite, remdamiesi kitų patirtimi, atitinkamai sumažinti trūkumų skaičių.

Tikiuosi, kad perskaitę šį straipsnį išvengsite bent kai kurių bloga kodavimo praktika kuriuos patyriau savo darbe. Jei kiltų klausimų dėl geriausios kodo praktikos, galite kreiptis į The Codest įgula pasitarti dėl savo abejonių.

Skaityti daugiau:

Duomenų gavimo strategijos "NextJS

Žiniatinklio programos saugumas - XSS pažeidžiamumas

Interneto programų saugumas. Target=”_blank” pažeidžiamumas

*Pavadinimo grafika paimta iš speednet.pl

Susiję straipsniai

Išmaniojo telefono sveikatos priežiūros programėlės su širdies piktograma ir kylančia sveikatos diagrama, pažymėtos The Codest logotipu, iliustracija, vaizduojanti skaitmeninės sveikatos ir sveikatos technologijų sprendimus.
Programinės įrangos kūrimas

Sveikatos priežiūros programinė įranga: Sveikatos priežiūros paslaugos: tipai, naudojimo atvejai

Įrankiai, kuriais šiandien naudojasi sveikatos priežiūros organizacijos, nė iš tolo neprimena prieš kelis dešimtmečius naudotų popierinių kortelių. sveikatos priežiūros programinė įranga dabar padeda sveikatos sistemoms, pacientų priežiūrai ir šiuolaikiniam sveikatos priežiūros paslaugų teikimui klinikinėse ir...

GERIAUSIAS
Abstrakti mažėjančios stulpelinės diagramos su kylančia rodykle ir auksine moneta, simbolizuojančia ekonomiškumą arba taupymą, iliustracija. Viršutiniame kairiajame viršutiniame kampe pavaizduotas The Codest logotipas ir šūkis "In Code We Trust" šviesiai pilkame fone.
Programinės įrangos kūrimas

Kaip padidinti savo Dev komandą neprarandant produkto kokybės

Didinate savo kūrėjų komandą? Sužinokite, kaip augti neprarandant produkto kokybės. Šiame vadove aptariami ženklai, kad atėjo laikas didinti komandą, komandos struktūra, įdarbinimas, vadovavimas ir įrankiai - ir kaip The Codest gali...

GERIAUSIAS
Programinės įrangos kūrimas

Sukurkite ateičiai atsparias žiniatinklio programas: The Codest ekspertų komandos įžvalgos

Sužinokite, kaip The Codest puikiai kuria keičiamo dydžio interaktyvias žiniatinklio programas, naudodama pažangiausias technologijas ir užtikrindama vientisą naudotojų patirtį visose platformose. Sužinokite, kaip mūsų patirtis skatina skaitmeninę transformaciją ir verslo...

GERIAUSIAS
Programinės įrangos kūrimas

10 geriausių Latvijoje įsikūrusių programinės įrangos kūrimo įmonių

Naujausiame mūsų straipsnyje sužinokite apie geriausias Latvijos programinės įrangos kūrimo įmones ir jų inovatyvius sprendimus. Sužinokite, kaip šie technologijų lyderiai gali padėti pakelti jūsų verslo lygį.

thecodest
Įmonių ir didinimo sprendimai

"Java" programinės įrangos kūrimo pagrindai: A Guide to outsourcing Outsourcing Successfully

Išnagrinėkite šį esminį vadovą, kaip sėkmingai outsourcing "Java" programinę įrangą kurti, kad padidintumėte efektyvumą, įgytumėte patirties ir sėkmingai įgyvendintumėte projektus su The Codest.

thecodest

Prenumeruokite mūsų žinių bazę ir būkite nuolat informuoti apie IT sektoriaus patirtį.

    Apie mus

    The Codest - tarptautinė programinės įrangos kūrimo bendrovė, turinti technologijų centrus Lenkijoje.

    Jungtinė Karalystė - būstinė

    • 303B biuras, 182-184 High Street North E6 2JA
      Londonas, Anglija

    Lenkija - vietiniai technologijų centrai

    • Fabryczna biurų parkas, Aleja
      Pokoju 18, 31-564 Krokuva
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšuva, Lenkija

    The Codest

    • Pagrindinis
    • Apie mus
    • Paslaugos
    • Case Studies
    • Sužinokite, kaip
    • Karjera
    • Žodynas

    Paslaugos

    • Patariamoji tarnyba
    • Programinės įrangos kūrimas
    • Galinės dalies kūrimas
    • Priekinės dalies kūrimas
    • Staff Augmentation
    • Atgalinės versijos kūrėjai
    • Debesų inžinieriai
    • Duomenų inžinieriai
    • Kita
    • QA inžinieriai

    Ištekliai

    • Faktai ir mitai apie bendradarbiavimą su išoriniu programinės įrangos kūrimo partneriu
    • Iš JAV į Europą: Kodėl Amerikos startuoliai nusprendžia persikelti į Europą?
    • Technikos plėtros centrų užsienyje palyginimas: Tech Offshore Europa (Lenkija), ASEAN (Filipinai), Eurazija (Turkija)
    • Kokie yra svarbiausi CTO ir CIO iššūkiai?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Autorinės teisės © 2026 The Codest. Visos teisės saugomos.

    lt_LTLithuanian
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian is_ISIcelandic lt_LTLithuanian