ソフトウェア工学

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

6
ワンライナー対読みやすさ:コードの削減を停止するタイミング [閉まっている]
閉じた。この質問は意見に基づいています。現在、回答を受け付けていません。 この質問を改善したいですか?この投稿を編集して事実と引用で答えられるように質問を更新してください。 2年前に閉店。 環境 私は最近、より良いフォーマットのコードの作成に興味を持ちました。そして、「コードを実行するための独自の「最良の」方法はもちろんないため、「良い慣行と見なすのに十分な人々によって承認されたルールに従う」という意味です。 最近はほとんどRubyでコードを書いているので、リンター(Rubocop)を使ってコードの「品質」に関する情報を提供し始めました(この「品質」はコミュニティ主導のプロジェクトruby-style-guideで定義されています)。 場合によってはコードの効率がコードの記述方法によって実際に影響を受ける場合でも、コードの効率についてではなく、「フォーマットの品質」のように「品質」を使用することに注意してください。 とにかく、すべてのことをして、私はいくつかのことを実現しました(または、少なくとも覚えていました)。 一部の言語(特にPython、Rubyなど)では、優れたコードのワンライナーを作成できます。 コードのガイドラインに従うことで、コードを大幅に短くすることができますが、それでも非常に明確です。 ただし、これらのガイドラインに厳密に従うと、コードがわかりにくく/読みやすくなります。 コードはいくつかのガイドラインをほぼ完全に尊重し、それでも品質が低い場合があります コードの読みやすさはほとんど主観的です(「私が明らかにすることは、仲間の開発者にとって完全に不明瞭かもしれない」) これらは単なる観察であり、もちろん絶対的なルールではありません。また、コードの読みやすさと以下のガイドラインはこの時点では無関係に見えるかもしれませんが、ここでのガイドラインはコードの1つのチャンクを書き換える方法の数を絞り込む方法です。 次に、いくつかの例を挙げて、すべてをより明確にします。 例 単純なユースケースを見てみましょうUser。「」モデルを持つアプリケーションがあります。ユーザーはオプションでありfirstnameかつsurname必須とemailアドレスを。 私は、メソッド「書きたいnameその後、名前を返します」(firstname + surname少なくとも、彼の場合は、ユーザーのを)firstnameまたはsurname、本、またはそのemail代替値としていない場合。 また、このメソッドでuse_emailパラメーターとして" "(ブール値)を使用して、フォールバック値としてユーザーの電子メールを使用できるようにします。このuse_emailパラメーターは(渡されない場合)デフォルトで" "になりますtrue。 それをRubyで記述する最も簡単な方法は次のとおりです。 def name(use_email = true) # If firstname and surname are both blank (empty string or undefined) # and we can use the email... if (firstname.blank? && …

6
廃止されたデータベース列の廃止に関するベストプラクティスは何ですか?[閉まっている]
閉じた。この質問はより集中する必要があります。現在、回答を受け付けていません。 この質問を改善したいですか?この投稿を編集するだけで1つの問題に焦点を当てるように質問を更新します。 2年前に閉店。 早い段階でクライアントからデータA、B、Cを収集するアプリケーションを設計していますが、後でデータA、B、Dを収集します。 A、B、C、およびDは非常に関連性が高く、現在は単一のデータベースPostgreSQLテーブルTの列として存在しています。 Cが不要になったら、アプリケーションからその参照を削除します(Django ORMを使用します)が、既に入力されたデータを保持します。そうするための最良の方法は何ですか? ABD用の新しいテーブルを作成することを考えましたが、それはテーブルTを参照する行で問題が発生する可能性があることを意味します。 列Cをそのまま残し、コード内の列Cへの参照を削除して、既存のデータが生き残るようにすることができます。 表示されていないより良いオプションはありますか? いくつかの追加の詳細: 行の数は多くなく、おそらくユーザーごとに1〜2です。これは大衆市場のアプリケーションですが、CからDに切り替えるまでに、ユーザーベースはまだそれほど大きくありません。CとDは同時に収集されない可能性がありますが、可能性はあります。CとDは、それぞれ1つだけでなく、複数の列を表している可能性があります。

