一休.com Developers Blog

一休のエンジニア、デザイナー、ディレクターが情報を発信していきます

普段MacやLinuxでWeb開発している方向けに知ってもらいたいC#とWindows

この記事は一休.com アドベントカレンダーの17日目の記事です。

qiita.com


宿泊事業部のいがにんこと山口です。
UIUXチームでフロントエンド、バックエンドのアプリケーション開発を担当しています。

一休では宿泊事業とレストラン事業があります。
私が所属する宿泊事業では開発言語にC#とVB.NETを使用しています。
その背景から開発にはWindowsを使っています。
普段MacやLinuxでWeb開発しているWebエンジニアにとってはWindows、C#を使ったWeb開発はあまり馴染みがないかもしれません。
そこでそんな方向けにWindows、C#を使ったWeb開発についてお話したいと思います。

C#について

まずはC#について。
C#に触れたことのない方はどんなイメージを持っていますかね?
Microsoft製?Javaみたい?使っている企業は?

色々なイメージがあるかと思います。
ここではC#を企業、開発環境、記述といった点から説明します。

使っている企業

C#を使っている企業ってどんな業界なんでしょう?
主にゲーム系、金融系で使われているイメージです。
ゲーム系はコンシューマー、ソシャゲに限らないですが、Unityを使っている企業はその流れでサーバーサイドもC#という企業が多いようです。
金融系はMicrosoftのサポートを期待しての導入でしょうか。
サポート期間の長さも特徴の一つで、それも採用の理由の一つかもしれません。 https://support.microsoft.com/ja-jp/lifecycle/search?alpha=Microsoft%20.NET%20Framework%203.5 を見ると2008年に出た.Net Framework 3.5(C#の実行環境)が2028年までサポートされることになっているので、20年ものサポート期間があることになります。 自社のWebサービス、アプリ(ゲームを除く)をやっている会社ではまだまだ採用している企業が多いとは言えません。
余談ですがC#erに特化した会社なんてのもできましたがゲーム向けですね。

開発環境

弊社ではVisual StudioというIDEを使用しています。
Visual Studioと聞いて思い浮かべるのはVisual Studio Codeでしょうか。
Visual StudioとVisual Studio Codeは全くの別物です。
Visual Studio Codeはクロスプラットフォームで動作するのに対して、Visual StudioはWindowsでのみ動作します。
C#の開発に使用するIDEとしてはVisual Studioが一強です。
他にはVisual Studio for MacやJetBrainsから出ているRiderというIDEもありますが一休では使用していません。

一休は.Net FrameworkというWindowsでのみ動作するC#の実行環境をメインに使用しています。
そのためWindowsにロックインされていますが、クロスプラットフォームである.Net Coreの登場に加え、上記のIDEもあるためMac、Linuxでの開発も可能です。
まだ.Net Coreの採用事例は少ないですがC#はWindowsだけのものではなくなってきています。

Windows内部でのWebサーバー

ローカル開発環境はIISというものを使用します。
いわゆるApacheやnginxのようなWebサーバーです。
画像のようにGUIからの操作が可能であり、もちろんCUIからの操作も可能です。
一休では開発環境の初期構築をしてくれるバッチファイルがあり、それを実行するとこのIISのサイトを構築、設定してくれるようになっています。

f:id:igatea:20181214181051p:plain

Docker

実はWindowsもDockerを動かすことができます。
Macで使われているDocker for MacのWindows版、Docker for Windowsがあります。
内部ではHyper-VでMobyLinuxを立ててその上にDockerコンテナがホスティングされるようになっています。

f:id:igatea:20181217035420p:plain

それだけでなく今やVirualboxなどの仮想環境構築ソフトに頼らずUbuntuも使うこともできるWSL(Windows Subsystem for Linux)というものもあります。
VagrantやDockerとは使い勝手が違うので躓くこともありますが、使用用途を限定すれば今のところ問題ありません。 www.atmarkit.co.jp

Webフレームワーク

一休ではC#でWebを開発するときにASP.NET Web FormsとASP.NET MVC、ASP.NET Web APIを使用しています。
ASP.NET Web FormsはイベントドリブンモデルでWindowsアプリケーションの知識をWebでも活用できるように作られたフレームワークです。
単体テストを行いにくかったり、固有の概念やビューとなるHTMLの制御が難しいなど、今のWeb開発には合っておらず新規で採用するメリットはありません。
そのためこれから新規プロジェクトを作る場合はMVCかWeb APIで作成するかと思います。

