web-dev-qa-db-ja.com

コーディング時に麻痺を克服するにはどうすればよいですか?

新しいプロジェクトを始めるとき、すぐに実装の詳細について考えることがよくあります。 「DataBaseHandlerはどこに配置しますか?どのように使用しますか?それを使用したいクラスはいくつかの抽象スーパークラスから拡張する必要があります。インターフェイスを使用する必要がありますか?含むクラスで使用する抽象化のレベルリクエストを送信してデータを解析する方法は?」

拡張性と再利用性のためにコーディングしたいので、長い間行き詰まってしまいます。しかし、完全に実装する方法について考え過ぎることはほとんど不可能だと感じています。

そして、「ねじって、完成させてください!」とだけ言うと、コードが整理されていない、抽象化のレベルが混在しているなどの理由で、すぐにレンガの壁にぶつかりました。

新しいプロジェクトを立ち上げながら、拡張性の高い論理的/モジュール構造をセットアップするためのテクニック/方法は何ですか?

--編集--

さて、これはすでに回答を受け入れるのが難しいタイプの質問ですが、さらにフィードバックを得たいと思っています。コンセンサスがあるかどうかを確認してください。 TDDは本当にクールに聞こえますが、率直に言って、私はJUnitの使用などに慣れるようにしています。同時に、TDDのファンが、TDDに関する1つの正当なポイントが私の問題を解決するという事実についてどう思いますか特定の問題は、TDDが設計の問題に実際に対処していないように見えることです。確かに、TDDが私がやりたいことを定義するのに役立ち、それからその方法を段階的に進めることができることに同意しますが、すべてユニットテストを通過できるさまざまな全体的なデザインパターン/構造があります。それだけです。単一のUNITSをテストします。少し混乱しているようですが……。多分私はいくつかの魔法の式を理解しようとしてさらに先延ばしにしようとしているだけかもしれませんが、ベテランの何人かがこの領域にどのようにアプローチしているか聞きたいです...

ありがとう!

37
LuxuryMode

Test-Driven-Development を使用することをお勧めします。特に、Eclipseなどの優れたIDEを使用する場合)には慣れる必要がありますが、利点は非常に大きくなります。

基本的には、コード自体を記述する前に、コードにテストを記述します。そのため、コードの使用方法の観点からコードを確認する必要があります。つまり、実装するシナリオが増えるほど、インターフェイスが進化します。

もう1つの特徴は、非常に小さなチャンクで実装することです(テクニックやプログラミングで経験を積むほど大きくなります)。そのため、毎回非常に小さく明確な問題に集中する必要があります。

また、最初にテストを作成してから実装するだけなので、失敗したテストが目の前にあります。したがって、ほとんどのプログラマーのようであれば、「このテストを機能させる必要がある」と考えるので、狂った分析に夢中にならないでしょう。

短いJavaの例:
たとえば、データベースからメッセージを読み書きするプログラムを開発したいとします。

だから私は最初の明確に定義されたアクションから始めます、私はDBが必要です:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
}

さて、ここでは、DBを返すようにDbConnector.getDBクラスを実装する必要があることがわかります。それまでは、このテストは失敗します。私は行ってそれをします...

次の処理を追加するのではなく、DBからメッセージをロードします。

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
}

今度は、メッセージをフェッチするという別の小さな機能をDBに追加しました。それを実装します。終了したら、次のようなものに到達するまで、一度に1つの機能に進みます。

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
  message = "foo bar";
  db.storeMessage(message);
  message = db.fetchMessage();
  assertEquals("foo bar", message);
}

非常に単純な例のように見えるかもしれませんが、これはより複雑なタスクでも機能します。最初は非常に時間がかかることを知っていますが、慣れるにつれて、実際にははるかに効率的であることがわかります。 1つは分析による麻痺を避け、もう1つははるかに堅牢なコードを取得するため、通常はバグが少なく、反復が少なくなります。

16
Asaf

これは私に起こったので、私は継続的なリファクタリングの考え方を受け入れる(そして受け入れる)習慣になりました。機能する可能性のある最も単純なものを作成し、それを整理し、整理し、分離し、テストして、次に進みます。

計画があまり進んでいないと言っているわけではありませんが、スクラップや私の頭の中の落書きとして非常に迅速かつ頻繁に発生します。全体として、私は時々この小さなプロセスをマイクロ反復と呼んでいます。なぜならそれらはそれぞれ5-20分かかり、経験から、私が取り組んでいるものを完了するのに2-3かかります(私が作っているものにもよりますが)。

余談ですが、私は多くの人々をさまざまな形式の書面(レポート、エッセイ、テクニカルライティング全般)で指導してきました。これは、作者のブロックを克服するために物事を書いてもらうのと同じ方法です。 「ページ上で頭に浮かぶトピックについてぼかしてください。それから私たちはそれを理解し、すべてを段落に分けてフローをチェックします。必要に応じて、書き直します。」

10
Steven Evers

