Mobile Pcの沼に嵌ってから1年が経った

Remote Work主体になってから、先月で1周年だった

Remote 振り返り(前置き)

仕事は職場にいる日より捗る。

=>これは、単純に職場にいると、インタラプトコストが嵩むというだけだろうなあというお気持ち。

大体働きすぎる。

=>特に自分は退勤しても、C#のコードを眺めたりすることがままあるので、「あー、そういえばあのコード、こう書けるからついでに直しておこう。」となりがち。そしてそれは、やってもやらなくてもストレスになることがわかってきた。(救いようがない。)

自分は良くとも、チームメンバーにRemoteが苦手な要員が要ると、ケアが必要になることもある。

=>年明けからフルリモートにしたのだが、チームメンバーにリモートが苦手な人が居たため、週1日は出勤することになっている。コロナということもあり、少々しんどいが、苦手な人が居る以上致し方ない。

オフライン主体の企業風土の中でリモート主体の開発チームに所属していると、現地とのコミュニケーションミスマッチに苦労することが多い

=>これは当たり前なのだけれど、オフライン主体の企業風土だと、それこそたばこ部屋とかで色々決められたりしがちなので、リモート環境だとそれらを観測する術がなくなるため非常にめんどくさい。

特に自分は、自分たちの開発チームに降りかかる火の粉を事前に払う役割(平たく言うと雑用)を持ってるので、この辺を観測するのは最初非常に苦労した。

そういう意味でも結果的に週に1日の出勤日はステークホルダーのお悩み観測をついでに行うようにしている。(そして大体この辺とペアプロ業をやってるだけで1日が終わる。)

Remote Workだと自宅の作業環境に投資したい欲が高まる

Remoteになったときに気付いてしまったのです。

自分の好きな機材、使いたい放題だと。

ここから、私のMobile Pc沼とモニター沼生活が幕を開けました。

Mobile Pcをめちゃくちゃ調べまくる日々

13型のノートPCが、Mobile Pcとしては非常にベーシックなラインなのですが、この13.3インチ、Ramの搭載量に難がありました。

なにせ16GBでも大容量な部類になってしまいます。

沼生活を始めた時点でRamが32GB搭載できる13型ノートPCが、

XPS13 2In1

Elite Book

のどちらかしかないという状態。

Surface Laptop 3 15インチ発売

正確に言うと、Surface Laptop 3 15の法人版のみですが、Ram32GB搭載モデルが発売されました。

13インチじゃないじゃん!!とスルーしようと思った後よくよく見てみると、15インチのSurface Laptop 3は、15インチにも関わらず、重量が1.5kg程度しかなかったので、ギリギリ許容範囲だろうか?どうだろうか?と悩むことに。

ディスプレイも3:2で使いやすそうだしなーうーんうーん。と言ってる間に、年が明けました。

XPS 13 発売

2IN1は前から発売していたものの、ラップトップ版のXPS13の方が年明けに発売し、これもRam32GB搭載のモデルが発売しました。

が、なぜかフロストホワイトのカラバリがおま国ということで、購入を回避することとなりました。

ThinkPad X13(AMD)発売

この辺になってくると、最早乗り換え先の選定が難航しすぎててとりあえず刻みたいという欲が出てきたので購入しました。

Ryzen Pro 4750U + 32GB Ram + 1TB PCIe SSDということで、刻む端末にしては強すぎましたが、thunderbolt3が搭載されていない点と、ディスプレイが狭額縁ではない点を除けば非常に素晴らしい機種でした。

が、Ryzenのせいなのか、若干VisualStudioでのGit Clone時に挙動が微妙だったりと、Intelにしときゃよかったかな感が若干あります。

Surface Laptop 4 発売延期

新型コロナの影響でSurface Laptop 4の発売が延期となりました。

結果的にX13で刻んだことがナイスプレイ俺!!と思っていた今日この頃でしたが、、、

LIFEBOOK WU2/E3 軽量5G対応 カスタムメイドモデル 発売

Tiger Lake Corei7 1165G7 + 32GB LPDDR4X-4266 Ram + 2TB PCIe SSD + IGZO液晶(+狭額縁) + thunderbolt4 + 5G + 898g

という、素晴らしい端末が発売されました。 私はX13で刻んでしまったので今回は導入しませんが、今Mobile Pcを導入するのであれば、予算さえあれば非常に良い選択肢に思います。

富士通さん、キーボードは良いけど、性能は保守的だなーとか今まで思ってて申し訳ございませんでした🙇

モニター沼編は次回以降です

※書くかどうかはわかりません。

Windows10 1903 でWSL2を有効にする

TL;DR

当初はWindows 10 2004から利用可能ということだったが、1903から利用が可能だったことを二か月くらい前に発見したけど、発見して満足してたのでとりあえず文章にしておく。

