どこにでもいるSEの備忘録

たぶん動くと思うからリリースしようぜ

【読んでみた】プログラマが知るべき97のこと

この前twadaさんの講演を聞いていました。

nogawanogawa.hatenablog.com

そのときに出てきた本を、読んでみたのでそのメモです。

プログラマが知るべき97のこと

プログラマが知るべき97のこと

ちなみにwebでも公開されているので、無料で読みたい方はこちらをご参照下さい。

https://プログラマが知るべき97のこと.com

本文も無料で読見返せることですし、目次に沿ってざっくり思ったことをまとめたいと思います。

バグとその修正

プログラミングをしていくうえで、バグは避けられません。 バグが発生したら、まずは自分を疑いましょう。あらゆる可能性を潰し、それでも原因が見当たらなくて初めて使用しているソフトウェアを疑いましょう。

表面上に見える不具合はひとつであっても、その原因が一つとは限りません。 原因が複数の場合が存在するということを頭においておく必要があります。

コードを修正する際には、必ずコードを書いて事象を再現します。 バグを修正したら、該当箇所だけでなくコード全体に対してテストを行い、修正が他の箇所に影響を与えていないことを確認します。

f:id:nogawanogawa:20181205155900j:plain:w400
バグ修正のあるべきプロセス

ビルドとデプロイメント

ビルドやデプロイは、プロダクトの価値に直接的に影響を与えていないかもしれません。 しかし、動くプロダクトを最も重視するアジャイル開発では、ビルドやデプロイの効率化によって”いつでもクライアントに提示できる状態"を維持し続けることが求められます。 ソフトウェアは、開発する側も使用する側も、最初が肝心です。健全な状態で健全なソフトウェアをリリースし続けることが求められています。

ソースコードは非常に質の高いものをかけるエンジニアが、ビルドスクリプトに対しては知らんぷり、という状況は好ましくありません。 ビルドについてきちんと理解して開発を行うことで、開発サイクルにかかる労力を削減し、コストの削減も可能なのです。

デプロイについて入念に準備することは、「開発者のPC上で動作する」状態から「顧客の前でデモができる」状態にステップアップするだけでなく、アジャイル開発における生産性を向上させる要因になります。

昨今では仮想化技術も進歩しましたし、いつでもどこでもサービスをリリースできるような健全な状態を保つことが求められます。

f:id:nogawanogawa:20181205161730j:plain:w400
CI/CD技術を使っていつでもリリースできるようにすることが大事

コーディングガイドラインとコードレイアウト

コーディング規約は、可能な限り自動的かつ強制的に守られるようにするべきでしょう。 コードの整形処理、アンチパターンの検知など、可能な限りすべてです。 健全なコードは、レイアウトや命名規則が順守され、一貫性が取れているので、初見で読んだ人でも内容をすぐに理解できるものです。

コメントは多すぎても少なすぎても理解の妨げになります。 コメントにはコードで表現できないことを書きます。 ドキュメント生成のためのコメントを除けば、書いてあるコードが主でそれを補助するのがコメントだということを頭に置く必要があります。

コーディング規約がバラバラだと、コードは私物化します。 趣味でやる範囲なら許されるかもしれませんが、仕事でやる範囲は少なからず誰かに迷惑をかけます。 レイアウトやコメント等を含め、可能な限り全員が理解しやすいコードを生産するように心がける必要があります。

f:id:nogawanogawa:20181205162909j:plain:w300

設計原則とコーディングテクニック

あらゆるソフトウェアには、必ずそれを使用するユーザがいます。 そして、ユーザは特定の条件下でそのソフトウェアを使用します。 プログラマは、このようなユーザやそれを取り巻くドメインに向き合うことこそ、設計の第一歩です。 ユーザやドメインに向き合うかどうかは、ドメイン固有の型を使用したり、意図しない操作をできなくしたり、設計した通りの操作をユーザに誘導するレイアウトになったりすることで、インターフェースは改良されていくのです。

また、昨今ではどんどん便利なツールが世の中に登場し、それと同時にそれらを組み合わせて更にコードなプロダクトを世に送り出すことが求められています。 この状況によって、エンジニアの能力以上のプロダクトを短期間でリリースする事が必要になり、品質の低下に陥りやすくなっています。 この状況を打開する方法はたった一つで、自動テストでしょう。 これによって、品質の維持を自動化し、エンジニアはリリースのペースに食らいつくことしかできません。

想像しているユーザーは本当に正しいでしょうか? もしかしたら隣にいる同僚もユーザーの1人になるかもしれません。 また、個人で開発しているわけではなく、誰かに

