"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Het werkt hier in z'n geheel niet. Ik krijg alleen maar de pagina met het robotje met daaronder: 'Sorry! Our services aren't available right now'.Woy schreef op dinsdag 4 september 2018 @ 14:19:
[...]
Hier maar gedeeltelijk, maar het is zeker wel een breder probleem dan alleen bij InZane: https://twitter.com/VSTS/status/1036927268587753472
Bij ons werkt het release-management gedeelte ieder geval niet, en dat is irritant, want ik wil net wat releasen.
Mijn privé account heeft verder ook geen problemen.
Ik kan nu echt niets doen omdat ik afhankelijk ben van application insights.
Hoeder van het Noord-Meierijse dialect
Ja baal er echt van, ik zit 2 dagen voor een deadline en morgen veel meetings, en ga het zo niet afkrijgen.Harrie_ schreef op dinsdag 4 september 2018 @ 15:52:
Hier ook problemen met Azure. In de Azure Portal allerlei pagina's die niet laden en 'lelijke meldingen'
Dáárom dat m'n AppInsights niet meer werkteHarrie_ schreef op dinsdag 4 september 2018 @ 15:52:
Hier ook problemen met Azure. In de Azure Portal allerlei pagina's die niet laden en 'lelijke meldingen'
En bedankt, ik moest even opzoeken wie dat ook alweer was en nu kan ik de komende maand Google Ads voor paardrijbroeken verwachten.gekkie schreef op dinsdag 4 september 2018 @ 18:51:
Tijd om mevrouw Rijbroek in te vliegen, ze hadden het ook maar in een blockchain moeten frutten !
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Sexy, ach heb je een goed excuus om op je werk gezellig je stokpaardjes te blijven berijdenMugwump schreef op dinsdag 4 september 2018 @ 19:13:
[...]
En bedankt, ik moest even opzoeken wie dat ook alweer was en nu kan ik de komende maand Google Ads voor paardrijbroeken verwachten.
Tijdens het testen een tweede bus toegevoegd. Bleek dat de tweede bus wel werkte, maar de eerste ineens niet meer. Het heeft me drie dagen gekost om er achter te komen dat in de loop langs alle bussen voor het opmaken van de variabele lijsten ook de variabele lijsten werden toegekend aan de bus, alleen dan zonder check op "met welke bus ben ik bezig?". De eerste bus kreeg dus 2 maal dezelfde variabele lijst toegekend waardoor die over de zeik ging.
Drie dagen naar de klote. Een voordeel is wel dat ik de achterliggende code nu ook ken en geleerd heb hoe ik het platform kan debuggen.
You don't have to be crazy to do this job, but it helps ....
Damn. Is dit de echte kracht van serverless?It's costing me 2.6c per day to support 141M monthly queries of 517M records.
Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana
Definieer "serverless" ?Cloud schreef op woensdag 5 september 2018 @ 09:41:
[...]
Damn. Is dit de echte kracht van serverless?
Als alles met "wolk" er in geldt als zijnde geen server, want je ziet ze niet ...
Ik gok dat zowel cloudflare als azure niet geheel gebakken lucht zijn (bij azure kun je daar sinds gisteren over twijfelen sinds ze aangegeven hebben dat het datacenter een oven was), maar gewoon een berg servers bevatten.
Kortom gewoon "time well spend" ?Alain schreef op dinsdag 4 september 2018 @ 23:11:
Drie dagen naar de klote. Een voordeel is wel dat ik de achterliggende code nu ook ken en geleerd heb hoe ik het platform kan debuggen.
Je hebt je dankzij een probleem een stuk diepgaander in de applicatie kunnen verdiepen (je inlezen in code zonder een werkelijk probleem is doorgaans toch oppervlakkiger dan dat je iets voor langere tijd moet debuggen waarbij je van lieverlee toch assumpties maar eens moet laten varen en dingen moet uitzoeken en testen) waar je bij iedere interactie en bij ieder toekomstig probleem de vruchten van plukt.
[ Voor 41% gewijzigd door gekkie op 05-09-2018 10:03 ]
Ik denk dat je prima kan begrijpen dat 'ie doelt op cloud functions zoals van Azure, AWS of Cloudflare waar je zelf geen kennis hebt van de onderliggende hardware, OS en whatsoevergekkie schreef op woensdag 5 september 2018 @ 10:00:
[...]
Definieer "serverless" ?
Als alles met "wolk" er in geldt als zijnde geen server, want je ziet ze niet ...
Ik gok dat zowel cloudflare als azure niet geheel gebakken lucht zijn (bij azure kun je daar sinds gisteren over twijfelen sinds ze aangegeven hebben dat het datacenter een oven was), maar gewoon een berg servers bevatten.
Het is een term die nu toch al even meegaat en iedereen weet dat er uiteindelijk gewoon ijzer onder hangt. Maar dat heb je ook met bijvoorbeeld containers of VPS'jes, en toch noemen we dat "virtual"...
[ Voor 12% gewijzigd door Merethil op 05-09-2018 10:04 ]
Ok dan klopte m'n analyse dus aardig ... "serverless" is in aardige mate een synoniem voor "in de wolken".Merethil schreef op woensdag 5 september 2018 @ 10:02:
[...]
Ik denk dat je prima kan begrijpen dat 'ie doelt op cloud functions zoals van Azure, AWS of Cloudflare waar je zelf geen kennis hebt van de onderliggende hardware, OS en whatsoever
Is "de cloud" als marketing term dan nu alweer uitgewerkt ?
Het is wel de meest optimale manier om serverless te gebruiken. Zoals hij zelf al uitlegt helpt het heel erg als de content die je serveert vrijwel statisch is en dus efficiënt gecached kan worden. Mooi voorbeeld van een situatie waarin je dus een goede use case hebt.Cloud schreef op woensdag 5 september 2018 @ 09:41:
[...]
Damn. Is dit de echte kracht van serverless?
In de praktijk zie ik serverless ook vaak genoeg worden toegepast in gevallen waar het absoluut niet het juiste middel voor het beoogde doel is. Als je serverless gaat doen met een wirwar aan functions / lambdas, shared states tussen executies in databases gaat opslaan, zoveel doet dat je executietijden in de buurt komen van de time-outs en ga zo maar door, dan had je misschien gewoon een applicatie moeten bouwen.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Nou, nee. Cloud computing is een stuk ruimer, maar serverless draait helemaal om het kunnen draaien van functions die je zelf definieert en je laat de provider (AWS, Azure etc) zelf bepalen wáár ze het draaien. Kans is dat je functions gewoon elke keer dat ze draaien op dezelfde server draaien, maar kans is ook dat er gewoon randomly gekozen wordt waar nog ruimte is.gekkie schreef op woensdag 5 september 2018 @ 10:05:
[...]
Ok dan klopte m'n analyse dus aardig ... "serverless" is in aardige mate een synoniem voor "in de wolken".
Is "de cloud" als marketing term dan nu alweer uitgewerkt ?
Je doet zelf niets meer met servers maar laat ze dat volledig managen en vanuit een developmentomgeving bouw je dan je functions voor gebruik als API voor andere doeleinden. Wij gebruiken het zelf vooral voor functies die we niet heel vaak nodig hebben op AWS, want zodra je de functie een tijdje niet gebruikt gaat 'ie in een vorm van hibernation waar hij niets kost totdat we hem weer aanroepen.
En zelfs dan is zo'n functie vaak centenwerk in een maand, tenzij je hem óf miljarden keren per maand aanroept, óf grote hoeveelheden data gaat verstouwen.
Nou dat dus jaMugwump schreef op woensdag 5 september 2018 @ 10:09:
[...]
serverless bekt gewoon net wat lekkerder dan not-tied-to-a-specific-server-whether-thats-virtualized-or-not.
[ Voor 9% gewijzigd door Merethil op 05-09-2018 10:10 ]
Serverless bekt gewoon net wat lekkerder dan execution-not-tied-to-a-specific-server-whether-thats-virtualized-or-not.Merethil schreef op woensdag 5 september 2018 @ 10:02:
[...]
Ik denk dat je prima kan begrijpen dat 'ie doelt op cloud functions zoals van Azure, AWS of Cloudflare waar je zelf geen kennis hebt van de onderliggende hardware, OS en whatsoever
Het is een term die nu toch al even meegaat en iedereen weet dat er uiteindelijk gewoon ijzer onder hangt. Maar dat heb je ook met bijvoorbeeld containers of VPS'jes, en toch noemen we dat "virtual"...
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Een sortement van "Pico-services" dus, vraag lijkt me wel of dat in dit geval zo maatgevend is ?Merethil schreef op woensdag 5 september 2018 @ 10:09:
[...]
Nou, nee. Cloud computing is een stuk ruimer, maar serverless draait helemaal om het kunnen draaien van functions die je zelf definieert en je laat de provider (AWS, Azure etc) zelf bepalen wáár ze het draaien. Kans is dat je functions gewoon elke keer dat ze draaien op dezelfde server draaien, maar kans is ook dat er gewoon randomly gekozen wordt waar nog ruimte is.
Je doet zelf niets meer met servers maar laat ze dat volledig managen en vanuit een developmentomgeving bouw je dan je functions voor gebruik als API voor andere doeleinden. Wij gebruiken het zelf vooral voor functies die we niet heel vaak nodig hebben op AWS, want zodra je de functie een tijdje niet gebruikt gaat 'ie in een vorm van hibernation waar hij niets kost totdat we hem weer aanroepen.
En zelfs dan is zo'n functie vaak centenwerk in een maand, tenzij je hem óf miljarden keren per maand aanroept, óf grote hoeveelheden data gaat verstouwen.
Het impliceert het stateless gedeelte, terwijl je in dit geval toch redelijk non computational intensief data wilt verifiëren. Op zich leuk als je probleem daar toevallig mooi in past en je een sterk wisselende load hebt.
Goh ik had niet verwacht dat de discussie die zou ontstaan nu over de definitie van "serverless" zou gaan. Natuurlijk heeft Azure en Cloudflare servers in hun serverparken staan, dat is nogal logischgekkie schreef op woensdag 5 september 2018 @ 10:00:
[...]
Definieer "serverless" ?
Als alles met "wolk" er in geldt als zijnde geen server, want je ziet ze niet ...
Ik gok dat zowel cloudflare als azure niet geheel gebakken lucht zijn (bij azure kun je daar sinds gisteren over twijfelen sinds ze aangegeven hebben dat het datacenter een oven was), maar gewoon een berg servers bevatten.

