A Framework for LightUp Applications of Grani

45

Transcript of A Framework for LightUp Applications of Grani

Page 1: A Framework for LightUp Applications of Grani
Page 2: A Framework for LightUp Applications of Grani

Work

http://grani.jp/

C#

Unity

Private

http://neue.cc/

@neuecc

https://github.com/neuecc/UniRx

Page 3: A Framework for LightUp Applications of Grani

神獄のヴァルハラゲート

モンスターハンターロアオブカード

Page 4: A Framework for LightUp Applications of Grani
Page 5: A Framework for LightUp Applications of Grani

Choice of Technology

Page 6: A Framework for LightUp Applications of Grani

using

Page 7: A Framework for LightUp Applications of Grani

WindowsWinForms, WPF

MacXamarin.Mac

Windows TabletWindows Store Application

Web ApplicationASP.NET MVC, OWIN

CloudMicrosoft Azure, AWS, GCP(Google)

C# Everywhere

GameUnity, Paradox, Unreal Engine

MobileXamarin.iOS

Xamarin.Android

Windows Phone 8 SDK

EmbeddedWindows Embedded

.NET Micro Framework

NUIKinect, LeapMotion

Page 8: A Framework for LightUp Applications of Grani

C#を選ぶ理由

WebからMobileへ

Page 9: A Framework for LightUp Applications of Grani

Grani Framework

Page 10: A Framework for LightUp Applications of Grani

あるのは文化

言語が思考を規定する

Page 11: A Framework for LightUp Applications of Grani

あるのは文化

言語が思考を規定する

Page 12: A Framework for LightUp Applications of Grani

共通ライブラリはプロジェクト参照で

ボトルネックはすぐに発見できるように

Page 13: A Framework for LightUp Applications of Grani

Grani.CoreLib

Page 14: A Framework for LightUp Applications of Grani

ヒュージモノリシックライブラリ

あくまでライブラリ

Page 15: A Framework for LightUp Applications of Grani

ただのConsoleApplicationランナー

/// <summary>/// 各バッチはこれを継承する、というマーカー的なもの/// </summary>public interface IBatchExecutor{

void Execute(string[] args);}

// 引数にクラス名渡してもらって、それ実行するだけ// コア部分はこれだけ。その前後に起動/終了の通知や多重実行禁止、実行時間計測がある程度var targetClass = args[0];var type = Assembly.GetCallingAssembly().GetType(targetClass, throwOnError: true);var batch = (IBatchExecutor)Activator.CreateInstance(type);batch.Execute(args.Skip(1).ToArray()); // 第一引数(型名)以外を渡す

Page 16: A Framework for LightUp Applications of Grani

TypedConnection

http://neue.cc/2013/08/06_423.html

public interface ITypedConnection : IDisposable{

DbConnection Slave { get; }DbConnection Master { get; }

}

public BattleEntity SelectById(BattleConnection battle, int id){

return battle.Master.Query<BattleEntity>("select * from battle where id = @id", new { id });}

public UserEntity SelectById(UserInfoConnection user, int id){

return user.Master.Query<UserEntity>("select * from user where id = @id", new { id });}

Page 17: A Framework for LightUp Applications of Grani

MicroORMは手書きSQL

基本クエリの自動生成

Page 18: A Framework for LightUp Applications of Grani

MicroORMは手書きSQL

基本クエリの自動生成

Page 19: A Framework for LightUp Applications of Grani

通信の記録の徹底

MySQL

Redis

HTTP

Page 20: A Framework for LightUp Applications of Grani

EnumerableExtensions

Page 21: A Framework for LightUp Applications of Grani

Grani.CoreLib.vNext

Page 22: A Framework for LightUp Applications of Grani

非依存性ほげもげ

Page 23: A Framework for LightUp Applications of Grani

Grani.Data.MySqlDapper

MySql.Data

Grani.Data.RedisCloudStructures

StackExchange.Redis

Jil

LZ4 for .NET

Grani.DiagnosticsJSON.NET

Semantic Logging Application Block

.NET Library choice in 2015

Grani.GlimpseGlimpse

Grani.OwinOwin

LightNode

Jil

JSON.NET

Grani.UnityUniRx

LINQ to GameObject

WebSocketSharp

JSON.NET

Page 24: A Framework for LightUp Applications of Grani

log4net / NLogからの脱却

