社内の人への質問の仕方

自分ならどう聞くかみたいなのをまとめてみます。
弊社内ではSlackでやり取りしているので、挨拶や回答期限の設定はしていません。

同じプロジェクトに参画していて同じ業務をしているチームメンバーに対して

自分自身がプログラマーで、プログラマーに質問を投げる想定

現在、入力画面で入力された値をチェックするタスクをしています。  
○○さんは編集画面の入力値チェックを実装されたと思いますが、  
文字数チェックと数字かどうかのチェックはどちらを先に判定しましたか?  

①質問の背景
②質問
を記載しています。
同じような業務をしているので、ざっくりめな質問を投げても通じ合えると思っているからです。

同じプロジェクトに参画しているリーダーやチームメンバーに対して

自分自身がプログラマーで、仕様の担当者に質問を投げる想定

入力画面の仕様について質問があります。  
現在、入力画面で入力された値をチェックするタスクをしています。  
入力画面の入力値チェックでは、nullチェックと文字数チェックと数字チェックをする仕様になっていると思います。  
チェックする順番は、  
1-nullチェック  
2-文字数チェック  
3-数字チェック  
で問題ないでしょうか?  

①何についての質問か
②現在の状況
③質問
を記載しています。
自分とは違う視点で仕事をしている人に対しては、最初にトピックを絞りにいきます。
こうすることで、「何に対して回答がほしいか」が明確になって、回答者側も思考の狭い範囲から回答を探せるので楽なんじゃないかなと思っています。

上司に対して

自分自身が設計者で、上司はこのプロジェクトのことは案件概要くらいしか知らない想定

実装時の入力値チェックについて、会社として方針があるか質問です。  
現在、○○というプロジェクトで入力値チェックの作業をしています。  
OKボタンを押したときにメッセージダイアログを出すよりも、  
値が入力された時点でテキストボックスの下に赤文字でエラーメッセージを出すほうが良いと思いました。  
複数の別の案件を確認したところ、テキストボックスの下に赤文字でエラーメッセージを出す実装はほぼありませんでした。  
テキストボックスの下に赤文字でエラーメッセージを出す実装は避けたほうが良いのでしょうか?  

①何についての質問か
②現在の状況
③調べたこと
④質問
を記載しています。
最初にトピックを絞りにいくのは先ほどと同じですが、何を調べたかも伝えることで上司の工数を1つ減らせるかなと思っています。

まとめ

私はこのテンプレートで質問することが多いです。
人によっては背景とか要らないという人がいるけど、私は、なぜ質問してきたかが分からないと答えるのが難しいタイプなので、背景を書くようにしています。
背景要らない人は読み飛ばせばいいだけの話なので。

また、

(前略)
テキストボックスの下に赤文字でエラーメッセージを出す実装は避けたほうが良いのでしょうか?
それとも、実装しても問題ないでしょうか?

という質問はしないようにしています。
複数人から何度か、「はい、お願いします」というような返事を受け取ったことがあるためです。
「Yesですか?Noですか?」と聞くのではなく、「Yesですか?」または「Noですか?」とだけ聞くようにしています。

この質問テンプレートは、情報が整理できてとてもよい一方で、
記載するのに時間がかかる点はデメリットです...

P.S.
「設計書終わった?」みたいに声かけてくる人が苦手です。
どのプロジェクトの?
基本設計?機能設計?詳細設計?
期限いつまでだったっけ?
みたいに考えることが多くてパニックになるので...(;^ω^)

ビジネスメールの書き方

新人さんに聞かれたけどうまく答えられなかったのでまとめてみます。

といっても私が別会社の時に習ったものなので、オリジナルではありません。

送り先

To, Cc, Bccの3種類があります。
Toは返信がほしい相手、Ccは見ておいてほしい相手、Bccは隠れて見てほしい相手です。
Ccには上司を入れることが多いイメージです。 このあたりの使い分けは気が向いたら追記します。

件名

「内容が分かるように」以上のことは言えません。
というのも、件名は、企業によってだいぶルールが違います...。
以前の会社では【】(すみかっこ)を多用してましたが、ヘイシャではほとんど使いません笑

本文の構成

まず本文の構成。例は社内向けの場合。

○○さん

お疲れ様です。○○です。

~~~要件~~~

よろしくお願いいたします。

-------
署名
-------
  • 宛先の名前

まず、宛先の名前を書きます。

社内なら○○さん○○課長各位など。
何を選ぶかは今後追記するかもしれません。

社外なら会社名 ○○様

  • 挨拶

次に挨拶+名前を書きます。

社内ならお疲れ様です。○○(自分の名字)です。
社外ならお世話になっております。○○(自分の名字)です。
...が無難だと思っています。

  • 本文

次に本文を書きます。
ここは特に指定があるわけではないので、分かりやすい文を心がけましょう。

一文が30~40字になるように、適度に改行を入れるといいようです。

  • 最後の挨拶

次に締めの挨拶を書きます。

以上、よろしくお願いいたします。とかご確認をお願いいたします。とかですね。

  • 署名

本文の最後には署名を書きます。

-------
会社名
部署名や役職
漢字名前 (ふりがなやアルファベット表記があると親切)
E-mail
会社住所
会社電話番号
-------

...などなど記載します。
「メール 署名 デザイン」とかでググればたくさん出てくると思うので、好みのものを見つけましょう!

送信前確認