Waar het mij om gaat is dat Troy geen (gevirtualiseerde) servers afneemt bij die partijen maar slechts executies voor die functions. Die functions schalen ideaal mee met drukte, beter nog dan je met gehele VMs zou kunnen doen. Want als er echt niets te doen is, betaal je in dit scenario echt 0. Maar de lichtste VM kost altijd wat. In dit geval een veelvoud van wat Troy nu betaalt, terwijl de lichtste VM hoogstwaarschijnlijk de pieken van HIPB absoluut niet aan kan.
Dat was wat ik bedoelde met de kracht van serverless
Ja als je zo'n lange naam verzint natuurlijk zekerMugwump schreef op woensdag 5 september 2018 @ 10:09:
[...]
Serverless bekt gewoon net wat lekkerder dan execution-not-tied-to-a-specific-server-whether-thats-virtualized-or-not.
[ Voor 10% gewijzigd door Cloud op 05-09-2018 10:47 ]
Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana
Blog post over geschreven een tijd geledengekkie schreef op woensdag 5 september 2018 @ 10:00:
Definieer "serverless" ?
De move van 'cloud' naar 'serverless' is gewoon een volgende stap waarin nog meer voor je gemanaged wordt. Da's alles.
Het "hurr durr er zijn heus wel servers" van veel developers is nogal vermoeiend. Iemand die dat zegt komt niet 'slim' over ofzo, wat veel wel lijken te denken.
[ Voor 17% gewijzigd door Hydra op 05-09-2018 12:35 ]
https://niels.nu
Of de term dekt de lading vrij beroerd, maar goed als daar consensus over is, mij bestHydra schreef op woensdag 5 september 2018 @ 12:34:
[...]
Blog post over geschreven een tijd geleden
De move van 'cloud' naar 'serverless' is gewoon een volgende stap waarin nog meer voor je gemanaged wordt. Da's alles.
Het "hurr durr er zijn heus wel servers" van veel developers is nogal vermoeiend. Iemand die dat zegt komt niet 'slim' over ofzo, wat veel wel lijken te denken.
Is FAAS (Function As A Service) wellicht nog wel duidelijker om aan te geven wat size en scope is van de building blocks die je extern laat managen.
Hoe kan dit winstgevend zijn voor Microsoft?Cloud schreef op woensdag 5 september 2018 @ 09:41:
[...]
Damn. Is dit de echte kracht van serverless?
🠕 This side up
Ik kan me voorstellen dat je op de schaal van Azure wel een hoop "rest" cpu-cycles zijn in de frictie van alle up en downscaling van hun cloud. Die kun je op zich goedkoop in de markt zetten. Zou wel betekenen dat als er veel gebruik van gemaakt zou worden de prijs wellicht ook om hoog zou moeten.Koenvh schreef op woensdag 5 september 2018 @ 12:58:
[...]
Hoe kan dit winstgevend zijn voor Microsoft?
Een aanzienlijk deel van de kostenbesparing behaalt Troy door Cloudflare, dat is wel belangrijk om te vermelden. Door zoveel mogelijk te cachen komen heel veel requests nooit bij de Azure Functions terecht.Koenvh schreef op woensdag 5 september 2018 @ 12:58:
[...]
Hoe kan dit winstgevend zijn voor Microsoft?
En voor wat betreft Microsoft en de winstgevendheid: goede vraag.
Mijn gedachten (ik ben absoluut niet zeker of dit waar is):
In principe hebben zij de servers al staan en draaien natuurlijk. Anders kunnen ze nooit on-demand extra VMs de lucht in schoppen binnen 10 minuten. Wellicht gebruikt Microsoft ook ongebruikte servercapaciteit om die functions op te draaien. En dan is het bijna pure winst, als we er even vanuit gaan dat een function-uitvoer niet noemenswaardig veel meer stroom gebruikt dan idle. Tegenwoordig zullen ze ook wel (gevirtualiseerde) servers hebben die gereserveerd zijn voor function uitvoer, gok ik. En daar is het een kwestie van slim voorspellen hoeveel capaciteit je nodig hebt. Maar dat geldt voor de servers die VMs moeten draaien uiteraard ook
Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana
Definieer 'dit'. Een specifieke, zwaar geoptimaliseerde use case waarbij het gros door Cloudflare al wordt afgevangen zegt niet zoveel over de vraag of functions in brede zin winstgevend zijn of zelfs Azure in nog bredere zin.Koenvh schreef op woensdag 5 september 2018 @ 12:58:
[...]
Hoe kan dit winstgevend zijn voor Microsoft?
De kosten van Function zijn simpelweg gebaseerd op aantal executies en gebruikte resources in de vorm geheugen-tijd combinatie. Omgerekend zou je grofweg 35 euro per maand voor het gebruik van een GB geheugen betalen en daar bovenop nog 16 cent per functie-executie. Dat lijkt niet veel, maar ik zie vaak genoeg ook ketens van functies waardoor je voor elke input aan het begin van een keten rustig 20 executies kunt krijgen. Als je dan 10 miljoen inputs per dag verwerkt, dan levert dat toch weer zo'n 600 euro per maand aan omzet op en daar bovenop nog de kosten voor resourcegebruik.
Wat functions natuurlijk vooral doen is zorgen dat je niet voor 'idle time' betaalt. In plaats van vaste capaciteit, virtueel of niet, in te kopen, koop je variabele capaciteit in. Microsoft benut dat feitelijk gewoon doordat ze de capaciteit die jij niet gebruikt weer aan iemand anders te verkopen.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]
De serverless servers kunnen de piek misschien prima aan, of je portomonee dat ook kan.
Mag hopen dat je ergens toch ook wel weer limieten op kunt zetten anders krijgen we dan misschien wel weer dezelfde blogs en twitters als toen sommige lui hun Amazon instance credentials in git parkeerden en een mooie rekening kregen.
Achja elk nadeel hep z'n voordeel.
[ Voor 4% gewijzigd door gekkie op 05-09-2018 15:07 ]
Ik weet het niet bij de rest, maar bij AWS krijg je automatisch een mail als je over je aangegeven limiet heen gaat. Ook kan je je functions throttelen of slechts zoveel function calls per uur instellen. Best netjes geregeld, ze willen vast klanten, niet wegrennende mensen omdat ze éénmaal 10.000 euro aan functions hebben gebruikt in een maand.gekkie schreef op woensdag 5 september 2018 @ 15:07:
Wordt een semi ddos op je function wel prijzig.
De serverless servers kunnen de piek misschien prima aan, of je portomonee dat ook kan.
Mag hopen dat je ergens toch ook wel weer limieten op kunt zetten anders krijgen we dan misschien wel weer dezelfde blogs en twitters als toen sommige lui hun Amazon instance credentials in git parkeerden en een mooie rekening kregen.
Achja elk nadeel hep z'n voordeel.
Mjah bij AWS is er toen geloof ik een hoop kwijtgescholden als damagecontrol.Merethil schreef op woensdag 5 september 2018 @ 15:14:
[...]
Ik weet het niet bij de rest, maar bij AWS krijg je automatisch een mail als je over je aangegeven limiet heen gaat. Ook kan je je functions throttelen of slechts zoveel function calls per uur instellen. Best netjes geregeld, ze willen vast klanten, niet wegrennende mensen omdat ze éénmaal 10.000 euro aan functions hebben gebruikt in een maand.
Hmm best jammer dat er weinig video en image formaten/containers bestaan waar je fijn en cheap (als in storage) een overlay (die je wel of niet laat zien) er in kan bakken, laat staan iets wat ook in één of het liefst meerdere browsers ook nog wil functioneren.
[ Voor 19% gewijzigd door gekkie op 05-09-2018 15:27 ]
Thanks! Veel fragmenten wist ik al maar zo'n samenhangend overzicht helpt veel.
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Dat kan je instellen. Je budgetten kan je namelijk vrij specifiek beheren.Merethil schreef op woensdag 5 september 2018 @ 15:14:
[...]
Ik weet het niet bij de rest, maar bij AWS krijg je automatisch een mail als je over je aangegeven limiet heen gaat. Ook kan je je functions throttelen of slechts zoveel function calls per uur instellen. Best netjes geregeld, ze willen vast klanten, niet wegrennende mensen omdat ze éénmaal 10.000 euro aan functions hebben gebruikt in een maand.
Om antwoord te geven wat dan het verdien model is:
- x-miljoen queries !oN!on! ja ok; maar hoeveel kwamen daadwerkelijk terecht bij de functie ipv cache?
- 9 van de 10x draait er naast serverless ook: database(s), storage(S3), ES, ???, meerdere buckets voor je serverless, API endpoints, etc.
- Ah je gaat dan ook wel even de simple email service gebruiken
- domains in route 53
- nog wat logging in cloudwatch
ah shit, vendor locked.
Laten we dan onze static instances ook bij AWS zetten. Nog wat storage erbij.. poef lekker 120$ p/m voor een 2 cpu servertje.

