若手のプログラマが軽めの技術情報と、技術系のポエムを書くブログです。

ブログをホームページと合併させました。

もともとドメインが余っていたこともあり、k4h4shi.comというホームページを新設してブログも移転しました。

以降は記事などもそちらに投稿していきます。

ホームページはhexoというブログフレームワークを使って作りました。

今後とも何卒よろしくお願いいたします。

追記: 記事の移行も完了しましたのでこのブログについては1ヶ月後に閉鎖しようと思います。 hatena blogさん、少しでも読んで頂いた皆さん、今までありがとうございました。

変わり続けるプログラミング言語と付き合うために

はじめに

西尾 泰和さんによって出版された、コーディングを支える技術を読んで考えたこと。

この本では、コーディングにおける数多の記法に対して、それ以前にあった問題とそれ以降に何が解決したのかを、歴史と具体例と共に纏めている。

以下は、あくまで本の内容に触発されて構成された持論です。

プログラミング言語と構文

プログラマの中で、構文とプログラミング言語は密接に結びついていることがある。

しかし、これはある意味ではとても危ういことでもある。

なぜなら、現存しているプログラミング言語は、制約の中で数多の記法の一部をある時点での言語仕様として採用しているに過ぎないから。

これからも同じだとは限らないし、最近の言語はドラスティックな変更が言語仕様に加えられることも多い。

確かに、特定のプログラミング言語の構文を通じて、プログラマはあらゆる問題の解決方法のサブセットを利用する。

けれど、それは決して全てではないし、同じ問題に対しての解決方法が1つとも限らない。

現存しているプログラミング言語が1つではない事も、それを表しているように思う。

そしておそらく、これからもそうなる事は無いだろうという事は経験から推測できる。

プログラミング言語はツール、それも進化する

例えるならば、プログラミング言語はそれぞれ目的を持ったツールであり、使い方も異なれば、壊れもするし廃れもする。

ただし、作られて消費されていくだけのツールではなく、改善されもすれば、進化していくツールでもある。

だからきっとプログラミング言語が変わり続けることだけは、これからも変わらない。

変わる知識と変わらない知識

では、プログラマに求められることは何か。

プログラマには、もちろんプログラミング言語を適切に使って、問題解決を行う事が求められる。

しかし、それが日々変わっていくとしたらどうなるだろう。

冗談ではなく、本当にそうなっている気さえしているのは自分だけではないと思う。

最近でもEcma Script 2017がリリースされ、Java 9のリリースも控えている。

やはり、より俯瞰的な視点を持ち問題解決に当たる事が求められる。

そのために何をすべきかということに答えることは、容易なことではない。

それこそ、答えは人によって異なる。

ただ一つの回答として、特定のプログラミング言語に縛られない知識を持つことはその助けになる。

そうすれば少なくとも、1つの言語と心中することにはならない。

第2言語を学んだことからの経験則

現在、第2言語としてJSを学習している。

それによって例えばスコープや、リテラル、関数と言ったものについての考え方は、大きく変わった。

JSで関数を書いていくことで、それと並行してJavaのStream APIに対する理解もより進んだ。

異なる言語を比較しつつ身につける事は、既存の知識を強化することにもつながる。

それに、最初のプログラミング言語を学ぶことに比べたら、はるかにマシだった。

コーディングを支える技術には、数多くの言語によるサンプルコードが掲載されている。

その種類はJava, JavaScript, Perl, Python, Ruby, アセンブリ言語まで幅広い。

ちょうど第2言語を学ぼうと思っている人へは、副読本としてもお勧めできる。

プログラミング言語を選択することについて

個人的には、プログラミング言語を選択することには慎重になるべきだけれど、選り好みするべきではないと考えている。

それよりも重要なことは、少なくとも1つの言語に精通することだと思う。

それによって、今後言語を選択する基準ができる。

また、案外求められていることは、基本的にどんな言語でも実装できるってことがだんだんわかってくる。

ただ、生産性に影響を与えることは確実なため、そういう意味で、慎重になるべきだはと思う。

言語の中でのプログラミングと、言語の中へのプログラミング

少しコンテキストが異なるけれど、プログラミング言語を選択することについては、スティーブマコネルも自著の中で触れている。

この場合は開発に利用すべき言語を選択することについてだが、重要なコンセプトが書かれている。

それは言語の中でのプログラミングと言語の中へのプログラミングを区別する事の重要性についてだ。

身近な言葉で言うなら、道具に使われるな、道具を使え。ということになる。

嬉しいことにプログラマは道具(プログラミング言語)を使って道具(関数やクラスやモジュール、フレームワークなど)を作れる。

関連する情報について

コードコンプリート第2版 上 の第4章の中で、プログラミング言語の選択についてと題された箇所がある。

