ソフトウェア工学

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

7
SOLIDに切り替えた後、大幅に増加したクラスの数を管理および整理しますか?
ここ数年、私たちは少しずつ一歩ずつ、より良い記述コードに徐々に切り替えてきました。私たちはついに、少なくともSOLIDに似たものへの切り替えを始めていますが、まだまだそこにはありません。切り替えを行って以来、開発者からの最大の不満の1つは、以前はすべてのタスクで開発者が5〜10個のファイルを操作するだけで十分だった数十個のファイルをピアレビューおよびトラバースできないことです。 切り替えを開始する前に、アーキテクチャは次のように編成されていました(1〜2桁以上のファイルが付与されています)。 Solution - Business -- AccountLogic -- DocumentLogic -- UsersLogic - Entities (Database entities) - Models (Domain Models) - Repositories -- AccountRepo -- DocumentRepo -- UserRepo - ViewModels -- AccountViewModel -- DocumentViewModel -- UserViewModel - UI ファイルに関しては、すべてが非常に線形でコンパクトでした。明らかにコードの重複、密結合、および頭痛の種がたくさんありましたが、誰もがそれを横断して理解することができました。完全な初心者、つまりVisual Studioを開いたことのない人は、わずか数週間でそれを理解できました。全体的なファイルの複雑さの欠如により、初心者の開発者や新規採用者も、あまり時間をかけずに貢献を始めることが比較的簡単になります。しかし、これはコードスタイルの利点が出てこないところです。 コードベースを改善するためのあらゆる試みを心から支持しますが、このような大規模なパラダイムシフトについて、チームの他のメンバーからプッシュバックを得るのは非常に一般的です。現在の最大のこだわりのポイントは次のとおりです。 単体テスト クラス数 ピアレビューの複雑さ ユニットテストは時間の無駄だと信じており、個々のコードよりも全体としてコードをはるかに迅速に処理テストできると信じているため、チームにとっては信じられないほど難しい販売でした。SOLIDの承認として単体テストを使用することはほとんど無益であり、この時点ではほとんど冗談になりました。 クラス数はおそらく克服すべき最大のハードルです。5〜10個のファイルを使用していたタスクは、70〜100個かかるようになりました。これらの各ファイルにはそれぞれ異なる目的がありますが、膨大な量のファイルが圧倒される場合があります。チームからの反応は、主にうめき声と頭を掻くものでした。以前は、タスクには1つまたは2つのリポジトリ、1つまたは2つのモデル、ロジックレイヤー、およびコントローラーメソッドが必要でした。 単純なファイル保存アプリケーションを構築するには、ファイルが既に存在するかどうかを確認するクラス、メタデータを書き込むクラスDateTime.Now、ユニットテストの時間を注入できるように抽象化するクラス、ロジックを含むすべてのファイルのインターフェイス、ファイルがあります各クラスの単体テストと、DIコンテナにすべてを追加するための1つ以上のファイルを格納します。 中小規模のアプリケーションの場合、SOLIDは非常に簡単に販売できます。誰もが保守性の利点と容易さを理解しています。ただし、非常に大規模なアプリケーションでは、SOLIDの価値提案が見られないだけです。だから私は、組織と管理を改善して、成長する痛みを乗り越える方法を見つけようとしています。 最近完了したタスクに基づいて、ファイルボリュームの例を少し強くしたいと思いました。ファイル同期要求を受信するために、新しいマイクロサービスのいずれかに機能を実装するタスクが与えられました。要求が受信されると、サービスは一連の検索とチェックを実行し、最終的にドキュメントをネットワークドライブと2つの個別のデータベーステーブルに保存します。 ドキュメントをネットワークドライブに保存するには、いくつかの特定のクラスが必要でした。 - …