-------
Je kan als je "slim" bent vrijwel gratis of voor enkele centjes per maand een enorme stack aan tech neerzetten. Zie het meer als entry level; net zoals je ook gratis (of goedkopere) licenties van Office krijgt als student. Ga je bij een bedrijf werken: dan wilt iedereen Office want ze weten niet anders. A 120 euro p/jaar (?).
Ik gebruik dus als basis openstack bij een provider in NL. Voor specifieke cases maak ik gebruik van AWS. Denk hierbij aan SES (1000 mails voor ~10 cent). EC2 instances voor een paar cent; free tier en die spot instances ($0.0069 per Hour).
------
Ik heb eens berekend wat het zou kosten om alles naar AWS te zetten. Resultaat was een factor 10 - 15 duurder.
Een beetje serieus systeem met forse volumes in de cloud hangen is meestal zeker niet goedkoper.
Of je moet de boel dus echt heel efficiënt kunnen inrichten en optimaal gebruik kunnen maken van "je betaalt alleen voor wat je gebruikt".
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Da's met niet-lambda services niet anders. Je kunt op veel verschillende manieren limiteren, bijvoorbeeld door een max te zetten op 't geld dat je uitgeeft. Ik heb op m'n account ook een billing max van 5 euro per maand staan IIRC.gekkie schreef op woensdag 5 september 2018 @ 15:07:
Wordt een semi ddos op je function wel prijzig.
https://niels.nu
Nu nog een profiler die de cost in $ of € uitspuugt ipv milliseconden of kloktikkenHydra schreef op woensdag 5 september 2018 @ 18:47:
[...]
Da's met niet-lambda services niet anders. Je kunt op veel verschillende manieren limiteren, bijvoorbeeld door een max te zetten op 't geld dat je uitgeeft. Ik heb op m'n account ook een billing max van 5 euro per maand staan IIRC.
Uiteraard, intern verkeer is 0.02$ / GB (0.00$ voor cloudfront en 0.01$ voor je eigen region) en extern is 0.09$ / GBMugwump schreef op woensdag 5 september 2018 @ 18:29:
De bottleneck met betrekking tot AWS migratie van een systeem dat wij ontwikkelen / beheren is vooral de hoeveelheid data die de AWS cloud inkomt en weer verlaat volgens mij. Zit niet heel diep in AWS, maar ik begreep dat daar een fors kostenplaatje aan zit.
Een beetje serieus systeem met forse volumes in de cloud hangen is meestal zeker niet goedkoper.
Of je moet de boel dus echt heel efficiënt kunnen inrichten en optimaal gebruik kunnen maken van "je betaalt alleen voor wat je gebruikt".
Exclusief de daadwerkelijke opslag ~$0.022 per GB en dan eventueel van je setup nog een 0.00x$ per 1k requests.
^ Dit is dan iig voor S3
De hele oplossing waar ik hier over praat slaat ongeveer 200TB aan data op. Er komen dagelijks forse hoeveelheden aan data vanuit andere systemen binnen en externe request liggen ook boven de 10M per dag.Douweegbertje schreef op woensdag 5 september 2018 @ 20:34:
[...]
Uiteraard, intern verkeer is 0.02$ / GB (0.00$ voor cloudfront en 0.01$ voor je eigen region) en extern is 0.09$ / GB![]()
Exclusief de daadwerkelijke opslag ~$0.022 per GB en dan eventueel van je setup nog een 0.00x$ per 1k requests.
^ Dit is dan iig voor S3
Dus dat loopt fors in de kosten.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Gaaf, wat is dat voor iets?Mugwump schreef op woensdag 5 september 2018 @ 20:40:
[...]
De hele oplossing waar ik hier over praat slaat ongeveer 200TB aan data op. Er komen dagelijks forse hoeveelheden aan data vanuit andere systemen binnen en externe request liggen ook boven de 10M per dag.
Dus dat loopt fors in de kosten.
Engineering is like Tetris. Succes disappears and errors accumulate.
Ik zal er nog naar kijken, al vond ik weinig configuratievoorbeelden.rutgerw schreef op donderdag 30 augustus 2018 @ 20:35:
@Lethalis Als je controle over je machine hebt, dan kun je ook nog je jobs managen met Jobber
Wel heb ik ontdekt dat ik een hoop dingen eenvoudig voor mezelf kan maken:
- In plaats van moeilijk doen met een mailconfiguratie in Python (of Java, C#), gebruik ik nu SSMTP waardoor ik simpelweg altijd de server zelf als mailserver kan gebruiken.
- In een crontab kun je environment variabelen zetten. Dus de MAILTO bovenaan mijn crontab kan ik gewoon uitlezen in het uitgevoerde script. Maar ik kan dus ook gewoon JOBNAME="USB Backup" boven een commando plaatsen en dat uitlezen.
Hierdoor krijg ik dus eigenlijk een heel simpel script dat als wrapper kan fungeren dat bijna geen configuratie nodig heeft. Het kan immers de MAILTO en JOBNAME uit de crontab uitlezen. Vervolgens het commando uitvoeren dat als argument(en) wordt meegegeven. En op basis van de exitcode een mailtje sturen (met SSMTP) met JOBNAME gelukt of mislukt (met prio).
De hoeveelheid werk valt dus erg mee... dus misschien dat ik het nu toch doe. Want wat ik tot nu toe aan bestaande wrapper scripts gevonden heb, zijn het elke keer "net niet".
Ask yourself if you are happy and then you cease to be.
Ik kan me goed in vinden in jouw verhaal van het simpel maken.Lethalis schreef op donderdag 6 september 2018 @ 08:42:
[...]
Ik zal er nog naar kijken, al vond ik weinig configuratievoorbeelden.
Wel heb ik ontdekt dat ik een hoop dingen eenvoudig voor mezelf kan maken:
- In plaats van moeilijk doen met een mailconfiguratie in Python (of Java, C#), gebruik ik nu SSMTP waardoor ik simpelweg altijd de server zelf als mailserver kan gebruiken.
- In een crontab kun je environment variabelen zetten. Dus de MAILTO bovenaan mijn crontab kan ik gewoon uitlezen in het uitgevoerde script. Maar ik kan dus ook gewoon JOBNAME="USB Backup" boven een commando plaatsen en dat uitlezen.
Hierdoor krijg ik dus eigenlijk een heel simpel script dat als wrapper kan fungeren dat bijna geen configuratie nodig heeft. Het kan immers de MAILTO en JOBNAME uit de crontab uitlezen. Vervolgens het commando uitvoeren dat als argument(en) wordt meegegeven. En op basis van de exitcode een mailtje sturen (met SSMTP) met JOBNAME gelukt of mislukt (met prio).
De hoeveelheid werk valt dus erg mee... dus misschien dat ik het nu toch doe. Want wat ik tot nu toe aan bestaande wrapper scripts gevonden heb, zijn het elke keer "net niet".
Hier een anekdote die ik graag gebruik: Ik had een API geschreven in Ruby on Rails (RoR). Nu is RoR verschillende simpel te gebruiken, maar omdat de API relatief stabiel (mede omdat RoR zo simpel is) was vergat ik continue de syntax en was ik om de maand weer een kwartiertje kwijt met uitzoeken hoe het ook alweer zat.
Uiteindelijk heb ik het de gehele API omgezet van RoR naar typescript. Daarbij had ik wel een nieuwe ORM nodig en dat werd TypeORM (vanwege typescript).
Dit ging best lekker, tot dat ik moest upgraden in verband met een kleine bug, maar toen kwam er een andere bug en... een andere... en nog één...
Ik was meer tijd kwijt aan het dubbelchecken of de ORM werkte dan dat ik er mee bespaarde. Ik heb een paar andere ORM gebruikt, maar geen 1 was van het niveau dat ik bij Entity Framework gewend ben.
Een paar dagen later had ik de oplossing: Gewoon geen ORM gebruiken en puur SQL gebruiken. Het enige wat ik nodig had was een kleine database migratie systeem en die heb ik geschreven en bestaat uit 30 regels code.
Sindsdien:Geen bugs, het systeem is sneller geworden en de query's zijn efficiënter geworden.
"Doubt—the concern that my views may not be entirely correct—is the true friend of wisdom and (along with empathy, to which it’s related) the greatest enemy of polarization." -- Václav Havel
Een combinatie van een operationeel systeem met datavoorziening richting consumenten en daarnaast ook een datawarehouse. Iets met logistiek.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Leuk en leerzaam artikel. Dank daarvoor.Hydra schreef op woensdag 5 september 2018 @ 12:34:
[...]
Blog post over geschreven een tijd geleden
De move van 'cloud' naar 'serverless' is gewoon een volgende stap waarin nog meer voor je gemanaged wordt. Da's alles.
Het "hurr durr er zijn heus wel servers" van veel developers is nogal vermoeiend. Iemand die dat zegt komt niet 'slim' over ofzo, wat veel wel lijken te denken.
Engineering is like Tetris. Succes disappears and errors accumulate.
So, programmers, you know those systems that have been maintained for TOO LONG? that are just too expensive (in terms of technical debt) to replace, that are just hacks on hacks on hacks at this point, are a never ending maintenance nightmare that can't be killed?
Voor de rest of it, lees het Twitter draadjeThat's life. Not in the sense of "your life", but Life in general.
Life was a moderately scoped novel idea for a single-celled lifeform that consumed chemicals spewing out of deep sea vents. simple, easy, ship by christimas, we'll be done and can move onto other projects.

Lijkt me dat deze mail op zichzelf al tegen de AVG in gaat

[ Voor 16% gewijzigd door Pizzalucht op 06-09-2018 10:37 ]
Hij is leuk, sowieso is Foone wel een aardig account om te volgenVincentio schreef op donderdag 6 september 2018 @ 10:31:
https://twitter.com/Foone/status/1037031222164082688
[...]
Voor de rest of it, lees het Twitter draadje
Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana
Dus zet jij dat maar even publiek met NAW, email, telefoon, etc.Pizzalucht schreef op donderdag 6 september 2018 @ 10:35:
Dit is al het tweede mailtje wat ik hem krijg, uit het niks:
[afbeelding]
Lijkt me dat deze mail op zichzelf al tegen de AVG in gaat

Tjolk is lekker. overal en altijd.
Dat zijn allemaal publieke gegevens hoor...Tjolk schreef op donderdag 6 september 2018 @ 11:33:
[...]
Dus zet jij dat maar even publiek met NAW, email, telefoon, etc.
Tjolk is lekker. overal en altijd.
Ze noemen ORM's niet voor niks "the vietnam of computer science"DevWouter schreef op donderdag 6 september 2018 @ 09:29:
[...]
Een paar dagen later had ik de oplossing: Gewoon geen ORM gebruiken en puur SQL gebruiken. Het enige wat ik nodig had was een kleine database migratie systeem en die heb ik geschreven en bestaat uit 30 regels code.
Sindsdien:Geen bugs, het systeem is sneller geworden en de query's zijn efficiënter geworden.
Ask yourself if you are happy and then you cease to be.
Lijkt me prima. Als je je mobiele nummer in je emailhandtekening zet en naar random bedrijven stuurt kun je wat mij betreft niet verwachten dat deze prive is/blijft.Tjolk schreef op donderdag 6 september 2018 @ 11:38:
Zijn mobiele nummer vast ook? Zal hem wel ff een appje sturen dan waar hij het kan nalezen.
Als jij dat zo ziet, prima.Tjolk schreef op donderdag 6 september 2018 @ 11:49:
Juist ja. Iets met pot en ketel dus.
Ik zie het meer als ergens een flyer ophangen met je 06 erop. Dan moet je het daarna ook niet vreemd vinden dat mensen je 06 weten.
Ben er ook wel redelijk van teruggekomen. Het is vooral handig als je heel snel een CRUD-achtig applicatietje wilt opzetten met een API / UI. Bij complexere database-interactie moet je je toch al snel in allerlei onhandige bochten gaan wringen.Lethalis schreef op donderdag 6 september 2018 @ 11:41:
[...]
Ze noemen ORM's niet voor niks "the vietnam of computer science"
En juist als je wat basale CRUD doet is vaak een document store net zo handig. Weg is de impedence mismatch.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Daar mee samenhangend, een Solr project (M'n Python werkje gebruikt Solr), damn dat is me een beest van een stuk software zeg. Ontiegelijk krachtig. Ik had echt geen idee dat er zo veel opties waren.
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Tsja, ik ben hoofdzakelijk .NET developer, maar toevallig pas ook nog Python gedaan. Onderstaand stukje code is een CRON job wrapper:Firesphere schreef op donderdag 6 september 2018 @ 13:37:
Terug in de Python wereld voor een eigen projectje. Wat heb ik dat gemist zeg, beetje roestig, en elke doorgewinterde Python expert zal m'n werk tot de fundering afbranden, maar toch, het werkt en hopelijk binnenkort een publiceerbaar stukje code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
| #!/usr/bin/env python """Jobwrapper script for crontab Example: MAILTO=info@****.com MAILFROM=info@****.com JOBNAME="USB Backup" 0 23 * * * /scripts/jobwrapper.py /scripts/usbbackup.py This script uses SSMTP for mail delivery. """ import os import sys import subprocess import socket from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText class ConfigurationError(Exception): def __init__(self, message): self.message = message def send_mail(mailto, contents): """Send mail with SSMTP""" process = subprocess.Popen(["/usr/sbin/ssmtp", mailto], stdin=subprocess.PIPE, stdout=subprocess.PIPE) process.stdin.write(contents) process.communicate() process.stdin.close() def create_mail(hostname, jobname, mailfrom, mailto, exitcode, output): """Create mail message""" title = '{0}: {1} {2}'.format(hostname, jobname, 'succeeded' if exitcode == 0 else 'failed') msg = MIMEMultipart('alternative') msg['Subject'] = title msg['From'] = mailfrom msg['To'] = mailto if exitcode != 0: msg['X-Priority'] = '2' html = [] html.append("<html>") html.append("<body>") html.append("<h1>{0}</h1>".format(title)) html.append("<pre><code>") html.append(output) html.append("</code></pre>") html.append("</body>") html.append("</html>") html_string = ''.join(html) part1 = MIMEText("Please use a HTML capable mail client -_-", 'plain') part2 = MIMEText(html_string, 'html') msg.attach(part1) msg.attach(part2) return msg.as_string() def main(): """Main function""" try: # Check configuration mailto = os.environ.get('MAILTO') if mailto is None: raise ConfigurationError('Please set the MAILTO environment variable') mailfrom = os.environ.get('MAILFROM') if mailfrom is None: raise ConfigurationError('Please set the MAILFROM environment variable') jobname = os.environ.get('JOBNAME') if jobname is None: raise ConfigurationError('Please set the JOBNAME environment variable') if len(sys.argv) == 1: raise ConfigurationError('No commandline parameters were passed!') # Run the command we get from the commandline arguments exitcode = 0 output = '' try: output = subprocess.check_output(sys.argv[1:], stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: output = e.output exitcode = e.returncode # Build mime message hostname = socket.getfqdn() mimetext = create_mail(hostname, jobname, mailfrom, mailto, exitcode, output) # Send it with SSMTP send_mail(mailto, mimetext) except ConfigurationError as e: print("Configuration error: ", e.message) except: print("Unexpected error: ", sys.exc_info()[0]) # Run main function main() |
Kom maar met die fakkels
Ik heb zelf ook nog wel wat kanttekeningen bij mijn scriptje, maar voor nu werkt het prima. 1 ding dat bijvoorbeeld mist is een afhandeling voor timeouts, dus als het sub process niet terugkomt. Een ander dingetje is als het subprocess erg veel regels produceert, dan gaat dit script geheugen vreten (of misschien wel vastlopen), omdat de output niet direct door wordt gegeven.
Maar dit zijn dus dingen die in mijn eigen situatie niet echt spelen momenteel en meer "nice to have" zijn.
Ask yourself if you are happy and then you cease to be.
Het enige dat ik zo snel zie, is dat het qua leesbaarheid, een extraction kan gebruiken for `send_mail` en `create_mail`. Anders dan dat... is't redelijk vergelijkbaar met mijn skillsLethalis schreef op donderdag 6 september 2018 @ 13:58:
[...]
Tsja, ik ben hoofdzakelijk .NET developer, maar toevallig pas ook nog Python gedaan. Onderstaand stukje code is een CRON job wrapper:
** weg gehaald, want de post was te lang, somehow **
Kom maar met die fakkelsMisschien leer ik er nog wat van.
Ik heb zelf ook nog wel wat kanttekeningen bij mijn scriptje, maar voor nu werkt het prima. 1 ding dat bijvoorbeeld mist is een afhandeling voor timeouts, dus als het sub process niet terugkomt. Een ander dingetje is als het subprocess erg veel regels produceert, dan gaat dit script geheugen vreten (of misschien wel vastlopen), omdat de output niet direct door wordt gegeven.
Maar dit zijn dus dingen die in mijn eigen situatie niet echt spelen momenteel en meer "nice to have" zijn.
Ik zal dan ook maar even code-dumpen:
*Code even in een quote gegooit, zodat het wordt afgekort. Scheelt spam spul enzo*main.py:
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import os import time import traceback import sys import MySQLdb import datetime from archivebot.channel import channel from archivebot.user import user from archivebot.savemessage import savemessage from archivebot.sendmessage import sendmessage from slackclient import SlackClient from websocket import WebSocketConnectionClosedException # This token is given when the bot is started in terminal slack_token = os.environ["SLACK_API_TOKEN"] dbuser = os.environ["DB_USER"] dbpwd = os.environ["DB_PASSWD"] dbname = os.environ["DB_NAME"] botkey = os.environ['BOTKEY'] def connect(): return MySQLdb.connect(host="localhost", # your host, usually localhost user=dbuser, # your username passwd=dbpwd, # your password db=dbname, use_unicode=True, charset="utf8mb4") # Makes bot user active on Slack # NOTE: terminal must be running for the bot to continue # Optionally, you can use supervisor. Supervisor conf to be shared maybe sc = SlackClient(slack_token) def handle_message(event, cursor, conn): if 'username' in event and event['username'] == 'StripeSlackBot': return # If it's a DM, treat it as a search query if event['channel'][0] == 'D': sendmessage().handle_query(sc, event, cursor, conn) return elif '<@' + botkey + '>' in event['text']: savemessage().save(cursor, event, conn, sc) # fix up the text so we're not spamming a single channel event['text'] += ' limit:1' event['text'] = event['text'].replace('<@'+botkey+'>', '') sendmessage().handle_query(sc, event, cursor, conn) return else: savemessage().save(cursor, event, conn, sc) return # Loop # @todo Daemonize if sc.rtm_connect(): conn = connect() cursor = conn.cursor() user().update_users(sc, conn, cursor) channel().update_channels(sc, conn, cursor) print('Archive bot online. Messages will now be recorded...') while True: try: for event in sc.rtm_read(): conn = connect() cursor = conn.cursor() if 'subtype' in event and event['subtype'] in ['message_changed']: handle_message(event, cursor, conn) elif event['type'] == 'message' and 'text' in event: handle_message(event, cursor, conn) elif event['type'] in ['group_joined', 'member_joined_channel', 'channel_created', 'group_left', 'team_join']: user().update_users(sc, conn, cursor) channel().update_channels(sc, conn, cursor) elif event['type'] in ['reaction_added'] and event['item']['channel'][0] != 'D': savemessage().reaction(cursor, event, conn) conn.close() except WebSocketConnectionClosedException: sc.rtm_connect() except: print(traceback.format_exc()) time.sleep(1) else: print("Connection Failed, invalid token?")
En de meest smerige van alle, sendmessage.py:
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 from archivebot.channel import channel from archivebot.user import user import os import datetime import requests import urllib3.request as urlrequest import pysolr class sendmessage(): def handle_query(self, sc, event, cursor, conn): solr = pysolr.Solr('http://localhost:8983/solr/Firesphere-StripeSlack-Indexes-SlackIndex/') try: text = [] localUser = None localChannel = None sort = 'desc' setSort = False limit = 10 start = 0 searchquery = { 'search': event['text'], 'search_cat': 'Slackbot', 'idsite': 9, 'rec': 1, 'apiv': 1, 'rand': event['ts'], '_id': event['user'].encode('hex'), } params = event['text'].lower().split() for p in params: # Handle emoji # usual format is " :smiley_face: " if len(p) > 2 and p[0] == ':' and p[-1] == ':': text.append(p) continue p = p.split(':') if len(p) == 1: if p[0] == 'help': sc.api_call( "chat.postMessage", channel=event['channel'], text='Usage:\n' + '<query> from:<user> in:<channel> sort:asc|desc limit:<number> start:<number>\n\n' + 'query: The text to search for.\n' + 'user (optional): Limit the search to one user, the username. Default: None\n' + 'channel (optional): Limit the search to one channel, the channel name. Default: None\n' + 'sort (optional): Either `asc` to search starting with the oldest messages, or `desc` to start from the newest. Default: Relevancy.\n' + 'limit (optional): The number of responses to return. Default 10\n' + 'start (optional): The offset of the results. E.g. to see the next 10 records. Default: 0\n' + 'Example:\n> composer from:@StripeSlackBot in:#general sort:desc limit:20 start:10\n' '---') text.append(p[0]) if len(p) == 2: if p[0] == 'from': localUser = user().get_user_by_name(cursor, p[1].replace('@', '').strip()) if localUser == None: raise ValueError('User %s not found' % p[1]) if p[0] == 'in': localChannel = channel().get_channel_by_name(cursor, p[1].replace('#', '').strip()) if localChannel == None: raise ValueError('Channel %s not found' % p[1]) if p[0] == 'sort': if p[1] in ['asc', 'desc']: sort = p[1] setSort = True else: raise ValueError('Invalid sort order %s' % p[1]) if p[0] == 'limit': try: limit = int(p[1]) except: raise ValueError('%s is not a valid number' % p[1]) if p[0] == 'start': try: start = int(p[1]) except: raise ValueError('%s is not a valid number' % p[1]) args = {} fq = '' if localUser: fq += '+(Firesphere\\\\StripeSlack\\\\Models\\\\Message_UserID:%s)' % localUser[0] if localChannel: fq += '+(Firesphere\\\\StripeSlack\\\\Models\\\\Message_ChannelID:%s)' % localChannel[0] if setSort: args.update({'Firesphere\\\\StripeSlack\\\\Models\\\\Message_RealDate': sort}) if limit: args.update({'rows': limit}) if fq != '': args.update({'fq': fq}) if start > 0: args.update({'start': start}) solrResults = solr.search(' '.join(text), **args) searchquery.update({'search_count': solrResults.hits}) tracking = analytics.url/piwik/?params if solrResults: for result in solrResults.docs: link = 'https://slackarchive.silverstripe.org/slack-archive/message/' + str(result['ID']) msgUser = 'SELECT SlackId FROM SlackUser WHERE ID = %s' cursor.execute(msgUser, [result['Firesphere\\StripeSlack\\Models\\Message_UserID']]) userID = cursor.fetchone() msgChannel = 'SELECT SlackId FROM Channel WHERE ID = %s' cursor.execute(msgChannel, [result['Firesphere\\StripeSlack\\Models\\Message_ChannelID']]) channelID = cursor.fetchone() message = ''.join(['Message by %s, on %s, in %s\n>>> %s\n---\n\n> Link to archive: %s\n' % ( '<@' + userID[0] + '>', result['Firesphere\\StripeSlack\\Models\\Message_RealDate'], '<#' + channelID[0] + '>', result['Firesphere\\StripeSlack\\Models\\Message_Message'], link )] ) sc.api_call( "chat.postMessage", channel=event['channel'], text=message ) searchHelptext="You can expand your search at https://slackarchive.silverstripe.org/slack-archive/search?Query=" + '%20'.join(text) sc.api_call( "chat.postMessage", channel=event['channel'], text=searchHelptext ) if event['channel'][0] != 'D': cursor.execute('SELECT ID FROM SlackUser WHERE SlackId = %s', [os.environ["BOTKEY"]]) botId = cursor.fetchone() cursor.execute('SELECT ID FROM Channel WHERE SlackID = %s', [event['channel']]) channelId = cursor.fetchone() cursor.execute('SELECT ID FROM Message WHERE Timestamp = %s AND ChannelID = %s', [event['ts'], channelId[0]]) previous = cursor.fetchone() cursor.execute('INSERT INTO Message (Created, LastEdited, Message, UserID, ChannelID, Timestamp, ParentID) VALUES(%s, %s, %s, %s, %s, %s, %s)', [datetime.datetime.now(), datetime.datetime.now(), searchHelptext, botId[0], channelId[0], event['ts'], previous[0]]) conn.commit() requests.get(tracking) else: sc.api_call( "chat.postMessage", channel=event['channel'], text='No results found' ) except ValueError as e: sc.api_call("chat.postMessage", channel=event['channel'], text=str(e))
Dit geval verwacht een bepaalde SQL structuur en een Solr instance voor search, structuur is gebaseerd op de standaard die SilverStripe (yah, duh, dat is waar ik voor werk) hanteerd. Nieuwe berichten worden elke 5 minuten naar Solr gestuurd voor de index en het domein in de code is hard-coded. En ja, domein bestaat en is een SilverStripe site die basically hetzelfde doet als deze code.
Verschil is, dat de Python code werkt met Slack, waar de website alleen maar gebruikt wat de Python code in de database heeft gepropt.
Indien mensen geinteresseerd zijn, de code slaat elk bericht in een Slack Workspace op in een database. Een ander stuk zorgt er voor dat alle nieuwe berichten elke X minuten naar Solr wordt gepushed zodat ze geindexed zijn voor search.
In de Slack Workspace kun je daarmee dus zoeken buiten de limiet van Slack voor gratis workspaces.
Ondersteund zijn bijvoorbeeld "@MyBotName zoek", en je krijgt 1 response, plus een link om verder te zoeken via de website.
Of je kan de bot direct aanspreken in de Slack DM, en je krijgt 10 resultaten terug.
Smerig dingetje, als het een mention is van de bot, pas ik het event van Slack aan, zodat er een limiet van 1 resultaat is, smerig, maar het werkt om te voorkomen dat ik een Slack channel vol spam
Fun fact: Je kan zien hoe erg ik bezig ben met functionaliteit vs. herbruikbaarheid aan m'n comments. Main.py was origineel een container die _alles_ deed... de refactor heeft duidelijk effect op mijn code comments gehad
[ Voor 77% gewijzigd door Firesphere op 06-09-2018 14:21 ]
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Ik zag in het smerige stukje code (sendmessage.py:59 en 63) None checks met een equality operator.Firesphere schreef op donderdag 6 september 2018 @ 14:01:
[...]
Ik zal dan ook maar even code-dumpen:
Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
Voor de rest word ik er een beetje duizelig van

Ask yourself if you are happy and then you cease to be.
Weer wat geleerd! Mijn linter en Python interpreter (en VSCode) vonden het allemaal prima, dus ik had het niet gezien. Thanks!Lethalis schreef op donderdag 6 september 2018 @ 14:25:
[...]
Ik zag in het smerige stukje code (sendmessage.py:59 en 63) None checks met een equality operator.
Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
Voor de rest word ik er een beetje duizelig van
Wat maakt je duizelig? Het meeste is eigenlijk alleen maar het opzoeken van de juiste referenties etc. voor Slack. Zoveel bijzonders gebeurd er eigenlijk niet
*edit*
Ah, `allow_equals:false` maakt m'n VSCode compleet over de rooie gaan inderdaad. Cool!
[ Voor 19% gewijzigd door Firesphere op 06-09-2018 14:39 . Reden: Ik snap BB Code nog steeds niet ]
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
De grote hoeveelheid nested if statementsFiresphere schreef op donderdag 6 september 2018 @ 14:29:
[...]
Wat maakt je duizelig? Het meeste is eigenlijk alleen maar het opzoeken van de juiste referenties etc. voor Slack. Zoveel bijzonders gebeurd er eigenlijk niet
Vooral in sendmessage.py. Ik zou de code met de eerste for loop waarschijnlijk afsplitsen in een aparte parse functie. Ook zou ik geen try catch gebruiken voor het controleren of iets een geldig getal is, maar een functie zoals isnumeric().
Python heeft geen switch() statement - ik heb het even opgezocht
[ Voor 14% gewijzigd door Lethalis op 06-09-2018 15:32 ]
Ask yourself if you are happy and then you cease to be.
in plaats van een switch hoor je gebruik te maken van een dictionary, maar dat is niet altijd even toepasselijk of handig. Zou zo ook niet 1,2,3 weten hoe dat goed te implementeren.Lethalis schreef op donderdag 6 september 2018 @ 15:17:
[...]
De grote hoeveelheid nested if statements
Vooral in sendmessage.py. Ik zou de code met de eerste for loop waarschijnlijk afsplitsen in een aparte parse functie. Ook zou ik geen try catch gebruiken voor het controleren of iets een geldig getal is, maar een functie zoals isnumeric().
Python heeft geen switch() statement - ik heb het even opgezocht- anders zou ik dat ook willen gebruiken in jouw code
[ Voor 8% gewijzigd door Gropah op 06-09-2018 15:43 ]
Que?Gropah schreef op donderdag 6 september 2018 @ 15:42:
[...]
in plaats van een switch hoor je gebruik te maken van een dictionary, maar dat is niet altijd even toepasselijk of handig. Zou zo ook niet 1,2,3 weten hoe dat goed te implementeren.
Een control mechanisme veranderen voor een datastructuur?
Edit: Ik zie wel wat voorbeeldjes online, maar dan moet je alsnog een if-clausule gaan toevoegen om de 'else / default' van een switch te fixen.
Edit2: Nee wacht, je kan natuurlijk de get functie gebruiken.
1
2
3
4
5
6
7
8
9
| a = 2; switchHack = { 1: "Foo", 2: "Bar", 3: "Baz" } print(switchHack.get(a, "Default")) |
Nee, ik vind het helemaal niks. Helemaal als je de krachtige Kotlin, Scala of Rust switch/when's kent.
[ Voor 38% gewijzigd door armageddon_2k1 op 06-09-2018 15:50 ]
Engineering is like Tetris. Succes disappears and errors accumulate.
De cognitieve complexiteit schiet door het dak inderdaad.Lethalis schreef op donderdag 6 september 2018 @ 15:17:
[...]
De grote hoeveelheid nested if statements
Vooral in sendmessage.py. Ik zou de code met de eerste for loop waarschijnlijk afsplitsen in een aparte parse functie. Ook zou ik geen try catch gebruiken voor het controleren of iets een geldig getal is, maar een functie zoals isnumeric().
Python heeft geen switch() statement - ik heb het even opgezocht- anders zou ik dat ook willen gebruiken in jouw code
Heb in m'n huidige project ook nog een stuk waarin we complete refactoring moeten doen van code die bol staat van de functies / methods met 100+ cognitive complexity.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Een switch is in veel gevallen ook gewoon syntax sugar coating, en wordt het onder de motorkap vertaalt naar if statement of een lookup table. Je kunt in Python een switch 'emuleren' door een lookup table te maken.armageddon_2k1 schreef op donderdag 6 september 2018 @ 15:45:
[...]
Que?
Een control mechanisme veranderen voor een datastructuur?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| def zero(): return "zero" def one(): return "one" def two(): return "two" switcher = { 0: zero, 1: one, 2: two } def numbers_to_strings(argument): func = switcher.get(argument, "nothing") return func() Input: numbers_to_strings(1) Output: One |
Bedankt voor 't complimentarmageddon_2k1 schreef op donderdag 6 september 2018 @ 10:09:
Leuk en leerzaam artikel. Dank daarvoor.
https://niels.nu
Zelf zou ik die main() op het einde binnen een if __name__ == "__main__" zetten. Of misschien de hele main() functie weghalen.
Maar da's natuurlijk allemaal muggenzifterij
Meer inhoudelijk: Ik vraag me af of een aantal ConfigurationErrors te combineren zijn (MAILTO, MAILFROM en JOBNAME), maar daar weet ik zo 1-2-3 ook geen elegantere oplossing voor. Daarnaast zou ik de output van de subprocess naar een tijdelijk bestand schrijven (Python heeft hier tempfile voor) om geheugenproblemen te voorkomen.
🠕 This side up
I prefereer dan weer ES. Niet zo zeer qua engine maar wel de stabiliteit en scale mogelijkheden. SOLR is me toch een partij vaak gecrashed hier en daar..Firesphere schreef op donderdag 6 september 2018 @ 13:37:
Terug in de Python wereld voor een eigen projectje. Wat heb ik dat gemist zeg, beetje roestig, en elke doorgewinterde Python expert zal m'n werk tot de fundering afbranden, maar toch, het werkt en hopelijk binnenkort een publiceerbaar stukje code.
Daar mee samenhangend, een Solr project (M'n Python werkje gebruikt Solr), damn dat is me een beest van een stuk software zeg. Ontiegelijk krachtig. Ik had echt geen idee dat er zo veel opties waren.
Overigens thx voor het sharen van je code, altijd leuk om door te lezen
🠕 This side up
Omdat dat eigenlijk de 'native' insteek van ES is. "Designed for the cloud" zeg maar. Solr heeft dan Solr Cloud met een zookeeper combo.Koenvh schreef op donderdag 6 september 2018 @ 20:38:
@Douweegbertje Uit interesse: In welk opzicht is Elastic Search beter schaalbaar?
Eigenlijk een lang verhaal kort; ES kan gewoon out of the box redundant met meerdere nodes werken. Solr niet
* whoami nog altijd fan van NHibernate voor complexe domain-models.Mugwump schreef op donderdag 6 september 2018 @ 12:52:
[...]
Ben er ook wel redelijk van teruggekomen. Het is vooral handig als je heel snel een CRUD-achtig applicatietje wilt opzetten met een API / UI. Bij complexere database-interactie moet je je toch al snel in allerlei onhandige bochten gaan wringen.
En juist als je wat basale CRUD doet is vaak een document store net zo handig. Weg is de impedence mismatch.
Al ben ik tegenwoordig wel niet zo veel meer met db's en ORM bezig; laatst nog eens Dapper gebruikt voor wat simpele data-access. Dat is dan wel geen full-blown ORM, maar ik was er wel best door gecharmeerd.
https://fgheysels.github.io/
Mijn .Net ervaring is wat beperkter dan mijn Java ervaring, maar wat maakt NHibernate zo fijn voor complexe domain-models? Hibernate vind ik juist wel wat tegenvallen op dat vlak.whoami schreef op donderdag 6 september 2018 @ 21:00:
[...]
* whoami nog altijd fan van NHibernate voor complexe domain-models.
Al ben ik tegenwoordig wel niet zo veel meer met db's en ORM bezig; laatst nog eens Dapper gebruikt voor wat simpele data-access. Dat is dan wel geen full-blown ORM, maar ik was er wel best door gecharmeerd.
Ik ben juist nog wel veel met data bezig en daardoor ook juist veel meer overgeschakeld op polyglot persistence. Het one size fits all datamodel in een SQL database levert bij een beetje forse hoeveelheid data al snel heel veel problemen op in combinatie met een ORM.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
So much voor het "uniforme" gedeelte van de URL. Dacht dat het nieuwsbericht zei dat ze er nog over nadachten hoe de URL om zeep te helpen, maar de expirimenten zijn al daar dus en nu al een aardige cluster fuck. Lijkt qua consistentie nu wel alsof ze PHP gesnoven hebben.
[ Voor 9% gewijzigd door gekkie op 06-09-2018 22:45 ]
Nou eigenlijk vind ik het wel een sterk punt.gekkie schreef op donderdag 6 september 2018 @ 22:45:
https://bugs.chromium.org/p/chromium/issues/detail?id=881410
So much voor het "uniforme" gedeelte van de URL. Dacht dat het nieuwsbericht zei dat ze er nog over nadachten hoe de URL om zeep te helpen, maar de expirimenten zijn al daar dus en nu al een aardige cluster fuck. Lijkt qua consistentie nu wel alsof ze PHP gesnoven hebben.
Dat iedereen een subdomain toevoegt genaamd 'www' slaat eigenlijk nergens op. De enige rede dat iedereen dat doet; is omdat iedereen het doet.
Vanuit het W3C kan je eigenlijk niet forceren dat het bullshit is. Immers is een subdomain een valid standaard.
Dus dan moet je het hebben van andere (grote) instanties. Een browser is een goed voorbeeld, net zoals bijvoorbeeld Google (ranking e.d.) die https konden "forceren".
Waarom is het wel ok dat browser letterlijk over de zeik gaan als er geen valid certificaat is? Waarom krijg je een shitload aan warnings als een site niet veilig is? Waarom ben je beschermd (sort of..) tegen XSS?
Eigenlijk is er een huge-ass list van items die een browser "regelt" wat inherent gelijk is aan deze change. Vele waarvan we eigenlijk niet meer bewust van zijn.
Hoe grappig ik python soms ook vindt, er heeft echt iemand een punt van zitten maken dat python dingen anders moet doen dan andere talen. Geen do-while ("not pythonic!"), maar wel een while-else. Bedankt joh, daar hebben we wat aan.armageddon_2k1 schreef op donderdag 6 september 2018 @ 15:45:
Nee, ik vind het helemaal niks. Helemaal als je de krachtige Kotlin, Scala of Rust switch/when's kent.
Heeft geen speciale krachten en is daar erg boos over.
Mjah dat is nou net het probleem, niet iedereen voegt het toe. www.example.com en example.com kunnen prima naar andere zaken verwijzen.Douweegbertje schreef op donderdag 6 september 2018 @ 23:08:
[...]
Nou eigenlijk vind ik het wel een sterk punt.
Dat iedereen een subdomain toevoegt genaamd 'www' slaat eigenlijk nergens op. De enige rede dat iedereen dat doet; is omdat iedereen het doet.
Vanuit het W3C kan je eigenlijk niet forceren dat het bullshit is. Immers is een subdomain een valid standaard.
Dus dan moet je het hebben van andere (grote) instanties. Een browser is een goed voorbeeld, net zoals bijvoorbeeld Google (ranking e.d.) die https konden "forceren".
Waarom is het wel ok dat browser letterlijk over de zeik gaan als er geen valid certificaat is? Waarom krijg je een shitload aan warnings als een site niet veilig is? Waarom ben je beschermd (sort of..) tegen XSS?
Eigenlijk is er een huge-ass list van items die een browser "regelt" wat inherent gelijk is aan deze change. Vele waarvan we eigenlijk niet meer bewust van zijn.
Met als gevolg dat je het ook niet zomaar kunt weglaten, ook al is het alleen maar in de representatie.
Vervolgens zie je dat ze zich in onmogelijke bochten moeten gaan wringen om een algoritme te bedenken om het toch te hiden. Door requests te doen naar zowel met als zonder subdomain en afhankelijk van de http status dan wel of niet dingen te gaan tonen. why oh why ?
Ik zie niet in wat het creatief hiden van een deel van de URL voor verbetering is, ondanks dat het gebruik van dat deel vaak (maar niet altijd) "overbodig" is.
En als dit dan zo'n ding was, waarom zijn we dan aan unicode urls begonnen (snap het wel voor de fijne inclusiviteit van de rest van de wereld met wat spannender schrift). Maar om nou te zeggen dat dat de begrijpbaarheid van URLs verhoogd.
Als de "www" in een url al te veel voor je is, leer wat bij of blijf dan gewoon van van het internet af.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Elegantie is uiteraard niet het enige criterium (mag ik hopen) waarop iets "geweldig" zou kunnen zijn, maar welke talen acht jij dan eleganter (en zijn ze vervolgens ook nog "geweldig") ?Mugwump schreef op donderdag 6 september 2018 @ 23:58:
Wat er zo geweldig moet zijn aan Python ontgaat mij ook volledig. Er zijn veel elegantere talen.
Eerlijk gezegd... verwar ik ze zelf momenteel ook regelmatigLethalis schreef op donderdag 6 september 2018 @ 15:17:
[...]
De grote hoeveelheid nested if statements

Ik ben dan ook niet echt "trots" op de sendmessage. Die heb ik expres gekozen omdat het dus de smerigste van allemaal isVooral in sendmessage.py. Ik zou de code met de eerste for loop waarschijnlijk afsplitsen in een aparte parse functie. Ook zou ik geen try catch gebruiken voor het controleren of iets een geldig getal is, maar een functie zoals isnumeric().
Zoaals uitgelegd hier boven... feedback zeer welkom!Mugwump schreef op donderdag 6 september 2018 @ 15:48:
[...]
De cognitieve complexiteit schiet door het dak inderdaad.
Heb in m'n huidige project ook nog een stuk waarin we complete refactoring moeten doen van code die bol staat van de functies / methods met 100+ cognitive complexity.
Ik ben zo gewend aan Solr tegenwoordig... ES is niet campatible genoeg met SilverStripe momenteel (naar mijn mening), en mijn ervaring met Solr, voor mij was de keuze vrij simpel.Douweegbertje schreef op donderdag 6 september 2018 @ 20:32:
[...]
I prefereer dan weer ES. Niet zo zeer qua engine maar wel de stabiliteit en scale mogelijkheden. SOLR is me toch een partij vaak gecrashed hier en daar..
Overigens thx voor het sharen van je code, altijd leuk om door te lezen
Ik ben niet anti-ES ofzo (eerder, ik vind het een top product), maar te weinig ervaring om het snel en effectief te laten werken. Solr daarentegen kostte me een half uur aan configuratie (en anderhalve dag aan indexeren van alle berichten in Slack, maar dat is ongerelateerd aan Solr
Ik vind Python een erg elegante taal eigenlijk. Hoofdzakelijk omdat de indentatie zo belangrijk is. Het dwingt de schrijver om na te denken over indentatie (en veel auto-formatters doen het ook fout, wat voor rare situaties zorgt). Deze geforceerde indentatie is vooral bij junior engineers belangrijk vind ik, omdat het er voor zorgt dat ze de gewoonte van goede indentatie leren.Mugwump schreef op donderdag 6 september 2018 @ 23:58:
Wat er zo geweldig moet zijn aan Python ontgaat mij ook volledig. Er zijn veel elegantere talen.
In mijn geval, is het gewoon de beste oplossing om een Slack bot te schrijven. Flexibeler dan een web-interface in PHP/.NET/Whatever, omdat het draait als een background daemon in plaats van een echte web service.
Maar uiteindelijk, is elke taal hetzelfde. Het is alleen andere woordjes voor bepaalde dingen.
[ Voor 158% gewijzigd door Firesphere op 07-09-2018 04:54 ]
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Nee, dit is legacy. Vroeger had je alleen maar WWW.domein.nl want dat was het internet. Iets anders ervoor was bv FTP.domein.nl voor de FTP en SMTP.domein.nl voor de smtp server. WWW is net zo goed een subdomein als kain.tweakblogs.net alleen weten de techneuten (en steeds meer normale gebruikers ook wel) dat in heel veel gevallen het domein zonder WWW en met WWW ervoor dezelfde site oplevert (niet 100% al weet ik eigenlijk niet zo goed waarom er mensen zijn die WWW ergens anders naartoe laten verwijzen maar goed). Waarom moet een browser een onderscheid maken tussen subdomein WWW en andere domeinen? Een browser moet gewoon de site openen, punt. En, tonen aan de gebruiker wat de url is....Douweegbertje schreef op donderdag 6 september 2018 @ 23:08:
Dat iedereen een subdomain toevoegt genaamd 'www' slaat eigenlijk nergens op. De enige rede dat iedereen dat doet; is omdat iedereen het doet.
Vanuit het W3C kan je eigenlijk niet forceren dat het bullshit is. Immers is een subdomain een valid standaard.
Exact expert nodig?
Douweegbertje schreef op donderdag 6 september 2018 @ 23:08:
[...]
Nou eigenlijk vind ik het wel een sterk punt.
Dat iedereen een subdomain toevoegt genaamd 'www' slaat eigenlijk nergens op.
nescafe in "URI > URL > Host > www, deprecated?"Crazy D schreef op vrijdag 7 september 2018 @ 06:38:
al weet ik eigenlijk niet zo goed waarom er mensen zijn die WWW ergens anders naartoe laten verwijzen maar goed
[ Voor 25% gewijzigd door RayNbow op 07-09-2018 06:48 ]
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 from archivebot.channel import channel from archivebot.user import user import os import datetime import requests import urllib3.request as urlrequest import pysolr class sendmessage(): def handle_query(self, sc, event, cursor, conn): solr = pysolr.Solr(os.environ['SOLR']) try: text, args = self.buildQueryParams(event, sc, cursor) solrResults = solr.search(' '.join(text), **args) if solrResults: for result in solrResults.docs: message = self.createMessage(result, cursor) sc.api_call( "chat.postMessage", channel=event['channel'], text=message ) searchHelptext="You can expand your search at https://slackarchive.silverstripe.org/slack-archive/search?Query=" + '%20'.join(text) sc.api_call( "chat.postMessage", channel=event['channel'], text=searchHelptext ) if event['channel'][0] != 'D': self.saveResponse(cursor, event, searchHelptext, conn) else: sc.api_call( "chat.postMessage", channel=event['channel'], text='No results found' ) self.trackSearch(event, solrResults.hits) except ValueError as e: sc.api_call("chat.postMessage", channel=event['channel'], text=str(e)) def createMessage(self, result, cursor): link = 'https://slackarchive.silverstripe.org/slack-archive/message/' + str(result['ID']) userID = user().get_user_by_id(cursor, result['Firesphere\\StripeSlack\\Models\\Message_UserID']) channelID = channel().get_channel_by_id(cursor, result['Firesphere\\StripeSlack\\Models\\Message_ChannelID']) message = ''.join(['Message by %s, on %s, in %s\n>>> %s\n---\n\n> Link to archive: %s\n' % ( '<@' + userID[0] + '>', result['Firesphere\\StripeSlack\\Models\\Message_RealDate'], '<#' + channelID[0] + '>', result['Firesphere\\StripeSlack\\Models\\Message_Message'], link )] ) return message def saveResponse(self, cursor, event, searchHelptext, conn): botId = user().get_user_id(cursor, os.environ['BOTKEY']) channelId = channel().get_channel_id(cursor, event['channel']) cursor.execute('SELECT ID FROM Message WHERE UUID = %s', [event['client_msg_id']]) parent = cursor.fetchone() cursor.execute('INSERT INTO Message (Created, LastEdited, Message, UserID, ChannelID, Timestamp, ParentID) VALUES(%s, %s, %s, %s, %s, %s, %s)', [datetime.datetime.now(), datetime.datetime.now(), searchHelptext, botId[0], channelId[0], event['ts'], parent[0]]) conn.commit() def buildSolrArgs(self, localUser, localChannel, sort, limit, start): args = {} fq = '' if localUser: fq += '+(Firesphere\\\\StripeSlack\\\\Models\\\\Message_UserID:%s)' % localUser[0] if localChannel: fq += '+(Firesphere\\\\StripeSlack\\\\Models\\\\Message_ChannelID:%s)' % localChannel[0] if sort is not None: args.update({'Firesphere\\\\StripeSlack\\\\Models\\\\Message_RealDate': sort}) if limit: args.update({'rows': limit}) if fq != '': args.update({'fq': fq}) if start > 0: args.update({'start': start}) return args def buildQueryParams(self, event, sc, cursor): text = [] localUser = None localChannel = None sort = None setSort = False limit = 10 start = 0 words = event['text'].lower().split() for word in words: # Handle emoji # usual format is " :smiley_face: " if len(word) > 2 and word[0] == ':' and word[-1] == ':': text.append(word) continue word = word.split(':') if len(word) == 1: # Send a help message if word[0] == 'help' and event['channel'][0] == 'D': sc.api_call( "chat.postMessage", channel=event['channel'], text='Usage:\n' + '<query> from:<user> in:<channel> sort:asc|desc limit:<number> start:<number>\n\n' + 'query: The text to search for.\n' + 'user (optional): Limit the search to one user, the username. Default: None\n' + 'channel (optional): Limit the search to one channel, the channel name. Default: None\n' + 'sort (optional): Either `asc` to search starting with the oldest messages, or `desc` to start from the newest. Default: Relevancy.\n' + 'limit (optional): The number of responses to return. Default 10\n' + 'start (optional): The offset of the results. E.g. to see the next 10 records. Default: 0\n' + 'Example:\n> composer from:@StripeSlackBot in:#general sort:desc limit:20 start:10\n' '---') text.append(word[0]) if len(word) == 2: if word[0] == 'from': localUser = user().get_user_by_name(cursor, word[1].replace('@', '').strip()) if localUser is None: raise ValueError('User %s not found' % word[1]) if word[0] == 'in': localChannel = channel().get_channel_by_name(cursor, word[1].replace('#', '').strip()) if localChannel is None: raise ValueError('Channel %s not found' % word[1]) if word[0] == 'sort' and word[1] in ['asc', 'desc']: sort = word[1] if word[0] == 'limit' and word[1].isnumeric(): limit = int(word[1]) if word[0] == 'start' and word[1].isnumeric(): start = int(word[1]) args = self.buildSolrArgs(localUser, localChannel, sort, limit, start) return text, args def trackSearch(self, event, numResults): """ Track searches in Piwik @todo Add a useragent and stuff, it's showing up weird in Piwik """ searchquery = { 'search': event['text'], 'search_cat': 'Slackbot', 'idsite': 9, 'rec': 1, 'apiv': 1, 'rand': event['ts'], '_id': event['user'].encode('hex'), 'search_count': numResults } tracking = 'https://piwik.casa-laguna.net/piwik.php?' + urlrequest.urlencode(searchquery) requests.get(tracking)
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Dan stap je wel erg snel over het verschil in expressiviteit tussen verschillende talen. Is het in VB net zo makkelijk om te werken met immutable datastructuren als in F#? Als je een relationele database wil uitvragen, kies je Pascal of SQL? Biedt Go higher kinded types?Firesphere schreef op vrijdag 7 september 2018 @ 01:43:
Maar uiteindelijk, is elke taal hetzelfde. Het is alleen andere woordjes voor bepaalde dingen.
De obligate link naar Paul Graham laat ik aan een ander
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Jep, ik generaliseer nogal daar, maar ik sta toch achter mijn reactie. Natuurlijk zijn er een hoop verschillen, maar de logische denkwijze om van A naar B te komen, is hetzelfdekenneth schreef op vrijdag 7 september 2018 @ 07:39:
[...]
Dan stap je wel erg snel over het verschil in expressiviteit tussen verschillende talen. Is het in VB net zo makkelijk om te werken met immutable datastructuren als in F#? Als je een relationele database wil uitvragen, kies je Pascal of SQL? Biedt Go higher kinded types?
De obligate link naar Paul Graham laat ik aan een ander
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
Dat is nogal een imperatieve denkwijze.Firesphere schreef op vrijdag 7 september 2018 @ 07:42:
[...]
Jep, ik generaliseer nogal daar, maar ik sta toch achter mijn reactie. Natuurlijk zijn er een hoop verschillen, maar de logische denkwijze om van A naar B te komen, is hetzelfde
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Ow?
I'm not a complete idiot. Some parts are missing.
.Gertjan.: Ik ben een zelfstandige alcoholist, dus ik bepaal zelf wel wanneer ik aan het bier ga!
* RayNbow kijkt naar Prolog...Firesphere schreef op vrijdag 7 september 2018 @ 07:42:
[...]
Jep, ik generaliseer nogal daar, maar ik sta toch achter mijn reactie. Natuurlijk zijn er een hoop verschillen, maar de logische denkwijze om van A naar B te komen, is hetzelfde
* RayNbow kijkt naar @Firesphere...
Succes.
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Pfff, dat heeft ook al geen do-while-loops. Eigenwijze figuren.
Ook geen while-loops, en ook geen loops. Eigenwijze figuren.
Heeft geen speciale krachten en is daar erg boos over.
Zoals Raynbow al zegt zijn er wel heel wat andere paradigma zoals het logische van talen als Prolog. Door de dominantie van de imperatieve paradigma kennen mensen dat soort zaken vaak niet eens, maar het is een hele andere manier van denken. Bij imperatieve talen denk je in 'stapjes die je achter elkaar uitvoert.
Stel dat je een Sudoku wilt oplossen. In een imperatieve taal ga je de oplossing bedenken in vormen van stapjes die je uitvoert. Hoogstwaarschijnlijk kom je dan uit op iets wat op een backtrackingalgoritme lijkt.
In Prolog formuleer je simpelweg het probleem. Hier een voorbeeldje van een volledige Sudoku solver in Prolog:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| sudoku(Puzzle) :- flatten(Puzzle, Tmp), Tmp ins 1..9, Rows = Puzzle, transpose(Rows, Columns), blocks(Rows, Blocks), maplist(all_distinct, Rows), maplist(all_distinct, Columns), maplist(all_distinct, Blocks), maplist(label, Rows). blocks([A,B,C,D,E,F,G,H,I], Blocks) :- blocks(A,B,C,Block1), blocks(D,E,F,Block2), blocks(G,H,I,Block3), append([Block1, Block2, Block3], Blocks). blocks([], [], [], []). blocks([A,B,C|Bs1],[D,E,F|Bs2],[G,H,I|Bs3], [Block|Blocks]) :- Block = [A,B,C,D,E,F,G,H,I], blocks(Bs1, Bs2, Bs3, Blocks). |
Zie de bron voor verder uitleg over hoe dat exact werkt.
Evenzeer is het denken in functionele talen die echt geen enkele vorm van state hebben heel anders dan in imperatieve talen, waar je altijd wel kunt terugvallen op iets van gedeelde state.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Identatie leren? Daar heb je toch een IDE voor?Firesphere schreef op vrijdag 7 september 2018 @ 01:43:
Ik vind Python een erg elegante taal eigenlijk. Hoofdzakelijk omdat de indentatie zo belangrijk is. Het dwingt de schrijver om na te denken over indentatie (en veel auto-formatters doen het ook fout, wat voor rare situaties zorgt). Deze geforceerde indentatie is vooral bij junior engineers belangrijk vind ik, omdat het er voor zorgt dat ze de gewoonte van goede indentatie leren.
Ik vind elegantie 'in the eye of the beholder', maar dit soort zaken worden juist door Pythonfans inderdaad vaak genoemd als reden dat Python zo geweldig is. Ik vind persoonlijk indentation als language construct namelijk zo ongeveer het meest onzalige idee allertijden.Firesphere schreef op vrijdag 7 september 2018 @ 01:43:
Ik vind Python een erg elegante taal eigenlijk. Hoofdzakelijk omdat de indentatie zo belangrijk is. Het dwingt de schrijver om na te denken over indentatie (en veel auto-formatters doen het ook fout, wat voor rare situaties zorgt). Deze geforceerde indentatie is vooral bij junior engineers belangrijk vind ik, omdat het er voor zorgt dat ze de gewoonte van goede indentatie leren.
Daarnaast heb je idee en uitwerking. het idee is wellicht dat je juist zou afdwingen dat mensen geen eindeloze nesting zouden toepassen met totaal onoverzienbare functies tot gevolg, maar de praktijk is vaak anders zoals jouw voorbeeld al aangeeft.
Het idee bij Pythondevelopers is vaak dat talen als Java en C# enorm verbose zijn en gigantisch ingewikkeld om hele simpele dingen te doen. Nou is dat beeld op veel vlakken sowieso al wel vaak gedateerd, maar er zijn ook heel wat nieuwe talen bijgekomen in dezelfde ecosystemen. Zo heb je Kotlin en F# bijvoorbeeld.
Python is ook wel prima voor scripting / automatisering, data science en dingen die je even snel in elkaar moet klussen, maar voor applicaties van serieuze omvang levert het in mijn ogen toch vooral een onoverzichtelijke brei op, maar ik heb persoonlijk ook echt een schurfthekel aan dynamic typing.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Dit is ook exact mijn mening.Mugwump schreef op vrijdag 7 september 2018 @ 09:39:
[...]
Python is ook wel prima voor scripting / automatisering, data science en dingen die je even snel in elkaar moet klussen, maar voor applicaties van serieuze omvang levert het in mijn ogen toch vooral een onoverzichtelijke brei op, maar ik heb persoonlijk ook echt een schurfthekel aan dynamic typing.
Zodra mn python script > 50 lines heeft ga ik namelijk huilen van ellende.
Hoewel ik het zelf erg tof vind is er nog een ander negatief punt;
python2.7 vs 3 en dan nog die dependency hell. De 1 required v1.2 en de ander 1.4 en dan sloop je de rest en dan zet je pip erop en dan valt heel python uit elkaar.
Zeker op een system waar je toch al snel diverse python-based dingen gebruikt kan je best tegen dit soort grappen aanlopen.
Je kunt er ook echt heel mooi 'verkennend' in programmeren middels Jupyter notebooks wat het erg geschikt maakt voor allerhande data science dingen.Douweegbertje schreef op vrijdag 7 september 2018 @ 09:50:
[...]
Dit is ook exact mijn mening.
Zodra mn python script > 50 lines heeft ga ik namelijk huilen van ellende.
Hoewel ik het zelf erg tof vind is er nog een ander negatief punt;
python2.7 vs 3 en dan nog die dependency hell. De 1 required v1.2 en de ander 1.4 en dan sloop je de rest en dan zet je pip erop en dan valt heel python uit elkaar.![]()
Zeker op een system waar je toch al snel diverse python-based dingen gebruikt kan je best tegen dit soort grappen aanlopen.
Collega van me was laatst een dag bezig om uit te vinden hoe hij een methode in een SDK nou precies moest aanroepen in Python.
Nou lag dat vooral aan hem, want ik was er binnen een kwartier wel uit, maar dynamic typing helpt dan ook echt niet. Bij een statically typed language miept je compiler tenminste gelijk.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Hindley-Milner, algebraic data types. Ik ben het eindelijk gaan waarderen. In dit tempo ga ik over tien jaar zelfs Haskell waarderen (en begrijpen)
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Wij hebben hier een stagiair die een onderzoek doet specifiek gericht op devven dus dit lijkt me de uitgelezen plek om buiten het enquete-topic de juiste doelgroep aan te spreken
Hoeder van het Noord-Meierijse dialect
"www" is een subdomein en werd voornamelijk populair omdat het vaak de naam was voor de machine bedoelt voor de buiten wereld (world-wide). Zo waren er vroeger ook site's die "w3" of "web" gebruikte als naam voor hun na buiten gerichte server. De reden waarom de prefix van "www" zo populair werd is omdat het zeer duidelijk aangaf dat het om een website ging en niet om een fysieke locatie. Dit was nog in de tijd dat men dacht dat voor online shoppen je een fysieke winkel moest simuleren waarbij je virtueel door gangpaden liep en waarbij je producten uit een virtueel rek pakte. Als je een beeld wilt vormen dan kan je het vergelijken door in VR door een supermarkt te lopen... alleen ipv van VR moet je denken aan een CRT monitor met een resolutie van 800x600 (als je geluk had!).
Zie men "Kom kijken bij ons op www..." dan wist men dan ze een computer moesten pakken ipv het stratenboek.
Tegenwoordig is "www" niet meer nodig om te communiceren dat het om een website gaat. Echter waar Google de plank mis slaat is dat er technische een heleboel redenen zijn. Het is namelijk een subdomein. En cookies van een hoofddomein gaan mee naar het subdomein. Twitter heeft geen "www" domein en toen ze ook afbeeldingen toe gingen staan, moesten ze een nieuw domein nemen. Anders kreeg je bij elke afbeelding namelijk ook de cookies.
Zelf heb ik het ook al een keer meegemaakt waarbij site.com/a en site.com/b een mapping hadden naar twee verschillende sites. Echter omdat ze dezelfde cookie gebruiken om je sessie bij te houden moest je twee verschillende browsers gebruiken.
Dan is er nog een derde reden: Het kan verwijzen naar verschillende systemen.
Als jij je mailserver en webserver zonder subdomein draait op twee verschillende machines dan moet er een systeem tussen gezet worden om het verkeer te splitsen. Nu is een mailserver een slecht voorbeeld omdat clients moeten kijken naar de MX-record, maar je moest soms best creatief zijn met port forwarding. Echter dat werkte alleen maar als de andere partij geen firewall had die alles blokkeerde behalve de gebruikelijke porten.
Persoonlijk ben ik overtuigd dat www staat voor WoutersWonderlijkeWereld
"Doubt—the concern that my views may not be entirely correct—is the true friend of wisdom and (along with empathy, to which it’s related) the greatest enemy of polarization." -- Václav Havel
www kán een subdomein zijn maar is meestal gewoon een hostnaam. Als het wel een subdomein is dan moet er ook een wildcard record in DNS zijn. Als dat wildcard record naar hetzelfde IP verwijst als het www-record dan zal www.domein.tld naar dezelfde site wijzen als domein.tld.DevWouter schreef op vrijdag 7 september 2018 @ 12:14:
Uhm... Auw...? Ik begin hier te toch een beetje te merken dat ik een ouwe rot ben.
"www" is een subdomein en werd voornamelijk populair omdat het vaak de naam was voor de machine bedoelt voor de buiten wereld (world-wide). Zo waren er vroeger ook site's die "w3" of "web" gebruikte als naam voor hun na buiten gerichte server. De reden waarom de prefix van "www" zo populair werd is omdat het zeer duidelijk aangaf dat het om een website ging en niet om een fysieke locatie. Dit was nog in de tijd dat men dacht dat voor online shoppen je een fysieke winkel moest simuleren waarbij je virtueel door gangpaden liep en waarbij je producten uit een virtueel rek pakte. Als je een beeld wilt vormen dan kan je het vergelijken door in VR door een supermarkt te lopen... alleen ipv van VR moet je denken aan een CRT monitor met een resolutie van 800x600 (als je geluk had!).
Zie men "Kom kijken bij ons op www..." dan wist men dan ze een computer moesten pakken ipv het stratenboek.
Tegenwoordig is "www" niet meer nodig om te communiceren dat het om een website gaat. Echter waar Google de plank mis slaat is dat er technische een heleboel redenen zijn. Het is namelijk een subdomein. En cookies van een hoofddomein gaan mee naar het subdomein. Twitter heeft geen "www" domein en toen ze ook afbeeldingen toe gingen staan, moesten ze een nieuw domein nemen. Anders kreeg je bij elke afbeelding namelijk ook de cookies.
Zelf heb ik het ook al een keer meegemaakt waarbij site.com/a en site.com/b een mapping hadden naar twee verschillende sites. Echter omdat ze dezelfde cookie gebruiken om je sessie bij te houden moest je twee verschillende browsers gebruiken.
Dan is er nog een derde reden: Het kan verwijzen naar verschillende systemen.
Als jij je mailserver en webserver zonder subdomein draait op twee verschillende machines dan moet er een systeem tussen gezet worden om het verkeer te splitsen. Nu is een mailserver een slecht voorbeeld omdat clients moeten kijken naar de MX-record, maar je moest soms best creatief zijn met port forwarding. Echter dat werkte alleen maar als de andere partij geen firewall had die alles blokkeerde behalve de gebruikelijke porten.
Persoonlijk ben ik overtuigd dat www staat voor WoutersWonderlijkeWereld
Je hebt gewoon veel meer controle dan met pakweg Entity Framework + de mapping-mogelijkheden zijn wel heel goed. Een legacy database mappen naar een min-of-meer OK object-model is in NHibernate mogelijk, daar waar het in EF bv veel moeilijker is. De leercurve is dan ook wel wat steiler.Mugwump schreef op donderdag 6 september 2018 @ 21:11:
[...]
Mijn .Net ervaring is wat beperkter dan mijn Java ervaring, maar wat maakt NHibernate zo fijn voor complexe domain-models? Hibernate vind ik juist wel wat tegenvallen op dat vlak.
Ik ben juist nog wel veel met data bezig en daardoor ook juist veel meer overgeschakeld op polyglot persistence. Het one size fits all datamodel in een SQL database levert bij een beetje forse hoeveelheid data al snel heel veel problemen op in combinatie met een ORM.
En misschien was ik wat ongenuanceerd: ik ben niet veel meer bezig met relationele data, momenteel
/dit topic gaat veel te snel.
https://fgheysels.github.io/
https://github.com/chromi...tter/url_formatter.cc#L71gekkie schreef op donderdag 6 september 2018 @ 23:19:
[...]
Vervolgens zie je dat ze zich in onmogelijke bochten moeten gaan wringen om een algoritme te bedenken om het toch te hiden.
Iemand op hackernews verwees hier naar; zit gewoon geen logica achter dus

In de reacties bij de Chromium bug kwam ook al langs dat iets als foo.www.example.com ook wordt omgezet naar foo.example.com, dat is natuurlijk ook al helemaal raar.hellum schreef op vrijdag 7 september 2018 @ 14:47:
[...]
https://github.com/chromi...tter/url_formatter.cc#L71
Iemand op hackernews verwees hier naar; zit gewoon geen logica achter dus
Hier heb ik nog nooit van gehoord, dus ik ben zeer benieuwd naar welke rfc dit beweert?downtime schreef op vrijdag 7 september 2018 @ 12:57:
[...]
www kán een subdomein zijn maar is meestal gewoon een hostnaam. Als het wel een subdomein is dan moet er ook een wildcard record in DNS zijn. Als dat wildcard record naar hetzelfde IP verwijst als het www-record dan zal www.domein.tld naar dezelfde site wijzen als domein.tld.
RFC1034roeleboel schreef op vrijdag 7 september 2018 @ 15:03:
[...]
Hier heb ik nog nooit van gehoord, dus ik ben zeer benieuwd naar welke rfc dit beweert?
Dit topic is gesloten.
Dit topic is niet de plaats om te lopen helpdesken. De Coffee Corner is primair bedoeld als uitlaatklep voor iedereen in de Devschuur® en niet als vraagbaak.