ソフトウェア工学

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

1
Javaのデフォルトメソッドの使用
何十年には、インターフェースがあった場合をされているのみ だけメソッドのシグネチャを特定する(のみ)。これが「物事を行う正しい方法™」だと言われました。 その後、Java 8が登場して次のように述べました。 えーと、ええと、今ではデフォルトのメソッドを定義できます。さようなら。 経験豊富なJava開発者と、最近(ここ数年)開発を始めたJava開発者の両方によって、これがどのように消化されているのか興味があります。また、これがJavaの正統性と実践にどのように適合するかについても疑問に思っています。 私はいくつかの実験的なコードを構築しており、リファクタリングを行っている間に、標準インターフェース(Iterable)を単純に拡張し、2つのデフォルトメソッドを追加するインターフェースになりました。そして正直に言うと、私はそれについてかなり気分が良いと感じています。 私はこれが少しオープンエンドであることを知っていますが、実際のプロジェクトでJava 8を使用する時間がありましたが、デフォルトメソッドの使用に関する正統性はまだありますか?それらが議論されるときに私が主に見るものは、既存の消費者を壊すことなく、インターフェースに新しいメソッドを追加する方法についてです。しかし、上記の例のように最初からこれを使用するのはどうですか。インターフェースに実装を提供することで問題に直面した人はいますか?

2
このプログラミング手法は何と呼ばれていますか?
インタビューでペアプログラミングを行っているときにこのプログラミング手法に出会い、Googleでその名前を見つけることができませんでした。 考え方は、最初に変数を使用する式を記述し、その後変数を計算するコードを記述することです。 ここでいくつかのサンプルコードを使用するには: private bool ValidPolicyNumber(string policyNumber) { var hasExpectedPrefix = policyNumber.Substring(0,5) == "POLIC"; var followedBy7Digits = Regex.IsMatch(policyNumber.Substring(6,7), "^[0-9]{7}$"); var hasLengthOf12 = policyNumber.Length == 12; return hasExpectedPrefix && followedBy7Digits && hasLengthOf12; } 前述の手法を使用してこの関数を記述する場合、最初に最後の行return hasExpectedPrefix && followedBy7Digits && hasLengthOf12;を記述し、次にその前の3行を記述します。 私が見つけた最も近い技術は「希望的観測」であり、それはSICPからのものですが、後で初期化する変数を使用するのではなく、後で実装する関数の呼び出しに関連しています。

8
「継承よりも構成を優先する」-署名の変更を防御する唯一の理由はありますか?
このページは、次の引数を使用して継承よりも構成を推奨しています(私の言葉で言い換えます)。 サブクラスでオーバーライドされていないスーパークラスのメソッドのシグネチャの変更により、継承を使用するときに多くの場所で追加の変更が発生します。ただし、Compositionを使用する場合、必要な追加の変更は1つの場所であるサブクラスのみです。 それが本当に継承よりも構成を優先する唯一の理由ですか?その場合、サブクラスが実装を変更しない(つまり、サブクラスにダミーのオーバーライドを設定する)場合でも、スーパークラスのすべてのメソッドをオーバーライドすることを推奨するコーディングスタイルを適用することで、この問題を簡単に軽減できるためです。ここに何かが足りませんか?

