diff --git a/Untitled.canvas b/Untitled.canvas new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/Untitled.canvas @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/Untitled.md b/Untitled.md new file mode 100644 index 0000000..e69de29 diff --git a/blog/DDD.md b/blog/DDD.md index 4ef1df6..4a1add1 100644 --- a/blog/DDD.md +++ b/blog/DDD.md @@ -1,11 +1,13 @@ **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? diff --git a/crud-lang/README.md b/crud-lang/README.md new file mode 100644 index 0000000..89717c0 --- /dev/null +++ b/crud-lang/README.md @@ -0,0 +1,46 @@ +# crud-lang + +_This is now in first-draft phase. Meaning, I just had the idea and I am jotting down very preliminary design decisions._ + + * an experimental language for CRUD applications (backend only though) + * Enterprise as a first-class citizen + * urls are made up directories and filenames + * a controller sourcefile is a file with the .ctl extension + * likewise + * .svc services + * .cl service clients (that call other services) + * .dao database access code (not objects) + * .qc queueconsumers + * .qp queueproducers + * .utl utilities + * there is a strict calling hierarchy. A service can not call a controller. It can only go 'down'. + * Services can not call other services, because that is the recipe for spaghetti. Refactor your logic, abstract and put lower level code in utilities. + * Utilities are allowed to call other utilities. OMG, spaghetti after all! TBD + + * It is an interpreter written in rust. OMG! + * And it has everything I like in other languages + * strictly typed + * [] is a list + * {} is a map + * no objects, no inheritance + * structs and duck typing + * everything is an expression + * nice iterators. + * First class functions? Maybe... + +**types** + +- u32, i32 +- u64, i64 +- f32, f64, +- string, bool, char +- struct enum + +**question** + +- how to model headers +- middleware, implement later + +**the example: ** + +- a very simple api that listens to GET /api/customers{:id} and returns a customer from the database diff --git a/crud-lang/src/api/customers.ctl b/crud-lang/src/api/customers.ctl new file mode 100644 index 0000000..f484f62 --- /dev/null +++ b/crud-lang/src/api/customers.ctl @@ -0,0 +1,7 @@ +GET /(id: u32) -> Json: + service.get(id) + +struct Customer: + id: u32, + first_name: string, + last_name: string diff --git a/crud-lang/src/api/customers.dao b/crud-lang/src/api/customers.dao new file mode 100644 index 0000000..c1c014b --- /dev/null +++ b/crud-lang/src/api/customers.dao @@ -0,0 +1,2 @@ +get(id: u32) -> Customer: + @sql(select id, first_name, last_name from customers where id = :id) diff --git a/crud-lang/src/api/customers.model b/crud-lang/src/api/customers.model new file mode 100644 index 0000000..b8933bd --- /dev/null +++ b/crud-lang/src/api/customers.model @@ -0,0 +1,4 @@ +Customer: + id: u32, + first_name: string, + last_name: string, diff --git a/crud-lang/src/api/customers.svc b/crud-lang/src/api/customers.svc new file mode 100644 index 0000000..eedd66a --- /dev/null +++ b/crud-lang/src/api/customers.svc @@ -0,0 +1,2 @@ +get(id: u32) -> Customer: + dao.get(id) diff --git a/tabellen.md b/tabellen.md new file mode 100644 index 0000000..acb6d0a --- /dev/null +++ b/tabellen.md @@ -0,0 +1,19 @@ +Ik ben niet de eerste die dit zegt, maar het is nog geen gemeengoed. +Als je een tabel definieert, neem dan altijd de volgende kolommen op (in volgorde van urgentie): +1. created_at timestamp +2. created_by varchar +3. deleted_at timestamp null +4. deleted_by varchar null +5. updated_at timestamp null +6. updated_by varchar null + +#3 en #4 zijn niet alleen _nullable_, maar ook _optional_. Dat wil zeggen, je kunt het record ook fysiek verwijderen. Maar mijn advies zou zijn: +1. maak een functionele delete logisch (deleted_at/by vullen als een gebruiker iets verwijdert (een functioneel event)) +2. maak een fysieke delete na bijvoorbeeld 2 jaar. Om aan juridische eisen te voldoen, of om verloren diskspace terug te krijgen. Of om zeker te weten dat de data niet gestolen kan worden. Of om tegen wie dan ook (toezichthouders, de politie) vol te kunnen houden dat je de data niet hebt. + +Geloof me, op een dag zul je er voordeel van hebben. + +PS. +#5 zou je zelfs nog kunnen gebruiken als _optimistic locking number_ hoewel een incrementele _integer_ waarde minstens net zo goed is. De overeenkomst is dat beide altijd oplopen. Bij een tijdgebaseerde waarde komen er allerlei vragen bij, zoals wat de precisie is, hoeveel nodes je hebt en of alle klokken gesynchroniseerd zijn. + +PS2. Bij de (gerenommeerde) bank waar ik ooit werkte was het 'toezichthouder'-argument één van de redenen voor een fysieke delete. \ No newline at end of file