ソフトウェア工学

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

1
おしゃべりなインターフェースを回避する方法
背景: サーバーアプリケーションを設計し、さまざまなサブシステム用に個別のDLLを作成しています。話を簡単にするために、2つのサブシステムがあるとします。1)Users2)Projects ユーザーのパブリックインターフェイスには、次のようなメソッドがあります。 IEnumerable<User> GetUser(int id); また、Projectsの公開インターフェースには次のようなメソッドがあります。 IEnumerable<User> GetProjectUsers(int projectId); したがって、たとえば、特定のプロジェクトのユーザーを表示する必要がある場合は、呼び出すことができます。これによりGetProjectUsers、オブジェクトがデータグリッドなどに表示するのに十分な情報を返します。 問題: 理想的には、Projectsサブシステムはユーザー情報も保存せず、プロジェクトに参加しているユーザーのIDのみを保存する必要があります。提供するためにGetProjectUsers、それが呼び出す必要GetUserのUsers自身のデータベースに格納された各ユーザーIDのシステム。ただし、これには多数の個別のGetUser呼び出しが必要であり、Userサブシステム内に多数の個別のSQLクエリが発生します。私は実際にこれをテストしていませんが、このおしゃべりなデザインを使用するとシステムのスケーラビリティに影響します。 私はさておき、サブシステムの分離を置けば、私は可能性があり、両方のシステムにより、単一のスキーマアクセス可能で、すべての情報を保存し、Projects簡単に行うことができJOIN、単一のクエリですべてのプロジェクトのユーザーを取得します。クエリ結果からオブジェクトProjectsを生成Userする方法も知っている必要があります。しかし、これは多くの利点を持つ分​​離を壊します。 質問: 誰もがこれらの個別のGetUser呼び出しをすべて回避しながら、分離を維持する方法を提案できますGetProjectUsersか? たとえば、私が考えていたのは、ユーザーが外部システムにラベルと値のペアでユーザーに「タグを付ける」機能を与え、特定の値を持つユーザーに要求することでした。たとえば、 void AddUserTag(int userId, string tag, string value); IEnumerable<User> GetUsersByTag(string tag, string value); 次に、プロジェクトシステムは、プロジェクトに追加された各ユーザーにタグを付けることができます。 AddUserTag(userId,"project id", myProjectId.ToString()); GetProjectUsersの実行中、1回の呼び出しですべてのプロジェクトユーザーをリクエストできます。 var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString()); 私がこれについて確信が持てない部分は、はい、ユーザーはプロジェクトにとらわれませんが、実際にはプロジェクトメンバーシップに関する情報はプロジェクトではなくユーザーシステムに保存されます。私は自然に感じないので、ここで私が見逃している大きな欠点があるかどうかを判断しようとしています。

3
データベースの排他的アークとは何ですか?なぜそれが悪いのですか?
私は、stackoverflowに関する開発者のQ&Aによって発生した最も一般的なデータベース設計の間違いを読んでいました。最初の答えは、排他的な弧についての句がありました: 排他的アークは、テーブルが2つ以上の外部キーで作成され、そのうちの1つだけがnull以外になる可能性がある一般的な間違いです。大ミス。1つには、データの整合性を維持することがはるかに困難になります。結局のところ、参照整合性があっても、これらの外部キーの2つ以上の設定を妨げるものはありません(複雑なチェック制約にもかかわらず)。 なぜ独占アークが邪悪なのかよくわかりません。基本的には理解できなかったのでしょう。独占アークについての良い説明はありますか?

