プログラミング設計論

こんにちは〜
ソフトウェアエンジニアをしております秦野です。
今回の記事は「プログラミング設計論」と題しまして、どのようにプログラムを設計すべきかという話をしようと思います。
 
そもそもなぜこの記事を書こうかと思ったかと言うと、プログラミングの設計は「一番重要」なことなのに何故かそれがいつも置いてけぼりになっているように感じたからです。
設計を重視せず、悲惨なコードに苦しんでいるエンジニアが一杯います。
 
まず、何故プログラミングの設計がエンジニアにとって「一番重要」と言えるのかを簡単に説明しようと思います。
エンジニアの仕事とは何でしょうか?エンジニアの仕事は言うまでもなくコードを書くことですね。もちろん他にも、仕様書作成であったり、打ち合わせなど他の仕事もありますがそれも全てコードを書くためにあります。
そして、コードを書くためにはコードを読まなければなりません。
出来るだけ事業スピードをあげるためには、沢山の機能を追加するためにはコードを読む時間ではなくてコードを書いている時間の割合が高くなるようにしなくてはなりません。
また、同じ機能を追加するにしても出来るだけ短い時間でコードを書けた方がいいことも言うまでもありません。
そして、コードを読む時間とコードを書く時間に関係するのが「どのようにコードが書かれているか、どのように書くか?」つまり、「どのように設計されているか、するか?」ということです。
つまり、設計の良し悪しがエンジニアの生産性に直結しているのです。
ビルゲイツに言わせるとエンジニアの能力差は100倍あるそうですが
全くもってその通りだと思います。設計スキルが低すぎて機能追加できなかったり、バグだらけのコードを書いてしまうエンジニアは一杯います。
エンジニアの能力差は無限にあると言ってもいいぐらいです。
 
それでは本題の「プログラミング設計論」の話に入ろうと思います。
「プログラミング設計論」というのは言い換えれば「プログラミングデザイン論」とも言えると思います。
ではデザインとは何でしょう?
私の中でデザインとは一言で言えば相手に情報を分かりやすく整理して伝えることです。
つまり、プログラムを設計する、書くと言うことは読み手にとっていかに分かりやすく書くか?ということに尽きると思います。
 
そこでどのように書くべきか?という問題にぶつかります。
私としての答えは使い手(読み手)にとって分かりやすいインターフェースとなるように書くべきだということになります。
つまり、カスタマーサイドに立って書こうということです。
ハンバーガーを売ってる訳でもないのにカスタマーサイドに立つ必要があるのか?と思うかもしれませんが、ちゃんと読み手のことを考えないコードが汚いコードになるのは必然です。
 
もしも「プログラミングする時に何を一番意識して書いていますか?」と聞かれれば「クライアント側から見て、すぐに理解できるかを意識しています。」と私は答えます。
プログラミングする時はインターフェースが命です。
インターフェースが全てです。
ある一連の処理を行うプログラムがあった時、それを一番上のメソッドから読み下した時に何を行なっているか大体分かるように書くべきなのです。(ここでは説明のため一旦メソッドをインターフェースとします。)
もっと言えば、普通の英語の文章を読んでいるようにプログラムを書くべきなのです。
プログラミング初心者でも、プログラミングを知らない人でも「ああ、ここではこういう処理を行なっているんですね。」と分かるようにすべきです。
もしも分からないのだとしたら、オブジェクト指向で書けていない、クラス分けやメソッドへの分離、メソッドの命名などが上手くいっていないのです。1つのメソッドに責務を詰め込みすぎているのです。
 
定食屋の自動券売機を考えてみましょう。
定食屋の券売機で食券を買う理由は何でしょう?
「食べたいものがあるから」ですね!
では、食券を買う時に食べたいもの以外に興味があることはありますか?
例えば、レシピ・物流経路・お店の誰が調理するか・お皿の種類などに興味がありますか?
私はありません。
レシピ以外に興味があるのは「いくらか?」というものぐらいです。
 
