自力でコードが書けるようになる思考

こんにちはマクロロです。

今回は自力でコードがかけるようになる思考やコードを書く際に意識していることなどを書きたいと思います。

コーディングをする際にいつもブログ記事などのコピペになっちゃうよ。。

最初からコードを自力で書くのは難しいよ。ステップを踏んで力をつけていこう!

複雑な事象を捉えるステップ

抽象的な問題にどう対処するのか

コーディングの前にまず、抽象的な問題に対するアプローチの仕方を理解する必要があると思います。

掴みどこがなくフワフワしているため、非常に解決するのが難しいです。

しかし、抽象的な問題や複雑な問題はただ漠然とその対象を眺めていても、解決策は浮かんできません。

ここでポイントなのが

どんな難解な問題もほとんどの場合、小さくシンプルな問題の塊であると意識することです。それは機能開発でも短かな問題解決にも当てはめることができます。

よくコンサルティング会社の選考で用いられるケース問題というものがあります。ケース問題は身近な抽象的問題を論理立てて解決策を提示するものです。

ケース問題もプログラミングと同様に非常に抽象的な問題をいかに、具体的にロジカルに問題を構造化できるかが問われます。

一回でもしっかり解き方のコツやフローを理解すれば、多様な問題に応用できるのでエンジニアでも身につけおくべき考え方であると思います。

私は現在外資系IT企業で働いていますが、新卒の際に外資系コンサルも内定をいただきました。

学生時代プログラミングばかりやっていた私でも、ある程度練習をすれば微塵ながら物事を構造化して考えるクセが身につきました。

このような考え方は日々の様々な問題解決だけに止まらず、アプリケーション開発においても非常に役に立っています。

ケース問題で構造化能力を鍛える

それでは実際に一例を挙げて、さくっとケース問題を解いていきましょう。

今回のお題は「新幹線内でのビールの売り上げを増加させる」という問題です。

皆さんはこの問題を解く際にどのように解決策を考えるでしょうか?

普段問題を構造的に捉えていない人は、いきなり解決策を提案します。例えば、「ビールの値段を安くする」や「広告を機内に貼る」などです。

確かにこれらは解決策の一つではありますが、問題を構造化せずにいきなり解決案を挙げていることで、「さらに効果のある施策を見逃している」、「実はあまり効果がある提案でなかった」などの自体が起こります。

では、どのように解いていくのか解決策の一例を上げていきます。

まずケース問題では問題に取り掛かる前に、ある程度自分で前提条件を設定する必要があります。

議論の発散を防ぐために前提条件を設けることである程度の終着点を決めておきます。