6
オブジェクトをプレゼンターにマッピングするクリーンなOOP方法
私は、それぞれの作品は、独自のタイプ(のようであるジャワ、中(例えばチェスなど)ボードゲームを作成していますPawn、Rookなど)。アプリケーションのGUI部分では、これらの各部分の画像が必要です。やることは rook.image(); UIとビジネスロジックの分離に違反しているため、作品ごとに異なるプレゼンターを作成し、作品タイプを対応するプレゼンターにマッピングします。 private HashMap<Class<Piece>, PiecePresenter> presenters = ... public Image getImage(Piece piece) { return presenters.get(piece.getClass()).image(); } ここまでは順調ですね。ただし、getClass()メソッドを呼び出すと慎重なOOPの第一人者が眉をひそめ、次のようなビジターを使用することをお勧めします。 class Rook extends Piece { @Override public <T> T accept(PieceVisitor<T> visitor) { return visitor.visitRook(this); } } class ImageVisitor implements PieceVisitor<Image> { @Override public Image visitRook(Rook rook) { return rookImage; } } 私はこのソリューションを気に入っています(ありがとう、第一人者)が、1つの重大な欠点があります。新しいピースタイプがアプリケーションに追加されるたびに、PieceVisitorを新しいメソッドで更新する必要があります。私のシステムをボードゲームフレームワークとして使用して、フレームワークのユーザーがピースとそのプレゼンターの両方の実装のみを提供し、それをフレームワークにプラグインするだけの簡単なプロセスで新しいピースを追加できるようにします。私の質問:このような拡張性を可能にするinstanceof、getClass()などのないクリーンなOOPソリューションはありますか?

8
スクラムチームはYAGNIの原則に従っていません
SCRUMミーティングで、製品チームは、モバイルアプリで使用されるAPIの機能について議論していました。私たちは、画面がどのように見えるべきか、そしてどのキー要素を含むべきか(「レイアウト」)を示すモックアップを用意しました。 これと製品所有者との議論に基づいて、API応答のプロトタイプ(HAL + JSON)を作成しました。それは非常にシンプルで、HALに準拠したJSONであり、モックアップにあるものを表すことしかできませんでした。ビジネスマンは頻繁にアイデアを変更する傾向があるため、私は将来のアイデアに影響されることはなく、ミニマルなアプローチを取ることにしました。私の提案はチームによって却下され、7対1に投票されました。 チームは、レイアウトをより柔軟に配置できる、より複雑で非セマンティックな抽象json構造を使用することにしました。そのアプローチの欠点は、設計上、nullおよび空のプロパティを持つ可能性のある一連の均一なオブジェクトになってしまったことです。彼らはまた、A / Bテストを可能にすると良いと思っていましたが、そのような要件がなかったため、予測に基づいていました。 ほとんどの場合、スプリントの一部ではなく、モックアップで言及されていないことについて議論していました。説明された問題は、「将来のマーケティングがどうなるか...」、「ビジネスが私たちに望むならどうなるか...」でした。 私と製品所有者は経験豊富なプログラマーであり、過去にこの種の問題を見てきました。YAGNIとKISSの原則に従うよう努めています。チームの他のメンバーは少し経験が浅く、これらの原則を知っていますが、理解していないようです。 チーム全体が私たちにとってより重要であり、私たちはそれほど重要ではない何かをめぐって戦いたくなかったので、私たちは彼らの解決策に同意しました。しかし、そのようなことが今後のより複雑な議論の先例になり得るのではないかと心配していますか?そのような行動に対処する方法は?チームリーダーとして、私がもっとうまくできることはありますか? 製品は初期段階のMVPであることに言及する価値があります。

4
何も返さない純粋なメソッドのテストを作成するにはどうすればよいですか?
値の検証を扱うクラスがたくさんあります。たとえば、RangeValidatorクラスは値が指定された範囲内にあるかどうかをチェックします。 すべてのバリデータクラスには2つのメソッドが含まれます:値is_valid(value)を返すTrueかFalse、値に応じて、ensure_valid(value)指定された値をチェックし、値が有効な場合は何もしないか、値が事前定義されたルールに一致しない場合は特定の例外をスローします。 現在、このメソッドに関連する2つの単体テストがあります。 無効な値を渡し、例外がスローされたことを確認するもの。 def test_outside_range(self): with self.assertRaises(demo.ValidationException): demo.RangeValidator(0, 100).ensure_valid(-5) 有効な値を渡すもの。 def test_in_range(self): demo.RangeValidator(0, 100).ensure_valid(25) 2番目のテストは、例外をスローすると失敗し、ensure_valid何もスローしないと成功しますが、assert内部にs がないという事実は奇妙に見えます。そのようなコードを読んだ人は、何もしていないように見えるテストがなぜあるのかをすぐに自問するでしょう。 これは、値を返さず、副作用のないメソッドをテストするときの現在のプラクティスですか?または、テストを別の方法で書き直す必要がありますか?または、単に私がやっていることを説明するコメントを入れますか?

