エンジニアHubPowered by エン転職

若手Webエンジニアのための情報メディア

教えて、ござ先輩! なぜプログラミングに「表現力」が必須? わずか3つの表現文法でイメージをコード化する方法

自分のイメージを、ちゃんとコードとして表現することができていますか?そのために必要なのは、イメージを論理へと変換する、「表現力」です。エンジニアが身につけるべき表現力を、ござ先輩がばっちり解説します!

f:id:blog-media:20170726134840j:plain

株式会社クオリティスタートの代表を務めている、湯本@gothedistanceと申します。インターネットでは、「ござ先輩」という愛称でブログを書いたり、雑誌やWebメディアに記事を書かせていただいています。本業ではITコンサルタントという立ち位置で、主に業務アプリケーションの業務分析/要件定義や、エンジニア向けの新人研修の講師などの仕事をしています。

プログラミングは非常に自由なもので、同じ処理や条件を記述しているにもかかわらず、エンジニアによって書かれたコードがかなり違うことがあります。「この時だけ動けばいい。あとは知らん」という刹那的なコードもあれば、「この2行だけで全てが表せる。変更にも強い」という堅牢なコードもあります。

新人や若手の方が「プログラミングができるようになる過程」を見ていく中で、この、「考えを表現できる力」が不足していると感じることが多々あります。「自分はこういうコードが書きたい」と言葉にすることができないと、自分が何を形にするべきか、また、自分が何につまずいているのかもわからないのではないでしょうか。本稿では、若いエンジニアに向け、「エンジニアが体得するべき表現力」の意味を解説してみたいと思います。

プログラミングにおける「表現力」とは?

「自分はこういうコードを書きたい」が言葉にできない最たる理由は、プログラミングにおける表現がどういったものかを把握できていないからだと考えています。2つのケースを引き合いにして、皆さんとプログラミングにおいて何をどう「表現」するのか?を、考えてみましょう。

1つ目は、定番の問題である「FizzBuzz」です。仕様は以下の通りです。

  • 3の倍数ならFizzと表示
  • 5の倍数ならBuzzと表示
  • 3と5の倍数ならFizzBuzzと表示
  • それ以外なら、当該数字を表示

表現のための文法はわずか3つ

プログラミングの基礎文法は3つしかありません。「順番に行う」「条件分岐」「繰り返し」です。これらを駆使して、どういった処理の流れを作ればよいのかを考えるのが、プログラミングです。

FizzBuzzのキモは倍数判定です。判定対象となる数字がどんな数字でも、ある数の倍数か否かを判定する必要があります。

処理内容を考えるにあたっては、具体的なケースを想定して処理の流れを考え、そこにある共通点を見つけることが重要です。3でも33でも345でも9980802でも、3の倍数として判断しなければなりません。

これらに共通している属性は、「3で割ると余りが0になる」です。ここにたどり着けば、あとは単純。「倍数=ある数字で割り切れる=余りがない」という連想を行うことで、条件分岐のコードに落とし込めるわけです。

つまり、FizzBuzzプログラムは「ある数で割った時に余りがない数(この場合は3)」の判定プログラムであると表現できます。これこそが、プログラミングにおける表現力です。

3の倍数ならFizzと表示

倍数=ある数字で割り切れることができる数

Fizzと表示するための要件を下段の概念に置き換えて、割り切れることができるか否かという状況を作り出し、条件分岐によって判断可能にしています。こうした表現能力、つまり、事象をYes/Noで判断できるところまで分解して表現できるかどうかが、「こういうコードを書けばいいんだ!」につながる鍵となります。

論理として成り立つように、言い換える

FizzBuzzの条件分岐は比較的単純なので、頭に入りやすいでしょう。一方、新人さんが苦労するのが、繰り返しの条件を作ることです。例えばwhile文です。while文は「ある条件が成り立つ限り繰り返す」ということを表現することが求められますが、上手く読解できない方が少なからずいらっしゃいます。

while文の例として素数判定がよく用いられます。ある数字が素数であることを証明するには、1と自分以外で割り切れないことを証明すればいいわけです。今年は2017年ですが、2017は素数です。2017を素数であるかを判定するためには、どんなことを表現する処理を書けばよいでしょうか?