ではここで「券売機にお金を入れて、食券のボタンを押すと料理を提供する」というサービスをメソッドとして定義してみましょう。
大体次のようになるでしょう。
解説用のコメントを入れていますが、簡潔なインターフェースを定義できているので本来はコメントは必要ありません。 

def serve_cuisine(ticket_type, charge)
  # まず、入力値をチェックするべき、不正な値ならそこから先の処理に進めてはならない
  raise Error('お金が足りないよ') unless enough_charge?(ticket_type, charge)
  chef = ChefRegistry.get_free_chef
  cuisine = chef.cook(ticket_type)
  serve_customer(cuisine)
end

これをインターフェースを意識しないエンジニアが実装すると、上から下に読んでも理解できないコードを書いてしまいます。
例えば、シェフを取得するコードで、例に挙げたコードではChefRegistryクラスを定義し、DBへのアクセス、アクティブレコードへの明示的なアクセスを避けて、高度に抽象化したメソッドを定義してそれを利用するようにしています。
このようにメソッドを定義することで次の利点があります。
クライアント(読み手、ユーザー)は裏側の知識なくシェフを取得することができます。ChefRegistryクラス内でアクティブレコードへのアクセスは隠されているので、アクティブレコードではない別のORマッパーを利用しても、全別々のNoSQLを利用しても、ファイルに読み書きするようにしてもユーザー側のコードは壊れません。
また、Chefの振る舞いではない、DB層からのChefインスタンスの生成という処理を別のクラスに分離できています。これを分離せずChefに振る舞いと関係ないメソッドを含めてしまうと、Chefクラスが肥大化して理解しにくいコードとなってしまいます。
つまり、知る必要がないことが上手く隠されている上、必要十分な情報が公開されており分かりやすく、柔軟性が高い、疎結合で凝縮性の高いコードになっているのです。

しかし、インターフェースを意識しない、クライアントのことを考えないプログラマーが書くコードはアクティブレコードに直接アクセスし、様々な条件分岐を行うような部分をユーザー側に公開してしまいます。1行で行なっているコードが10行以上の表現となってそんな実装の詳細を知らなくてもいいクライアント側のコードに書き殴られてしまうのです。
自動券売機の例で言えば、こちらが求めていない、レシピや物流経路、担当しているシェフの名前などを知らされるようなものです。
そんなことはどうでもいいからクライアントが必要なものを手軽に届けて欲しいと思います。
他のコードの部分についても同様です。
それぞれ1行で済むようなコードが何十行にもなって表現され、このメソッドって何をするためのものなんだっけ?このコードとこのコードの関係はどのような関係なのか?関係あるのか?ないのか?インターフェースが明確でないと機能の役割分担が明確でなくなり非常に分かりづらいコードとなってしまいます。

ここまで、プログラミング設計論と言いつつ、インターフェースの話しかしていませんが各種のプログラミング論、オブジェクト指向プログラミング、関数型プログラミングMVCアーキテクチャ、様々なアーキテクチャ論は全てインターフェースの話を、つまり設計のデザインの話をしています。
いかに人がコードやシステムを理解しやすいようにするか。という問題に対して全て発展してきたものです。
だから、プログラミングの設計をする、プログラミングの設計を学ぶときはインターフェースを分かりやすくするためにしているんだという視点を忘れないで欲しいと思います。
基本をまとめると
インターフェースは
・意味のある言葉として一目で理解できる
・不必要な情報は見せない
・役割が明確である
以上の点を守る必要があります。
また、これらが守られていれば次のような利益を得ることができます。
・理解しやすく、コードを読む時間を少なくすることができる
・どこで何をしているか明確で、必要な機能を必要な場所に素早く追加できる
・機能修正が必要な時も素早く修正できる上、他の部分への影響が少ないか全くない
・部分的な機能を抜き出しやすい(モジュール化・マイクロサービス化しやすい)