メール送信の前に指さし確認するべき7点があります。

  1. 宛先があっているか
  2. 件名がついているか
  3. 本文 宛先の人の名前
  4. 本文 挨拶「お世話になっております、○○です」的な
  5. 本文 最後挨拶「以上、よろしくお願いいたします」的なやつ
  6. 本文 自分の署名
  7. 添付ファイル

個人的には、これを毎回(脳内で)指さし確認していたらメールのミスほぼなかったので、結構使えると思います!

引用返信

返信の際は引用返信しましょう。
ビジネスでは、話の流れを保持しておくために引用返信が基本です。

余談ですが、私が高1の時はまだLINEがなくて、メールでやり取りしていました。
引用返信=晒しのような感覚だったので、ビジネスでは引用返信が基本だと知って驚いたものです...

以上

また何か思い出したら書き足します~

System.Reflection.TargetParameterCountException: 'パラメーター カウントが一致しません。'

...というエラーが出ましたというお話。
C# フォームアプリケーションです。

フォームを操作していると起きるエラーなのに、エラー発生場所はprogram.csApplication.Run()になります。

スタックトレース

   場所 System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   場所 System.Delegate.DynamicInvokeImpl(Object[] args)
   場所 System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
   場所 System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
   場所 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   場所 System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
   場所 System.Windows.Forms.Control.InvokeMarshaledCallbacks()
   場所 System.Windows.Forms.Control.WndProc(Message& m)
   場所 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   場所 System.Windows.Forms.Form.WndProc(Message& m)
   場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   場所 System.Windows.Forms.Application.Run(Form mainForm)
   場所 NullableArgInvoke.Program.Main() (C:\Users\xxx\datas\NullableArgInvoke\Program.cs):行 19

結論をいうと、invokeの呼び方が悪かったです。
nullableなDateTime型を引数に持つメソッドをinvokeしようとして、nullを渡していたのですが、
実はnew DateTime?()しないといけなかった、というだけでした。

共有のためにサンプルプログラム書きました↓
successボタンを押しても何も起きませんが、failureボタンを押すとProgram.csでエラーが起きます。

    public partial class Form1 : Form
    {
        private Button m_successButton;

        private Button m_failureButton;

        private TextBox m_textBox;

        private delegate void displayNumber(int? number);

        public Form1()
        {
            InitializeComponent();

            m_successButton = new Button();
            m_successButton.Location = new Point(12,12);
            m_successButton.Text = "success";
            m_successButton.Click += SuccessButtonClicked;
            this.Controls.Add(m_successButton);

            m_failureButton = new Button();
            m_failureButton.Location = new Point(12, 41);
            m_failureButton.Text = "failure";
            m_failureButton.Click += FailureButtonClicked;
            this.Controls.Add(m_failureButton);

            m_textBox = new TextBox();
            m_textBox.Location = new Point(21, 70);
            this.Controls.Add(m_textBox);
        }

        private void DisplayNumber(int? number)
        {
            if (number.HasValue == true)
            {
                m_textBox.Text = number.Value.ToString();
            }
            else
            {
                m_textBox.Text = string.Empty;
            }
        }

        private void SuccessButtonClicked(object sender, EventArgs e)
        {
            BeginInvoke(new displayNumber(DisplayNumber), new int?());
        }

        private void FailureButtonClicked(object sender, EventArgs e)
        {
            BeginInvoke(new displayNumber(DisplayNumber), null);
        }
    }

VB怖い

私はC#erです。

先日、2006年に作成したアプリの改造案件を渡されました。

言語はVBでした。
C#erですが、VBはカタコトくらいには読み書き出来ます。

そのアプリは、VB.NETで書かれているフォームアプリケーションでした。

2006年のソリューションなのに、VS2019で開けました。すごい。

開いたら、まず、Program.vbなんて存在しないことに驚きました...
どこでフォームのインスタンス作ってるんだと思いましたが、なんとか、プロジェクトのプロパティで「スタートアップオブジェクト」としてメインフォームが設定されているのを発見。

新しい画面を追加する改造なので、
ここはベターに、メインフォームから別のフォームを呼び出す処理をコピペしようとしたところ、

            frm2.Left = Me.Left + (Me.Width - frm2.Width) / 2
            frm2.Top = Me.Top + (Me.Height - frm2.Height) / 2
            frm2.Show()

...Newしてないんだが?!

調べていたらこちらを発見

既定のインスタンスとか暗黙のインスタンスと呼ばれるもので、VS2005のVBで復活しました。賛否両論あると思います。

Visual Basic 2005 の My 機能の検証 http://msdn.microsoft.com/ja-jp/library/ms379610(v=vs.80).aspx

VB6.0 で「Form の既定のインスタンス」を防ぐには? http://blogs.wankuma.com/jeanne/archive/2006/10/25/42449.aspx

うそだろ...

ただヘイシャは「リリース済みアプリのリファクタリングはよほどのことがない限りしない」方針なのと、 私個人として「できる限りコピペで実装したほうがコードの可読性は高まる」と思っているため、 同様にNewせず実装しました。

...このあと上司に機能レビューしてもらっていたところ、 前回までの実装で挙動がおかしかったためソースを見られ、 結果上司は「新しく書くコードはNewする」という方針にしたのでコードを書き換える作業が生じましたが それはまた別の話...

とにかく、 C#erからすると、Newしないで書けるVB怖い!という話でした。