Oh ja
Niet mee eens dat er geen verdere eisen mogen worden gesteld. Maar dat moet dan wel in de vorm van sterkte, niet in de vorm van x cijfers en y leestekens. Op zo'n manier dat een "correct horse battery staple" ook gewoon wordt geaccepteerd.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Zullen we weer terug gaan naar slechte programmeervoorbeelden?
| Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72
Gezien bij een collega, die al jarenlang C en Fortran programmeert en nu overmoet op Python:
python script wordt opgeroepen in shell script (standaard procedure bij ons)
als input heeft het python script de datum van een run van data
meneer vond het logisch om dat timestamp veld in python te coderen als
timestamp = %timestamp%
en vervolgens in het shell script een search en replace van het python script te doen, en %timestamp% te vervangen door de effectieve waarde van de timestamp, dat weg te schrijven als een nieuw python script, dat dan te runnen, en daarna dat gemodificeerde python script weer te verwijderen
python script wordt opgeroepen in shell script (standaard procedure bij ons)
als input heeft het python script de datum van een run van data
meneer vond het logisch om dat timestamp veld in python te coderen als
timestamp = %timestamp%
en vervolgens in het shell script een search en replace van het python script te doen, en %timestamp% te vervangen door de effectieve waarde van de timestamp, dat weg te schrijven als een nieuw python script, dat dan te runnen, en daarna dat gemodificeerde python script weer te verwijderen
Bloemen scheiden het gras in de tuin.
Tja, dat is natuurlijk veel te omslachtigErycius schreef op zondag 19 maart 2017 @ 20:28:
Gezien bij een collega, die al jarenlang C en Fortran programmeert en nu overmoet op Python:
python script wordt opgeroepen in shell script (standaard procedure bij ons)
als input heeft het python script de datum van een run van data
meneer vond het logisch om dat timestamp veld in python te coderen als
timestamp = %timestamp%
en vervolgens in het shell script een search en replace van het python script te doen, en %timestamp% te vervangen door de effectieve waarde van de timestamp, dat weg te schrijven als een nieuw python script, dat dan te runnen, en daarna dat gemodificeerde python script weer te verwijderen

