Coder Social home page Coder Social logo

mluukkai.github.io's People

Contributors

mluukkai avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

mluukkai.github.io's Issues

Osa 1: Aneemiset funktiot ovat iso ongelma ohjelmoinnin opetuksessa, jos vältettäisiin niitä?

Kohdassa jossa sanotaan: "Tässä tilanteessa meidän onkin käytettävä yleistä Javascriptin ja yleisemminkin funktionaalisen ohjelmoinnin kikkaa, eli määritellä funktio joka palauttaa funktion"

Ymmärrän kyllä, että joskus on hyvä osata palauttaa funktio, mutta tämä ongelma ratkaisee filosofisesti väärän ongelman väärällä tavalla.

Setteri metodit edustavat aneemisia funktioita ja niitä käytetään usein argumenttina olio-ohjelmoinnin inferioriteettiin funktionaaliseen ohjelmoimiseen; valitettavasti kyseessä on eräänlainen olkiukko: settereitä ei pitäisi ikinä joutua käyttämään olio-ohjelmoinnissa, koska silloin monet hyvät periaatteet jää käyttämättä ja koodia uudelleenkäytetään väärin ("laiskasti" ja "epäadaptiivisesti", jolloin muutoksien tekeminen hidastuu).

Todellisissa ohjelmissa funktioiden tulisi puhua domain kieltä ja suorittaa structeille transformaatioita, eikä asettaa niiden propertien arvoja. Transformaation parametrit ovat usein määriteltävissä viitteillä, eivätkä sinäänsä tarvitse tyypitettyjä argumentteja. Tyypitettyjen argumenttien yleiskäyttöisyys johtuu lähinnä siitä, että olio-ohjelmointia opetetaan väärin.

Kyseisessä React ohjelmassa olet tehnyt sen virheen, että exposaat ulospäin muutoksen, joka ei ole tarpeellinen: haluat inkrementoida yhdellä tai asettaa nollaksi, mutta toteutat uudelleen käytettävän funktion, joka pakottaa argumentin käyttöön aneemisen rajapinnan vuoksi. Olio-ohjelmoinnin idea on enkapsuloida dataa epäaneemisten metodien taakse, eikä toteuttaa koodaus APIa, joka mahdollistaa olion ulkopuolisten asioiden muuttaa sen sisäistä tilaa.

Oikeampi tapa olisi hyödyntää Inversion of Control periaatteita: koska napin painallus laukaisee eventin, nappi tarvitsee viittauksen eventtiin. Miten paljon kyseinen nappi muuttaa tilaa, riippuu siitä, mitä nappi on syönyt konstruktorissaan: Epäaneeminen nappi osaa inkrementoida tai dekrementoida arvoa luvulla X tai asettaa arvon lukuun X. Komponentti joka käyttää (immutablea) nappia, ei itse määrittele sen funktiota, vaan se voi ottaa minkä tahansa napin sisään omassa konstruktorissaan (ja lukea miten paljon juuri tämän napin painallus muuttaa tilaa) tai toisinpäin, eli komponentti on itse määritelly rajapinnan muutoksille, joita napit voivat suorittaa sille epäaneemisten funktioviittausten avulla (setToZero, incrementByOne).

Tämä on oikeastaan mielestäni se ydin ongelma ohjelmoinnin opettamisessa ja suurin syy, minkätakia funktionaalinen- vs olio-ohjelmointi riita on mielestäni lähinnä keinotekoinen vastakkainasettelun väline, koska se perustuu fundamentaaliseen väärinkäsitykseen sen suhteen, minkälaisia ovat hyvä kompleksiset ohjelmat.

Hyvä kompleksinen ohjelma ei anna olioidensa määritellä miten ne tekevät muutoksia (esim. changeState(state + 1) ), vaan hyvät kompleksiset ohjelmat antavat olioidensa määritellä mitä niille voidaan tehdä (esim. interface changeState(), jossa eventin sattuessa composition omistava olio muuttuu compositiona elävän olion ominaisuuksien mukaan; tai composition omistava olio omistaa sallitut muutokset interfacena, jota compositiossa elävän olion pitää noudattaa).

Aneemiset funktiot johtavat usein transaktioihin, jotka eivät skaalaudu oikeassa maailmassa tai ole ylläpidettävissä. Käsittääkseni ongelma ulottuu niin pitkälle, että se osittain selittää miksi pankit eivät käytä hajautettuja ACID tietokantoja, vaan turvautuvat BASE-arkkitehtuurin mukaisiin järjestelmiin.