今回は以下のような設定を仮定します。

  • アルバイトで売り子をしているAさんからの依頼である
  • ビールを売る新幹線の区間は東京から大阪までの間
  • 東京から大阪までの間で人の入れ替わりはないものとする
  • 乗客は満員であるとする
  • 前提条件を設定したらこの「新幹線でのビールの売り上げを増加させる」という抽象的な問題をもっと具体的なものへと変換させていきます。

    例えば以下のような感じです。

    新幹線内でのビールの売り上げ =「新幹線の車両の本数×ビールの単価×一人当たりのビールの購入数×ビールの購入客数」

    このように「売り上げ」がどのような要素で構成されているのかを分解することで、より明確にどの項目に対して施策を打っていけば良いのかを明確にします。

    ここで、現実的にアルバイトのAさんが工夫できそうな項目を上げていきます。

  • 新幹線の車両の本数→アルバイトに車両を増やす権限はない
  • ビールの単価→物の単価はだいたい限りなく最低値に設定してある
  • 一人当たりのビールの購入数→ビールを新幹線で酔っぱらうまで飲む人は少ない
  • ビールの購入客数→工夫次第で増やせそう
  • 上記のように分解した項目から、改善余地がありそうな項目を現実性を加味してピックアップします。

    今回は、「購入客数」という項目に対して何かアプローチができそうだと判断します。

    ここでさらに、「購入客数」がどのような要素で構成・影響されているのかを分解していきます。

    購入客数 =「乗客の回転率×Aさんが新幹線を往復する回数×一車両の乗客数×Aさんの接客能力」

    ここでまた、改善余地がありそうな項目を選別します。

  • 乗客の回転率→前提条件で同じ人が乗っている想定なので弄れない
  • Aさんが新幹線を往復する回数→改善できそう
  • 一車両の乗客数→前提条件で常に満員だと仮定している
  • Aさんの接客能力→工夫次第で改善できそう
  • ここでようやくボトルネックとなる事項が浮かんできました。

    「Aさんが新幹線を往復する回数」と「Aさんの接客能力」、この2点の問題にアプローチするような施策を考えます。

    「新幹線を往復する回数に関しては」今まで、東京〜大阪間を1往復しかしていなかったのを、移動スピードを少しあげることで1.5往復に増やしアプローチする顧客を増やす。

    「Aさんの接客能力」に関しては、「売り上げの高い先輩にコツを聞く」→「多様なお客さんに柔軟に対応できるような接客のノウハウを得る」などの施策を打てます。

    ケース問題は100%正しい答えがあるものでありません。なので突っ込みどころ満載で問題ないです。

    しかし、抽象的な問題を構造化し、ある程度万人が納得できるロジックで構成された現状分析のうえで、妥当な施策が最終的に挙げられているかが大事です。

    コードを書く際の思考

    上記でケース問題を例にして、抽象的な問題にどのように対処していくのかをみてきました。

    アプリケーション開発や競技プログラミングのような問題でも、最初は解決すべき問いは抽象的です。そういった点で、ケース問題を解く思考とプログラムで機能を実装する思考は共通しているところがあります。

    例えば、Twitterのようなアプリだったら「ユーザー同士がコミュニケーションを取れるような機能をつける」だったり、競技プログラミングであれば「じゃんけんゲームのようなもののロジックを作る」など。

    それをどのように実現させるかは、まず全体を俯瞰して捉え、どのような手順で、どのようなアルゴリズムを用いて達成していくのかを考えていかなければなりません。

    全体の地図がわからない状況でいきなり手を動かしてコーディングすることは不可能であり、確実に抜け漏れのない論理にまず落とし込まなければなりません。

    実際にアプリケーション開発で任意の機能を作成する際は以下のフローで作成していくと良いでしょう。

    1. 実現したいことがどのような仕組みで動いているのか概念を理解する
    2. その概念をどのような技術や論理で実現できるかを考える
    3. 実際にその機能が動作するようなロジックを自然言語でフローを考える
    4. 上記で考えたフローを実際にプログラミング言語で実装する

    この四つのステップがあって初めて手を動かしてコーディングし、機能を開発することができます。

    よほどの天才エンジニアを除いては、このようにしっかり全体をしっかり俯瞰してどのようなロジックなのかを一つ一つ理解してからコーディングする必要があります。

    それではもう少し各過程を詳しくみていきます。

    実現したいことがどのような仕組みで動いているのか概念を理解する

    まずアプリケーション全体がどのように動いているかをしっかり理解する必要があります。

    正直このフェーズはエンジニアでなくても、誰でも理解できる過程です。

    例えば、Twitterを例にすると。

  • アカウントを作って自分を登録する
  • 表現したい考えを書き込んで送信する
  • 定期的に呟きを見たい人をフォローする
  • 他の人のツイートに対してコメントする
  • 簡単にツイッターの機能をあげると上記のようなことです。

    そのアプリでどんなことを実現しているのかの全体像を捉えます。

    その概念をどのような技術や論理で実現できるかを考える

    この段階に入るとエンジニアっぽい工程に入ります。

    例えばログイン機能の場合は、

    ①「ユーザーが情報(メールアドレスやパスワード)を入力できるフォーム画面を用意する」→②「入力されたメールアドレスをサーバー側に送る」→③「サーバーからDBへメールアドレスを送信する」→④「DBから送られてきたメールアドレスに対応するパスワードをサーバーに返す(ユーザーが存在していると仮定)」→⑤「フォームから受け取ったパスワードとDBから送られてきたパスワードが等しいかどうか検証する」

    このように一段間抽象的だった機能説明を、より詳細にどのようにその機能を実現するのかを理解します。

    このフェーズの理解が曖昧だと次の段階で詰まるので、しっかりと理解するようにしましょう。

    実際にその機能が動作するようなロジックフローを自然言語で考える

    上記の過程を理解することができたら、ここでコーディングレベル・文法レベルのロジックまで落とし込んでいきます。

    ここでは例を簡単にするために、「ログイン機能」をみていきます。簡単なログイン機能は以下のようなロジックが必要です。

    (フロントエンドからデータを受け取った後からのサーバーサイドの話に限定します)

  • フロントから送信されてきたパスワードとメアドをそれぞれ変数に保持する
  • メアドをキーにしたクエリを投げて、DBからパスワードをとってくる
  • 送られてきたパスワードとDBから取得したパスワードが同値かboolで確認
  • Trueだった場合ホームにリダイレクト、Falseの時はエラーを返す
  • 今回説明のために少し簡素化しましたが、このフェーズのイメージとしては上記のように、よりコーディング 可能なレベルまで具体的にしていきます。

    上記で考えたフローを実際にプログラミング言語で実装する

    ここまできてようやくコードを書き始めます。自然言語で表現したロジックをコードに置き換えます。

    正直、上記の過程でロジックがしっかり作成されていれば、この過程はあまり難しいものではありません。

    大体の場合、「実現したいこと+その言語」で出てくるからです。

    さらにここで一番大事なことが、とにかく小さく動くコードを徐々に追加していくというこです。

    確認作業をせずに、複数行一気にコードを書くと必ずどこかでつまります。

    ネットなどに落ちているコードをコピペした際に上手く動かず、修正箇所を見つけるのが難しいのも自分で1から確認作業をしていないからです。

    なれるまでは一行一行コードを書いたら、それが正しい振る舞いをしているのかどうかを逐次確かめながら追加していってください。

    まとめ

    今回はケース問題を取り上げて、抽象的な事象をどのように具体的なロジックに落とし込んでいくのか。

    そして、そのような問題に対する思考をコーディングする際にどのように応用していくのかを説明しました!

    私も未熟なエンジニアでまだまだ経験と知識があまいです。あくまで私の一個人の意見であり、確実に最良の方法ではありません。

    しかし、私がプログラミングを学習していく過程で、今回書いた内容を意識して取り組むことで、少なからず自力でコードを書けるようになった実感があります。

    全く自力でコードがかけなかった時と比べて圧倒的にスキルの向上を感じています。

    現在、写経したりProgateなどで文法を勉強しているけど、自力でコーディングできるようになる感覚がいまいち持てないと感じている人は、今回紹介したようなことを意識してみてください。

    WordPressをレンタルサーバーからクラウド(Iaas, Paas)に移行する手順前のページ

    コロナ禍でのマルタ留学は可能か?次のページ

    関連記事

    1. プログラミング

      react-reduxの基礎

      こんにちは、マクロロです!季節も巡り、もうすぐ夏がきますね。。…

    2. プログラミング

      RailsからGolangを習得する際の壁

      こんにちはまくロロです。今回はRailsからGolangを習得する際…

    3. プログラミング

      Gitとは?Gitの概念を理解しよう

      こんにちは、まくロロです。今回は、Gitの概念を説明していき…

    4. プログラミング

      dockerを使ってGolangの環境構築

      こんにちは、まくロロです。最近はサーバーをGo、フロントにR…

    5. プログラミング

      kubernetes(k8s)とは

      こんにちは、まくロロです。先日とある企業さんのk8sハンズオンに参加…

    6. プログラミング

      railsのincludesメソッドで関連しているデータを取得する

      こんにちは、まくロロです。申請していたアドセンスがついに通りました!…

    コメント

    1. この記事へのコメントはありません。

    1. この記事へのトラックバックはありません。

    最近の記事

    PAGE TOP