5
Pythonが複数行のラムダを許可しないのはなぜですか?
BDFLがPythonラムダを単一行にすることを選択した具体的な理由を誰かが説明できますか? これはいい: lambda x: x**x これによりエラーが発生します。 lambda x: x**x ラムダを複数行にすると、通常のインデント規則が何らかの形で「乱れ」、例外を追加する必要があることを理解していますが、それだけのメリットはありませんか? たとえば、JavaScriptを見てください。これらの匿名関数なしでどのように生きることができますか?彼らは不可欠です。Pythonistasは、引数として渡すためにすべての複数行関数に名前を付ける必要をなくしたくないですか?
50 lambda  python 

2
ブール変数のプレフィックスとして常に「is」を使用する必要がありますか?[閉まっている]
isブール変数のプレフィックスとして常に使用する必要がありますか?過去の何かを示すブール値はどうですか?私が書く必要がありますisInitializedかwasInitialized?私は性質のために書くべきですIsManyMembersかHasManyMembers? ベストプラクティスはありますか?または、私はただ英語の規則に従って書くべきですか?


4
リフレクションを使用して汎用のセッターとゲッターを作成するのはなぜ悪い考えですか?
しばらく前に、すべての可変変数に対してゲッターとセッターを持たないようにする方法に関する質問に対するこの回答を書きました。当時、私はこれが悪い考えであると口にするのが難しい直感しか持っていませんでしたが、OPはそれを行う方法を明示的に求めていました。私はここでなぜこれが問題になるのかを検索し、この質問を見つけました。その質問の答えは、絶対に必要でない限りリフレクションを使用するのは悪い習慣であると考えているようです。 それで、特に一般的なゲッターとセッターの場合に、反射を避けるべきだという理由を誰かが言葉で表現できますか?
49 java  reflection 

6
Cで構造体を返す多くの関数が、実際に構造体へのポインターを返すのはなぜですか?
return関数のステートメントで構造全体を返すのではなく、構造へのポインタを返すことの利点は何ですか? 私はfopen他の低レベル関数のような関数について話しているが、おそらく構造体へのポインタを返す高レベル関数もあるだろう。 これは単なるプログラミングの質問ではなく、設計上の選択であり、2つの方法の長所と短所についてもっと知りたいと思っています。 構造体へのポインターを返すのが利点だと思った理由の1つは、ポインターを返すことで関数が失敗したかどうかをより簡単に判断できることNULLです。 完全な構造を返すのは、NULL私にとっては難しいか、効率が悪いでしょう。これは正当な理由ですか?

2
MVCを介したMVPの改善点は何ですか?
Model-View-Controller(MVC)およびModel-View-Presenter(MVP)パターンについて3日間読んでいます。そして、私を非常に悩ませる1つの質問があります。既にMVCがあったのに、ソフトウェアデザイナーがMVPを発明したのはなぜですか? MVCが解決しなかった(またはひどく解決した)が、MVPが解決できる問題は何ですか?MVPが解決するのはどの問題ですか? MVPの歴史と説明、またはMVCとMVPの違いに関する記事をたくさん読んでいますが、私の質問に対する明確な答えがありませんでした。 私が読んだ記事の1つで、次のように言われました。 次に、Model View Presenterを使用します。これは、最新のコンポーネントベースのグラフィカルユーザーインターフェイスに適用した場合のMVCパターンの不備に対する応答でした。最新のGUIシステムでは、GUIコンポーネント自体が、中央のコントローラーではなく、マウスの動きやクリックなどのユーザー入力を処理します。 だから、理解できませんが、実際には別の方法で、GUIコンポーネントがユーザー入力を自分で処理しないようにすることはできますか?そして、「自分で処理する」とはどういう意味ですか?

7
同じメンバーで異なる名前の2つの構造体は、良いアイデアですか?
私は極座標とデカルト座標の両方を扱うプログラムを書いています。 それがポイント、との1の種類ごとに二つの異なる構造体を作成しても意味がないXし、Yメンバーと1はであるRとThetaメンバー。 それとも、あまりにも多くのことをされ、でちょうど1構造体を持っている方が良いですfirstし、secondメンバーとして。 私が書いているのは簡単で、あまり変わりません。しかし、私はデザインの観点から何が良いのか興味があります。 最初のオプションの方が良いと思います。より読みやすく、型チェックの利点が得られます。
49 design 

