Vahva tyypitys on kuollut

Monday, December 14th 2009 at 13:47 in Technology, NoSQL

Olen nyt tehnyt muutaman harrasteprojektin kahdella staattisesti tyypitetyllä kielellä: Scalalla ja Go:lla. Molemmissa tapauksissa olen törmännyt kohtuuttomiin hankaluuksiin heti, kun pitäisi käsitellä JSON-muotoista dataa.

Staattisen tyypityksen perusongelma on, että se vaatii kaikkien tietorakenteiden olevan ennalta määritellyn tyypityksen mukaisia. Esimerkiksi JSON-rakenne voi kyllä olla tällainen:

{ "title":  "Otsikko",
  "text":   "Teksti",
  "author": "Kirjoittaja" }

Ylläoleva rakenne voitaisiin kuvata Go:ssa tyypillä map[string]string tai Scalassa tyypillä Map[String, String].

Mutta heti, jos jokin kentistä on vähän erilainen, tulee ongelmia:

{ "title":   "Otsikko",
  "text":    "Teksti",
  "authors": ["Kirjoittaja 1", "Kirjoittaja 2"] }

Tuollainen rakenne kun ei vastaa enää mitään staattista tyypitystä. Go:ssa täytyy käyttää geneerisiä interfaceja eli tyyppiä map[string]interface{} ja Scalassa taas Any-tyyppiä muodossa Map[String, Any].

Tämä taas aiheuttaa, että kenttien arvoja ei voi enää lukea suoraan tyyliin authors := json["authors"], vaan ne pitää typecastata tai assertoida erikseen tyyliin authors, ok := json["authors"].([]string). Tästä seuraa sitten hirvittävää monimutkaisuutta, kun käsitellään sisäkkäisiä hierarkioita ja taulukoita.

Johtopäätökseni tästä kaikesta on, että staattisesti tyypitetyt kielet eivät kerta kaikkiaan sovi nykyaikaiseen web-ohjelmointiin, jossa käsitellään dynaamisia tietorakenteita.

Pystyn myös hyvin näkemään, että Javalla tai C#:llä pääasiallisesti ohjelmoivat henkilöt eivät arvosta JSONia läheskään niin paljon kuin esimerkiksi Python-koodaajat, koska se ei "istu" mukavasti kieleen. Tästä seuraa myös, että CouchDB:n ja MongoDB:n kaltaisten NoSQL-tietokantojen käyttö on kovin hankalaa, koska niiden koko idea perustuu dynaamisiin JSON-rakenteisiin.

Kannattaa siis luopua staattisesti tyypitetyistä kielistä nyt, ettei jää ikuisesti jumiin SQL:n ja XML:n rajoittuneeseen maailmaan!

[Update: Puhuin alun perin hieman sekaisin staattisesta ja vahvasta tyypityksestä. Olen tietoinen näiden eroista, ja viittaan tässä lähinnä staattisen tyypityksen ongelmiin. Korjasin sanamuodon pariin kohtaan mutta jätin otsikon ennalleen.]

81 Comments
Aki Björklund 14.12.2009 14:42:07

Itse asiassa C# ei ole ollenkaan niin kömpelö kun luulet ja istuu erinomaisesti kieleen – nykyisin. Esimerkiksi ASP.NET MVC:ssä palautetaan JSON-vastaus näin:

return JSON(new { nimi = "arvo", nimi2 = "arvo2" });

…jossa nimi ja nimi2 voivat olla ihan ennalta määräämättömiä.

Kennu 14.12.2009 14:46:49

Aki: Entä JSONin parsiminen?

Aki Björklund 14.12.2009 15:02:43

Tietääkseni deserialisointi onnistuu ennalta määrättyyn tyyppiin tai vain objektiksi onnistuu kyllä, mutta voisin kuvitella dynaamisten propertyjen aksessoinnin olevan rumaa. 4.0:n dynamic-tyyppi ratkaissee tuonkin ongelman.

…näyttäisi siltä, että olin oikeassa, ensimmäinen googletus toi tällaisen tuloksen:

http://www.nikhilk.net/CSharp-Dynamic-Programming-JSON.aspx

Vesa Marttila 14.12.2009 15:26:33

Puhutaanko nyt siis tyypityksen vahvuudesta vai siitä onko se staattinen vs. dynaaminen? Pythonhan esimerkiksi on vahvasti, mutta ei staattisesti tyypitetty.

Kennu 14.12.2009 15:54:48

Vesa: Tarkoitin staattista tyypitystä, mutta otsikosta ja joistakin lauseista tuli vähän kärkevämpiä puhumalla vahvasta tyypityksestä sekaisin.

Kennu 14.12.2009 15:58:00

Aki: Tuota juuri ajoin kirjoituksellani takaa, että staattisesti tyypitetyissä kielissä pitää etukäteen tietää täsmälleen sen tietorakenteen muoto. Tai sitten typecastailla rumasti jälkeenpäin.

Pythonissahan voi sanoa vain article = simplejson.loads("{ ... }") ja sitten äccessöidä kenttiä vapaasti tyyliin article['authors'][0] jne. Pythonin duck typing huolehtii siitä, että virheellisestä datasta nousee Exception, mutta koodi voi kuitenkin olla yksinkertaista.

Mikael Gueck 14.12.2009 18:23:24

Vai että Kennultakin tätä bullshait hypeä oikein tuutin täydeltä.

Koska on tyypillinen käyttötapaus, että saadaan määrittelemättömässä, tai itseään kuvaamattomassa formaatissa, viesti, jota halutaan käsitellä sen merkityksen mukaisesti.

Kennu 14.12.2009 18:43:00

Mikael: Mikäs tässä nyt oli hypeä? Tämä on ihan jokapäiväinen tilanne monissa projekteissa, joissa tietoa välitetään JSON-muodossa eri komponenttien välillä tai varastoidaan tietokantaan ja myöhemmin luetaan sieltä.

Mikael Gueck 14.12.2009 18:52:39

Scala, funktionaalinen suitsutus, NoSQL... jutut joita tehdään samasta syystä kuin aikanaan poltettiin poikien kanssa koulun takana tupakkia välitunnilla.

Kun JSON:illa viestitään tietoa, viestillä on yleensä hyvin spesifinen formaatti, koska kysytään jotain spesifistä asiaa, joka sitten halutaan näyttää käyttäjälle. Viestillä on siis varsin staattinen tyyppi. Jokainen voi itse päättää, haluaako käyttää työkaluja jotka tukevat staattista tyypitystä, kun joka tapauksessa sitä käyttävät.

Kennu 14.12.2009 18:58:35

Mikael: Ja entä mitä sitten tehdään, jos ohjelmointikielen staattinen tyyppisysteemi ei pysty kuvaamaan sitä tietorakennetta, joka JSON-viestissä on? Kuten esimerkiksi tuossa alkuperäisessä esimerkissäni kävi, ja se oli sentään vielä hyvin yksinkertainen tapaus.

Yleisesti ottaen staattinen tyypitys ei taivu sellaisiin tilanteisiin, joissa käsitellään sisäkkäisiä vapaamittaisia listoja ja assosiatiivisia arrayta, joissa on vaihteleva määrä jäseniä.

Sinulla tuntuu olevan pientä muutosvastarintaa näihin juttuihin, vaikka niistä on oikeasti hyötyä ohjelmoinnin tuottavuuden tehostamisessa. :-)

Apo 14.12.2009 19:27:13

Eikös tuossa esimerkissä ole vikana esimerkissä käytetyn rajapinnan kömpelyys eikä niinkään kielen rajoitteet?

Kyllähän javallakin voi tehdä JsonObjektin joka tuottaa geneeriseltä vaikuttavia objekteja syöttödatan perusteella:

List authors = json.get("authors")

