読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

ReactiveProperty 3.6.0をリリースしました

ReactiveProperty

昨日の夜にやろうと思ったんですが今日になってしまいました。

www.nuget.org

今回は、iOS向けのSetBindingメソッドが正しく動いてなかった奴の修正と、ReactiveCommandAsyncReactiveCommandクラスのSubscribeメソッドに引数無し版を追加しました。どちらもプルリクエストです。ありがたやありがたや。

Visual Studio 2017 リリース記念勉強会で発表してきました

.NET

3月11日にC#ユーザー会が開催したVisual Studio 2017 リリース記念勉強会で発表してきました。

発表資料を公開します。

30分というあわただしい感じの発表になってしまいましたが、なにか1つくらい知らない機能を持ち帰っていただけたらいいなと思って発表しました。どうだったのかなぁ。

ASP.NET CoreでAngularをする VSCodeを使おう

ASP.NET TypeScript

dotnet new angularでプロジェクト作成して、webpackしてdotnet runで実行できることはわかりました。 では、Visual Studio Codeで快適に作業するにはどうするのがいいのか?ということになりますよね!

Visual Studio Codeで開発するには以下のような感じでとりあえずやってます。

まずは、PowerShellあたりで適当なフォルダを掘ってdotnet new angularします。

> mkdir AngularVSCode
> cd AngularVSCode
> dotnet new angular

必要パッケージを入れます

> npm install
> dotnet restore

VSCodeを立ち上げましょう!

> code .

ターミナルを表示して、webpack -wと打ち込みます。これでTypeScriptに変更があったら自動でwebpackが走るようになります。もう1つターミナルを立ち上げてdotnet runしましょう。

これで下準備完了です! あとは、Angular弄ってブラウザをリフレッシュすれば変更が反映された状態になります。

では、快適Angular生活をVisual Studio Codeで!!

ASP.NET CoreでAngularをするHello world

ASP.NET TYpeScript

以下の記事の続きです。

blog.okazuki.jp

ひな形に自分のプログラムを追加してHello worldしてみます。

ClientAppフォルダにAngularのプログラムの本体がいます。そこを弄っていきます。

ClientApp/app/componentsフォルダにhelloworldフォルダを作りましょう。そして、その中にhelloworld.component.tsファイルとhelloworld.component.htmlを作ります。

Angularのお作法に従いコンポーネントを作っていきます。helloworld.component.tsは以下のような感じで。

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'helloworld',
    templateUrl: './helloworld.component.html'
})
export class HelloWorldComponent implements OnInit {
    constructor() { }
    
    title:string = "Hello world";

    ngOnInit() { }
}

helloworld.component.htmlは以下のような感じにします。

<h1>{{title}}</h1>

コンポーネントのプロパティを単純に表示してるだけですね。

ClientApp/app/app.module.tsに作成したモジュールを追加します。ルーティングもhelloworldという文字列で遷移するように設定しておきます。

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { HelloWorldComponent } from "./components/helloworld/helloworld.component";

@NgModule({
    bootstrap: [ AppComponent ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        CounterComponent,
        FetchDataComponent,
        HomeComponent,
        HelloWorldComponent
    ],
    imports: [
        UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
        RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: HomeComponent },
            { path: 'counter', component: CounterComponent },
            { path: 'fetch-data', component: FetchDataComponent },
            { path: 'helloworld', component: HelloWorldComponent },
            { path: '**', redirectTo: 'home' }
        ])
    ]
})
export class AppModule {
}

そして、ナビゲーションメニューのClientApp/app/components/navmenu/navmenu.component.htmlにメニューを追加します。

<div class='main-nav'>
    <div class='navbar navbar-inverse'>
        <div class='navbar-header'>
            <button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
                <span class='sr-only'>Toggle navigation</span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
            </button>
            <a class='navbar-brand' [routerLink]="['/home']">dotnet_angular_helloworld</a>
        </div>
        <div class='clearfix'></div>
        <div class='navbar-collapse collapse'>
            <ul class='nav navbar-nav'>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/home']">
                        <span class='glyphicon glyphicon-home'></span> Home
                    </a>
                </li>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/counter']">
                        <span class='glyphicon glyphicon-education'></span> Counter
                    </a>
                </li>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/fetch-data']">
                        <span class='glyphicon glyphicon-th-list'></span> Fetch data
                    </a>
                </li>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/helloworld']">
                        Hello world
                    </a>
                </li>
            </ul>
        </div>
    </div>