Bash:
1
| sed 's/%timestamp%/20170319/g' script.py | python |
Hoe deed ie dat in C? Search-and-replace en dan opnieuw compileren? Of een search-and-replace in de binary doen?Erycius schreef op zondag 19 maart 2017 @ 20:28:
Gezien bij een collega, die al jarenlang C en Fortran programmeert en nu overmoet op Python:
python script wordt opgeroepen in shell script (standaard procedure bij ons)
als input heeft het python script de datum van een run van data
meneer vond het logisch om dat timestamp veld in python te coderen als
timestamp = %timestamp%
en vervolgens in het shell script een search en replace van het python script te doen, en %timestamp% te vervangen door de effectieve waarde van de timestamp, dat weg te schrijven als een nieuw python script, dat dan te runnen, en daarna dat gemodificeerde python script weer te verwijderen
Ik zie de relevantie met zijn verleden ook niet helemaal

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Dan maak je gewoon winst met winkelen!
Pistolebob schreef op vrijdag 10 maart 2017 @ 15:26:
Otto.nl:
[afbeelding]
Negatieve aantallen van producten zijn toe te voegen aan de winkelwagen
objects of this type must match the following regular expression: (31-(0[13578]|1[02])-|(29|30)-(0[13-9]|1[0-2])-|(0[1-9]|1\\d|2[0-8])-(0[1-9]|1[0-2])-)([1-9]\\d{3}|0\\d{2}[1-9])|^(29-02-)((\\d{2})(0[48]|[2468][048]|[13579][26])|(0[48]|[2468][048]|[13579][26])00)
Ja zo kan je ook datums valideren
Ja zo kan je ook datums valideren
Let op: Mijn post bevat meningen, aannames of onwaarheden
Blijkbaar wordt het toch wel vaker gebruikt. Ik heb zelf deze weleens moeten ontleden, lijkt er wel op:Gamebuster schreef op maandag 28 augustus 2017 @ 12:53:
objects of this type must match the following regular expression: (31-(0\[13578]|1\[02])-|(29|30)-(0[13-9]|1[0-2])-|(0[1-9]|1\\d|2[0-8])-(0[1-9]|1[0-2])-)([1-9]\\d{3}|0\\d{2}[1-9])|^(29-02-)((\\d{2})(0\[48]|\[2468]\[048]|\[13579]\[26])|(0\[48]|\[2468]\[048]|\[13579]\[26])00)
Ja zo kan je ook datums valideren
((18|19|20)[0-9]{2}[-](0[13578]|1[02])[-]([012][1-9]|3[01]|[12][0])|(18|19|20)[0-9]{2}[-](0[469]|11)[-]([012][1-9]|30|[12][0])|(18|19|20)[0-9]{2}[-](02)[-](0[1-9]|1[0-9]|2[0-8])|(((18|19|20)(04|08|[2468][048]|[13579][26]))|2000)[-](02)[-]29|(18|19|20)[0-9]{2}[-](00)[-](00))
Kater? Eerst water, de rest komt later
Hetzelfde idee, maar wel andere schrijfwijze. Dit zijn dus geen copy/pasta's van elkaar die eventueel zijn aangepast... Dat betekent dat tenminste 2 personen het een goed idee vonden om dit te schrijvenHaan schreef op maandag 28 augustus 2017 @ 12:58:
[...]
Blijkbaar wordt het toch wel vaker gebruikt. Ik heb zelf deze weleens moeten ontleden, lijkt er wel op:
((18|19|20)[0-9]{2}[-](0\[13578]|1\[02])[-](\[012][1-9]|3\[01]|\[12]\[0])|(18|19|20)[0-9]{2}[-](0\[469]|11)[-](\[012][1-9]|30|\[12]\[0])|(18|19|20)[0-9]{2}[-](02)[-](0[1-9]|1[0-9]|2[0-8])|(((18|19|20)(04|08|\[2468]\[048]|\[13579]\[26]))|2000)[-](02)[-]29|(18|19|20)[0-9]{2}[-](00)[-](00))
Let op: Mijn post bevat meningen, aannames of onwaarheden
Het type mensen dat regular expressions op deze manier gebruiken zijn meestal niet het type waar je lekker mee een pint kan gaan drinken
- Jamie ZawinskiSome people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
https://niels.nu
Ik heb deze geleerd:
Regex is like violence - if it doesn’t solve your problems, you are not using enough of it.
Voor de volledigheid dan maar
quote: Jamie Zawinski"You are trying to shoehorn your existing preconceptions of how one
should program onto a vastly different (and older, and more internally
consistent) model. I suggest your time would be better spent learning
and understanding that other model, and learn to use it properly, and
learn what it can and cannot do, rather than infecting it with this new
cancer out of ignorance.
The notion that everything is a stream of bytes is utterly braindead.
The notion that regexps are the solution to all problems is equally
braindead.
Just like Perl.
Some people, when confronted with a problem, think “I know,
I'll use regular expressions.” Now they have two problems."
Hoeder van het Noord-Meierijse dialect
De grootste wtf is dan ook niet de expression zelf, maar het regeltje daarvoor:Gamebuster schreef op maandag 28 augustus 2017 @ 13:03:
[...]
Hetzelfde idee, maar wel andere schrijfwijze. Dit zijn dus geen copy/pasta's van elkaar die eventueel zijn aangepast... Dat betekent dat tenminste 2 personen het een goed idee vonden om dit te schrijven
Regexes hebben echt hun waarde (zelfs als ze zo lelijk lang zijn). Zeker in situaties waar je data in een ongestructureerde platte string aangeleverd krijgt waar je kaas van moet maken. Het gaat pas mis als je regexes gebruikt als een soort van Shotgun approach voor alles wat op een bytestring lijkt.objects of this type must match the following regular expression:
Natuurlijk hebben regexes hun waarde, want er zijn een heleboel gevallen waar het nuttig is. Maar voor zaken als een datum zou ik geen regex gebruiken maar een datetime library die het kan controlleren. Die weet immers veel beter of een datum geldig is, dan dat mijn regex dat kan; en kan het desnoods omzetten.mcDavid schreef op dinsdag 29 augustus 2017 @ 08:59:
[...]
Regexes hebben echt hun waarde (zelfs als ze zo lelijk lang zijn). Zeker in situaties waar je data in een ongestructureerde platte string aangeleverd krijgt waar je kaas van moet maken. Het gaat pas mis als je regexes gebruikt als een soort van Shotgun approach voor alles wat op een bytestring lijkt.
Ook moet je uitkijken met een regex, afhankelijk van de regex implementatie, bij performance-critical code.
Een regex is hier prima te gebruiken. Maar dan wel om de verschillende componenten te extracten uit de datumstring, niet om ook nog eens een semantische controle uit te voeren op die componenten.
Ik verwacht dus hooguit iets als: ^\s*(\d+)\s*-\s*(\d+)\s*-\s*(\d+)\s*$
Ik verwacht dus hooguit iets als: ^\s*(\d+)\s*-\s*(\d+)\s*-\s*(\d+)\s*$
[ Voor 17% gewijzigd door .oisyn op 29-08-2017 15:33 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Soms hoop je daar op he? ^^
Wij hebben in onze codebase ook iets vergelijkbaars zitten als het eerste voorbeeld. Die checkt op het oudst mogelijke geboortedatum (wens van klant..) en om het in de bestaande codebase te douwen is er gekozen om een regex te gebruiken. Ook leuk natuurlijk dat het iets later in de code wel wordt omgezet in een date object en de database in wordt geschoven, maar ja...
Wij hebben in onze codebase ook iets vergelijkbaars zitten als het eerste voorbeeld. Die checkt op het oudst mogelijke geboortedatum (wens van klant..) en om het in de bestaande codebase te douwen is er gekozen om een regex te gebruiken. Ook leuk natuurlijk dat het iets later in de code wel wordt omgezet in een date object en de database in wordt geschoven, maar ja...
Iets wat ik diep in mijn CMS vond 
Fijn! Maar waarom niet gewoon str_split()
?
code:
1
2
3
4
5
6
7
8
9
10
11
12
| function word2array($word) { $aantal = strlen($word)-1; $i = 0 ; $return = array(); while($i <= $aantal) { $return[] = substr($word,$i,1); $i++ ; } return $return ; } |
Fijn! Maar waarom niet gewoon str_split()
☎ Telecommunicatie van vroeger
🚅Alles over spoor en treintjes
Inderdaad, alleen wel bizar dat er nog geen unicode ondersteuning lijkt te zijn.DJMaze schreef op dinsdag 5 september 2017 @ 13:22:
[...]
Ook fout. Want beide ondersteunen geen unicode
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
| <?php function str_split_unicode($str, $l = 0) { if ($l > 0) { $ret = array(); $len = mb_strlen($str, "UTF-8"); for ($i = 0; $i < $len; $i += $l) { $ret[] = mb_substr($str, $i, $l, "UTF-8"); } return $ret; } return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY); } ?> |
Dit werkt wel
☎ Telecommunicatie van vroeger
🚅Alles over spoor en treintjes
Behalve dat je nu hard coded hebt gekozen voor UTF-8AW_Bos schreef op dinsdag 5 september 2017 @ 13:24:
[...]
Inderdaad, alleen wel bizar dat er nog geen unicode ondersteuning lijkt te zijn.
PHP:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php function str_split_unicode($str, $l = 0) { if ($l > 0) { $ret = array(); $len = mb_strlen($str, "UTF-8"); for ($i = 0; $i < $len; $i += $l) { $ret[] = mb_substr($str, $i, $l, "UTF-8"); } return $ret; } return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY); } ?>
Dit werkt wel.
Dit vast ook ($l > 0 best zinloos namelijk)
PHP:
1
2
3
4
5
6
7
8
| function str_split_unicode($str, $l = 0) { $l = intval($l); if ($l > 1) { preg_match_all("/.{0,{$l}}/u", $str, $match); return $match[0]; } return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY); } |
[ Voor 11% gewijzigd door DJMaze op 05-09-2017 13:37 ]
Maak je niet druk, dat doet de compressor maar
Joah... maar dat is uit de PHP-manual
☎ Telecommunicatie van vroeger
🚅Alles over spoor en treintjes
Edit: Sorry, reageerde op een hele oude post
[ Voor 183% gewijzigd door Harrie_ op 05-09-2017 13:50 ]
Hoeder van het Noord-Meierijse dialect
Ik kreeg vandaag een C# codebase ter review waar ik toch heel vaak heel erg hard om heb moeten huilen. 
Duidelijk geschreven door iemand met een database-achtergrond die ook wel wat kan scripten. Het meest treffende vond ik nog wel deze situatie.
Probleem
Er moeten een paar rijen in een volkomen statische databasetabel (SQL server) toegevoegd worden.
Gekozen oplossing
Duidelijk geschreven door iemand met een database-achtergrond die ook wel wat kan scripten. Het meest treffende vond ik nog wel deze situatie.
Probleem
Er moeten een paar rijen in een volkomen statische databasetabel (SQL server) toegevoegd worden.
Gekozen oplossing
- Stored procedure aangemaakt voor insert
- Stored procedure slikt een user defined table type met feitelijk exact dezelfde structuur als de doeltabel.
- Er is een tweede stored procedure om dynamisch een tabel structuur uit te lezen (kolomnaam, datatype en lengte)
- Die tweede stored procedure wordt vanuit de codebase gebruikt om de structuur van de user defined table type uit te lezen
- Op basis van die uitgelezen structuur wordt in de codebase een nieuwe DataTable opgebouwd met een stuk custom logica voor datatypen
- Die DataTable wordt in de code gevuld met de rijen, waarbij ook elke keer voor de zekerheid nog maar gecheckt wordt of de kolomnaam voorkomt
- Met die gevulde DataTable wordt de oorspronkelijke stored procedure aangeroepen en worden de insert statements uitgevoerd.
[ Voor 3% gewijzigd door Mugwump op 06-09-2017 17:07 ]
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Het is vooral een volkomen onnodig verwoven bak spaghetticode. Zit ook nog eens verpakt in classes / methods waarvan de naamgeving gespeend is van elke vorm van logica.PolarBear schreef op woensdag 6 september 2017 @ 17:21:
Het is vooral overengineerd
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Een UDTT kan handig zijn als je bulk-operaties moet uitvoeren. De stored procedure die het schema van de UDTT teruggeeft kan gebruikt worden door een importer die CSV-files inleest, die een soortgelijke structuur hebben. Daarmee kun je een enigszins generieke importer bouwen.
Maar het kan ook zwaar overengineered zijn.
Maar het kan ook zwaar overengineered zijn.
We are shaping the future
Dat snap ik. Daarom gaf ik ook eerst de 'probleemstelling'. Dit is niet overengineeren, dit is gewoon de volstrekt verkeerde oplossing voor het 'probleem'. Ter illustratie, het is ook niet zo dat op basis van de dynamische structuur een poging tot casting de datatypen in de C# wordt gepoogd. De datatypen van de values worden er voor elke waarde gewoon hardcoded ingegooid. De structuur wordt ook slechts éénmalig gebruikt, dus met een generieke opzet voor hergebruik heeft het ook niets van doen.Alex) schreef op woensdag 6 september 2017 @ 18:53:
Een UDTT kan handig zijn als je bulk-operaties moet uitvoeren. De stored procedure die het schema van de UDTT teruggeeft kan gebruikt worden door een importer die CSV-files inleest, die een soortgelijke structuur hebben. Daarmee kun je een enigszins generieke importer bouwen.
Maar het kan ook zwaar overengineered zijn.
Het is een breder probleem in de hele codebase overigens. Werkelijk alle interactie met de database wordt gedaan via stored procedures, zelfs zaken als het ophalen van een enkel veldje uit een tabel op basis van een key. Of simpele inserts waarbij pakweg de helft van de business logic in de C# code zit en nog eens een helft in de stored procedure. Volstrekt niet te unit testen natuurlijk, dus de code coverage is exact 0% evenals de documentatie.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
Een fraai stukje testwerk dat ik tegenkwam:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| @Test public void testItGetsAllOffices() { when(mockOfficeRepository.getAll()).thenReturn(Arrays.asList( givenOffice("Amsterdam"), givenOffice("Rotterdam") )); List<Office> offices = officeService.getAll(); assertThat(offices, hasSize(2)); assertThat(offices, hasItem(offices.get(0))); assertThat(offices, hasItem(offices.get(1))); verify(mockOfficeRepository, times(1)).getAll(); } private Office givenOffice(String name) { Office office = new Office(); office.setName(name); return office; } |
Bij mocks moet ik gelijk aan deze tweet denken:

