誰もが同じことを言います:「本当のプログラマーは本当の問題を処理する方法を知っています。」しかし、彼らはこの能力をどこでどのように学んだかを忘れています。それは学校で教えられていません。
複雑なプログラミングの問題に取り組む能力を向上させるにはどうすればよいですか?どの戦略が効果的ですか?アルゴリズムや設計パターンなど、私が注目すべき特定の領域はありますか?
誰もが同じことを言います:「本当のプログラマーは本当の問題を処理する方法を知っています。」しかし、彼らはこの能力をどこでどのように学んだかを忘れています。それは学校で教えられていません。
複雑なプログラミングの問題に取り組む能力を向上させるにはどうすればよいですか?どの戦略が効果的ですか?アルゴリズムや設計パターンなど、私が注目すべき特定の領域はありますか?
回答:
動作する場合と動作しない場合があるいくつかのテクニック:
必要に応じてRモードまたはLモードの思考を使用する
Rモードは、私たちが一般にサブコンシャスに関連付ける創造的で非言語的なアプローチです。Lモードは、「内なる声」に関連付けられた線形、論理的、言葉によるアプローチです。
問題が手に負えないように見える場合、それはおそらくあなたが間違った思考モードを使用してそれを解決しようとしているためです。プログラマーの場合、デフォルトの思考モードはLモードである傾向があるため、一時的にオフにしてRモードにアクセスすると動作する場合があります。
Rモード思考にアクセスする方法
多くの方法がありますが、おそらくポアンカレ法(有名な数学者にちなんで命名)を試してください。
問題について知っていることをすべて書き留めてください。それのすべての簡単な側面(もしあれば)をすぐに解決します。残りの「ハード問題」リストから1つのアイテムを選択し、邪魔されたり邪魔されたりしない散歩に出かけます。
散歩中に問題を分析しようとせず、問題に関連する可能性のある興味深い画像や感覚を心をさまようと観察させてください。それらを合体させます。インスピレーションに襲われた場合、すぐに歩行を停止し、戻ってあなたが得た洞察を書き留めてください。
すべての問題に洞察が得られるまで、すすぎ、繰り返します。その後、洞察の調査を開始します。
本の推薦
また、実用的な思考と学習を読むことは、より良い問題解決者になるのに役立つかもしれません。(最近この本を参照しているようです...)
他の人に聞いて...
真剣に。最大のリソースは、隣に座っている人です。問題の答えを彼らに尋ねるのではなく、あなたの隣に座って、あなたに問題を説明させてください。
多くの場合、口頭でそれを解決します。
時には他の人が質問をしたり、精神的な水門の鍵を開ける詳細を指摘したりします。
最終的には、パペットを使用せずに頭の中で物事を言語化することを学び、問題の主要な詳細をより迅速に発見します。
そして、少なくとも他のすべてが失敗した場合、彼らはあなたが使用することを考えていなかったテクニックをあなたに示すことができるかもしれません。
実際、私の短い答えは「より多くの問題を解決する」です。しかし、ポイントは次のとおりです。本当に問題に集中し、あきらめないでください。StackOverflowなどに関するヘルプを求めないでください。(StackOverflowを読むことはもちろん大丈夫です!)ほぼ機能するソリューションが得られるまで一生懸命努力してください。そして、満足のいく解決策が見つかるまで続けます。
私にとって問題解決は2つのことです:
私の意見では、ポイント2は本当に重要です。なぜなら、問題に悩まされる時間が長くなるほど、思考を変えざるを得なくなるからです。また、問題解決により多くの時間を費やすことができ、スキルをさらに向上させることができます。;-)
ところで、エドワード・ド・ボノを読むことをお勧めします。私は主に物理学を勉強して問題解決能力を身につけましたが、彼の執筆は本当に興味深いです。
さて、私の問題解決ツールキットは次のとおりです。
これらのツールのほとんどは再帰的に適用できることに注意してください。
そして、私のアルゴリズムはこれです:
ステップ1.は難しい決定ですが、練習すればするほどより良い決定を下します。
ああ、私はほとんど最も重要な成分をほとんど忘れています:
プロセス全体について前向きに考えます。「XYZが問題を解決することを願っています」とは思わないでください。むしろ、「XYZが機能しない場合、YZXが問題の原因になり得ないことを知っており、ZYXが機能するかどうかを確認します。」問題を発見するプロセスがエレガントで有益なものになった場合、特に問題解決は時々楽しくなります。
同様に問題を特定するスキルの作業を開始します。解決する前に問題があることを認識しなければならない場合があります。学校では、生徒にはあまりにも多くの回答が必要であり、十分な質問がありません。
問題を解決するあなたの周りの人々を見つけて、彼らがそれについてどうするか尋ねてください。
間違っているように準備してください。それらをすべて自分自身で維持しても改善されず、役に立たなくなります。
ソフトウェアエンジニア向けのコンピュータサイエンス教育の主な利点は、抽象化を作成して理解できることです。抽象化を使用して、Stringクラスメソッドなどの一般的な機能を、より大きな問題に集中できる再利用可能なタイトなパッケージにカプセル化します。
抽象化を認識して作成することを学びます:
しかし最も重要なことは、抽象化によって、問題をより小さく管理しやすいチャンクに分割する方法を教えてくれることです。科学の背景と組み合わせると、それらのスキルを組み合わせることで、ノイズを切り抜けて問題の中心に到達できるエンジニアを作成できます。
科学的方法を使用して問題を解決する方法を学びます。
見つけるのが難しい問題が存在する実稼働アプリケーションのトラブルシューティングを行う場合、いくつかの変数を分離して除去するために、いくつかの変数を除去するために(非実稼働環境で)アプリケーションを実際にさらに壊すことが役立つ場合があります。
要約すると、コンピューターサイエンスの学位に必要なすべての物理学の選択科目や他の科学の選択科目から学んだ科学的方法は、これらの問題を一連のボランティアでプラセボと新薬試験を試しているかのように解決するのに役立ちます。時にはそれを改善するために何かを悪化させなければならない科学者のように、時にはエンジニアとして同じことをしなければなりません。
この方法で科学的に考えることは、一般に、科学の背景での経験からのみ得られます。問題を解決することは、AからBへの線形パスとして認識できない場合があります。
つまり、コンピューターサイエンスを研究し、他の科学分野を研究し、関数型プログラミングを学びます。これらは、あなたが科学者のように考え、枠外で考えるのに役立ちます。
あなたが探しているのは、コンピュータサイエンスのヒューリスティックです。
私たちの99%がtrenchで何をするかということになると、太陽の下で本当に新しいものは何もありません。そのため、問題が表示され、DPの問題、またはメモ化などの恩恵を受ける可能性のある別の問題として認識される場合があります。
この知識をどのようにして得ますか?適切なCS学位は、始めるのに適した場所です...ソフトウェア工学や情報システムではなく、ほとんどの学部生が「実用的ではない」と文句を言うものです。
あなたは自分でこれを行うことができますが、おそらくもっと難しいでしょう。これらの2つのコースから始めます。
私の答えは特にコーディングに関連していますが、あらゆるものに適用できます。
練習の面では、私が何をするかを伝えることができます。私はプログラミングよりも応用数学に興味がありますが、コンピューティングに適用される応用数学は一種のプログラミングです。私は周りに問題と解決策を見ています。既知のソリューション(または既存のコードライブラリ)にリンクする前(または私の仕事にタイムリーなソリューションが必要な場合など)に、「これが未解決の問題である場合-つまり、見つけることができません」缶詰のソリューション、どのように進みますか?」答えがやや簡単な場合は、ソリューション(分析、またはそれを解決するコンピュータープログラム)の作成を検討してください。複雑なエンドケースを無視します。既存のライブラリを再発明するのではなく、アプローチとアルゴリズムの調査に興味があります。ソリューションに多大な労力が必要な場合は、ソリューション全体をプログラムしないでください。少なくとも、使用したいデータ構造とメソッドの種類について考えてください。他の方法も考えてください。
これには素晴らしいSOの質問があります。
私の答えは:
改善する最善の方法は練習することです!
RSSフィード(http://www.mensa.org.uk/puzzles/)を購読し、出てきたら完成させるのに時間をかけます。
パズルデイデスクカレンダー(例:http : //www.calendars.com/product.asp? PID=1&MGID=-1&IID=46387&cm_mmc=Affiliate_Program--performics--k137666-_-DDI% 20Link)定期的な、一口サイズの、さまざまな問題を解決できるので、アイデアも。
これらは常にあなたが直面している問題から話題から外れますが、多様性はあなたが今までにない方法で考えることを強いるので重要です。
編集:また、http://www.mindtools.com/pages/main/newMN_TMC.htmで問題解決のヒントを確認してください。
チェスをする
チェスは、プログラミングの問題を解決するための優れたトレーナーです。問題の層と論理ツリーは非常にうまく関連しています。また、次善策をたどって時間を無駄にする前に、先を考えて計画を立てるのにも役立ちます。
チェスには、左右の「思考モード」のバランスも必要です。分析的になりすぎると、すべてを計算しようとして動けなくなる可能性がありますが、これは不可能です。ただし、クリエイティブなインスピレーションはすべて、計算によって確認し、状況の具体的な現実に適合するようにする必要があります。難しい問題はこのようなものです。
チェスは、研究と実践が非常に直線的な方法で確実な改善をもたらす方法を示しています。これは、プログラムの問題解決にも当てはまります。
チェスをすることは、学ぶべきことがどれだけあるかをよく理解するのにも役立ちます。あなたは10年間プログラミング(またはチェス)を行っていますが、あなたはまだグランドマスターではありません。
最近、プロジェクトオイラーで問題を解決しています。問題の難易度はさまざまです。通常、ソリューションには大量のコードは必要ありませんが、アルゴリズムの実行時など、多くの要因を考慮する必要があります。答えを入力するだけで、好きな言語を使用できます。多くの問題に対する最適なソリューションの良い説明と、各問題に関する多くの議論があります。毎日1つの問題を解決しようとすると、問題の解決と分析がどれほど改善されるかに驚くでしょう。追加のクレジットとして、手続き型言語(C ++など)、スクリプト言語(pythonなど)、関数型言語(F#など)など、多くの言語で同じ問題を解決してみてください。
私は科学のバックグラウンドから来ているので、問題を見るとき、私は科学的方法からの戦術を使う傾向があります。私は特に仮説に基づいて「実験」を設定し、「コントロール」を使用するのが好きなので、何かを構築し、それについて1つだけを変更/追加し、その1つの変更/追加の結果が何であるかを確認します必要な結果が得られない場合は、元に戻して別のものを変更します。これは、コードのトラブルシューティング/デバッグに適しています。時々、求めている答えが得られますが、失敗した場合でも常に新しいことを学びます。還元主義を通して学ぶことも好きです-既に存在するもの(常に理解できないかもしれないものから始めるのは良いことですが、動作することは知っています)を見て、私には複雑に見えます。問題に総合的に取り組むよりも、脳がこのような学習を処理する方が簡単な場合があり、その知識を使用して他の同様の複雑なものを自分で構築できます。また、論理と推論に関する本を読んで、古典思想家と現代思想家の両方から作品を選ぶことをお勧めします(アリストテレスから始めて、あなたのやり方を練り上げてください)。それらは、コンピューターの問題解決に役立つ基本的なロジックの基礎の一部を提供します。そして、もちろん、問題を解決できず、しばらくその問題に取り組んでいる場合は、頭を休めてください。問題の特定の側面に反論することは、有害な場合があります。誰もが休憩が必要です:)
問題解決の最も難しい部分は「知覚的狭小化」です。
問題のように見えるものを選び、疲れ果てて何も進まなくなるまで、後を追って行きます。
これを行う方法は、確実に-絶対に-あなたが本当に問題を理解することです。「正しい問題の解決」は、問題解決の最も重要な部分です。
時々彼らはこれを「箱の外で考える」と呼びます。「ボックス」は、実際の根本的な問題を含まない可能性がある狭い視点です。枠を超えて考えることは、解決すべき適切な問題を探すことです。
間違った問題に早期に焦点を絞ることに伴う狭小化を回避するための戦略に関する多くの本があります。
ほとんどのトリックは、実際の結果がどうなるかを特定することです。次に、その望ましい結果をブロックするものを見つけます。
正直に言って、誰もが違うと思うので、誰もがより良い問題解決者になるためのロードマップは異なります。他の人の経験から学ぶことができますが、最終的にはあなた自身の道を築かなければなりません。これは本質的に何かを「難しい方法」で学習することですが、この場合は効果的です。
ここに私が問題解決を改善し始めた方法がありますが、私はまだ素晴らしい問題解決者ではありませんが、昨年よりも良いものです。私は、管理用の3つの新しいレポートを追加することにより、オープンソースの時間追跡ソフトウェアを拡張することを含む新しいプロジェクトを仕事で受け取りました。このソフトウェアは、私が使用したことがない言語で書かれており、文書化が不十分で、難読化されていました。掘り下げて大量の研究を行い、基本的な機能が揃ったらそれらを改良し、最終的にさらに機能を追加しました。
つまり、言い換えれば、何らかの実世界のプロジェクトを見つけて作業することをお勧めします。現在プログラマーとして雇用されている場合は、プロジェクトを見つけるか、上司に依頼してください。このシナリオが仕事の外、おそらく契約/フリーランスの仕事か何かを見つけることができない場合。必要に応じて問題を非常に迅速かつ迅速に解決し、プロジェクトの強度のためにその知識を保持します。これがうまくいかない場合は、このスレッドの他の全員が提案していることを行ってください:)。
プログラマーは、お気に入りのプログラミング言語で問題を解決する方法を視覚化することで、問題を精神的に攻撃するのは簡単です。彼のお気に入りの道具がハンマーであるとき、すべての問題を釘として見る古典的な大工のように。
実践的なレベルを超えて、「これが最適な方法でそれを解決するために必要なものだ」と考えるだけで、問題解決の最良の練習ができると思います。ソリューションを適用するために(多くの)新しいことを学ばなければならない場合もありますが、重要な点は、ソリューションを解決する能力が歴史的および既存の手法に限定されるべきではないということです。
私にとって古い実用的な例は、通常はすべてのミューテックスを叩いてコンフォートゾーンのすぐ前に行っていたとしても、問題が実際にプリエンプティブスレッドを必要としないことに気付いたときに、効率的な協調マルチタスクを実装する方法を学びました最終的には常にある時点で快適にならないように思われます。
アプリケーション開発において、私たちが直面している問題の多くは、私たち自身の発明か、コードベースを台無しにした相続人の発明のどちらかです。問題を解決することは、ほとんどの場合、ソースを見つけることになります。多くの場合、問題が発生している場所を見つけたら、それを解決するために必要なのは単なる能力だけです。
そのために:
世界のすべての脳トレーニングは、脳が使用するための情報なしでは役に立たない。問題を解決するためには、まず可能性が何であるかを知る必要があります!それでも、問題の説明だけでなく、優れた情報を扱う方がはるかに迅速です。
何かが実行に時間がかかりすぎる理由について、牛が帰ってくるまで推測するかもしれません。しかし、「最初にデータを取得する」と言うと、非常に多くの例外がスローされていることがわかり、代わりにifステートメントに変更できることに気付くかもしれません。情報を収集する方法を知らずに、私のプラットフォームでは例外にかなりのオーバーヘッドがかかること、そしてそれを試す前にチェックする方法があることを知っていれば、問題を解決することはできません。
答えには2つの部分があります。
a)実際の問題解決のためのテクニック
b)思考と問題解決においてあなたの脳を本質的に「より良く」する
テクニックには常に素晴らしい答えがあります(問題などを知っていると仮定してください)ので、私はそれをあまり取り上げません。脳のトレーニングに関しては、これらのシナプスを通過して相互接続を構築するためにできることがいくつかあります
1)新しい言語、本物の言語を学ぶ(フランス語、中国語などが最近は良い方法かもしれません)
2)新しい楽器の演奏を学ぶ
3)ペイント、ドロー、彫刻などの芸術的なことをする
4)スクラブルをプレイするか、クロスワードをする
5)あなたがそれを意味するようなダンス。いいえ、冗談ではありません。ダンスはあなたの脳と思考に影響を与えることが示されています
6)あなたの経験を広げ、革新的な解決策は、ある分野で理論を別の分野に適用することから生まれたので、あなたが面白いと思うさまざまな分野や分野を研究する
7)運動、運動は思考プロセスを改善するために非常に重要です
最後に、難しい問題を解決するための最善のヒントを提供します。長い散歩をします。私はそれがあなたの頭をきれいにし、問題を熟考させるために奇跡を起こすことがわかった
私のアドバイスは、本を捨てることです!
もちろん、文字通りではありません。つまり、既存のソリューションについて学習せずに、経験の少ないトピック領域に参加し、そこで難しい問題を解決します。あなたの創造性と批判的思考、そしておそらくリファレンスマニュアルだけに頼ってください。
画像フォーマットを設計することもできます。またはWebサーバー。または圧縮スキーム。ファイルシステム。カーネル。人工知能。プログラミング言語。コンピュータビジョンシステム。
あなたが面白いと感じるもの、それはかなり複雑であり、あなたが決して学んだことはありません。それについて読んではいけない。ただまっすぐに飛び込む。実験。間違えます。車輪を再発明します。
助けを求めないでください。チュートリアルは避けてください。理論から離れてください。棚からソリューションをプルしないでください。
どうして?
何回か試してみて、達成したことに満足したら、数か月そのままにしてください。その後、新たに戻って、新しい視点を見つけることができるかどうかを確認します。その後、問題と、他の人がどのようにそれを解決したか(または人々と話すか)について読み始めます。この時点で、読みながら「はい、それは理にかなっている」と言う代わりに、「はい、正確に」、「まあある程度」、または「すごい、賢い」と言います。
言い換えれば、読んだものについてもっと批判的に考え、それを添付する大きな「メンタルフレームワーク」をすでに持っているので、あなたはそれを理解し、覚えるのがはるかに簡単であることに気付くでしょう。独立して発見したものに満足し、たくさんの新しい知識を持ち帰ります。
ソリューションを完璧にしようとしないでください。問題を解決できることを自分自身に証明してください。「できる」という態度を採用し、問題に気が進まない場合は、最初にそれを解決した人がおそらくあなたと同じくらい知っていたことを覚えておいてください(実際、彼らはそれが解決策を持っていることを知りませんでした!)
問題解決は、読むことで教えたり学んだりできるものではありません。問題を解決するための唯一の方法は、問題を解決することです。
問題解決のためのさまざまな手法と方法論があり、特定のドメインの問題を解決するために使用できるツールとテクノロジーについて読むことができます。常に問題について考え、解決策を考え出さない限り(すべての問題に対して複数の解決策を考え出し、それらを相互に評価する)、次に他者が開発した解決策に対してあなたの解決策を評価しない限り、問題が良くなることはありません解決します。
Pragmatic Thinking and Learning:Refactor Your Wetware by Andy Huntのコピーをお勧めします。それは、あなたがどのように考え、反応し、学ぶかを理解することに関する本です。行動理論やその他の認知科学から関連する理論を取り入れています。これは特にソフトウェア開発者向けですが、あらゆるナレッジワーカーに適用できます。
私のようなプログラミングの初心者には、「Think Like a Programmer」という本をお勧めします。最初の章では、あなたが知っていることから始めて、削減し、類推し、実験することで、問題の修正と分割などの問題解決技術を扱います。
次に、C ++の例を使用したより高度な手法があります。配列、ポインター、動的メモリ、クラス、再帰、コードの再利用に関する問題を解決します。この部分についてはまだコメントしきれないのでコメントできません。
理論にとらわれないで、もっと練習してください。練習には経験が必要です。