ソフトウェア工学

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

5
「最低の開発者」として技術的負債と戦う?
あなたが会社で働いていて、あなたがしていることは彼らのためにソフトウェアを開発しているとしましょう。あなたは全体像を知らないか、わずかかもしれません。あなたが持っているのは、問題追跡システムを介して割り当てられたタスクです。タスクが与えられ、タスクがそれらを説明するように動作させ、送り返します。2つの整数を追加するのと同じように: function add(a,b){return a + b;} しかし、後でプロジェクトが進むにつれて、addより複雑になるにつれて、パラメーターを追加して値を返す関数だけでなく、何らかのアーキテクチャが必要になっていることに気付くでしょう。しかし、あなたはそれを知りませんでした。そもそも、彼らが必要とするのはその単純なことだけでしたadd。addがそれほど複雑になるとは思わなかった。 プロジェクトはより多くの機能を備えて進行しますが、そもそもこれは期待していなかった機能です。そして最後には、既存のコードを壊したり書き換えたりすることを避けるために、ハッキングを積み重ね続け、関数のレイヤーを重ねます。 これらの状況にどのように対処しますか?「最低開発者」としての技術的負債とどのように戦いますか? 明確化: あなたは「実装者」であり、階層の最下位です。 問題は見えますが、問題については発言権がありません。 技術的な負債を定量化したり、ツールを探したりするわけではありません。 3番目の「重複」について リファクタリングとリライト-あなたはあなたのタスクにロックされています。あなたは余分に行うために支払われていません。 アーキテクチャの概要-システム全体は知っていますが、アーキテクチャについてはわかりません。 コードフリーズ-電話ではありません。あなたは管理者ではありません。 モジュール化-アーキテクチャのアイデアはありません。モジュールは要件の変化に応じて変化します。 自動テスト-なし。

2
モナドは、継承階層の実行可能な(たぶん望ましい)代替手段ですか?
このようなモナドの言語に依存しない説明を使用します。最初にモノイドを説明します。 モノイドは(おおよそ)のパラメータとして、いくつかの種類を取り、同じ型を返す関数のセットです。 モナドを取る関数の(おおよそ)が設定されているラッパーパラメータとしてタイプと同じラッパー・タイプを返します。 これらは説明であり、定義ではないことに注意してください。その説明を気軽に攻撃してください! したがって、OO言語では、モナドは次のような操作構成を許可します。 Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land() モナドは、含まれるクラスではなく、これらの操作のセマンティクスを定義および制御することに注意してください。 従来、OO言語では、クラス階層と継承を使用してこれらのセマンティクスを提供していました。したがってBird、メソッドtakeOff()、flyAround()およびを持つクラスがありland()、Duckはそれらを継承します。 しかし、その後、penguin.takeOff()失敗するため、飛べない鳥とのトラブルに巻き込まれます。例外のスローと処理に頼らなければなりません。 また、ペンギンがであると言うとBird、たとえばの階層もある場合、多重継承の問題に遭遇しますSwimmer。 基本的に、私たちはクラスをカテゴリーに分類し(カテゴリー理論に謝罪して)、個々のクラスではなくカテゴリーごとにセマンティクスを定義しようとしています。しかし、モナドは階層よりもそれを行うためのはるかに明確なメカニズムのようです。 したがって、この場合、Flier<T>上記の例のようなモナドができます。 Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land() ...そして、インスタンス化することはありませんFlier<Penguin>。おそらくマーカーインターフェイスを使用して、静的な型付けを使用してそれを防ぐこともできます。または、実行時の機能チェックで解決します。しかし、実際には、プログラマーはゼロで割るべきではないという意味で、ペンギンをフライヤーに入れてはいけません。 また、より一般的に適用できます。チラシは鳥である必要はありません。たとえばFlier<Pterodactyl>、またはFlier<Squirrel>、これらの個々のタイプのセマンティクスを変更せずに。 型階層ではなく、コンテナ上の構成可能な関数によってセマンティクスを分類すると、特定の階層に適合する「やる、しない」クラスの古い問題を解決します。また、簡単&はっきりと同じように、クラスの複数の意味を可能にするFlier<Duck>だけでなく、Swimmer<Duck>。動作をクラス階層で分類することにより、インピーダンスの不一致に苦労しているようです。モナドはそれをエレガントに処理します。 私の質問は、継承よりも合成を優先するようになったのと同じように、継承よりもモナドを優先することも理にかなっていますか? (ところで、これがComp Sciにあるのか、それともComp Sciにあるのかはわかりませんでしたが、これは実際的なモデリングの問題のように見えます。

7
静的データをデータベースまたは他の場所に保存する必要がありますか?
現時点ではいくつかのソフトウェアに取り組んでいますが、これでどのルートを取るべきかわかりません。モバイルデバイスのどこかに保存するデータがあります。データは決して変化せず、階層的な関係があり、表示の入力に使用されます。このデータにはかなりの量があります。 次のオプションがあります。 列挙型/オブジェクトのセット XMLファイル 組み込みSQLiteデータベース この特定のケースでは、enumsオプションが最も作業が少ないと思いますが、そのようなコードに埋め込まれているデータから匂いがします。 XMLファイルは最も理にかなっていると思いますが、それを解析することはリソースヒットになります。 データベースのパフォーマンスへの影響はそれほど大きくありませんが、静的データでは過剰すぎるようです。 ここで正しい設計パスはどれですか? 注:「決して」変更しないと、変更されることはほとんどありません。問題のデータは一連の政府標準のモデルであるため、将来のある時点で変更される可能性がありますが、定期的に変更されることはなく、標準の変更によってソフトウェアが自動的に更新されることもありません要件の変更をトリガーします。
20 design 

1
名前空間の長所と短所対PHPのinclude / require?
最近、PHPで名前空間を使用し始めました。初めて見たとき、その構文は見苦しく、決して使用しないと思いました。ただし、include / requireステートメントを再度記述する必要がないように、オートローダー(spl_autoload_register)を作成しました。 名前空間が好きですが、include / requireステートメントよりも客観的な利点がありますか、それとも同じ目標を達成するためのまったく同じ方法ですか?
20 php  namespace 

6
段階的な入力:「静的型システムを持つほとんどすべての言語には動的型システムもあります」
Aleks Bromfieldによるこの主張は次のように述べています。 静的型システムを持つほとんどすべての言語には、動的型システムもあります。C以外に、私は例外を考えることはできません これは有効な主張ですか?実行時のReflectionクラスまたはLoadingクラスを使用すると、Javaがこのようになりますが、この「漸進型付け」の考え方を多数の言語に拡張できますか?

6
超高レベルの言語はありますか?[閉まっている]
閉まっている。この質問はトピック外です。現在、回答を受け付けていません。 この質問を改善したいですか? 質問を更新して、 Software Engineering Stack Exchangeのトピックになるようにします。 5年前に閉鎖されました。 歴史的に、HLLはC、FortranまたはPascalのようなものであり、VHLLはRubyまたはPythonのようなものです。私は4GL、5GL、DSL、LOPという用語に精通しており、定義についてはウィキペディアを読むべきではありません。UHLLを探しています。 私の質問は、生産性が一桁以上高いコンピューター言語がありますか? 生産性が高いということは、オーサリングされたコードが少なくなり、結果を達成するプログラマの時間が減り、バグやデバッグが減り、コードと要件の概念的リンクが密接になり、変更と保守の労力が減るということです。 私が興味を持っている主なドメインは、GUIまたはブラウザのフロントエンド、データの永続性、および印刷や電子メールなどの他のシステムへの接続を備えた汎用のビジネスおよびコンシューマアプリケーションです。他の人は他の場所に集中するかもしれません。 これらの言語の一部はドメイン固有である可能性があり、それらは大規模で機能的なアプリケーションの構成機能にすぎない可能性があることを認識しています。Excelスプレッドシートはこのカテゴリに分類されます。 これらの言語の一部は一般的に見えるかもしれませんが、それでも範囲が狭く、多くの問題に適さない可能性があることを認識しています。たとえば、Matlabは、主にユーザーインタラクションとテキストデータを扱うプログラムには適していません。 VHLLとの類推によって、UHLLにあるかもしれない機能のいくつかを知っています。次の1つ以上を見つけることを期待しています(そして、リストに自由に追加してください)。 GUIフォームの描画は、GUIフォームのプログラムです 行、列、ヘッダーを含むテーブルは、データベース内のテーブルのプログラムです 宣言ロジックは、IFステートメントなしで、何をいつ実行するかを指示します FORループなしのデータセットの操作 データ駆動、パターンマッチング、ツリーウォーキングなどの非順次実行 この質問の動機は、比較的単純なビジネス要件を大量のコードに変換して、コンピューターが望むものや必要なものを提供するという大変な努力にますます飽き飽きしていることです。問題は、私の痛みを分かち合い、言語のレベルを上げ、コンピューターにもっと多くのハードワークをさせることに取り組んでいる他の人を見つけることです。これは1970年代から80年代の主要な焦点でしたが、まだ起こっていますか? これらは私の質問に対するいくつかの提案された回答であり、私が知っている言語を要約または列挙するためにここに提供されており、私の見解ではどれが足りないかです。 HLLまたはVHLLであり、より高いレベルに属する個々の機能を含む多くの言語があります。私はそれらのほとんどを使用しました(しばしばひどく)。彼らが含まれます マクロと自己変更機能を備えたLisp Haskell、データ依存性とパターンマッチング 行とテーブルを扱うSQL Rebol、それは賢いようですが、私は本当にそれを取得しません APL(およびJ)、その多次元配列と超小型演算子 LINQを使用したC# 素晴らしいコレクションと正規表現が組み込まれたAWK / Perl / Python / Ruby これらの言語には低レベルの機能が多すぎてUHLLにはなりません。プログラマーは、有用なプログラムのために、多くの低レベルの構成体を作成する必要があります。 RAD / 4GLパッケージがあります。私はいくつかを使用しました: dBase / Foxpro Dataflex / Powerflex(私の製品) アクセス PowerBuilder そして、私が使ったことのないものがたくさんあります。ほとんどの場合、言語はせいぜいHLLですが、パッケージにはフレームワークが含まれており、言語とパッケージ間の特権接続が含まれているため、アプリケーションを迅速に構築できます。なぜこのアプローチが蒸気を使い果たしたのかはわかりませんが、いずれにしてもUHLLはそうではありません。 生のフレームワーク/ライブラリがあります。私はいくつか使用しました: …

4
リポジトリパターンを使用する場合
最近、リポジトリパターンをORMと組み合わせて使用​​するのは良い習慣ではないことを読みました。私の理解から、これはSQLデータベース上で提供する抽象化がパターンに含まれるには漏れやすいためです。 これについていくつか質問があります。 ORMを切り替えたい場合はどうしますか?リポジトリに含まれていない場合、アプリケーションにORM固有のコードが含まれます。 ORMを使用せず、データアクセスとオブジェクトデータの入力にADO.NETを使用している場合、リポジトリパターンはまだ有効ですか? リポジトリパターンではなくORMを使用する場合、よく使用されるクエリはどこに保存しますか?各クエリをクラスとして表現し、インスタンスを作成するための何らかのクエリファクトリを用意するのが賢明でしょうか?

3
TDDとリファクタリングの難しさ(または-なぜこれが本来よりも痛いのか?)
TDDアプローチを使用することを自分で学びたいと思っていたので、しばらくの間、やりたいプロジェクトがありました。大規模なプロジェクトではなかったので、TDDの良い候補になると思いました。しかし、何かがおかしくなったように感じます。例を挙げましょう: 高レベルでは、私のプロジェクトはMicrosoft OneNoteのアドインであり、プロジェクトをより簡単に追跡および管理できます。また、いつか自分のカスタムストレージとバックエンドを構築することにした場合に備えて、このためのビジネスロジックをOneNoteから可能な限り切り離したままにしておきたいと考えました。 最初に、基本的な平易な言葉の受け入れテストから始めて、最初の機能で何をしたいかを概説しました。これは次のようなものです(簡潔にするために説明を省略しています)。 ユーザーがプロジェクトの作成をクリックします プロジェクトのタイトルにユーザーが入力する プロジェクトが正しく作成されたことを確認します UIのものといくつかの中間計画をスキップして、最初のユニットテストに行きます。 [TestMethod] public void CreateProject_BasicParameters_ProjectIsValid() { var testController = new Controller(); Project newProject = testController(A.Dummy<String>()); Assert.IsNotNull(newProject); } ここまでは順調ですね。赤、緑、リファクタリングなど。今では実際に保存する必要があります。ここでいくつかの手順を省略して、これで終わります。 [TestMethod] public void CreateProject_BasicParameters_ProjectMatchesExpected() { var fakeDataStore = A.Fake<IDataStore>(); var testController = new Controller(fakeDataStore); String expectedTitle = fixture.Create<String>("Title"); Project newProject = testController(expectedTitle); Assert.AreEqual(expectedTitle, newProject.Title); } …

4
複数のインターフェイスを結合する空のインターフェイス
次の2つのインターフェイスがあるとします。 interface Readable { public void read(); } interface Writable { public void write(); } 場合によっては、実装オブジェクトはこれらの1つしかサポートできませんが、多くの場合、実装は両方のインターフェイスをサポートします。インターフェイスを使用する人々は次のようなことをしなければなりません: // can't write to it without explicit casting Readable myObject = new MyObject(); // can't read from it without explicit casting Writable myObject = new MyObject(); // tight coupling to actual implementation MyObject myObject …

7
std :: stringパラメーターに渡された0から最良に保護する方法は?
何か気がかりなことに気づきました。std::stringaをパラメーターとして受け入れるメソッドを作成するたびに、未定義の動作に自分自身を開放しました。 たとえば、これ... void myMethod(const std::string& s) { /* Do something with s. */ } ...このように呼び出すことができます... char* s = 0; myMethod(s); ...そしてそれを防ぐために私ができることは何もありません(私は知っています)。 だから私の質問は次のとおりです。誰かがこれからどのように身を守るのでしょうか? 頭に浮かぶ唯一のアプローチは、次のstd::stringように、パラメータとしてを受け入れるメソッドの2つのバージョンを常に記述することです。 void myMethod(const std::string& s) { /* Do something. */ } void myMethod(char* s) { if (s == 0) { throw std::exception("Null passed."); } else { myMethod(string(s)); } …
20 c++ 

5
なぜgitコミットには作成されたブランチの名前が含まれないのですか?
機能ブランチを使用してチームでgitを操作するとき、歴史上のブランチ構造を理解するのが難しいことがよくあります。 例: 機能ブランチfeature / make-coffeeがあり、機能のブランチと並行してmasterでバグ修正が続けられたとしましょう。 履歴は次のようになります。 * merge feature/make-coffee |\ | * small bugfix | | * | fix bug #1234 | | | * add milk and sugar | | * | improve comments | | * | fix bug #9434 | | | * make coffe (without milk …
20 git  branching 

2
Javaがファイル名を引数に入れないのはなぜですか?
CおよびC ++では、mainメソッドは、argv [0]の配列の最初の位置にファイル名を保持します。ただし、Javaでは、ファイル名はargs文字列配列に含まれません。 これには実用的な理由がありますか?これにより、コマンドライン引数を1ベースではなく0ベースで反復処理することを理解していますが、利点はありますか?ファイル名は役に立たないとみなされましたか?
20 java  c++  c 

2
ロジックプログラミングを使用して対話型プログラム(ゲーム/シミュレーションなど)を実装する方法
ロジックプログラミングは、OOや関数型プログラミングなど、他のプログラミングパラダイムの汎用的な代替手段として機能すると聞いています。(Prologはチューリング完全なので、これはそうでなければなりません!) しかし、Prologや同様の言語でのシンプルなグラフィカルコンソールゲームのように、対話型プログラムをどのように実装するのかがわかりません。ファクト、より多くのファクトを導出できるルール、およびファクトを取得するクエリがあります。これらの基本要素を使用して、数独ソルバーのようなものを作成する方法は簡単にわかります。しかし、パックマン、またはもっと単純なポンはどうですか? 注:低レベルの詳細ではなく、概念的な概要を探しています。(たとえば、高レベルの用語では、I / Oをどのように処理しますか?ゲームの状態をどのように保存しますか?「メインループ」のようなものを実装しますか?時間の経過をどのように測定し、応答しますか? )

4
例外をいつ、どのように使用すればよいですか?
設定 例外をいつどのように使用するかを判断するのに苦労することがよくあります。簡単な例を考えてみましょう。AbeVigodaがまだ生きているかどうかを判断するために、「http://www.abevigoda.com/」と言うWebページをスクレイピングしているとします。これを行うには、ページをダウンロードし、「Abe Vigoda」というフレーズが表示される時間を探すだけです。安倍のステータスが含まれているため、最初の外観を返します。概念的には、次のようになります。 def get_abe_status(url): # download the page page = download_page(url) # get all mentions of Abe Vigoda hits = page.find_all_mentions("Abe Vigoda") # parse the first hit for his status status = parse_abe_status(hits[0]) # he's either alive or dead return status == "alive" where parse_abe_status(s)は「Abe Vigoda is something」という形式の文字列を取り、「something」部分を返します。 このページを安倍のステータスのためにスクレイピングするはるかに優れた、より堅牢な方法があることを議論する前に、これは私がいる一般的な状況を強調するために使用される単純で不自然な例であることを忘れないでください。 …

8
Java-配列を「ベクター」と呼ぶのはなぜですか?
Javaプログラミングに関する本を読んでいます。「ベクトル」という言葉の定義を理解していることを確認したいと思います。ウィキペディアによると、ベクターは「1次元配列」であり、ソースはhttp://en.wikipedia.org/wiki/Vectorです。 配列を単に配列と呼ぶ方が簡単ではないでしょうか?「ベクター」などの派手な言語を使用する必要がある理由はありますか?配列とベクトルに違いはありますか? 出典:Cracking the Coding Interview、4th Edition、by Gayle McDowell、page 47。 FAQ Q-english.stackexchange.comに投稿しなかったのはなぜですか? A-コンピュータサイエンス指向の人だけが良い答えを得ると思うからです。
20 java 

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