ziguzagu.org

今年のいつだったか忘れたけど「Common Lispやろう」と思い立って、すこーしずつやってきた。まだ入門の初期段階だけど得られたことについてまとめて、トレタ Advent Calendar 2019の1日目の記事とする。残念ながらまた遅れた…。そして仕事ではCommon Lispは無縁だし一切関係はない。

入門にあたって

新しく言語を学ぶときはだいたい書籍を一冊選んで写経することから入るのだけど、Common Lisp については最高の書籍があった。

Land of Lisp

たんに Common Lisp の入門本というだけでなく、(Common Lisp の性質もあってか)これまでのプログラミング人生で読んだ本のうち間違いないく記憶に残る名著で、きっと今後も何度か読んでいくような気がする。とにかくすばらしい本。

強力な「リスト」の概念

Emacsを通してなんとなく理解はしてたリストだったけど、ちゃんとCommon Lispに入門して得られたリストの概念はそれこそ強力だった。

値と次のセルのポインタ。リストはこの2つの要素をもつコンスセルがつなぎ合わさったもの。

つまり自分もよく知っていた単純な連結リストですべてのシンタックスが表現されていて、それを操作する原始的な関数群が用意されてる(car、cdr、caddr、cddar…)だけといえばだけなんだけど、データ構造が全部これで説明も実装もできるというのは、自分が経験した言語では一切考えもしないことだった。

コードもデータも同じシンタックスで表せる、という概念

これも結局はリストの話といえば話だけど「コードとデータがまったく同じシンタックスである」というのは最初は????だった。が、よくよくみて理解できたときには、これもまた自分が過去に経験した言語では一切考えたこともない表現、概念で、改めてLispが今まで経験したどの言語とも似ていないものたらしめている要因だった。

人間が読みやすいかどうかはちょっといまだ謎いけど、この概念は強力すぎてどう説明したらよいのかちょっとわからない…。

マルチパラダイムの意味

手続き型、オブジェクト指向、関数型、ジェネリックなどなど「マルチパラダイムな言語」というのはいっぱいある。Common Lispもマルチパラダイム。なんだけど「すべてのパラダイムにおいて同じシンタックスが使われる」というのはどの言語にもない特徴。他の言語にあるパラダイムに応じて書き方を変える・選択するというのがないのは、それすらも含めてマルチパラダイムであるという意味でLispの最大の特徴。

なんだか「リストすごい」みたいな話しかしてないような気もするけど、いや、すごくすごいのでしょうがない。

高水準言語の機能の原理

Common Lisp を学んでて「(高水準)プログラミング言語の原子みたいな感じ」というイメージを何度も抱いた。リスト、シンタックス、対称性のある関数、lambda、など「Lispですべてのプログラミング言語表せるのでは?」と何度も思ったし、自分の手に馴染んでる言語にある機能、シンタックスも結果としてすべてがLispにある概念に帰結する感じがされた。

Emacsが楽しい

Emacsを15年以上使ってるけど、なんとなくでリストというもの理解して、他のEmacs Lispを見様見真似で最低限の言語や機能を理解した上で設定書くくらいの感じでしかなかった。それがCommon Lispに入門してからはEmacs Lispをどんどん読み書きできるようになって、Emacsがまた楽しくなってきた。

IDEは便利だし生産性を向上させるすばらしいもので自分も使いこなせたらとは思うのだけど、毎度トライするたびに結果的にEmacsに戻ってきてしまったのは、つまるところこういう「自分の馴染む道具を作っていく楽しさ」を無限に見いだせてしまうところというのを改めて実感した。

プログラミング、やっぱり楽しい

決して読みやすいとも思えないし、イマイチ理解に苦しむ関数名とかそういのもいっぱいあるし、なにか長くなると未だに頭が追いつかないときもあるけど、この「(高水準)プログラミング言語のための原子」とも思える概念の塊であるこの言語は、いろいろな点で自分の視野を広げつつ、今までのプログラミング体験の点と点をつなぐ感じが大変気持ち良い。

結果としてプログラミングという行為そのものがより楽しくなる。

つまりはそういうことだ。

Netlifyを使い始めて1ヶ月がたったので使用感のメモ。

ブログをEmacs org-mode + Hugo + Netlifyに移行した

移行後から今日までに追加でやったことといえば以下あたり。

  • 記事2つ投稿
  • Analyticsを有効化
  • 404エラーになってるURLの救済(リダイレクトor空ファイル作成)
  • HTMLの微調整いろいろ