1
LLVMにツリーのようなIRではなく、アセンブリのようなIRがあるのはなぜですか?または:プロジェクトがclangのASTではなくLLVM IRをターゲットとするのはなぜですか?
なぜLLVMの中間表現(LLVM IR)はツリーのようではなくアセンブリのようですか? あるいは、言語の実装がclangのASTではなくLLVM IRをターゲットにしているのはなぜですか? そのように思える場合、私は一度に2つの異なる質問をしようとはしていません。私にとっては、クライアントとライブラリの両方のプログラマーが、LLVMのAPIは明らかに優れたソフトウェア設計であり、「なぜ?」 私が尋ねる理由は、IRがASTに似ていればLLVMがフロントエンドにより多くの機能を提供できるように見えることです。clangのASTベースのツールはどのフロントエンドにも使用できるからです。あるいは、LLVM IRを対象とする言語は、clangのASTを対象とする場合、より多くの機能を取得できます。 ClangにはASTを作成および操作するためのクラスと関数があり、LLVMプロジェクトに強く結び付けられている唯一のフロントエンドプロジェクトです。なぜclangのAST機能はLLVMの外部にあるのでしょうか。 私の頭上では、Rust(rustc)、D(ldc)、Haskell(GHC)はすべてLLVMをバックエンドとして使用できますが、Clang ASTは使用しません(私が知る限り、間違っている)。これらのコンパイラのすべての内部詳細はわかりませんが、少なくともRustとDは確かにclangのASTにコンパイルできるようです。Haskellも可能かもしれませんが、それについてはあまり確信が持てません。 これは歴史的な理由によるものですか(LLVMはもともと「低レベルの仮想マシン」であり、clangは後で登場します)?これは、他のフロントエンドがLLVMに供給するものを可能な限り制御したいからでしょうか?clangのASTが「非Cライク」言語に不適切である根本的な理由はありますか? 私はこの質問をマインドリーディングの練習にするつもりはありません。コンパイラー設計に興味はあるが、まだ流notではない私たちにとって役立つものにしたいだけです。LLVMおよびclangプロジェクトは公開で開発されているため、これらのプロジェクトの開発に精通している人が答えられるか、答えがコンパイルオタクにとって十分に明白であり、彼らが答えるのに十分自信があると感じることを望んでいます。 明らかではあるが不十分な回答を先取りするには: はい、アセンブリのようなIRを有するIR工芸誰により詳細に制御できます(おそらくX langは打ち鳴らすより良いコードベースとASTの形式を持っている)が、それが唯一の答えだ場合、その疑問は、なぜLLVMはない」となっのみ assembly-を持っています高レベルのツリーのようなIRと低レベルのアセンブリのようなIRではなくIRが好きですか?」 はい、プログラミング言語をASTに解析するのはそれほど難しくありません(少なくとも他のコンパイル手順と比較して)。それでも、なぜ個別のASTを使用するのですか?他に何もなければ、同じASTを使用すると、ASTで動作するツールを使用できます(ASTプリンターのような単純なものでも)。 はい、よりモジュール化することは良いことであることに強く同意しますが、それが唯一の理由である場合、他の言語実装がclangのASTではなくLLVM IRをターゲットとする傾向があるのはなぜですか? これらのプリエンプションは誤っているか、詳細を見落としている可能性があります。詳細がある場合、または私の仮定が間違っている場合は、お気軽にこれらの回答を行ってください。 より明確に答えられる質問に答えたい人のために:アセンブリのようなIR対ツリーのようなIRの長所と短所は何ですか?

7
単純なドメインオブジェクトを表すプリミティブvsクラス?
domain-speciifcオブジェクトとプレーンな文字列または数字を使用する場合の一般的なガイドラインまたは経験則は何ですか? 例: 年齢階級と整数? FirstNameクラスとString? UniqueID vs String PhoneNumberクラスvs文字列vs Long? DomainNameクラスとString? ほとんどのOOP実践者は、間違いなくPhoneNumberとDomainNameの特定のクラスを言うと思います。それらを有効にするものとそれらを比較する方法に関するルールが増えると、単純なクラスをより簡単かつ安全に処理できるようになります。しかし、最初の3つについては、さらに議論があります。 私は「年齢」クラスに出会ったことはありませんが、非負でなければならないので理にかなっていると主張することができます(負の年齢について議論できることはわかっていますが、プリミティブ整数とほぼ同等である良い例です)。 文字列は「名」を表すのが一般的ですが、空の文字列は有効な文字列ですが、有効な名前ではないため、完全ではありません。通常、比較は大文字小文字を無視して行われます。空のチェック、大文字と小文字を区別しない比較などを行う方法はありますが、これを行うにはコンシューマーが必要です。 答えは環境に依存しますか?私は主に、おそらく10年以上にわたって存続し、維持されるエンタープライズ/高価値ソフトウェアに関心を持っています。 おそらく私はこれを考えすぎていますが、クラスとプリミティブのどちらを選択するかについてのルールがあるかどうかを知りたいと思います。