2
相対的な予想タスク時間をスケジュールに組み込むビルドシステムはありますか?
これが私の質問の小さな図です: ADという名前の4つの独立したタスクで構成されるビルドジョブを想定します。DはACよりも時間がかかります。 相対的なタスク時間を組み込むことができないビルドシステムは、次のようにタスクをスケジュールする場合があります。 --------------------------------------- CPU1: A | C | --------------------------------------- CPU2: B | D | --------------------------------------- 対照的に、スケジューラがタスクの時間差を認識している場合、次のようなはるかに短いスケジュールが考えられます。 --------------------------------------- CPU1: A | B | C | --------------------------------------- CPU2: D | --------------------------------------- 私の質問: 相対的な予想タスク時間をスケジュールに組み込むビルドシステムはありますか? この種の構築システムに関する学術研究は何ですか? これらのビルドシステム(存在する場合)はどこから時間情報を取得しますか?ヒューリスティック、以前のビルド中に収集されたタイミング? そのようなビルドシステムが存在しない場合、なぜですか?一見しただけで価値がなくなるような落とし穴はありますか?


4
単一の責任を持つ大規模なクラス
2500行のCharacterクラスがあります。 ゲーム内のキャラクターの内部状態を追跡します。 その状態をロードして永続化します。 〜30個の着信コマンドを処理します(通常=に転送しますGameが、一部の読み取り専用コマンドはすぐに応答します)。 Game実行中のアクションと他のユーザーの関連アクションに関する〜80の呼び出しを受け取ります。 私にCharacterは、単一の責任があるように思われます。キャラクターの状態を管理し、受信コマンドとゲームを仲介することです。 既に分割されている他のいくつかの責任があります。 CharacterOutgoingクライアントアプリケーションの発信更新を生成するために呼び出すがあります。 Characterは、Timer次に何ができるかを追跡するを持っています。着信コマンドはこれに対して検証されます。 だから私の質問は、SRPや同様の原則の下でこのような大規模なクラスを持つことは容認できますか?煩雑さを軽減するためのベストプラクティスはありますか(メソッドを個別のファイルに分割するなど)。それとも、私は何かを見逃していますか?それを分割する本当に良い方法はありますか?これは非常に主観的なものであり、他の人からのフィードバックが欲しいと思います。 サンプルを次に示します。 class Character(object): def __init__(self): self.game = None self.health = 1000 self.successful_attacks = 0 self.points = 0 self.timer = Timer() self.outgoing = Outgoing(self) def load(self, db, id): self.health, self.successful_attacks, self.points = db.load_character_data(id) def save(self, db, id): db.save_character_data(self, health, self.successful_attacks, self.points) …

4
SOLIDをフォローする場合、ファイルの読み取りと書き込みには2つの異なる責任がありますか?
SOLIDの調査を始めたばかりで、ファイルの読み取りとファイルへの書き込みが同じ責任であるかどうかはわかりません。 ターゲットは同じファイルタイプです。アプリケーションで.pdfを読み書きしたい。 それが違いを生む場合、アプリケーションはPythonです。