最も単純な解法は、2から順番に割り算をして、自分自身以外の数字で割り切れるかを判定することです。例えば、10であれば2で割ったら割り切れるので素数ではありません。11は2〜10のいかなる数字でも割り切れないので、素数です。

こういったロジックを作れば、どんな数字が対象になっても素数であると判定できます。 では、この素数探索アルゴリズムを実現するために、どういう繰り返し条件を設定してwhile文を作ればいいか、少し考えてみて下さい。以下が回答例です。

     num = 2017 
     cnt = 1 
     while num > cnt: 
         cnt += 1
         if num % cnt == 0:
            break

ポイントはnum > cntです。「自分自身以外の数字で割り切れるかを判定する=2から自分の数字まで順番に繰り返す=判定したい数>割る数字」に展開していることがポイントです。実際に11が代入された時の流れを追いかけると、さらに頭に入ることでしょう。

まとめると、以下のような図になります。

design title image

自分の意図を表現できない場合は、「例えば、この場合だったらどう動くのが正しい?」という質問に上手く答えることができません。「何がやりたいの?」と聞かれたら「例えば、こういう時にはこうしたい!」と表現できるように、習慣づけましょう。

考え方の違いでコードはここまで変わる

もう1つ例題を考えてみましょう。ロジックの発想が違うだけで随分と違うコードになるという事例です。自戒を込め、私自身が直面した課題に基づく例題です。

DBを操作するプログラミングの中で、最も面倒なことの1つは検索条件の組み立てです。SQLAlchemyを例に取ります。検索条件に名前と名字を入れて、特定のユーザーを探し出す機能を作ろうとしていましたが、当時の私がイメージしていたコードは下のようなものでした。

query = session.query(User)
if firstname:
     rs = query.filter(User.firstname==firstname)
  if lastname:
     rs = query.filter(User.lastname==lastname)

SQLAlchemyの強力な表現力で、ある程度組み立ては楽になっています。このコードに致命的な欠陥があるわけではありませんが、プログラミングにおいて、同じことを何度も繰り返すのは、原則的に回避すべきです。その意味で、上のようにifを書き続けるのはスマートではありません。

このようなコードに私自身違和感があったことから、ある掲示板で相談したところ、以下のコードが代替案として提案されたのです。

q = session.Query(User)
q = q.filter((User.firstname==firstname) | (not firstname)).\
        .filter((User.lastname==lastname) | (not lastname))

このfilterの面白いところは、ifではなく、SQLAlchemyの|演算子を使っている点です。左側の条件が成り立つ(firstnameに値が入っている)場合は左側の式が評価され、firstnameがFalseだったらAND 1=1というWHERE句になるのです。

AND 1=1は常にTrueを返すので、検索条件としては機能していません。検索キーワードがない=AND 1=1を返すという考えは私にはなかったので、大変勉強になりました。

前者と後者のコードを比較すると、機能という意味では同じです。しかし、目的は1つだったとしても、それを実現するための方法は複数存在します。このように複数の方法を知ることで、より高度なプログラミングにもアプローチできるようになるのです。

上で紹介した例の場合、|という新しいボキャブラリーを学んだことで、私は新しい表現に出会うことができました。

プログラミングは表現の良し悪しで全てが変わる

プログラミングは「つまり、こうなる」の繰り返しです。この「つまり」の部分をどう表現するか、言葉を変えれば「要は、こうでしょ?」と言い換えること。これがプログラミングにおける表現力であり、「つまり、こうなる」の論理をどう構築するかによって、出来上がってくるコードの質が全く違います。 プログラミングは表現記法が非常に限られた状態で、自分の意図を表現することが求められます。皆さんが、やりたいことをコードに落とすためのヒントを掴んでもらえれば嬉しく思います。

執筆者プロフィール

湯本 堅隆(ゆもと・みちたか) @gothedistance

@gothedistance
ブログ「GoTheDistance」の中の人。ISPの電話サポートのアルバイトをきっかけにIT技術に興味を持ち、2003年にアイ・ティ・フロンティア(現タタ・コンサルタンシー・サービシズ)に新卒で入社。2016年5月に退職し、エンジニアの活躍の場をエンジニアがいないユーザー企業にまで広げていく必要があると強く感じ、(株) クオリティスタートを創業。著書に『独習Python入門―1日でプログラミングに強くなる!』がある。