Upgrade to Pro — share decks privately, control downloads, hide ads and more …

軽率にインターフェース使ってる? / Are you using the interface carelessly?

軽率にインターフェース使ってる? / Are you using the interface carelessly?

にー兄さん

August 06, 2022
Tweet

More Decks by にー兄さん

Other Decks in Programming

Transcript

  1. 発表者について にー兄さん 23歳・学生 基本武器はUnity C#とTypeScript(Node.js) 他C++, Zig, Rust, Java, Python,

    Ruby, VisualBasic, CoffeeScriptなど Unity 歴:趣味8年 / 実務2年半 C#歴  :6,7年(Unity JSで書いてる時期がある) 中長期インターンあわせて5社でUnityの実務コードを書いたことがあったり
  2. インターフェースの文法 interfaceというキーワードで 作成できる 実装するクラスの骨を”定義” - プロパティ - メソッド - イベント

    など定義可能 public interface IHoge { // プロパティの定義 int Foo { get; } // インスタンスメソッドの定義 void Bar(); // イベントの定義 event Action Boo; }
  3. 抽象クラスとの違い 抽象クラスを”継承”し、 抽象メソッドを”実装”する 抽象クラスには 具体的な実装も書ける オーバーライドもできる メンバの継承もできる 抽象クラスは 一つしか継承できない (C#の場合)

    public abstract class AbstractHoge { public abstract void Bar(); protected virtual void Foo() { Console.WriteLine("Foo"); } } public class Hoge2 : AbstractHoge { public override void Bar() { Console.WriteLine("bar"); } protected override void Foo() { base.Foo(); Console.WriteLine("overrided"); } }
  4. IEnumerable ”列挙できる”ことを保証 IEnumeratorと組み合わせて定義 する 有名な実装先は Array<T>やList<T> foreach文が使えるようになる IEnumerable<int> intEnumrable =

    new int[] { 1, 2, 3 }; IEnumerable<string> strEnumrable = new List<string>() { "a", "b", "c" }; foreach (var num in intEnumrable) { Console.WriteLine(num); } foreach (var str in strEnumrable) { Console.WriteLine(str); }
  5. IDisposable 必ず”破棄する”ことを定める Dispose()メソッドを 呼ぶようにプログラマに指示 メモリの解放処理や 入出力のクローズ処理、 デバイスの動作終了処理 を実装することが多い using文、using宣言が使える var

    buffer = new char[50]; using (var reader = new StreamReader("file1.txt")) { reader.Read(buffer, 0, buffer.Length); } var buffer = new char[50]; var reader = new StreamReader("file1.txt"); reader.Read(buffer, 0, buffer.Length); reader.Dispose(); OR https://docs.microsoft.com/ja-jp/dotnet/standard/garbage-collection/using-objects より引用
  6. ReactivePropertyとIReadOnlyReactiveProperty UniRxの主要な機能である ReactiveProperty 値が変更されたことを受けて 購読者に通知する機能がある これによりMV(R)Pという UIのためのアーキテクチャを構築 // Reactive Propertyの初期化

    var reactiveInt = new ReactiveProperty<int>(); // 変更されたら通知 reactiveInt.Subscrive(x => { Debug.Log(x); }); // Valueプロパティから値を変更 reactiveInt.Value = 1;
  7. ReactiveProperty<T>のコード(一部抜粋) public interface IReadOnlyReactiveProperty<T> : IObservable<T> { T Value {

    get; } bool HasValue { get; } } public interface IReactiveProperty<T> : IReadOnlyReactiveProperty<T> { new T Value { get; set; } } public class ReactiveProperty<T> : IReactiveProperty<T>, ... { public T Value { get { return value; } set { ... } } }
  8. getterのみ公開する ReactivePropertyを ReadOnlyとして公開できる 外部からは変更できないが 購読できる 不要な情報の隠蔽により 安全な実装ができた class A {

    private ReactiveProperty<int> _intReactiveProperty; public IReadOnlyReactiveProperty<int> ROIntReactiveProperty => _intReactiveProperty; private void Hoge() { _intReactiveProperty.Value = 10; } } class B { void Main() { var a = new A(); a.ROIntReactiveProperty.Value = 10; // エラー!!! } }
  9. 具体の差し替え 天気を取得するサービスの例 都市コードを入力したら その時の天気を返してくれるAPI 具体的にどうする? - A社の天気予報サービス? - B社の天気予報サービス? -

    オレオレ天気予報? public enum Weather { Sunny, Rainy, Cloudy } public interface IWeatherService { Task<Weather> TryGetWeatherAsync(string cityCode); }
  10. サンプルの一部 _movableや_serviceは抽象的 中身が何なのかわからない CarなのかBusなのか? A社の天気予報なのか? public class App { private

    readonly IMovable _movable; private readonly IWeatherService _service; public App(IMovable movable, IWeatherService service) { _movable = movable; _service = service; } public async Task RunAsync(string cityCode) { var weather = await _service.TryGetWeatherAsync(cityCode); switch (weather) { case Weather.Rainy: _movable.GoForward(); break; case Weather.Cloudy: _movable.GoForward(); break; case Weather.Sunny: default: _movable.GoBack(); break; } } }
  11. 処理の流れと依存方向は? new A(); class A { public A() { new

    B(); } } class B { public B() { new C(); } } class C { }
  12. 依存方向 A C B AがBに依存 BがCに依存 依存方向 A C B

    AがBに依存 CがICを実装 B名前空間に依存 IC BがICに依存
  13. 依存方向 A C B AがBに依存 BがCに依存 依存方向 A C B

    AがBに依存 CがICを実装 B名前空間に依存 IC BがICに依存 依存性逆転の原則 依存方向が逆転 している