Tuossahan menettää kyllä tyypityksen edut, mutta tiedon käyttäjäpään tekemisen saa hieman kevyemmäksi jos data esimerkiksi vain tulostetaan.

Mikael Gueck 14.12.2009 19:28:08

Tuossa esimerkkitapauksessasi kyse ei ole siitä etteikö esimerkiksi Java taipuisi käsittelemään tuota viestiä, vaan siitä ettei tapa käsitellä viestiä ole tarkalleen se, minkä ensimmäiseksi sait päähäsi.

Triviaali ratkaisu on käyttää tilanteissa, jossa kirjalla voi olla yksi tai useampi kirjoittaja, aina listaa. Helppo tapa luoda JSON:ista Java/C# objekti on käyttää mitä tahansa sadoista valmiista kirjastoista jotka tekevät tästä triviaalia.

Minulla on muutosvastarintaa tähän huuhaaseen samalla tavalla kuin kreationismiin - asiat joita tehdään siksi että niihin halutaan uskoa ovat minulla eri kategoriassa kuin asiat joiden hyödyllisyydestä on todella näyttöä.

Funktionaalinen paradigma (sanon tämän henkilönä joka on kirjoittanut urallaan Lispiä rahasta, ja isäni kirjoittaa sitä edelleen) hävisi, koska sen toteutukset tarjosivat koodareille huomattavasti enemmän vapausasteita, kuin mitä tarvitaan siihen, että rakennetaan tuotteita joista on bisneshyötyä, ja jokainen vapausaste maksaa ohjelmiston joka elinkarren vaiheessa maltaita.

Mutta hei, tervemenoa vaan ylläpitämään vuosiksi jonkun Pythonilla koodaamaa softaa, jonka käyttämät kirjastot monkeypatchaavat niin rumasti, että softan toiminta muuttuu totaalisesti riippuen siitä, missä järjestyksessä kirjastot ladataan. Tai no, en usko että meinaat niin tehdä.

Kennu 14.12.2009 19:41:14

Apo: Eikö tuossa juuri jouduta typecastaamaan, jos json.get() on geneerinen metodi, joka palauttaa Objectin. Siis näin:

List authors = (List ) json.get("authors")

Jossain vähän monimutkaisemmassa tietorakenteessa se paisuu sitten muotoon

List authors = (List ) ((HashMap ) json.get("article")).get("authors")

Jne... Eli menee ihan toivottomaksi dynaamisesti tyypittäviin kieliin verrattuna. Tämä oli se pointti kirjoituksessani.

Mikael Gueck 14.12.2009 20:23:27

http://dev.gueck.com/code-examples/wiki/KennuIsWrong

Kennu 14.12.2009 20:29:27

Mikael: Esimerkkisi kuvaa mallin, jossa kentät ja tyypit ovat kiinteät (title, text, authors). Minun esimerkissäni niiden määrää ja nimiä ei ole etukäteen päätetty (HashMap ), vaan vasta ohjelman ajon aikana voidaan hakea mitä tahansa kenttää.

Kennu 14.12.2009 20:35:18

Mikael: Lisäksi pitänee huomauttaa, että jouduit juuri koodaamaan yli 10 riviä Java-koodia useaan eri tiedostoon toteuttaaksesi saman asian, jonka itse tein Pythonilla yhdellä rivillä. ;-)

Mikael Gueck 14.12.2009 20:38:17

Minulla ei vielä harmi kyllä ole pääsyä sellaiseen tekoälyohjelmistoon, joka osaisi itsekseen rakentaa ohjelmistoja, vaan kyllä pääsääntöisesti ihmiset joutuvat määrittelemään rajapintoja, jotka sitten julkaistaan ja joita käytetään.

Joudumme yleensä viemään tämän jopa niin pitkälle, että meidän pitää tietää ihan spesifinen palvelin, jolta sitten tietyllä varsin hyvin määritellyllä tavalla kysytään spesifistä asiaa joka halutaan tietää.

Tämä on se käyttötapaus, jota vastaan ainakin itse arvioin työkaluni. Ehkä sitten kun tulee sellainen käyttötapaus jossa on tarvis kysyä tuntemattomasta paikasta tuntematonta asiaa, jonka merkitystä en tunne, mutta jota kuitenkin haluan käsitellä sen spesifisen merkityksen kautta, esimerkiksi hakea jotain tiettyä kenttää, joudun funtsimaan ovatko työkalut riittäviä.

Heimo Laukkanen 14.12.2009 20:38:33

Mikaelin koodiesimerkki on hieno näyte siitä, miten javallakin saadaan hyviä kirjastoja käyttämällä aikaiseksi joustavaa, selkeää ja hyvin hallittavaa koodia. Epäreiluksi tilanteen tekee se, että Mikael on pitkän linjan ammattilainen joka saa vanhan C tai Lisp-koodinkin näyttämään hyvälle.

Minä pidän pythonista skriptikielenä, mutta arvostan enemmän todella hyvin toimivaa ja luottamuksen arvoista java-infrastruktuuria, joka tekee sen mitä lupaa ja suojaa ohjelmoijaa ampumasta itseään tai kaveriaan hirveän pahasti jalkaan.

Millä tahansa kielellä ja ympäristöllä pystyy suunnittelemaan ja tekemään vaikeasti ylläpidettävää jälkeä. Toiset ympäristöt vain tekevät siitä helpompaa. Väitän että robustin ja hyvän python-järjestelmän kirjoittaminen on vaativampaa kuin saman työn tekeminen javalla, sillä python antaa ohjelmoijalle niin paljon vapauksia.

Tämä sanottuna siitäkin huolimatta, että parhaillaan integroin yhdessä projektissa pythonin skriptikieleksi java-infrastruktuuriin ( Jython ) ja koodaan huvikseni työpöytäsovellusta PyQT:ta käyttäen.

Kennu 14.12.2009 20:44:17

Mikael: "Tekoäly" tulee nopeasti eteen esimerkiksi siinä tilanteessa, että tietokantaan on tallennettu vanhoja artikkeleita, joissa "author"-kenttä on merkkijono, mutta uudemmissa se onkin muuttunut string-arrayksi. Kun tällaisia muutoksia kumuloituu ajan mittaan jatkuvasti lisää (kuten dynaamisesti kehittyvässä webbipalvelussa yleensä käy), eikö käy aika työlääksi yrittää hallita niitä tekemällä jokaista variaatiota varten oma staattinen Java-luokka?

Toisin sanoen yrität argumentoida, että dynaamisten tietorakenteiden puuttuminen ei haittaa, koska dynaamisia tietorakenteita ei tarvita ylipäätään. Minä taas väitän että niitä tarvitaan, ja että ne ovat jopa elinehto nopeasti kehittyville palveluille.

Mikael Gueck 14.12.2009 20:46:41

Eiköhän jätetä tämä tähän.

Heimo Laukkanen 14.12.2009 20:56:04

Olisi pitänyt katsoa sun tageista, että ajattelet asiaa NoSQL-kulmasta ja key-value data storetuksesta.

Tuossa tulet jo hienosti yhteen ongelmaan NoSQL-mallin kanssa, eli mitä tapahtuu kun datamallit elävät. Välttämättä hyvä vastaus ei ole kumuloituva hack-logiikka clientteihin. Valitettavasti olen nähnyt tätä problematiikkaa tuotannossa - ja poistanut sellaisen tuotannosta.

Kennu 14.12.2009 20:58:42

Huima: Olen samaa mieltä siitä, että infrastruktuurin/kirjaston/frameworkin on syytä olla stabiili ja jämäkkä. Sitten taas sovelluskoodin pitää olla mahdollisimman kevyttä ja yksinkertaista, jotta kehitystyö on nopeaa ja joustavaa ja kuitenkin bugitonta. Parhaimmillaan sovellus tehdään melkein kokonaan DSL-kielellä, joka on erityisesti suunniteltu juuri siihen tarkoitukseen. Vrt. Djangon tietokantamallit.

