Skip to content

Instantly share code, notes, and snippets.

View rinotc's full-sized avatar

Chiba Toshinori rinotc

View GitHub Profile
class ChangeEmailUseCase @Inject() (
userEmailUniqueChecker: UserEmailUniqueChecker,
userRepository: UserRepository
) {
import ChangeEmailOutput._
override def handle(input: ChangeEmailInput): ChangeEmailOutput = {
val result = for {
user <- userRepository.findById(input.userId).toRight(NotFoundUser(input.userId))
@rinotc
rinotc / DomainServiceCommonSample.scala
Last active March 12, 2023 14:46
よくあるドメインサービスの実装
trait UserEmailUniqueChecker extends DomainService {
/**
* 引数のメールアドレスがユニークであるかどうかを調べる
*/
def check(email: EmailAddress): Boolean
}
final class User private (
val id: UserId,
@rinotc
rinotc / rust-self-memo.rs
Last active December 24, 2022 02:34
Rustの self, &self, &mut self に関するメモ
fn main() {
let mut rect = Rectangle {
width: 10,
height: 15,
};
println!("rectangle area is: {}", rect.area());
// let mut で宣言されたものでないと呼び出せない。
rect.set_width(20);
// rect の内部状態が代わり、rect.widthが20になっているので、結果は300になる
println!("rectangle area is: {}", rect.area());
@rinotc
rinotc / english-name.ts
Created May 21, 2022 01:30
typescriptで値オブジェクト書いてみたサンプル
import {PreferNominal} from "../../prefer-nominal";
import * as E from "fp-ts/Either";
export class EnglishName {
// noinspection JSUnusedGlobalSymbols
readonly _englishNameBrand: PreferNominal;
constructor(readonly value: string) {
if (!EnglishName.isValid(value)) {
throw new TypeError(this.requirementErrorMessage);
package sample2
import usecase.create.CreateUserOutput.UserNameConflict
import usecase.create.{CreateUserInput, CreateUserOutput, CreateUserUseCase}
class CreateUserInteractor(
userNameConflictValidator: UserNameConflictValidator,
userRepository: UserRepository
) extends CreateUserUseCase {
package sample2
import user.{UserId, UserName, UserNameDuplicateError}
/**
* ユーザー
*
* @note デフォルトコンストラクタは `private` にして生成処理を絞っている。
* ADTを利用した状態遷移はインスタンスの生成方法の制御が重要である。
* 型パラメータを自由につけてインスタンスを生成できては、制約の効果がないためだ。
class Person private (val firstName: String, val lastName: String, val age: Int)
object Person {
class Builder {
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
private var hasFirstName: Boolean = false
private var hasLastName: Boolean = false
@rinotc
rinotc / precondition-adt-sample_first_CreateUserInteractor.scala
Created May 20, 2022 12:41
ドメインサービスでバリデーション入れた場合のサンプル
package first
import first.usecase.{CreateUserInput, CreateUserOutput, CreateUserUseCase}
final class CreateUserInteractor(userService: UserService, userRepository: UserRepository) extends CreateUserUseCase {
override def handle(input: CreateUserInput): CreateUserOutput = {
val newUser = User.create(input.name)
userService.exists(newUser) match { // このバリデーションが必ず必要だが、知らないとできない。
package com.github.rinotc.purchaseSample.models.purchase
import com.github.rinotc.purchaseSample.models.money.Money
import com.github.rinotc.purchaseSample.models.part.Part
import com.github.rinotc.purchaseSample.models.{Aggregate, Entity}
import java.util.Currency
/**
* 購入注文
@rinotc
rinotc / TypeSafeBuilderSample.scala
Last active May 20, 2022 00:06
Generalized type constrains を使ったtype-safe builder
class Person(
val firstName: String,
val lastName: String,
val age: Int
) {
protected def this() = this("", "", 0)
protected def this(pb: Person.Builder[_]) = this(pb.firstName, pb.lastName, pb.age)
}
object Person {