梅雨明けまだかなと思いながらプログラムをどう効率的に組んでいこうかを考えてた

梅雨っていつ明けるんですかね?気圧に連動して体調悪くなるから早く明けてほしいのだけど明けそうで明けない。ただ、日曜は晴れて今朝も晴れていたので昨日に引き続いて早朝に長男と自転車に乗る練習をしたのだが、昨日よりもスムーズに乗れていたので子供の成長に素直に驚いた。
子供がどんどん成長してくれてとても喜ばしいのだが一点悩みがある。それは子供の自転車を駐輪する場所が我が家にはなく玄関に入れて雨風を凌いでいることだ。これにより毎回子供の自転車を親が持って出し入れしないといけないのだが、子供用とはいえ16インチの自転車を出し入れするのは流石に辛い。なので、早く木工の知識をつけて自転車小屋を作りたいなぁと思っている。ただ、その前に工具を買って始めなければいけないのだが、まだ始められていないのでどうにかして工具を揃えてこのコロナ禍の間にスキルを磨きたいところだ。
さて、今週は木曜日から祝日続きで4連休になるため3営業日しか仕事ができず中々切羽詰まっている状況なのだが、効率的に仕事をするために息抜きにプログラムの効率的な実装方法を考えていた。まぁ、考えたと言っても前提としてオブジェクト指向言語に限るという条件があるのだが、自分のやっている仕事上、オブジェクト指向言語しか使わないので問題ないだろう。
やったことは以下の3つ
- Interfaceを定義する
- メソッドを実装したもの(基本的に呼び出し先のInterfaceを使って処理を実装する)
- 呼び出されるプログラムに沿ってDIした実態を実装する
とまぁ当たり前なことなのだが、ちょっと例を自分へのメモとして下に書いておく
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
/** * 外部リソースアクセス用クラスを格納するための格納クラス */ trait EntityIOContext /** * ScalaCSV用の格納クラス */ class EntityIOContextForScalaCSV(reader: CSVReader.type, writer: CSVWriter.type) extends EntityIOContext /** * ScalikeJDBC用の格納クラス */ class EntityIOContextForJDBC(session: DBSession) extends EntityIOContext /** * サンプルのドメインサービス */ trait SampleDataService { def readData(path: String)(implicit ctx: EntityIOContext): Try[SampleData] def storeData(data: SampleData)(implicit ctx: EntityIOContext): Try[SampleDataId] } /** * DI用コンテナ */ trait UsesSampleDataService { def sampleDataService: SampleDataService } /** * ユースケースで使用するインプットデータ */ case class ImportSampleDataInputData(path: String) /** * ユースケースで使用するアウトプットデータ */ case class ImportSampleDataOutputData(sampleDataId: SampleDataId) /** * SampleDataインポート用Presenter */ trait ImportSampleDataPresenter { def complete(outputData: ImportSampleDataOutputData): Unit } /** * DIコンテナ */ trait UsesImportSampleDataPresenter { def importSampleDataPresenter: ImportSampleDataPresenter } /** * SampleDataインポート用ユースケース */ trait ImportSampleDataUseCase { def handler(input: SampleInputData)(implicit ctxForScalaCsv: EntityIOContextForScalaCsv, ctxForJDBC: EntityIOContextForJDBC): Unit } /** * インタラクタ */ trait ImportSampleDataInteractor extends UsesSampleDataService with UsesImportSampleDataPresenter { override def handler(input: SampleInputData)(implicit ctxForScalaCsv: EntityIOContextForScalaCsv, ctxForJDBC: EntityIOContextForJDBC): Unit = for { sampleData <- sampleDataService.readData(input.path)(ctxForScalaCsv) sampleDataId <- sampleDataService.sampleDataService(sampleData)(ctxForJDBC) } yield importSampleDataPresenter(SampleDataOutputData(sampleDataId)) } |
というこの前書いたサンプルがあったとき、実際にプログラムで利用するための実装は以下のようになる。
1 2 3 4 5 6 7 8 9 10 11 |
/** * 実装したインタラクタに依存性を注入したもの */ trait UsesImportSampleDataInteractorForSampleProgram { def importSampleDataInteractor: ImportSampleDataInteractor = ImportSampleDataInteractorForSampleProgram object ImportSampleDataInteractorForSampleProgram extends ImportSampleDataInteractor with UsesSampleDataServiceForSampleProgram // このサンプルには書いていないが別なところでプログラムようにDIしたService with UsesImportSampleDataPresenterForSampleProgram // このサンプルには書いていないが別なところでプログラムようにDIしたPresenter } |
これなら呼び出す方を気にしなくても実装ができるしテストも実装しやすいから良いと思うけど、如何せん作るものが多すぎて吐き気がするのが効率化を図たいなぁ・・・。とりあえず眠いから今日は寝るか。