GitHubでホストしてるのでpushした回数 = デプロイ回数なのだけど、40回くらいデプロイしたっぽい。

Good: 管理画面がシンプルで使いやすい

一度設定が終われば見るべきところはほとんどないのだけど、初期のサイト作成から必要な設定(ドメイン、証明書あたり)を終わらせるまで迷うことなくすっと終わる。これは本当に楽ちん。iPhoneで見てもレスポンシブル対応しててすべての機能が使えるところも大変良い。

Good: デプロイが速い

Hugoが速いというのはあるにせよ、デプロイの処理はだいたいが20秒未満で完了してる。たまにキューがたまっているのかGitHubへのpushから数十秒待つこともあったけど、じっと見てなきゃわかんない程度。単にビルドするだけでなく、生成されたHTMLがセキュアでないコンテンツ(HTTPなURLの埋め込み)でないかどうかの検出もやってくれて警告だしたりするのも追加でやってるのも加えると十分どころ大変速い(MovableTypeを偲ぶ…)。

Good: いろいろできるRedirect, Rewrite, CustomHeader

古いブログやサイトを移行するのにいろいろURLが変わってしまうのはまぁ仕方のないこと。それをカバーすべくURL Redirect, Rewriteの機能があるのだけ必要な機能が十分そろってる。ワイルドカードやドメインも含めたRedirectできるのでおそらく困ることはない。くわえてCustomHeaderを追加するというのもできるので、静的サイトといえど必要なセキュリティ系のヘッダなんかも適宜いれることができる。これもデプロイのプロセスに組み込まれていて即時反映される。エライ。

Good: Hugo + Gitによる安心感

Netlifyと直接関係あるものないものあるけど、

  • Hugoですべてのページがローカルで確認できること
  • テンプレート、コンテンツ含めGitで管理すること
  • Netlifyの画面から特定のDeployを再度publish(ある意味Rollback)できること

これらによる安心感と追跡性はSaaSやインストール型ソフトウェアによるCMSではなかなかない。

前職でMovableType.netの開発時に「MTテンプレートをGitでバージョン管理することこそ未来!」とGitHub連携を提案・実装したがまぁそれより遥かにできが良い。コンテンツごと管理しちゃってるんだもの。

Good: ここまで無料

Hugoなりの静的サイトジェネレーターでサイトを生成・ホストするだけであれば(トラフィック課金は別にして)無料。個人的にはフリーミアムモデルでここまでできてしまうのはサービスの継続性の観点を考えると関心しないのだけど、個人利用に関しては嬉しい人が多いであろう。

Normal: レスポンスタイムはまぁまぁ

この簡素な構造のブログのトップページ(圧縮時2.7KB)で、CDNのキャッシュ無しの状態だと300msくらい、キャッシュありだとその半分の150msくらい。これを速いと見るか遅いと見るかはその人の背景にもよるかもしれない。思ったよりRTTが長いようで(安定して70ms~100msくらい)個人的にはここもうちょっと速いの期待してた。

Bad: Analytics add-onはしょぼい

有料機能としてAnalytics add-onを有効化して1ヶ月見ていたが、CDNのアクセスログを元に統計出すにしてもちょっとしょぼい。本当にサイトにかかれている6つの数値&チャートしかない。転送量での課金・リミットがあるにせよ、今どきBotのようなものもPageViewにカウントされる(と思われる)のはいまいちだし、DUVがIPアドレスベースってのも実を伴っていない。404エラーTOP10くらいしか有益なものはない。せめてUser-Agentの統計くらいだしてほしい感じ。とはいえJavaScriptなし、Cookieなしではまぁできることの限界もある。ただ、これだけに$9/monthはちょっと高いなぁという気がする。一方でベースのホスティング費用が無料なので、その分も払ってると考えるとまぁありか、ぐらいのお布施感。

まとめると

いくつか書いたけど、まぁ大変良い。

GitHub Actions / Pages という強敵も出てきたけど、DNS・証明書周りの管理や、Identify や Form といった add-on の存在を考えると、ペライチ以上のコーポレートサイトや製品サイト、マニュアルやドキュメントサイトなどはNetlifyでいけそうな気がする。あと2FAがあればセキュリティ的にも満点でなかろうか。

ブログ以外になんかサイト作る機会ができたら(たぶんないけど)まず第1の選択肢として入れておきたい。