Eli jos ei välttämättä opettaisi opiskelijoita ajattelemaan "väärin" ja "funktionaalisesti", vaan pyrittäisiin myös osoittamaan, että ongelman voi ratkaista oikeaoppisesti funktioreferenssien avulla ja oliopohjaisesti ilman parametreja.

En sano, että tulisi sanoa, että tämmöinen on se "ainoa oikea tapa", koska joskus on kiva tehdä asioita helposti, mutta on myös äärimmäisen tärkeää tietää, miten asia tehtäisiin oikein ilman aneemisia funktioita. Mikään ei ole ollut työelämässä palkitsevampaa, kuin saada joku huomaamaan, että aneemiset funktiot ovat ongelma ja niistä eroon refaktoroiminen tekee kompleksiselta tuntuvasta koodista äärimmäisen luettavaa ja parhaillaan johtaa deklaratiiviseen systeemiin, jonka ominaisuudet voidaan konffia kasaan, eikä kova koodata.

Myönnän että tämä on hieman saivartelua, mutta mielestäni myös ensiluokkaisen tärkeä näkökulma; aneemiset funktiot ovat yksi tärkeimmistä antipatterneista.

Osa 4: Ympäristömuuttujan asettaminen package.jsonissa ei onnistu suoraan Windowsilla

Kohdassa "test-ympäristö" on seuraava pätkä:

{
  // ...
  "scripts": {
    "start": "NODE_ENV=production node index.js",
    "watch": "NODE_ENV=development node_modules/.bin/nodemon index.js",
    "test": "NODE_ENV=test node_modules/.bin/jest --verbose test"
  },
  // ...
}

