初めてWPFで若い男性にインタビューするように頼まれたときのことを思い出します-私は数時間尋ねる価値があるもののリストを作りました(そして、泥の中に私の顔を打たないように答えを再確認しました)そのような人かどうか。 そして今、10-15の質問で武装し、交渉室に入り、自己紹介をし、いくつかの一般的な質問をし、ところで、以下を指定します。
-そして、WPFを使用した開発経験は何年ですか?
-私はWPFを知りません....
-...
あなたが最も明白なものを除いてすべてを予見していることに気付くこの厄介な瞬間...
私にとっても予想外だったのは、申請者の履歴書に5年の開発経験があり、興味深いプロジェクトの説明がたくさんリストされていることでした。知っているのは、.Netのメモリについて考える必要がないということだけです...
重要なものとして答えに頼ることができるように、何を尋ねることができますか?
-彼がどんな本を読んだか、何回聞いた? しかし、学んだ定式化は、人が実際の問題を解決できるという意味ではなく、その定式化は本の定式化とは異なり、時には何らかの理由で開発の一般原則からの逸脱を必要とします。
-環境の技術的なニュアンスをすべて書き留めて、それらについて尋ねますか? しかし、実際には、ガベージコレクションがどのように機能するか(バージョンごとに変化します)および何世代がそこにあるかについての知識が必要な人はいますか? この余分な知識が決してあると言っているわけではありませんが、この機能の知識や無知は開発者の「品質」を決定することを許しません。
-コードの例を尋ねますか? しかし、どのコードが表示されますか? すでに何人がそれを支配していますか? どのような条件で書かれていましたか? これらの華麗な300行が、雨季の大西洋の波の音に1か月に書き込まれたとしたらどうでしょうか。 それから、次の300の華麗なラインを得るために「作業」雰囲気を再現できますか
私は自分の考えを共有し、インタビューに対するこのアプローチに対する建設的な批判を聞きたいです。 私のアイデアは、「OWN」コードを表示して聞くことです。 夕方、最も一般的な「エラー」を含むひどいコードの例をスケッチしました。 実際の開発経験が4年以上の上級開発者は、エラーの80%以上を特定し、仮想アーキテクチャの既存の問題を指摘するはずです。
そして、実際にはコード:
1 using System; 2 using System.Collections.Generic; 3 4 namespace App.Services 5 { 6 public enum LoginResult 7 { 8 Unknown = 0, 9 Success = 1, 10 WrongLogin = -1, 11 WrongPass = -2, 12 Error 13 } 14 15 public class LoginService 16 { 17 public string LastError = string.Empty; 18 19 /// <summary> 20 /// Allow to login new user 21 /// </summary> 22 /// <param name="login">login</param> 23 /// <param name="password">password</param> 24 /// <param name="asAdmin">asAdmin</param> 25 /// <returns>login result</returns> 26 public LoginResult Login(string login, string password) 27 { 28 List<Login> dbLogins = new List<Login>(); 29 try 30 { 31 dbLogins.AddRange( 32 DAL.GetItems<Login>( 33 "select * from db.Login where Name='" + login + "'")); 34 } 35 catch (Exception ex) 36 { 37 lock ((object)777) 38 { 39 LastError = ex.Message; 40 } 41 throw ex; 42 } 43 if (dbLogins.Count < 1) 44 { 45 return LoginResult.WrongLogin; 46 } 47 48 var prevUser = App.CurrentUser; 49 App.CurrentUser = dbLogins[0]; 50 if (password.CompareTo(App.CurrentUser.Password) != 0) 51 { 52 App.CurrentUser = prevUser; 53 return LoginResult.WrongPass; 54 } 55 56 var log = System.IO.File.AppendText(App.LogFile); 57 log.WriteLine("New user loggined. Login=" + App.CurrentUser.Name); 58 59 if (!(bool)((EventService)App.Service).SendWithConfirm(prevUser)) 60 { 61 log.Write("Error sending to user."); 62 } 63 64 GC.Collect(); 65 GC.Collect(); 66 67 return LoginResult.Success; 68 } 69 } 70 }
エラー(申請者から聞くと予想される行番号と説明):
12-「エラー」の値は「-1」になります。これは既存の値を複製し、将来的に区別することを許可しません。
17(1)-パブリックフィールド。 適切な形式の規則により、フィールドを公開することは推奨されません。
17(2)-コードによる変数への書き込みは、ロックを介して「実装」されますが、外部の消費者は、変数の呼び出しを誰かと同期する必要があることに気付かない場合があります。
20-無意味なコメント。
24-解説は正しくありません。
28-publicメソッドは外部からパラメーターを受け入れましたが、それらの正確性(少なくともnull)のチェックを実行しませんでした。
32-強いつながり。
33(1)-SQLインジェクションを使用する潜在的な場所。 リクエストを形成するためにパラメーターではなく連結が使用されるため。 次に、パラメータ化されていないクエリは、続編サーバーによってキャッシュされません(DBMSが続編の場合)。
33(2)-同様のスタイルのクエリ生成は、アプリケーションを特定のDBMSに「バインド」します。
33(3)-この方法で文字列を連結することは、最も効率的な解決策ではありません。
35-正しい形式のルールに従って、すべてを連続して処理するのではなく、処理できるエラーをキャッチする必要があります。
37-このロックは機能しません。
39-変数の無意味な値であり、開発者にとって診断上の利点はありません。
41-現在のスタックトレースは、エラーの診断に役立つ可能性がありますが、このような例外により回復不能に失われます。
49(1)-アプリケーションの状態の破壊。エラーが低い(ヌルパスワード)場合、現在のユーザーはすでにフィールドに新しいログインを持っているためです。
49(2)-暗黙的なビジネスロジック。 他のログインを遮断する理由
50(1)-パスワードのnullがチェックされないため、アプリケーション状態の破壊につながる例外が存在する可能性があります。
50(2)-パスワードはクリアテキストで保存および使用されます。
53-良い形の規則によると-認証エラーの原因に関するそのような詳細な情報は報告されるべきではありません。
56(1)-よく考え抜かれたロギングメカニズムの欠如。
56(2)-ストリームは開きますが、そのクローズと破棄は実行されず、データは最終ファイルに書き込まれない場合があります。
56(3)-ファイルを操作すると、例外が発生する可能性があります。実際には、ログインは既に通過していますが、上記の1レベルは認証エラーと解釈できます。
57-ログファイルアナライザーが突然作成され、それを必要とする人がいれば、ログファイルアナライザーの寿命を決して単純化しない意味のない情報。
59(1)-接続されていることに加えて、返される結果に関して「過大評価」された期待のネストされた呼び出し。
59(2)-明白でないビジネスロジック。
61-無意味なログエントリ。
64.65-アプリケーションの大きなメモリの問題の兆候。 (また、なぜ連続して2回の呼び出しが行われ、どうしてそれを行う価値がないのかを聞くことも期待しています)
たぶん誰かがすでにこのアプローチをとっており、彼らの経験を共有することができますか?