</div>

他のを真似て書いてるだけで何がおきてるのか私にもわかりません。

そして、アプリケーションのルートフォルダでwebpackコマンドを実行します。(webpack入れてないひとはnpm install -g webpackしてね)

PS C:\Users\kaota\Documents\Visual Studio Code\Projects\dotnet-angular-helloworld> webpack
Hash: 58aabf820ca74ec21bf0a8dac7da2d1b48f06b83
Version: webpack 2.2.1
Child
    Hash: 58aabf820ca74ec21bf0
    Time: 10190ms
                 Asset     Size  Chunks             Chunk Names
        main-client.js  24.1 kB       0  [emitted]  main-client
    main-client.js.map  27.2 kB       0  [emitted]  main-client
Child
    Hash: a8dac7da2d1b48f06b83
    Time: 10155ms
             Asset    Size  Chunks             Chunk Names
    main-server.js  154 kB       0  [emitted]  main-server

そして、dotnet runをしましょう。

http://localhost:5000/ にアクセスするとHello worldメニューが増えています。そして、それをクリックすると以下のようにハローワールドが表示されます。

f:id:okazuki:20170305095150p:plain

やったね!

ASP.NET CoreでAngularをする下準備

ASP.NET TypeScript
2017/03/05 日時点の情報です

@angular/cliとか使って始めるのもいいですが、これだとサーバーサイド何でつくるの??という感じになってしまうので、C#erとしては今やるならASP.NET Coreでしょ!ということで始め方をメモっておきます。

結論としてはdotnetコマンドで作れます。ということで最新の.NET Core SDK 1.1のRC4を以下のページからダウンロードしてきました。

github.com

インストールしてdotnet --infoと打ち込むと以下のように表示されます。

PS C:\Users\kaota\Documents\Visual Studio Code\Projects> dotnet --info
.NET Command Line Tools (1.0.0-rc4-004771)

Product Information:
 Version:            1.0.0-rc4-004771
 Commit SHA-1 hash:  d881d45b75

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.14393
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\1.0.0-rc4-004771

次にAngularとかSPA関連のプロジェクトテンプレートをダウンロードします。以下のコマンドを打ち込みます。

dotnet new --install Microsoft.AspNetCore.SpaTemplates::*

しばらく待ってるとインストールが終わります。終わったらdotnet newと打ち込んでみましょう。以下のようにAngularとかのテンプレートがインストールされてることがわかります。(Vue.jsはないのね)

PS C:\Users\kaota\Documents\Visual Studio Code\Projects> dotnet new
Template Instantiation Commands for .NET Core CLI.

Usage: dotnet new [arguments] [options]

Arguments:
  template  The template to instantiate.

Options:
  -l|--list         List templates containing the specified name.
  -lang|--language  Specifies the language of the template to create
  -n|--name         The name for the output being created. If no name is specified, the name of the current directory is
 used.
  -o|--output       Location to place the generated output.
  -h|--help         Displays help for this command.
  -all|--show-all   Shows all templates