話が大きくなり過ぎるのを防ぐために、コードベースで話をしましたが、どのようなシステムにしろそれが他のもの、例えばAPIや他のサービスと連携するようなものならインターフェースの重要性に変わりはありません。
だから私の今回の話はシステム設計の一般論を語っているものとも言えるかも知れません。
今回はプログラミングに関しては1回目の投稿でしたので、基本であり最終奥義でもあるインターフェースの話をしました。
インターフェースを上手く表現できるようになると、つまり設計能力が高くなるとどんなプログラミング言語でも上手く操れるようになります。
新しいプログラミング言語を始めても直ぐに上達して、美しいコードを書くことができるようになります。
プログラミングを学ぶこと、書くことがどんどん楽しくなります。
だからプログラミング言語やソフトウェアの使い方だけを学ぶのではなく、プログラマの地力と言える設計能力を高めることが重要だと思います。

今回は理論にほぼ費やしましたので次回からはもう少し具体的な例を出していきたいと思います。

最後までお読み頂きありがとうございます。
 
 

「初めまして」と「経営者としての成長戦略」

みなさんこんにちは。

iPhoneのニュースアプリ「Collect - SNSニュースアプリ」を開発している会社の代表兼エンジニアをしている秦野芳彰です。

このブログでは私が起業してから得た知識や学び、起業や会社経営について、またその他の様々な発見などを投稿していこうと考えています。

 今回は私の第一回のブログ投稿として、自己紹介と「経営者としての成長戦略」について話したいと思います。

まず私自身と会社について簡単に説明させて下さい。

私の略歴は次のようになっています。

慶應義塾大学商学部卒、ゼミは木戸一夫研究会所属、ゼミでは経営戦略についての知識を学びました。

大学卒業後メーカーの資材部門に3年勤務した後に退職し、株式会社Collectを立ち上げ、2018年10月にアプリをリリースしました。

気づいた人もいると思いますが、私は理系でもなければ前職でIT系で働いていた訳でもありません。

また、プログラミングもやったことのない完全な未経験者でした。

会社の人員も1人(私だけ)ですが、アプリの仕様の作成、デザインの作成、機能の実装、サーバの構築等々全てをやり通してアプリをリリースしました。

何でそんな大変そうなことをしたのだろうかと思う人もいるかもしれませんがこれが私の「経営者としての成長戦略」だからです。

 

会社を経営する上で重要な能力は何だろうか?と考えた時に私が重要だと思った能力が3つあります。

1つ目は経営戦略の能力、2つ目はプログラミングの能力(テクノロジーを理解する能力)、3つ目はデザインの能力。

これら3つの能力が会社、特に大企業を運営する上で非常に重要な能力だと思いました。そして、これらの能力を身につけるために自分の時間の大部分を割いてきました。なお、ベンチャーを経営する上では1つ目の経営戦略の能力はあまり必要ありません。

大企業を経営する上でなぜ経営戦略の能力が重要かと言うと、経営戦略とは一言で言えばいかに会社のリソースをうまく配分して経営効率を高めるかと言うその戦略のことであり、大企業を経営するとはいかにうまくリソースを分配するかという問題だからです。一方、ベンチャーにおいて経営戦略の能力があまり必要でないということもここで軽く説明しておきます。大企業においてリソースの分配が重要ということは、商品やサービスに既に需要があるということが暗黙の前提となっていました。しかし、ベンチャーではそもそも提供する商品やサービスに事前に大きな需要があるかどうか正確には分かりませんし、リソースもあまりないのが普通です。そのため、経営効率を高めるという問題を解くのではなく、どこにサービスの需要があるか?という問題を解くのがベンチャーなのです。各ベンチャー企業はそれぞれ需要がありそうな領域に対して、商品やサービスをマーケットインしていきます。そのための理論もPMFなどという形で発展しています。

 