Structured Log

Stream Logging

Out of Process

Page 25: A Framework for LightUp Applications of Grani

System.Diagnostics.Tracing.EventSource

[EventSource(Name = "Grani")]public sealed class GraniEventSource : EventSource{

public static readonly GraniEventSource Log = new GraniEventSource();

// 中略

/// <summary>HttpClientで引っ掛けた全外部Httpアクセスを記録します</summary>[Event(1030, Level = EventLevel.Verbose, Keywords = Keywords.Diagnostics)]public void Http(string method, string path, string parameter, int statusCode, double duration){

WriteEvent(1030, method ?? "", path ?? "", parameter ?? "", statusCode, duration);}

}

Page 26: A Framework for LightUp Applications of Grani

Semantic Logging Application Block(SLAB)https://github.com/mspnp/semantic-logging

IObservable<EventEntry>

Page 27: A Framework for LightUp Applications of Grani

EventSource(ASP.NET)Event Tracing for

Windows(ETW)SLAB Service

SLABの外部プロセスサービス

Page 28: A Framework for LightUp Applications of Grani

Google BigQuery最強

LINQ to BigQueryありますhttps://github.com/neuecc/LINQ-to-BigQuery

Page 29: A Framework for LightUp Applications of Grani

Glimpse最強

http://getglimpse.com/

http://neue.cc/2015/02/16_505.html

Page 30: A Framework for LightUp Applications of Grani

新規ユーザー登録をする、とする

Page 31: A Framework for LightUp Applications of Grani

カスタムプラグインでDB周りを更に可視化

Page 32: A Framework for LightUp Applications of Grani

アプリケーションに沿った情報を出す

Page 33: A Framework for LightUp Applications of Grani

StackExchange.Redis + CloudStructureshttps://github.com/neuecc/CloudStructures

Page 34: A Framework for LightUp Applications of Grani

Redisに「何」を入れるか

Page 35: A Framework for LightUp Applications of Grani

UseOwin

UseLightNode

https://github.com/neuecc/LightNode/

Page 36: A Framework for LightUp Applications of Grani

API専用Microフレームワークの不在

https://github.com/intridea/grape

ASP.NET Web API

Page 37: A Framework for LightUp Applications of Grani

俺々フレームワーク is Evil...?

Page 38: A Framework for LightUp Applications of Grani

// 開発環境用Startup(本番では使わないミドルウェア/設定込み)public class Startup{

public void Configuration(IAppBuilder app){

app = new ProfilingAppBuilder(app); // 内製Glimpse表示用AppBuilderラッパー(Middlewareトラッカー)app.EnableGlimpse(); // Glimpse.LightNdoe同梱ユーティリティapp.Use<GlobalLoggingMiddleware>(); // 内製ロギングミドルウェアapp.Use<ShowErrorMiddleware>(); // 内製例外時表示ミドルウェア

app.Map("/api", builder =>{

var option = new LightNodeOptions(AcceptVerbs.Get | AcceptVerbs.Post,new LightNode.Formatter.Jil.JilContentFormatter(),new LightNode.Formatter.Jil.GZipJilContentFormatter())

{OperationCoordinatorFactory = new GlimpseProfilingOperationCoordinatorFactory(),ErrorHandlingPolicy = ErrorHandlingPolicy.ThrowException,OperationMissingHandlingPolicy = OperationMissingHandlingPolicy.ThrowException,

};

builder.UseLightNode(option);});// Indexはデバッグ画面に回すapp.MapWhen(x => x.Request.Path.Value == "/" || x.Request.Path.Value.StartsWith("/DebugMenu"), builder =>{

builder.UseFileServer(new FileServerOptions(){

EnableDefaultFiles = true,EnableDirectoryBrowsing = false,FileSystem = new PhysicalFileSystem(@".¥DebugMenu"),

});});// それ以外は全部404app.MapWhen(x => !x.Request.Path.Value.StartsWith("/Glimpse.axd", StringComparison.InvariantCultureIgnoreCase), builder =>{

builder.Run(ctx =>{

ctx.Response.StatusCode = 404;return Grani.Threading.TaskEx.Empty;

});});

}}

Page 39: A Framework for LightUp Applications of Grani

<?xml version="1.0" encoding="utf-8"?>

<!-- OWIN向けウェブコン --><!-- Glimpse系のはリリース時にはxsltでまるっと消す --><configuration>