Windowsilla NODE_ENVin asettaminen ei onnistu suorilta käsin tällä tavalla. Ratkaisuna on ladata npm package cross-env (https://www.npmjs.com/package/cross-env) ja sen avulla asettaa ympäristömuuttujat:

{
  // ...
  "scripts": {
    "start": "cross-env NODE_ENV=production node index.js",
    "watch": "cross-env NODE_ENV=development node_modules/.bin/nodemon index.js",
    "test": "cross-env NODE_ENV=test node_modules/.bin/jest --verbose test"
  },
  // ...
}

Osa1: Kehitysympäristön valinta

Sanotaan: "Asenna myös joku järkevä webkoodausta tukeva tekstieditori, enemmän kuin suositeltava valinta on Visual studio code. Myös Atom on tarkoitukseen toimiva.

Älä koodaa nanolla, notepadilla tai geditillä. Netbeanskaan ei ole omimmillaan Web-koodauksessa ja se on myös turhan raskas verrattuna esim. Visual Studio Codeen."

Yksi varteen otettava vaihtoehto on pilvinatiivi Cloud 9, jonka opetuslisenssi ei vaadi opiskelijalta luottokorttia.

Pilvinatiivilla kehitysympäristöllä on helpompaa testata HTTPS:ää, sekä joidenkin thirdparty paveluiden (esim. Googlen OAuth2.0) käyttöä, jotka vaativat oikean top-level domainin toimiakseen. Toki Cloud 9 vaatii vanhoilta devaajilta hieman totuttelua, kun paradigma on erilainen.

Itse olen devannut Cloud 9:llä jo yli kaksi vuotta, koska Dockerisoinnit ovat usein "ongelmattomia", mutta käytännössä Windows koneilla ne eivät toimi ja Macillä imaget menee rikki käyttöjärjestelmäpäivitysten yhteydessä. Lisäksi viimeisimmässä projektissa, jossa olen tehnyt Micro Service + Micro Frontend tyylistä systeemiä, Dockerin imagejen buildaamiseen menee yli 11 minuuttia ja käynnistämiseen hieman yli minuutti -> oikean imagen devaaminen on helpompaa ja kivempaa ja jos Dockeria on pakko käyttää, on hyvä, että se jää päälle virtuaalipalvelimelle, koska läppärin joutuu aina työpäivän päätteeksi sammuttamaan (hibernation tilat ja muut "väärin sammutukset" saattavat korruptoida Docker containerit, jolloin pitää tehdä rebuildi).

Cloud 9 on tuntunut yhtä hyvältä Docker + Mac kombon jälkeen, kuin Golang NodeJS:än jälkeen, eli ero on massiivisen mukava, kun asiat vaan toimii oikeasti, eikä leikisti.

Osa 1: Selvennystä HTTP POST + 302 käyttötapauksista

Kun koodataan esimerkiksi RESTful APIa vasten, on tyypillistä, että POST requestiin vastavaan 302:lla, koska RESTful paradigman mukaan, POST edustaa CRUD-periaatteen Createa.

Idea ei kuitenkaan ole siinä, että 302 sisältäisi POST bodyn, koska siitä ei ole mitään hyötyä HTTP protokollan käyttötarkoitusten näkökulmasta. Itseasiassa POST bodyn lähettäminen 302:n mukana on bugi ja HTTP-standardin vastainen ominaisuus.

Carnary Chromen tulkinta standardista on siis virheellinen, eikä kyseistä "bugia", jossa POST body tipahtaa pois 302:n jälkeen, tulla ikinä korjaamaan; HTTP-speksissä sanotaan "MUST NOT repost without user prompt".

POSTin tarkoituksena on oikean HTTP-semantiikan mukaan luoda uusi Unique Resource, ja jotta tähän uuteen resurssiin voitaisiin viitata, on 302 hyvä tapa vastata POST requestiin: Unique Resource vastaan otettu ja luotu, löydät sen tämän Unique Resource Identifierin (uri) takaa.

Fullstack devaamisessa olisi hyvä tuoda esiin tätä RESTful APIen maailmaa ja HTTP:n semantiikkaa CRUD pohjaisena protokollana. URI on siis eräänlainen pointteri ja POST requestin ei ole pakko aina vastata dataobjektilla (200 + JSON) vaan pointterikin käy.

Tämän vuoksi Preserve Logs täpän ruksittaminen on hyvä idea, koska jotkut RESTful palvelut käyttävät pointteritulkintaa oikeaoppisesta HTTPn käytöstä. Lisäksi sillä on tärkeä implikaatio: POST kyselyn vastaanottava palvelin ei voi tietää, onko lähetys duplikaatti. Jos normaalissa ohjelmassa suoritettaisiin Factory patternia, joka palauttaisi dataa referenssin sijaan, ei voitaisi laskea objektien määrää palautusarvojen perusteella ilman naivia oletusta, että koodissa ei ole virheitä.

Tämmöinen design patternikin on olemassa, kuin POST / REDIRECT / GET: https://en.wikipedia.org/wiki/Post/Redirect/Get

Osa 5: Frontendin testauksen alkeet (mochalla)

Tässä asennusohjeet miten react-sovelluksia voi testata käyttäen seuraavia kirjastoja

  • Mocha
  • Chai
  • Sinon
  • Enzyme

Seuraavat ohjeet tulisi suorittaa, kun materiaalissa ensimmäisen kerran aletaan tehdä testejä enzymeä käyttäen (mikäli jest ei syystä tai toisesta toimi ja on jo osassa 4 joutunut käyttämään mochaa). Sinonia tarvitsee mock-funktioiden tekemiseen, joiden käyttö tulee myöhemmissä testeissä vastaan.

Tee src/ -kansion alle setupTests.js

import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

configure({ adapter: new Adapter() })

Asenna seuraavat npm-paketit:

npm install --save-dev mocha
npm install --save-dev chai
npm install --save-dev sinon
npm install --save-dev enzyme enzyme-adapter-react-16
npm install --save babel-preset-react-app
npm install --save cross-env
npm install --save-dev --save-exact jsdom jsdom-global

Lisää package.jsoniin tämä:

"babel": {
  "presets": [
    "react-app"
  ],
  "plugins": [
    "transform-es2015-modules-commonjs"
  ]
}

Lopuksi kirjoita package.jsonin test skriptiksi tämä:

"test": "cross-env NODE_ENV=development mocha -r jsdom-global/register -r ./src/setupTests.js --compilers js:babel-core/register src/tests/*.test.js"
  • Tee testit src/tests/ -kansion alle
  • Aja komennolla npm test

ks.
https://www.codementor.io/daveschinkel13/running-mocha-enzyme-with-creat-react-app-84flnngkk
https://gist.github.com/busypeoples/409a34199a3dd7ceacffe25ac6c10547

Osa 1: Chrome konsolinkäytöstä

Disable Cachen lisäksi Preserve Logs täppä on myöskin osoittautunut äärimmäisen hyödylliseksi, kun käytetään OAuth2 tyylisiä palveluita autentikoinnissa tai maksujärjestelmissä. Siitä ei useinkaan ole haittaa, logien clearaus on helppoa.

Osa1: "Käytä Chrome Carnaryä"; kyseessä ei ole bugi vaan HTTP 1.1 standardi

Sanotaan: "Erään Chromessa olevan, hieman sovelluskehitystä haittaavan bugin takia kaikkein suositeltavinta on Chromen ns. canary-version käyttäminen."

Kyseinen "bugi" ei ole bugi, vaan HTTP-standardin mukainen ominaisuus:
"If the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued." -HTTP 1.1 standardi.

Monet selaimet tiputtavat POST requestin bodyn tästä syystä ja tuota "bugia" ei tulla ikinä korjaamaan. Käsittääkseni myös wget ja curl (GNU versiot) jättävät bodyn matkalle, jos tulee 302 (ainakin löytyy stackoverflow threadit näistä).

Fullstack devaamisen tärkeimpiä juttuja on standard compliance, joten Chrome Carnaryn käyttö devauksen helpottamiseksi, perustuen väärään HTTP-standardin tulkintaan, on ikään kuin huono idea :) ... devausta helpottavat "kirjastot", jotka eivät noudata standardeja, ovat juuri se syöpä minkä vuoksi NodeJS, Python ja jotkin PHP frameworkit "mätänevät" kovaa vauhtia, kun ongelmat ratkaistaan väärin ja väärät ratkaisut jäävät elämään osaksi teknologian historiaa.