Toistaiseksi en ole havainnut, että Python olisi infrastruktuurin kehittämisessä epäluotettavampaa kuin Java tai jokin muu staattisesti tyypitetty kieli. Sen sijaan siinä on kyllä kiistattomia etuja, kuten metaclassien ja joidenkin muiden ominaisuuksien mahdollistamat keinot toteuttaa noita DSL-kielimäisiä rajapintoja sovellusohjelmoijien käyttöön.

Pythonissa pitää ehkä lähinnä miettiä testausta vähän enemmän kuin Javassa. Pythonin kääntäminen tarkistaa vain syntaksin; datatyyppien oikeus voidaan todeta vasta ajamalla koodi kertaalleen test-casejen läpi.

Kennu 14.12.2009 21:01:16

Samaa mieltä, että dynaamisten datamallien eläminen on ongelma, joka kaipaa fiksuja ratkaisuja. Olen kuitenkin melko varma, että erillinen staattinen tyypitys datamallin jokaiselle sukupolvelle EI ole se oikea ratkaisu. Ehkä enemmänkin tarvitaan sellaisia sääntöjä, että esimerkiksi aiempaa datatyyppiä ei vaihdeta, vaan ainoastaan lisätään uusia kenttiä, jotka vanha koodi voi turvallisesti ignoroida.

Heimo Laukkanen 14.12.2009 21:16:16

Datarakenteiden haasteet ei ole mikään uusi kysymys, siitähän lähdetään liikkeelle kun järjestelmiä rakennetaan. Jos mallit muuttuvat ja niitä tallennetaan NoSQL storageen, alkaa rakenteiden muuttuminen olla ongelma - koska on vain kaksi vaihtoehtoa: 1) dynaaminen tulkinta 2) objektien konversio datarakenteen muuttuessa.

Relaatiokantojen kanssa elävät eivät koe näitä ongelmia, koska hyvää tietomallia on myös helppo muuttaa ja SQL antaa työkalut datan manipulointiin helposti ja tehokkaasti. Ja tuhannet ja tuhannet ihmiset ovat käyttäneet aikaa taatatkseen, että speksattu toimenpide toimii standardin määrittelemällä tavalla.

Jos se ei ole riittänyt, ovat jotkut käyttäneet dynaamisuuden aikaansaamiseksi XML:ää ja XSD-schemoja, jotka antavat mahdollisuuden tasapainoilla kontrollin ja dynaamisuuden välillä... antaen samalla tehokkaita työkaluja dynaamisen datan manipulointiin ( Xpath, XQuery ).

Ei kai dynaamisuus vai dynaamisuuden tähden ole mikään tavoite?

Kennu 14.12.2009 21:31:21

Relaatiotietokannat vs. dynaamiset key-value-storet alkaa olla jo laajempi keskustelunaihe. :-) Itselläni on muutama konkreettinen syy, miksi haluan siirtyä pois relaatiokannoista:

  • Skaalautuvuuden toteuttaminen on työlästä ja epävarmaa.
  • Tietorakenteet ovat jäykkiä (esim. moniulotteiset arrayt, assosiatiiviset arrayt jne).
  • Joinit ja muu indeksien hyödyntäminen on epädeterminististä ja riippuu kuun asennosta.

Dynaamisuutta pidän siinä suhteessa itseisarvona, että sen puute ei saa olla esteenä fiksujen sovellusten ja tietorakenteiden suunnittelulle. Joskus yksiulotteinen SQL-tietokantarivi riitää sovellukselle, joskus taas ei.

Ossi 15.12.2009 11:48:54

"...tietokantaan on tallennettu vanhoja artikkeleita, joissa "author"-kenttä on merkkijono, mutta uudemmissa se onkin muuttunut string-arrayksi. Kun tällaisia muutoksia kumuloituu ajan mittaan jatkuvasti lisää (kuten dynaamisesti kehittyvässä webbipalvelussa yleensä käy),..."

Hox! Nyt tajusin miksi intoilet näiden funktionaalisten ja tyypittömien kielten puolesta. Yrität korjata niillä pohjalla olevaa ongelmaa, eli huonoksi mennyttä tietokantaa, jossa data ei enää ole kannan kuvaamassa muodossa.

Eikö huomattavasti helpompaa ja järkevämpää olisi korjata oikea ongelma, eli tietokannassa oleva datatyyppi oikeaksi? Tässä tapauksessa ei esimerkiksi kovin monimutkaista algortmiä tarvitsisi tehdä, jotta tekijät saisi pilkottua erikseen kannasta, kannassa olevan varchar-kentän muutettua listaksi ja uudet arvot kirjoitettua sinne.

Apo 15.12.2009 13:29:28

Kennu:

Ei pakota castaamaan jos get metodin signature on List. Sopivalla rajapintavalinnalla nuo dataparsimiset voi tehdä tyypitetysti tai tyypittämättömästi kielestä riippumatta.

Python: article['authors'][0] Java: article.get("authors")[0]

Kömpelyys tulee siis enemminkin käytetystä rajapinnasta kuin kielestä.

Kennu 15.12.2009 13:39:03

Ossi: Esittämäsi ratkaisu toimii pienessä mittakaavassa, mutta mitä isompi tietokanta ja enemmän käyttäjiä, sitä vaikeammaksi käy joka kerta pienen muutoksen yhteydessä muuttaa kaikki vanhat recordit.

Mietipä esimerkiksi Facebookia. Veikkaatko, että heillä luetaan muutosten yhteydessä kaikki vanhat pari miljardia riviä sisään, lisätään uusi kenttä, ja kirjoitetaan takaisin?

Jos käytössä on SQL-tietokanta, niin jo pelkkä ALTER TABLE aiheuttaa ongelmia. Se kun lukitsee taulun operaation ajaksi ja joutuu kopioimaan vanhat rivit uuteen tauluun. Ja tämä pitää tehdä jokaisella tietokantapalvelimella erikseen. Eli syntyy käyttökatko, tai sitten tarvitaan joku monimutkainen logiikka, joka ohjaa kirjoitusoperaatiot ALTER TABLEjen aikana toisille servereille.

Toisin sanoen jos tavoitellaan oikeaa skaalautuvuutta, niin tietokannan pitää joustaa sillä tavalla, että vanhaa dataa ei tarvitse joka kerta muokata, kun lisätään uusi kenttä. Juuri tämä on näiden uusien schemaless-NoSQL-tietokantojen ideana.

Kennu 15.12.2009 13:46:53

Apo: Ei tuo kiinteän interfacen määrittely edelleenkään onnistu, jos rakenne on vaikka tällainen:

{ "authors": { "kennu": {"name": "Kennu", "url": "..." }, { "ossi": {"name": "Ossi", "url: "..." } .... }

Apo 15.12.2009 13:55:13

Kennu:

Minkälaisella Pythonilla tuota rakennetta käytetään?

Kennu 15.12.2009 14:03:19

Apo: Niin mitä? :-) Pythonillahan tuota voisi käsitellä esimerkiksi näin:

url = json['authors']['kennu']['url']

Pointtina tässä oli vaan, että sisäkkäiset arrayt ja assosiatiiviset arrayt ei mäppäydy staattisiin tyyppisysteemeihin mitenkään järkevästi.

Ossi 15.12.2009 14:43:31

Minusta käyttökatko on lyhyempi ja pienempi paha, kuin antaa tietokannan rakenteen lähteä sotkeutumaan muutosten takia.

Voin olla wanha pieru, mutta minusta koko tämä esittämäsi ajattelumaailma kuulostaa turhan anarkistiselta ja ylipäätään väärältä tavalta ratkaista ongelma.

Kennu 15.12.2009 14:50:04

Ossi: Hehheh, taitaisi olla toinen ääni kellossa, jos Facebook suljettaisiin aina pariksi päiväksi, kun tietokantaan tehdään pieni muutos.

Heimo Laukkanen 15.12.2009 15:27:19

Facepalm

Ossi 15.12.2009 15:34:38

Miksi FB muka pitäisi sulkea päiviksi, kun tietokantaan tehdään pieni muutos?

FB:ssä on aina silloin tällöin lyhyitä huoltokatkoja. Eivät ne ketään tapa.

Kennu 15.12.2009 15:53:23

Ossi: Tässä on kyse skaalautuvuudesta. Jos sinun ajattelemasi käyttökatko kestää kahden minuutin ajan miljoonalla rivillä, niin tuhannella miljoonalla rivillä se kestääkin jo 2000 minuuttia eli puolitoista vuorokautta.

Mikael Gueck 15.12.2009 16:23:02

Ossi, muista, että kun rakennetaan FB:n kokoista jättisovellusta, niin missään nimessä relaatiotietokantoja ei voi käyttää niin, että kokonaisuus partitioitaisiinkin pienemmiksi paloiksi yhden jättimäisen relaatiokannan sijaan, jolloin voitaisiin edelleen käyttää kaikkia valmiita työkaluja, mutta silti hajauttaa alter tablet rinnakkain ajettaviksi tuhansille redundanteille koneille ilman palvelukatkoa, ja pitää huolta siitä että tietomalli on eheä, koska tälläinen yksinkertainen ratkaisu ei vain kerta kaikkiaan sovellu NoSQL-ajatusmalliin, ja siksi sitä ei luonnollisesti kukaan voi ottaa tuotantoon.

Kennu 15.12.2009 16:31:28

Mikael: Horisontaalinen partitointi on hyvä menetelmä tiettyjen ongelmien ratkaisuun. Olen rakentanut muutamia skaalautuvia palveluita sitä hyödyntäen. Tosin monet relaatiokantojen ominaisuudet eivät sitten enää toimi, kuten transaktiot, foreign keyt, unique keyt, auto_increment-kentät jne. ja ne pitää ratkaista jollain omalla tavalla. Tietyt NoSQL-tietokannat, kuten esimerkiksi Cassandra, ratkaisevat juuri näitä ongelmia valmiiksi.

Pelkästään ALTER TABLEjen suhteen voi kuitenkin miettiä, että onko oikeasti järkevää ostaa 1000 palvelimen konesali ajamaan sitä 2 minuutin käyttökatkoa rinnakkain? Vai olisiko sittenkin pointtia käyttää dynaamisia tietorakenteita, jolloin koko operaation voi jättää tekemättä, ja käsitellä historialliset tietorakenteet sovelluksessa vasta sitten, kun niitä joskus tietokannasta ladataan.

Mikael Gueck 15.12.2009 17:19:51

En tiedä, miksi perustelit näkemystäsi Facebook-tason skaalautuvuustarpeella, sillä siellä tehdään juuri noin.

Jos tietomalli on eheä, ei ole tarpeen rakentaa häkkäyskoodia jossa arvotaan joka kohdassa jossa halutaan tietää author, sekä "author", "authors", "authros" jos jollain on mennyt dynaamisesti typo tuotantokantaan validaation puuttumisen seurauksena, jne.

Jos ei ole tarpeen rakentaa häkkäyskoodia, voidaan nauttia staattisen tyypityksen merkittävistä käytännön eduista, ja rakentaa varsin automaattisesti rajapintoja, joita sitten muut ihmiset ja yritykset voivat käyttää hyväkseen, ilman että heidän tulee tietää että kun etsitään authorsia, pitää ottaa Kennun typo edellisvuodelta omassa sovelluskoodissa huomioon.

Kaikki tämä johtaa siihen, ettei ole mitään tarvetta heittää oikeasti hyvin toimivia valmiiden ja tuotannossa testattujen työkalujen ekosysteemejä metsään jotta voisi itse rakentaa kaiken alusta asti, muutaman kokeellisen täysin tarpeettoman vemputtimen päälle.

Tietysti vemputtimia on kiva kokeilla kotona, mutta jälleen kerran, vaikka kuinka innostuisi tupakin poltosta välitunnilla koulun takana, se ei tee tupakoinnista fiksua eikä terveellistä.

Kennu 15.12.2009 17:28:50

Mikael: Facebook on kehittänyt Cassandran juuri siitä syystä, että relaatiotietokantojen skaalaaminen on niin hankalaa. Samaten Twitter on hiljalleen siirtymässä NoSQL-kantoihin. FriendFeedillä on käytännön esimerkki siitä, että ALTER TABLEt jumittavat tietokannan liian pitkäksi aikaa, joten siirtyivät käyttämään schemaless-rakennetta MySQL:n päällä (http://bret.appspot.com/entry/how-friendfeed-uses-mysql).

Tällä hetkellä eletään murrosvaihetta, kun odotellaan NoSQL-vaihtoehtojen kypsyvän tuotantoasteelle, ja käytetään niitä vielä SQL-kantojen rinnalla (vrt. Facebookin MySQL+Cassandra). Pian voidaan kuitenkin luopua SQL-kannoista kokonaan niissä sovelluksissa, joissa perinteinen relaatiomalli aiheuttaa enemmän haittaa kuin hyötyä.

Mikael Gueck 15.12.2009 17:52:35

Se, että Facebook tykkää IHAN ITSE rakentaa omat työkalut, vaikka markkinoilla olisi valmiita saatavilla, ei suinkaan ole hyve, vaan osoitus kehityskulttuurin kypsymättömyydestä.

Talouspuolella aivan sama ongelma ratkaistaan tavalla, joka edelleen säilyttää relaatiokannan hyvät puolet, eli tieto on taatusti ehjää, mutta siihen päästään myös käsiksi skaalautuvalla tavalla: http://www.oracle.com/us/products/middleware/coherence/index.htm

Kantatason partitiointia ja valmiilla tuotteella cachetusta ja työn paikallistamista voi myös yhdistellä halutulla tavalla.

Kennu 15.12.2009 17:55:07

Luulen että järkevän keskustelun voidaan todeta päättyneen, kun Oracle-kortti on vedetty esiin :-)

Apo 15.12.2009 17:55:42

Python: url = json['authors']['kennu']['url'] Java: String url = json.get("authors/kennu/url").string

Eli alkuperäinen kysymykseni pätee vieläkin:

Eikös tuossa (alkuperäisessä) esimerkissä ole vikana esimerkissä käytetyn rajapinnan kömpelyys eikä niinkään kielen rajoitteet?

Heimo Laukkanen 15.12.2009 17:58:39

Hei,

Oracle Coherence on yksi erinomaisia ostoja, jota Oracle teki. Asiakkaina paljon isoja pankkeja, jotka ihan oikeasti tekevät rahaa sillä isolla datamäärällä jota käsittelevät.

Kennu 15.12.2009 18:03:49

Apo: Well played :-) Huono puoli tuollaisessa XPath-tyyppisessä rajapinnassa on, että objektien muokkaaminen on kuitenkin hankalaa. Dynaamisessa tyypityksessä voi sanoa vaikkapa:

json['authors']['apo'] = {'name':'Mikko', 'url':'...'}

Esittämässäsi ratkaisussa pitää kehittää joku oma rajapinta muokkaamista varten. Keksitkö helposti sellaisen?

Kennu 15.12.2009 18:07:11

Huima: Olen vakuuttunut, että Oraclen tuotteet sopivat mainiosti pankkien käyttöön ja varmaan joihinkin isoihin Javalla koodattuihin enterprise-sovelluksiin. Tunnen molemmat alat huonosti enkä lähde niitä kyseenalaistamaan.

Mutta webbisaitteja en lähtisi Oraclen tuotteilla (enää) mistään hinnasta rakentamaan..

Mikael Gueck 15.12.2009 18:11:46

Kommenttisi on hauska, koska Tangosolin (Oracle Coherence oli aiemmin Tangosol Coherence) Cameron Purdy on maailmanlaajuisesti ehkä kovin laajasti käytetyn tuotteen rakentanut jätkä, joka puhuu juuri näistä asioista myös harrastaja-lähestymistapaa kannattavien kehittäjien suosimissa konferensseissa, ja tuote on paras markkinoilta löytyvä.

Apo 15.12.2009 20:09:53

Kennu, pala kakkua ;)

Python: json['authors']['apo'] = {'name':'Mikko', 'url':'...'} Java: json.get("authors").append("apo").set("name","Mikko").set("url","..")

Ei kovin perus-java-ratkaisu, mutta mahdollistaa tiedon tyypittämättömän käsittelyn. Itse diggaisin java-käytössä ehkä enemmän hybridistä:

json.get("authors").append("apo", new Author("Mikko","url"))

Osma Ahvenlampi 15.12.2009 22:00:28

Kennu, mä oon tätä sun NoSQL/scripting uskontoa seuratessa ihmetellyt välillä että mitä ihmettä se ihan fiksu mies huutaa, mutta pari kommenttia tässä ketjussa selvitti asian perusteellisesti.

  1. Sulle "SQL" on yhtä kuin "MySQL". On niitä sellaisiakin kantajärjestelmiä, joissa jokainen ALTER TABLE ei vedä teratavua dataa offline kolmeksi viikoksi. Ilmaiseksikin niitä saa (joskin maksullisista kannattaa joskus myös maksaa). Kannattais hieman tehdä tutkimusta eikä vaan kehitystä. En nyt nimeä yhtään, jätetään se harjoitustehtäväksi.

  2. Jos olet huolissasi skaalautuvuudesta tai suorituskyvystä mutta ET koskaan ole kuullut Tangosol Coherencesta, niin se tarkoittaa ettet oikeasti ole koskaan joutunut etsimään ratkaisua skaalautuvuusongelmaan jota ei ratkaista ostamalla viidelläsadalla eurolla lisää RAMmia - tai ainakaan et ole kysynyt apua missään foorumissa jossa joku toinenkin joskus olisi.

No offense, mutta NoSQL on ihan tuubaa. Saahan sitä toki harrastaa, mutta tämmösiä otsikoita kirjottaessa pitäis jo voida osoittaa että tarjottuun ratkaisuun on olemassa joku ongelmakin.

Kennu 15.12.2009 22:32:04

Osma: Sinulla taas näyttää olevan vahva usko SQL:n soveltuvuuteen mihin tahansa käyttöön. :-) Minun periaatteena on, että pitkä historia ja osaaminen yhden työkalun käytössä ei saa johtaa siihen, että sillä samalla vasaralla hakataan niin naulat kuin ruuvitkin puuhun loppuelämän ajan. Eli nimenomaan ei saa takertua uskontoihin, vaan pitää pohtia oikeasti, mikä teknologia sopii mihinkin tarkoitukseen.