3
マルチリポジトリ環境でのパッケージおよびバージョン戦略
私たちは、独自のgitリポジトリを管理する複数のチームを持つ小規模企業です。これはWebプラットフォームであり、各チームの成果物は夜間テストのために1日の終わりに展開されます。バージョン管理とパッケージングに関するプロセスを形式化しようとしています。 すべてのチームには、日々の開発を行うマスターブランチがあります。各チームの品質保証メンバーは、チームの変更による成果物を、すべてのコンポーネントがシェフによって結合されるテストベッドに展開することを望んでいます。アーティファクトはtarballですが、それらをRPMに変換して、バージョンについて正しく考え、推論できるようにします。 リリースプロセスには、各gitリポジトリの開発ブランチ(ほとんどの場合マスター)からリリースブランチを切り離すことが含まれます。これは、成果物のセットでテストとサインオフを実行する品質保証に与えられます。 たとえば、これは関連するリリースブランチを持つ典型的なgitリポジトリです。 0-0-0-0-0-0-0-0-0-0 (master) | | 0 0 (rel-1) | 0 (rel-2) 開発ブランチから来るパッケージのバージョン管理を実行するスキームを見つけようとして立ち往生しています。各リポジトリのmasterブランチに過度にタグを付けたり、タグをリリースブランチのみに制限したりするのは望ましくありません。ただし、標準のyum / rpmセマンティクスを使用して、テストマシンにデプロイされたパッケージを照会できる必要があります。masterブランチにタグがない場合、開発バージョンはどのようになりますか?私git describeはビルドバージョンの有用な表現を提供できることを理解していますが、ブランチ上のさまざまなリリースポイントがタグ付けされている場合はうまく機能します。 EDIT1:@ Urban48の回答に応えて リリースプロセスについてもう少し説明する必要があると考えました。この議論のためにmaster、すべてのリポジトリにブランチがあると仮定しましょう。このmasterブランチは開発ブランチと見なされ、CI-CD対応の自動化されたQA環境に展開されます。これは、マスターの安定性を確保するために夜間テストのサブセットが実行される場所です。リリースブランチをカットする前に、このジョブのパイプラインを確認します。リリースブランチは短命です。リリースブランチを(安定したマスターから)カットした後、完全なリグレッションが実行され、修正が行われ、運用環境に展開されたとします。これには約1週間かかります。ほぼ2週間ごとに実稼働環境にリリースします。 機能ブランチは常にマスターから切り離され、CI-CD安定性チェックを受けるマスターとマージする前に、ある程度の開発者テストを受けます。 修正プログラムは(リリースブランチからカットされた)修正プログラムブランチで作成され、本番環境への影響を最小限に抑えて展開されます。 リリースおよびホットフィックスブランチのバージョン管理戦略は、semverに従います。QAサイクル中のリリースブランチはv2.0.0-rc1、v2.0.0-rc2などのバージョンを通過し、最終的にQAサインオフがになりv2.0.0ます。 バージョンがになるリリースブランチ(およびマスター)にマージされる小さな機能のドットリリースを行うことがありますv2.1.0。また、ホットフィックスはv2.1.1パターンを想定しています。 ただし、問題はこれらのブランチをバージョン管理することではありません。このバージョン管理スキームをまったく変更しないことをお勧めします。唯一の変更点は、開発ブランチ、つまり 主人。CI-CD環境で、以前のリリースから実稼働環境に存在するバージョンを確実に示す方法を教えてください。これは、理想的にはスマートgitタグ付けによって行われますが、masterブランチに過度にタグ付けしないものが推奨されます。