Osa 1: var, let ja const

Tässä kohtaa olisi ehkä hyvä avata, että miksi var on historiallisista syistä olemassa ja miten sen variable scope eroaa letistä.

Osa 1: XMLHttpRequest vs Fetch API

FullStack devaamisen suurimpia kipuja on ollut JavaScriptin callback hell-tyyliset ratkaisut. XHR on standardi vuosimallia 1999 ja Fetch on promisepohjainen ratkaisu vuosimallia 2014. Toki Fetch ei tue kaikkia selaimia vielä, mutta osittain kai siksi, ettei Microsoft enää oikein jaksa devata IE:tä, kun on Edge.

Siinä kohtaa, kun opiskelijat valmistuvat työelämään, uskon ettei Fetchin käytöstä ole haittaa ja lisäksi opiskelijat tottuisivat parempaan koodaustapaan (promiset, async / await) jo heti kättelyssä. Vaikka me olemme marssineet läpi callback helvetin, ei sen olemassa olosta välttämättä tarvitse uutta sukupolvea muistuttaa, kun ongelma alkaa pikkuhiljaa olemaan ratkaistu :)

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

Windows ongelmat

Useat opiskelijat törmänneet ongelmiin windowsin kanssa. Esimerkkejä windowsin käyttöön.

"start": "API_URL=http://localhost:3100 node scripts/start.js",
muuttuu
"start:win": "set API_URL=http://localhost:3100&&node scripts/start.js",

Ja

"test": "cross-env NODE_ENV=test node_modules/.bin/jest --verbose test",
muuttuu
"test": "cross-env NODE_ENV=test jest",
tai
"test": "jest --verbose"

Osa1: Oppimistavoitteet; Autentikaatiosta voisi sanoa pari sanaa

Signed Cookies tyyliset ratkaisut ovat tulleet jäädäkseen, joten OAuth 2 yms. autentikaatio prosessit, sekä signed cookieiden varaan rakentuvat tavat jakaa salaista dataa webissä, ovat tärkeä osa nykyaikaista Full-Stack devaamista, etenkin pilvinatiiveissa projekteissa.

Esimerkiksi elokuva-alalla suunnitellaan tiedostoformaatteja, jotka perustuvat security certificate providereihin, sekä palvelimiin, joilla on lupa jaella käyttäjille signed-cookieita, sekä lisäksi CDN + AWS S3 tai GCS palveluun, joka sisältää adaptiiviset striimitiedostot, jotka dekoodaantuu ainoastaan certin ja signed-cookien yhdistelmällä (eli hieman samaan tapaan kuin public ja pricate key jutut).

Toki tämä saattaisi istua paremmin osaan 6.