これは、コーディングを支える技術で語られているコンセプトを、開発に置けるよりマクロな視点から語ったものであり、参照することをおすすめする。

最後に

長々と持論を書いたけれど、コーディングを支える技術は良い本だと思ったってのが動機だった。

出版されたのが2013年と少し古い本だけれど、その内容自体が廃れないものについてのために、古さを感じることはなかった。

ただ、もしこの本が今書かれていたとしたら、例えば関数型プログラミングについても、取り上げられていただろうなとかは思う。

しかしそれでも、プログラミングについて、言語に縛られない視点を持つことを助けてくれることに関しては、変わらない。

少しでも言語オタクじみたところがあったり、第2言語を学ぼうと思っている人へなら、ぜひオススメしたい本だった。

node-REDを弄ってみた。

仕事でnode-REDに触れる可能性があるので事前に調査を行い、実際に弄ってみました。

node-REDとは

node-REDは視覚的にnodeとedgeを描くことでハードウェアやデバイス、オンラインサービスを接続するためのツールです。

img

node-REDの特徴

ブラウザ上に構築されている

node-REDはブラウザで動作するFlowエディタを提供しており、視覚的にFlowを記述できます。

FlowはNode(プラグイン/モジュール)とEdge(Node間の接続)からなり、ワンクリックで実行環境にデプロイ可能です。

リッチテキストエディタJavascriptプログラミングが行えるNodeを利用してプログラムを作成することもできます。

作成したテンプレートやFlowはエディタに組み込まれたライブラリに保存し、再利用することもできます。

node.js上で構築されている

node.js上に構築されており、イベント駆動/ノンブロッキングモデルを活用できます。

そのためにRaspberry Piなどの低コストハードウェア、クラウド上で実行するにも理想的な環境が提供されています。

また、Node.jsのエコシステムに存在するモジュールを利用して、Node-REDを拡張できることも意味します。

Json形式のインポート/エクスポートによるFlowの共有

Node-REDで作成したFlowはJson形式でインポート/エクスポートすることで他の人と共有できます。

オンラインFlowライブラリにて、作成したFlowを公開、または利用することも可能です。

実際に弄ってみる

Node-REDのインストールと起動

Linux/OS Xで既にNode.jsをインストールしている場合はTerminalにて以下を実行します。

$ sudo npm install -g node-red
$ node-red

僕の場合は条件に合致しましたが、それ以外の場合は公式のGetting Startedを参照ください。

Node-REDへアクセス

デフォルトの場合はブラウザから以下のポートでアクセスできます。

http://localhost:1880/

アクセスするとブラウザでFlowエディタが立ち上がります。

Hello worldを表示してみる

新しい技術に触れた時はとりあえずHello worldだと思います。

ということでhttpで/helloworldエンドポイントへアクセスしたら、helloworldと表示するFlowを作ってみました。

最終的なFlowはこんな感じになります。

Flowの構成

Flowは、以下のNodeから構成されています。

  • HTTP Request Node
  • Template Node
  • HTTP Response Node

これらをつなげることで、「こんなリクエストがあった時、こんなメッセージを、こんな風に返す。」という一連の流れを記述できます。

今回の場合は、

  • /helloworldにGETされる
  • msgは'Hello World!'
  • msgをBodyに含むレスポンスを返す。

というようなFlowを作ります。

Flow作成の手順

HTTP Request Nodeを追加する

左側のペインから、任意のノードをドラックして中央のFlowペインへドロップすることでNodeが追加できます。 今回は、まずはエンドポイントを追加したいので、httpノードをFlowに追加します。

HTTP Requrest Nodeのパラメータを編集する

Flowペインへ追加したノードをダブルクリックすることで、Nodeにパラメータを設定するためのDrawerが表示されます。 今回は、以下の設定を行います。

  • Method: GET
  • URL: /helloworld
HTTP Response Nodeを追加する

Requestに対するResponseが必要なので、Nodeを追加します。 今回は特にResponseに設定は行わず、デフォルトのままにします。

Request Node と Response Nodeをつなげる

Request Nodeの右端とResponse Nodeの左端をつなげます。 これにより、これらのNodeを関連づけ、左から右へ流れるFlowにすることができます。

一旦デプロイしてみる

まだBodyを設定していませんが、正常に動くかデプロイしてみます。 デプロイの際は、画面右上のdepoloyボタンを押下します。 上からトーストが出たら成功です。

エンドポイントにアクセス

/helloworldエンドポイントにアクセスしてみます。 今回の場合ですとurlは以下になります。

http://localhost:1880/helloworld

空のレスポンスが帰ってきたら、ひとまずここまでは成功です。