Skaalautuvuus on muutenkin vain yksi SQL-tietokantojen ongelmista. Yhtä lailla ongelmallista on se, että relaatiomalli ei sovi nykyisten web-sovellusten datan mallintamiseen kovin hyvin. Moniulotteisten arrayden ja hierarkioiden mallintaminen SQL:llä on kuin ajaisi käärmettä pyssyyn. Sen takia CouchDB, MongoDB ja vastaavat NoSQL-tuotteet käyttävät JSONia natiivina datamallina.

Skaalautuvuuskeskustelun voi muuten jakaa selkeästi kahtia. Toisaalta voidaan käydä teoreettista keskustelua siitä, minkä takia SQL transaktioineen ja relaatioineen skaalautuu luonnostaan huonosti, ja miten uudet NoSQL-kannat ja relaxed/eventual consistency -ajattelu pystyvät ratkomaan samoja ongelmia uudella tavalla.

Toisaalta voidaan sitten ratkoa jotain konkreettista, yksittäistä skaalautumisongelmaa, jossa Coherence, Terracotta tai muu vastaava platformi voi kenties olla ihan hyvä ratkaisu. Omissa projekteissani niille ei ole ollut tarvetta enkä niitä sen tarkemmin tunne, vaan sopiva horisontaalinen partitointi, message queuing ja välimuistitus (pelkillä open source -ohjelmistoilla, voisin lisätä) on ratkaissut kulloisetkin ongelmat.

Ossi 15.12.2009 23:08:08

Tässä kommenttiketjussa on erinomaisia viestjä! Kennun provo on saanut asiantuntevaa väkeä liikkeelle. Tästä /cheer.

Minua tässä dynaamisessa tyypityksessä ja Scala / Python / funktionaalinen ohjelmointi -koodeissa häiritsee sen vaikeaselkoisuus. Tiiviiseen tilaan ahdetty kryptinen koodi on varmasti tehokasta sellaiselle henkilölle, joka on asian aikanaan tuottanut ja hallitsee näin koko sovelluksen toiminnallisuuden omassa päässään.

Vaan valitettavan usein koodiin joutuu koskemaan gurukoodaajan kadottua seuraavaan projektiin joku toinen kehittäjä. Ehkäpä vielä vähemmän guru. Ja jos tällöin funktionaalisen gurukoodin ymmärtämiseen menee enemmän kuin puoli päivää työaikaa, valuvat funkkarikoodauksen hyödyt hukkaan.

Mitä NoSQL:ään tulee, on aika rohkeaa olettaa sellaisten välineitten olevan tuotantovalmiita vielä ensi vuoden aikana. Okei, ehkä webbipalveluihin, mutta webbipalvelut - varsinkin Linux Apache MySQL Perl - eivät todellakaan ole koko maailma.

Erottaisin tässä keskustelussa muuten kaksi asiaa toisistaan: tietokannan joustavuuden tietomallin muuttuessa useasti ja tietokannan skaalautuvuuden. MySQL:llä toki on ongelmia kummassakin suhteessa "oikeisiin" kantoihin verrattuna.

Kennu 15.12.2009 23:56:10

Voisin muuten todeta tähän väliin ihan anti-provona, että duuniprojekteissa en minäkään ole vielä käyttänyt NoSQL-tietokantoja. Puhun siis niistä ainoastaan harrasteprojektien ja teorian pohjalta, enkä ole tyrkyttämässä niitä kellekään tuotantokäyttöön tänä päivänä. Duunissa asiat on pääsääntöisesti hoidettu MySQL:llä ja PHP:llä/Pythonilla sekä Memcachedilla.

Jollain todennäköisyydellä Tokyo Tyrant menee kyllä tuotantokäyttöön lähiaikoina, sillä sen key-value-store sopii tiettyihin tarkoituksiin erityisen hyvin. Lähinnä hybridiratkaisuna, jossa MySQL toimii pääasiassa read-only-tietokantana, ja tiheään tapahtuvat kirjoitusoperaatiot (laskurit yms) laitetaan Tokyoon, etteivät turhaan hakkaa MySQL-palvelinta N kertaa sekunnissa.

Mikael Gueck 16.12.2009 01:46:11

Tai voisit vaikka vaihtaa PHP:n sovelluksen osalta Javaan, jolloin sinulla ei ole enää rajoitteena se, että sovelluksen paikallinen tila katoaa totaalisesti jokaisen sivunlatauksen yhteydessä, vaan luot "volatile ConcurrentMap counter"in, jota sitten inkrementoit.

Mutta se olisi toisaalta triviaali, ylläpidettävä sadan rivin ratkaisu, jonka jatkokehitykseen löytyy markkinoilta henkilöstöä, eikä päästäisi ottamaan käyttöön kokeellista softaa, jonka ainoat ekspertit löytyvät tois'puol jokkee, ja bugikorjausten saaminen löytyviin ongelmiin on sattuman kauppaa.