11
「推論するのは簡単」-それはどういう意味ですか?[閉まっている]
他の開発者がそのフレーズを使用して、いくつかのパターンを「宣伝」したり、ベストプラクティスを開発したりすることを何度も耳にしました。ほとんどの場合、このフレーズは、関数型プログラミングの利点について話しているときに使用されます。 「推論するのは簡単」というフレーズは、説明やコードサンプルなしでそのまま使用されています。だから私にとっては、次の「話題」の言葉のようになり、より「経験のある」開発者が講演で使用します。 質問:「推論するのは簡単ではない」例をいくつか挙げてください。「推論するのは簡単」の例と比較できますか?

10
パラメーターとしてのカスタムオブジェクトを避ける必要がありますか?
Studentというカスタムオブジェクトがあるとします。 public class Student{ public int _id; public String name; public int age; public float score; } そして、生徒の情報を表示するために使用されるクラスWindow: public class Window{ public void showInfo(Student student); } 正常に見えますが、Windowを個別にテストするのは簡単ではありません。関数を呼び出すには、実際のStudentオブジェクトが必要だからです。そこで、Studentオブジェクトを直接受け入れないようにshowInfoを変更しようとしています。 public void showInfo(int _id, String name, int age, float score); ウィンドウを個別にテストする方が簡単です: showInfo(123, "abc", 45, 6.7); しかし、修正版には別の問題があることがわかりました。 生徒の変更(例:新しいプロパティの追加)には、showInfoのメソッド署名を変更する必要があります Studentに多くのプロパティがある場合、Studentのメソッド署名は非常に長くなります。 それでは、カスタムオブジェクトをパラメーターとして使用するか、オブジェクトの各プロパティをパラメーターとして受け入れますか?

6
多くの小さなリクエストと少数の大きなリクエスト(APIデザイン)
現在、次のような組織でプロジェクトに取り組んでいます。 クライアント -REST APIを介してメインサーバーからデータを取得します。 サーバー -サードパーティAPIを介して他のさまざまなサーバーからデータを要求します サードパーティ API-サーバーにデータを提供する私の制御できないサービス(Reddit、Hackernews、Quoraなど) 議論のために、クライアントが最初に各サードパーティAPIからのアイテムのリストを必要とするとしましょう。このリストからアイテムが選択されます。この時点で、クライアントはアイテムの完全なコンテンツとアイテムへの応答(コメント)を表示する必要があります。私は3つのオプションの間で決定しようとしています: アラカルト このアプローチでは、サーバーに3つのエンドポイントがあります。1つはアイテムのリストを取得し、1つはアイテムのメインコンテンツを取得し、もう1つはアイテムの応答を取得します。 長所:必要以上にリクエストを送信することはありません。リクエストは小さくなければならないので、一般的には高速になります。 短所:私は多くの要求をしなければなりません。リストから項目を選択した後、ユーザーはメインコンテンツを見る前に待たなければならない場合があり、それから応答を見るためにさらに長く待たなければならない場合があります サーバー側キャッシュ このリクエストでは、サーバーを1回呼び出して、すべてのソースのすべてのデータを「フェッチ」します。その後、データはサーバーにキャッシュされます。クライアントは以前と同じRESTエンドポイントを持つことになりますが、サーバーには既にデータがあり、それをクライアントにフィードするだけなので、呼び出しと呼び出しの間にあまり待つ必要はありません。 長所:クライアント側での実装は依然として簡単ですが、遅延の問題はありません 短所:サーバー側が少し複雑で、最初の呼び出しには本当に長い時間がかかる可能性があります。 クライアント側キャッシュ このシナリオは前のシナリオと似ていますが、クライアントがサーバーに対して1回だけ要求を行うという点が異なります。つまり、すべてのデータを提供します。ここから、データを保存して適切に使用するのはクライアントの責任です。 長所:簡単なサーバー実装、最初の呼び出し後は非常に高速 短所:最初の呼び出しは非常に遅く、より複雑なクライアント側の実装になります どちらが最善のアプローチであるのか、あるいは明らかな解決策が欠けているのかもしれません。どんなアドバイスも大歓迎です!