「文章にしろ、和音にしろ、リズムにしろ、美しく、優雅なもの優れたものはすべて、シンプルである」

あらゆるコードはシンプルであるべきです。 シンプルな関数の組み合わせによって、世の中に価値を生み出す複雑なプロダクトが構成されるべきなのです。

美は、シンプルなものから生じ、シンプルなものに宿るのです。

最後に、プロジェクトを行う際のテクニックとして、プロダクトに名前をつけましょう。 エンジニアが、プロダクトに命を吹き込むというと大げさですが、こだわりを持つ大きなきっかけになります。 あらゆる不具合の根本的原因になりうる"妥協"を抑制する効果があります。 ユーザにプロダクトのイメージを膨らませてもらうメリットもあります。 ぜひ、名前をつけましょう。

ドメインの考慮

コードがどのような概念を表現しているかは、ひと目で分かるようにするべきです。 それは他のプログラマが必要な概念を理解する手間がなくなりますし、何より未来の自分の理解の手助けになります。

人間の頭の中の概念を、コンピュータ上で再現することがプログラミングであるということを考えれば、実際にそのそのソフトウェアを利用する人の概念に従ってプログラムも記述されるべきです。 そのために、エンジニアは人間を相手にして対話を繰り返し、ドメインに対する理解を深める必要があるです。

エラー、例外とその処理

技術的例外とビジネス的例外は明確に区別しましょう。 問題が生じているということが同じであっても、問題が生じているレイヤが全く異なります。 そして、その対象の方法も全く異なるためです。

ビジネス的例外には、プログラムをできてほしいことだけできるようにすることが望ましいです。 その上で、ユーザーが使いやすいようにインターフェースを設計します。 決められた入力以外すべて排除することはエンジニアにとっては簡単でも、ユーザにとっては使いやすくはありません。 使いやすく、かつ、できるはずのことだけできる状況が健全です。

エラーに対する対応は先送りしないようにしましょう。 そして、異常終了するコードを無理やり生かして置かないようにしましょう。 自分で書いたコードに対して、向き合ってその場で対処しないといけません。

技術、知識の習得

技術はすごい速さで変化していきます。学ばなければ置いていかれるのは確実です。

モチベーションはこうですよね。

入念に計画された訓練では得意なことに取り組むのではない。自分で鍛え、少なくともまだ得意ではないことに取り組むのである。楽しいとは限らない。

楽しいだけとは限らないですね。むしろ辛いことのほうが多い気がします。  

言語にはその言語独自の文化というものがあり、真にその言語を知るには、その文化も正しく学ぶ必要があるのです。

言語の特性にあった書き方をすると、非常に効率がいいです。プログラミング言語もやはり"言語"なのだと感じます。

プロはただ、がむしゃらに働けばいいというものではありません。プロの仕事には、入念な準備と効率化のための努力,そして日々の反省と絶え間ない変化が必要なのです。

我武者羅にやるのではなく、最大効率で頑張るのがプロですね。

要するに、

"手を動かせ。毎日、少しずつ、新しいことに取り組め。"

ってことなんでしょうね。

夜と魔法

エンジニアが寝ている間も、担当するシステムは動き続けることはよくあります。 作成したソフトウェアは、ユーザの保守担当に預けたり、開発チームが当分お守りをしたりと、状況は様々かもしれません。

できれば重たいテストなどは休日か夜間に自動でやらせましょう。 当たり前ではありますが、それだけでだいぶ楽になるはずです。

誰が使うソフトウェアであるにせよ、出力されるログは最小限にしましょう。 ログは、仮にそれが正常なメッセージであったとしても、多く出力されてしまうと大事なメッセージを見逃す原因になります。

魔法

同じ組織の中でも、いつも順調なチームと、いつも順調でないチームがあったりします。 大体の場合は、エンジニアやマネージャが絶妙なバランスで噛み合っている時、プロジェクトはうまくいきます。 そういった神がかり的な魔法にかかった状況は、人事異動などで簡単に崩れ去り、状況はあっという間に悪くなります。 他の人の仕事に必要以上に首を突っ込む必要はありません。それでも、他人が何をやっているのかをも学ぶことは決して無駄にはなりません。 それができていれば、バランスが崩れてもすぐに立て直せるはずです。

パフォーマンス向上、最適化、その具体策

まずメジャーなアルゴリズム理論や、ハードウェアの特性について学ぶ必要があります。 その上で、自分の環境で達成できるかもしれない限界を把握することが重要です。