https://twitter.com/rabbitonweb/status/918473231216136192

https://twitter.com/rabbitonweb/status/918473231216136192
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Verwijderd
Het volgende kwam ik laatst ergens tegen:
code:
1
2
3
4
5
6
| def get_errors_from_check(self, messages): errors = [] for error in messages: errors.append(error) return errors |

C#:
1
2
3
4
5
6
7
8
9
10
| public bool GetWarningMessage() { if(iWarning == 0) { return false; } else { return true; } } |

We are shaping the future
Hebben jullie nooit dat je een stukje WTF-waardige code ziet, maar je het eigenlijk niet weg durft te halen? Ik denk dan, als iemand dergelijke rare constructies gebruikt, dan zal er een goede reden voor geweest zijn. Maar wellicht schat ik dan veel van mijn vakgenoten (en mezelf bij tijd en wijlen) te hoog in. 
Case in point:
Case in point:
C#:
1
| (int)(object)myObj |
Ik vermoed een manier om geen warning te krijgen als je een decimal/double naar een int castGaius schreef op donderdag 23 november 2017 @ 15:34:
Hebben jullie nooit dat je een stukje WTF-waardige code ziet, maar je het eigenlijk niet weg durft te halen? Ik denk dan, als iemand dergelijke rare constructies gebruikt, dan zal er een goede reden voor geweest zijn. Maar wellicht schat ik dan veel van mijn vakgenoten (en mezelf bij tijd en wijlen) te hoog in.
Case in point:
C#:
1 (int)(object)myObj
(wel een hele slechte workaround om een classcastexception te voorkomen)
[ Voor 4% gewijzigd door YakuzA op 23-11-2017 16:17 ]
Death smiles at us all, all a man can do is smile back.
PSN
In c# mag je een double gewoon naar een int casten hoor. Komt geen classcastexception aan te pas.YakuzA schreef op donderdag 23 november 2017 @ 16:16:
[...]
Ik vermoed een manier om geen warning te krijgen als je een decimal/double naar een int cast
(wel een hele slechte workaround om een classcastexception te voorkomen)
Ik heb eens een applicatie van een leverancier voor de gein door een decompiler heen gehaald, daar werden zo'n beetje alle events afgehandeld in één event handler. Met daarin een switch statement die als je'm uit print tot de maan rijkt denk ik
Snel weer gesloten, wil ik niet weten..

