Work
http://grani.jp/
C#
Unity
Private
http://neue.cc/
@neuecc
https://github.com/neuecc/UniRx
神獄のヴァルハラゲート
モンスターハンターロアオブカード
Choice of Technology
using
Windows
WinForms, WPF
Mac
Xamarin.Mac
Windows Tablet
Windows Store Application
Web Application
ASP.NET MVC, OWIN
Cloud
Microsoft Azure, AWS, GCP(Google)
C# Everywhere
Game
Unity, Paradox, Unreal Engine
Mobile
Xamarin.iOS
Xamarin.Android
Windows Phone 8 SDK
Embedded
Windows Embedded
.NET Micro Framework
NUI
Kinect, LeapMotion
C#を選ぶ理由
WebからMobileへ
Grani Framework
あるのは文化
言語が思考を規定する
あるのは文化
言語が思考を規定する
共通ライブラリはプロジェクト参照で
ボトルネックはすぐに発見できるように
Grani.CoreLib
ヒュージモノリシックライブラリ
あくまでライブラリ
ただの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()); // 第一引数(型名)以外を渡す
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 });
}
MicroORMは手書きSQL
基本クエリの自動生成
MicroORMは手書きSQL
基本クエリの自動生成
通信の記録の徹底
MySQL
Redis
HTTP
EnumerableExtensions
Grani.CoreLib.vNext
非依存性ほげもげ
Grani.Data.MySql
Dapper
MySql.Data
Grani.Data.Redis
CloudStructures
StackExchange.Redis
Jil
LZ4 for .NET
Grani.Diagnostics
JSON.NET
Semantic Logging Application Block
.NET Library choice in 2015
Grani.Glimpse
Glimpse
Grani.Owin
Owin
LightNode
Jil
JSON.NET
Grani.Unity
UniRx
LINQ to GameObject
WebSocketSharp
JSON.NET
log4net / NLogからの脱却
Structured Log
Stream Logging
Out of Process
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);
}
}
Semantic Logging Application Block(SLAB)
https://github.com/mspnp/semantic-logging
IObservable<EventEntry>
EventSource(ASP.NET)
Event Tracing for
Windows(ETW)
SLAB Service
SLABの外部プロセスサービス
Google BigQuery最強
LINQ to BigQueryあります
https://github.com/neuecc/LINQ-to-BigQuery
Glimpse最強
http://getglimpse.com/
http://neue.cc/2015/02/16_505.html
新規ユーザー登録をする、とする
カスタムプラグインでDB周りを更に可視化
アプリケーションに沿った情報を出す
StackExchange.Redis + CloudStructures
https://github.com/neuecc/CloudStructures
Redisに「何」を入れるか
UseOwin
UseLightNode
https://github.com/neuecc/LightNode/
API専用Microフレームワークの不在
https://github.com/intridea/grape
ASP.NET Web API
俺々フレームワーク is Evil...?
// 開発環境用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"),
});
});
// それ以外は全部404
app.MapWhen(x => !x.Request.Path.Value.StartsWith("/Glimpse.axd", StringComparison.InvariantCultureIgnoreCase), builder =>
{
builder.Run(ctx =>
{
ctx.Response.StatusCode = 404;
return Grani.Threading.TaskEx.Empty;
});
});
}
}
<?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" />
<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>
UniRx - Reactive Extensions for Unity
https://github.com/neuecc/UniRx
uGUI.Ext(仮)
Unity + Rxに適したUIパターンの模索
Passive View
Presenter
(Supervising Controller)
Model
updates view
state-change
events
user events
update model
UIControl.XxxAsObservable
UnityEvent.AsObservable
ObservableEventTrigger
Subscribe
ToReactiveProperty
ReactiveProperty
Subscribe
SubscribeToText
SubscribeToInteractable
Conclusion
派手なことはない
手を入れるべきところは大胆に
A Framework for LightUp Applications of Grani

A Framework for LightUp Applications of Grani