パフォーマンスを考慮する上で、真っ先に考えるべきは通信の回数を削減することです。 システムには様々なレイヤーで無数の通信が発生しますが、アルゴリズムの観点その回数を削減することが性能改善の第一の着想になります。

並列処理・並行処理は性能を向上させる有効な手段の一つですが、メモリの共有には慎重になる必要があります。 単一プロセスでは発生し得ない不具合が、並列処理では発生します。 メモリの共有には最大限に慎重に、できればプロセス分割してメモリを分割して処理を進めましょう。

最後に、性能改善には不具合と隣り合わせになることが多いです。 その際に思い出したいのは、プログラム中の依存関係を極力小さくし、想定しなければ行けない範囲を極小化することです。 これにより、注意する範囲を限定して、本来向き合うべき対象に集中することができます。

プロとしての心構え、態度

プログラマの三大美徳は

  • 怠惰
  • 短気
  • 傲慢

だと言われています。 これらはすべて自分のコードにこだわりを持った結果の性質となっています。

自分の書くコード、環境、開発を取り巻くあらゆるものにこだわりましょう。 決してその場しのぎでコードを書くことのない、全力で考え抜かれたコードを生産し続けるのがプログラマです。 自分が書いたコードに一生付き合っていくつもり、あるいはそのコードによってキャリアが左右されると考えれば、自ずと品質は良くなっていくはずです。

そして、テクノロジーの先端を常に追いかけ続けてください。 古きを見て新しきを知る、その逆も然りです。 常に自分のできることを広げていく努力が、プロダクトの価値につながっていくのですから。

頑張りすぎない、余裕からいいアイデアは生まれます。 煮詰まったら、一旦コンピュータから距離を取ることも効果的な場合もあります。 余裕がなければ自らのスキルを上げる時間も取れません。 生産性を最大化することに注力することが、プログラマには求めれられています。

プログラミング言語パラダイム

プログラミング言語には設計思想、パラダイムがあり、これは各言語でそれぞれ異なります。 そして、パラダイムの異なる言語を学ぶことで、現在使用しているプログラミングについても今までと違った視点で記述できるようになるので、レベルが上がります。

複数の言語を扱えるようになる最大のメリットは、同じ問題に対して複数のアプローチを持つことができる点です。 単一の言語では、定石と呼ばれる書き方を習得しますが、別の言語では全く異なるアプローチが定石になっていることがあります。 これらを一つ一つ学ぶことで、過去に習得した言語でもより柔軟な考えのもとプログラミングができるようになるのです。

リファクタリングと保守

プログラムはプログラマが思う以上に残ってしまう、保守されてしまうものです。 今は知らない誰かが自分の書いたコードを保守するかもしれませんし、1人で進めていたプロジェクトが気がついたらチームで取り組む大きなプロジェクトになることもあります。 プログラマである以上、自分の書いたコードは他人に見られて恥ずかしくないように魂を込める必要があります。

一般的にコードは重複しないようにリファクタリングするべきです。 プログラマには既存のコードをリファクタリングしなければならないときがやってきます。 リファクタリングは、あくまで外部からみた振る舞いを変更せずに内部の動作を整理することなので、コードを書き直すことではありません。 書き直しではなく、きちんとしたリファクタリングが可能なように、場当たり的なコードは作成しないようにしなければなりません。

再利用と重複

重複をあえて作るときがあって、それはドメインやコンテキストが異なるときです。 コンピューター上での振る舞いは同じでも、その挙動が意味する内容が異なる、そんなコードを再利用すると、途端にコードは複雑になります。 単純化したはずが、余計に複雑に見える典型例です。

スケジュールと納期、見積もり

心構え

スケジュールが厳しいプロジェクトも当然存在します。 そんな中でも、故意の技術的負債は回避すべきです。 仮に技術的負債を作ってしまっても、すぐにそれを返済すべきなのです。 それがエンジニアとして、”分別のある行動”と言えるでしょう。

行動

常に自分の行うタスクは明確に、簡潔に、数時間スパンで完了する分量で管理できるようにしましょう。 一番ダメなのは、気がついたら手探り状態になってしまうことです。 集中したい気持ちはわかります。 だからこそ、短いスパンでの具体的作業に落としこんで、無駄のない作業として管理すべきなのです。

見積もりの考え方

  • 見積もり:価値・数字・量についての大まかな量。これには事実の裏づけに基づく測量が必要
  • ターゲット : 実現したいビジネス上の目標
  • コミットメント : 「ある機能をいつまでに一定品質で提供する」といった約束