Kennu 16.12.2009 01:56:07

Meillä ei käytetä Javaa. Olen kyllä evaluoinut Scalaa juuri sillä silmällä, että olisiko se jo riittävän kypsynyt kieli hyödyntämään JVM:n edut ilman Javan haittapuolia.

Mutta kuten tässä nimenomaisessa blogikirjoituksessa tuli todettua, Scalakaan ei staattisen tyypityksen takia pääse lähellekään Pythonin yksinkertaisuutta ja dynaamisuutta sovelluskehityksessä. Lähinnä Scalan type inferencing ja kevennetty syntaksi vähentävät hieman turhaa kirjoittelua Javaan nähden, ja funktionaaliset ominaisuudet on ihan näppäriä.

Btw, Pythonin virtuaalikone toimii pitkälti samalla idealla kuin JVM, eli bytecode ja luokat/objektit pysyvät muistissa.

Heimo Laukkanen 16.12.2009 02:04:05

snap

Tässä keskustelussa hyvin näkee sen, miten käytössä olevat työkalut ja mallit määrittävän sen, miten maailmaa katsotaan. Ymmärrän Kennun halun tutkia ja viehtymyksen uusiin paradigmoihin, koska itsekin koen monesti samaa - mutta onneksi kolleegat kuten Mikael osaavat palauttaa maan pinnalle ja freimata kysymyksen toisesta näkökulmasta uudestaan.

NoSQL storageilla on omat hyvät käyttötapauksensa, mutta niihin liittyy aina suuri määrä uusia haasteita, jotka eivät ole välittömästi selviä. Sen minkä voittaa toisaalla, häviää toisaalla.

Tämä siis ajatuksena Kennulle, kun nykyään mielipidevaikuttajana saattaa omalla innostuneisuudellaan, blogillaan ja artikkeleillaan saattaa vahingossa jollekin juniorille päähän hassuja ajatuksia, jonka jälkiä sitten joku toinen joutuu myöhemmin korjaamaan.

Kennu 16.12.2009 02:15:20

Huima: Ymmärrän hyvin sinun ja Mikaelin näkökulman. Olen ajoittain käynyt samankaltaista taistelua töissä "perinteistä kiinnipitäviä" IT-ylläpitäjiä vastaan. Taisteleminen on tärkeää. Toisaalta me R&D-ihmiset ymmärrämme sen seurauksena paremmin tuotannon vaatimukset, ja toisaalta tuotantoihmiset eivät jää ikuisesti jumittamaan niihin totuttuihin, vanheneviin ratkaisuihin. Löytyy tasapaino.

Oman roolini mielipidevaikuttajana aion pitää vastaisuudessakin R&D-henkisenä, sillä puhun mielellään niistä asioista, joista olen innostunut. Kyllä niitä Java-SQL-jääriä löytyy vastapainoksi ihan riittämiin saarnaamaan 90-luvun teknologioiden ihanuudesta ja stabiiliudesta jatkossakin! ;-)

Mikael Gueck 16.12.2009 02:24:04

Sovitaanko siis tällä puheella, että kun otat NoSQL/Scala-ratkaisun tuotantoon, jäät myös sitä ainakin pariksi vuodeksi ylläpitämään, ennen lentämistä seuraavaan kukkaan?

Heimo Laukkanen 16.12.2009 02:29:37

R&D-näkökulmassa kuitenkin kannattaa pitää mukana myös hieman sitä management / kustannusnäkökulmaa, jonka laskelmat saattavat muuttua hyvin erilaisiksi kun systeemin vanhoja perusperiaatteita muutetaan. Joskus perinteillä on nimenomaan arvoa siinä, että hallittavuus ja arvattavuus säilyy - ja toimintaa voidaan turvallisesti skaalata, ilman että homma hajoaa käsiin kesken matkan.

Tänään olen viettänyt suuren osan päivästä seuraten Java Enterprise Edition 6:n featureiden esittelyä verkkoseminaarissa ja taputtanut karvaisia käsiäni, koska kehitys on mennyt mahtavasti eteenpäin standardoiden hyväksi havaittuja best practiceja ja antaen sovelluskehittäjille erittäin hyviä ja turvallisia rakennuspaloja sovelluskehitykseen. Hyvänä esimerkkinä vaikkapa JPA 2.

Kaikki eivät tietenkään halua käyttää tai tarvitse kiveä rakennusmateriaaliksi. He voivat sitten tyytyväisinä asua heinämajoissaan, sillä asuntohan jyrätään joka tapauksessa yli kun tuulen suunta vaihtuu ja tulee uusi trendi. :-D

Keskustelu on tärkeää :-D

Kennu 16.12.2009 02:32:19

Olen ollut nykyisessä työpaikassani hieman vajaat 10 vuotta. Onneksi en joudu pahemmin enää ylläpitämään niitä Java-ratkaisuja, joita tein ihan alkuvaiheessa. ;-) Kyllä kaikki omat ratkaisut tuppaa kummittelemaan pitkään jälkeenpäin, kun tekee pitkäjänteistä työtä. Mutta en ole koskaan antanut sen olla uusien asioiden opiskelun esteenä. Pythoniakin olen käyttänyt ja opiskellut hiljalleen vuosien ajan, mutta nyt vasta sitä on alettu meillä käyttää ihan vakavissaan PHP:n rinnalla.

Kennu 16.12.2009 02:43:38

Heimo: Vertaus heinämajaan on itse asiassa aika hyvä. Webbipalveluita pitää nykyään pystyä rakentamaan todella nopeasti pienellä porukalla, eikä siinä haluta käyttää aikaa massiivisten J2EE-kivijalkojen pystyttämiseen. Monet palvelut kuolevat kuitenkin pois hetken päästä.

Joskus saitti sitten kasvaa isoksi, ja heinämaja pitäisi saada pysymään pystyssä, mutta kuitenkin olemaan yhä joustava ja muovautuva uusille ominaisuuksille. Juuri tässä kohtaa näen sekä Pythonin että NoSQL-kantojen lupauksen. Niillä pääsee nopeasti ja ketterästi liikkeelle, mutta ne myöskin skaalautuvat isoon mittakaavaan, ja arkkitehtuurikin voidaan tehdä alusta asti järkevärakenteiseksi (Djangon data modelit ovat oikein nättejä).

Heimo Laukkanen 16.12.2009 02:52:50

Ehkä sulle pitäisi näyttää, miltä nykyaikainen Java web-mvc näyttää, miltä datamallit näyttävät JPA:lla tehtynä, sekä kuinka controllerit ovat yksinkertaisia ja selkeitä annotaatioilla merkattuina ... hyvin samaan tyyliin kuin Railsissa tai Djangossa on.

Samalla kuitenkin saa käyttöön rikkaan ja laajan infrastruktuurin, josta löytyy reittejä ja mahdollisuuksia kytkeä sovellus vaikka kahvinkeittimeen tai jättimäiseen klusteriin, jossa kaikki virtuaalikoneet jakavat yhteisen 'virtuaalisen objektimuistin'.

Java-ekosysteemi on oikeasti mennyt viimeisen 5 vuoden aikana järkyttävällä tavalla eteenpäin ja ottanut sisäänsä myös paljon uusia hype-elementtejä, mahdollistaen JVM:n sisällä skriptaamisen dynaamisilla kielillä jne.

Liikkellelähdön vaikeuskin on vanhaa muistoa. Developerit pystyvät lähtemään todella nopeasti liikkelle JPA 2 + Spring 2.5 yhdistelmällä - saaden jopa valmiin pohjaprojektin Netbeans 6.8:lla muutamalla napin painalluksella.

Kennu 16.12.2009 02:59:45