Voor zover ik kan zien zou het origineel om een waarde van een enum gaan. Ik vraag me serieus af wat hier de bedoeling van is geweest. Ik bedoel, .Net evalueert sowieso eerst de uitkomst van beide casts voordat er iets met de uitkomst gebeurt toch?YakuzA schreef op donderdag 23 november 2017 @ 16:16:
[...]
Ik vermoed een manier om geen warning te krijgen als je een decimal/double naar een int cast
(wel een hele slechte workaround om een classcastexception te voorkomen)
Dus volgens mij is de enige uitkomst van de cast naar object die er toe doet het spekken van de energiemaatschappij en het meehelpen van de opwarming van de aarde. Maar het lijkt me onwaarschijnlijk dat de dienstdoende ontwikkelaar dat als uitgangspunt had bij het schrijven van deze code.
Bizar hoeveel je fout* kan doen in vier regels codeAlex) schreef op dinsdag 21 november 2017 @ 20:47:
C#:
1 2 3 4 5 6 7 8 9 10 public bool GetWarningMessage() { if(iWarning == 0) { return false; } else { return true; } }

* technisch gezien misschien niet direct fout, maar wel lelijk, onhandig, misleidend, ouderwets, kan ook in 1 statement
[ Voor 16% gewijzigd door Haan op 24-11-2017 09:35 ]
Kater? Eerst water, de rest komt later
Ik ben dan altijd benieuwd wat voor developer erachter zit? Amateur die net begint of iemand die al 15jaar erop heeft zitten..
Misschien wel een amateur die al 15 jaar lang dit soort code schrijft.matty___ schreef op vrijdag 24 november 2017 @ 09:47:
Ik ben dan altijd benieuwd wat voor developer erachter zit? Amateur die net begint of iemand die al 15jaar erop heeft zitten..
Van dezelfde auteur...
C#:
1
2
3
4
5
| public void Validate() { var intVal = Convert.ToInt32(_fooService.GetFooIdentifier()); if (intVal.ToString() == null) |
We are shaping the future
Wordt nu serieus een string?? geconvert naar een integer, om vervolgens weer terug te converten naar een string...Alex) schreef op vrijdag 24 november 2017 @ 19:01:
Van dezelfde auteur...
C#:
1 2 3 4 5 public void Validate() { var intVal = Convert.ToInt32(_fooService.GetFooIdentifier()); if (intVal.ToString() == null)

Jazeker. Al wordt er alleen maar een numerieke waarde ingevuld, het onderliggende datatype is string.
En als kers op de taart: FooIdentifier is in ongeveer 15% van de gevallen null, omdat de waarde niet verplicht is.
En als kers op de taart: FooIdentifier is in ongeveer 15% van de gevallen null, omdat de waarde niet verplicht is.
[ Voor 27% gewijzigd door Alex) op 24-11-2017 19:08 ]
We are shaping the future
Er is daar maar een antwoord goed op:Alex) schreef op vrijdag 24 november 2017 @ 19:07:
Jazeker.
En als kers op de taart: FooIdentifier is in ongeveer 15% van de gevallen null, omdat de waarde niet verplicht is.

Een REST service die een totaalbedrag teruggeeft als bedrag * 100... Maar het bedrag ex BTW is het normale bedrag

Exact expert nodig?
Voutloos schreef op zaterdag 25 november 2017 @ 14:22:
En de BTW voor dat product is niet toevallig 9900%, want dan klopt t ook.