うまくいくかもしれないいくつかのこと:

  • 解決しようとしている中心的な問題を特定します-やりたいことの核心は何ですか?それだけを実装し、それを実行するための最小限のサポートコードを実装します。満足のいく結果が得られたら、繰り返し作成し、各ステップで容赦なくリファクタリングします。
  • 他のプログラミングパラダイムがうまくいくかどうかを確認してください。そのすべてのメリットにもかかわらず、オブジェクト指向プログラミングはすべての問題に対する答えではなく、すべてのプログラマの頭脳がそのように機能するわけではありません。 (純粋な)関数型言語を選択します。いくつかの手続き型コードを記述します。ハードウェアレベルに潜り込み、Cやアセンブラを実行します。 etc.心を揺さぶる可能性のあるいくつかの言語(現在C++/Java/C#/ VB/...)のようなものを使用していると仮定します) :Haskell、ML、LISP(さまざまな方言から選択できます)、Erlang、Prolog、Smalltalk、Javascript(Javaのように動作させ、代わりにそのクロージャの性質を採用することを試みた場合)) 、C、Pascal、awk、そしておそらくさらに多くの機能です。重要な機能は、現在使用しているものとは大きく異なる必要があるということです。これは、多くの問題が発生している大きなプロジェクトで実行したいものではありませんが、サイドプロジェクト(個人または仕事関連)の場合、新しい洞察が得られます。
  • 根本的に異なる設計方法を使用します。別の角度からデザインをピックアップできるかどうかを確認します。私は通常、クラスをレイアウトすることから設計を始めると思います。変更のためのデータ構造から始めますか?または、UIを最初に設計して、文字どおり入力フォームを描画してから機能を設計するのはどうですか?
2
tdammers

多くの設計上の決定については、使い捨てのプロトタイプにコーディングすることにより、いくつかのアーキテクチャまたは設計オプションを探索できる、短時間の限られた研究努力である「スパイク」を実行するのに役立ちます。たとえば、いくつかのオープンソースライブラリの使用方法や、クラスとインターフェイスの編成方法を探ることができます。最初の方法では不十分な場合に別のアプローチを試すことができるように短くしておくことです。うまくいけば、アーキテクチャの決定を下したり、コンセプトを証明したりするために十分な知識を得ることができます。演習自体は、必ずしも「ライターブロック」から抜け出すのに役立つ即時コーディングを含みます。

その後、Asafが言及したTDDまたはBDDアプローチを使用してプロジェクトの実装を進めることが有益です。

1
Turnkey

あなたはそれを必要としないでしょう なので、最初はあまり考えないでください。

より多くの時間をかけて定義し、目標と問題を理解します。

「拡張性と再利用性」は、適切に作成されたソフトウェアプログラムのライフサイクルの自然な結果です。

1
9dan

私たちは中規模のプロジェクトを検討していると仮定します。
私は、最初に設計図に行くことから始めます。これを行う前に、機能要件と非機能要件を準備しておく必要があります。最初にソフトウェアアーキテクチャを考え出します。つまり、要件に合うアーキテクチャパターンを調べます。
アーキテクチャの外観を決定したら、低レベルの設計に入る必要があります。つまり、すべてのエンティティ、クラス、機能を調べます。ここでは、再び適合するパターンを特定します。その過程で、基本クラスとは何か、そして必要なインターフェースがわかります。
その後、フレームワークを構築し、いくつかの簡単なテストを実行して、これが機能以外のすべての要件を満たしているかどうかを確認できます
次に、@ Asafが示唆したように、テスト駆動開発を行います。

覚えておいてください。設計とアーキテクチャに十分な時間を費やしているにもかかわらず、必要が生じた場合は常にアーキテクチャを再検討する用意があります。

0
hangar18

これは素晴らしい質問だと思います。誰にとっても何もうまくいきません。私はそのような麻痺はあなたの分野でますます有能になることの自然な副産物だと思います。とは言っても、私が役立ついくつかのことを次に示しますが、問題は解決しません。

  • あなたの初期のプロジェクトを脇に置いて、曖昧なバージョンで作業してください。これはあなたがあなたに言うバージョンです:a。コードはきれいであるはずがありません。実際、大規模なリファクタリングと再フォーマットは許可されていません。それを完全に組織化せず、優れたコーディングの束縛から解放してください。 b。それだけで動作します。 c。他のすべての懸念を捨てるとき、問題の領域について私が何を学ぶかは常に驚きます。私はまた、多くの場合、より賢明な方法で適切なデザインにたどり着くのに役立つ小さな一口になってしまいます。

  • コンピューターを使わずに、プロジェクトの進行中に適切なサイズの時間を確保します。あなたが実際に達成しようとしていることを概念化し、OO /デザインパターンの狂気を超越する魔法の禅を探してください。

0
Kevin Hsu

私は通常、ゼロから始めて、可能な限り最も単純なプロトタイプを作成し、何かを実行します。プロトタイプを使用して、ハッピーパステストケース、インターフェイスを駆動するテストケースをリバースエンジニアリングしてから、テストカバレッジの構築に役立つ前後の契約について検討します。

問題が完全に理解されるまで、抽象化、最適化、または検証について心配する必要はありません。

0
sbrenton

あなたの考えに具体的な表現を与えてください:それらを書き留める/タイプする、それらを引き出すなど。これは、必要に応じて考えを再検討するのに役立ちます。それはあなたが輪になって行くのを止めます。より明確に考えるのに役立ちます。

自分がどこにも行かず、どこにでも何かを考えているのを見るときはいつでも、私はそれらをタイプするので、はっきりと考えることができます。

0
Srisa