5
「静的インターフェイス」は良い習慣ですか?
最近、インターフェイスに静的メソッドを持つオプションがあることに気付きました。インターフェイスの静的フィールドと同様に、興味深い動作があります。これらは継承されません。 実装される実際のインターフェースで有用かどうかはわかりません。ただし、プログラマは、ユーティリティクラスなどの静的なものの単なるエンベロープであるインターフェイスを作成できます。 簡単な例は、グローバル定数の単なるエンベロープです。クラスと比較して、public static final想定されているボイラープレートの欠落に簡単に気付くことができます(冗長性が低くなります)。 public interface Constants { String LOG_MESSAGE_FAILURE = "I took an arrow to the knee."; int DEFAULT_TIMEOUT_MS = 30; } また、設定キーのこの疑似列挙のように、より複雑なものを作成することもできます。 public interface ConfigKeys { static createValues(ConfigKey<?>... values) { return Collections.unmodifiableSet(new HashSet(Arrays.asList(values))); } static ConfigKey<T> key(Class<T> clazz) { return new ConfigKey<>(clazz); } class ConfigKey<T> { private …
13 java  java8 

1
TDD方法論をトップダウンで適用できますか?
方法論であるTDDが次のケースをどのように処理するかはわかりません。Pythonでmergesortアルゴリズムを実装するとします。私は書くことから始めます assert mergesort([]) === [] そしてテストは失敗します NameError:名前 'mergesort'は定義されていません 次に追加します def mergesort(a): return [] テストに合格しました。次に追加します assert mergesort[5] == 5 そして私のテストは失敗します AssertionError 私はパスします def mergesort(a): if not a: return [] else: return a 次に、追加します assert mergesort([10, 30, 20]) == [10, 20, 30] そして今、私はこの合格を試みなければなりません。mergesortアルゴリズムを「知っている」ので、次のように記述します。 def mergesort(a): if not a: return [] else: left, …
13 tdd 

4
現代のCの書き方について、一般に受け入れられているガイドラインはありますか?
私はJava / Groovyの強力なバックグラウンドを持ち、管理ソフトウェア用の非常に大きなCコードベースを維持するチームに割り当てられました。 データベース内のblobの処理やPDFおよびExcelでのレポートの生成など、いくつかの問題点はJava Webサービスに外部化されています。 ただし、Java開発者として、コードのいくつかの側面に少し混乱しています。 それは冗長です(特に「例外」を扱う場合) 巨大なメソッドがたくさんあります(2000行以上のメソッド) 高度なデータ構造はありません(リスト、セット、およびマップをたくさん見逃しています) 懸念事項の分離なし(SQLはコード全体でうれしそうに混合されています) その結果、ビジネスは大量の技術コードに隠されており、Object Orientedと関数型プログラミングのピンチで形作られた私の脳は楽ではないと感じています。 プロジェクトの良い面は、コードが単純であることです。フレームワーク、実行時のバイトコード操作、AOPはありません。また、サーバーは、Javaが「hello world」を吐き出すのに必要なメモリよりも少ないメモリを使用することにより、1台のマシンで10000人以上のユーザーに同時に応答できます。 私は、一般に受け入れられている現代の原則に従ってCコードを書く方法を学びたいです。現代のCをどのように記述し構造化するかについて、一般に受け入れられている原則はありますか? 「Effective Java」本に相当するものに少し似ていますが、C用です。 回答とコメントに照らして編集: 私は自分の考え方をCコードに適合させ、OOPにミラーリングしようとはしません。 コメントから推奨されるコーディングスタイルガイド(The GNU Coding StandardsおよびThe Linux Kernel Coding Style)をスキャンして読み始めました。 次に、このコードスタイルを同僚に提案しようとします。最も難しいのは、同僚に、巨大なメソッドを小さなパーツに分割し、同じ4行のエラー処理コードを繰り返すことをメソッドの助けによって回避できることを納得させることです。
13 c  maintenance 

4
ジュニア開発者にコードレビューへの参加を促す方法は?
私は現在、3人の下級者と一緒に上級開発者として働いており、コードレビュープロセスを導入して、生産に入るコードの品質を管理しました。 私たち全員がお互いの作業をレビューすることは非常に有益であると感じていますが、約5週間のプロセスの後、ツール(BitBucket)でコメントをするのは私だけです。 職場には一部文化的な問題があり、コメントが間違っている場合にはおそらく自然な抵抗がありますが、何らかの方法がありますか?

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