対象読者

Docker / WSLを利用している or 利用したい人 WSL2がWin 10 2004からしか利用できないと悲しい思いをしていた人

WSL2のインストール方法

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

Linux ディストリビューションのインストールについても、上記URLに説明があるので併せてご参照の上セットアップを行う。

自分は主にUbuntuを利用していますが、他のLinuxでも問題ない。はず。

Docker Desktop For Windowsのインストール

https://www.docker.com/get-started

WSL2を有効にした状態で、↑から、Docker Desktop For Windows を取得してインストールする。

Enable WSL 2 Windows Featuresのチェックボックスはつけたままインストール処理を行う。

感想

Microsoftさんのこういうところは本当に頭が下がります。

とともに、WSL2が1903で使えるんだと、2004に上げるインセンティブが弱くなるなぁ(個人の感想です。)

備忘録:開発用PCのセットアップ2020

インストールするもの

ブラウザ

Google Chrome

HyperV有効化

Docker For Windows有効化

=>まだWindows10 2004のアップデートがもらえない勢なのでWSL2が使えない。

Windows Terminal

IDE / エディター

Visual Studio 2019 Pro Visual Studio Code

Microsoft 365

旧o365 Solo導入

Visual Studio Extensions

※ 最近はLive ShareやIntelliCodeは勝手に入るので少し楽

VCS / SCM

Git For Windows(エディターの紐づけはVisual Studio Codeを設定。 AutoCrlf => true)

Logicool Options

ショートカットも一緒に設定

ScreenPresso

保存枚数は10000枚、スクリーンショット取得後の動作は、何もしないに設定

launchSettings.jsonのconfigを変更して、DockerのServicePortを限定してみる

Dockerサポートを有効にしてスキャフォールディングしたWebApiのlaunchSettings.jsonを確認してみた

f:id:CreatioVitae:20200701000354p:plain publishAllPortsがtrueになっているので、起動するたびにPortが変わってしまう設定になっています。 Api単体で使うときはこれでもいいのですが、ViewからWebApiを発火させたい場合は、Portは固定させたい欲があります。

Microsoft Docsを見てみた

docs.microsoft.com

      "httpPort": 51803,
      "useSSL": true,
      "sslPort": 44360

といきなり冒頭に答えが書いてあります。

publishAllPortsにはfalse(試してませんが、恐らく規定値falseな気がするので、消してもいいくらいかもしれません。)

httpPort、sslPortの設定については、useSSLをしている以上は、sslPortがあれば問題ない気がしますが、httpPortを書かなくてもおけまるなのかは未検証です。

    "Docker": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/weatherforecast",
      "publishAllPorts": false,
      "httpPort": 51803,
      "useSSL": true,
      "sslPort": 44360
    }

launchSettings.json、あんまわかってない問題

launchSettings.json、ローカルデバッグの強い味方、のはずなんですが、自分は現在あまりわかってないなーということを再認識したので、余裕が出来たら一度深堀してみたい領域だなーと感じました。(小並感)

.NET Coreのタイムゾーン識別ID問題について

前提となる開発環境

開発機 / IDE / Testing Framework

Windows 10、VisualStudio 2019 、xUnit、TestHostも利用

ローカルデバッグ環境

Docker(WSL に Ubuntuをインストールして運用)

Dev,Prod環境

Linux(Ubuntu)

備考

チーム開発をしていて、自分はWindows機だけれど、チームメンバーにはMac機の方もいらっしゃる

.NET CoreでTimeZoneInfo取得しようと思ったら、タイムゾーンを識別するためのIdが、WindowsLinuxで異なる問題

TimeZoneInfoを取得したいだけの人生だったので、安易に

var hoge = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time"));

って書いてしまいがちなのですが、これだと、Windowsでしか動かないコードでした。(Linux環境だとTimeZoneNotFoundExceptionで例外が発生する。)

Linuxだと、

var hoge = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo"));

と書くのが正しいらしく、「あ、環境によって識別Id違うんですね。」というお話でした。 そして、この辺、どういうアプローチが正道なのかなと、調べてみると、↓のWebページが出てきました。

devblogs.microsoft.com

要約すると、TimeZoneConverterを利用しましょうということが書いてあります(雑)

TimeZoneConverterを使おう

github.com

TZConvert.GetTimeZoneInfo を利用することで、この識別ID問題を解決してくれます。

なので、どちらのIDを指定しても動作するようになりました。

こんな感じ

var hoge = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TZConvert.GetTimeZoneInfo("Tokyo Standard Time"));

var hoge = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TZConvert.GetTimeZoneInfo("Asia/Tokyo"));