Templates                                     Short Name      Language      Tags
------------------------------------------------------------------------------------------
Console Application                           console         [C#], F#      Common/Console
Class library                                 classlib        [C#], F#      Common/Library
Unit Test Project                             mstest          [C#], F#      Test/MSTest
xUnit Test Project                            xunit           [C#], F#      Test/xUnit
Empty ASP.NET Core Web Application            web             [C#]          Web/Empty
MVC ASP.NET Core Web Application              mvc             [C#], F#      Web/MVC
MVC ASP.NET Core with Angular                 angular         [C#]          Web/MVC/SPA
MVC ASP.NET Core with Aurelia                 aurelia         [C#]          Web/MVC/SPA
MVC ASP.NET Core with Knockout.js             knockout        [C#]          Web/MVC/SPA
MVC ASP.NET Core with React.js                react           [C#]          Web/MVC/SPA
MVC ASP.NET Core with React.js and Redux      reactredux      [C#]          Web/MVC/SPA
Web API ASP.NET Core Web Application          webapi          [C#]          Web/WebAPI
Solution File                                 sln                           Solution

Examples:
    dotnet new mvc --auth None --framework netcoreapp1.0
    dotnet new classlib --framework netstandard1.4
    dotnet new --help

では、適当なフォルダ(ここではdotnet-angular-helloworldという名前にしました)を作って、そこでdotnet new angularをしてみましょう。

そして、npm installdotnet restoreして必要なパッケージをダウンロードします。

最後にdotnet runで実行してみます。そして http://localhost:5000/ にアクセスしてみましょう。

以下のように、ちょっとハローワールド…?というくらい作りこまれたページが表示されます。

f:id:okazuki:20170305091636p:plain

ふむ。とりあえず、これでAngular始めるときのとっかかりとしてC#erがやるにはちょうどいいかも?サーバーサイドはASP.NET Coreでいけるしね!

一定時間やりなおしが出来るようにする

UWP XAML

メール削除とかしたけど、一定時間取返しがきくみたいなUIがありますよね。 あぁいうのどうやるんだろうというのを考えてみました。

UWPでやってみますが、WPFでもXamarin.Formsでも基本的に同じ感じになると思います。見た目凝るのが一番難しそう。

Modelの作成

とりあえず、ReactivePropertyとPrism.Coreを参照に追加して以下のコードを書きます。

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace App2
{
    class LazyActionSampleApp
    {
        public ObservableCollection<Guid> Guids { get; } = new ObservableCollection<Guid>();

        public Task<bool> AddGuidAsync(IObservable<Unit> cancel)
        {
            var guid = Guid.NewGuid();
            this.Guids.Add(guid);

            var tcs = new TaskCompletionSource<bool>();

            Observable.Return<Func<bool>>(() => true)
                .Delay(TimeSpan.FromMilliseconds(3000))
                .Amb(cancel.Take(1).Select<Unit, Func<bool>>(_ => () => { this.Guids.Remove(guid); return false; }))
                .Subscribe(x => tcs.SetResult(x()));

            return tcs.Task;
        }
    }
}

Reactive ExtensionsのAmbを使うと先に発火したほうを後ろに流すことができます。これを使ってコミット処理(今回はtrueを返すだけ)とキャンセル処理(今回はコレクションに追加したものを削除する)といったFuncを合成してSubscribeして実行しています。一応処理が成功したのかキャンセルされたのかは戻り値で返すようにしました。

あとは、VMとVを作っておしまい。

using Prism.Mvvm;
using Reactive.Bindings;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading.Tasks;

namespace App2
{
    public class MainPageViewModel : BindableBase
    {
        private LazyActionSampleApp Model { get; } = new LazyActionSampleApp();

        public ObservableCollection<Guid> Guids => this.Model.Guids;

        public ReactiveProperty<bool> IsBusy { get; } = new ReactiveProperty<bool>(false);

        public AsyncReactiveCommand AddCommand { get; }

        public AsyncReactiveCommand CancelAddCommand { get; }

        public MainPageViewModel()
        {
            this.AddCommand = new AsyncReactiveCommand(this.IsBusy.Select(x => !x).AsObservable());
            this.CancelAddCommand = new AsyncReactiveCommand(this.IsBusy.AsObservable());

            var cancelTrigger = new Subject<Unit>();
            this.AddCommand
                .Subscribe(async x =>
                {
                    this.IsBusy.Value = true;
                    await this.Model.AddGuidAsync(cancelTrigger);
                    this.IsBusy.Value = false;
                });

            this.CancelAddCommand.Subscribe(_ =>
            {
                cancelTrigger.OnNext(Unit.Default);
                return Task.CompletedTask;
            });
        }
    }
}
using Windows.UI.Xaml.Controls;

namespace App2
{
    public sealed partial class MainPage : Page
    {
        private MainPageViewModel ViewModel { get; } = new MainPageViewModel();

        public MainPage()
        {
            this.InitializeComponent();
        }
    }
}
<Page
    x:Class="App2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Button Content="Add"
                Command="{x:Bind ViewModel.AddCommand}" 
                HorizontalAlignment="Stretch"/>
        <Button Content="Cancel"
                Command="{x:Bind ViewModel.CancelAddCommand}" 
                HorizontalAlignment="Stretch"
                Grid.Row="1" />
        <ListView ItemsSource="{x:Bind ViewModel.Guids}"
                  Grid.Row="2" />
    </Grid>
</Page>

実行結果

こんな感じになります。

www.youtube.com

Azure AD対応のマルチテナントアプリケーションを作ってみよう

Azure ASP.NET

以下のサイトにサンプルがあるので、それに沿ってやっていきます。

github.com

Azure ADのディレクトリを作る

というわけでさくっとクラシックポータルからAzure ADのディレクトリを作ります。 ここでは、okazukimultitenanttestという名前で作りました。

アプリケーションも作りましょう。multitenanttestappという名前でWebアプリケーションとして作っておきます。 サイオンオンURLと応答URLを、以下のような感じにします。

https://これから作るWebAppsの名前.azurewebsites.net/

アプリケーション ID/URIを以下のようにします。

https://<テナント名>.onmicrosoft.com/なんか適当

テナント名は今回はokazukimultitenanttestなのでhttps://okazukimultitenanttest.onmicrosoft.com/multitenantappみたいにしました。

アプリケーションの追加から、Microsoft Graphを追加してデリゲートされたアクセス許可にSign in and read user profileを選択します。

そして、キーを生成してメモっておきます。

アプリの作成

空のASP.NET Webアプリケーションを作ります。MVCにチェックを入れておきましょう。 クラウドにホストするを選んでAzureのWeb appsにデプロイできるようにしておきます。(後からでもできる)

ControllersフォルダにHomeControllerを作ります。Indexに対してViewも作っておきましょう。ここら辺は、Indexアクションを右クリックしてビューを追加を選ぶと楽です。

NuGetの追加

NuGetを使って以下のパッケージをインストールします。

  • Microsoft.Owin.Host.SystemWeb
  • Microsoft.Owin.Security.OpenIdConnect
  • Microsoft.Owin.Security.Cookies

Startup.csの追加

OWINのスタートアップのクラスを作ります。Visual StudioにOWIN Stgartupクラスのテンプレートがあるので、そこから選んで作りましょう。

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using Microsoft.IdentityModel.Protocols;
using System.Configuration;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using System.IdentityModel.Tokens;
using System.IdentityModel.Claims;

[assembly: OwinStartup(typeof(MultiTenantApp.Startup))]

namespace MultiTenantApp
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var clientId = ConfigurationManager.AppSettings["ida:ClientId"];
            var authority = "https://login.microsoftonline.com/common";

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = clientId,
                    Authority = authority,
                    TokenValidationParameters = new TokenValidationParameters
                    {
                        // 自分でやるのでfalse
                        ValidateIssuer = false,
                    },
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        RedirectToIdentityProvider = ctx =>
                        {
                            var appBaseUrl = $"{ctx.Request.Scheme}://{ctx.Request.Host}{ctx.Request.PathBase}";
                            ctx.ProtocolMessage.RedirectUri = appBaseUrl;
                            ctx.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
                            return Task.FromResult(0);
                        },
                        SecurityTokenValidated = ctx =>
                        {
                            // ここで本当はテナントIDとかのチェックをする
                            var issuer = ctx.AuthenticationTicket.Identity.FindFirst("iss").Value;
                            var upn = ctx.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
                            var tenantId = ctx.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

                            // 上記値をチェックして不正なテナントやユーザーだったら
                            // SecurityTokenValidationExceptionを投げる

                            return Task.FromResult(0);
                        },
                        AuthenticationFailed = ctx =>
                        {
                            // エラーの時のリダイレクト
                            ctx.OwinContext.Response.Redirect("/Home/Error");
                            ctx.HandleResponse();
                            return Task.FromResult(0);
                        }
                    }
                });
        }
    }
}

画面の作成

サインインして情報を表示するプログラムを書いてみましょう。HomeControllerを以下のように書き換えます。

using System;
using System.Collections.Generic;
using System.IdentityModel.Claims;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MultiTenantApp.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            var ctx = this.HttpContext.GetOwinContext();
            var issuer = ctx.Authentication.User.FindFirst("iss").Value;
            var upn = ctx.Authentication.User.FindFirst(ClaimTypes.Name).Value;
            var tenantId = ctx.Authentication.User.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

            this.ViewBag.Issuer = issuer;
            this.ViewBag.Upn = upn;
            this.ViewBag.TenantId = tenantId;

            return View();
        }

        public ActionResult SignOut()
        {
            this.HttpContext.GetOwinContext().Authentication.SignOut();
            return Redirect("/Home");
        }
    }
}

Authorize属性をつけている点とOwinContext経由で認証情報を取っているところがポイントです。

Index.cshtmlでは以下のようにViewBagの情報を画面に出しています。

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<ul>
    <li>@this.ViewBag.Issuer</li>
    <li>@this.ViewBag.Upn</li>
    <li>@this.ViewBag.TenantId</li>
</ul>

Web.configへの設定の追加

Web.configに設定を追加します。ADにアプリ作ったときに取得できるクライアントIDとキーをappSettingsのida:ClientIdとida:Passwordに設定します。

<add key="ida:ClientId" value="クライアントID" />
<add key="ida:Password" value="パスワード" />

実行して動作確認

デプロイして実行してみると以下のようにログイン画面が出ます。(httpsでアクセスしてね) ログインが求められるのでお手持ちのAzure ADのテナントに登録されているユーザーでログインしてみます。(無ければAzureクラシックポータルから作ってください)

ログインすると、以下のように情報が表示されます。

f:id:okazuki:20170302140747p:plain

テナントIDの取得方法

Azure ADのテナントIDの取得方法ですが、以下のようにして取得できるみたいです。

stackoverflow.com

以下のURLにアクセス

https://login.windows.net/YOURDIRECTORYNAME.onmicrosoft.com/.well-known/openid-configuration

出てきたJSONのauthorization_endpointにあるGUIDっぽいのがテナントIDになります。

SIerから日本マイクロソフトへ転職しました

Other

2月17日付で富士通の子会社のSIerを退職しました。2月20日から日本マイクロソフトで働きはじめました。 ということで振り返りを。

富士通の子会社に入社

2005年に富士通の子会社に入社しました。確か当時1500人規模だったと記憶しています。 新宿に拠点を構えて、中部、大阪にも支社がある感じです。

そんなところで何をしてきたかというと、半年間みっちりJavaでWebアプリケーション開発を行う研修をしました。 当時はまだVisual Studioとかは企業向けでは無償ではなくてSharpDevelop?とかExpressEditionがではじめたかも?というくらいでした。それを使ってチャットアプリケーションを作って同期にばらまいて、授業中にチャットでわからないところとか質問し合ってたのはいい思い出です。

研修が終わり配属されたのは全社の技術支援を行うような感じの部門。(ちなみに配属先希望の選択肢にはなかった) そこで待ち受けてたのは社内向けJava用Webアプリケーションの開発をすることになりました。

Spring Framework, Hibernateを使った感じのライブラリで、IDEがまさかのSun Java Studio Creator(現在はNetBeansに吸収されて消滅した感じ)。 渋い感じのチョイスだなと思ってました。

既存のDBのスキーマを読み取ってHibernate関連のファイルを自動生成する処理が気に入らなかったので、velocityというテンプレートエンジンを使うように作り替えたりしました。

割と好きにさせてもらえたので当時のリーダーの人には感謝してますし、当時の目標でもありました。途中でいなくなっちゃったけど。

あとは、プロジェクトで何かしら問題が起きたら手伝いに行くとかということをしてました。 DataTableの性能が出ない問題とか、サーバーサイドExcelオートメーションとか辛い問題もありましたが、性能改善とか設計レビューとかそいうのもやってました。あと技術相談とか。

3日のはずが…

そんなこんなで過ごしていたら「クラウドに興味のある人?」という問いが上司から来たので「はーい!」と手をあげたら3日間の教育にぶち込まれることが決まりました。しかも対象は幹部社員クラスの人たちらしい…。やだなぁと思い4連休へ突入したのでした。

4連休明けて会社に戻ってくると3日間の教育は別の人が割り当てられてました。 何があったのか聞いてみると、大田くんには2年間の教育に行ってもらうと言われて??????となりました。

そんなこんなで2年間のクラウドの教育をするという壮大な計画に巻き込まれてしまいました。 ただし、これはあくまで部署として推薦するだけで会社として1名選出する過程で別の部署の人を推すので大田くんがなることはないと言われたのを今でも覚えてます。その日の夕方「大田くんに決まったよ」と言われました。

2年間の本社勤務

ということで電車だけで1時間30分くらいかかる通勤生活が2年間決まりました。 富士通のクラウドの勉強や商談支援などをしてたのですが、当時富士通が富士通のデータセンターにAzureをホストしてたのもあって、それをやりたいやりたいオーラを出してたら、1年たった頃にチームがえがあってそちらに移してもらえました。 そして、さらに半年後なぜかチームリーダーに…。嫌だと言ったのに!!

ここでは、大企業のスピード感(遅い)というものを肌を持って感じました。関係者が増えれば増えるほど色々なしがらみができて意思決定や資料のレビューなどに時間がかかるんだなぁ大変なんだなぁと思いました。

でも、本当にすごい人もいるんだなというのもここで学びました。 マネジメントがきちんとできる人のもとでのチームの作業はとてもやりやすかったですし、Windows系をガチでやってる人スゲェ…というものや、ハードの世界もちょろっとのぞき見しました。振り返ってみるといい経験でした。

パッケージ製品の面倒をみる

出向も無事終わり、戻ってくると共通技術をみる部門は無くなって、その後継の部門に配属という感じになりました。 そこで待ち受けてたのはExcel方眼紙とのにらめっこ。

ちょっと、ここでやる気がマジでなくなって転職を考えたりもしましたが踏みとどまりました。

今と同じようなお仕事が始まる

その後、チーム移動をしてもらってドローンを見たり、UnityしたりAzureしたりして今に至ります。

ドローンは、ARDroneを使ってカメラ画像から地面に貼り付けた色付きガムテープを認識してその上を移動して端っこまで行くと折り返すというのを作ったりしてました。 100万円以上する馬鹿でかいディスプレイの前でやったのが怖かったです。緊急ホバリングボタンを割と押しまくってことなきを得た感じではありました。

最後の我儘

人権がない開発環境(メモリ8GB + HDD)でお仕事してたのですが、その開発環境のリース期限が切れるということで、どんなマシンがいい?と聞かれた時に駄目もとでSurface Bookがいいって言ったのですが、リースの係りの人がめっちゃ頑張ってくれて1月31日に納品されてしまいました。

普通は富士通製のしかダメなんだけどね…本当に頑張ってくれてありがとうございましたという感想しか出て来ません。

納品されたときには辞めるということを伝えていたので上司のもとに行ってしまいました。

PCのリースの切り替えと転職活動は丁度平行で進んでいて、落ちた場合に満足できる環境で仕事したいと思って言って見た我儘でしたが、本当に実現してしまうとは思ってませんでした。結果は転職してしまうことになってしまいました。

大きめのSIerのいいところ

何と言っても新入社員研修がちゃんとあるというのがいいですね。半年間。そのあとも仮配属という形をとっていて本配属まで色々な経験を積ませてもらえます。いきなり配属されると何十年も1つの部署しか知らないっていう人も多くなるので若いうちに色々経験させておこうという試みみたいです。

部署によると思いますが、私の場合は色々な経験を積ませてもらいました。 プロジェクト支援から、社内FWのメンテや、技術資料の整備、プロジェクト体験諸々です。

まぁ人によっては10年間同じ分野のプロジェクトにどっぷりという人もいるので、一概には言えないですが、私の場合は割と好きなことをさせてもらえたと思っています。ここら辺は、入る会社というよりも配属と上司がどんな人かという運が大きいと思います。

あと、教育も色々揃ってたりするので、その気になればいろんな教育を受けることもできますし、富士通向けセミナーとかいうのも大きな会社さんがやってくれるので、そういうところで技術のキャッチアップをすることもできます。まぁここら辺は、一般公開されてるイベントとかセミナーに積極的に参加するのでも構わないと思うんですが、社内で開催されているということで仕事として参加しやすいというのはあるかもしれませんね。

あと、本当に色々なことを会社全体で見たらやっているので、積極的に動いていれば多分いろんなことに出会える確率は高いのではないかと思います。

大きめのSIerのダメなところ

何でしょうね。動きは遅い気がします。 企画がなかなか通らなくて、実装にしわ寄せがきたりとかそういうめんどくさいことはありますね。

Microsoft MVP

日本マイクロソフトで働くことになるということで、Microsoft MVPも卒業することになります。(社員はMVPになれないので) Microsoft MVPも6年やってきてて、そろそろベテランとは行かないまでも、中堅どころなのかな?と思うようになってきてたので、丁度いい引き際なのかもしれません。

Microsoft MVPは、過去1年間のコミュニティ活動などを申請して、それを評価してもらって受かると1年間Microsoft MVPを名乗っていいという表彰制度です。あくまで過去1年間の活動に対する評価なので、MVPになったからと言って何か責任が発生したりするわけではありません。

当然、更新しようと思ったら、7月に申請して更新をしないといけないので、それなりのコミュニティ活動などをしないといけないというのはあります。

Microsoft MVPになって良かったのは、本を書く機会に恵まれたというところでしょうか。id:ch3cooh393 先生に、Windows 8のストアアプリの本を書かないかと誘われた時はうれしかったというのを覚えています。Windows store appの本の中では割と売れた本っぽいので満足満足。

https://www.amazon.co.jp/Windows8ストア-アプリ開発入門-大田-一希/dp/4798035440

あと、私は割とコミュ障なのでMVPだということで人に話しかけてもらえるのが割とありがたかったです。 そうでもないと、誰とも話さずに勉強会が終わるとかいうのもザラなので…。

Global Summit

Microsoft MVPの数ある特典の中で一番でかいのがこれです。

1年に1度、マイクロソフト本社でNDAセッションを3日間ぶっ通しで聴ける貴重な機会です。 まぁ全部英語なので、英語できない私にとっては80%くらい情報は素通りしてしまうのですが…。 英語できるようにならないとなぁ。

ちなみに、NDAなもんでMicrosoft MVPがGlobal Summitに行くとNDAじゃないご飯とかパーティのことばかり写真をあげたりツイートしたりするので、アメリカにパーティしに行ってるように見えるのは仕様です。

日本マイクロソフト

ということで、日本マイクロソフトで働くことになりました。 プレミアムフィールドエンジニアというところで働くことになります。 プレミアムサポートのお客様相手のお仕事になるらしいので、私を引っ張り出そうとするとプレミアムサポートを結んで、営業にお願いすればいいのかしら? よくわかんないですね。

まぁ中でいろんなことやって行くことになると思うので楽しみです。

最後に

今までお仕事一緒にしてくれた人達からは、学ぶことがたくさんあり未熟な大学院卒業したての新社会人を、ここまで育ててくれたことに感謝でいっぱいです。 これで、途切れることなく、何かしらで絡むことができたらいいなぁと思っています。

これからも、日々学ぶこと、そしてそれをアウトプットすることを目標に頑張って行きたいと思います。

ということで私の退職エントリはこれでおしまい。最後まで見てくれてありがとうございました!