update everything, fix up CoP post
This commit is contained in:
parent
dbf6ebdeee
commit
0450e50258
91
Gemfile.lock
91
Gemfile.lock
@ -1,12 +1,12 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.2.2)
|
||||
activesupport (6.0.3.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
coffee-script (2.4.1)
|
||||
@ -16,38 +16,39 @@ GEM
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.17.13)
|
||||
ruby-enum (~> 0.5)
|
||||
concurrent-ruby (1.1.6)
|
||||
dnsruby (1.61.3)
|
||||
addressable (~> 2.5)
|
||||
em-websocket (0.5.1)
|
||||
concurrent-ruby (1.1.7)
|
||||
dnsruby (1.61.5)
|
||||
simpleidn (~> 0.1)
|
||||
em-websocket (0.5.2)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.7.0)
|
||||
faraday (1.0.1)
|
||||
faraday (1.1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.12.2)
|
||||
ruby2_keywords
|
||||
ffi (1.13.1)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.1)
|
||||
github-pages (204)
|
||||
github-pages (209)
|
||||
github-pages-health-check (= 1.16.1)
|
||||
jekyll (= 3.8.5)
|
||||
jekyll (= 3.9.0)
|
||||
jekyll-avatar (= 0.7.0)
|
||||
jekyll-coffeescript (= 1.1.1)
|
||||
jekyll-commonmark-ghpages (= 0.1.6)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.13.0)
|
||||
jekyll-feed (= 0.15.1)
|
||||
jekyll-gist (= 1.5.0)
|
||||
jekyll-github-metadata (= 2.13.0)
|
||||
jekyll-mentions (= 1.5.1)
|
||||
jekyll-mentions (= 1.6.0)
|
||||
jekyll-optional-front-matter (= 0.3.2)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
jekyll-readme-index (= 0.3.0)
|
||||
jekyll-redirect-from (= 0.15.0)
|
||||
jekyll-redirect-from (= 0.16.0)
|
||||
jekyll-relative-links (= 0.6.1)
|
||||
jekyll-remote-theme (= 0.4.1)
|
||||
jekyll-remote-theme (= 0.4.2)
|
||||
jekyll-sass-converter (= 1.5.2)
|
||||
jekyll-seo-tag (= 2.6.1)
|
||||
jekyll-sitemap (= 1.4.0)
|
||||
@ -55,7 +56,7 @@ GEM
|
||||
jekyll-theme-architect (= 0.1.1)
|
||||
jekyll-theme-cayman (= 0.1.1)
|
||||
jekyll-theme-dinky (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.2)
|
||||
jekyll-theme-leap-day (= 0.1.1)
|
||||
jekyll-theme-merlot (= 0.1.1)
|
||||
jekyll-theme-midnight (= 0.1.1)
|
||||
@ -66,13 +67,14 @@ GEM
|
||||
jekyll-theme-tactile (= 0.1.1)
|
||||
jekyll-theme-time-machine (= 0.1.1)
|
||||
jekyll-titles-from-headings (= 0.5.3)
|
||||
jemoji (= 0.11.1)
|
||||
kramdown (= 1.17.0)
|
||||
jemoji (= 0.12.0)
|
||||
kramdown (= 2.3.0)
|
||||
kramdown-parser-gfm (= 1.1.0)
|
||||
liquid (= 4.0.3)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.5.1)
|
||||
nokogiri (>= 1.10.4, < 2.0)
|
||||
rouge (= 3.13.0)
|
||||
rouge (= 3.23.0)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.16.1)
|
||||
addressable (~> 2.3)
|
||||
@ -80,20 +82,20 @@ GEM
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 3.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.12.3)
|
||||
html-pipeline (2.14.0)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.6.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (3.8.5)
|
||||
jekyll (3.9.0)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 0.7)
|
||||
jekyll-sass-converter (~> 1.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 1.14)
|
||||
kramdown (>= 1.17, < 3)
|
||||
liquid (~> 4.0)
|
||||
mercenary (~> 0.3.3)
|
||||
pathutil (~> 0.9)
|
||||
@ -113,14 +115,14 @@ GEM
|
||||
rouge (>= 2.0, < 4.0)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.13.0)
|
||||
jekyll-feed (0.15.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-gist (1.5.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.13.0)
|
||||
jekyll (>= 3.4, < 5.0)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-mentions (1.5.1)
|
||||
jekyll-mentions (1.6.0)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-optional-front-matter (0.3.2)
|
||||
@ -128,14 +130,15 @@ GEM
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-readme-index (0.3.0)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
jekyll-redirect-from (0.15.0)
|
||||
jekyll-redirect-from (0.16.0)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-relative-links (0.6.1)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-remote-theme (0.4.1)
|
||||
jekyll-remote-theme (0.4.2)
|
||||
addressable (~> 2.0)
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
rubyzip (>= 1.3.0)
|
||||
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
|
||||
rubyzip (>= 1.3.0, < 3.0)
|
||||
jekyll-sass-converter (1.5.2)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.6.1)
|
||||
@ -152,8 +155,8 @@ GEM
|
||||
jekyll-theme-dinky (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-hacker (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-hacker (0.1.2)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-leap-day (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
@ -187,13 +190,16 @@ GEM
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
jemoji (0.11.1)
|
||||
jemoji (0.12.0)
|
||||
gemoji (~> 3.0)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
kramdown (1.17.0)
|
||||
kramdown (2.3.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.2.1)
|
||||
listen (3.3.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.3.6)
|
||||
@ -202,22 +208,24 @@ GEM
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.14.0)
|
||||
minitest (5.14.2)
|
||||
multipart-post (2.1.1)
|
||||
nokogiri (1.10.9)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
octokit (4.18.0)
|
||||
octokit (4.19.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (3.1.1)
|
||||
rb-fsevent (0.10.3)
|
||||
rb-fsevent (0.10.4)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rouge (3.13.0)
|
||||
rexml (3.2.4)
|
||||
rouge (3.23.0)
|
||||
ruby-enum (0.8.0)
|
||||
i18n
|
||||
ruby2_keywords (0.0.2)
|
||||
rubyzip (2.3.0)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.7.4)
|
||||
@ -228,15 +236,20 @@ GEM
|
||||
sawyer (0.8.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
simpleidn (0.1.1)
|
||||
unf (~> 0.1.4)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (1.3.1)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.7)
|
||||
tzinfo (1.2.8)
|
||||
thread_safe (~> 0.1)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
zeitwerk (2.3.0)
|
||||
zeitwerk (2.4.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
14
Makefile
14
Makefile
@ -1,8 +1,12 @@
|
||||
# pacman -Sy ruby ruby-bundler
|
||||
BUNDLE := bundle
|
||||
|
||||
serve:
|
||||
${BUNDLE} exec jekyll serve -w -I -D -H 0.0.0.0
|
||||
docker run -it --rm \
|
||||
-v $$(pwd):/srv/jekyll \
|
||||
-p 4000:4000 \
|
||||
jekyll/jekyll \
|
||||
jekyll serve -w -I -D -H 0.0.0.0
|
||||
|
||||
update:
|
||||
${BUNDLE} update
|
||||
docker run -it --rm \
|
||||
-v $$(pwd):/srv/jekyll \
|
||||
jekyll/jekyll \
|
||||
bundle update
|
||||
|
@ -9,6 +9,7 @@ repository: mediocregopher/blog.mediocregopher.com
|
||||
twitter_username: mediocre_gopher
|
||||
github_username: mediocregopher
|
||||
rss: rss
|
||||
highlighter: rouge
|
||||
|
||||
plugins:
|
||||
- jekyll-feed
|
||||
|
@ -6,6 +6,7 @@
|
||||
<link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" href="{{ "/assets/normalize.css" | relative_url }}">
|
||||
<link rel="stylesheet" href="{{ "/assets/skeleton.css" | relative_url }}">
|
||||
<link rel="stylesheet" href="{{ "/assets/friendly.css" | relative_url }}">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{{ "/assets/main.css" | relative_url }}">
|
||||
{%- feed_meta -%}
|
||||
|
@ -8,64 +8,49 @@ description: >-
|
||||
[A previous post in this
|
||||
blog](2019-08-02-program-structure-and-composability.html) focused on a
|
||||
framework developed to make designing component-based programs easier. In
|
||||
retrospect pattern/framework proposed was over-engineered; this post attempts to
|
||||
present the same ideas but in a more distilled form, as a simple programming
|
||||
pattern and without the unnecessary framework.
|
||||
|
||||
Nothing in this post will be revelatory; it's surely all been said before. But
|
||||
hopefully the form it takes here will be useful to someone, as it would have
|
||||
been useful to myself when I first learned to program.
|
||||
|
||||
## Axioms
|
||||
|
||||
For the sake of brevity let's assume the following: within the context of
|
||||
single-process (_not_ the same as single-threaded), non-graphical programs the
|
||||
following may be said:
|
||||
|
||||
1. A program may be thought of as a black-box with certain input and output
|
||||
methods. It is the programmer's task to construct a program such that
|
||||
specific inputs yield specific desired outputs.
|
||||
|
||||
2. A program is not complete without sufficient testing to prove it's complete.
|
||||
|
||||
3. Global state and global impure functions makes testing more difficult. This
|
||||
can include singletons and system calls.
|
||||
|
||||
Any of these may be argued, but that will be left for other posts. Any of these
|
||||
may be said of other types of programs as well, but that can also be left for
|
||||
other posts.
|
||||
retrospect, the pattern/framework proposed was over-engineered. This post
|
||||
attempts to present the same ideas in a more distilled form, as a simple
|
||||
programming pattern and without the unnecessary framework.
|
||||
|
||||
## Components
|
||||
|
||||
Properties of components include:
|
||||
Many languages, libraries, and patterns make use of a concept called
|
||||
"component", but in each case the meaning of "component" might be slightly
|
||||
different. Therefore to begin talking about components we must first describe
|
||||
specifically what is meant by "component" in this post.
|
||||
|
||||
1. *Creatable*: An instance of a component, given some defined set of
|
||||
parameters, can be created independently of any other instance of that or any
|
||||
other component.
|
||||
For the purposes of this post, properties of components include:
|
||||
|
||||
2. *Composable*: A component may be used as a parameter of another component's
|
||||
instantiation. This would make it a child component of the one being
|
||||
instantiated (i.e. the parent).
|
||||
1... **Abstract**: A component is an interface consisting of one or more
|
||||
methods. Being an interface, a component may have one or more implementations,
|
||||
but generally will have a primary implementation, which is used during a
|
||||
program's runtime, and secondary "mock" implementations, which are only used
|
||||
when testing other components.
|
||||
|
||||
3. *Abstract*: A component is an interface consisting of one or more methods.
|
||||
Being an interface, a component may have one or more implementations, but
|
||||
generally will have a primary implementation, which is used during a
|
||||
program's runtime, and secondary "mock" implementations, which are only used
|
||||
when testing other components.
|
||||
1a... A function might be considered a single-method
|
||||
component if the language supports first-class functions.
|
||||
|
||||
4. *Isolated*: A component may not use mutable global variables (i.e.
|
||||
singletons) or impure global functions (e.g. system calls). It may only use
|
||||
constants and variables/components given to it during instantiation.
|
||||
2... **Creatable**: An instance of a component, given some defined set of
|
||||
parameters, can be created independently of any other instance of that or any
|
||||
other component.
|
||||
|
||||
5. *Ephemeral*: A component may have a specific method used to clean up all
|
||||
resources that it's holding (e.g. network connections, file handles,
|
||||
language-specific lightweight threads, etc).
|
||||
3... **Composable**: A component may be used as a parameter of another
|
||||
component's instantiation. This would make it a child component of the one being
|
||||
instantiated (i.e. the parent).
|
||||
|
||||
5a. This cleanup method should _not_ clean up any child components given as
|
||||
instantiation parameters.
|
||||
4... **Isolated**: A component may not use mutable global variables (i.e.
|
||||
singletons) or impure global functions (e.g. system calls). It may only use
|
||||
constants and variables/components given to it during instantiation.
|
||||
|
||||
5b. This cleanup method should not return until the component's cleanup is
|
||||
complete.
|
||||
5... **Ephemeral**: A component may have a specific method used to clean
|
||||
up all resources that it's holding (e.g. network connections, file handles,
|
||||
language-specific lightweight threads, etc).
|
||||
|
||||
5a... This cleanup method should _not_ clean up any child
|
||||
components given as instantiation parameters.
|
||||
|
||||
5b... This cleanup method should not return until the
|
||||
component's cleanup is complete.
|
||||
|
||||
Components are composed together to create programs. This is done by passing
|
||||
components as parameters to other components during instantiation. The `main`
|
||||
@ -128,12 +113,12 @@ fast to run, (usually) easy to formulate, and yield consistent results.
|
||||
|
||||
This program could instead be written as being composed of three components:
|
||||
|
||||
* `stdin`, a construct given by the runtime which outputs a stream of bytes.
|
||||
* `stdin`: a construct given by the runtime which outputs a stream of bytes.
|
||||
|
||||
* `disk`, accepts a file name and file contents as input, writes the file
|
||||
* `disk`: accepts a file name and file contents as input, writes the file
|
||||
contents to a file of the given name, and potentially returns an error back.
|
||||
|
||||
* `hashFileWriter`, reads a stream of bytes off a `stdin`, collects the stream
|
||||
* `hashFileWriter`: reads a stream of bytes off a `stdin`, collects the stream
|
||||
into a string, hashes that string to generate a file name, and uses `disk` to
|
||||
create a corresponding file with the string as its contents. If `disk` returns
|
||||
an error then `hashFileWriter` returns that error.
|
||||
@ -201,14 +186,15 @@ gain. This is because we have not yet written tests.
|
||||
|
||||
## Testing
|
||||
|
||||
As has already been firmly established, testing is important.
|
||||
Testing is important. This post won't attempt to defend that statement, that's
|
||||
for another time. Let's just accept it as true for now.
|
||||
|
||||
In the second form of the program we can test the core-functionality of the
|
||||
`hashFileWriter` component without resorting to using the actual `stdin` and
|
||||
`disk` components. Instead we use mocks of those components. A mock component
|
||||
implements the same input/outputs that the "real" component does, but in a way
|
||||
which makes testing a particular component possible without reaching outside the
|
||||
process. These are unit tests.
|
||||
which makes it possible to write tests of another component which don't reach
|
||||
outside the process. These are unit tests.
|
||||
|
||||
Tests for the latest form of the program might look like this:
|
||||
|
||||
@ -277,9 +263,9 @@ func TestHashFileWriter(t *testing.T) {
|
||||
|
||||
Notice that these tests do not _completely_ cover the desired functionality of
|
||||
the program: if `disk` returns an error that error should be returned from
|
||||
`hashFileWriter`. Whether or not this must be tested as well, and indeed the
|
||||
pedantry level of tests overall, is a matter of taste. I believe these to be
|
||||
sufficient.
|
||||
`hashFileWriter`, but this functionality is not tested. Whether or not this must
|
||||
be tested as well, and indeed the pedantry level of tests overall, is a matter
|
||||
of taste. I believe these tests to be sufficient.
|
||||
|
||||
## Configuration
|
||||
|
||||
@ -299,7 +285,7 @@ on the command-line, rather than reading from stdin, and second, there should be
|
||||
a command-line parameter declaring which directory to write files into. The new
|
||||
implementation looks like:
|
||||
|
||||
```
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -376,12 +362,12 @@ meaning all unit tests remained valid.
|
||||
A program can be split into three stages: setup, runtime, and cleanup. Setup
|
||||
is the stage during which internal state is assembled in order to make runtime
|
||||
possible. Runtime is the stage during which a program's actual function is being
|
||||
performed. Cleanup is the stage during which runtime stop and internal state is
|
||||
performed. Cleanup is the stage during which runtime stops and internal state is
|
||||
disassembled.
|
||||
|
||||
A graceful (i.e. reliably correct) setup is quite natural to accomplish, but
|
||||
unfortunately a graceful cleanup is not a programmer's first concern, and
|
||||
frequently is not a concern at all. However, when building reliable and correct
|
||||
unfortunately a graceful cleanup is not a programmer's first concern (and
|
||||
frequently is not a concern at all). However, when building reliable and correct
|
||||
programs, a graceful cleanup is as important as a graceful setup and runtime. A
|
||||
program is still running while it is being cleaned up, and it's possibly even
|
||||
acting on the outside world still. Shouldn't it behave correctly during that
|
||||
@ -393,7 +379,17 @@ During setup a single-threaded process (usually `main`) will construct the
|
||||
"leaf" components (those which have no child components of their own) first,
|
||||
then the components which take those leaves as parameters, then the components
|
||||
which take _those_ as parameters, and so on, until all are constructed. The
|
||||
components end up assembled into a directed acyclic graph.
|
||||
components end up assembled into a directed acyclic graph (DAG).
|
||||
|
||||
In the previous examples our DAG looked like this:
|
||||
|
||||
```
|
||||
---> stdin
|
||||
/
|
||||
hashFileWriter
|
||||
\
|
||||
---> disk
|
||||
```
|
||||
|
||||
At this point the program will begin runtime.
|
||||
|
||||
@ -405,12 +401,13 @@ called until all of its parent components have been cleaned up.
|
||||
Inherent to the pattern is the fact that each component will certainly be
|
||||
cleaned up before any of its child components, since its child components must
|
||||
have been instantiated first and a component will not clean up child components
|
||||
given as parameters (as-per component property 5a).
|
||||
given as parameters (as-per component property 5a). Therefore the pattern avoids
|
||||
use-after-cleanup situations.
|
||||
|
||||
With go this pattern can be achieved easily using `defer`, but writing it out
|
||||
manually is not so hard, as in this toy example:
|
||||
|
||||
```
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -510,14 +507,14 @@ func main() {
|
||||
In lieu of a FAQ I will attempt to premeditate criticisms of the component
|
||||
oriented pattern laid out in this post:
|
||||
|
||||
*This seems like a lot of extra work.*
|
||||
**This seems like a lot of extra work.**
|
||||
|
||||
Building reliable programs is a lot of work, just as building reliable-anything
|
||||
is a lot of work. Many of us work in an industry which likes to balance
|
||||
reliability (sometimes referred to by the more specious "quality") with
|
||||
maleability and deliverability, which naturally leads to skepticism of any
|
||||
suggestions which require more time spent on reliability. This is not
|
||||
necessarily a bad thing, it's just how the industry functions.
|
||||
Building reliable programs is a lot of work, just as building a
|
||||
reliable-anything is a lot of work. Many of us work in an industry which likes
|
||||
to balance reliability (sometimes referred to by the more specious "quality")
|
||||
with maleability and deliverability, which naturally leads to skepticism of any
|
||||
suggestions requiring more time spent on reliability. This is not necessarily a
|
||||
bad thing, it's just how the industry functions.
|
||||
|
||||
All that said, a pattern need not be followed perfectly to be worthwhile, and
|
||||
the amount of extra work incurred by it can be decided based on practical
|
||||
@ -525,19 +522,19 @@ considerations. I merely maintain that when it comes time to revisit some
|
||||
existing code, either to fix or augment it, that the job will be notably easier
|
||||
if the code _mostly_ follows this pattern.
|
||||
|
||||
*My language makes this difficult.*
|
||||
**My language makes this difficult.**
|
||||
|
||||
I don't know of any language which makes this pattern particularly easy, so
|
||||
unfortunately we're all in the same boat to some extent (though I recognize that
|
||||
some languages, or their ecosystems, make it more difficult than others). It
|
||||
seems to me that this pattern shouldn't be unbearably difficult for anyone to
|
||||
implement in any language either, however, as the only language feature needed
|
||||
is abstract typing.
|
||||
I don't know of any language which makes this pattern particularly easier than
|
||||
others, so unfortunately we're all in the same boat to some extent (though I
|
||||
recognize that some languages, or their ecosystems, make it more difficult than
|
||||
others). It seems to me that this pattern shouldn't be unbearably difficult for
|
||||
anyone to implement in any language either, however, as the only language
|
||||
feature needed is abstract typing.
|
||||
|
||||
It would be nice to one day see a language which explicitly supported this
|
||||
pattern by baking the component properties in as compiler checked rules.
|
||||
|
||||
*This will result in over-abstraction.*
|
||||
**This will result in over-abstraction.**
|
||||
|
||||
Abstraction is a necessary tool in a programmer's toolkit, there is simply no
|
||||
way around it. The only questions are "how much?" and "where?".
|
||||
@ -548,7 +545,7 @@ between the different abstracted types once they've been established using other
|
||||
methods. Over-abstraction is the fault of the programmer, not the language or
|
||||
pattern or framework.
|
||||
|
||||
*The acronymn is CoP.*
|
||||
**The acronymn is CoP.**
|
||||
|
||||
Why do you think I've just been ackwardly using "this pattern" instead of the
|
||||
acronymn for the whole post? Better names are welcome.
|
||||
|
69
assets/friendly.css
Normal file
69
assets/friendly.css
Normal file
@ -0,0 +1,69 @@
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #f0f0f0; }
|
||||
.highlight .c { color: #60a0b0; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #40a070 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #40a070 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #40a070 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #40a070 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #40a070 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #40a070 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */
|
8
assets/skeleton.css
vendored
8
assets/skeleton.css
vendored
@ -307,12 +307,12 @@ li {
|
||||
/* Code
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
code {
|
||||
padding: .2rem .5rem;
|
||||
margin: 0 .2rem;
|
||||
/*padding: .2rem .5rem;*/
|
||||
/*margin: 0 .2rem;*/
|
||||
font-size: 90%;
|
||||
white-space: nowrap;
|
||||
background: #F1F1F1;
|
||||
border: 1px solid #E1E1E1;
|
||||
/*background: #F1F1F1;
|
||||
border: 1px solid #E1E1E1;*/
|
||||
border-radius: 4px; }
|
||||
pre > code {
|
||||
display: block;
|
||||
|
Loading…
Reference in New Issue
Block a user