2つ目のプログラミングの能力(テクノロジー(特にIT)を理解する能力)ですが、なぜこの能力が重要かと言うと今ではどんなサービスであれITと無関係でいることはできないからです。昔はインターネットに繋がっていなかった自動車や家電も今ではインターネットに繋がり、インターネットを通して情報をやり取りして新しいサービスを提供しています。今後、私達が予想もしなかったような分野にもインターネットは接続されていくでしょう。Amazonでは機械学習でユーザーの好みを学習しておすすめ商品をレコメンドしてくれます。ニュースアプリではユーザーが好みそうな記事を表示してくれます。これらの技術全てに使われているものがプログラミングでありITの技術であり、アルゴリズムなのです。新しいサービスを提供しようと思った時に、そのサービスの内容は今ある技術で実装できるのか?また、新しいアルゴリズムを知ることでこのアルゴリズムを使って何かサービスができないか?と考えた時にその技術に対する理解がなければサービスを作れません。

私のアプリでもおすすめ記事やトップニュースを機械学習によって自動で作成していますが、もしも私が機械学習を理解できていなければ手作業で毎日おすすめ記事リストやトップニュースリストを作成しなければならなかったでしょう。自力で実装できたからこそ私が寝ている間でもサーバーが自動で計算しておすすめ記事リストをユーザーに配布してくれるのです。手作業で何時間もかかることをパソコンが数分で計算してくれることは実際に体験すると本当に驚くべきことです。そしてそうした効率化は全てテクノロジーの恩恵です。テクノロジーの恩恵を自分が受けるもしくはサービスとして提供するには常にテクノロジーを理解しようと努める必要があります。

 

3つ目はデザインの能力です。

私がデザインが重要な能力だと思ったのはジョブズiPhoneで成功したのはジョブズにデザインセンス、デザインの良し悪しを判断する能力があったからだと考えたからです。

ジョブズと言えば現実歪曲フィールドが有名ですよね?

考えてみてください、もしもジョブズに現実歪曲フィールドはあるがデザインセンスがなかった時のことを。

ジョブズiPhoneをみてこんなことを言うかも知れません。

「何だこのシンプルなデザインは?こんなのデザインしたとは言えない。もっと、こうゴツゴツしてインパクトのあるデザインにしろ」

現実歪曲フィールドのせいで、デザイナーはやむなく指示された通りにデザインを修正してしまい、今世に出ているような洗練されたデザインのものは生み出されなかったかも知れません。

Apple製品には一貫して使いやすい、分かりやすいという特徴があると思っていますがこれはジョブズのデザイン精神が製品に息づいているからでしょう。

つまり、経営者であるジョブズのデザイン能力の高さが効果を発揮していると言えます。

同じような機能を提供する製品であっても、人はより使いやすい方、使っていて気持ちがいいもの、かっこいいものを利用したいでしょう。

この時に重要となる能力がデザイン能力なのです。

 

私はデザインとは絵や図や文字を利用して相手に情報を分かりやすく整理して伝えることだと思っています。

現実に存在するiPhoneのようなデバイスでなくても画面の中のWebサービスであってもどんな製品・サービスでもデザインは必ず必要になります。

そしてそのデザインの良し悪しによってサービスが選択されるかされないかが決まってしまうことが多分にあります。

つまり、デザイン能力とはサービスの成否を決めてしまうほど重要な能力なのです。

だから、私は3つ目に重要な能力としてデザイン能力をあげたのです。

 

ここでプログラミングの能力もデザインの能力も重要だということは分かったでもその能力をわざわざ自分で身につける必要があるのか?と思った人もいるでしょう。結論から言うと、ベンチャーで成功するためには別に必須の能力ではないでしょう。あったほうがいい能力ではあると思いますが、プログラミングができる人、デザインができる人を雇えばいいのです。

ではなぜ私がわざわざこれらの能力を身につけるために努力したのかと言うと、経営者としての意思決定能力をできる限り高めたいと考えたからです。