Mä en tykkää Javasta kielenä. Siinä joutuu koodaamaan liikaa turhaa boilerplate-koodia, tekemään joka perhanan asiasta erillisen luokan/hakemistopuun, ja siitä puuttuu liikaa nykyaikaisten kielten ominaisuuksia. Noin muuten JVM-pohjaiset ympäristöt varmasti onkin ihan kehittyneitä. Tosin vihaan Tomcatia, joka on aivan järkyttävän monimutkainen konfiguroida käyttöön permissioineen ja hakemistohierarkioineen.

Tekisitkö muuten tuotantojärjestelmän JRubylla tai Jythonilla? Onko ne kypsiä?

Heimo Laukkanen 16.12.2009 03:17:10

Sulla on vanhat kokemukset Javasta kielenä. Maailma on muuttunut - ja vaikka kaikkia featureita ei olekaan verrattuna moneen muuhun kieleen, asiat pystytään kuitenkin tekemään. Koodaukseen käytettävä aika ei kuitenkaan ole elinkaaresta kuin pieni osa.

Tomcat onkin Tomcat. Appservereitä on useita. Itse olen tykännyt Glassfishistä.

En tekisi JRubyllä tai Jythonilla (pelkästään) tuotantojärjestelmää, mutta voisin hyvin käyttää niitä tuotantojärjestelmän osana. Minä en näe tarvetta tehdä kaikkea dynaamisella kielellä, vaan käyttää skriptikieliä tukena ja apuna.

Glassfish + Spring Framework + Jython on ihan hyvä setti.

Kennu 16.12.2009 03:24:52

Totta kai asiat pystytään tekemään. Pystytään ne tekemään myös x86-assemblerilla. :-) Kyse on pitkälti siitä, kuinka paljon ylimääräistä vaivaa koodaaja joutuu näkemään yksinkertaisen asian toteuttamiseksi, ja kuinka paljon turhaa bugipinta-alaa koodiin jää roikkumaan. Minun alallani koodaukseen (ja debuggaukseen) käytettävä työ on merkittävä osa kokonaistyöstä. Tehtävät asiat on yksinkertaisia, ja ne pitää saada toteutettua yhtä yksinkertaisesti, ilman ylimääräistä höhhää.

Apo 16.12.2009 13:18:38

Kennu:

"Scalakaan ei staattisen tyypityksen takia pääse lähellekään Pythonin yksinkertaisuutta ja dynaamisuutta sovelluskehityksessä"

Enkö jo osoittanut että kyseessä ei ole yksittäisen kielen tai staattisen tyypityksen vaan kirjastojen rajapintasuunnittelun tuoma ongelma mistä esimerkkisi otat?

Kennu 16.12.2009 15:09:30

Apo: Osoitit, että voidaan tehdä kirjastoja, jotka kiertävät staattisen tyypityksen ongelmia. Tarkoitin, että Pythonilla tai vastaavalla kielellä koodatessa näitä ongelmia ei ole alun perinkään, eli ei tarvitse tehdä niitä kirjastoja, vaan voidaan käyttää natiiveja datatyyppejä. Ts. pääsee koodaamaan heti itse sovellusta rakentamatta sitä kivijalkaa ensin pohjalle.

Mikael Gueck 16.12.2009 17:20:28

Lol. Vai että python-virtuaalikone on kuin JVM.

Pythonin virtuaalikoneessa on pari "kivaa" "featurea" kuten GIL, joka pitää huolta siitä, että Python-koodi ei käytännössä pysty käyttämään uudesta hienosta serveristäsi kuin yhtä corea kerrallaan, johon dynaamisilla kehittäjillä on tietysti hyvä neuvo: pyöritä, samalla tavalla kuin PHP:n tapauksessa, useampaa imagea sovelluksesta palvelimellasi, mikä tietysti heittää roskakoriin heti kaikki edellä mainitut hyödyt ja koko argumenttisi.

Tämä siis mainitsemattakaan Python-virtuaalikoneen 80-luvun Lisp-koneiden tasolla olevaa roskienkeruuta, tai Python-kirjastojen surkeata dokumentaatiota ja yleistä tasoa, josta seuraa kivoja yllätyksiä kun käytännössä yrittää tehdä asioita joista on luvattu että kyllä nää nyt ihkudynaamisesti toimii.

Tilanne on pitkälti sama kuin MySQL:n foreign keyiden, transaktioiden, ja tietotyyppien enforcauksen kanssa. Dynaaminen jengi vaahtosi pitkään ettei sellaisia tarvita, koska nehän kannattaa tehdä jokaisen ihkuitse sovelluskoodissa, ja nyt ollaan tilanteessa jossa MySQL kyllä mainostaa että kaikki featuret on, mutta käytännössä, toisin kuin kaaaaaikkien muiden tietokantojen kanssa, joudut valitsemaan että haluatko kannan olevan ehjä, vai nopea.

Kennu 16.12.2009 17:32:48

Mikael: Ei se mitään heitä roskakoriin, vaan edelleen Pythonin bytecode ja luokat ja objektit pysyvät muistissa kuten JVM:ssä. Kun käytössä on joka tapauksessa useita rinnakkaisia fyysisiä palvelimia, niin ei kaikki voi mitenkään olla yhdessä jaetussa VM:ssä. Eli tarvitaan joka tapauksessa jokin erillinen tapa jakaa tilatieto, kuten sessiot ja cachet, kaikkien palvelinten kesken.

Toisin sanoen Java/JVM on kyllä Pythonia parempi hyödyntämään multi-coreja, kun sovellus pyörii vain yhdellä palvelimella. Mutta jos kehität sovelluksen sillä oletuksella, että se pyörii aina vain yhdellä palvelimella yhden VM:n sisällä, niin se ei tule skaalautumaan.

Heimo Laukkanen 16.12.2009 17:46:40

Ennen kuin puhuu Javan skaalaamisesta, kannattaa tarkistaa että on tutustunut Oracle Coherenceen tai vaikka Terracottaan.

Mikael Gueck 16.12.2009 17:53:14

Käyt vuoden 2010 alkua juhlistaaksesi ostamassa kaupasta palvelimia, joissa on uusia Intelin 6-coreisia prossuja 4 kappaletta, ja muistia vaikka 24GB, koska täällä meillä suurin palvelimiin liittyvä kulu on niiden ylläpito.

Jos pyörität palvelimella yhtä Python-prosessia per core, se tarkoittaa 24 prosessia. Jos jokainen image pitää datasettiä muistissa, palvelimen käsittelemän datasetin koko voi olla vähän alle 1GB.

Jos pyörität palvelimella yhtä JVM:aa joka spawnaa 24 työthreadia, datasettisi koko voi olla noin 23GB per palvelin.

Jos sinulla on vaikkapa 500GB datasetti lohkottavana, ja kuormasi vaatii noin 500 corea (jos unohdetaan täysin tehokkuuserot JITatun Javan ja tulkitun Python-bytekoodin välillä) niin kuinka monta palvelinta ostat kummassakin tapauksessa, kuinka paljon tilaa, sähköä ja lämmönsiirtokapasiteettia ne vaativat palvelinhuoneessa, ja kuinka paljon sekä fyysisiä että käyttöjärjestelmätason ylläpitäjiä tarvitse, kun alat skaalaamaan ylöspäin?

Kennu 16.12.2009 17:59:44

Mikael: Mun sovellusdomainissa muistin määrä ei ole ollut ongelma. Emme pidä cachea Python-VM:ien sisällä, vaan erillisissä memcached-prosesseissa, jotka voi olla myös jaettu usean edustapalvelimen kesken.

Olen ihan vakuuttunut, että JVM:llä voi tehdä hienoja asioita, ja on monia käyttötapauksia, joissa siitä on suurta hyötyä. Meidän tapauksessa vaan Pythonilla voi tehdä tarvitsemamme asiat yhtä lailla.