3
純粋なPOCOモデルを持つことの利点は何ですか?
純粋なPOCOモデルを持つことの主な利点は何ですか?私は、モデルはクリーンでシンプルであるべきだと思いますが、モデルクラス内の子オブジェクトのメンテナンスを維持する傾向があります。例えば、私が持っている場合ClassAとClassB、以下のように定義されました: public class ClassA { public string MyProp { get; set; } public IEnumerable<ClassB> Children { get; } public void AddChild(ClassB newChild) { /*... */ } public void RemoveChild(ClassB child) { /* ... */ } } public class ClassB { public string SomeProp { get; set; } } addメソッドとremoveメソッドがあることに本質的に問題はありますか?代わりにリストを公開し、クライアントコードに、null以外の単純なデータ検証の責任を渡すものを追加できるようにし、別のクラスに複製しないようにする必要がありますか? どんな助けもありがたいです。ありがとう。
14 c#  .net  poco 

3
並列配列を使用できるのはいつですか?
私は「並列配列」またはリストと呼んでいるものを使用するコード(新しいコード)を実行しています。つまり、関連データを含む2つの配列があり、配列内の位置(インデックス)によってリンクされています。 私はこれを混乱させ、あらゆる種類のエラーを起こしやすいと考えています。私が通常提案する解決策は、CompanyCompanyIdおよびCompanyNameフィールドで呼び出されるオブジェクトを作成することです。 非常に現実的な例: List<string> companyNames; List<int> companyIds; //...They get populated somewhere and we then process for(var i=0; i<companyNames.Count; i++) { UpdateCompanyName(companyIds[i],companyNames[i]); } これらの並列配列は悪い習慣と見なされていますか?

2
型自体の代わりに、型制約のあるジェネリックメソッドを使用するのはなぜですか?
別のStackExchangeの質問で、このプロトタイプを使用している人に気付きました。 void DoSomething<T>(T arg) where T: SomeSpecificReferenceType { //Code.... } 型の制約は1つだけであることに注意してください(SomeSpecificReferenceType)。単純にではなく、そのように記述することの違いと利点は何ですか? void DoSomething(SomeSpecificReferenceType arg) { //Code.... } どちらの場合も、argコンパイル時の型チェックの対象となります。どちらの場合も、メソッドの本体は、argコンパイル時に認識されている特定の型の(またはその子孫である)知識に安全に依存できます。 これは、熱心な開発者が通常の継承について学ぶ前にジェネリックについて学ぶ場合ですか?または、メソッドシグネチャがこのように記述される正当な理由がありますか?
14 c#  .net  generics 

3
1つの実装を構築する多数。DI絶望?サービスロケーターを使用しますか?
インジェクションを受け入れるのではなく、依存関係を直接構築するクライアントが1001人いるとします。上司によると、1001のリファクタリングはオプションではありません。実際には、ソースへのアクセスさえ許可されていません。クラスファイルだけです。 私たちがやるべきことは、これらの1001クライアントが通過するシステムを「近代化」することです。好きなことをリファクタリングできます。依存関係はそのシステムの一部です。そして、それらの依存関係のいくつかは、新しい実装を行うために変更することになっています。 私たちがやりたいことは、この多数のクライアントを満たすために、依存関係の異なる実装を構成する機能を持っていることです。悲しいことに、クライアントはコンストラクターまたはセッターによるインジェクションを受け入れないため、DIはオプションのようには見えません。 オプション: 1)クライアントが使用するサービスの実装をリファクタリングして、クライアントが現在必要としていることを行うようにします。完了です。柔軟ではありません。複雑ではありません。 2)実装をリファクタリングして、ファクトリを通じて取得したさらに別の依存関係に作業を委任します。これで、ファクトリをリファクタリングすることで、すべてが使用する実装を制御できます。 3)実装をリファクタリングして、作業をサービスロケーターを介して取得したさらに別の依存関係に委任します。これhashmapで、少しのキャストが行われたオブジェクトへの文字列である可能性のあるサービスロケーターを構成することで、すべてが使用する実装を制御できます。 4)まだ考えていないこと。 目的: 設計が不十分な古いクライアントコードを無意味な複雑さを加えることなく未来にドラッグすることによって引き起こされる設計の損傷を最小限に抑えます。 クライアントは依存関係の実装を知っていないか制御するべきではありませんが、で構築することを主張しますnew。制御することはできませんnewが、構築しているクラスを制御します。 私の質問: 何を考慮しなかったのですか? Doc Brownからの質問 異なる実装間で構成する可能性が本当に必要ですか?何のために? 機敏。未知の多く。経営陣は変化の可能性を望んでいます。外の世界への依存を失うだけです。またテスト。 実行時の仕組みが必要ですか、それとも異なる実装を切り替えるためにコンパイル時の仕組みが必要ですか?どうして? コンパイルの時間の仕組みで十分です。テストを除く。 どの粒度で実装を切り替える必要がありますか?一斉に?モジュールごと(それぞれがクラスのグループを含む)?クラスごと? 1001のうち、一度に実行されるのは1つだけです。すべてのクライアントが一度に使用するものを変更しても問題はないでしょう。ただし、依存関係を個別に制御することはおそらく重要です。 誰がスイッチを制御する必要がありますか?あなた/あなたの開発者チームのみ?管理者ですか?各クライアントは自分で?または、クライアントのコードのメンテナンス開発者ですか?それでは、メカニックはどれほど簡単/堅牢/完全に機能する必要があるのでしょうか? テスト用の開発。外部ハードウェアの依存関係が変化するため、管理者。テストと構成が簡単である必要があります。 私たちの目標は、システムを迅速に作り直し、近代化できることを示すことです。 実装スイッチの実際の使用例 1つは、ハードウェアソリューションの準備が整うまで、一部のデータがソフトウェアによって提供されることです。