Http Response Bodyを設定する

では、レスポンスにBodyを設定するにはどうしたらよいのでしょうか。 HTTP ResponseNodeは、左端に接続されているNodeのmsg.payloadの値をBodyとして返します。 ということで、Template Nodeを現在の2つのノードの間に追加して、msg.payloadに値を設定します。

差分デプロイを行う。

今回の変更では、すべてをデプロイし直す必要はないため、差分デプロイを行います。 そうすることで必要最低限だけ、デプロイし直してくれます。

再度エンドポイントへアクセスする

/helloworldエンドポイントへアクセスしてみると、無事にHello Wolrd!と表示されていることがわかります。

まとめ

このようにNode-REDでは、基本的に以下の流れで素早く開発ができます。

  • Nodeを追加
  • Nodeのパラメータの設定
  • 複数Nodeを関連付けてFlowを作成
  • デプロイを行う

素早いプロトタイピング

このような素早いプロトタイピングは、Node-REDを導入するメリットの一つだと思います。

主にIoT分野での活用を想定しているツールだそうですが、個人的にはプロトタイピングやプログラミング学習などにも利用できるのではないかと思っています。

関数型プログラミングとの共通点

関数型プログラミングの特性が現れているのも面白い部分の一つです。

ノードをつなげていくと、ちょうどフローチャートの様にも見えますが、ifやwhileと行った制御構文は登場しません。

これは、ノードを使って記述しているのは処理そのものではなく、あくまでメッセージの受け取りと、加工、そして結果の受け渡しだからです。

今後について

今後は、ひとまず一通りどんなノードがあるのかを調べつつ引き続き学習していきます。 各種ノードについてのまとめをしていきますので、よかったらご覧ください。

参考リンク

構造コード vs リアルコード

ZERO BUGSを購入して読んでみたところ、構造 vs リアルコードという章があり興味深かったので抜粋して少し考えてみる。

2種類のコード

この章の中で著者はコードを構造コードとリアルコードの二つに分類している。

自分が書いているコードがどちらに当たるのかを考えてみることで、本来の目的を見失わずに済むかもしれない。

構造コードとは

構造コードとは、ものをつなぎ合わせるためのコード。

処理を共通化を行うコードや、デザインパターンなどがそれにあたり、繰り返し出現する構造を抽出して柔軟性を高めたい場合などに記述される。

著者は1行の構造コードは2つの異なる場所で必要とされた場合にのみ描かれるべきだと言う。

リアルコードとは

リアルコードとは、実際に何かを行うコード。

ファイルを開いたり、画面に何かを描画したり、月までの距離を計算したりするのがリアルコード。

構造コードに対比させるならば、1行のリアルコードは目的の達成に必要とされた場合にのみ書かれるべきだと思う。

高品質のコードを目指すために

高品質なコードを目指すためには、構造コードを可能な限り減らすことが必要となる。

コードの良さを表す関数gの最適化問題

以下の式ではrはリアルコード、sは構造コード、fは必要とされる柔軟性、そしてtはタスクを完了させるために必要なコードを表す。

g(r, s) = r - s
  s >= f
  r == t

ここでの目的は、gを最大化させることである。

rに対しsが大きすぎるならば、それだけgも小さくなってしまう。

必要な柔軟性だけを担保し、タスクに対してコードを書いていくと良いことがわかる。

構造コードを書くべき時

著者は、後方互換性が必要な局面において3か所以上で参照されることがわかっている場合には、構造コードを書くべきだとしている。

これはKISSやYAGNIにも共通する考え方である。

後々のことを考えて、というのは構造コードを追加する理由にはならないということだ。

「初めて何かを行うときは、ただやるのみだ。2回目に何か似たようなことを行うとき重複に気付いてたじろぎ、それでも同ようにやるだろう。似たようなことを行うのが3回目なら、リファクタリングしよう。」

同じコードを3回書いた時、これらを共通化できないか、するならばどんな構造コードが必要かを問いかけるようにすると良いだろう。

まとめ

無意味な構造コードを書きがちな自分にとっては良い戒めであり、すっと理解できた。

設計や構造をあれこれするよりも、言語のAPIを上手く利用したり、品質の良いライブラリを活用することで、1行のリアルコードが為すタスクを最大にすることを考える必要がある。

著者は2種類に分けるのは教えるのに便利だからであり、どちらのカテゴリにも当てはまらないものがある。だから原理を一度理解したならば、その先へ進んで欲しいと言う。

しばらくは、この2つの分類でコードを考えてみようと思う。

参考文献

リファクタリングを読んで。

リファクタリングについて