Mikael Gueck 16.12.2009 18:26:57

Sori, luulin että puhuttiin työn skaalaamisesta.

Osma Ahvenlampi 16.12.2009 20:27:42

Niin, tän keskustelun pointti ei siis olekaan "vahvasti tyypitetyt kielet ovat kuolleita, dynaaminen skriptaus ja skematon data FTW", vaan "Kennun R&D:n projektit on niin pieniä ja aito tutkimus työkaluista sen verran puutteellista että että näähän koodais vaikka bash-skripteinä" :)

Mikäs siinä. Blogin omistaja päättää aiheen.

Kennu 16.12.2009 20:35:08

Osma: Teillä on Heimon kanssa kova hinku vedota siihen, että meillä ei käytetä Coherencea projekteissa, vaikka emme edes toteuta projektejamme Javalla tai Oraclen tietokannoilla, ja lähtökohtanamme on muutenkin open source -työkalujen käyttö.

Trollaamisestanne huolimatta en siis koe tarvetta opiskella sellaista työkalua, joka on lähtökohtaisesti out-of-scope, ja jolle mulla ei ole edes tiedossa ongelmaa, joka sillä olisi tarpeen ratkaista.

Osma Ahvenlampi 16.12.2009 21:15:16

Mua ei vois vähempää kiinnostaa käytätkö Coherencea :)

Emme mekään sitä käytä. Terracottaa kokeiltiin ja todettiin ettei se toimi oikeasti niin hyvin kuin mitä papereista vois uskoa -- ehkä jossain pienemmässä hommassa joo, mutta pienemmät hommat tekee yhdelläkin koneella. Tai sitten me ei osattu, on sekin mahdollista. Jos joku on edellisestä eri mieltä, kuulen mielelläni, sillä JOS se oikeasti toimii, mulla olis sille (ja sen hyödyntämisen asiantuntemukselle) käyttöä.

Sen sijaan mua kiinnostaa se, että sun perustelut sille mitä yrität myydä Ratkaisuna Kaikkeen eivät oikeasti pidä vettä -- ja sitä ei muuta se, että yhtäkkiä ne eivät olekaan enää ratkaisu kuin johonkin omaan rajattuun ongelmajoukkoosi.

Tässä ketjussa on näytetty (itseäni parempien koodaajien toimesta), että se minkä kuvittelit ratkeavan paremmin Pythonilla ei ollut kiinni Pythonista vaan siitä ettet ollut osannut muita työkaluja oikein hyödyntää.

Python on hieno kieli, jolle on paljon käyttötarkoituksia, mutta jonka käyttäjistä suurin osa ei osaa sitä käyttää. Sama koskee Javaa, C#:a, jne jne. Ensin pitää osata käyttää useampaa kuin yhtä työkalua oikein, vasta sitten niitä voi verrata toisiinsa.

Ainoa yleisesti käytetty ohjelmointiympäristö mitä edellinen ei koske on PHP -- sitäkään ei sen käyttäjät osaa käyttää, mutta se ei edes ole hieno, ainoastaan välttävä :)

Kennu 16.12.2009 21:32:02

@Osma: "Tässä ketjussa on näytetty (itseäni parempien koodaajien toimesta), että se minkä kuvittelit ratkeavan paremmin Pythonilla ei ollut kiinni Pythonista vaan siitä ettet ollut osannut muita työkaluja oikein hyödyntää."

Missä kohtaa näytettiin? Jos nyt jäädään jankkaamaan siitä, onko jokin omatekoinen DOM-objektimalli yhtä hyvä kuin kielessä vakiona tulevat natiivisti toimivat dynaamiset datatyypit, niin keskustelu jatkuu pitkään... Mun mielestä se nyt vaan ei ole yhtä hyvä. Kuten totesin, hyvällä kielellä ja ohjelmointiympäristöllä pääsee heti ohjelmoimaan itse sovellusta, eikä tarvitse rakentaa ensin pohjalle näitä "kivijalkoja". Puhumattakaan suorituskykyimplikaatioista, jos yksinkertaisiakin assosiatiivista arrayta varten pitää rakentaa joku oma XPath-johdannainen string-parseri, ja jokainen objektiviittaus vaatii aina merkkijonon parsimisen, jne.

Pythonissa asia nyt vain toimii niin, että JSON-objektit ja kielen natiivit datatyypit ovat suoraan vaihdannaisia keskenään, eikä siihen tarvita mitään API-luokkia väliin. Sama pätee JavaScriptiin, PHP:n, Rubyyn ja moniin muihin kieliin, sekä ilmeisesti myös C#:iin sitten, kun dynamic-avainsana saadaan siihen mukaan. Mutta Javassa näin ei ole, ja se on sen takia jäljessä kehityksestä. Piste.

@Osma: "Sen sijaan mua kiinnostaa se, että sun perustelut sille mitä yrität myydä Ratkaisuna Kaikkeen eivät oikeasti pidä vettä"

En ole tietääkseni yrittänyt myydä mitään "Ratkaisuna kaikkeen". Jo alkuperäisessä blogikirjoituksessa kirjoitin, että puhun nimenomaan web-ohjelmoinnista. Jostain yksittäisestä kommentista tämä qualifieri on saattanut jäädä väittelyn huumassa pois, pahoittelut jos näin on käynyt ja aiheuttanut väärinkäsityksen.

Kennu 16.12.2009 23:25:53

Kirjoitin vähän pitemmin auki omia ajatuksiani Apon ehdottaman "DOM-mallinnuksen" haittapuolista:

http://kfalck.net/2009/12/16/staattiset-datatyypit-vs-proprietaariset-dom-mallit

Kennu 23.12.2009 15:27:27

Selailin muuten Javan versiohistoriaa ja huomasin, että tuki dynaamisille tyypeille on tulossa Java 7:ään joskus 2010 loppupuolella. Kiintoisaa nähdä, pitääkö se Javan kilpailukykyisenä, ja pystyvätkö Jythonin ja JRubyn kaltaiset kielet sitten toimimaan paljon tehokkaammin JVM:n päällä.

http://en.wikipedia.org/wiki/Java_version_history#Java_SE_7

Joni 3.1.2010 21:00:46

Vähän myöhäinen kommentti tähän ketjuun mutta tässä on esimerkki puhtaasti funktionaalisesta Scala JSON kirjastosta:

http://github.com/dpp/liftweb/tree/joni_json_docs/lift-base/lift-json/

Siinä JSON:a ei kuvata Map:nä vaan abstraktina syntaksi puuna. Kts. esim featuret "case class extraction, LINQ style queries, XPath like queries"

Ilkka 31.3.2010 17:10:41

Kiitoksia erinomaisesta keskustelusta.

Päädyin tässä pitkän (pari päivää) pohdinnan jälkeen Scalaan, kun mietin kieltä millä teen projektin Googlen AppEnginen päälle. Olin ensin aikeissa tehdä Javalla, sitten Pythonilla, mutta Scala voitti vaikka ei ollut edes kilpailussa mukana (alussa).

Kun tulee vanhemmaksi (ja viisaammaksi?) niin saapi se dynaamisuus jäädä vähemmälle :)

Ilkka

Kennu 31.3.2010 23:09:02

Jännä juttu, meikäläisellä se on mennyt toisin päin, kun tekee yhä mieli kohottaa tuottavuutta dynaamisella tyypityksellä. Ehkä se johtuu pitkästä C:n ja C++:n parissa vietetystä nuoruudesta ja sen traumoista. :-)


You can use Markdown to format your comment:

  • > quoted text
  • *italic* text
  • **bold** text
  • `code block` (multi-line is ok, whitespace is preserved)
  • [link text](http://www.google.com "link title")

Separate paragraphs in your text with two newlines