3
C ++で強く型付けされたtypedef
私は、コンパイル段階で特定の種類のバグをキャッチするために、強く型付けされたtypedefを宣言する方法を考えていました。多くの場合、intをいくつかのタイプのIDにtypedefするか、位置または速度を指定するベクトルを入力します。 typedef int EntityID; typedef int ModelID; typedef Vector3 Position; typedef Vector3 Velocity; これにより、コードの意図をより明確にすることができますが、長い夜のコーディングの後、さまざまな種類のIDを比較したり、速度に位置を追加したりするなど、愚かな間違いを犯す可能性があります。 EntityID eID; ModelID mID; if ( eID == mID ) // <- Compiler sees nothing wrong { /*bug*/ } Position p; Velocity v; Position newP = p + v; // bug, meant p + v*s but …
49 c++  c++11  type-safety 

8
プログラミング言語にボトムタイプがある理由はありますか?
ボトムタイプは、数学タイプ理論に主に現れる構成です。空のタイプとも呼ばれます。値を持たないタイプですが、すべてのタイプのサブタイプです。 関数の戻り値の型がボトム型の場合、それは戻り値がないことを意味します。期間。永久にループするか、例外をスローする可能性があります。 プログラミング言語でこの奇妙なタイプを持つことのポイントは何ですか?それほど一般的ではありませんが、ScalaやLispなどの一部に存在します。

5
すべての<algorithm>関数がコンテナーではなく範囲のみを取得するのはなぜですか?
には多くの便利な関数がありますが&lt;algorithm&gt;、それらはすべて「シーケンス」、つまりイテレータのペアで動作します。たとえば、コンテナがあり、そのstd::accumulate上で実行したい場合、次のように書く必要があります。 std::vector&lt;int&gt; myContainer = ...; int sum = std::accumulate(myContainer.begin(), myContainer.end(), 0); 私がやろうとしているのは: int sum = std::accumulate(myContainer, 0); 私の目では、これはもう少し読みやすく、はっきりしています。 コンテナの一部のみを操作したい場合があるかもしれないので、範囲を渡すオプションがあることは間違いなく便利です。しかし、少なくとも私の経験では、それはまれな特別なケースです。私は通常、コンテナ全体を操作したいと思うでしょう。 これは、コンテナとのコールを取るラッパー関数書くのは簡単だbegin()し、end()その上に、このような便利な機能が標準ライブラリに含まれていません。 このSTL設計の選択の背後にある理由を知りたい。

3
C ++で同じ目的でインターフェイスを使用できる一方で、PImplパターンのポイントは何ですか?
C ++でPImplイディオムを使用する多くのソースコードが表示されます。その目的はプライベートデータ/タイプ/実装を非表示にすることであるため、依存関係を削除し、コンパイル時間とヘッダーインクルードの問題を減らすことができると思います。 しかし、C ++のインターフェイス/純粋な抽象クラスにもこの機能があり、データ/型/実装を隠すために使用することもできます。また、オブジェクトを作成するときに呼び出し元にインターフェイスを表示させるために、インターフェイスのヘッダーでファクトリメソッドを宣言できます。 比較は次のとおりです。 費用: パブリックラッパー関数の実装を繰り返す必要さえないため、インターフェイスの方法のコストは低くvoid Bar::doWork() { return m_impl-&gt;doWork(); }なります。インターフェイスで署名を定義するだけです。 よく理解された: インターフェイステクノロジーは、すべてのC ++開発者によく理解されています。 パフォーマンス: インターフェイス方法のパフォーマンスは、PImplイディオムよりも悪くありません。どちらも余分なメモリアクセスです。パフォーマンスは同じだと思います。 以下は私の質問を説明するための擬似コードです。 // Forward declaration can help you avoid include BarImpl header, and those included in BarImpl header. class BarImpl; class Bar { public: // public functions void doWork(); private: // You don't need …

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