Exact expert nodig?
ik kom de volgende functienaam tegen op stage
waarschinlijk kon de auteur niet beslissen of de functienaam in het nederlands of in het engels moest
C#: filename
1
2
3
| CalculateAndShowVoedingsAndEnergiePercentageWaarde(){ } |
waarschinlijk kon de auteur niet beslissen of de functienaam in het nederlands of in het engels moest
[ Voor 10% gewijzigd door ard1998 op 28-11-2017 11:03 ]
Nog erger dan dat... wat is een EnergiePercentageWaarde? En wat is een Voedings? Volgens mij was iemand hard toe aan een energydrink tijdens het verzinnen van deze naamard1998 schreef op dinsdag 28 november 2017 @ 11:03:
ik kom de volgende functienaam tegen op stage
C#: filename
1 2 3 CalculateAndShowVoedingsAndEnergiePercentageWaarde(){ }
waarschinlijk kon de auteur niet beslissen of de functienaam in het nederlands of in het engels moest
Een method waar het woord 'And' in voorkomt kan sowieso al nooit goed zijn, dat zouden minimaal twee methods moeten zijn
Kater? Eerst water, de rest komt later
nope....ard1998 schreef op dinsdag 28 november 2017 @ 11:03:
ik kom de volgende functienaam tegen op stage
C#: filename
1 2 3 CalculateAndShowVoedingsAndEnergiePercentageWaarde(){ }
waarschinlijk kon de auteur niet beslissen of de functienaam in het nederlands of in het engels moest
Janoz in "[alg] Slechtste programmeervoorbeelden deel 4"
Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'
Helemaal mee eens. Zelf kom ik meestal tegen dat er Engels gebruikt wordt tenzij het een domein specifieke term betreft. Ook dan alleen Nederlands voor het specifieke woord, aanvullende (werk)woorden wel in het Engels. 'And' en 'Or' is inderdaad kandidaat om op te splitsen
Server 1: Intel N305 | 48GB RAM | 5*4TB NVME | 4x 2.5GbE
Server 2: Intel N5105 | 64GB RAM | 1TB NVME | 4x 2.5GbE
Server 3: Intel Xeon E5-2670 | 128GB RAM | 512+750GB SATA SSD | 6x10TB HDD | 6x 1GbE [Buiten gebruik]
Daar heb je toch de oplossing voor door een version in een header mee te geven? Bijv.Crazy D schreef op zondag 26 november 2017 @ 13:03:
[...]
Scherp, maar nee... Ik vermoed dat dit 1 van de 1e velden waren in de API, en decimalen is altijd erg onhandig. Programmeur 2 kwam een tijdje later om andere properties door te voeren, en die pompt t gewoon door zoals t uit de database komt. Et voilà, mooi stukje inconsistentie in je API gebouwd. Die, eenmaal in gebruik, niet meer te wijzigen is zonder dat diverse apps en andere koppelingen de boel moeten aanpassen.
code:
1
| Accept: application/vnd.api-naam+json; version=2.0 |
Ik ken een groot Europees kledingmerk waar als je de juiste header meegeeft er allemaal checks niet goed werken waardoor je vouchers niet op geldigheid worden gecontroleerd

[ Voor 11% gewijzigd door alienfruit op 28-11-2017 20:18 ]

Ik denk dat Tony Hoare met zijn $1.000.000.000 nog aan de lage kant zat
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Ik zal de letterlijke code niet kopiëren/plakken, maar vandaag een paar uur vast gezeten doordat een stukje data niet verwerkt werd naar verwachting.
Men neme een String, splitst deze op elke delimiter en gooit alle elementen op een vaste plek in een array. Zou niet moeilijk moeten zijn. Tot bleek dat iemand z'n eigen implementatie van Java's String.split() had geschreven die subtiel afwijkt van het origineel... Beschouwt opeenvolgende delimiters als ééntje
Dat was nou geheel niet de bedoeling, en verklaart dus meteen waarom elementen op de verkeerde positie belanden
Men neme een String, splitst deze op elke delimiter en gooit alle elementen op een vaste plek in een array. Zou niet moeilijk moeten zijn. Tot bleek dat iemand z'n eigen implementatie van Java's String.split() had geschreven die subtiel afwijkt van het origineel... Beschouwt opeenvolgende delimiters als ééntje

