ソフトウェア工学

システム開発ライフサイクル内で働く専門家、学者、学生向けのQ&A

6
ソースコードの記述中に80文字の制限のベストプラクティスに従う方法
だからあなたが知っているように言ってベストプラクティスがあります ソースコードの行を80文字に制限します。 2つのリンクがあります。 80文字がコード幅の「標準」制限であるのはなぜですか? ワイドスクリーンモニターの時代には、80文字の制限がまだ関係していますか? そして、このベストプラクティスを検索すれば、もっとうまくいくと思います。 しかし、これは非常に難しいと思います。サンプルの例を次に示します。 public class MyClass { public void myMethod() { final Map<String, List<MyInterfaceHere>> myReference したがって、各クラスと各メソッドと各ステートメントをインデントします。 そして、「myReference」にある最後の「e」の終わりまでに、すでに列60にいます。 私は実際にコンストラクタを呼び出して、私が持っている参照にオブジェクトを割り当てるために20個のスペースが残っています。 私はこれが本当に良く見えることを意味します: public class MyClass { public void myMethod() { final Map<String, List<MyInterfaceHere>> myReference = new HashMap<String, List<MyInterfaceHere>>(); ここでのベストプラクティスは何ですか?

3
長時間実行される未リリースコードのGit分岐戦略
私たちのチームでは、個々の作業単位(ストーリー)に加えて、より長時間実行される作業テーマ(叙事詩)があります。複数のストーリーが壮大です。 従来、各ストーリーに機能ブランチがあり、それらがQAに合格したときにそれらを直接マスターにマージしました。ただし、Epicが「機能完了」と見なされるまで、Epicで完了したストーリーのリリースを控えたいと思います。これらの機能は、Epic全体が閉じられたときにのみ本番環境にリリースされます。さらに、ナイトリービルドサーバーがあります-すべての閉じられたストーリー(不完全なEpicsの一部を含む)がこのナイトリーサーバーに自動的にデプロイされるようにします。 これを達成するためのレポの管理方法に関する提案はありますか?「エピックブランチ」を導入することを検討しました。ここでは、クローズドストーリーをマスターに直接ではなく、関連するエピックブランチにマージしますが、私の懸念は次のとおりです。 壮大なブランチを長時間開いたままにしておくと、マージの競合が心配です ナイトリービルドでは、すべてのエピックブランチを「ナイトリービルド」ブランチにマージする必要があります。繰り返しますが、マージの競合が発生する可能性があり、これは自動的に行われます

8
例外をスローするコンストラクターでエラーを記録する必要がありますか?
私は数か月間アプリケーションを構築していましたが、次のようなパターンが明らかになりました。 logger.error(ERROR_MSG); throw new Exception(ERROR_MSG); または、キャッチする場合: try { // ...block that can throw something } catch (Exception e) { logger.error(ERROR_MSG, e); throw new MyException(ERROR_MSG, e); } したがって、例外をスローまたはキャッチするたびに、ログに記録します。実際、それはアプリケーションで行ったほとんどすべてのロギングでした(アプリケーションの初期化のための何かに加えて)。 それで、プログラマーとして、私は繰り返しを避けます。そこで、ロガー呼び出しを例外構築に移動することにしました。そのため、例外を構築するたびに、ログが記録されます。確かに、私のために例外をスローするExceptionHelperを作成することもできますが、それはコードの解釈を難しくし、さらに悪いことに、コンパイラはそれをうまく処理できず、そのメンバーへの呼び出しがすぐに投げます。 それで、これはアンチパターンですか?もしそうなら、なぜですか?

2
std :: exceptionから派生/継承する必要がありますか?
私の最初の「深刻な」C ++ライブラリを設計するとき、私は次のことを自問しています: 例外を派生させるのは良いスタイルstd::exceptionですか?それは子孫ですか?! 読んだ後でも 例外クラスの設計 ライブラリに実装する「良い数」の例外とは何ですか? まだわかりません。というのは、一般的な(ただし、良くないかもしれない)プラクティスに加えて、ライブラリユーザーとしてstd::exception、ライブラリ実装で標準ライブラリ関数が失敗した場合にのみライブラリ関数がs をスローし、それについて何もできないと仮定するからです。しかし、それでも、アプリケーションコードを記述するとき、私にとっては非常に便利であり、また、単にをスローするだけでも見栄えが良いstd::runtime_errorです。また、私のユーザーは、定義された最小限のインターフェース(what()コードやコードなど)に依存することもできます。 また、たとえば、ユーザーが誤った引数を指定した場合、をスローするよりも便利なのは何std::invalid_argumentですか?だから、std :: exceptionのまだ一般的な使用と組み合わせて、他のコードで見ます:さらに進んで、カスタム例外クラス(例えばlib_foo_exception)から、そしてから派生してみませんかstd::exception。 考え?
15 c++  exceptions 

4
APIと関数型プログラミング
Clojureなどの関数型プログラミング言語への(明らかに限定された)経験から、データのカプセル化はそれほど重要ではないようです。通常、マップやセットなどのさまざまなネイティブタイプは、オブジェクトよりもデータを表すための優先通貨です。さらに、そのデータは一般に不変です。 たとえば、この件に関するインタビューで、Clojureの名声のRich Hickeyからの有名な引用の1つを次に示します。 Fogus:その考えに従うと、Clojureがそのタイプでデータ隠蔽のカプセル化を行わないという事実に驚く人もいます。なぜデータ隠蔽をやめることにしたのですか? ヒッキー:Clojureがプログラミングを抽象化に重点を置いていることを明確にしましょう。ただし、ある時点で、誰かがデータにアクセスする必要があります。また、「プライベート」という概念がある場合、それに対応する特権と信頼の概念が必要です。そして、それは非常に多くの複雑さと小さな価値を追加し、システムに硬直性をもたらし、しばしば物を本来あるべきでない場所に住まわせます。これは、単純な情報がクラスに入れられるときに発生する他の損失に追加されます。データが不変である限り、誰かが変更される可能性のあるものに依存するようになる可能性があることを除いて、アクセスを提供することによってもたらされる害はほとんどありません。まあ、大丈夫、人々は実際の生活の中で常にそうしていて、物事が変わると適応します。そして、それらが合理的であれば、彼らは、将来変化する可能性のある何かに基づいて決定を下すときを知っています。だから、それはリスク管理の決定であり、プログラマは自由にすべきだと思う。抽象化に向けてプログラミングを行い、実装の詳細と結婚することを警戒したいという感覚がなければ、優秀なプログラマーになることは決してありません。 オブジェクト指向の世界から来て、これは私が長年にわたって学んだ神聖な原則のいくつかを複雑にするようです。これらには、情報隠蔽、デメテルの法則、統一アクセス原則などが含まれます。カプセル化という一般的なスレッドにより、他の人が触れてはいけないことを知るためのAPIを定義できます。本質的に、一部のコードのメンテナーがコンシューマーのコードにバグを導入する可能性を心配することなく、自由に変更やリファクタリングを行えるようにするコントラクトを作成します(オープン/クローズ原則)。また、他のプログラマーがそのデータを取得または構築するために使用できるツールを知るための、クリーンで精選されたインターフェースを提供します。 データへの直接アクセスが許可されると、そのAPIコントラクトは壊れ、カプセル化の利点はすべてなくなるようです。また、厳密に不変のデータは、ドメイン固有の構造(オブジェクト、構造体、レコード)の受け渡しを、状態とその状態で実行できる一連のアクションを表すという意味であまり役に立たないようです。 APIを定義する必要があり、多くの開発者がシステムの特定の部分の操作に関与するなど、コードベースのサイズが巨大になったときに発生するように思われるこれらの問題に、機能コードベースはどのように対処しますか?これらのタイプのコードベースでこれがどのように処理されるかを示すこの状況の例はありますか?

6
戦略パターンの利点
if / thenの場合にコードを書くことができるのに、なぜ戦略パターンを使用するのが有益なのですか? 例:TaxPayerクラスがあり、そのメソッドの1つが異なるアルゴリズムを使用して税金を計算します。では、なぜif / thenケースを持ち、戦略パターンを使用する代わりに、そのメソッドで使用するアルゴリズムを見つけられないのでしょうか?また、なぜTaxPayerクラスの各アルゴリズムに個別のメソッドを実装できないのですか? また、実行時にアルゴリズムが変更されるとはどういう意味ですか?

4
OOPアプリケーションでのパラメーター管理
OOPの原則を実践する方法として、C ++で中規模のOOPアプリケーションを作成しています。 私のプロジェクトにはいくつかのクラスがあり、それらのいくつかはランタイム構成パラメーターにアクセスする必要があります。これらのパラメーターは、アプリケーションの起動時にいくつかのソースから読み取られます。ユーザーのhome-dirにある設定ファイルから読み込まれるものもあれば、コマンドライン引数(argv)であるものもあります。 そこで、クラスを作成しましたConfigBlock。このクラスは、すべてのパラメーターソースを読み取り、適切なデータ構造に格納します。例としては、構成ファイルまたは--verbose CLIフラグでユーザーが変更できるパスとファイル名があります。次に、ConfigBlock.GetVerboseLevel()この特定のパラメーターを読み取るために呼び出すことができます。 私の質問:このようなすべてのランタイム構成データを1つのクラスに収集することをお勧めしますか? 次に、クラスはこれらすべてのパラメーターにアクセスする必要があります。私はこれを達成するためのいくつかの方法を考えることができますが、どの方法を取るべきかはわかりません。クラスのコンストラクターは、次のようにConfigBlockへの参照を指定できます。 public: MyGreatClass(ConfigBlock &config); または、CodingBlockの定義を含むヘッダー「CodingBlock.h」を含めるだけです。 extern CodingBlock MyCodingBlock; その後、クラスの.cppファイルのみがConfigBlockのものを含めて使用する必要があります。 .hファイルは、このインターフェイスをクラスのユーザーに導入しません。ただし、ConfigBlockへのインターフェイスはまだありますが、.hファイルからは隠されています。 このように隠すのは良いですか? インターフェイスをできるだけ小さくしたいのですが、最終的には、構成パラメーターを必要とするすべてのクラスがConfigBlockに接続する必要があると思います。しかし、この接続はどのように見えますか?

1
配列の要素数を計算するために、sizeof(TYPE)よりもsizeof(element)を好むのはなぜですか?
私は「キングKNのCプログラミング」を読んでいて、次の文を見つけました。 式sizeof(a)/sizeof(a[0])を使用して配列内の要素数を計算することについて説明しました。式sizeof(a)/sizeof(t)(tはaの要素の型)も機能しますが、劣った手法と見なされます。 なぜそれが劣った技術と見なされるのですか?
15 c  array 

2
基本クラスのテストを回避しても大丈夫ですか?
かなり汎用的である必要がある柔軟性/抽象化を与えるために、かなりの量の「メタプログラミング」を持つ基本クラスがあります。 基本クラスの共通メソッドを使用するサブクラスが多数あり、各サブクラスのすべてのケースをカバーする動作指向の単体テストがあります。 基本クラスのテストをスキップしても大丈夫ですか?

1
Consumer / ProducerとObserver / Observableの違い
私は、次の3つの部分で構成されるアプリケーションの設計に取り組んでいます。 特定のイベントの発生(ファイルの作成、外部リクエストなど)を監視する単一のスレッド これらのイベントを処理することでこれらのイベントに応答するN個のワーカースレッド(各ワーカーは単一のイベントを処理して消費し、処理に時間がかかる場合があります) これらのスレッドを管理し、エラー処理を行うコントローラー(スレッドの再起動、結果のログ記録) これは非常に基本的で実装するのは難しくありませんが、それを行うための「正しい」方法は何だろうと思っています(この具体的なケースではJavaですが、より高い抽象化の答えもありがたいです)。2つの戦略が思い浮かびます。 Observer / Observable:監視スレッドはコントローラーによって監視されます。イベントが発生した場合、コントローラーに通知され、再利用可能なキャッシュスレッドプールから新しいタスクを空きスレッドに割り当てることができます(または、すべてのスレッドが現在ビジーである場合、FIFOキューでタスクを待機してキャッシュします)。ワーカースレッドはCallableを実装し、結果(またはブール値)で成功を返すか、エラーを返します。その場合、コントローラーは何をすべきかを決定します(発生したエラーの性質に応じて)。 プロデューサー/コンシューマー:監視スレッドはコントローラーとBlockingQueueを共有し(イベントキュー)、コントローラーはすべてのワーカーと2つを共有します(タスクキューと結果キュー)。イベントの場合、監視スレッドはタスクオブジェクトをイベントキューに入れます。コントローラーは、イベントキューから新しいタスクを取得し、それらをレビューして、タスクキューに入れます。各ワーカーは新しいタスクを待機し、タスクキュー(先着順、キュー自体で管理)からそれらを取得/消費し、結果またはエラーを結果キューに戻します。最後に、コントローラーは結果キューから結果を取得し、エラーが発生した場合に対応する手順を実行できます。 両方のアプローチの最終結果は似ていますが、それぞれわずかな違いがあります。 オブザーバーを使用すると、スレッドの制御は直接行われ、各タスクは特定の新しく生成されたワーカーに割り当てられます。スレッド作成のオーバーヘッドは高くなる可能性がありますが、キャッシュされたスレッドプールのおかげではありません。一方、Observerパターンは、複数ではなく単一のObserverに縮小されます。これは、厳密に設計されたものではありません。 キュー戦略は拡張が容易なようです。たとえば、1つではなく複数のプロデューサーを追加するのは簡単で、変更を必要としません。欠点は、作業をまったく行わない場合でも、すべてのスレッドが無期限に実行され、エラー/結果の処理が最初のソリューションほど洗練されていないことです。 この状況で最もふさわしいアプローチは何ですか?その理由は?ほとんどの例は、Observerケースの新しい値で多くのウィンドウを更新したり、複数のコンシューマーとプロデューサーで処理したりするなど、明確なケースのみを扱っているため、この質問に対する答えをオンラインで見つけるのは難しいと感じました。どんな入力でも大歓迎です。

5
ユーザーが機能だと思ったバグをどのように処理しますか?
質問: エンドユーザーが機能だと思ったバグに対処する適切な方法は何ですか? 精緻化: かなりの割合のユーザーが機能として期待している場合、より安定させるために「未修正」または「修正済み」のままにしておくべきだと思いますか?ただし、ユーザーのごく一部が0.1%または1%などの機能であると期待している場合は、このバグを修正する必要があります。 理論的には、これはマイナーなバグ修正であるため、セマンティックバージョニングで考慮されるようにPATCHとして認定できます:xyZ それが文書化されている限り、(機能として意図されていないので)PATCHとしてまだ資格がありますか? 編集:この特定のケースでは、他の開発者が使用する内部使用ライブラリのAPIのバグです。

3
クライアントソフトウェアのみを配布する場合、サーバーでGPLライセンスソフトウェアを商業的に使用できますか?
私は、GPLコードを使用してソフトウェアを配布する場合、そのコードはGPLの下でライセンス供与される必要があるというGPL の規則を理解しています。 ただし、この場合のルールは何かと思っています。クライアント側のソフトウェアを販売および配布するサービスを作成しています。 クライアント側のソフトウェアには、GPLコードはまったく含まれていません。それは100%私自身のコードです。 ただし、クライアントソフトウェアは、GPLコードを内部的に使用するサーバーに接続します。 私はない私のサーバー側のソフトウェアを配布します。サーバー側ソフトウェアは、私が単独で制御する専用サーバー上に存在しますが、クライアント側ソフトウェアは、そのサーバーに接続しないと機能しません。 これは1つのソフトウェアとしてカウントされますか?これを行う場合、クライアント側のソースコードをGPLとしてライセンスする必要がありますか?または、ソースコードをリリースせずにクライアント側のソフトウェアを販売できますか?
15 licensing  gpl 

6
TDDの最初のテストで大丈夫だと思うオブジェクトを作成しています
私はTDDにかなり慣れていないので、実装コードの前に来る最初のテストを作成するときに問題があります。実装コードにフレームワークがなければ、私は最初のテストを自由に書くことができますが、Java / OOの問題に対する考え方によって常に汚染されているようです。 たとえば、私のGithub ConwaysGameOfLifeExampleで最初に書いたテスト(rule1_zeroNeighbours)では、まだ実装されていないGameOfLifeオブジェクトを作成することから始めました。存在しないsetメソッド、存在しないstepメソッド、存在しないgetメソッドを呼び出し、アサートを使用しました。 テストはさらにテストを書いてリファクタリングするにつれて進化しましたが、元々は次のようなものでした: @Test public void rule1_zeroNeighbours() { GameOfLife gameOfLife = new GameOfLife(); gameOfLife.set(1, 1, true); gameOfLife.step(); assertEquals(false, gameOfLife.get(1, 1)); } この最初のテストを書くためにこの初期段階でどのように決定したかに基づいて実装の設計を強制していたので、これは奇妙に感じました。 あなたがTDDを理解する方法でこれは大丈夫ですか?私はテストと実装がリファクタリングによって時間とともに進化したという点でTDD / XPの原則に従っているようです。この方法で開始することにより、ソリューション。 TDDは他にどのように使用されますか?GameOfLifeオブジェクトなしで、プリミティブと静的メソッドのみで開始することにより、リファクタリングの反復をさらに行うことができましたが、それはあまりにも不自然に思えます。

3
インターフェースを使用する理由と一般的に制約されたタイプを使用する理由は何ですか
ジェネリック型パラメーター(クラステンプレート、およびパラメーターポリモーフィズムとも呼ばれますが、それぞれの名前には異なる意味があります)をサポートするオブジェクト指向言語では、多くの場合、型パラメーターに型制約を指定して、それを降順にすることができます別のタイプから。たとえば、これはC#の構文です。 //for classes: class ExampleClass<T> where T : I1 { } //for methods: S ExampleMethod<S>(S value) where S : I2 { ... } これらのインターフェースによって制約されるタイプよりも実際のインターフェースタイプを使用する理由は何ですか?たとえば、メソッドシグネチャを作成する理由は何I2 ExampleMethod(I2 value)ですか?

4
誰かが私のコードを再ライセンスし、それを配布したとして私を訴えることはできますか?[閉まっている]
閉まっている。この質問はトピック外です。現在、回答を受け付けていません。 この質問を改善したいですか? 質問を更新して、 Software Engineering Stack Exchangeのトピックになるようにします。 4年前に閉鎖されました。 私がいくつかのコードを公開し、非常に寛容なライセンス(例:unlicense)によってそのコードに対するすべての著作権を放棄したとしましょう。 企業は私のコードを取得し、独自のライセンスの下で再公開し、その新しいライセンスに違反しているとして私を訴えることができますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.