<configSections><section name="glimpse" type="Glimpse.Core.Configuration.Section, Glimpse.Core" />

</configSections><connectionStrings configSource="<!-- 接続文字列は外部に回す(DebugとReleaseでxsltで変換して別参照見るように) -->" /><appSettings>

<!-- なんかここに書いたり外部ファイルとmergeしたり:) --></appSettings><system.web>

<!-- system.web配下のは片っ端から消してしまう --><httpModules>

<clear /><add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" />

</httpModules><httpHandlers>

<clear /><add path="glimpse.axd" verb="GET" type="Glimpse.AspNet.HttpHandler, Glimpse.AspNet" />

</httpHandlers><roleManager>

<providers><clear />

</providers></roleManager><customErrors mode="Off" /><trace enabled="false" /><sessionState mode="Off" /><httpRuntime targetFramework="4.5" requestPathInvalidCharacters="" /><globalization culture="ja-jp" uiCulture="ja-jp" /><!-- リリース時にxsltでfalseにする --><compilation debug="true" />

</system.web><system.webServer>

<validation validateIntegratedModeConfiguration="false" /><globalModules>

<clear /></globalModules><modules>

<!-- モジュールも全消し --><remove name="OutputCache" /><remove name="Session" /><remove name="UrlRoutingModule-4.0" />

Page 40: A Framework for LightUp Applications of Grani

<globalModules><clear />

</globalModules><modules>

<!-- モジュールも全消し --><remove name="OutputCache" /><remove name="Session" /><remove name="UrlRoutingModule-4.0" /><!-- 以下デフォで読まれるモジュール名が延々と続く(system.webServer下は一括clearが使えなくて辛い)... --><add name="Glimpse" type="Glimpse.AspNet.HttpModule, Glimpse.AspNet" preCondition="integratedMode" />

</modules><handlers>

<add name="Glimpse" path="glimpse.axd" verb="GET" type="Glimpse.AspNet.HttpHandler, Glimpse.AspNet" preCondition="integratedMode" /></handlers>

</system.webServer><!-- おまじない(笑)セクション --><system.net>

<connectionManagement><add address="*" maxconnection="1024" />

</connectionManagement><settings>

<servicePointManager expect100Continue="false" useNagleAlgorithm="false" /></settings>

</system.net><!-- WebServiceでやるならPersistResultsで(当然このセクションもリリースでは消す) --><glimpse defaultRuntimePolicy="PersistResults" endpointBaseUri="~/Glimpse.axd">

<tabs><ignoredTypes>

<add type="Glimpse.AspNet.Tab.Cache, Glimpse.AspNet" /><add type="Glimpse.AspNet.Tab.Routes, Glimpse.AspNet" /><add type="Glimpse.AspNet.Tab.Session, Glimpse.AspNet" /><add type="Glimpse.Core.Tab.Trace, Glimpse.Core" />

</ignoredTypes></tabs><runtimePolicies>

<ignoredTypes><add type="Glimpse.Core.Policy.ControlCookiePolicy, Glimpse.Core" /><add type="Glimpse.Core.Policy.StatusCodePolicy, Glimpse.Core" /><add type="Glimpse.Core.Policy.AjaxPolicy, Glimpse.Core" /><add type="Glimpse.AspNet.Policy.LocalPolicy, Glimpse.AspNet" /><add type="Glimpse.Core.Tab.Trace, Glimpse.Core" />

</ignoredTypes></runtimePolicies>

</glimpse></configuration>

Page 41: A Framework for LightUp Applications of Grani

UniRx - Reactive Extensions for Unityhttps://github.com/neuecc/UniRx

uGUI.Ext(仮)

Page 42: A Framework for LightUp Applications of Grani

Unity + Rxに適したUIパターンの模索

Passive View

Presenter(Supervising Controller)

Model

updates view

state-change

events

user events

update model

UIControl.XxxAsObservable

UnityEvent.AsObservable

ObservableEventTrigger

Subscribe

ToReactivePropertyReactiveProperty

Subscribe

SubscribeToText

SubscribeToInteractable

Page 43: A Framework for LightUp Applications of Grani

Conclusion

Page 44: A Framework for LightUp Applications of Grani

派手なことはない

手を入れるべきところは大胆に

Page 45: A Framework for LightUp Applications of Grani