Windows Server 2012インストール

Windows Server 2012をインストールしてみた。

2つのインストール方法

「Server Coreインストール」と「GUI使用サーバ」の2つの選択肢があった。

予備知識がなかったので説明文を読んで選ぶことにする。 「Server Coreインストール」を推奨していたのでこちらを選択してインストール。

インストールは問題なく終わったが、ログオンするとコマンドプロンプトのウィンドウが開いているだけ。 すべてコマンドから設定等行うようである。 しかも、なぜかIMEが日本語入力となっている。

GUI使用モードへの変更(フルインストール)

GUIがないとなにもできそうもないのでネットで切り替え方法を検索した。 GUI使用モードとは、「フルインストール」と言うらしい。

https://technet.microsoft.com/ja-jp/library/hh831786

ここに変更方法が記載されているので実行しようとするが、PowerShellで実行する必要があるとのこと。

PowerShellはほとんど使ったことがないのでコマンド自体知らない。 「ps」かな?と思って打ったが違う。「powershell」でいいらしい。

Install-WindowsFeature Server-Gui-Mgmt-Infra,Server-Gui-Shell –Restart

どうにかGUIが表示されるようになったので、ネットワークの設定など変更をしたいのだがWindows8と同様デスクトップになっているのでわかりづらい。 ネットで検索しながらコントロールパネルの表示方法などの操作方法を確認したりした。

IMEの設定

最初、どのWindowでもIMEが日本語入力になっているので何かの間違いかと思ったが、ネットで検索してみるとWin2008やWin7と動作が変更されたようで、日本語入力になってしまうらしい。

IMEの状態をアプリ個々に設定するというオプションで回避するとのこと。 https://social.technet.microsoft.com/Forums/ja-JP/35b7564c-d415-46c6-9320-3b9448a3173f/imeoff?forum=winserver8

コントロールパネル→「言語」の「詳細」をクリック→「詳細設定」ウィンドウの「入力方法の切り替え」-「アプリ ウィンドウごとに異なる入力方法を設定する」にチェック

まとめ・感想

最初のインストールオプションは「GUIを使用」(フルインストール)のほうを選ぶ。

IMEの動作が以前のWindowsと変更されているので、こちらも設定を変更しておく。 「アプリ ウィンドウごとに異なる入力方法を設定する」


IMEのデフォルトを日本語入力したことについて、マイクロソフトの人は誰もダメだと言わなかったんでしょうか? この設定でよいとOKした人呼んで罵倒していいレベルだと思うんですが。サーバOSですよ。 この件に関係なかったらすみませんが、日本マイクロソフトの人、仕事してください。お願いします。


個人的な推測であるが、WindowsサーバOSを使っている企業・機関の割合は世界的に見れば日本がかなり高いと思う。欧米より高いのではと勝手に思っている。それなのにこの扱い。ひどい。

ちなみに現時点で最新のWindows Server 2012 R2については持っていないので、このままのIME設定なのかは不明。

クラシックASPのコーディング考慮点 その2

If文の書き方

On Error Resume Nextの動作について。

If文の評価式で実行時エラーが発生した場合の動作を確認してみた。

On Error Resume Next
If Foo() = True Then
    Response.Write "<p>returned True.</p>"
Else
    Response.Write "<p>returned False.</p>"
End If

Function Foo()
    Err.Raise 5
    'Foo = False
End Function

Foo関数で実行時エラーが発生しているので、Falseの評価をしてほしいのだが、実際は「returned True.」と表示される。

この点を考慮すると、vbscriptでIf文を使う場合は、以下のようにするとよいだろう。

If 「エラーかどうかの判定」 Then
    'エラー時の処理
Else
    '正常時の処理
End If

具体的には、

If Not Foo() Then
    Response.Write "<p>returned False.</p>"
Else
    Response.Write "<p>returned True.</p>"
End If

となる。

同様にDo While文でも評価式で実行時エラーが発生するとループの中の処理が実行されるので注意する。

ちなみに、Select Case文だと、End Select行の次行から処理される。

入力値の表示と復元

PostメソッドでFormデータをsubmitすることが前提。

Request.Formから入力値をそれぞれ取得するのは効率が悪い。 表示時に使用したgDataに復元できる関数を用意する。