「ソフトウェア見積もりの主目的は、プロジェクトの結果を予言することではない。見積もりを行うのは、プロジェクトのターゲットがコントロールによって達成可能な程度に現実的なものかを判断するためである。」

進捗の見える化

最後に、進捗は目で見てわかる証拠がたくさんある状態を維持するようにしましょう。 これがあれば進捗状況を正確に把握でき、頭の中だけの架空の虚偽進捗は発生しなくなります。

シンプルさ

コードの美しさとは何でしょうか。 これはこれまでも、おそらくこれからもつきまとっていく、答えのない問いだとは思います。 それでも、ある程度の"コツ"があるとすれば、それはシンプルであることだと、私も思います。

誰が読んでもわかる、必要以上に複雑になっていないコード、そういったコードは美しいことが多いです。 シンプルに、簡潔に、短くコードを記述できるようになることが、美しいコードを書く近道なのかもしれません。

チームと協調

エンジニアは一見、1人で黙々と作業している時間が長いように思いますが、実際には他人と対話していることのほうがずっと長いはずです。 良好な関係で、ペア、テスター、レビュアーと対話を進めることが重要になります。 これらは敵ではありません。 全員プロダクトの品質を上げるための味方なのです。

建設的な対話を行うことができれば、自ずとプロジェクトもうまく進むはずです。

テストとその実践、テスター

やらなければいけないとわかっていても嫌われるのがテストでしょう。

テストはプロダクトの品質向上に欠かせません。 プロダクトの真の仕様に沿った正しいテストをクリアすることで、品質は担保されていきます。 直接的に品質につながっている実感がわかないかもしれません。 しかし、テストをしないことは、構造解析をしていない橋を納品するようなものなのです。

テストやそのテストを行うテスターをよく思わない気持ちも理解できます。 しかし、テスターは本来敵ではなく、品質を向上させる同じ目的を持った味方です。 そして、テスターとうまくやってくことさえできれば、バグの原因調査などが効率的になり、開発効率は上がるはずなのです。

ツール、自動化、開発環境

現在我々の開発には様々なツールが利用可能になっています。 まず、ツールは使い倒してなんぼです。 習得にはそれなりに時間がかかるものですが、習得してしまえば劇的に生産性を上げる力を持っています。

次に、プログラマーは怠惰であるべきです。 可能な範囲で、開発に関するあらゆることを自動化すべきです。 人間は、頭でわかっていてもちょっとした急ぎで適当なコードを書いてしまい、それが後々まで残ってしまうということなどよくある話です。 ビルドに始まり、コーディング規約の矯正、テストのカバレッジ測定まで、あらゆることを自動化することが望ましいのです。

これらは、開発環境の裏で実際に何が起こっているのかを理解する事も重要です。 ただツールを使うのと、原始的なやり方を知ってツールを使うのでは本質的に全く異なります。 ぜひ、修行だと思って一度身をもって苦労しましょう。 そして、その苦労を超えて、最高の開発環境を追求することにこだわりましょう。 プログラマにとって、それは権利であり、パフォーマンスを上げるための責務でもあると思います。

ユーザと顧客

開発者とユーザは違います。そして我々は開発者であり、ユーザではありません。 ユーザのすることは、我々の想像の範囲を必ず超えてきます。 ユーザはユーザのコンテクストで話をするため、言うことに一貫性がないこともあります。 これは、ある意味仕方のないことで、エンジニアは根気強く対話を繰り返すしかありません。

エンジニアはプログラミングの段階から、ユーザの目線に経つことが望ましいです。 DSLドメイン固有の型を使って、極論、ユーザが自分でプログラムを読んで理解できるようにすることが望ましいです。 そうすることで、ユーザに寄り添った業務要件定義がそのままシステムに反映されます。 業務としてできないことをできないように、できるはずのことをできるように、業務の目線から作っていくことが必要になります。

感想

大事なことがあまりにも多いので、後半は単なるメモ書きになってしまいました。

一つ言えることは

テストはちゃんと書けよ

ってことはちゃんとわかりました。

学生のときに初めてITの世界に足を踏み入れてからもう10年近く経つわけですが、未だに知らないこと、わかっているけど実践できていないこと、 やってもなかなかうまくいかないこと、たくさん載っていました。

長いエンジニア人生ですので、この先も毎日いろんなことを学んで行くと思いますが、こういった先輩プログラマの言葉は素直に心に響きますね。 時々内容を見なおして、少しでも先輩プログラマのようになっていきたいものです。