Osa 1: SPA vs Pilvinatiivit sovellukset

Tässä SPA osiossa olisi ihan hauska mainita myös pilvinatiiveista sovelluksista, jotka eivät enää lähetä edes JSONia, vaan pelkät muutokset käsiteltävään URI viitteeseen. Vaikka pilvinatiivi fullstack devaaminen ei olisikaan tämän kurssin skopessa, olisi hauskaa näyttää opiskelijoille tämä trendi:

Staattiset sivulataukset -> dynaamiset sivulataukset -> SPA + RESTful, eli JSON lataukset -> pilvinatiivit pavelut, joissa lähetetään ainoastaan käyttäjän tekemät muutokset.

Yksi tapa ajatella tätä trendiä on tarkastella sitä, että kuka on käyttäjä:
Kukatahansa, jolla on linkki -> kuka tahansa + täysivaltaisempi HTTP-stäkin käyttö -> Selkeästi määritelty selain -> Selkeästi määritelty käyttäjä, jolla on selaimen lisäksi identiteetti (wallet).

EU:ssa GDPR lainsäädäntö tulee viemään palveluita enemmän Wallet tyylisen palvelutarjoilun suuntaan, koska ilman selkeästi määriteltyä Wallettia, EU:n kansalainen voi pyytää palveluntarjoajaa tuhoamaan tietoja, jotka ovat sotkeutuneet käyttäjän Walletin ulkopuoliseen dataan, mutta kuuluvat silti käyttäjälle.

Eli muutamalla sanalla ehkä hieman historiaa ja todennäköisiä tulevaisuuden trendejä. En tiedä yhtäkään pilvinatiivia tekstieditoria, joka ei toimisi muutoksia tallentamalla, vaan toimisi yhä RESTful + SPA arkkitehtuurilla.

Osa 1: Java ja JavaScript

Tämä osio jossa puhutaan Javan ja JavaScriptin syntaksin samankaltaisuudesta kuulostaa lähinnä hämmentävältä; mielummin varmaan vain alleviivaisin, että vaikka JavaScriptin nimessä on Java mainittu, ei kielillä ole muilta osin juuri mitään yhteneväisyyskiä edes perustietotyyppien käsittelyn kanssa (array vs object). Java on kovasti tyypitetty imperatiivinen kieli, JavaScript on jotain ihan muuta, jota kutsutaan EcamScriptiksi, joka on prototypaalinen multi-paradigma kieli.

Osa1: Ubuntun paketinhallinnasta ja nvm:stä

Sanotaan: "Asenna koneeseesi heti myös Node.js. Materiaali on tehty versiolla 8.6, älä asenna mitään sitä vanhempaa versiota. Ubuntulla Node.js:ää todennäköisesti ei kannata asentaa pakettienhallinnasta eli apt-get:illä, sillä sieltä saatava versio on antiikkinen."

Jos en muista väärin, niin Ubuntulla asennettu NodeJS käyttää nvm:ää, jossa defaultti on 4.6 NodeJS ja latest stable on NodeJS 8.6; eli nvm:llä on kätevää vaihtaa käytössä olevan Noden versiota. Tämän olen testannut Googlen pilvessä Ubuntu 16.04 imagea vastaan pari viikkoa sitten työelämässä; jos siis muistini ei ole petollinen tässä kohtaa. Usein nykyään NodeJS tulee nvm:än kanssa ja vanha defaultti versio on ihan yleinen juttu.

Osa 1: Taulukot ja oliot

Vaikka prototypaalisen kielen ominaisuuteen kuuluu, että kaikki datatyypit ovat olioita, on mielestäni hyödyllistä viljellä sellaista ajattelutapaa, jossa taulukot ja oliot ovat eri asioita; jos joku opiskelija saa tästä idean, että taulukoita voi manipuloida niiden olio ominaisuuksia käyttäen, opiskelija tulee ampumaan itseään pahasti jalkaan.

Lisäksi kannattaa varoittaa siitä, että arraytä tulisi aina manipuloida pushin yms. metodien kautta, sekä käyttää ainoastaan numeroituja indeksejä, eikä assosiatiivisia indeksejä, koska assosiatiivinen indeksi muuttaa arrayn objektiksi ja resetoi lenghtin yms.: https://www.w3schools.com/js/tryit.asp?filename=tryjs_array_associative_2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.