' Request.FormからCollectionにデータを復元する。
' arListId : 一覧識別子の配列
Function CreateFormCollection(arListId)
   Dim i
   Dim o
   Dim listCnt
   Dim colNmInfo
   Dim isList,lstId,idx, childNm
   Dim nm

   Set o = CreateCollection()
   
   listCnt = UBound(arListId) + 1
   
   For i = 0 To listCnt - 1
      o.Add arListId(i), CreateCollection()
   Next
   
   isList = False
   lstId = ""
   idx = 0
   childNm = ""
   
   For Each nm In Request.Form
      isList = False
      For i = 0 To listCnt - 1
         '一覧識別子 + "_" + index + "_" + name の分解
         Set colNmInfo = GetIndexAndNameFromNameInList(nm, arListId(i))
         If colNmInfo.Count > 0 Then
            isList = True
            lstId = arListId(i)
            idx = colNmInfo("idx")
            childNm = colNmInfo("nm")
         End If
      Next
      
      If Not isList Then
         o.Add nm, Request.Form(nm)
      Else
         If Not o(lstId).Exists(idx) Then
            o(lstId).Add idx, CreateCollection()
         End If
         
         o.Item(lstId)(idx).Add childNm, Request.Form(nm)
      End If
   Next
   
   Set CreateFormCollection = o
End Function

Const LISTID_SEPARATOR = "_"

'一覧識別子 + "_" + index + "_" + name の分解
Function GetIndexAndNameFromNameInList(nm, lstId)
   Dim o
   Dim idx, childNm
   Set o = CreateCollection()


   If Mid(nm, 1, Len(lstId) + 1) = lstId & LISTID_SEPARATOR Then
      If InStr((Len(lstId) + 1) + 1, nm, LISTID_SEPARATOR) > (Len(lstId) + 1)  + 1 Then
         idx = CLng(Mid(nm, Len(lstId) + 1 + 1 _
                  , InStr(Len(lstId) + 1 + 1, nm, LISTID_SEPARATOR) _
                      - (Len(lstId) + 1) - 1 _
                ))
         childNm = Mid(nm, Len(lstId & LISTID_SEPARATOR & idx & LISTID_SEPARATOR) + 1)
         o.Add "idx", idx
         o.Add "nm", childNm
      End If
   End If
   
   Set GetIndexAndNameFromNameInList = o
End Function

簡単なものであるが、一覧データを復元できるような仕組みにしている。 1階層のみで一覧の中の一覧は対応していない。

使用例

<%
'省略


Sub InitializePage()
    TemplateInitializePage
    
    Dim i
    Set gData = CreateFormCollection(Array("lst1", "lst2"))
    If gData("lst1").Count = 0 Then
       For i = 0 To 5 - 1
          gData("lst1").Add i, CreateCollection()
          gData("lst1")(i).Add "txtCol1", Right("0000" & (i+1), 4)
          gData("lst1")(i).Add "txtCol2", "あいうえお" & i
       Next
    End If
End Sub

Sub RenderHtml()
    If Not gNoErrorHandlingForDebug Then
        On Error Resume Next
    End If
    
    Dim i, s, row, nm
%>

<html>
<head>
<title>sample04</title>
</head>
<body>
<form name="f" method="post">
   <input type="text" name="txtVal1" value="<%= Server.HTMLEncode(gData("txtVal1")) %>"><br>
   <input type="text" name="txtVal2" value="<%= Server.HTMLEncode(gData("txtVal2")) %>"><br>
   <table>
      <tr><th>Index</th>
          <th>列1</th>
          <th>列2</th>
      </tr>
<%
   For i = 0 To gData("lst1").Count - 1
      Set row = gData("lst1")(i)
%>
      <tr><td><%=i%></td>
         <td><input type="text" name="<%="lst1_" & i & "_txtCol1"%>" value="<%=Server.HTMLEncode(row("txtCol1"))%>"></td>
         <td><input type="text" name="<%="lst1_" & i & "_txtCol2"%>" value="<%=Server.HTMLEncode(row("txtCol2"))%>"></td>
      </tr>
<%
   Next
%>
   </table>

   <div><input type="button" name="btnPost" value="post" onclick="document.f.submit();">
   </div>
%>
</form>
</body>
</html>
<%
End Sub 'RenderHtml
%>