[ Voor 6% gewijzigd door ShitHappens op 05-03-2018 19:17 ]
Dat lijkt wel PHP
Hoeder van het Noord-Meierijse dialect
Zo gek is dat niet. En dus lijkt het niet PHP
.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Ik vind het ook niet zo vreemd. Je moet ergens definiëren wat de operatie 'concatenate' doet op twee strings. De conventie is daarvoor in C# geloof ik dat null wordt omgezet naar een lege string. Het enige alternatief is dan een null reference / pointer gooien, maar dat schiet ook niet echt op. Of je moet van string een value type maken met default waarde lege string, maar dat gaat ook wel de nodige chaos opleveren.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
C# Interactive is wel één van de beste toevoegingen aan Visual Studio in lange tijd. Iets wat ik ook echt gebruik, i.t.t. CodeLens of die "klik 1x op iets in de solution explorer om een preview te krijgen"-functie.
We are shaping the future
PHP geeft '0' en niet "".
Never explain with stupidity where malice is a better explanation
Toch vind ik het nog steeds net niet zo lekker werken als IntelliJ het doet voor Java. Zoiets voor LINQ zou ook echt een fijne toevoeging zijn.Alex) schreef op dinsdag 6 maart 2018 @ 18:22:
C# Interactive is wel één van de beste toevoegingen aan Visual Studio in lange tijd. Iets wat ik ook echt gebruik, i.t.t. CodeLens of die "klik 1x op iets in de solution explorer om een preview te krijgen"-functie.
Ik doe beide talen en ze hebben allebei hun voor en nadelen, maar qua tooling kan Microsoft echt heel veel leren van JetBrains. Resharper maakt nog wel het één en ander goed, maar het blijft op sommige vlakken toch wel behelpen.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
+ in PHP is ook geen string concatenatie.incaz schreef op dinsdag 6 maart 2018 @ 18:31:
PHP geeft '0' en niet "".
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Moest default(string) nu een lege string zijn, dan zou ik het ook niet zo merkwaardig vinden.Mugwump schreef op dinsdag 6 maart 2018 @ 18:00:
[...]
Ik vind het ook niet zo vreemd. Je moet ergens definiëren wat de operatie 'concatenate' doet op twee strings. De conventie is daarvoor in C# geloof ik dat null wordt omgezet naar een lege string. Het enige alternatief is dan een null reference / pointer gooien, maar dat schiet ook niet echt op. Of je moet van string een value type maken met default waarde lege string, maar dat gaat ook wel de nodige chaos opleveren.
Echter, default(string) is null, dus dan vind ik het wel raar dat er beslist is dat null + null == string.Empty
https://fgheysels.github.io/
Klopt, je moet iets. En dat is het hele probleem met dat null-gedrocht. Gegeven dat een string nullable is, is het vast een redelijke oplossing. En het is begrijpelijk dat C# de null heeft overgenomen van Java en C. Maar eigenlijk had dat ding niet moeten bestaanMugwump schreef op dinsdag 6 maart 2018 @ 18:00:
[...]
Ik vind het ook niet zo vreemd. Je moet ergens definiëren wat de operatie 'concatenate' doet op twee strings. De conventie is daarvoor in C# geloof ik dat null wordt omgezet naar een lege string. Het enige alternatief is dan een null reference / pointer gooien, maar dat schiet ook niet echt op. Of je moet van string een value type maken met default waarde lege string, maar dat gaat ook wel de nodige chaos opleveren.
Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.
Stel nu dat één van de waarden "ABC" is. Wat zou de logische samenvoeging van "ABC" en null dan zijn?whoami schreef op dinsdag 6 maart 2018 @ 20:58:
[...]
Moest default(string) nu een lege string zijn, dan zou ik het ook niet zo merkwaardig vinden.
Echter, default(string) is null, dus dan vind ik het wel raar dat er beslist is dat null + null == string.Empty
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
"ABC" + niet gedefinieerd = niet gedefinieerd
https://fgheysels.github.io/
Null is niet zozeer niet gedefinieerd. Null is null.
Deze keuze zou ook totaal onwerkbare situaties opleveren. Als je een error message logt op basis van string concatenation, interpolated strings of iets vergelijkbaars zou je of nulls gaan loggen of helemaal niets vanwege nullreferences om maar eens wat te noemen.
Het zou achteraf gezien handiger zijn geweest om een string nooit null te laten zijn, tenzij je hem expliciet als nullable definieert, maar wat C# doet is op zich nog vrij logisch gezien het feit dat je nou eenmaal null hebt.
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
null is null is niets / niet gedefinieerd.Mugwump schreef op dinsdag 6 maart 2018 @ 22:35:
[...]
Null is niet zozeer niet gedefinieerd. Null is null.
Ik zeg niet dat het een slechte keuze is dat string concat met null naar een lege string gaat; ik zeg wel dat ik het niet logisch vind.Deze keuze zou ook totaal onwerkbare situaties opleveren. Als je een error message logt op basis van string concatenation, interpolated strings of iets vergelijkbaars zou je of nulls gaan loggen of helemaal niets vanwege nullreferences om maar eens wat te noemen.
[ Voor 24% gewijzigd door whoami op 06-03-2018 22:56 ]
https://fgheysels.github.io/
Wellicht is het op het eerste gezicht niet logisch, maar wat zou het dan moeten doen? Een exception throwen? er <null> o.i.d. van maken? Zorgen dat "foo" + null ook null is? Er zijn verschillende redenen waarom ze hier voor gekozen hebben, een daarvan is dat de String klasse wordt gedeelt door alle .NET talen (ook F#) en zich daar exact hetzelfde moet gedragen. Daarbij is het ook gewoon goed gedocumenteerd dat het zich zo gedraagt.whoami schreef op dinsdag 6 maart 2018 @ 22:53:
[...]
Ik zeg niet dat het een slechte keuze is dat string concat met null naar een lege string gaat; ik zeg wel dat ik het niet logisch vind.
string + null lijkt me dat hij dan gewoon een lege string toevoegt. Handig voor strings te bouwen waarbij er ongedefinieerde waardes kunnen zijn.
null + null zou imo gewoon null moeten zijn.
null + null zou imo gewoon null moeten zijn.
'Multiple exclamation marks,' he went on, shaking his head, 'are a sure sign of a diseased mind.' - Pratchett.
Ik vind het ook raar, kijk je immers naar bijvoorbeeld het optellen van nullable ints, dan zie je:
> int? x = 2;
> int? y = null;
> int? z = x + y;
> z
null
> int? x = 2;
> int? y = null;
> int? z = x + y;
> z
null
Kater? Eerst water, de rest komt later
Waarom zou dan in het eerste voorbeeld de string null vertaald moeten worden naar een lege string, maar in het tweede voorbeeld niet? Dat zou het toch alleen maar inconsistent maken?boe2 schreef op woensdag 7 maart 2018 @ 09:52:
string + null lijkt me dat hij dan gewoon een lege string toevoegt. Handig voor strings te bouwen waarbij er ongedefinieerde waardes kunnen zijn.
null + null zou imo gewoon null moeten zijn.
"niets" is heel wat anders dan "ongedefinieerd". Ik denk dat je in de war bent met NULL uit SQL, wat een heel ander beestje is.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Dat vind ik dan weer raar, ik had een uitkomst van 2 logischer gevonden. Niet omdat null gelijk is aan 0, maar omdat een berekening met null gewoon een identity operatie is. 2 * (int?)null zou dan ook 2 moeten zijn. Maar (int?)null - 3 wel -3 (immers, null-3 = null+(-3) = -3+null = -3)Haan schreef op woensdag 7 maart 2018 @ 10:08:
Ik vind het ook raar, kijk je immers naar bijvoorbeeld het optellen van nullable ints, dan zie je:
> int? x = 2;
> int? y = null;
> int? z = x + y;
> z
null
[ Voor 8% gewijzigd door .oisyn op 07-03-2018 10:35 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
> var a = new int?[]{2, null};Haan schreef op woensdag 7 maart 2018 @ 10:08:
Ik vind het ook raar, kijk je immers naar bijvoorbeeld het optellen van nullable ints, dan zie je:
> int? x = 2;
> int? y = null;
> int? z = x + y;
> z
null
> var b = a.Sum();
> b
2
Dat hangt er dus helemaal vanaf hoe je je concat definieert. MIJ lijkt dat een functie het resultaat moet geven dat het beste voldoet aan de behoeften van de gebruikers. En dan lijkt het mij echt ondubbelzinnig dat de behoefte aan een niet-nullgevoelige concat aantoonbaar veeel groter is dan eentje die wel gevoelig is.boe2 schreef op woensdag 7 maart 2018 @ 09:52:
null + null zou imo gewoon null moeten zijn.
Ik vind dat redeneren vanuit een soort formele puurheid ipv vanuit het gebruik zo vreemd? En het is niet dat het nou zo moeilijk is om expliciet op null te checken als dat relevant is.
Never explain with stupidity where malice is a better explanation
Hoezo is null een identity operatie dan?.oisyn schreef op woensdag 7 maart 2018 @ 10:29:
Niet omdat null gelijk is aan 0, maar omdat een berekening met null gewoon een identity operatie is.
null zelf niet, maar een operatie met null. Waarom zou a+b+c+d+e+f ineens in de war gegooid moeten worden alleen omdat c null is (bijvoorbeeld)? Ik zie het dan gewoon als niet bestaand, en dus wordt het a+b+d+e+f .PrisonerOfPain schreef op woensdag 7 maart 2018 @ 12:37:
[...]
Hoezo is null een identity operatie dan?
Hetzelfde geldt voor vermenigvuldigen ipv optellen, waaruit volgt dat null dus geen 0 is (anders zou vermenigvuldigen met null altijd 0 opleveren), maar dat x <op> null altijd x oplevert, waaruit volgt dat null dan de identity is van op.
Dit hele principe is in feite wat string concatenatie doet.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Je kunt het ook vergelijken met het aanroepen van Stringbuilder.Append(stringVal) waarbij stringVal null is..oisyn schreef op woensdag 7 maart 2018 @ 12:58:
[...]
null zelf niet, maar een operatie met null. Waarom zou a+b+c+d+e+f ineens in de war gegooid moeten worden alleen omdat c null is (bijvoorbeeld)? Ik zie het dan gewoon als niet bestaand, en dus wordt het a+b+d+e+f .
Hetzelfde geldt voor vermenigvuldigen ipv optellen, waaruit volgt dat null dus geen 0 is (anders zou vermenigvuldigen met null altijd 0 opleveren), maar dat x <op> null altijd x oplevert, waaruit volgt dat null dan de identity is van op.
Dit hele principe is in feite wat string concatenatie doet.
Append is uiteindelijk ook gewoon een concatenatie, maar als je null Append, dan wordt niet opeens de hele string null.
Ik denk het ook vooral het feit dat het hier een operator betreft de verwarring veroorzaakt. De methode string Concat(string a, string b) met documentatie die beschrijft dat null-values worden omgezet naar lege strings veroorzaakt veel minder verwarring.
Ik vind het feit dat die twee consistent zijn (en bijvoorbeeld ook consistent met StringBuilder) minder misleidend dan de wijze waarop bijvoorbeeld voor nullable ints de operator anders werken dan een Sum().
"The question of whether a computer can think is no more interesting than the question of whether a submarine can swim" - Edsger Dijkstra
C# Code die ik regelmatig in een codebase tegenkom waarmee ik vaak werk.
try
{
try
{
DoStuff();
}
catch(Exception ex)
{
throw new CustomException(ex.Message, ex.StackTrace)
}
}
catch(CustomException ex)
{
Logger.LogError(ex);
}

try
{
try
{
DoStuff();
}
catch(Exception ex)
{
throw new CustomException(ex.Message, ex.StackTrace)
}
}
catch(CustomException ex)
{
Logger.LogError(ex);
}
Geen indenting, dat is inderdaad belachelijk
Als je het zo onder elkaar zet zit het er idd knullig uit, maar op zich is het niet een hele rare constructie. Alleen meestal heb je er een laagje abstractie tussen als je zoiets doet.
Verwijderd
dat is een hele slechte aanname, je krijgt hier bugs/ foute resultaten van dus vind ik dat ie beter een null pointer exception kan gooien, vb: ik heb 10 bitcoins, maar doordat c niet gedefinieerd is heb ik er nog maar 8 omdat c eigenlijk 2 moest zijn..oisyn schreef op woensdag 7 maart 2018 @ 12:58:
[...]
null zelf niet, maar een operatie met null. Waarom zou a+b+c+d+e+f ineens in de war gegooid moeten worden alleen omdat c null is (bijvoorbeeld)? Ik zie het dan gewoon als niet bestaand, en dus wordt het a+b+d+e+f .
Hetzelfde geldt voor vermenigvuldigen ipv optellen, waaruit volgt dat null dus geen 0 is (anders zou vermenigvuldigen met null altijd 0 opleveren), maar dat x <op> null altijd x oplevert, waaruit volgt dat null dan de identity is van op.
Dit hele principe is in feite wat string concatenatie doet.
Het is geen aanname, het is een definitie

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Een erg onintuïtieve en wazige. Als een operatie met null gelijk is aan een identiteitsfunctie, zou dan ook null / 3 = 3? En null^3 = 3? Ik zie weer mooie ongedetecteerde fouten binnensluipen, en geen enkele reden waarom je hier iets aan hebt...
Als je een mooie, wiskundige, semantiek aan wil hangen, is het antwoord dat je gewoon die hele null uit het raam moet gooien. Als je wel null hebt is elke semantiek een zooitje, en dan lijkt het me het netste als de boel ook maar gewoon meteen een exception gooit, want alles wat je met null doet is gewoon flauwekul, en dat leidt tot fouten. Maar dat wel bekend, geloof ik.
[ Voor 4% gewijzigd door bwerg op 25-03-2018 21:20 ]
Heeft geen speciale krachten en is daar erg boos over.
Wat null doet en of die definitie intuitief is of niet hangt af van de situatie. Neem nu een spreadsheet waarin de formule =SUM(A:A) gebruik. Dan is het verdomd handig dat alle lege cellen in deze operatie hetzelfde effect hebben als 0. Voor iets als =PRODUCT(A:A) geldt een ander neutraal element, nl. 1.
(Wat wel vreemd is dat het product van een lege verzameling volgens Excel 0 is... Dat doet Haskell beter...
)
(Wat wel vreemd is dat het product van een lege verzameling volgens Excel 0 is... Dat doet Haskell beter...
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Zeker, maar een general-purpose programmeertaal kan dus niet van zo'n context gebruik maken. Lege cellen zien als null is trouwens ook een beetje een scheve vergelijking, aangezien in excel-achtige programma's lege cellen ook gewoon opvulmateriaal voor je scherm zijn. Je begint al met 17.179.869.184 lege cells, en het is soms gewoon witruimte tussen gevulde cells. Natuurlijk wil je dat dat genegeerd wordt.RayNbow schreef op maandag 26 maart 2018 @ 05:56:
Neem nu een spreadsheet waarin de formule =SUM(A:A) gebruik.
Dat heeft ook vooral die hele null niet, en het laat ook zien dat je het totaal niet mist.Dat doet Haskell beter...
[ Voor 53% gewijzigd door bwerg op 26-03-2018 09:42 ]
Heeft geen speciale krachten en is daar erg boos over.
Het heeft daarentegen wel ⊥ als lid van elk type.bwerg schreef op maandag 26 maart 2018 @ 09:32:
Dat heeft ook vooral die hele null niet, en het laat ook zien dat je het totaal niet mist.
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
En als iemand het ooit bewust gebruikt, heeft het de duidelijke semantiek 'dit crasht of blijft hangen, jammer de bammer', in tegenstelling tot null, waar gewoon functionaliteiten van serieuze programma's van afhangen.RayNbow schreef op maandag 26 maart 2018 @ 10:06:
[...]
Het heeft daarentegen wel ⊥ als lid van elk type.
Ik voel in ieder geval niet de behoefte om argumenten van functies op ⊥ te gaan checken.
[ Voor 10% gewijzigd door bwerg op 26-03-2018 10:22 ]
Heeft geen speciale krachten en is daar erg boos over.
Kun je die dan checken?bwerg schreef op maandag 26 maart 2018 @ 10:14:
Ik voel in ieder geval niet de behoefte om argumenten van functies op ⊥ te gaan checken.
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Nee, vandaar de '
Heeft geen speciale krachten en is daar erg boos over.
Dat hangt van de context af, zoals RayNbow ook al zegt
Nee, null is de identiteit voor de operatie. Bij null/3 krijg je 1/3, immers: a/3 = a * (1/3), en null * (1/3) = 1/3Als een operatie met null gelijk is aan een identiteitsfunctie, zou dan ook null / 3 = 3?
Wat is ^? XOR? Machtsverheffen?En null^3 = 3?
Bij XOR krijg je idd 3. Bij machtsverheffen will je de null wellicht propagaten.
[ Voor 3% gewijzigd door .oisyn op 26-03-2018 11:49 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Ik kreeg de indruk dat het ging over een logische betekenis voor general purpose van een taal op zich. Voor een context-specifieke semantiek lijkt het me beter om het expliciet te maken, door een speciale optelling-met-null-operator te maken o.i.d..oisyn schreef op maandag 26 maart 2018 @ 11:47:
[...]
Dat hangt van de context af, zoals RayNbow ook al zegt
Heeft geen speciale krachten en is daar erg boos over.
Ging het ook, maar het ging om het feit dat C# bij strings null wordt gezien als lege string bij concatenatie, maar iets anders doet bij nullable ints. Dat vind ik onlogisch, ik had het liever consistent gezien.bwerg schreef op maandag 26 maart 2018 @ 12:09:
[...]
Ik kreeg de indruk dat het ging over een logische betekenis voor general purpose van een taal op zich.
En welke afhandeling je dan ook kiest, voor beide is wel wat te zeggen.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Sinds kort zit ik op een project bij de overheid om onderhoud te plegen op 6 jaar oude JBoss/Seam applicatie. (Welke laat ik even in het midden
)
Het is de ene WTF na de andere Holy Crap als ik door de sources ga. Behalve een gaar DTO "oplossing" met generatie d.m.v. reflection (wat niet te debuggen is) komt ik pareltjes als deze tegen:
Daarnaast is het blijkbaar populair geweest om setters "this" te laten retourneren en vooral ook niet de bean spec te volgen zodat je lekker kan method chainen. Voorbeeldje:
Echt wel makkelijk om te debuggen
En uiteraard veel methoden / class namen zoals "AbstractedDitIsEenObjectDatZoEnZoDoetMaarTochStiekemWatAndersServiceImplementation". Een gezonde mix van NL en EN.
En dit is nog maar een kleine greep uit de grote verzameling van verbazingen die ik dagelijks ontdek
.

Het is de ene WTF na de andere Holy Crap als ik door de sources ga. Behalve een gaar DTO "oplossing" met generatie d.m.v. reflection (wat niet te debuggen is) komt ik pareltjes als deze tegen:
Java:
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
| private String save0() { .... save1() } private String save1() { .... save2() } private String save2() { .... save3() } private String save3() { .... save4() } private String save4() { .... } private String save4a() { .... save4() } private String save5p1() { .... save4a() } |
Daarnaast is het blijkbaar populair geweest om setters "this" te laten retourneren en vooral ook niet de bean spec te volgen zodat je lekker kan method chainen. Voorbeeldje:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| public class Foo { public Foo doThis(Var var1) { this.var1 = var1; return this; } public Foo doThat(Var var2) { this.var2 = var2; return this; } public Foo doOther(Var var3) { this.var3 = var3; return this; } .... etc.. } //om vervolgens te kunnen doen: Foo foo = new Foo().doThis(var1).doThat(var2).doOther(var3); |
Echt wel makkelijk om te debuggen

En uiteraard veel methoden / class namen zoals "AbstractedDitIsEenObjectDatZoEnZoDoetMaarTochStiekemWatAndersServiceImplementation". Een gezonde mix van NL en EN.
En dit is nog maar een kleine greep uit de grote verzameling van verbazingen die ik dagelijks ontdek

[ Voor 5% gewijzigd door Standeman op 06-09-2018 15:06 ]
The ships hung in the sky in much the same way that bricks don’t.
Let op:
Uiteraard is het in dit topic niet de bedoeling dat andere users en/of topics aangehaald worden om ze voor gek te zetten. Lachen om je eigen code, of over dingen die je "wel eens tegengekomen bent" is prima, maar hou het onderling netjes.
Uiteraard is het in dit topic niet de bedoeling dat andere users en/of topics aangehaald worden om ze voor gek te zetten. Lachen om je eigen code, of over dingen die je "wel eens tegengekomen bent" is prima, maar hou het onderling netjes.