Compare commits

...

2 Commits

  1. 13
      src/css/y.css
  2. 146
      src/posts/0022-even-more-stupid-than-you-think/index.org

13
src/css/y.css

@ -69,6 +69,19 @@ figcaption { text-align: right; font-style: italic; font-size: 0.875em; }
#toc ul { padding-left: 2em; }
#toc, blockquote, pre.example, .line-block { margin: 1rem; padding: 1rem; border-left: solid var(--gr); }
.pubDate { display: inline-block; width: 7em; font-size: .825em; opacity: 0.4; }
/* blockquote */
blockquote {
padding-top: 0;
padding-bottom: 0;
}
blockquote > p:first-child {
margin-top: 0;
padding-top: 0;
}
blockquote > p:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
/* COLORS */
/* colortheme switch */

146
src/posts/0022-even-more-stupid-than-you-think/index.org

@ -0,0 +1,146 @@
#+title: Even more stupid than you think
#+description:
#+keywords: programming
#+author: Yann Esposito
#+email: yann@esposito.host
#+date: [2021-11-02 Tue]
#+lang: en
#+options: auto-id:t
#+startup: showeverything
We all know about the [[https://en.wikipedia.org/wiki/KISS_principle][KISS (keep it simple, stupid)]] principle.
In fact, unlike what it looks to suggest. Keeping things simple is more
difficult than one imagine at first[fn:simple-vs-easy].
The other adage from Einstein being:
#+begin_quote
Make everything as simple as possible, but not simpler.
---Albert Einstein[fn:einstein]
#+end_quote
And what is hidden here, is the fact that finding a way to build something
that is simple need an internal comprehension of the system.
To me this is typically what algebra is all about.
Find a system as simple as possible that still respect a set of properties.
So after a few years of experience in software development everyone will
agree with the principle.
And this is a bit easy to agree with a principle.
What is difficult is to really dig about how simple something could be.
So here are a few evidences about my experience about how far you can go.
And if you don't like the word "simple" think about the word /abstraction/.
The sense of /abstraction/ is also quite large.
If I wanted to be more precise, I would say, that a good programming
abstraction is generally sustained by a good algebraic abstraction.
What provide a good algebraic abstraction is the certainty that your system
will be *composable* upon some properties.
So the important word here is *composability* which is arguably superior to /modularity/.
Here are a few example about how far we could / should go.
[fn:simple-vs-easy] If you want a great overview of the subject, I highly
suggest you to watch [[https://thestrangeloop.com/2011/simple-made-easy.html][Simple made Easy]] video from Rich Hickey.
[fn:einstein] This is only attributed to Albert Einstein. He apparently
said something similar but we don't have any strong evidence he wrote or
said exactly that.
* CRUD+Search
:PROPERTIES:
:CUSTOM_ID: crud-search
:END:
With this simple abstraction you could build successful API.
#+begin_src clojure
(defprotocol CRUDPS
(create [this id value])
(read [this id])
(update [this id new-value])
(delete [this id])
(patch [this id new-partial-value])
(search [this partial-value pagination-parameters]))
#+end_src
One important detail is that we could provide "partial values".
So we should have a language that should support the notion of "sub-object".
And if you are doing this in javascript, this should be easy.
In Java or Haskell, it might be a bit more funky.
So just that. It is even simpler than an ORM.
You don't need more than that most of the time.
If you force yourself to work within this restriction this give you
immediately a few pretty good properties.
1. *Portability*; This protocol is so simple to write it is easy to implement
it for different DBs. Postgres, ES, MongoDB, etc...
2. *Scalability*; as this only focus on a single table/index, you do not have
to think about join.
One of the most important property of my system is generally to never
write join.
And you can go surprisingly far without the need of any join.
In fact, most of the time "fake join" are more efficient, et good enough
for almost all user facing use case.
3. *Simplicity*; by only using this API internally, it is easy to manipulate
DB accesses.
Use HTTP, with 90% CRUD + Search.
This is enough for most use cases.
And by search, don't think about something too fancy.
A sub-JSON will be enough for most use case.
Then later you will probably want to add text search/matching.
Why sub-JSON is probably superior to your SQL query?
Because it is composable, more precisely this is a morphism, which SQL
queries aren't.
What do I precisely mean by "sub-JSON"?
Simply the ~<@~ operator in Postgres.
Or the basic MongoDB/ES search.
Not some system introducing complex structure.
So you want to match:
#+begin_src js
{"foo":"bar"}
// should match with
{"foo": bar,
"x": "y"}
// but shouldn't match
{"foo":"notbar",
"x":"y"}
//nor
{"x":"y"}
#+end_src
So this is a morphism with the following property:
#+begin_src
(find x) AND (find y) <=> (find (x inter y))
#+end_src
Which is not possible to easily do with a SQL query.
If you have a string representing a query Q1, and another string
representing a query Q2.
It is difficult to produce a query for Q1 AND Q2.
Because, there are field selection for example.
For most modern web application/API you don't need to enforce strong
constant on that either.
For example, you can loose so much time trying to support a great update or patch.
Doing so in a concurrent system is hard.
If you don't care much, most of the time this will be perfectly ok.
So just with that and the correct data structure.
No search by text, no join.
Just 1 table, per data structure saving JSON + the ability to search by sub-json.
We created, multiple time, a big reliable and nice to use API.
No surprise, no discussion about query optimization, no problem about scalability.
Loading…
Cancel
Save