ポイントは、gDataのKey名とinputタグのname属性の値を一致させる。こうすることで、CreateFormCollection()で処理してくれる。

一覧形式のデータについては、name属性を「(一覧の識別子)+"_"+index+"_"+(名前)」の形式とすることで、一覧をコレクション配列として復元している。

javascript出力時のエスケープ処理

htmlに文字を埋め込む場合、< > & をエスケープする必要がある。

aspでは、Server.HTMLEncode()が用意されているのでこれを利用する。

javascriptの場合についても、入力値などの文字列をjavascriptに埋め込む場合にはエスケープが必要である。

とりあえず、下記のような関数を用意した。

Function JsEscape(v)
    Dim s
    s = Replace(v, "\"     , "\\")
    s = Replace(s, vbCrLf  , "\n")
    s = Replace(s, vbCr    , "\n")
    s = Replace(s, vbLf    , "\n")
    s = Replace(s, """"    , "\""")
    s = Replace(s, "'"     , "\'")
    s = Replace(s, Chr(&H8), "\b")
    s = Replace(s, Chr(&HC), "\f")
    s = Replace(s, Chr(&H9), "\t")
    s = Replace(s, Chr(&HB), "\v")
    
    s = Replace(s, "&"     , "\x26")
    s = Replace(s, "<"     , "\x3c")
    s = Replace(s, ">"     , "\x3e")
    JsEscape = s
End Function

htmlに埋め込むことが前提なので、< > & を追加している。 エスケープ対象文字はほかにもあって、Unicode文字のLine SeparatorやParagraph Separatorがあるとのこと。

JSONの場合には、javascriptと同じエスケープでは駄目なので、以下を用意した。

Function JsonEscape(v)
    Dim s
    s = Replace(v, "\"     , "\\")
    s = Replace(s, vbCrLf  , "\n")
    s = Replace(s, vbCr    , "\n")
    s = Replace(s, vbLf    , "\n")
    s = Replace(s, """"    , "\""")
    s = Replace(s, "/"     , "\/")
    s = Replace(s, Chr(&H8), "\b")
    s = Replace(s, Chr(&HC), "\f")
    s = Replace(s, Chr(&H9), "\t")
    s = Replace(s, Chr(&HB), "\u000b")
    
    s = Replace(s, "'"     , "\u0027")
    
    s = Replace(s, "&"     , "\u0026")
    s = Replace(s, "<"     , "\u003c")
    s = Replace(s, ">"     , "\u003e")
    JsonEscape = s
End Function

単純にエスケープ対象の文字をReplace関数で置き換えているが、もっといい方法があるだろう。 少なくとも1文字ずつ処理したほうが速い気がする。

クラシックASPのコーディング考慮点

いまさらだが、クラシックASPのシステムに携わることになったので、ASPのコーディングについて整理してみる。

言語

VBScriptJScriptがあるが、VBScriptを使うのでVBScriptについて。 ブラウザ側はjavascriptなのでJScriptを使ったほうがいいのかもしれない。 後日まとめようと思う。

気をつけること

エラーハンドリングが貧弱

VBScriptでは、エラーハンドリングなしとOn Error Resume Nextの2つしかない。

資源開放が必要な操作については、On Error Resume Nextを使うしかないのだが、 エラーの発生箇所を調べるようとすると1行ごとにチェックを入れる破目になることがある。

エラーが発生した行などの情報を取得できればいいが使えそうな手段がないようである。 エラー箇所特定の常套手段としては、エラーハンドリングなしにする。 そうすればASP側のエラー出力をブラウザ側で見ることができる。

ただ、エラーハンドリングなしにするには、事前にOn Error Resume Nextの使用箇所を考えておく。 最小限の利用で済むようにしておく。

特に資源開放が必要なものについては、必ず終了処理が実行されるようにする。 データベースのコネクション、結果セットやファイルアクセスが該当する。

グローバル変数の多用

コレクションが組み込まれてないので、画面に表示する項目一つ一つに変数を割り当ててしまいがちになる。 一応、クラス機能があるので画面で使うものを定義しておくことができるが、 IDEのサポートがないためクラス定義してもあまり便利でない。

VBScriptにはコレクションは組み込まれてないが、ScriptランタイムのDictionaryオブジェクトがあるので連想配列のように使える。

Server.CreateObject("Scripting.Dictionary") で生成できる。

サンプル

実際にコードを書いて検討してみる。

サンプル1

sample1.asp

<%@ LANGUAGE=VBScript %>
<% Option Explicit %>
<!-- #include file="config/settings.inc" -->      <%'環境依存定義のInclude%>
<!-- #include file="../common/inc/common.inc" --> <%'共通の定数と関数のInclude%>
<%
On Error Resume Next

'グローバル変数
Dim gErrInfo, gData
Dim gDbCon              'DB Connecgtion

'=== エントリー部 ===
Set gErrInfo = CreateCollection()  'Scripting.Dictionary
Set gData = CreateCollection()
Set gDbCon = Nothing

InitializePage
If Err.Number <> 0 Then
    gErrInfo.Add gErrInfo.Count, CreateErrorInfo("ERR-0001", "sample.asp", "初期化に失敗しました。", "0010 Initialize Error.")
End If
If gErrInfo.Count = 0 Then
    LoadPage
End If
TerminatePage

'=== プロシージャ、ファンクションの定義 ===
Sub InitializePage()
End Sub

Sub LoadPage()
    gData("sample_value") = "サンプル値"
End Sub

Sub TerminatePage()
    If Err.Number <> 0 Then
        gErrInfo.Add "ERR-9990", "sample.asp", "エラーが発生しました。", "9990 No Handling Error."
    End If
    On Error Resume Next
    If Not gDbCon Is Nothing Then
        gDbCon.Close
        Set gDbCon = Nothing
    End If
    On Error GoTo 0
End Sub

Function CreateErrorInfo(sErrCd, sSource, sErrMsg, sDetailMsg)
    Dim info
    Set info = CreateCollection()
    info.Add "Timestamp", Now()
    info.Add "ErrCode", sErrCd
    info.Add "Source", sSource
    info.Add "Message", sErrMsg
    info.Add "DetailMessage", sDetailMsg
    info.Add "Err.Number", Err.Number
    info.Add "Err.Source", Err.Source
    info.Add "Err.Description", Err.Description
    Err.Clear
    Set CreateErrorInfo = info
End Function
%>

<html>
<head>
</head>
<body>
<!-- コンテンツ -->
</body>
</html>
ポイント

コレクションを使って、画面に出力するデータを集約してみた。 そうすることによって、グローバル変数を少なくすることができる。

  • エラー情報生成関数の定義

上記例では、CreateErrorInfo()という関数を定義して、エラー発生時の情報を集めている。 また、実行時エラーのエラーハンドリングを行った場合、Errオブジェクトから必要な情報を取得してからErr.Clearとしている。そうすることで、後続処理でErr.Numberを見るだけでエラーハンドリングしているかどうかがわかる。

  • 初期処理、メイン処理、終了処理の関数化

上記サンプルでは、InitializePage、LoadPage、TerminatePageの3つの関数とした。

初期化処理、メイン処理、終了処理の3つの構成にすることで、プログラムの見通しをよくし、TerminaitePageで資源開放の処理を行っている。

問題点
  • 共通側でのハンドリングが難しい

共通側で認証チェックなどの共通的な処理が必要な場合、個々のaspに修正が発生してしまう。 事前処理だけであれば、common.incで処理して別ページへのRedirectなどの手段が使え、Response.Endでスクリプトの処理を停止することは可能。

  • htmlの出力時に一時的な変数の扱い

ループで使用するカウンタや局所的に出力内容を編集したい場合、グローバルスコープで変数を宣言する必要がある。

  • その他

エラー情報を単純にコレクションとしているが、やはり拡張性や各aspでの利用方法の標準化を考えるとクラス化したほうがよいだろう。

サンプル2

サンプル1の問題点を改善してみる。

common.incの抜粋

' エラー情報
Class ErrorInfo
    Private mList
    Private mIsNoError
    
    Private Sub Class_Initialize()
        Set mList = CreateCollection()
        mIsNoError = False
    End Sub
    
    Function AddErr(sErrCd, sSource, sErrMsg, sDetailMsg)
        Dim info
        Set info = CreateCollection()
        info.Add "Timestamp", Now()
        info.Add "ErrCode", sErrCd
        info.Add "Source", sSource
        info.Add "Message", sErrMsg
        info.Add "DetailMessage", sDetailMsg
        info.Add "Err.Number", Err.Number
        info.Add "Err.Source", Err.Source
        info.Add "Err.Description", Err.Description
        Err.Clear
        mIsNoError = True
        Set AddErr = info
    End Function
    
    Public Default Property Get Items(i)
        Set Items = mList(i)
    End Property
    
    Public Property Get Count
        Count = mList.Count
    End Property
    
    Public Property Get IsNoError()
        IsNoError = (Not mIsError)
    End Property
    
    Public Function ToString()
        '省略
    End Function
    
End Class

' ページコントローラ
Class PageController
    Private mIsRedirectReuqested
    Private mIsTransferReuqested
    Private mNextPageUrl
    
    Private Sub Class_Initialize()
        mIsRedirectReuqested = False
        mIsTransferReuqested = False
        mNextPageUrl = ""
    End Sub
    
    Public Property Get IsRedirectReuqested
        IsRedirectReuqested = mIsRedirectReuqested
    End Property
    
    Public Property Get IsTransferReuqested
        IsTransferReuqested = mIsTransferReuqested
    End Property
    
    Public Property Get NextPageUrl
        NextPageUrl = mNextPageUrl
    End Property
    
    Public Sub SetRedirect(sNextPageUrl)
        mIsRedirectReuqested = True
        mNextPageUrl = sNextPageUrl
    End Sub
    Public Sub SetTransfer(sNextPageUrl)
        mIsTransferReuqested = True
        mNextPageUrl = sNextPageUrl
    End Sub
    
    Public Function MovePageIfRequired()
        If Me.IsRedirectReuqested And Me.NextPageUrl <> "" Then
            Response.Clear
            Response.Redirect Me.NextPageUrl
            MovePageIfRequired = True
            Exit Function
        End If
        If Me.IsTransferReuqested And Me.NextPageUrl <> "" Then
            Response.Clear
            Server.Transfer Me.NextPageUrl
            MovePageIfRequired = True
            Exit Function
        End If
    End Function
End Class


common_page_template.inc

<%
Dim gNoErrorHandlingForDebug 'デバッグ用・エラーハンドリングなし設定

Dim gErrInfo  'エラー情報
Dim gPageCntr 'ページコントローラ
Dim gData     '画面データ
Dim gCnn      'DBコネクション

' このTemplateで共通的に使うGlobal変数の初期化
gNoErrorHandlingForDebug = False
Set gErrInfo = New ErrorInfo
Set gPageCntr = New PageController
Set gData = CreateCollection()
Set gCnn = Nothing

' ページのメイン処理
Sub PageMain()
    If Not gNoErrorHandlingForDebug Then
        On Error Resume Next
    End If
    
    GetSourceName 'check implementation
    
    InitializePage
    If Err.Number <> 0 Then
        gErrInfo.Add "ERR-0001", GetSourceName(), "初期化でエラーが発生しました。", ""
    End If
    If gPageCntr.MovePageIfRequired() Then
        Exit Sub
    End If
    
    If gErrInfo.Count = 0 Then
        LoadPage
    End If
    TerminatePage
    
    If gPageCntr.MovePageIfRequired() Then
        Exit Sub
    End If
    
    If Err.Number <> 0 Then
        gErrInfo.Add "ERR-9991", GetSourceName(), "エラーが発生しました。", "9991 No Handling Error."
    End If
    RenderHtml
End Sub

'このTemplateの初期処理
Sub TemplateInitializePage()
End Sub

'このTemplateの終了処理
Sub TemplateTerminatePage()
    If Err.Number <> 0 Then
        gErrInfo.Add "ERR-9990", GetSourceName(), "エラーが発生しました。", "9990 No Handling Error."
    End If
    On Error Resume Next
    If Not gCnn Is Nothing Then
        gCnn.Close
        Set gCnn = Nothing
    End If
    On Error GoTo 0
End Sub

'=== Page側実装関数 ===
Function GetSourceName()
    Err.Raise vbObjectError + 1, "common_page_template.inc", "GetSourceName()はページ側で定義する必要があります。"
    'GetSourceName = "common_page_template.inc"
End Function

Sub InitializePage()
    Err.Raise vbObjectError + 1, "common_page_template.inc", "InitializePage()はページ側で定義する必要があります。"
    'TemplateInitializePage
End Sub

Sub LoadPage()
    Err.Raise vbObjectError + 1, "common_page_template.inc", "LoadPage()はページ側で定義する必要があります。"
End Sub

Sub TerminatePage()
    Err.Raise vbObjectError + 1, "common_page_template.inc", "TerminatePage()はページ側で定義する必要があります。"
    'TemplateTerminatePage
End Sub

Sub RenderHtml()
    Err.Raise vbObjectError + 1, "common_page_template.inc", "RenderHtml()はページ側で定義する必要があります。"
End Sub

%>


sample02.asp

<%@ LANGUAGE=VBScript %>
<% Option Explicit %>
<!-- #include file="config/settings.inc" -->
<!-- #include file="../common/inc/common.inc" -->
<!-- #include file="../common/inc/common_page_template.inc" -->

<%
' デバッグ用・エラーハンドリングなし設定
'gNoErrorHandlingForDebug = True  'コメントを外すとエラーハンドリングしない。

If Not gNoErrorHandlingForDebug Then
    On Error Resume Next
End If

'グローバル変数

'=== エントリー部 ===
Call PageMain()

'=== プロシージャ、ファンクションの定義 ===
Function GetSourceName
    GetSourceName = "sample02.asp"
End Function

Sub InitializePage()
    TemplateInitializePage
End Sub

Sub LoadPage()
    gData("sample_value") = "サンプル値"
End Sub

Sub TerminatePage()
    TemplateTerminatePage
End Sub

Sub RenderHtml()
    If Not gNoErrorHandlingForDebug Then
        On Error Resume Next
    End If
%>

<html>
<head>
</head>
<body>
<!-- コンテンツ -->
</body>
</html>
<%
End Sub 'RenderHtml
%>
ポイント
  • htmlの出力を関数化

上記では、RenderHtmlでhtmlの出力を行っている。 これのメリットは、出力内容を編集する際にグローバル変数を多用しなくて済むこと。 リストのループカウンタや簡単な文字列編集等で一時的な変数を使用したい場面でローカル変数を使うことができる。

aspをhtmlのテンプレートとして見てしまうと、少しわかりづらいかもしれないが変数を局所化するメリットのほうを選択したい。

  • 処理のテンプレート化

common_page_template.incにてメインの処理をテンプレート化すると、共通的な処理を組み込みしやすい。 例えば、テンプレート側で認証のチェックを行って、認証されてなければログイン画面に遷移させることも比較的簡単にできる。

ここで1つ注意したい点がある。 同じ名前の関数を定義している点。 vbscriptでは、同一名の関数を定義してもエラーが発生しない。 重複している場合、後から宣言した関数が有効となる。 あまり多用するのもどうかと思うが、ページ側で実装すべき関数を明示する意味で使っている。

  • その他

今回は、基本的なエラー処理とページ遷移処理をクラス化してみた。 そのほか考慮すべき点はいろいろあると思うが、少なくとも入力値の扱い方やデータの表示の仕方についてだけは検討すべきだろう。別途取り上げることにする。

Windows10 Windows Update強制適用

Windows10アップグレード後、起動したままほっといたのだが、 WindowsUpdateが実行され勝手に再起動していた。

インストールするのはまあ仕方ないとして、再起動するのは勘弁してほしい。 Windowsに期待しても無駄か。

Pro以上のエディションであれば回避することも可能という記事を見たが、Homeエディションでは再起動のタイミング調整だけが可能なようだ。

設定 → 更新とセキュリティ → Windows Updateの画面で、詳細オプションをクリックすると以下の画面が表示される。

f:id:umejan:20150807222324p:plain

「自動(推奨)」が初期値で、これを「再起動の日時を設定するように通知する」に変更する。

どのくらいほっとけるのか、最長何日後まで再起動を遅らせられるのかとかはわからず。 次回確認することにする。

このPCではVirtualBox上で開発用の環境を動かしていたのだが、 少なくともWindows10Homeでは常時動かしておくようなアプリケーションはやめておいたほうがいいと認識した。 まあ、Homeエディションで仮想環境を動かす人はそんなにいないと思うが。

2015/09/12 追記
上記の設定をしておくと一応再起動はしないようだが、再起動のスケジューリングのダイアログが表示されたままになる。 全画面でこのダイアログが表示されているので、Windowsを使いたければスケジューリングしなければなさそう。

「再起動の日時を設定するように通知する」のその後 - umejanのブログ

コードを直訳したコメントは必要?

ちょっと気になったので読んでみた。


コードを直訳したコメントは必要なのか?「要る派」と「要らない派のまとめ」【 社畜ちゃん台詞メーカー 】 - Togetterまとめ


タイトルを見て不要としか思えずどんな意見が出てるかと思ったら、意外にも要る派が多いことにびっくり。
要る派の意見をいくつかピックアップしてみる。

  • わからない人が多い

非エンジニアとかを想定している人もいたが、そもそもそのようなプログラミングがわからない人向けに記述する必要はないだろう。
設計書とか仕様書とかで説明するべきだと思う。

  • 検索用

本当に直訳コメントを検索するか?
使われている箇所を調べたり、なにを表しているかなど検索する場合、元の関数や変数の名前で検索するよね。
コメントをあてにして検索するのは気休めになるくらいだと思う。

  • 英語がわからない・日本語だとすぐわかる

本当に英語が苦手という意味で言っている人がいるが、どうなんでしょう?
使う英単語なんて中学レベルくらいじゃないのかな。
あとは業務固有の単語とか。
それから、日本語だとすぐわかると言っているが、正確な仕様を確認するには関数であれば中身を見るしかないよね。

  • コメントがあっても困ることない

意外とそれなりの経験あるプログラマでもこのような意見があるように見えたが、直訳コメントを頼りにしてコードを追っていったり、理解しようとするのは危険だろう。
コメントはコメントであってプログラムの動作にはまったく影響しない。
プログラムを理解するにはコードを見るしかない。



自分のコメントの書き方としては、

処理のまとまりごとに見出しを入れる。
わかりずらいと思われる処理については、その意図やなにを求めているのかを書く。
あとは、必要に応じて関数、クラス、メソッド、変数コメントに説明を入れる。

という感じか。

すこし心配なのは、プログラマなのにコードを見ずにとりあえずわかったと自分を納得させるため、とか思っている人がいるような気がする。

私個人は、直訳コメント要らない派。

Windows10アップグレード その2

Windows10アップグレード後の設定やスタートメニューの使い方

  • プライバシーオプションの変更

タブレットなどモバイル端末向けなためか、MSにいろいろとデータを送信しているらしいのでそれらを無効にした。

「設定」→「プライバシー」で変更できたので、不要そうなオプションをOFFにした。
f:id:umejan:20150803205732p:plain


  • コントロールパネルや管理ツールの呼び出し方

スタートメニューのすべてのアプリで探すのは手間がかかるのでどうしたものかと思ったが、
スタートメニューで右クリックすれば、よく使う管理系プログラムのショートカットが表示できる。
f:id:umejan:20150803210646p:plain

そのほかにショートカット作りたい場合は、タスクバーにピン留めするか、スタート画面にピン留めする。
スタート画面とは、スタートメニューの右側のタイル表示部分を言うらしい。
アップグレード直後のスタート画面に表示されているタイルは、デスクトップではどれも使わなさそうなので一つずつピン留めを外すの操作をして全て削除した。

f:id:umejan:20150803212012p:plain


とりあえず、管理ツールリモートデスクトップをスタート画面にピン留めした。

これである程度、Windows7と同様に操作できそうかな。

Windows10アップグレード

昨日、Windows7からWindows10にアップグレードしてみた。

機種は aspire 1410 の Windows7 homeエディション。

 

何も考えずにアップグレードしたが、だいたい問題なくWindows10に移行できた模様。

 

VirtualBoxは、ネットワークデバイスが削除されてしまったので一度アンインストールし、Ver.5.0.0.101をインストールしたら動作した。

 

あと気になるのは、タスクマネージャで「列の選択」がなくなっていて、ワーキングセットメモリやハンドル数などが表示できない点。

これらの情報はWindows10ではどうやるのかな?

 

調べたところ、Windows8からなくなったらしい。

taskmanager alternativeで検索するといくつかヒット。

とりあえず代わりにProcess Explorerをインストール。一応以前のタスクマネージャで確認していた情報が見れるようだ。

https://technet.microsoft.com/ja-jp/sysinternals/bb896653.aspx