リファクタリングとは、プログラムの機能を変えずに、設計と実装を改善することです。 その目的は主に、現存するプログラムのscalability(拡張性)やMaintainability(保守性)を高めることです。 しかし、それがなぜ重要なのかを説明することや、実践することは難しく、すでに定着していない場合は導入がし辛いように思います。 現に現場の実務プロセスでは、バグ改修以外の理由でのコードの改変が認められていないプロジェクトも存在します。 それでもなお、僕はリファクタリングが開発を行う上で有用な考え方だと思います。 それは少し学習しただけでも、以下のような幾つかの気づきがあったからです。

リファクタリングの学習を始めたことによる気づき

  • 良い設計の適用方法のガイドラインになる。
  • IDEなどのツールの活用方法の理解を助ける。
  • テストを書く習慣づけを身につけることができる。

これらはあくまで学習と技術力向上という観点で見たリファクタリングのメリットです。 実際の開発でどのように役に立つかは、まだ経験がないため、その他の方へ譲ります。 つまり、プログラミング上での作法がなぜ重要なのか、それに反するものにどう対処すれば良いのかは学べます。

作法とリファクタリングの関係

例えば変数の命名には以下のような作法があります。 変数名は名詞で、省略せず、短く簡潔に意図を伝えるようにすること。

これを守ることで、同じ変数に対する複数回の代入は行いづらくなります。 なぜなら意味に反する値を入れるわけにはいかないからです。(プログラム上は出来ますが、論外です) すると、結果的にはそれによって式の結果を保持する一時変数が増えます。

ここで例えば、問い合わせによる一時変数の置き換えというリファクタリング手法を適用します。 式の結果を変数に格納するのではなく、式の結果を返すメソッドを作成し、それを利用する。というものです。 このメリットは、メソッドとする事で、その他のプログラムから利用できるようになる事です。

すると、必然的にメソッドが増えていきます。 そうなれば、クラスの抽出というリファクタリング手法が使えるかもしれません。

このように考えると作法が、これらの単純な設計上の問題を導き出すことがわかります。 このようにして、プログラムを書いている中で生まれる設計上の問題に対して、どう対処すべきかをリファクタリングの手法は教えてくれます。

実際のプロジェクトへの適用

個々人による開発能力を向上させることは、多かれ少なかれ全体へ影響を与えます。 上にあげたようにして、個人が良い設計を行なっていく。というような場合にはリファクタリングには大きな価値があると思います。 しかし、実際のプロジェクトへ抜本的に導入することは難しいかもしれません。

なぜならば、個々人の能力と取り組みに左右されることが大きいように思うからです。 それにあくまで拡張性と保守性への改善の取り組みであって、機能追加のような見える成果は出づらいからです。 しかし、よく整理されたプログラムは開発の速度へ影響を与えます。 開発期間中に要件が変わる場合、その場で拡張性が求められることもありえます。

日頃から、プログラマ個々人がすべき時にすることとして、徐々に始めるしかないのかもしれません。

まとめ

マーティン・ファウラーリファクタリングを読んで、実際に幾つかのテクニックを試してみて気づいたことをまとめました。 個人的に一番興味深かったことは、変更を加える際、既存のコードを残したままに変更を加えていた事です。 そうする事で、終始テストはグリーンのまま、レッドになった際は手順のミスが発覚します。 以前は、自分はいきなり破壊的な変更を加えるような事もあったため、安全な手順を踏んだ変更を加えるための手順と原則がわかった事は重要でした。

プログラマに必要な能力とは

プログラマに必要な能力といえば何が思い浮かぶだろう。 それぞれがそれぞれに考えがあるように思うけれど、自分にとってはその時々によって答えが変わってくる質問だと思う。 今の自分ならデザインパターンリファクタリングの手法を用いて、設計上の問題を解決する能力を思い浮かべる。

ちょうどマーティン・ファウラーリファクタリングを読み始めたばかりだが、自分はつくづく影響を受けやすいのだと思う。

この質問は時々問い直して、自分の答えの推移を見れたら面白いかもしれない。

SNSとしてのGithub

まず始めに、僕はGithubが大好きです。 なぜならGithubはエンジニアの理想を体現していると言っても過言ではないからです。

何かを食べた、何かを観た、聴いた。どこどこへ行ったというような情報はSNSに溢れています。 面白画像や動画、アンケート、ちょっと食傷気味になるくらいにいろいろなコンテンツがあります。 SNS上では人が何を考え、何をしたかを共有しています。

僕はGithubでも同じことが起こっているように思います。

例えば好きなアカウントをフォローすることができますし、Starを投げて応援することもできます。 コミットログはタイムラインに成りえますし、コードは投稿されるコンテンツです。

常に重要なことに目を向けたい、何かに貢献したい、そういう人達にとっては、一番楽しいSNSたり得ると思います。