Emacsで今開いているファイル&カーソル行をtig (on tmux)で開く設定をいれて往来できるようにしたらとても快適になった。

(defun my:tig-current-file ()
  (interactive)
  (shell-command
   (format "tmux new-window 'cd %s && tig blame +%s %s'"
           (file-name-directory buffer-file-name)
           (line-number-at-pos)
           (file-name-nondirectory buffer-file-name))))
(define-key vc-prefix-map [(t)] 'my:tig-current-file)

magitいれて全部Emacsで完結より、vc-mode + tig適宜使うのほうが省コストで汎用性も高いと思うので引き続きこの感じで。

ブログを自分も開発にメインで関わっていたMovableType.netから、Emacs org-mode + ox-hugo + Hugo + Netlify という形に移行した。

古いブログの記事も全部MT形式で書き出して、スクリプト書いてorg-modeフォーマットに変換したのだけど、text_hatena形式で書いていた記事とかなんかいろいろあって、スクリプトが想定より壮大になってしまった。Markdownで書かれた記事も書き方いろいろでやたらHTML混ざってるものとかあったりで、まぁいろいろ一苦労だった。

とはいえ移行してみると最高。

  • すべての記事が手元にプレーンテキストとして存在している
  • org-captureですぐに下書き始めれる
    • ウェブの管理画面にいって書き始める最初の「どっこらしょ」がない

この2点による体験が素晴らしい。

これでもう少しカジュアルにブログ書いていけるかな?

昨日職場でちらっと話していた、個人的に気をつけているというか回避しようとしてることに、SQLアンチパターンにのってそうな名前をつけてみた(文体もそれっぽくかいてみる)。

SQLに限った話でもなく純粋にクラス設計のアンチパターンともいえると思う。

目的:デフォルトで否定したい

デフォルトの挙動が否定側のような意味や、否定となるレコード数が支配的になることがわかっている場合そのままの意図をテーブル名やカラム名に持ち込みたくなる気持ちも理解できます。

アンチパターン:否定的な単語をつけtrueをデフォルト値としてしまう

create table awesome_functions (
  disabled bool not null default true
);

スキーマだけ見ると「ふむ」と一瞬納得しかけるが、コード上では結構えぐいことになっている or なっていくはず。

if !awesome_function.disabled?
  # 一部の人はイケてる機能を実行
end

あるいは以下。

unless awesome_function.disabled?
  # 一部の人はイケてる機能を実行
end

否定の否定は、何をしたいのかそれはどのような条件なのか書いた本人がその瞬間しかわかりません。もしくは本人もよくわかっていない可能性が高く、自分で嘘をついたのかどうかすら判別不能のはずです。

アンチパターンの見つけ方

否定形の接頭詞(dis-、non-、not-、un-、im- など)が現れた場合はすでに危険が及んでいます。 否定的な単語(failed、negative など)が現れた場合、ひょっとしたら何かを間違っている可能性があります

アンチパターンを用いても良い場合

それがユビキタス言語でありドメインを理解している関係者にとって自然な場合には用いても良いかもしれません。 (が、自分の経験上は思いつきませんでした…)

解決策:ポジティブに

カラム名の場合

ほとんどの場合ポジティブな単語に入れ替え値を反転させるだけで意図や条件はより伝わりやすくなります。

if awesome_function.enabled?
  # 一部の人はイケてる機能を実行
end

すでに存在してしまっているものについては反転した値を返す肯定形で別メソッドを使いそちらを標準的に使うことでコード上での問題はある程度回避できます。

def enabled=(val)
  disabled = !val
end

def enabled?
  !disabled?
end

テーブル名の場合

ORM の機能をつかってテーブル名に否定形単語がはいったまま肯定形単語のクラスとすることもできるかもしれませんし、チャンスがあればテーブル名を変えることも検討できるとよいですが、おそらくはそのタイミングでクラス名や場合によってはそのオブジェクトを保持している変数名まで変更せねばならず、影響範囲がかなり大きなリファクタリングを行うことになってしまいます。しかもロールバックがしんどい。

この場合は、過渡期を経て新しい肯定形の名を関したテーブルに移行する計画を立てましょう。それに価値が見合うのであれば…。

まとめ

うそ発見器にかけられたときのようにすべてを「No」で答える必要はありませんし、「No」が正解となる答える前提で質問を考える必要はありません。

前向きに人生をおくりましょう。