ASP.NET MVCについては特筆する点はありませんが、一般的なMVCフレームワークの機能が備わっており、薄すぎず厚すぎずでちょうどいい塩梅のフレームワークとなっています。
ASP.NET MVCはMVCという名前はついていますが実はモデルに相当する機能はありません。
そこでロックインされていないのでモデルの作成は柔軟に行えるようになっているところもメリットです。

記述型式

ここからはC#の記述を紹介します。
C#は強い静的型付けの言語です。
そしてオブジェクト指向言語でもあります。

実際のコードを見てみましょう。

public class Child : Parent
{
    private readonly string str;

    private readonly int num;

    public Child(string str, int num)
    {
        this.str = str;
        this.num = num;
    }

    public string GetContent()
    {
        return $"str = {str}, num = {num}";
    }
}

var child = new Child("test", 1);
child.GetContent();
// str = test, num = 1

オブジェクト指向言語をやってきた方なら細かい差異はあれど理解しやすいのではないでしょうか。
このコードだけ見るとかなりJavaに近いですね。
名前空間、パッケージによるアクセシビリティレベルが違ったりEnumにメソッドが生やせないといった違いはあります。
加えて型推論、getter setter、async awaitなど便利な機能に加えてLINQという便利なコレクションライブラリもあります。

型推論

// int型に
var num = 1;

// List<string>型に
var strList = new List<string>() { };

getter, setter, メンバ

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName
    {
        get => $"{FirstName}{LastName}";
    }
}


var Person = new Person();
Person.FirstName = "Taro";
Person.LastName = "Tanaka";
Console.WriteLine(Person.FullName);

プロパティごとにアクセス修飾子を変えることもできます。

public int Age
{
    get;
    private set;
}

readonlyというものも。

public class Person
{
    private readonly DateTime birthday;

    public Person(DateTime birthday)
    {
        this.birthday = birthday;
    }
}

インスタンスフィールドであればコンストラクタ内でのみ割り当て可能という制限をつけることができます。

初期化

オブジェクト初期化子
public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public Person() { }
}

var Person = new Person()
{
    FirstName = "Taro",
    LastName = "Tanaka"
};
名前付き引数
public class Person
{
    public Person(int age, DateTime birthday)
    {
        // 処理
    }
}

var Person = new Person(age: 5, birthday: DateTime.Now);

async await

単数のタスク
public async Task<string> GetSingleAsync()
{
    var result = await GetStringAsync();
    return $"結果={result}";
}

private Task<string> GetStringAsync()
{
    var task = Task<string>.Run(() =>
    {
        // 何か重い処理
        return "async!";
    });
    return task;
}

var single = new SampleAsync().GetSingleAsync().Result;
複数のタスク
public async Task<string> GetMultiAsync()
{
    var task1 = GetStringAsync();
    var task2 = GetStringAsync();
    var task3 = GetStringAsync();
    var task4 = GetIntAsync();

    var results = await Task.WhenAll(task1, task2, task3);

    return string.Join(",", results);
}

var multi = new SampleAsync().GetMultiAsync().Result;

LINQ

コレクションを便利に扱える拡張メソッドです。
これがとても強力でこれがあるからこそC#は良いと言えるほどです。

var arr = new string[] { "a", "bb", "ccc" };

// 含んでいるか
arr.Any(s => s == "a");
// True

// 絞り込み
arr.Where(s => s.Length >= 2);
// IEnumerable<string> { "bb", "ccc" }

// 射影
arr.Select(s => s + s);
// IEnumerable<string> { "aa", "bbbb", "cccccc" }

// 他にも色々

IEnumerableな値(簡単に言うとforeachでループ可能)が返されるためメソッドチェーンで書くことが可能です。

arr.Where(s => s.Length >= 2)
    .Select(s => s + s)
    .ToArray();

他にも

  • 拡張メソッド
  • ジェネリクス
  • 属性定義、Attribute
  • null条件演算子
  • 例外フィルター
  • タプル、分解

といったものがあります。
記述だけ見るとモダンな言語に劣らず便利なものがそろっていますよね。
この記事で少しでもWindows、C#でのWeb開発に興味を持ってもらえたら幸いです。

明日はid:undersooon 「ちょっとしたことを検索できる」Slack botを作った、です。