brick-house
This commit is contained in:
parent
52876c05ad
commit
ab3972ff04
BIN
assets/_cheese/2022/brick-house.jpg
Normal file
BIN
assets/_cheese/2022/brick-house.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
@ -26,7 +26,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0.5em 0;
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
@ -78,14 +78,12 @@ figure {
|
|||||||
|
|
||||||
img,figcaption {
|
img,figcaption {
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
width: 90%;
|
|
||||||
max-width: 600px;
|
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
height: auto;
|
height: auto;
|
||||||
display: block
|
display: block
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:500px) {
|
@media (max-width:600px) {
|
||||||
img,figcaption {
|
img,figcaption {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -249,7 +247,7 @@ nav#TableOfContents ul {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:500px) {
|
@media (max-width:600px) {
|
||||||
nav#TableOfContents {
|
nav#TableOfContents {
|
||||||
float: none;
|
float: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -294,7 +292,7 @@ nav#TableOfContents ul {
|
|||||||
content: ' - ';
|
content: ' - ';
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:500px) {
|
@media (max-width:600px) {
|
||||||
.article-list li .article-date,
|
.article-list li .article-date,
|
||||||
.article-date li .article-title {
|
.article-date li .article-title {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -1,11 +1,95 @@
|
|||||||
---
|
---
|
||||||
title: "git-subtrac and Zig"
|
title: "zig, git-subtrac and dependencies"
|
||||||
date: 2022-04-23T05:37:51+03:00
|
date: 2022-04-23T05:37:51+03:00
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
TLDR: I wish plain `git clone <repository>` would check out submodules if they
|
TLDR: modern programming languages make it very easy to add many dependencies.
|
||||||
are in the same repository.
|
That is nice for development, but a nightmare for maintenance. Unfortunately,
|
||||||
|
zig is following suit. I wish we could accept that adding dependencies does not
|
||||||
|
have to be trivial. If we accept that, thanks to ubiquity of git, we may have
|
||||||
|
almost solved the dependency problem.
|
||||||
|
|
||||||
|
Adding dependencies
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
All of the programming languages I've used professionally whose name does not
|
||||||
|
start with "c"[^1] have package managers[^2], which make "dependency
|
||||||
|
management" easy. These package managers will, as part of the project's build
|
||||||
|
process, download and build the dependencies, making adding and using
|
||||||
|
third-party dependencies easy.
|
||||||
|
|
||||||
|
Because C/C++ still does not have a universal package manager, not adding
|
||||||
|
external dependencies to C/C++ is the path of least resistance. Instead, it is
|
||||||
|
common to rely on libraries already installed in the system. Because of this
|
||||||
|
cultural difference, there is a plethora of dependency managers that will
|
||||||
|
discover, but not install dependencies: autotools, cmake, pkg-config and
|
||||||
|
others. As a result, C/C++ projects I've been involved usually had 0-5
|
||||||
|
non-system dependencies, whereas non-C/C++ projects -- tens, hundreds or
|
||||||
|
thousands[^3]. Having many system dependencies is painful for user experience,
|
||||||
|
so (the good) C/C++ projects also avoid having too many of them.
|
||||||
|
|
||||||
|
Not doing things that are easy to do requires discipline: brushing teeth,
|
||||||
|
limiting candy intake, not adding dependencies all over the place. If it is
|
||||||
|
easy to add dependencies and there is no discipline not doing so, the project
|
||||||
|
will gain a lot of dependency "weight" with time.
|
||||||
|
|
||||||
|
{{<img src="_cheese/2022/brick-house.jpg"
|
||||||
|
alt="House made out of Duplo pieces"
|
||||||
|
caption="Just like this brick house, \"modern\" package managers are optimized for building, not maintenance. Photo mine, house by my sons."
|
||||||
|
hint="photo"
|
||||||
|
>}}
|
||||||
|
|
||||||
|
In Go and Python small number of dependencies is often a sign of care and
|
||||||
|
quality. [mattn/go-sqlite3](https://github.com/mattn/go-sqlite3),
|
||||||
|
[uber/zap](https://github.com/uber-go/zap),
|
||||||
|
[apenwarr/redo](https://github.com/apenwarr/redo) and
|
||||||
|
[django](https://djangoproject.com) are good examples. Making it easy to depend
|
||||||
|
on external code is is convenient during development, but frees developers from
|
||||||
|
their basic right (or obligation?) to audit understand them. And adds real
|
||||||
|
long-term maintenance costs.
|
||||||
|
|
||||||
|
The costs of just having dependencies are huge. I haven't done a survey and
|
||||||
|
have only my experience to base this on (read: "many anecdotes of me failing to
|
||||||
|
build stuff I wrote a decade ago"). But it is bad enough that I have a
|
||||||
|
dependency checklist and am prepared to do grunt work to avoid or strip it.
|
||||||
|
Here is my checklist:
|
||||||
|
|
||||||
|
- Obvious: does it work at all?
|
||||||
|
- How easy is it to build, run and run it's tests?
|
||||||
|
- Is it well written? API surface, documentation, tests, error handling, error
|
||||||
|
signaling, logging, metrics (if applicable), etc.
|
||||||
|
- It's system dependencies.
|
||||||
|
- It's transitive dependencies.
|
||||||
|
|
||||||
|
If a dependency is well written, but has more transitive dependencies than I
|
||||||
|
need and there is no good alternative, I will fork it and remove unnecessary
|
||||||
|
code and dependencies. My recent example is
|
||||||
|
[sql-migrate](https://github.com/motiejus/sql-migrate).
|
||||||
|
|
||||||
|
To sum up, the "modern" languages optimize for initial development experience,
|
||||||
|
not maintenance. And as [Corbet says][linux-rust]. "We can't understand why
|
||||||
|
Kids These Days just don't want to live that way". Kids want to build, John,
|
||||||
|
not maintain. A 4-letter Danish corporation made a fortune by selling toys that
|
||||||
|
do not need to be maintained: they are designed to be disassembled and built
|
||||||
|
anew. It is very hard to change the guts of an existing structure without
|
||||||
|
rebuilding it.
|
||||||
|
|
||||||
|
If I may combine Corbet's views with mine: if we understand and audit our
|
||||||
|
dependencies (and transitive ones), we will have less dependencies and a more
|
||||||
|
maintainable system. Win-win.
|
||||||
|
|
||||||
|
Which brings us to...
|
||||||
|
|
||||||
|
Transitive dependencies and git-subtrac
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
[`git-subtrac`][git-subtrac] does not deal with transitive dependencies. At
|
||||||
|
least not directly. Or I am not aware of it. Ok, I haven't tried.
|
||||||
|
|
||||||
|
If we audit and thus understand our dependencies, we will be able to add
|
||||||
|
transitive ones to our project even without support of git-subtrac. So perhaps
|
||||||
|
git-subtrac shouldn't care?
|
||||||
|
|
||||||
I use [`git-subtrac`][git-subtrac] for some of my projects, and am not very
|
I use [`git-subtrac`][git-subtrac] for some of my projects, and am not very
|
||||||
enthusiastic about Zig getting it's own package manager (can we all use
|
enthusiastic about Zig getting it's own package manager (can we all use
|
||||||
@ -13,8 +97,8 @@ git-subtrac and be done with it?). A few weeks ago in a park in Milan my
|
|||||||
conversation with [Andrew Kelley](https://andrewkelley.me/) was something like:
|
conversation with [Andrew Kelley](https://andrewkelley.me/) was something like:
|
||||||
|
|
||||||
- me: "git-subtrac yadda yadda yadda submodules but better yadda yadda yadda".
|
- me: "git-subtrac yadda yadda yadda submodules but better yadda yadda yadda".
|
||||||
- Andrew: "if I clone a repository that uses git-subtrac with no extra
|
- Andrew: "if I clone a repository that uses it with no extra parameters, will
|
||||||
parameters, will it work as expected?"
|
it work as expected?"
|
||||||
- me: "no, you have to pass `--recursive`, so git will checkout submodules...
|
- me: "no, you have to pass `--recursive`, so git will checkout submodules...
|
||||||
even if they are already fetched."
|
even if they are already fetched."
|
||||||
- Andrew: "then it's a piece-of-shit-approach."
|
- Andrew: "then it's a piece-of-shit-approach."
|
||||||
@ -37,80 +121,6 @@ make our dependency unavailable.
|
|||||||
It is, howerver, harder to *add* a dependency with submodules than with, say,
|
It is, howerver, harder to *add* a dependency with submodules than with, say,
|
||||||
`go get <dependency>`. Let's talk about adding dependencies.
|
`go get <dependency>`. Let's talk about adding dependencies.
|
||||||
|
|
||||||
Adding dependencies
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
All of the programming languages I've used professionally whose name does not
|
|
||||||
start with "c"[^1] have package managers[^2], which make "dependency
|
|
||||||
management" easy. These package managers will download and build the dependency
|
|
||||||
tree, sometimes conveniently generate a "lock file", so your project has an
|
|
||||||
illusion of being "reproducible".
|
|
||||||
|
|
||||||
C/C++ projects I've been involved usually had 1-5 non-system dependencies,
|
|
||||||
whereas all others -- tens or hundreds. This uncovers an obvious correlation:
|
|
||||||
if it's easy to add dependencies, they will be added. En masse. Not adding
|
|
||||||
dependencies in Go/Python/whatever requires discipline. Slip once, add some
|
|
||||||
crap -- it will be very hard to remove, as changing dependencies often require
|
|
||||||
large rewrites. Not adding dependencies in C/C++, however, is the path of least
|
|
||||||
resistance. However, in the long term, my C/C++ projects tended to survive
|
|
||||||
longest (or required least amount of changes to build and run after the world
|
|
||||||
moved on) just because of this.
|
|
||||||
|
|
||||||
Making it easy to depend on external code is is convenient during development,
|
|
||||||
but frees (or denies, depending how one looks at it) developers from their
|
|
||||||
basic right (or obligation?) to understand them. And adds real long-term
|
|
||||||
maintenance costs.
|
|
||||||
|
|
||||||
To sum up, the "modern" languages optimize for initial development experience,
|
|
||||||
not maintenance. And as [Corbet says][linux-rust]. "We can't understand why
|
|
||||||
Kids These Days just don't want to live that way". Kids want to build, John,
|
|
||||||
not maintain. This house is in desperate need of maintenance, but my son
|
|
||||||
refuses to do so, and builds a new car instead.
|
|
||||||
|
|
||||||
{{<img src="https://dl.jakstys.lt/mtpad/house.jpg"
|
|
||||||
alt="House of Duplo pieces"
|
|
||||||
caption="House of Duplo pieces"
|
|
||||||
width="50%"
|
|
||||||
>}}
|
|
||||||
|
|
||||||
This is why I am always hesitant to pull in code to my project, and have a my
|
|
||||||
dependency checklist:
|
|
||||||
|
|
||||||
- Obvious: does it work at all?
|
|
||||||
- How easy is it to build, run and run it's tests?
|
|
||||||
- Is it well written? API surface, documentation, tests, error handling, error
|
|
||||||
signaling, logging, metrics (if applicable), etc.
|
|
||||||
- It's system dependencies.
|
|
||||||
- It's transitive dependencies.
|
|
||||||
|
|
||||||
Zooming into the last part: C projects tend to do it well. For Go and Python
|
|
||||||
projects a small number of dependencies is often a sign of care and quality on
|
|
||||||
other areas, too. [mattn/go-sqlite3](https://github.com/mattn/go-sqlite3),
|
|
||||||
[google/brotli](https://github.com/google/brotli),
|
|
||||||
[apenwarr/redo](https://github.com/apenwarr/redo),
|
|
||||||
[cmph](http://cmph.sourceforge.net/) are good examples.
|
|
||||||
|
|
||||||
If a dependency is well written, but has more transitive dependencies than I
|
|
||||||
need and there is no good alternative, I will fork it and remove unnecessary
|
|
||||||
code and dependencies. My recent example is
|
|
||||||
[sql-migrate](https://github.com/motiejus/sql-migrate).
|
|
||||||
|
|
||||||
If I may combine Corbet's views with mine: if we understand and audit our
|
|
||||||
dependencies (and transitive ones), we will have less dependencies and a more
|
|
||||||
maintainable system. Win-win.
|
|
||||||
|
|
||||||
Which brings us to...
|
|
||||||
|
|
||||||
Transitive dependencies and git-subtrac
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
[`git-subtrac`][git-subtrac] does not deal with transitive dependencies. At
|
|
||||||
least not directly. Or I am not aware of it. Ok, I haven't tried.
|
|
||||||
|
|
||||||
If we audit and thus understand our dependencies, we will be able to add
|
|
||||||
transitive ones to our project even without support of git-subtrac. So perhaps
|
|
||||||
git-subtrac shouldn't care?
|
|
||||||
|
|
||||||
Conclusion
|
Conclusion
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -118,10 +128,12 @@ Can git checkout local submodules when they are in the same repository, so our
|
|||||||
conversation of reconsidering (or not having) a zig package manager doesn't
|
conversation of reconsidering (or not having) a zig package manager doesn't
|
||||||
stop after 5 seconds?
|
stop after 5 seconds?
|
||||||
|
|
||||||
[^1]: Alphabetically: Erlang, Go, Javascript, PHP, Perl, Python.
|
[^1]: Alphabetically: Erlang, Go, Java, Javascript, PHP, Perl, Python.
|
||||||
[^2]: Usually written in the same language. Zoo of package managers (sometimes
|
[^2]: Usually written in the same language. Zoo of package managers (sometimes
|
||||||
a couple of popular ones for the same programming language) is a can of worms
|
a couple of popular ones for the same programming language) is a can of worms
|
||||||
in an on itself worth another blog post.
|
in an on itself worth another blog post.
|
||||||
|
[^3]: `go.sum` of a project I am currently involved clocks around 6k lines.
|
||||||
|
This is quite a lot for Go, but still peanuts to Node.js.
|
||||||
|
|
||||||
[git-subtrac]: https://github.com/apenwarr/git-subtrac/
|
[git-subtrac]: https://github.com/apenwarr/git-subtrac/
|
||||||
[linux-rust]: https://lwn.net/SubscriberLink/889924/a733d6630e3b5115/
|
[linux-rust]: https://lwn.net/SubscriberLink/889924/a733d6630e3b5115/
|
||||||
|
79
layouts/shortcodes/img.html
Normal file
79
layouts/shortcodes/img.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
# Responsive images and resizing
|
||||||
|
|
||||||
|
Our picture width is 700 css pixels. "Retina" screens have 2 device pixel ratio
|
||||||
|
(dpr), crazy folks have 4. So the maximum width of the picture we can possibly
|
||||||
|
care about is 700*4=2800px.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- image -->
|
||||||
|
{{ $src := resources.GetMatch (.Get "src") | resources.Fingerprint }}
|
||||||
|
{{ $max := $src | resources.Fingerprint }}
|
||||||
|
{{ $j350 := $src.Resize "350x" }}
|
||||||
|
{{ $j700 := $src.Resize "700x" }}
|
||||||
|
{{ $j1400 := $src.Resize "1400x" }}
|
||||||
|
{{ $j2800 := $src.Resize "2800x" }}
|
||||||
|
|
||||||
|
{{ with .Get "hint" }}
|
||||||
|
{{ else }}
|
||||||
|
{{ errorf "missing value for param 'hint': %s" .Position }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $hint := .Get "hint" }}
|
||||||
|
{{ $w350 := $src.Resize (print "350x webp " $hint ) }}
|
||||||
|
{{ $w700 := $src.Resize (print "700x webp " $hint ) }}
|
||||||
|
{{ $w1400 := $src.Resize (print "1400x webp " $hint ) }}
|
||||||
|
{{ $w2800 := $src.Resize (print "2800x webp " $hint ) }}
|
||||||
|
|
||||||
|
<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
|
||||||
|
{{ with .Get "link" }}<a href="{{ . }}">{{ end }}
|
||||||
|
<picture>
|
||||||
|
<source type="image/webp"
|
||||||
|
sizes="(max-width: 600px) 350px, 700px"
|
||||||
|
srcset='
|
||||||
|
{{- if ge $src.Width "350" }}
|
||||||
|
{{ with $w350.RelPermalink }}{{.}} 350w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "700" }}
|
||||||
|
{{ with $w700.RelPermalink }}, {{.}} 700w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "1400" }}
|
||||||
|
{{ with $w1400.RelPermalink }}, {{.}} 1400w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "2800" }}
|
||||||
|
{{ with $w2800.RelPermalink }}, {{.}} 2800w{{ end }}
|
||||||
|
{{- end }}'
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
sizes="(max-width: 600px) 350px, 700px"
|
||||||
|
srcset='
|
||||||
|
{{- if ge $src.Width "350" }}
|
||||||
|
{{ with $j350.RelPermalink }}{{.}} 350w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "700" }}
|
||||||
|
{{ with $j700.RelPermalink }}, {{.}} 700w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "1400" }}
|
||||||
|
{{ with $j1400.RelPermalink }}, {{.}} 1400w{{ end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if ge $src.Width "2800" }}
|
||||||
|
{{ with $j2800.RelPermalink }}, {{.}} 2800w{{ end }}
|
||||||
|
{{- end }}'
|
||||||
|
src="{{ $j700.RelPermalink }}"
|
||||||
|
{{ if or (.Get "alt") (.Get "caption") }}alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" }}{{ end }}"{{ end }}
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
|
{{ if .Get "link" }}</a>{{ end }}
|
||||||
|
{{ if or (or (.Get "title") (.Get "caption")) (.Get "attr") }}
|
||||||
|
<figcaption>{{ if isset .Params "title" }}
|
||||||
|
<h4>{{ .Get "title" }}</h4>{{ end }}
|
||||||
|
{{ if or (.Get "caption") (.Get "attr") }}<p>
|
||||||
|
{{ .Get "caption" }}
|
||||||
|
{{ with .Get "attrlink" }}<a href="{{ . }}"> {{ end }}
|
||||||
|
{{ .Get "attr" }}
|
||||||
|
{{ if .Get "attrlink" }}</a> {{ end }}
|
||||||
|
</p> {{ end }}
|
||||||
|
</figcaption>
|
||||||
|
{{ end }}
|
||||||
|
</figure>
|
||||||
|
<!-- image -->
|
Loading…
Reference in New Issue
Block a user