.NET Core / C#マルチプラットフォームになったからこそ気にしなけばならないことがあると感じる

昔はWindowsでしか動かさなかったので、このへんの識別IDもWindows用だけ使えばよかったんですが、.NET Coreになって様々な環境で駆動出来るようになったことで気にしなければならないことがあるんだなあと感じました。

移植容易性に係るお話でもあるので、意識していきたいのと、やっぱりWindows機だと、Linux機で動くかわからないので、ローカルデバッグ環境はDockerで良かったと感じてみたりしました。

予習:.NET 5 Preview 4(Preview5はこれから見る)

C#9が使えるのは.NET 5だけ

Buildは少し観測しつつ、de:codeでキャッチアップするゆとり勢なので、ようやく予習を始める。

MAUI

devblogs.microsoft.com github.com => 旧Xamarin Forms(まだ名前空間をリネームしただけ。)

.NET 5(In C# 9)

devblogs.microsoft.com

Native Int

a.k.a. IntPtr IntPtrのエイリアスで、整数演算ができるようになった。ものらしい。 intとの違いはCPU Native。 32bit CPUなら32bit整数、64bitなら64bit整数 C#単体というよりC++等CPUネイティブなアレとのジョイントがある場合に重宝するのかしら? 普段そういったことをしていないのでわからず……。

Target Typed New

所謂左辺から型推論するアレ。コード量が減る印象。

        [HttpPost]
        public List<WeatherForecast> Post() => new()
        {
            new(){ Date = DateTime.Now, TemperatureC = 20, Summary = "test_now" },
            new(){ Date = DateTime.Now.AddHours(2), TemperatureC = 19, Summary = "test_now_plus_2_hours" },
            new(){ Date = DateTime.Now.AddHours(4), TemperatureC = 18, Summary = "test_now_plus_4_hours" }
        };

なお、C#8までは

        [HttpPost]
        public List<WeatherForecast> Post() => new List<WeatherForecast>
        {
            new WeatherForecast { Date = DateTime.Now, TemperatureC = 20, Summary = "test_now" },
            new WeatherForecast { Date = DateTime.Now.AddHours(2), TemperatureC = 19, Summary = "test_now_plus_2_hours" },
            new WeatherForecast { Date = DateTime.Now.AddHours(4), TemperatureC = 18, Summary = "test_now_plus_4_hours" }
        };

とかになる。 メソッド呼び出し時も左辺から型推論になるはずなので、よく使うことになりそう。

Type Switch (C# 9.0 ver)

        public WeatherForecast GetResponsesByStatusCode(int statusCode) => statusCode switch
        {
            < 600 and >= 500 => new() { Date = DateTime.Now, TemperatureC = 20, Summary = "server_error_pattern" },
            < 500 and >= 400 => new() { Date = DateTime.Now, TemperatureC = 20, Summary = "request_error_pattern" },
            < 400 and >= 200 => new() { Date = DateTime.Now, TemperatureC = 20, Summary = "request_success_pattern" },
            _ => throw new ArgumentException(nameof(statusCode))
        };

色々使える予約語が増えていたりと、便利に気持ち悪く進化してきている印象。 型スイッチはC# 7 以降で、コード表現の向上のために色々入ってきているので使っていきたい。

型スイッチでは、and, or, notキーワードが追加されている。 これで、ずっと書きたかった、 

if(hoge is not null){ } 

が書けるようになる。 今までは

if(!hoge is null )

とか、書いていたり、andとかor条件だった場合にはさらにかっこがネストされたりするのがなくなるのは嬉しいので歓迎したい。

パターンマッチングのプロパティパターンを使ってみる(Case Null検査)

null検査のときの書き方問題

HogeのInstanceであるhogeがnon nullである検査をしたい場合、

hoge is Hoge

と書いてしまうことが多いのですが、C#8.0から、パターンマッチングにプロパティパターンが追加されているので、

hoge is { }

と書けばnon nullかの検査が出来るので、hogeの型がめちゃんこ長い名前でも{ } って書くだけなので、書くのが楽になりました。

もちろん型パターンでの型変換も書ける

if (hoge is {} nonNullHoge ){
    // ・・・
}

ただ、この場合、あくまでHoge?がHogeになるだけなので、型変換としてのうまみは微妙なところです。 Object型を、型パターンで is string stringHoge みたく、変換するようなニーズには対応できないので。 通常、hoge is {} の検査をすれば、C#のフロー解析では、後続のコードでは、hogeが Non Null であるという判断をするはずなので、nonNullHogeに変換する必要性はあまり感じないです。

とはいえ、Applicationを書いていると、HogeFugaPiyoForFooBarXXX みたいな、修飾が色々されたクラスを作成することも多いので、{ }で済ませられるのはとても助かっています。