1
同僚が極端な複雑さと抽象化を持ち込むのを防ぐ方法は?
私の同僚が展示しているように見えるので、私は非常に困難な時間を過ごしています 早すぎる/不要な最適化の取り組み 疑わしい抽象化を伴う早期重複排除 たとえば、変更されたVIPERアーキテクチャを使用します。彼は、他のルーターで何が複製されるかを実際に知らずに、最初のviperスタックを実装する一環として、ルーターコンポーネントの基本クラスを(ジェネリックを使用して)導入しました。現在UseCase、ユースケースを保持するタイプを提供する必要がありますが、ほとんどのルーターには複数のユースケースはなく、1つだけです。 将来の投機的な機能の ための汎用ソリューションの考案たとえば、アプリ内にこのような画面が2つしかない場合、静的なセルテーブルビューを作成するためのマネージャーを作成しました。 UIなので、マネージャーは役に立たない。 偶発的な複雑さの選択 ひどい英語で言葉の壁があることを示しているとき、どうやってこれと戦うのですか?

2
現実の世界-リスコフ代替原理
背景:私はメッセージングフレームワークを開発しています。このフレームワークでは次が可能になります。 サービスバスを介したメッセージの送信 メッセージバス上のキューにサブスクライブする メッセージバスのトピックを購読する 現在RabbitMQを使用していますが、近い将来にMicrosoft Service Bus(オンプレミス)に移行することを知っています。 インターフェイスと実装のセットを作成して、ServiceBusに移行するときに、クライアントコード(パブリッシャーまたはサブスクライバー)を修正せずに新しい実装を提供するだけでよいようにします。 ここでの問題は、RabbitMQとServiceBusが直接翻訳できないことです。たとえば、RabbitMQはExchangeとトピック名に依存していますが、ServiceBusは名前空間とキューに関するものです。また、ServiceBusクライアントとRabbitMQクライアントの間に共通のインターフェイスはありません(たとえば、両方にIConnectionがある場合がありますが、インターフェイスは異なります-共通の名前空間からではありません)。 そのため、次のようにインターフェイスを作成できます。 public interface IMessageReceiver{ void AddSubscription(ISubscription subscriptionDetails) } 2つのテクノロジーの翻訳不可能な特性により、上記のインターフェースのServiceBusとRabbitMQの実装には異なる要件があります。したがって、IMessageReceiverのRabbitMq実装は次のようになります。 public void AddSubscription(ISubscription subscriptionDetails){ if(!subscriptionDetails is RabbitMqSubscriptionDetails){ // I have a problem! } } 私にとって、上記の行は、リスコフの代替可能性の規則を破ります。 SubscriptionがIMessageConnectionを受け入れるように、これを反転させることを検討しましたが、RabbitMq SubscriptionにはRabbitMQMessageConnectionの特定のプロパティが必要になります。 だから、私の質問は: これがLSPに違反することを修正できますか? 場合によっては避けられないこと、または何かが足りないことに同意しますか? うまくいけば、これは明確で話題になっています!

3
PHP Webアプリのフローを把握できなくなったため、作業が難しくなっています
私は数年前からプログラミングを行ってきましたが、C#とJavaScriptに非常に慣れてきました。大規模なC#およびJavaScriptプロジェクトがいくつかありますが、問題なくナビゲートできます。私は最近、PHPの経験がなくても作業するためにPHPとAngularJSプロジェクトを開始しました。 物事のPHP側の流れを追跡するのが難しくなりつつあります(JavaScript側は大きくなりますが、簡単に処理できます)。私が始めたときに犯した主要な設計ミスは山積みになり始め、今後の設計に影響を与えています。新しいものを実装するには、ますます時間がかかります。 私は締め切りが厳しく、良い、乾いた、固い、コードを書くのがますます難しくなっています。コードのチャンクをコピー/貼り付けして、設計時間が長くなるにつれてその動作にわずかな変化を加えることがより魅力的になっています。また、コンテキスト切り替えを行う必要があるときはいつでもコードベースに戻るのに時間がかかります(あるプロジェクトからこのプロジェクトに戻る)。このプロジェクトに戻るときはいつでも恐怖を感じます。 これを解決するためにどのような手順を実行できますか?上司は開発者ではなく、開発やソフトウェアのライフサイクルに精通していないため、時間がかかる可能性があることも正当化する必要があります。そのため、説明は通常より難しい場合があります。

5
OOPコーディングスタイル:コンストラクターですべてを初期化しますか?
私はまだ見習いプログラマーであると考えているので、私はいつも典型的なプログラミングのための「より良い」方法を学ぼうとしています。今日、私の同僚は私のコーディングスタイルが不必要な仕事をしていると主張しており、他の人から意見を聞きたいと思っています。通常、OOP言語(通常はC ++またはPython)でクラスを設計するとき、初期化を2つの異なる部分に分けます。 class MyClass1 { public: Myclass1(type1 arg1, type2 arg2, type3 arg3); initMyClass1(); private: type1 param1; type2 param2; type3 param3; type4 anotherParam1; }; // Only the direct assignments from the input arguments are done in the constructor MyClass1::myClass1(type1 arg1, type2 arg2, type3 arg3) : param1(arg1) , param2(arg2) , param3(arg3) {} …

6
リフレクションはプライベート変数を制限できないので不利ですか?
private修飾子は、クラス外部からのアクセスを制限するために使用されていますが、反射他のクラスを使用すると、プライベートメソッドとフィールドにアクセスすることができます。ですから、もしそれが要件の一部であるなら、どうやってアクセシビリティを制限できるのだろうと思っています。

2
イベントソーシングでプロセスマネージャーを実装する方法
私はCQRSとイベントソーシングの概念を学ぶために、小さなサンプルアプリケーションに取り組んでいます。私が持っているBasket骨材とProduct独立して動作するはず集計を。 実装を示すための擬似コードを次に示します Basket { BasketId; OrderLines; Address; } // basket events BasketCreated { BasketId; } ItemAdded { BasketId; ProductId; Quantity } AddItemSucceeded { BasketId; ProductId; Quantity } AddItemRevoked { BasketId; ProductId; Quantity } ItemRemoved { BasketId; ProductId; Quantity } CheckedOut { BasketId; Address } Product { ProductId; Name; Price; } …

2
Javaインターフェイスのすべてのメソッド宣言がパブリック抽象ではないため、これらの修飾子を使用してメソッドを宣言する必要がありますか?
Java 8以降、defaultメソッドがインターフェイスに導入されました。事実上、これはのすべてのメソッドがであるとinterfaceは限らないことを意味しますabstract。 Java 9(おそらく)以降、privateメソッドは許可されます。これは、のすべてのメソッドがであるとinterfaceは限らないことを意味しますpublic abstract。 「Javaインターフェイスのメソッドは、publicアクセス修飾子を付けて、または付けずに宣言する必要がありますか?」という質問 スタックオーバーフローで/programming/161633/should-methods-in-a-java-interface-be-declared-with-or-without-a-public-access-mで尋ねられました そこでは、ほとんどの回答はpublic abstract使用すべきではないと主張しました。なぜなら、のメソッドはinterface以外のものではないからですpublic abstract。もはやそうではありません。 インターフェースのこれらの新しい機能をpublic abstract考慮して、Javaインターフェースメソッドの宣言でキーワードを使用する必要がありますか? 私の特定の環境では、経験豊富なソフトウェアエンジニアがJavaを経験していない人がいて、Javaコードを時々読んでいます。public abstractキーワードを省略すると、インターフェースがこれらのキーワードを使用するためのさまざまなルールを持つようになった経緯に詳しくない人にとっては、さらなる混乱点が生じると思います。

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