1
依存関係の促進戦略:サイロ化またはオーケストレーション?
私たちは、相互に依存し合う多くのアプリとWebサービス(一部のパブリック向け製品、一部の内部およびプライベート「バックエンド」の一部)を持っています。これらの各コンポーネントには、4つの環境(特定の目的に役立つサーバー/ノードのクラスター)があります。 非生産 DEV-CIがプッシュ変更を構築する統合開発環境。エンジニアがローカルで再現できないバグを見つけるのに役立ちます QA -分離されたQA /テスト環境 DEMO -ビジネス関係者のための安定したUAT環境 製造 LIVE -私たちのライブ/制作環境 コードの昇格は次のようになります:(LOCAL開発者のマシン)=> DEV=> QA=> DEMO=> LIVE。 と呼ばれるmyappRESTful Webサービスによってサポートされるアプリケーションがありmyws、それ自体がと呼ばれるDBによってサポートされているとしmydbます。 現在、これらの依存関係の中で私が「オーケストレーション」プロモーションと呼ぶものmyapp-devがmyws-devありますmydb-dev。が使用するポイント。同様に、myapp-qaがmyws-qaを使用することを指すmydb-qa。同じのためにDEMOとLIVE。 これの問題は、たとえばにmyapp変更を加えるたびにmyws、mydbにも変更を加える必要があることです。しかし、各DEV環境は依存関係の環境を指しているため、DEVこれらの変更をすべて同時にスケジュールしてロールアウトする必要があります。さらに、1つのビルドが不安定になったり壊れたりすると、他の上流コンポーネントがダウンすることがよくあります。たとえば、開発者がを変更するときに何かを壊した場合、通常mydb-dev、myws-devおよびmyapp-devクラスターも不安定になります。 これを解決するために、私は「サイロ化された」プロモーション戦略と呼ぶものの提案をまとめます。すべてのコンポーネント間の依存関係はこのガイドラインに従います。 上流の依存DEMO関係は、すべての非実稼働環境(DEV、QAおよびDEMO)の下流の依存関係の環境に依存します。そして 上流の依存LIVE関係は、本番環境の下流の依存関係の環境に依存します この規則を使用myapp-devするとmyws-demo、実際にはをポイントし、を使用しますmydb-demo。同様に、およびmyapp-qaも指します。myws-demomydb-demo 私は見つけることができることをここに利点があるビルドの安定化:それははるかに少ない可能性が高いということであるDEMOコードはにそれを作ることができないので、特定のコンポーネントのための環境が不安定になるDEMOの両方の厳格なテストなしDEVとQA。 この方法で見つけられる唯一の欠点DEMOは、特定のコンポーネントで問題が発生した場合、すべての上流の依存関係のすべての非本番環境が突然破壊されることです。しかし、DEVとで実行されたテストのために、これが非常にまれに発生するはずであることに反対しQAます。 これはしていまし解決して、この問題とその解決策が既に(私が画策/サイロ化呼び出しています何のほかに)それらに名前を持っている場合、私は驚かないだろう多くの開発者(ずっと賢く自分よりも経験)という問題です。だから私は尋ねます:サイロ化されたプロモーション戦略のメリットはどんな短所よりも重要ですか、そして私がここで見落としているかもしれない短所は何ですか?

