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) |