ã»ãšãã©ãã¹ãŠã®ææ°ã®ãœãããŠã§ã¢è£œåã¯ãè€æ°ã®ãµãŒãã¹ã§æ§æãããŠããŸãã å€ãã®å ŽåããµãŒãã¹éãã£ãã«ã®é·ãå¿çæéã¯ããã©ãŒãã³ã¹ã®åé¡ã®åå ã«ãªããŸãã ãã®çš®ã®åé¡ã«å¯Ÿããæšæºçãªè§£æ±ºçã¯ãè€æ°ã®ãµãŒãã¹éãªã¯ãšã¹ãã XNUMX ã€ã®ããã±ãŒãžã«ããã¯ããããšã§ãããããã¯ãããåŠçãšåŒã°ããŸãã
ãããåŠçã䜿çšããå Žåãããã©ãŒãã³ã¹ãã³ãŒãã®æçãã®ç¹ã§çµæã«æºè¶³ã§ããªãå ŽåããããŸãã ãã®æ¹æ³ã¯ãåŒã³åºãåŽã«ãšã£ãŠã¯æã£ãã»ã©ç°¡åã§ã¯ãããŸããã ç®çãç¶æ³ãç°ãªãã°ããœãªã¥ãŒã·ã§ã³ã¯å€§ããç°ãªããŸãã å
·äœçãªäŸã䜿çšããŠãããã€ãã®ã¢ãããŒãã®é·æãšçæã瀺ããŸãã
å®èšŒãããžã§ã¯ã
ããããããããããã«ãçŸåšåãçµãã§ããã¢ããªã±ãŒã·ã§ã³ã®ãµãŒãã¹ã® XNUMX ã€ã®äŸãèŠãŠã¿ãŸãããã
ãã©ãããã©ãŒã éžå®äŸã®èª¬æããã©ãŒãã³ã¹ã®äœäžã®åé¡ã¯éåžžã«äžè¬çãªãã®ã§ãããç¹å®ã®èšèªããã©ãããã©ãŒã ã«ã¯åœ±é¿ããŸããã ãã®èšäºã§ã¯ãSpring + Kotlin ã®ã³ãŒãäŸã䜿çšããŠåé¡ãšè§£æ±ºçã瀺ããŸãã Kotlin ã¯ãJava éçºè
ãš C# éçºè
ã«ãšã£ãŠãåæ§ã«ç解ã§ããŸã (ãŸãã¯ç解ã§ããŸãã)ãããã«ãã³ãŒã㯠Java ãããã³ã³ãã¯ãã§ç解ããããã§ãã çŽç²ãª Java éçºè
ã«ãšã£ãŠç解ããããããã«ãKotlin ã®é»éè¡ãé¿ãã(Lombok ã®ç²Ÿç¥ã«åŸã£ãŠ) çœéè¡ã®ã¿ã䜿çšããŸãã æ¡åŒµã¡ãœããã¯ããã€ããããŸãããå®éã«ã¯éçã¡ãœãããšã㊠Java ããã°ã©ããŒã«ã¯éŠŽæã¿ã®ãããã®ãªã®ã§ãæçã®å³ãæãªããªãçšåºŠã®ç ç³ã«ãªããŸãã
æžé¡æ¿èªãµãŒãã¹ãããããŸãã 誰ããææžãäœæããŠè°è«ã®ããã«æåºãããã®éã«ç·šéãè¡ãããæçµçã«ææžãåæãããŸãã æ¿èªãµãŒãã¹èªäœã¯ããã¥ã¡ã³ãã«ã€ããŠã¯äœãç¥ããŸãããããã¯ãããã§ã¯èæ
®ããªãå°ããªè¿œå æ©èœãåããæ¿èªè
ã®ãã£ããã«ãããŸããã
ãããã£ãŠããã£ãã ã«ãŒã (ããã¥ã¡ã³ãã«çžåœ) ããããããããã®åå è ãäºåã«å®çŸ©ãããŠããŸãã éåžžã®ãã£ãããšåæ§ãã¡ãã»ãŒãžã«ã¯ããã¹ããšãã¡ã€ã«ãå«ãŸããŠãããè¿ä¿¡ãŸãã¯è»¢éããããšãã§ããŸãã
data class ChatMessage(
// nullable Ñак как пПÑвлÑеÑÑÑ ÑПлÑкП пПÑле persist
val id: Long? = null,
/** СÑÑлка Ма авÑПÑа */
val author: UserReference,
/** СППбÑеМОе */
val message: String,
/** СÑÑлкО Ма аÑÑаÑО */
// Оз-за ПÑПбеММПÑÑей ÑвÑзкО JPA+СУÐРпÑПÑе пПЎЎеÑжОваÑÑ Ðž null, О пÑÑÑÑе ÑпОÑкО
val files: List<FileReference>? = null,
/** ÐÑлО ÑвлÑеÑÑÑ ÐŸÑвеÑПЌ, ÑП зЎеÑÑ Ð±ÑÐŽÐµÑ ÐŸÑОгОМал */
val replyTo: ChatMessage? = null,
/** ÐÑлО ÑвлÑеÑÑÑ Ð¿ÐµÑеÑÑлкПй, ÑП зЎеÑÑ Ð±ÑÐŽÐµÑ ÐŸÑОгОМал */
val forwardFrom: ChatMessage? = null
)
ãã¡ã€ã«ãšãŠãŒã¶ãŒã®ãªã³ã¯ã¯ãä»ã®ãã¡ã€ã³ãžã®ãªã³ã¯ã§ãã ããã§ã¯ç§ãã¡ã¯æ¬¡ã®ããã«æ®ãããŠããŸãã
typealias FileReference = Long
typealias UserReference = Long
ãŠãŒã¶ãŒããŒã¿ã¯Keycloakã«ä¿åãããRESTçµç±ã§ååŸãããŸãã ãã¡ã€ã«ã«ã€ããŠãåæ§ã§ãããã¡ã€ã«ãšãã®ã¡ã¿æ
å ±ã¯ãå¥ã®ãã¡ã€ã« ã¹ãã¬ãŒãž ãµãŒãã¹ã«ååšããŸãã
ãããã®ãµãŒãã¹ãžã®ãã¹ãŠã®åŒã³åºãã¯ã éããªã¯ãšã¹ãã ããã¯ããããã®ãªã¯ãšã¹ãã®è»¢éã«ããããªãŒããŒããããããµãŒãããŒã㣠ãµãŒãã¹ã«ãããªã¯ãšã¹ãã®åŠçã«ãããæéãããã¯ããã«å€§ããããšãæå³ããŸãã ç§ãã¡ã®ãã¹ããã³ãã§ã¯ããã®ãããªãµãŒãã¹ã®äžè¬çãªåŒã³åºãæé㯠100 ããªç§ã§ãããããå°æ¥çã«ã¯ãããã®æ°å€ã䜿çšããäºå®ã§ãã
å¿ èŠãªæ å ±ããã¹ãŠå«ãæåŸã® N ã¡ãã»ãŒãžãåä¿¡ããããã®åçŽãª REST ã³ã³ãããŒã©ãŒãäœæããå¿ èŠããããŸãã ã€ãŸããããã³ããšã³ãã®ã¡ãã»ãŒãž ã¢ãã«ã¯ã»ãŒåãã§ããããã¹ãŠã®ããŒã¿ãéä¿¡ããå¿ èŠããããšèããããŸãã ããã³ããšã³ã ã¢ãã«ã®éãã¯ããã¡ã€ã«ãšãŠãŒã¶ãŒããªã³ã¯ãããããã«ããããã«åŸ©å·åããã圢åŒã§æ瀺ããå¿ èŠãããããšã§ãã
/** Ð ÑакПЌ вОЎе ПÑЎаÑÑÑÑ ÑÑÑлкО Ма ÑÑÑМПÑÑО ÐŽÐ»Ñ ÑÑПМÑа */
data class ReferenceUI(
/** ÐЎеМÑОÑОкаÑÐŸÑ ÐŽÐ»Ñ url */
val ref: String,
/** ÐОЎОЌПе пПлÑзПваÑÐµÐ»Ñ ÐœÐ°Ð·Ð²Ð°ÐœÐžÐµ ÑÑÑлкО */
val name: String
)
data class ChatMessageUI(
val id: Long,
/** СÑÑлка Ма авÑПÑа */
val author: ReferenceUI,
/** СППбÑеМОе */
val message: String,
/** СÑÑлкО Ма аÑÑаÑО */
val files: List<ReferenceUI>,
/** ÐÑлО ÑвлÑÑÑÑ ÐŸÑвеÑПЌ, ÑП зЎеÑÑ Ð±ÑÐŽÐµÑ ÐŸÑОгОМал */
val replyTo: ChatMessageUI? = null,
/** ÐÑлО ÑвлÑÑÑÑ Ð¿ÐµÑеÑÑлкПй, ÑП зЎеÑÑ Ð±ÑÐŽÐµÑ ÐŸÑОгОМал */
val forwardFrom: ChatMessageUI? = null
)
以äžãå®è£ ããå¿ èŠããããŸãã
interface ChatRestApi {
fun getLast(n: Int): List<ChatMessageUI>
}
UI æ¥å°Ÿèªã¯ãããã³ããšã³ãã® DTO ã¢ãã«ãã€ãŸã REST çµç±ã§æäŸãã¹ããã®ãæå³ããŸãã
ããã§é©ãã¹ãããšã¯ããã£ãã ID ãæž¡ããŠããããChatMessage/ChatMessageUI ã¢ãã«ã§ãããã£ãã ID ãæããªãããšã§ãã ãµã³ãã«ã®ã³ãŒããä¹±éã«ãªããªãããã«ãããã¯æå³çã«è¡ããŸãã (ãã£ããã¯åé¢ãããŠããããããã£ãã㯠XNUMX ã€ã ãã§ãããšæ³å®ã§ããŸã)ã
å²åŠçãªäœè«ChatMessageUI ã¯ã©ã¹ãš ChatRestApi.getLast ã¡ãœããã¯ã©ã¡ãããå®éã«ã¯é åºä»ã Set ã§ããå Žåã« List ããŒã¿åã䜿çšããŸãã ãã㯠JDK ã§ã¯åé¡ããããããã€ã³ã¿ãŒãã§ã€ã¹ ã¬ãã«ã§èŠçŽ ã®é åºã宣èšãã (è¿œå ããã³åé€ãããšãã«é åºãç¶æãã) ããšã¯æ©èœããŸããã ãã®ãããé åºä»ãããã Set ãå¿
èŠãªå Žåã«ã¯ List ã䜿çšããããšãäžè¬çã«ãªã£ãŠããŸã (LinkedHashSet ããããŸãããããã¯ã€ã³ã¿ãŒãã§ã€ã¹ã§ã¯ãããŸãã)ã
éèŠãªå¶é: é·ãè¿ä¿¡ã転éã®é£éã¯ãªããšä»®å®ããŸãã ã€ãŸããã¡ãã»ãŒãžã¯ååšããŸããããã®é·ã㯠XNUMX ã¡ãã»ãŒãžãè¶
ããŸããã ã¡ãã»ãŒãžã®ãã§ãŒã³å
šäœãããã³ããšã³ãã«éä¿¡ããå¿
èŠããããŸãã
å€éšãµãŒãã¹ããããŒã¿ãåä¿¡ããã«ã¯ã次㮠API ããããŸãã
interface ChatMessageRepository {
fun findLast(n: Int): List<ChatMessage>
}
data class FileHeadRemote(
val id: FileReference,
val name: String
)
interface FileRemoteApi {
fun getHeadById(id: FileReference): FileHeadRemote
fun getHeadsByIds(id: Set<FileReference>): Set<FileHeadRemote>
fun getHeadsByIds(id: List<FileReference>): List<FileHeadRemote>
fun getHeadsByChat(): List<FileHeadRemote>
}
data class UserRemote(
val id: UserReference,
val name: String
)
interface UserRemoteApi {
fun getUserById(id: UserReference): UserRemote
fun getUsersByIds(id: Set<UserReference>): Set<UserRemote>
fun getUsersByIds(id: List<UserReference>): List<UserRemote>
}
å€éšãµãŒãã¹ã¯æåã¯ãããåŠçãæäŸããŠãããã©ã¡ãã®ããŒãžã§ã³ã§ã Set çµç± (èŠçŽ ã®é åºãä¿æãããäžæã®ããŒã䜿çš) ãš List çµç± (éè€ãããå¯èœæ§ããããŸã - é åºã¯ä¿æãããŸã) ãæäŸããŠããããšãããããŸãã
åçŽãªå®è£
åçŽãªå®è£
REST ã³ã³ãããŒã©ãŒã®æåã®åçŽãªå®è£ ã¯ãã»ãšãã©ã®å Žå次ã®ããã«ãªããŸãã
class ChatRestController(
private val messageRepository: ChatMessageRepository,
private val userRepository: UserRemoteApi,
private val fileRepository: FileRemoteApi
) : ChatRestApi {
override fun getLast(n: Int) =
messageRepository.findLast(n)
.map { it.toFrontModel() }
private fun ChatMessage.toFrontModel(): ChatMessageUI =
ChatMessageUI(
id = id ?: throw IllegalStateException("$this must be persisted"),
author = userRepository.getUserById(author).toFrontReference(),
message = message,
files = files?.let { files ->
fileRepository.getHeadsByIds(files)
.map { it.toFrontReference() }
} ?: listOf(),
forwardFrom = forwardFrom?.toFrontModel(),
replyTo = replyTo?.toFrontModel()
)
}
ãã¹ãŠãéåžžã«æ確ã§ãããããã¯å€§ããªå©ç¹ã§ãã
ãããåŠçã䜿çšããå€éšãµãŒãã¹ããããŒã¿ããããã§åä¿¡ããŸãã ããããç§ãã¡ã®çç£æ§ã¯ã©ããªãã§ãããã?
ã¡ãã»ãŒãžããšã«ãäœæè ãã£ãŒã«ãã®ããŒã¿ãååŸããããã« UserRemoteApi ã XNUMX ååŒã³åºããããã¹ãŠã®æ·»ä»ãã¡ã€ã«ãååŸããããã« FileRemoteApi ã XNUMX ååŒã³åºãããŸãã ããã ãã®ããã§ãã ChatMessage ã® forwardFrom ãã£ãŒã«ããš ReplyTo ãã£ãŒã«ãããäžå¿ èŠãªåŒã³åºããå¿ èŠãšããªãæ¹æ³ã§ååŸããããšããŸãã ãã ãããããã ChatMessageUI ã«å€ãããšååž°ãçºçããåŒã³åºãã«ãŠã³ã¿ãŒãå€§å¹ ã«å¢å ããå¯èœæ§ããããŸãã åã«è¿°ã¹ãããã«ããã¹ããããŸããªãããã§ãŒã³ã XNUMX ã€ã®ã¡ãã»ãŒãžã«å¶éãããŠãããšä»®å®ããŸãããã
ãã®çµæãã¡ãã»ãŒãžããšã«å€éšãµãŒãã¹ãžã®åŒã³åºãã 2 ïœ 1 åçºçããã¡ãã»ãŒãžã®ããã±ãŒãžå šäœã§ JPA åŒã³åºãã 6 åçºçããŸãã åŒã³åºãã®åèšæ°ã¯ã1*N+20 ãã 4*N+10 ãŸã§å€åããŸãã ããã¯å®éã®åäœã§ã¯ãããã§ãã? ããŒãžãã¬ã³ããªã³ã°ããã®ã« 500 åã®ã¡ãã»ãŒãžãå¿ èŠã ãšããŸãã åä¿¡ã«ã¯ XNUMX ç§ãã XNUMX ç§ããããŸãã ã²ã©ãïŒ XNUMXms以å ã«æãããã§ãã ãããŠãããã³ããšã³ãã§ã·ãŒã ã¬ã¹ãªã¹ã¯ããŒã«ãå®çŸããããšã倢èŠãŠããããããã®ãšã³ããã€ã³ãã®ããã©ãŒãã³ã¹èŠä»¶ã¯ XNUMX åã«ãªãå¯èœæ§ããããŸãã
é·æïŒ
- ã³ãŒãã¯ç°¡æœã§èªå·±ææžåãããŠããŸã (ãµããŒã ããŒã ã®å€¢ã§ã)ã
- ã³ãŒãã¯ã·ã³ãã«ãªã®ã§ã足ãæãããæ©äŒã¯ã»ãšãã©ãããŸããã
- ãããåŠçã¯ç°ç©ã®ããã«ã¯èŠãããããžãã¯ã«ææ©çã«çµ±åãããŠããŸãã
- ããžãã¯ã®å€æŽã¯ç°¡åã«è¡ãããããŒã«ã«ã§è¡ãããŸãã
ãã€ãã¹ïŒ
ãã±ãããéåžžã«å°ãããããããã©ãŒãã³ã¹ãäœäžããŸãã
ãã®ã¢ãããŒãã¯ãåçŽãªãµãŒãã¹ããããã¿ã€ãã§ããèŠãããŸãã å€æŽã®é床ãéèŠã§ããå Žåãã·ã¹ãã ãè€éã«ãã䟡å€ã¯ã»ãšãã©ãããŸããã åæã«ãç§ãã¡ã®éåžžã«åçŽãªãµãŒãã¹ã®ããã©ãŒãã³ã¹ã¯ã²ã©ããã®ã§ããããããã®ã¢ãããŒãã®é©çšç¯å²ã¯éåžžã«çãã§ãã
åçŽãªäžŠååŠç
ãã¹ãŠã®ã¡ãã»ãŒãžã®åŠçã䞊è¡ããŠéå§ã§ããŸããããã«ãããã¡ãã»ãŒãžã®æ°ã«å¿ããæéã®çŽç·çãªå¢å ãé¿ããããšãã§ããŸãã ããã¯å€éšãµãŒãã¹ã«å€§ããªããŒã¯è² è·ããããããããç¹ã«è¯ããã¹ã§ã¯ãããŸããã
䞊ååŠçã®å®è£ ã¯éåžžã«ç°¡åã§ãã
override fun getLast(n: Int) =
messageRepository.findLast(n).parallelStream()
.map { it.toFrontModel() }
.collect(toList())
䞊åã¡ãã»ãŒãžåŠçã䜿çšãããšãçæ³çã«ã¯ 300 ïœ 700 ããªç§ãåŸãããŸããããã¯åçŽãªå®è£ ãããã¯ããã«åªããŠããŸãããããã§ãååãªé床ã§ã¯ãããŸããã
ãã®ã¢ãããŒãã§ã¯ãuserRepository ãš fileRepository ãžã®ãªã¯ãšã¹ããåæçã«å®è¡ããããããããŸãå¹ççã§ã¯ãããŸããã ãããä¿®æ£ããã«ã¯ãåŒã³åºãããžãã¯ãå€§å¹ ã«å€æŽããå¿ èŠããããŸãã ããšãã°ãCompletionStage (å¥å CompletableFuture) çµç±ã§ã¯æ¬¡ã®ããã«ãªããŸãã
private fun ChatMessage.toFrontModel(): ChatMessageUI =
CompletableFuture.supplyAsync {
userRepository.getUserById(author).toFrontReference()
}.thenCombine(
files?.let {
CompletableFuture.supplyAsync {
fileRepository.getHeadsByIds(files).map { it.toFrontReference() }
}
} ?: CompletableFuture.completedFuture(listOf())
) { author, files ->
ChatMessageUI(
id = id ?: throw IllegalStateException("$this must be persisted"),
author = author,
message = message,
files = files,
forwardFrom = forwardFrom?.toFrontModel(),
replyTo = replyTo?.toFrontModel()
)
}.get()!!
æåã¯åçŽãªãããã³ã° ã³ãŒããç解ãã«ãããªã£ãŠããããšãããããŸãã ããã¯ãçµæã䜿çšãããå€éšãµãŒãã¹ãžã®åŒã³åºããåé¢ããå¿ èŠããã£ãããã§ãã ããèªäœã¯æªãããšã§ã¯ãããŸããã ããããã³ãŒã«ãçµã¿åããããšããŸããšã¬ã¬ã³ãã«èŠãããå žåçãªåå¿æ§ã®ãããŒãã«ãã«äŒŒãŠããŸãã
ã³ã«ãŒãã³ã䜿çšãããšããã¹ãŠãããé©åã«èŠããããã«ãªããŸãã
private fun ChatMessage.toFrontModel(): ChatMessageUI =
join(
{ userRepository.getUserById(author).toFrontReference() },
{ files?.let { fileRepository.getHeadsByIds(files)
.map { it.toFrontReference() } } ?: listOf() }
).let { (author, files) ->
ChatMessageUI(
id = id ?: throw IllegalStateException("$this must be persisted"),
author = author,
message = message,
files = files,
forwardFrom = forwardFrom?.toFrontModel(),
replyTo = replyTo?.toFrontModel()
)
}
ããã§ïŒ
fun <A, B> join(a: () -> A, b: () -> B) =
runBlocking(IO) {
awaitAll(async { a() }, async { b() })
}.let {
it[0] as A to it[1] as B
}
çè«çã«ã¯ããã®ãããªäžŠååŠçã䜿çšãããš 200 ïœ 400 ããªç§ãåŸãããŸãããããã¯ãã§ã«äºæ³ã«è¿ãå€ã§ãã
æ®å¿µãªããããã®ãããªåªãã䞊ååã¯ååšãããæ¯æããªããã°ãªããªã代åã¯éåžžã«æ®é ·ã§ããåæã«å°æ°ã®ãŠãŒã¶ãŒã ããäœæ¥ããŠãããšã倧éã®ãªã¯ãšã¹ãããµãŒãã¹ã«éããããããããã«ããŠã䞊ååŠçãããŸãããæ²ãã4æ代ã«æ»ã£ãŠããŸããŸãã
ãã®ãããªãµãŒãã¹ã䜿çšããå Žåã®çµæã¯ã1300 åã®ã¡ãã»ãŒãžãåŠçããã®ã« 1700 ïœ 20 ããªç§ã§ããã ããã¯æåã®å®è£ ãããé«éã§ãããããã§ãåé¡ã¯è§£æ±ºãããŸããã
䞊åã¯ãšãªã®å¥ã®äœ¿çšæ³ãµãŒãããŒãã£ã®ãµãŒãã¹ããããåŠçãæäŸããŠããªãå Žåã¯ã©ããªããŸãã? ããšãã°ãã€ã³ã¿ãŒãã§ã€ã¹ ã¡ãœããå ã®ãããåŠçå®è£ ã®æ¬ åŠãé ãããšãã§ããŸãã
interface UserRemoteApi {
fun getUserById(id: UserReference): UserRemote
fun getUsersByIds(id: Set<UserReference>): Set<UserRemote> =
id.parallelStream()
.map { getUserById(it) }.collect(toSet())
fun getUsersByIds(id: List<UserReference>): List<UserRemote> =
id.parallelStream()
.map { getUserById(it) }.collect(toList())
}
å°æ¥ã®ããŒãžã§ã³ã§ãããåŠçãæåŸ
ããå Žåãããã¯çã«ããªã£ãŠããŸãã
é·æïŒ
- ã¡ãã»ãŒãžããŒã¹ã®äžŠååŠçãç°¡åã«å®è£ ããŸãã
- åªããæ¡åŒµæ§ã
çæïŒ
- ç°ãªããµãŒãã¹ãžã®ãªã¯ãšã¹ãã䞊è¡ããŠåŠçããå ŽåãããŒã¿ã®ååŸãšãã®åŠçãåé¢ããå¿ èŠæ§ã
- ãµãŒãããŒãã£ã®ãµãŒãã¹ã®è² è·ãå¢å ããŸãã
é©çšç¯å²ã¯åçŽãªã¢ãããŒããšã»ãŒåãã§ããããšãããããŸãã ä»è ã®å®¹èµŠãªãæªçšã«ãããµãŒãã¹ã®ããã©ãŒãã³ã¹ãæ°ååäžããããå Žåã¯ã䞊åãªã¯ãšã¹ãæ¹åŒã䜿çšããã®ãåççã§ãã ãã®äŸã§ã¯ãããã©ãŒãã³ã¹ã 2,5 ååäžããŸããããããã§ã¯æããã«ååã§ã¯ãããŸããã
ãã£ãã·ã³ã°
å€éšãµãŒãã¹ã® JPA ã®ç²Ÿç¥ã«åºã¥ããŠãã£ãã·ã¥ãå®è¡ã§ããŸããã€ãŸããåä¿¡ãããªããžã§ã¯ãã (ãããåŠçäžãå«ã) å床åä¿¡ããªãããã«ã»ãã·ã§ã³å ã«æ ŒçŽããŸãã ãã®ãããªãã£ãã·ã¥ã¯èªåã§äœæããããšãã@Cacheable ãåãã Spring ã䜿çšããããšãã§ããããã« EhCache ã®ãããªæ¢è£œã®ãã£ãã·ã¥ããã€ã§ãæåã§äœ¿çšããããšãã§ããŸãã
ããããåé¡ã¯ããã£ãã·ã¥ããããããå Žåã«ã®ã¿åœ¹ç«ã€ããšã§ãã ãã®å Žåãäœæè ãã£ãŒã«ãã«ã¯ãããããå¯èœæ§ãéåžžã«é«ããªããŸã (ããšãã° 50%) ãããã¡ã€ã«ã«ã¯ãŸã£ãããããããŸããã ãã®ã¢ãããŒãã«ããå€å°ã®æ¹åã¯åŸãããŸãããããã©ãŒãã³ã¹ãæ ¹æ¬çã«å€ããããã§ã¯ãããŸãã (ãã¬ãŒã¯ã¹ã«ãŒãå¿ èŠã§ã)ã
ã»ãã·ã§ã³é (é·ã) ãã£ãã·ã¥ã«ã¯ãè€éãªç¡å¹åããžãã¯ãå¿ èŠã§ãã äžè¬ã«ãã»ãã·ã§ã³éãã£ãã·ã¥ã䜿çšããŠããã©ãŒãã³ã¹ã®åé¡ã解決ããã®ã¯é ããã°é ãã»ã©è¯ãã§ãããã
é·æïŒ
- ã³ãŒããå€æŽããã«ãã£ãã·ã¥ãå®è£ ããŸãã
- çç£æ§ãæ°ååäžããŸããïŒå Žåã«ãã£ãŠã¯ïŒã
çæïŒ
- 誀ã£ãŠäœ¿çšãããšããã©ãŒãã³ã¹ãäœäžããå¯èœæ§ããããŸãã
- ç¹ã«é·ããã£ãã·ã¥ã®å Žåãã¡ã¢ãªã®ãªãŒããŒãããã倧ãããªããŸãã
- è€éãªç¡å¹åãå®è¡æã«åçŸãå°é£ãªåé¡ãåŒãèµ·ãããšã©ãŒã
å€ãã®å Žåããã£ãã·ã¥ã¯èšèšäžã®åé¡ãè¿ éã«è§£æ±ºããããã ãã«äœ¿çšãããŸãã ããã¯ããããã䜿çšããŠã¯ãããªããšããæå³ã§ã¯ãããŸããã ãã ããããããåžžã«æ éã«æ±ããæåã«çµæãšããŠåŸãããããã©ãŒãã³ã¹ã®åäžãè©äŸ¡ããŠããã決å®ãäžãå¿ èŠããããŸãã
ãã®äŸã§ã¯ããã£ãã·ã¥ã«ããããã©ãŒãã³ã¹ãçŽ 25% åäžããŸãã åæã«ããã£ãã·ã¥ã«ã¯éåžžã«å€ãã®æ¬ ç¹ããããããããã§ã¯äœ¿çšããŸããã
çµæ
ããã§ããããåŠçã䜿çšãããµãŒãã¹ã®åçŽãªå®è£ ãšããããé«éåããããã€ãã®ç°¡åãªæ¹æ³ãæ€èšããŸããã
ããããã¹ãŠã®æ¹æ³ã®äž»ãªå©ç¹ã¯ãã®åçŽãã§ãããããããå€ãã®æ¥œããçµæãåŸãããŸãã
ãããã®æ¹æ³ã«å ±éããåé¡ã¯ãäž»ã«ãã±ããã®ãµã€ãºãåå ã§ããã©ãŒãã³ã¹ãäœäžããããšã§ãã ãããã£ãŠããããã®è§£æ±ºçãããªãã«åããªãå Žåã¯ãããæ ¹æ¬çãªæ¹æ³ãæ€èšãã䟡å€ããããŸãã
解決çãæ¢ãã«ã¯ã䞻㫠XNUMX ã€ã®æ¹åããããŸãã
- ããŒã¿ã®éåæäœæ¥ (ãã©ãã€ã ã·ãããå¿ èŠãªããããã®èšäºã§ã¯èª¬æããŸãã)ã
- åæåŠçãç¶æããªããããããæ¡å€§ããŸãã
ããããæ¡å€§ãããšãå€éšåŒã³åºãã®æ°ã倧å¹
ã«æžããåæã«ã³ãŒãã®åæãç¶æãããŸãã èšäºã®æ¬¡ã®éšåã§ã¯ããã®ãããã¯ã«ã€ããŠèª¬æããŸãã
åºæïŒ habr.com