経営者の仕事とは何でしょうか?

経営者の仕事とは一言で言えば「会社レベルの意思決定をすること」だと思っています。

具体的には、ベンチャー企業であればエンジニアを採用する時、候補者の中から誰を採用するか、決定するのは社長でしょう。大企業であれば、社長が直接誰を採用するか決定するのではなく、採用戦略の決定だけを行うかも知れません。企業の規模が異なれば同じようなことであっても意思決定の種類と質が異なるようになります。

しかし、一貫して質の高い意思決定が経営者には求められます。

つまり、経営者の優秀さとは意思決定の質の高さなのです。

エンジニアを採用する時、その決定を行う人がそのエンジニアリングの能力にたけていなければ正しい意思決定を行うことはできません。自分にエンジニアの能力が無ければ他の人に採用を任せることもできますが、今度は採用を任せる人を決めるという意思決定を行わなければなりません。ここでも、自分のエンジニア能力が高ければ高いほど、採用を任せるのに最適な人を選ぶことができます。結局、誰かに任せたとしても意思決定の質に、それに関連した能力について自身でどれだけ高い能力を持っているかということが問題になります。

これまで説明してきた通り、プログラミング(テクノロジー)やデザインというものは会社を経営する上で無くてはならない重要な要素となっています。

そして、会社の多くの意思決定において、これらの要素に基づいた意思決定が求められてきます。

例えば、先ほどから例にあげている、エンジニアを採用する時、またエンジニアを統括するマネジャーを採用する時でも同様にテクノロジーに対する理解能力は求められるでしょう。さらに、会社が新しいサービスを作るときにもテクノロジーの能力、そしてデザインの能力も求められます。 

このように重要であり、常に求められる能力であると考えたので私はまずこれらの能力を身につけることを最優先課題と考えました。

そして、その能力について高い能力を身につけるには自身で実際にそれらの能力を必要とすることに挑戦しなければならないと思いました。

高い能力を身につけるためには実際に自分で「体験」することが非常に重要だと私は考えています。重要なことなのでここで詳しく説明しておきましょう。

例えば、テニスのサーブを考えて下さい。テニスのサーブを上手くできる人は次の内、誰でしょうか?

A:サーブの打ち方を本で読んだだけの人

B:サーブの打ち方をYoutubeで見ただけの人

C:サーブの打ち方を実際の練習の中で試行錯誤して身につけた人

明らかに実際に自分で体験したCさんがもっとも上手くサーブを打てるでしょう。

ここではスポーツを例にあげましたがプログラミングでも事情は同じです。

新しいプログラミング言語フレームワークを学ぶ時、私は本やWebサイトに書いてある内容をそのまま鵜呑みにすることはあまりありません。しっかり身につけようと考えた時はいつも、書いてあるサンプルコードを実際に自分のMacに入力して同じように動くかを確かめます。大体、ちゃんと同じように動きますが、この「同じように動いた」ということを確認するのがまさに「体験」したということなのです。この体験があるからこそ知識が本当の意味で自分のものになるのです。英語の勉強でも単語を覚える時、単にその意味だけでなく、その単語を発音したり、長文を読みながら発音することで身につけるでしょう?それと同じことです。実際に体験することで自身の生きた能力となるのです。これはテニスだろうが、プログラミングだろうが、英語の勉強だろうが何でも当てはまります。

ちゃんと体験して、高い能力を身につけたい。そう思ったからこそ、一見無謀に見えるかも知れませんが1人でアプリを作成するということに挑戦したのです。

なお、経営者に求められる能力はもちろん私があげた3つの能力だけではありませんし、ベンチャー企業においては別の能力も必要にもなります。

今回の投稿はあくまでも私の「経営者としての成長戦略」とそれに関連して経営者にとって重要な能力を提示したものです。

今回の私の投稿が誰かの役に立てれば幸いです。