Commit a2b97d10 authored by Thomas Randolph's avatar Thomas Randolph
Browse files

Switch to Hexo

parent 83318643
Pipeline #5838304 passed with stages
in 1 minute and 55 seconds
_site
.sass-cache
.jekyll-metadata
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules
image: ruby:2.3
image: node:4.2.2
pages:
cache:
paths:
- node_modules/
script:
- gem install jekyll
- jekyll build -d public/
- npm install hexo-cli -g
- npm install
- hexo deploy
artifacts:
paths:
- public
......
.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
\ No newline at end of file
Copyright (C) 2017 Tom Randolph
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely need to edit after that.
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'jekyll serve'. If you change this file, please restart the server process.
# Site settings
# Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site
title: (Tom Randolph).log(
email: websites@thomasrandolph.info
description: > #
baseurl: "" # the subpath of your site, e.g. /blog
url: "http://log.rockerest.com" # the base hostname & protocol for your site
permalink: /post/:title.html
defaults:
-
scope:
path: ""
type: "posts"
values:
layout: post
author: "Tom Randolph"
author-link: http://gitlab.com/u/rockerest
author-gitlab: rockerest
author-twitter: rockerest
# Build settings
markdown: kramdown
subtitle:
description: words
author: Tom Randolph
language:
timezone:
# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: http://log.rockerest.com
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:
# Directory
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:
# Writing
new_post_name: :year-:month-:day-:title.md # File name of new posts
default_layout: post
titlecase: false # Transform title into titlecase
external_link: true # Open external links in new tab
filename_case: 0
render_drafts: false
post_asset_folder: false
relative_link: false
future: true
highlight:
enable: true
line_number: true
auto_detect: false
tab_replace:
# Category & Tag
default_category: uncategorized
category_map:
tag_map:
# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
date_format: YYYY-MM-DD
time_format: HH:mm:ss -ZZ
friendly_date: MMM DD, YYYY
# Pagination
## Set per_page to 0 to disable pagination
per_page: 10
pagination_dir: page
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: default
node_sass:
debug: false
outputStyle: nested
precision: 5
sourceComments: false
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type:
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
</head>
<header class="site-header">
<div class="wrapper">
<a class="site-title" href="{{ site.baseurl }}/">
<img src="http://www.gravatar.com/avatar/8361ba9354d54301d67cf2d0ded0f504" />
{{ site.title }}
</a>
<nav class="site-nav">
<div class="trigger">
{% for my_page in site.pages %}
{% if my_page.title %}
<a class="page-link" href="{{ my_page.url | prepend: site.baseurl }}">{{ my_page.title }}</a>
{% endif %}
{% endfor %}
</div>
</nav>
</div>
</header>
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
{% include header.html %}
<div class="page-content">
<div class="wrapper">
{{ content }}
</div>
</div>
{% include footer.html %}
</body>
</html>
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
<p class="post-meta">
<time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time>
{% if page.author %}
<a href="{{ page.author-link }}"><span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span></a>
{% if page.author-github %}
<a class="icon" href="https://github.com/{{ page.author-github }}"><span class="fa fa-github"></span></a>
{% endif %}
{% if page.author-gitlab %}
<a class="icon" href="https://gitlab.com/u/{{ page.author-gitlab }}"><span class="fa fa-gitlab"></span></a>
{% endif %}
{% if page.author-twitter %}
<a class="icon" href="https://twitter.com/{{ page.author-twitter }}"><span class="fa fa-twitter"></span></a>
{% endif %}
{% endif %}
</p>
</header>
<div class="post-content" itemprop="articleBody">
{{ content }}
</div>
</article>
/**
* Syntax highlighting styles
*/
.highlight {
background: #fff;
@extend %vertical-rhythm;
.highlighter-rouge & {
background: #eef;
}
.c { color: #998; font-style: italic } // Comment
.err { color: #a61717; background-color: #e3d2d2 } // Error
.k { font-weight: bold } // Keyword
.o { font-weight: bold } // Operator
.cm { color: #998; font-style: italic } // Comment.Multiline
.cp { color: #999; font-weight: bold } // Comment.Preproc
.c1 { color: #998; font-style: italic } // Comment.Single
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
.gd { color: #000; background-color: #fdd } // Generic.Deleted
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
.ge { font-style: italic } // Generic.Emph
.gr { color: #a00 } // Generic.Error
.gh { color: #999 } // Generic.Heading
.gi { color: #000; background-color: #dfd } // Generic.Inserted
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
.go { color: #888 } // Generic.Output
.gp { color: #555 } // Generic.Prompt
.gs { font-weight: bold } // Generic.Strong
.gu { color: #aaa } // Generic.Subheading
.gt { color: #a00 } // Generic.Traceback
.kc { font-weight: bold } // Keyword.Constant
.kd { font-weight: bold } // Keyword.Declaration
.kp { font-weight: bold } // Keyword.Pseudo
.kr { font-weight: bold } // Keyword.Reserved
.kt { color: #458; font-weight: bold } // Keyword.Type
.m { color: #099 } // Literal.Number
.s { color: #d14 } // Literal.String
.na { color: #008080 } // Name.Attribute
.nb { color: #0086B3 } // Name.Builtin
.nc { color: #458; font-weight: bold } // Name.Class
.no { color: #008080 } // Name.Constant
.ni { color: #800080 } // Name.Entity
.ne { color: #900; font-weight: bold } // Name.Exception
.nf { color: #900; font-weight: bold } // Name.Function
.nn { color: #555 } // Name.Namespace
.nt { color: #000080 } // Name.Tag
.nv { color: #008080 } // Name.Variable
.ow { font-weight: bold } // Operator.Word
.w { color: #bbb } // Text.Whitespace
.mf { color: #099 } // Literal.Number.Float
.mh { color: #099 } // Literal.Number.Hex
.mi { color: #099 } // Literal.Number.Integer
.mo { color: #099 } // Literal.Number.Oct
.sb { color: #d14 } // Literal.String.Backtick
.sc { color: #d14 } // Literal.String.Char
.sd { color: #d14 } // Literal.String.Doc
.s2 { color: #d14 } // Literal.String.Double
.se { color: #d14 } // Literal.String.Escape
.sh { color: #d14 } // Literal.String.Heredoc
.si { color: #d14 } // Literal.String.Interpol
.sx { color: #d14 } // Literal.String.Other
.sr { color: #009926 } // Literal.String.Regex
.s1 { color: #d14 } // Literal.String.Single
.ss { color: #990073 } // Literal.String.Symbol
.bp { color: #999 } // Name.Builtin.Pseudo
.vc { color: #008080 } // Name.Variable.Class
.vg { color: #008080 } // Name.Variable.Global
.vi { color: #008080 } // Name.Variable.Instance
.il { color: #099 } // Literal.Number.Integer.Long
}
This diff is collapsed.
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ site.title | xml_escape }}</title>
<description>{{ site.description | xml_escape }}</description>
<link>{{ site.url }}{{ site.baseurl }}/</link>
<atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<generator>Jekyll v{{ jekyll.version }}</generator>
{% for post in site.posts limit:10 %}
<item>
<title>{{ post.title | xml_escape }}</title>
<description>{{ post.content | xml_escape }}</description>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
<guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
{% for tag in post.tags %}
<category>{{ tag | xml_escape }}</category>
{% endfor %}
{% for cat in post.categories %}
<category>{{ cat | xml_escape }}</category>
{% endfor %}
</item>
{% endfor %}
</channel>
</rss>
---
layout: default
---
<div class="home">
<ul class="post-list">
{% for post in site.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<span class="post-meta">
<span class="fa fa-fw fa-calendar-o"></span>
{{ post.date | date: "%b %-d, %Y" }}
</span>
<span class="post-meta">
<span class="fa fa-fw fa-user"></span>
{{ post.author | default: "Anonymous" }}
</span>
</li>
{% endfor %}
</ul>
<p class="rss-subscribe">subscribe <a href="{{ "/feed.xml" | prepend: site.baseurl }}">via RSS</a></p>
</div>
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"hexo": {
"version": "3.2.2"
},
"dependencies": {
"hexo": "^3.2.0",
"hexo-generator-archive": "^0.1.4",
"hexo-generator-category": "^0.1.3",
"hexo-generator-index": "^0.2.0",
"hexo-generator-tag": "^0.2.0",
"hexo-renderer-ejs": "^0.2.0",
"hexo-renderer-marked": "^0.2.10",
"hexo-renderer-scss": "^1.0.2",
"hexo-renderer-stylus": "^0.3.1",
"hexo-server": "^0.2.0"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Convention Syndrome, or: How To Be Mediocre</title>
<meta name="description" content="words">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/monokai-sublime.min.css">
<link rel="stylesheet" href="/css/screen.css">
<link rel="canonical" href="/2015/01/24/convention-syndrome-or-how-to-be-mediocre/">
<!-- RSS feed here -->
</head>
<body>
<header class="site-header">
<div class="wrapper">
<a class="site-title" href="/">
<img src="https://www.gravatar.com/avatar/8361ba9354d54301d67cf2d0ded0f504" />
(Tom Randolph).log(
</a>
</div>
</header>
<div class="page-content">
<div class="wrapper">
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">Convention Syndrome, or: How To Be Mediocre</h1>
<p class="post-meta">
<time datetime="Sat Jan 24 2015 19:30:00 GMT-0700" itemprop="datePublished">Jan 24, 2015</time>
<a href="http://log.rockerest.com/">
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Tom Randolph</span>
</span>
</a>
<a class="icon" href="https://gitlab.com/rockerest">
<span class="fa fa-gitlab"></span>
</a>
<a class="icon" href="https://twitter.com/rockerest">
<span class="fa fa-twitter"></span>
</a>
</p>
</header>
<div class="post-content" itemprop="articleBody">
<section>
<h3>Convention Syndrome</h3>
<!-- <figure class="fr" style="width: 50%;" >
<img src="/build/img/code-convention.png" />
<figcaption>
Just a little taste of convention.
</figcaption>
</figure> -->
<p>
Not too long ago, I interviewed a potential candidate for a front end developer position.
As part of the interview, I asked the interviewee if they had ever used OAuth2 in coordination
with their JavaScript application. They had, and I asked them to show it to me.
</p>
<p>
The candidate explained to me how they had used <a href="http://yeoman.io/" target="_blank" rel="external">Yeoman</a> to install
the <a href="https://github.com/meanjs/generator-meanjs" target="_blank" rel="external">mean.js generator</a>. Then the interviewee
showed me some code not really related to OAuth. As I watched them, I pointed out some places the OAuth
handling might be done, but we dropped it before we found anything.
</p>
<p>
The last thing the candidate said regarding OAuth was <em>&quot;I used Yeoman to generate the MEAN
application and one of the options was to set up authentication, so I said yes and it just set
it up for me. I know it uses <a href="http://passportjs.org/" target="_blank" rel="external">Passport</a>.&quot;</em>
</p>
<p>
Unfortunately, Passport has very little to do with your application
<a href="http://oauth.net/articles/authentication/" target="_blank" rel="external">performing an authentication handshake</a> with
an authentication service &mdash; except that Passport <strong>is</strong> the authentication service. The
front end must handle access tokens, OAuth claims, and more.
</p>
<p>
Later, I asked the same candidate to
<a href="http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/" target="_blank" rel="external">write
the FizzBuzz program</a>. Besides taking way too long, the interviewee couldn't remember the syntax
for a <span class="fw">for</span> loop, and resorted to writing a function that simulated a
<span class="fw">for</span> loop using a <span class="fw">while</span> loop. They explained this
oversight was because they typically used library iterators like
<a href="http://underscorejs.org/#each" target="_blank" rel="external">Underscore's <span class="fw">.each</span></a>.
</p>
<p>
<a href="http://blog.codinghorror.com/why-cant-programmers-program/" target="_blank" rel="external">Why can't programmers... program?</a>
The one thing that sticks out &mdash; and is reaffirmed over and over &mdash; is that an affliction is spreading (has spread?)
among some developers. I've called it <em>Convention Syndrome</em>, but it could easily be
called <em>Generator Syndrome</em>.
</p>
</section>
<section>
<h3>What's Going On?</h3>
<p>
More and more, the tools that we use are billed as <em>&quot;the last [X] you'll ever need.&quot;</em> Having
things done for you is more desirable than knowing how it works. <em>&quot;Spin up a prototype in 15
minutes,&quot;</em> or any variation of the amount of time, is so common that it makes me cringe just
hearing it. The problem I have seen over and over is that &mdash; despite being able to present a prototype
in a short amount of time &mdash; the developer is rarely able to create a truly innovative end result.
A convention can only hold your hand so far, and a generator will never meet exactly your business' needs.
</p>
<blockquote>
If I choose a tool to do each job, I have to know how they all hook together.
</blockquote>
<p>
I have used <a href="http://www.sublimetext.com/" target="_blank" rel="external">Sublime Text</a> for a long time, and recently switched to
<a href="https://atom.io/" target="_blank" rel="external">Atom</a>. One of the many things these editors have in common is that they are simple.
In fact, I'm writing this post in Atom right now. The beauty of a tool that does a basic task like <em>edit text</em>
and really nothing more has many facets, but here are two:
<ul>
<li>
It can do it well.
</li>
<li>
It forces me to understand the interactions.
</li>
</ul>
</p>
<p>
I generally choose a tool for each job, and each tool runs independently of the others. If I choose a tool to do
each job, I have to know how they all hook together. That is a positive thing.
</p>
<p>
The important distinction here is that &quot;job&quot; is absolutely not &quot;get a web app working.&quot; A task
is something much more concrete, like &quot;manage routing, hashchange, and URL history on the client side.&quot;
By the way, that's a task I'd earmark for <a href="http://sammyjs.org/" target="_blank" rel="external">Sammy.js</a> to handle, but I'll talk
about that another time.
</p>
<p>
Let's go back to my interviewee from before. As we looked through OAuth2 code, I saw something familiar:
</p>
<pre><code class="js">'Authorization': 'Bearer ' + Cookie( "access" )</code></pre>
<p>
This is the code to add the Authorization header to a request, and provide your stored OAuth Bearer Token to the
API. Sure that we had just stumbled upon the OAuth handler code implementation, I asked the candidate
<em>&quot;where in your application is that access cookie set?&quot;</em> This is an application that this person
<strong>built</strong>, and their answer was, <em>&quot;...Uh, I'm not really sure.&quot;</em>
</p>
<p>
Reliance on generators and convention to &quot;make our jobs easier&quot; is doing nothing but creating a breed
of developer who's no better than the documentation of their tool <em>du jour</em>. The ability to think
&quot;outside-the-box&quot; apparently only applies if the newest tool on the block has a bigger box than
the tool that was being used previously. Knowledge of application architecture and understanding how systems work
seem to be scoped to only the tool. As soon as the tool disappears, stops being maintained, stops meeting needs,
or &mdash; frankly &mdash; stops being &quot;cool&quot; (whatever that means), so too does that knowledge
disappear, never applied again.
</p>
<p>
This is why I'm calling this <em>Convention <a href="http://en.wikipedia.org/wiki/Syndrome" target="_blank" rel="external">Syndrome</a></em>: not
because conventions are the problem, but because it seems that the trend has been to forgo <em>understanding</em>
for the sake of <em>convention</em>. These symptoms may all stem from a central issue, perhaps a level of laziness,
perhaps a desire to produce instead of understand. Whatever the reason, I'm diagnosing the syndrome, not the condition.
The real issue is that the <em>Convention Syndrome</em> is creating a plethora of developers who appear to be wildly
unskilled if you move them just inches outside their comfort zone.
</p>
</section>
<section>
<h3>The Web, A La Carte</h3>
<p>
One of the problems I haven't even touched on regarding this topic is future-proofing applications. The reason I
haven't touched on it is because I can rant at length about it, but more importantly: because it's not central to
the symptoms of the syndrome.
</p>
<p>
That said, however, it would behoove me to mention one piece of maintainability to help explain why <em>a la
carte</em> is so powerful. Let's assume you've chosen a monolith to build your app. Let's call it <em>Angelic</em>.
It does everything for you except butter your bread. It comes with some tradeoffs, like you hard code the names
of your models directly into the presentation template, and you do the same thing with code to respond to events
like clicks &mdash; they're written right into the HTML. You know this isn't great, but it's the