5f85cb94b094eb4886c0b76017a9c970e4f93ac3
WellKnownIdentifier.md
... | ... | @@ -0,0 +1,171 @@ |
1 | +# Well-known Identifier |
|
2 | + |
|
3 | +## Introduction |
|
4 | + |
|
5 | +Well-known Identifiers are predictable identifiers or location descriptors, by |
|
6 | +which humans or machines can find certain files, executables, services, or |
|
7 | +resources. They allow a human or computer to discover affordances within a given |
|
8 | +context, which expose a well-known interface, without the need of additional out |
|
9 | +of band information. |
|
10 | + |
|
11 | +The description of this pattern is inspired by [Well-Known Uniform Resource |
|
12 | +Identifiers](https://en.wikipedia.org/wiki/Well-known_URI), by recognizing that |
|
13 | +this is a more general pattern. Once you start looking for it you will discover |
|
14 | +it in very different kind of contexts. |
|
15 | + |
|
16 | +Some of the examples may seem trite and obvious, but we think it's useful to |
|
17 | +recognize the common pattern across different contexts, to consider why this |
|
18 | +pattern works (for technical and cultural reasons), and to consider in which |
|
19 | +other contexts this pattern could be applied but is not yet common practice. |
|
20 | + |
|
21 | +## Tensions |
|
22 | + |
|
23 | +Computer systems consist of many different software components. These components |
|
24 | +expose affordances, which can be used by other components, or by human |
|
25 | +operators. Examples of affordances are the awk interpreter, a HTTP endpoint, a |
|
26 | +function in a library, or the Linux kernel API. These are all resources the |
|
27 | +environment may offer to the programmer and their program. |
|
28 | + |
|
29 | +These affordances need to be discovered. The programmer can do so by consulting |
|
30 | +documentation, or using introspection facilities of the environment. The |
|
31 | +specifics can then be encoded inside the program. This however makes the program |
|
32 | +rigid and brittle. These specifics can and will change, or differ across |
|
33 | +contexts (systems), so instead we make them configurable, so the program makes |
|
34 | +fewer assumptions, and thus can be more easily adapted to a new context or |
|
35 | +environment. |
|
36 | + |
|
37 | +But this reduces convenience. Before the program "just worked" (within a narrow |
|
38 | +context), the new program can operate in a broader context, but only after |
|
39 | +appropriately configuring it. Thus a tension arises. |
|
40 | + |
|
41 | +Well-known identifiers resolve this tension by allowing the program/programmer |
|
42 | +to make certain assumptions safely, because there is an agreed upon convention |
|
43 | +for where to discover certain affordances. |
|
44 | + |
|
45 | +For the developer they resolve a tension between novelty and familiarity, |
|
46 | +allowing existing knowledge to transfer to new software, because new |
|
47 | +functionality is provided through a familiar interface. |
|
48 | + |
|
49 | +## Pattern Description |
|
50 | + |
|
51 | +Given a directory or namespace lookup system (file system paths, URL paths, |
|
52 | +namespaces of symbols and function, etc), if there is either a documented |
|
53 | +standard or a strong cultural convention that a certain type of affordance |
|
54 | +(abstract interface) is available under a specific identifier, then this forms a |
|
55 | +Well-known Identifier. |
|
56 | + |
|
57 | +Well-known Identifiers are resolved relatively to a given context, like the |
|
58 | +current filesystem, a HTTP origin, or the current classpath. In this sense they |
|
59 | +provide an abstraction. Each context can decide what to provide at that |
|
60 | +identifier (location), as long as what is provided implemements the expected |
|
61 | +interface or format. |
|
62 | + |
|
63 | +Well-known Identifiers are both a technical and a cultural pattern. Technically |
|
64 | +they complement the idea of "programming to an interface, not to an |
|
65 | +implementation". They answer the question of where to find, or how to access, |
|
66 | +the interface. They allow for service discovery, and form a type of |
|
67 | +[[ConventionOverConfiguration]]. |
|
68 | + |
|
69 | +How "well-known" an identifier is is a sliding scale. Often only a subset of |
|
70 | +existing systems will use a well-known common name, while others use other |
|
71 | +arbitrarily chosen names, leading to unnecessary friction in terms of |
|
72 | +interoperability. It is the role of technology leaders to push for adoption of |
|
73 | +well-known identifiers within the projects they lead, as well as to recognize |
|
74 | +the potential of coining identifiers in new areas, and to advocate for their |
|
75 | +common use. |
|
76 | + |
|
77 | +Some well-known identifiers are standardized through standard bodies like the |
|
78 | +IETF or W3C, however the existence of a standard does not say anything about its |
|
79 | +adoption, neither does the lack of a standard imply a lack of common use. |
|
80 | +Ultimately adoption is a cultural problem, but the existance of a documented |
|
81 | +standard can certainly help in gaining adoption. |
|
82 | + |
|
83 | +## Examples |
|
84 | + |
|
85 | +On POSIX-compatible operating systems `/bin/sh` is a standard identifier. So is |
|
86 | +`/usr/bin/env`, but `/bin/bash` for instance is not. (Some systems use |
|
87 | +`/usr/bin/bash`). Note that even though these conventions have been common |
|
88 | +practice for decades, it is still possible to find UNIX style systems that don't |
|
89 | +adhere to them. |
|
90 | + |
|
91 | +On the web there are a number of well-known URIs standardized through RFC 8615, |
|
92 | +under the `/.well-known` path prefix, like `/.well-known/webfinger` or |
|
93 | +`/.well-known/caldav`. Another one is `robots.txt` defined in RFC 9309. |
|
94 | + |
|
95 | +There are standard TCP ports by which certain services can be found, like port |
|
96 | +80 for HTTP, 443 for HTTPS, or 25/587 for SMTP. In a sense they are also an |
|
97 | +application of this pattern. |
|
98 | + |
|
99 | +Certain JVM libraries and tools will look for their configuration on the |
|
100 | +classpath, for instance Logback tries to find a `logback.xml`. While this is an |
|
101 | +identifier that's specific to one tool, it's a mechanism that could be leveraged |
|
102 | +more generally. |
|
103 | + |
|
104 | +Similarly JVM system properties that are understood by mutiple libraries/tools |
|
105 | +seems to be an underutilized mechanisms. |
|
106 | + |
|
107 | +There are several commonly used well-known environment variables. Most software |
|
108 | +intended to run in a cloud environment understand the `PORT` variable to decide |
|
109 | +which HTTP port to run on. Most CI environments set the `CI` variable to signal |
|
110 | +that the code is being run on CI. |
|
111 | + |
|
112 | +## Use for Clojure tooling |
|
113 | + |
|
114 | +These standard identifiers are important for machines and programs, but they can |
|
115 | +also be important for humans. Gaiwan does a lot of projects, for clients and |
|
116 | +open-source, and we want people to feel comfortable going from one project to |
|
117 | +another. That's why we have our own set of standard identifiers that we set up |
|
118 | +on every project. |
|
119 | + |
|
120 | +- `bin/launchpad` - start development environment |
|
121 | +- `bin/kaocha` - run tests |
|
122 | +- `(user/go)` - start the application |
|
123 | +- `(user/browse)` - open the application in a browser |
|
124 | + |
|
125 | +Other common identifiers |
|
126 | + |
|
127 | +- `(user/reset)` - use tools.namespace to do a reset/reload of changed namespaces |
|
128 | +- `(user/reset-all)` - use tools.namespace to do a reset/reload of all namespaces |
|
129 | +- `(user/portal)` - launch the portal UI |
|
130 | + |
|
131 | +Some of these we have adopted based on earlier precedent in the Clojure |
|
132 | +ecosystem, some of these we have coined ourselves. In both cases we advocate for |
|
133 | +their adoption and use across the ecosystem. |
|
134 | + |
|
135 | +The first two, `bin/launchpad` and `bin/kaocha`, are worth highlighting. We |
|
136 | +strongly encourage anyone adopting these tools |
|
137 | +([Launchpad](https://github.com/lambdaisland/launchpad) and |
|
138 | +[Kaocha](https://github.com/lambdaisland/launchpad)), to create these two |
|
139 | +executables within their projects. |
|
140 | + |
|
141 | +We sometimes get questions about that. Why not use `clj -X:kaocha`, or `bb run |
|
142 | +launchpad`. The problem with these is that they are not general enough. Not |
|
143 | +every project uses Clojure CLI or Babashka. By having an executable path that is |
|
144 | +independent of the concrete tooling we create an abstraction. From the |
|
145 | +programmer's point of view they can invoke Kaocha the same way on any project. |
|
146 | +The same goes for tooling, like CI, which gets a standardized way to invoke |
|
147 | +Clojure tests. |
|
148 | + |
|
149 | +What goes into these executables can be adjusted to the needs of the project. |
|
150 | +Besides invoking the appropriate Clojure launcher, they can perform additional |
|
151 | +steps. For instance, it's common for `bin/kaocha` to run `npm install` when |
|
152 | +needed. |
|
153 | + |
|
154 | +In [[Gaiwan Corgi]] we have the key combination `,,` to evaluate a snippet |
|
155 | +that's stored in a register, and we set some registers so we can easily invoke |
|
156 | +some of the above. |
|
157 | + |
|
158 | +- `,,g` - runs `(user/go)` |
|
159 | +- `,,b` - runs `(user/browse)` |
|
160 | +- `,,p` - runs `(user/portal)` in clj |
|
161 | +- `,,P` - runs `(user/portal)` in cljs |
|
162 | + |
|
163 | +## Further reading |
|
164 | + |
|
165 | +- [Wikipedia: Well-known URI](https://en.wikipedia.org/wiki/Well-known_URI) |
|
166 | + |
|
167 | +## History |
|
168 | + |
|
169 | +### 2024-05-20 |
|
170 | + |
|
171 | +- First public version (Arne Brasseur) |