1
マイクロコントローラー用RTOSのメッセージキュー
現在、マイクロコントローラー用のRTOSを書いています。全体がC ++ 11で書かれています-誰かが興味を持っていて、リポジトリへのリンクが一番下にある場合。 現在私は、スレッド間(または、割り込みハンドラーとスレッド間、または割り込みハンドラーと他の割り込みハンドラー間)でオブジェクトを受け渡すための単純なデータキューであるクラスを作成しています。通常、私は他のプロジェクトにあるいくつかの共通のAPIを追跡しようとすると、まだ私は持っている同時キューのいずれかの例が見つかりませんでしたemplace()機能とサポートタイムアウトを。 私の一般的な「問題」は、次の2つのインターフェースを決定できないことです。 (std::chrono::duration<Rep, Period>はテンプレートタイプです。わかりやすくするためにテンプレートのボイラープレートは省略しています) 最初のバージョン: template<typename T> class FifoQueue { public: ... template<typename... Args> int tryEmplaceFor(std::chrono::duration<Rep, Period>, Args&&... args); int tryPopFor(T&, std::chrono::duration<Rep, Period>); int tryPushFor(const T&, std::chrono::duration<Rep, Period>); int tryPushFor(T&&, std::chrono::duration<Rep, Period>); ... } 2番目のバージョン: template<typename T> class FifoQueue { public: ... template<typename... Args> int tryEmplaceFor(std::chrono::duration<Rep, Period>, …

3
プライベート依存リンクをsetup.pyでどのように処理する必要があるか
仕事ではプライベートpypiサーバーを使用します。このpypiサーバーは、依存関係リンクとして指定されています。 ... from setuptools import setup config = ConfigParser.ConfigParser() rc = os.path.join(os.path.expanduser('~'), '.pypirc') config.read(rc) dependency_links = [ 'https://{}:{}@<private_url>'.format( config.get('dc', 'username'), config.get('dc', 'password'))] setup( dependency_links=dependency_links, ...) これは、ほとんどの場合問題なく機能します。ただし、少し前に、クライアントサーバーにパッケージをインストールする必要がありました。この.pypircため、パッケージをインストールする前に、有効なものをコピーする必要がありました。 また、上記のコードは汚いハックのように感じられます。 資格情報をハードコーディングせずに、保護された依存関係リンクを指定する適切な方法は何ですか?
10 python 

2
単体テストと統合テストのコードカバレッジレポートを分けますか、それとも両方のレポートを1つにしますか?
単体テストと統合テストの個別のコードカバレッジレポート、または両方のコードカバレッジレポートが必要ですか? この背後にある考え方は、コードカバレッジにより、コードが可能な限りテストによってカバーされていることを確認できるということです(とにかく、マシンができる限り)。 個別のレポートがあると、単体テストでカバーされなかったこと、統合テストでカバーされなかったことを知るのに便利です。しかし、この方法では、総カバレッジ率を確認できません。

1
ゲーム業界では、ゲーム/レンダリングの視覚的な部分に自動テストを使用していますか?どうやって?
ゲームの一部は、自動化された方法(ロジック、数学、入力処理)で簡単にテストできます。しかし、純粋に視覚的で簡単にテストできないものもたくさんあります。 ゲーム業界がこれをすべて手動テストに任せたとしたら、私は驚きます。十分なお金があるので、少なくともゲームの視覚的な側面のいくつかを回帰テストできるように努力が払われたと思います。 これは本当ですか?もしそうなら、ゲームのレンダリングをテストすることができる可能な方法は何ですか?出力のキャプチャと画像の比較(これは信頼できますか?)?低レベルでグラフィックカードからのデータをインターセプトしますか?その途中で頂点情報(など)をキャプチャするグラフィックスカード?可能性はたくさんあるようです。しかし、これに関する情報は見つかりません:( 注:この質問はこの質問の重複であるとマークされていましたが、これを行う方法について特定のtech / frameworks / toolsについては質問していませんが、このプラクティスに関するアイデア、および実際のゲーム業界が行っていること(ある場合)彼らはまったくそうします)。

3
クリーンなコードとハイブリッドオブジェクトおよび機能羨望
そのため、最近、コードにいくつかの主要なリファクタリングを行いました。私がしようとした主なことの1つは、クラスをデータオブジェクトとワーカーオブジェクトに分割することでした。これは、とりわけ、Clean Codeの次のセクションに触発されました。 ハイブリッド この混乱は、半分のオブジェクトと半分のデータ構造である不幸なハイブリッドデータ構造につながることがあります。それらには重要な機能を果たす関数があり、パブリック変数またはパブリックアクセサーとミューテーターのいずれかがあり、すべての目的と目的のためにプライベート変数をパブリックにして、他の外部関数がそれらの変数を手続き型プログラムが使用する方法で使用するように誘惑しますデータ構造。 そのようなハイブリッドは、新しい関数を追加することを難しくしますが、新しいデータ構造を追加することも難しくします。彼らは両方の世界で最悪です。それらを作成しないでください。それらは、作者が関数や型からの保護を必要としているかどうか、またはさらに悪いことに無知である混乱した設計を示しています。 最近、私はワーカーオブジェクトの1つ(たまたま、Visitorパターンを実装する)のコードを見て、これを確認しました。 @Override public void visit(MarketTrade trade) { this.data.handleTrade(trade); updateRun(trade); } private void updateRun(MarketTrade newTrade) { if(this.data.getLastAggressor() != newTrade.getAggressor()) { this.data.setRunLength(0); this.data.setLastAggressor(newTrade.getAggressor()); } this.data.setRunLength(this.data.getRunLength() + newTrade.getLots()); } 私はすぐに「!このロジックがであるべき機能の羨望自分自身に言ったData-特に、クラスhandleTradeメソッド。handleTradeとupdateRunする必要があり、常に一緒に起こります」。しかし、「データクラスは単なるpublicデータ構造です。それを始めれば、ハイブリッドオブジェクトになるでしょう!」 何が良いのか、そしてその理由は?どちらを行うかをどのように決定しますか?

2
クイックソートの悪い例は何ですか?
私はクイックソートについて学習しており、クイックソートが困難なさまざまな配列を例示したいと思います。私が念頭に置いているクイックソートには、初期ランダムシャッフルはなく、2つのパーティションがあり、中央値を計算しません。 これまでに3つの例を考えました。 [1,2,3,4,5,6,7,8,9,10] - when the array is sorted [10,9,8,7,6,5,4,3,2,1] - when the array is reversed [1,1,1,1,1,1,1,1,1,1] - when the array is the same values [1,1,1,2,2,2,3,3,3,3] - when there are few and unique keys たとえば、これについてはよくわかりません。 [1,3,5,7,9,10,8,6,4,2] では、クイックソートが(ほぼ)理想的である配列と比較して困難な配列は何でしょうか?

2
JVMはmainメソッドによってスローされた例外をどのように処理しますか?
私は例外を理解し、それらをスローし、それらを処理し、それらをコールスタックの下位のメソッド(つまりthrows)に伝達します。 私が理解していないのはこれです: public static void main(String[] args) throws Exception { ... } 今、私はをmainスローする場合Exceptionに、JVMがそれを処理すると仮定します(正しい?)。その場合、私の質問は次のとおりです。 JVMはスローされた例外をどのように処理しmainますか?それは何をするためのものか?
10 java  exceptions  jvm 

1
マシンコードJITと実行無効ビット
CPU / OSに実行無効ビットがある場合、ランタイム生成のマシンコード(JITの出力など)は実際にはどのようにCPUによって実行されますか? 私の知る限りでは、多くの最新のプロセッサおよびオペレーティングシステムは、NXのサポートは、任意のアドレスに格納されている防止マシンコード、(インテルおよびARMを含む)は、ビット含む他の実行中からコンパイルされたバイナリのコードセクションより。明らかに、これはシェルコードインジェクション攻撃を防ぐので、優れたセキュリティ上の利点です。 しかし、動的にマシンコードを生成するLLVMのようなJITエンジンはどうやってこれを回避するのでしょうか?
10 machine-code  jit  llvm 

1
GCCがC ++とCのバイソンから再帰的降下パーサーに切り替えたのはなぜですか?
それを必要とする言語変更、またはバイソンがもはや適切または最適ではなくなったいくつかの実際的な理由はありましたか? 私は上を見ウィキペディア彼らが参照し、切り替えることGCC 3.4とGCC 4.1のリリースノート。 これらのリリースノートには次のように記載されています。 手書きの再帰降下C ++パーサーは、以前のGCCリリースからのYACC派生のC ++パーサーに取って代わりました。新しいパーサーには、C ++ソースコードのより適切な解析、拡張機能の処理、適切なセマンティクス分析と解析の間の(可能な場合は)明確な分離に必要な、大幅に改善されたインフラストラクチャが含まれています。新しいパーサーは、古いパーサーで見つかった多くのバグを修正します。 そして: 古いBisonベースのCおよびObjective-Cパーサーは、新しい、より高速な手書きの再帰下降パーサーに置き換えられました 私が知りたいのは、彼らが抱えていた実際の問題と、Bisonを使用して解決することが不可能/非実用的である理由です。
10 c++  c  parsing  compiler 

3
パック構造体がC言語の一部ではないのはなぜですか?
すべてのCコンパイラは、C構造体(__attribute__ ((__packed__))または#pragma pack())を「パック」するオプションを提供します。信頼できる方法でデータを送信または保存する場合は、パッキングが必要であることは誰もが知っています。これは、C言語の最初の日からの要件でもあったに違いありません。 では、なぜパック構造体がC言語仕様の一部ではないのでしょうか。それらの必要性が数十年前から知られているにもかかわらず、それらはC99またはC11にさえありませんか?何が欠けていますか?なぜコンパイラ固有なのですか?
10 c 

5
「charset」が一般的な使用法で「エンコード」を本当に意味するのはなぜですか?
私を長い間混乱させてきたのは、多くのソフトウェアが「charset」と「encoding」という用語を同義語として使用していることです。 人々がユニコードの「エンコーディング」に言及するとき、それらは常にユニコード文字をASCIIやUTF-8のようなバイトのシーケンスとして表すためのルールセットを意味します。これは合理的で直感的なようです。これは、指定したルールセットを使用して、これらの文字をバイトとして「エンコード」するという考え方です。 これらのルールセットは、すべてのユニコード文字の一部のサブセットを「エンコード」する機能しか提供しないことがあるので、「文字セット」の短縮形である「文字セット」は、ユニコード文字のセットを意味するだけで、これらの文字はエンコードされます。したがって、エンコーディングは文字セットを意味します(128文字のエンコードに関するルールのみを持つASCIIのようなエンコーディングは、それらの128文字の文字セットに関連付けられます)が、文字セットはエンコーディングを意味する必要はありません(たとえば、UTF-8、UTF) -16とUTF-32はすべて異なるエンコーディングですが、同じ文字セットをエンコードできます)。 それでも-そして、これが私の質問の核心です-「charset」という単語の実際の用法は、単語の構成が意味するものと一致しません。ほとんどの場合、「エンコード」を意味するために使用されます。 例えば: charsetHTML の属性は、エンコーディングを指定するために使用されます CharsetJavaのsはエンコーディングです charsetsとcharacter setsMySQLでは、これもエンコーディングです。 この好奇心の強い(乱用)言語の使用は何歳ですか?この「直感的ではない」「文字セット」の定義はどのようにして生まれましたか?それはおそらく、実際に、使用中のエンコーディングとそれらがサポートする文字セットとの間に1対1のマッピングが実際にあった時代に由来するのでしょうか?それとも、この単語の定義を規定する特に影響力のある標準や仕様はありましたか?

6
独自のそれぞれのコントローラーを取得する必要があるものを決定する方法は?
PHPで構築したWebアプリケーションでMVCパターンを使用しています。 一連のアクションに新しい専用コントローラーが必要か、それとも既存のコントローラー内に配置する必要があるかを判断するのに常に苦労しています。 コントローラーを作成する際に従うべき良い経験則はありますか? 例えば、私は持つことができます: AuthenticationController アクションあり: index() ログインフォームを表示します。 submit() フォームの送信を処理します。 logout()、自明です。 または LoginController アクションあり: index() ログインフォームを表示します。 submit() フォームの送信を処理します。 LogoutController アクション付き: index() ログアウトを処理します。 または AccountController アクションあり: loginGet() ログインフォームを表示します。 loginPost() ログインフォームの送信を処理します。 logoutGet() ログアウトを処理します。 registerGet() 登録フォームを表示します。 registerPost() フォームの送信を処理します。 また、アカウントに関連するその他のアクション。
10 mvc 

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