Compare commits
2 commits
master
...
algebraic-
Author | SHA1 | Date | |
---|---|---|---|
9dcedab3aa | |||
96646455bd |
|
@ -69,6 +69,19 @@ figcaption { text-align: right; font-style: italic; font-size: 0.875em; }
|
||||||
#toc ul { padding-left: 2em; }
|
#toc ul { padding-left: 2em; }
|
||||||
#toc, blockquote, pre.example, .line-block { margin: 1rem; padding: 1rem; border-left: solid var(--gr); }
|
#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; }
|
.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 */
|
/* COLORS */
|
||||||
/* colortheme switch */
|
/* colortheme switch */
|
||||||
|
|
146
src/posts/0022-even-more-stupid-than-you-think/index.org
Normal file
146
src/posts/0022-even-more-stupid-than-you-think/index.org
Normal file
|
@ -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…
Reference in a new issue