obsidian
This commit is contained in:
parent
f4b0c84a43
commit
129f96d2dd
10 changed files with 318 additions and 3272 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
1
.obsidian/app.json
vendored
Normal file
1
.obsidian/app.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
||||||
1
.obsidian/appearance.json
vendored
Normal file
1
.obsidian/appearance.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
||||||
31
.obsidian/core-plugins.json
vendored
Normal file
31
.obsidian/core-plugins.json
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"file-explorer": true,
|
||||||
|
"global-search": true,
|
||||||
|
"switcher": true,
|
||||||
|
"graph": true,
|
||||||
|
"backlink": true,
|
||||||
|
"canvas": true,
|
||||||
|
"outgoing-link": true,
|
||||||
|
"tag-pane": true,
|
||||||
|
"properties": false,
|
||||||
|
"page-preview": true,
|
||||||
|
"daily-notes": true,
|
||||||
|
"templates": true,
|
||||||
|
"note-composer": true,
|
||||||
|
"command-palette": true,
|
||||||
|
"slash-command": false,
|
||||||
|
"editor-status": true,
|
||||||
|
"bookmarks": true,
|
||||||
|
"markdown-importer": false,
|
||||||
|
"zk-prefixer": false,
|
||||||
|
"random-note": false,
|
||||||
|
"outline": true,
|
||||||
|
"word-count": true,
|
||||||
|
"slides": false,
|
||||||
|
"audio-recorder": false,
|
||||||
|
"workspaces": false,
|
||||||
|
"file-recovery": true,
|
||||||
|
"publish": false,
|
||||||
|
"sync": true,
|
||||||
|
"webviewer": false
|
||||||
|
}
|
||||||
176
.obsidian/workspace.json
vendored
Normal file
176
.obsidian/workspace.json
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"id": "d0f24fb31cb69abb",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "5bced732a7d8e497",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "26f2d4238c095833",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "blog/DDD.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "DDD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "vertical"
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"id": "da43cfeabd226020",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "519fca9f71da36b7",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "150253fc5fd1ff81",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "file-explorer",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"autoReveal": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-folder-closed",
|
||||||
|
"title": "Files"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a00c6b25c7dedd28",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "search",
|
||||||
|
"state": {
|
||||||
|
"query": "",
|
||||||
|
"matchingCase": false,
|
||||||
|
"explainSearch": false,
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical"
|
||||||
|
},
|
||||||
|
"icon": "lucide-search",
|
||||||
|
"title": "Search"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "09bd6da3ec7a0953",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "bookmarks",
|
||||||
|
"state": {},
|
||||||
|
"icon": "lucide-bookmark",
|
||||||
|
"title": "Bookmarks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 300
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"id": "a7fc8838a6532f5a",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "41536dfa22776dde",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "ce99ca53e49e21bd",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "backlink",
|
||||||
|
"state": {
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": "",
|
||||||
|
"backlinkCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-coming-in",
|
||||||
|
"title": "Backlinks"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "62e0f4bf75ad229c",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outgoing-link",
|
||||||
|
"state": {
|
||||||
|
"linksCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-going-out",
|
||||||
|
"title": "Outgoing links"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c26e35f9e98d75c3",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "tag",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"useHierarchy": true,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-tags",
|
||||||
|
"title": "Tags"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8664a3d8e5e59b8e",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outline",
|
||||||
|
"state": {
|
||||||
|
"followCursor": false,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-list",
|
||||||
|
"title": "Outline"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 300,
|
||||||
|
"collapsed": true
|
||||||
|
},
|
||||||
|
"left-ribbon": {
|
||||||
|
"hiddenItems": {
|
||||||
|
"switcher:Open quick switcher": false,
|
||||||
|
"graph:Open graph view": false,
|
||||||
|
"canvas:Create new canvas": false,
|
||||||
|
"daily-notes:Open today's daily note": false,
|
||||||
|
"templates:Insert template": false,
|
||||||
|
"command-palette:Open command palette": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": "26f2d4238c095833",
|
||||||
|
"lastOpenFiles": [
|
||||||
|
"blog/uniek.md",
|
||||||
|
"blog/senior.md",
|
||||||
|
"blog/hergebruik.md",
|
||||||
|
"blog/DDD.md",
|
||||||
|
"blog"
|
||||||
|
]
|
||||||
|
}
|
||||||
15
blog/DDD.md
Normal file
15
blog/DDD.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
**de belofte**
|
||||||
|
'If programmers are not interested in the domain, they only learn what the application should do, but not the principles behind it. Useful software can be built that way, but the project will never arrive at a point where powerful new features unfold as corollaries to older features'
|
||||||
|
|
||||||
|
Roept van alles bij me op, zoals, ben ik wel geïnteresseerd in het domein? Heb ik het altijd fout gedaan? Is dit waarom mijn leven zo moeilijk is en gaat alles straks vanzelf als ik maar betere domein modellen bedenk?
|
||||||
|
Die twijfels zijn de omgekeerde medaille van de belofte die het boek doet: 'Hé joh, als je wat beter je best doet, wordt alles mooi en gaan de moeilijke dingen vanzelf'.
|
||||||
|
|
||||||
|
**de taal metafoor**
|
||||||
|
Evans beschrijft hoe hij Spaanse les had: het was verboden Engels te praten. Daardoor leerde hij het beter.
|
||||||
|
Is dit hoe hij op het idee van 'ubiquitous language is gekomen'. Developers dwingen de taal van de business te gebruiken in plaats van technisch jargon?
|
||||||
|
|
||||||
|
Gaat de vergelijking met natuurlijke talen op? Het lijkt me wel
|
||||||
|
|
||||||
|
gaat het misschien zelfs dieper? Kan de structuur van de business taal verloren gaan door technische principes, zoals code reuse, toe te passen? Het lijkt me wel.
|
||||||
|
51
|
||||||
25
blog/hergebruik.md
Normal file
25
blog/hergebruik.md
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
Een aspect waar ik nooit iemand over hoor als het gaat over code dupliceren, versus hergebruiken (abstraheren etc) is dit: je hebt code en je hebt ... tja, code.
|
||||||
|
|
||||||
|
Je hebt technische code, die een file leest, of queries uitvoert, of een moeilijk algoritme uitvoert zoals een _dual pivot quicksort_.
|
||||||
|
|
||||||
|
En je hebt code die een lijstje gegevens uit de database haalt en kijkt of daar een bepaalde waarde in voorkomt. Of zoiets. De 'domme' code die bovenop de lowlevel technische lagen komt. Kan ook heel complex zijn door de combinaties van regels. Het is ook het deel van de applicatie dat min of meer rechtreeks voortkomt uit de wensen van die ene gebruiker drie jaar geleden. En omdat een andere gebruiker dit jaar een net andere wens heeft voor dat lijstje, kopieren de de oude code, passen iets aan en voila, het werkt.
|
||||||
|
|
||||||
|
Een sorteer algoritme is bijna wiskunde. Quicksort is quicksort, onafhankelijk van de wetten van het universum, of van gebruikerswensen. De komende honderd jaar komen er misschien sorteer algoritmes bij, maar dat maakt de oude niet minder goed.
|
||||||
|
|
||||||
|
Gebruikers daarentegen zijn grillige wezens. Misschien willen ze wel elke maand iets anders, als je ze de kans geeft. Dit deel van de code is veranderlijk, komt heel vaak in verschillende variaties voor. Omdat het moeilijk is om het gemeenschappelijke erin zo te maken dat het maar één keer in de code hoeft te staan.
|
||||||
|
|
||||||
|
**Moet je überhaupt hergebruiken?**
|
||||||
|
Neem dat ene geval waarbij je data wil tonen in een tabel op het scherm. De query om de data op te halen wordt nog een paar keer aangeroepen om dropdowns voor filters te kunnen vullen. De rijen op het scherm zijn gesorteerd. Ja het hoeft niet voor de dropdown, maar het werkt toch prima? Totdat het onmogelijk lang duurt.
|
||||||
|
|
||||||
|
Of je stopt het in een aparte library zodat je buurteam het ook kan gebruiken. Iedere nieuwe developer neemt aan dat het de ultieme waarheid is, tot iemand ze vertelt dat zelf aan kunnen passen. Ja je moet wel een aparte pipeline draaien en dan de dependency versie updaten. Je bent zo een paar uur verder, met je toevoeging aan een _Enum_. En maar hopen dat het geen code breekt van andere teams.
|
||||||
|
|
||||||
|
Zodra je de ultieme waarheid hebt ontdekt is het overigens prima om dat in code uit te hakken. Quicksort bijvoorbeeld. Dat wiel vind je liever niet opnieuw uit.
|
||||||
|
|
||||||
|
**Leftpad**
|
||||||
|
We zijn doorgeschoten in het importeren van standaard functies, die we ook zelf hadden kunnen schrijven. Leftpad in de javascript wereld. Maar voor java: guava, commons-text, commons-io. Ik noem maar een paar. Mijn favoriete hobby is het vervangen van guava *List* factories door standaard java functies. Ja het werkt. Totdat er een *vulnerability* in zit. Of de developer zijn toetsenbord aan de wilgen hangt. String.isEmpty? Heb je dat echt nodig?
|
||||||
|
|
||||||
|
**Logging**
|
||||||
|
Mijn grootste
|
||||||
|
|
||||||
|
**hoe vaak verandert het?**
|
||||||
|
en hoe groot is de moeite om de abstractie te ontleden om dat ene afwijkende geval in te bouwen
|
||||||
62
blog/senior.md
Normal file
62
blog/senior.md
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
layout: post
|
||||||
|
|
||||||
|
title: "Wat is het verschil tussen een junior en een senior developer?"
|
||||||
|
|
||||||
|
author: sander.hautvast
|
||||||
|
|
||||||
|
categories: [java, jdk-22]
|
||||||
|
|
||||||
|
image: assets/images/classfile/writer.jpg
|
||||||
|
|
||||||
|
beforetoc: "seeds"
|
||||||
|
|
||||||
|
featured: true
|
||||||
|
|
||||||
|
hidden: false
|
||||||
|
|
||||||
|
lang: nl
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Performance probleem in een middelgrote (java) applicatie: in de frontend kun je voor het overzichtscherm filteren op diverse kolommen in de database. Die waardes worden dynamisch bepaald (zonder caching) en komen dan in drop-downs terecht.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Na een paar jaar in productie performt dit niet meer zo goed. Er komt een story voor op de backlog en de junior in het team pakt het op. Ik was even met hem gaan zitten om de aanpak door te spreken. Die leek me prima: log statements inbouwen en op de testomgeving kijken waar de meeste tijd in gaat zitten. _Keep it simple_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Elke dag in de standup geeft hij een update en er lijkt genoeg voortgang in te zitten. Toch duurt het nu al zeker een sprint. Niet zo'n probleem, want dat heb ik zelf ook vaak bij deze opdrachtgever....
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Het feit dat hij in de standup meldt dat de sortering (in java) de meeste tijd kost en dat hij die naar de database wil verplaatsen met een _order-by_ doet geen alarmbellen afgaan. Integendeel: de database kan dat vaak sneller. Bovendien is iedereen druk met andere zaken. Op het moment dat we met een mede-senior toch eens dieper op de story ingaan, zien we dat hij erg veel code heeft gewijzigd in zijn branch. Allebei kennen we dit deel van de applicatie niet zo goed. De _refactoring_ lijkt daarom best riskant.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Maar eh, waarom sorteren we eigenlijk? We willen een lijstje unieke waardes. Moeten we daar x-duizend records voor sorteren??
|
||||||
|
|
||||||
|
Ah, _hergebruik_... De code die de filterwaardes bepaalt (dynamisch opgebouwde query) doet ook de uiteindelijke selectie voor de records op het overzichtsscherm. Voor dat laatste is sortering zinvol. Maar voor de filterwaardes hoeft dat helemaal niet!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Kortom: als we de bewuste methode dupliceren en bij één ervan de sortering weglaten, zijn we er ook.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
En ja, ik heb liever leesbare code, die er twee keer staat, dan iets abstracts, waar je eerst een half uur moet studeren voor het begint in te dalen wat er precies gebeurt.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
En dan: waarom voeren we de query vijf keer uit? O, omdat er vijf kolommen zijn op te filteren. Kan dat niet in één keer? O, en wat is dat, Spring BeanUtils? Het R-woord: _Reflectie_ De oorspronkelijke developer, nu niet meer in het team, heeft zich uitgeleefd om alles lekker abstract en dynamisch te maken, zonder zich zorgen te maken over toekomstige ontwikkelingen, zoals junior developers of meer data in de database.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dus drie mogelijke performance verbeteringen en de nodige kansen om de code simpeler te maken. Klinkt als een plan. En niet alles in één keer uitvoeren. Eerst maar eens kijken of een enkele optimalisatie genoeg is. (Is er ook een test die dit afdekt?)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Kortom, twee weken weggegooid werk? Ja, een senior had dit waarschijnlijk beter gedaan. Maar hoe word je senior, behalve door stug door te gaan met ouder worden? We zelf toch ook vaak genoeg op de bek gegaan. En hoe leer je code kennen? Door eens wat te refactoren. Misschien niet committen.
|
||||||
|
|
||||||
5
blog/uniek.md
Normal file
5
blog/uniek.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
Wanneer is iets uniek?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Twee records met dezelfde waardes, behalve de ID kolom. Zijn die het zelfde?
|
||||||
3272
vault.js
3272
vault.js
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue