DDD çµè«
- ãšãŠãé«ã
- 確ç«ãããããžãã¹ããã»ã¹ã§ããŸãæ©èœãã
- å¿ èŠãªããšãè¡ãå¯äžã®æ¹æ³ã§ããå ŽåããããŸãã
- ã¹ã±ãŒãªã³ã°ãäžåå
- è² è·ã®é«ãã¢ããªã±ãŒã·ã§ã³ã«å®è£ ããã®ãé£ãã
- ã¹ã¿ãŒãã¢ããã§ããŸãåäœããªã
- ã¬ããŒãã«ã¯é©ããŠããŸãã
- ORMã«ç¹å¥ãªæ³šæãå¿ èŠ
- ãšã³ãã£ãã£ã¯èª°ããç¬èªã®æ¹æ³ã§ç解ãããããåé¿ããã®ãæåã§ãã
- LINQã§ã¯ãä»æ§ã®æšæºå®è£ ã¯ãæ©èœããŸããã
ãšãŠãé«ã
ç§ããããã¯ã«ã€ããŠè°è«ããDDDã䜿çšãããã¹ãŠã®éçºãããŒãžã£ãŒã¯ãäž»ã«Evansã®æžç±ãDDDã®ååã«éåããã«FooBarãäœæããã«ã¯ã©ãããã°ããã§ããïŒã
ã°ã¬ãã°ã€ã³ã°ã«ãããšãGoogleã®CQRSã°ã«ãŒãã§æããããã質åã¯æ¬¡ã®ãšããã§ãã RAMã§éèšã®ãã¹ãŠã®ã«ãŒããååŸãããšããã¹ãŠãé ããªãå§ããŸãã ã©ãããã°ããã§ããïŒã ãã®è³ªåã«ã¯æãããªçãããããŸãããSQLã¯ãšãªãèšè¿°ããå¿ èŠããããŸããã ãã ããæåã®SQLã¯ãšãªãèšè¿°ããããšã¯æããã«DDDã«ãŒã«ã«åããŸãã
ãšãŽã¡ã³ã¹èªèº«ã¯ã€ã³ã°ãšåæããæ¬ã¯å¥ã®é åºã§æžãããã¹ãã§ãããšè¿°ã¹ãã éèŠãªæŠå¿µã¯ã EntityãšValueObjectã§ã¯ãªãã Bounded ContextãšUbiquitous Language ã§ã ã
ã¬ããŒãã«ã¯ãã¡ã€ã³ã¢ãã«ã¯å¿ èŠãããŸããã ã¬ããŒãã¯åãªãããŒã¿ããŒãã«ã§ãã ããŒã¿ããªãã³ã¯ããã¡ã€ã³ããªãã³ãããã¬ããŒãã«é©ããŠããŸãã äžèŠãããšããã®æç¹ã§ãDDDãæªããšèšãå¿ èŠããããŸãã ããããããã¯ããã§ã¯ãããŸããã DDDã䜿çšããŠã¬ããŒããäœæããã ãã§ã¯ãçã®å¢çã³ã³ããã¹ãã§ã¯ãããŸããã
å¶éãããã³ã³ããã¹ã
DDDã®æãéèŠãªè«æã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã«å¯ŸããŠ1ã€ã®å€§ããªãã¡ã€ã³ã¢ãã«ãéçºããããšããªãããšã§ãã ããã¯è€éãããŠã誰ãå¿ èŠãšããŸããã äŒæ¥ç®¡çã®ã¬ãã«ã§ããã¹ãŠã®éšéãåãçšèªã䜿çšãããã¹ãŠã®ããžãã¹ããã»ã¹ãåãããã«ç解ããããšã決å®ãããå Žåã«ã®ã¿ãã¢ããªã±ãŒã·ã§ã³å šäœã«å¯ŸããŠ1ã€ã®ãã¡ã€ã³ã¢ãã«ãäœæã§ããŸãã
誰ããç¬èªã®æ¹æ³ã§ç解ãããšã³ãã£ãã£
çšèªãããŒã ã¡ã³ããŒå šå¡ãšåæããããšã¯éåžžã«é£ããããšã確èªããŸããã Entityãšããçšèªã¯é害ã«ãªããŸãããIEntity<TKey>ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããããšããŸããããIdãValueObjectsã䜿çšããŠã³ãã³ããéä¿¡ã§ããããšã«ããã«æ°ä»ããŸããã ãã®ãããªãªããžã§ã¯ãã«IEntity <TKey>ã䜿çšãããšæ··ä¹±ããããã IHasIdãåªå ããŠIEntityãæŸæ£ããŸããã
DDDã§ã¯ORMã«ç¹å¥ãªæ³šæãå¿ èŠã§ã
ã¹ã¿ãã¯ãªãŒããŒãããŒã§ã®DDDã®NHacknate察Entity Frameworkã«ã€ããŠã¯ãããªãã®æ°ã®è°è«ããããŸãã NHibernateã®æ¹ãäžè¬çã«åªããŠããŸããããŸã å€ãã®åé¡ããããŸãã ORMã䜿çšããå Žåã®æšæºçãªã¢ãããŒãã¯ããã©ã¡ãŒã¿ãŒãªãã®ã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããããããã£ã»ãã¿ãŒãä»ããŠå€ãèšå®ããããšã§ãã ããã¯ã«ãã»ã«åã®äžæã§ãã ã³ã¬ã¯ã·ã§ã³ãšLazy Loadã«ã¯ç¹å®ã®åé¡ããããŸãã ããã«ãããŒã ã¯ãããã¡ã€ã³ããçµäºãããã€ã³ãã©ã¹ãã©ã¯ãã£ããéå§ããå Žæãšãæ°žç¶æ§ç¡èŠãæäŸããæ¹æ³ã決å®ããå¿ èŠããããŸãã
LINQã§ã¯ãä»æ§ã®æšæºå®è£ ã¯ãæ©èœããŸããã
Evansã¯Javaã®äžçã®ç·ã§ãã ããã«ãæ¬ã¯ãã£ãšåã«æžãããŸããã
public abstract class Specification<T> { public abstract bool IsSatisfiedBy(T entity) };
ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšãããšãã¡ã¢ãªå ã®ã³ã¬ã¯ã·ã§ã³ãæäœã§ããŸãããSQLã¯ãšãªã®æ§ç¯ã«ã¯ãŸã£ããé©ããŠããŸããã ææ°ã®CïŒã§ã¯ã ãã®ãªãã·ã§ã³ã®æ¹ãé©ããŠããŸãã
public abstract class Specification<T> { public bool IsSatisfiedBy(T item) { return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any(); } public abstract IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates); }
å¿çšåé
ãã¡ã€ã³ã¢ããªã³ã°ã¯ç°¡åãªäœæ¥ã§ã¯ãããŸããã DDDã§ã¯ãããã€ãã®åæã¿ã¹ã¯ãéçºè ã«å§ä»»ããŸãã ããã¯ããšã©ãŒã®ã³ã¹ããé«ãå Žåã«æ£åœåãããŸãã ã³ãŒããã©ãã ãéãæžãããŠããŠããã·ã¹ãã ãæ£ããåäœããããéã倱ã£ããšããŠããã·ã¹ãã ãã©ãã ãéãåäœãããã¯é¢ä¿ãããŸããã å®éãéã®ããšãèšããŸããHFTçšã®ãœãããŠã§ã¢ãéçºããŠããŠããã®åäœæ¹æ³ãå®å šã«ç解ããŠããªãå Žåã¯ããœãããŠã§ã¢ã®é床ãäœäžãããããŸã£ããåäœããªãããšãæãŸããã§ãã ã ãããå°ãªããšãããªãã¯è¶ é«éã§ãéã倱ãããšã¯ãããŸããããæ£ããååŒã§ã¯ãããŸãã:)
æç¶äžå¯èœãªããžãã¹ïŒç¹ã«ã¹ã¿ãŒãã¢ããïŒã§ã¯ãå€ãã®å Žåã察象ã¢ãã«ã®ç解ããããŸããã ãã¹ãŠãæ¯æ¥å€ãããŸãã ãããã®æ¡ä»¶ã§ã¯ãããžãã¹ããã»ã¹ã®åå è ã«åäžã®çšèªã䜿çšããããã«èŠæ±ããããšã¯ç¡æå³ã§ãã
Cqrs
çµè«ã¯æããã§ããDDDã¯ãéã®åŒŸäžžãã§ã¯ãªããæ®å¿µã§ã:)ãã ããç¹å®ã®ããŠã³ãã³ã³ããã¹ãã§ã®DDDã®ãã¿ãŒã²ããã¢ããªã±ãŒã·ã§ã³ãã«ããã倧ããªå©çãåŸãããšãã§ããŸãã
1980幎ãããŒãã©ã³ããã€ã€ãŒã¯éåžžã«åçŽãªçšèªCQSãçå®ããŸããã 2000幎代åé ãã°ã¬ãã°ã€ã³ã°ã¯ãã®æŠå¿µãæ¡å€§ããæ®åãããŸããã ãã®ãããCQRSãç»å ŽããŸãã...ãããŠãCQRSã¯ç¹°ãè¿ã誀解ããããšããæå³ã§ãDDDã®éåœãã»ãŒç¹°ãè¿ããŸããã
ã€ã³ã¿ãŒãããã«ã¯CQRSã®è³æããããããããšããäºå®ã«ããããããã誰ããããŸããŸãªæ¹æ³ã§ãæºåãããŠããŸãã å€ãã®ããŒã ã¯ãCQRSã®ååã䜿çšããŠããŸãããCQRSãšã¯åŒã³ãŸããã ã·ã¹ãã ã«ã¯Commandããã³Queryã®æœè±¡åããªãå ŽåããããŸãã IOperationãŸãã¯Func <T1ãT2>ããã³Action <T>ã«çœ®ãæããããšãã§ããŸãã
ããã«ã¯ç°¡åãªèª¬æããããŸãã æåã®CQRSã®çµæã¯ã次ã®ç»åã®ãããªãã®ãçæããŸãã
Dino Esposito ã¯ãã®å®è£ ãDELUXEãšåŒã³ãŸã ã ããã§ã®ãã€ã³ãã¯ãCQRSãäž»ã«ã€ãã³ããœãŒã·ã³ã°ã®ã³ã³ããã¹ãã§ã°ã¬ãã°ã€ã³ã°ã«é¢å¿ãæã£ãŠããããšã§ãã å®éãã€ãã³ããœãŒã·ã³ã°ã§ã¯CQRSã䜿çšããå¿ èŠããããŸããããã®éã¯å¿ èŠãããŸããã
ãããã£ãŠãCQRSã䜿çšãããšãã¢ããªã±ãŒã·ã§ã³ã¹ã¿ãã¯ãèªã¿åããšæžã蟌ã¿ã«åå²ããèªã¿åãã¹ã¿ãã¯ã®ãã¡ã€ã³ã¢ãã«ã䜿çšããªãããšã§ããã¬ãŒãã¬ããŒãã®åé¡ã解決ã§ããŸãã èªã¿åãã¹ã¿ãã¯ã¯ ãç°ãªãããŒã¿ããŒã¹ããã³/ãŸãã¯ä»ã®ããæé©ãªããŒã¿ã¢ã¯ã»ã¹APIã䜿çšããå ŽåããããŸãã
ã¢ããªã±ãŒã·ã§ã³ãã³ãã³ãããã³ãã©ãŒãããã³ãªã¯ãšã¹ãã«åå²ããããšã«ã¯ãäºæž¬å¯èœæ§ã®åäžãšããå¥ã®å©ç¹ããããŸãã DDDã®å Žåãç¹å®ã®ããžãã¹ããžãã¯ãæ¢ãå Žæãç¥ãã«ã¯ããµããžã§ã¯ãé åãç解ããå¿ èŠããããŸãã CQRSã®å Žåãããã°ã©ããŒã¯ã³ãã³ããã³ãã©ãŒã§æžã蟌ã¿ãè¡ãããããšãåžžã«èªèããŠãããã¯ãšãªã¯ããŒã¿ãžã®ã¢ã¯ã»ã¹ã«äœ¿çšãããŸãã ããã«ãäžèŠãããšããæããã§ãªãå©ç¹ãããã€ããããŸãã 以äžã§æ€èšããŸãã
CQRSã®äž»èŠãªèª¿æ»çµæ
- ã€ãã³ããœãŒã·ã³ã°ã«ã¯CQRSãå¿ èŠã§ããããã®éã¯äžèŠã§ã
- å®ã
- ã©ãã«ã§ããã£ãã
- ã¹ã±ãŒã©ãã«
- 2ã€ã®ããŒã¿ã¹ãã¢ã¯å¿ èŠãããŸããã ããã¯å¯èœãªå®è£ ã®1ã€ã§ãããå¿ é ã§ã¯ãããŸãã
- ã³ãã³ããã³ãã©ã¯å€ãè¿ãããšãã§ããŸãã åæããªãå Žåã¯ã ã°ã¬ãã°ã€ã³ã°ãšãã£ããšã¹ããžããšè°è«ããŠãã ããã
- ãã³ãã©ãŒãå€ãè¿ããå Žåãã¹ã±ãŒã«ã¯æªåããŸãããéåæ/åŸ æ©ããããŸãããããããã©ã®ããã«æ©èœããããç解ããå¿ èŠããããŸã
CQRSã®ã¡ã€ã³ã€ã³ã¿ãŒãã§ã€ã¹ã¯æ¬¡ã®ããã«ãªããŸã ã
[PublicAPI] public interface IQuery<out TOutput> { TOutput Ask(); } [PublicAPI] public interface IQuery<in TSpecification, out TOutput> { TOutput Ask([NotNull] TSpecification spec); } [PublicAPI] public interface IAsyncQuery<TOutput> : IQuery<Task<TOutput>> { } [PublicAPI] public interface IAsyncQuery<in TSpecification, TOutput> : IQuery<TSpecification, Task<TOutput>> { } [PublicAPI] public interface ICommandHandler<in TInput> { void Handle(TInput input); } [PublicAPI] public interface ICommandHandler<in TInput, out TOutput> { TOutput Handle(TInput input); } [PublicAPI] public interface IAsyncCommandHandler<in TInput> : ICommandHandler<TInput, Task> { } [PublicAPI] public interface IAsyncCommandHandler<in TInput, TOutput> : ICommandHandler<TInput, Task<TOutput>> { }
次ã®ããšã«åæããŸããã
- ã¯ãšãªã¯åžžã«ããŒã¿ã®ã¿ãåä¿¡ããŸãããã·ã¹ãã ã®ç¶æ ã¯å€æŽããŸããã ã·ã¹ãã ãå€æŽããã«ã¯ã次ã®ã³ãã³ãã䜿çšããŸã
- ã¯ãšãªã¯ããã¡ã€ã³ã¢ãã«ããã€ãã¹ããŠãå¿ èŠãªæ圱ãçŽç·ã§è¿ãããšãã§ããŸã
ãã®å Žåã ã³ãã³ãããªãå Žåã ãã¹ãŠã®Queryã¯åžžã«åãinputã§åãçµæãè¿ããŸã ã ãã®ãããªçµç¹ã¯ãQueryã«æ»ãçµæãå€æŽããå¯èœæ§ã®ããç¶æ ããªãããããããã°ãå€§å¹ ã«ç°¡çŽ åããŸãã
å¿ èŠã«å¿ããŠãç£æ»ãã°ãŸãã¯æ¬æ Œçãªã€ãã³ããœãŒã·ã³ã°ããåºæ¬ã¯ã©ã¹ãä»ããŠãã¹ãŠã®ã³ãã³ããã³ãã©ãŒã«æ¥ç¶ã§ããŸãã
ã¡ã€ã³ã®CQRSã€ã³ã¿ãŒãã§ãŒã¹ãFunc <T1ãT2>ããã³Action <T>ã«ãã£ã¹ãã§ããããšã«æ°ä»ãã®ã¯é£ãããããŸããã ã¹ããŒãã¬ã¹ã§äžå€ãªãã®ãè¿œå ãããšã çŽç²ãªé¢æ° ïŒhié¢æ°åããã°ã©ãã³ã°ïŒãåŸãããŸããå³å¯ã«èšãã°ãã»ãšãã©ã®ã¯ãšãªã¯ãã¡ã€ã«ã·ã¹ãã ãããŒã¿ããŒã¹ããŸãã¯ãããã¯ãŒã¯ã§åäœãããããããã¯ééãã§ãã ã¯ãšãªã®çµæããã£ãã·ã¥ããããšãã§ããŸãããããŒã¿ãããŒãšæ§æå¯èœæ§ãç·åœ¢åããããšã®å©ç¹ãåŸãããšãã§ããŸãã
HTTPãä»ããCQRS
CQRSã®ååã¯ãHTTPãä»ããå®è£ ã«éåžžã«é©ããŠããŸãã HTTPä»æ§ã§ã¯ãGETãªã¯ãšã¹ãã¯ãµãŒããŒããããŒã¿ãè¿ãå¿ èŠãããããšãæ確ã«èŠå®ãããŠããŸãã POSTãPUTãPATCH-ç¶æ ãå€æŽããŸãã Webããã°ã©ãã³ã°ã®åªãããã©ãŒã ã¯ããã©ãŒã éä¿¡ãªã©ã®POSTæäœãå®è¡ããåŸã®GETãžã®ãªãã€ã¬ã¯ããšèŠãªãããŸãã
ã ãã
- GETã¯ã¯ãšãªã§ã
- POST / PUT / PATCH / DELETEã¯ã³ãã³ã
äžè¬çã«äœ¿çšãããæäœã®åºæ¬ã¯ã©ã¹
ã¬ããŒãã¯ãããŒã¿èªã¿åãã®å¯äžã®é »ç¹ãªã¿ã¹ã¯ã§ã¯ãããŸããã äžè¬çãªèªã¿åãæäœã®ããäžè¬çãªå®çŸ©ã¯æ¬¡ã®ãšããã§ãã
- ãã£ã«ã¿ãªã³ã°
- ããŒãžããŒã·ã§ã³ïŒããŒãžããŒã·ã§ã³ïŒ
- ãããžã§ã¯ã·ã§ã³ã®äœæïŒã¯ã©ã€ã¢ã³ãåŽã§å¿ èŠãªåœ¢åŒã§ã®éçŽã®è¡šçŸïŒ
AutoMapperãç©æ¥µçã«äœ¿çšããŠã ãããžã§ã¯ã·ã§ã³ãæ§ç¯ããŠããŸãã ãã®ããããŒã®éç«ã£ãæ©èœã®1ã€ã¯Queryable-Extensionsã§ããããã¯ãRAMã«ãããã³ã°ãã代ããã«ãSQLã«å€æããããã®Expressionãæ§ç¯ããæ©èœã§ãã ãããã®æ圱æ³ã¯åžžã«æ£ç¢ºã§å¹ççã§ã¯ãããŸããããã©ããããããã¿ã€ãã³ã°ã«æé©ã§ãã
ä»»æã®ããŒãã«ããããŒã¿ããŒã¹ããã³ãã£ã«ã¿ãªã³ã°ãµããŒããžã®ããŒãžåãããåºåã®å Žåã䜿çšã§ããIQueryå®è£ ã¯1ã€ã®ã¿ã§ãã
public class ProjectionQuery<TSpecification, TSource, TDest> : IQuery<TSpecification, IEnumerable<TDest>> , IQuery<TSpecification, int> where TSource : class, IHasId where TDest : class { protected readonly ILinqProvider LinqProvider; protected readonly IProjector Projector; public ProjectionQuery([NotNull] ILinqProvider linqProvier, [NotNull] IProjector projector) { if (linqProvier == null) throw new ArgumentNullException(nameof(linqProvier)); if (projector == null) throw new ArgumentNullException(nameof(projector)); LinqProvider = linqProvier; Projector = projector; } protected virtual IQueryable<TDest> GetQueryable(TSpecification spec) => LinqProvider .GetQueryable<TSource>() .ApplyIfPossible(spec) .Project<TSource, TDest>(Projector) .ApplyIfPossible(spec); public virtual IEnumerable<TDest> Ask(TSpecification specification) => GetQueryable(specification).ToArray(); int IQuery<TSpecification, int>.Ask(TSpecification specification) => GetQueryable(specification).Count(); } public class PagedQuery<TSortKey, TSpec, TEntity, TDto> : ProjectionQuery<TSpec, TEntity, TDto>, IQuery<TSpec, IPagedEnumerable<TDto>> where TEntity : class, IHasId where TDto : class, IHasId where TSpec : IPaging<TDto, TSortKey> { public PagedQuery(ILinqProvider linqProvier, IProjector projector) : base(linqProvier, projector) { } public override IEnumerable<TDto> Ask(TSpec spec) => GetQueryable(spec).Paginate(spec).ToArray(); IPagedEnumerable<TDto> IQuery<TSpec, IPagedEnumerable<TDto>>.Ask(TSpec spec) => GetQueryable(spec).ToPagedEnumerable(spec); public IQuery<TSpec, IPagedEnumerable<TDto>> AsPaged() => this as IQuery<TSpec, IPagedEnumerable<TDto>>; }
ApplyIfPossibleã¡ãœãã㯠ãéèšãŸãã¯æ圱ã®ã¬ãã«ã§ãã£ã«ã¿ãªã³ã°ãå®è¡ãããŠãããã©ããã確èªããŸãïŒå¿ èŠãªå Žåãªã©ïŒã Projectã¡ãœããã¯ãAutoMapperã䜿çšããŠæ圱ãäœæããŸãã
ãªãŒããã£ã«ã¿ãŒãšDynamic Linqã¯ãå€ãã®é¡äŒŒãããã©ãŒã ã§äœæ¥ããå Žåã«åœ¹ç«ã¡ãŸãã
public static class AutoFilterExtensions { public static IQueryable<T> ApplyDictionary<T>(this IQueryable<T> query , IDictionary<string, object> filters) { foreach (var kv in filters) { query = query.Where(kv.Value is string ? $"{kv.Key}.StartsWith(@0)" : $"{kv.Key}=@0", kv.Value); } return query; } public static IDictionary<string, object> GetFilters(this object o) => o.GetType() .GetTypeInfo() .GetProperties(BindingFlags.Public) .Where(x => x.CanRead) .ToDictionary(k => k.Name, v => v.GetValue(o)); } public class AutoFilter<T> : ILinqSpecification<T> where T: class { public IDictionary<string, object> Filter { get; } public AutoFilter() { Filter = new Dictionary<string, object>(); } public AutoFilter([NotNull] IDictionary<string, object> filter) { if (filter == null) throw new ArgumentNullException(nameof(filter)); Filter = filter; } public IQueryable<T> Apply(IQueryable<T> query) => query.ApplyDictionary(Filter); }
create / editã³ãã³ãããéèšãæ§ç¯ããã«ã¯ãæ±çšã®TypeConverterã䜿çšã§ããŸãã
ã³ã³ãããžã®ç»é²ãç°¡çŽ åããããã«ãå¥çŽã䜿çšã§ããŸã ã
ãããã«
ç§ãã¡ã¯è·å Žã§ã€ãã³ããœãŒã·ã³ã°ã䜿çšããã«CQRSãç©æ¥µçã«äœ¿çšããŠããããããŸã§ã®ãšããå°è±¡ã¯éåžžã«è¯å¥œã§ãã
- ã¯ã©ã¹ã¯å°ããã1ã€ã®ããšã ããæ åœããããšãä¿èšŒãããŠãããããã³ãŒãããã¹ãããæ¹ãç°¡åã§ãã
- åãçç±ã§ãã·ã¹ãã ã®å€æŽãç°¡åã«ãªããŸãã
- ã³ãã¥ãã±ãŒã·ã§ã³ãç°¡çŽ åããããã®ã³ãŒããŸãã¯ãã®ã³ãŒãã®å Žæã«é¢ããè«äºããªããªããŸããã ããŸããŸãªããŒã ã¡ã³ããŒã®ã³ãŒããçµ±äžãããŸãã
- DDDã¯ãåæã·ã¹ãã ã¢ããªã³ã°ãšéèšã®äœæã«äœ¿çšãããŸãã 察å¿ããããŒãã«ã®ãã¹ãŠã®ã¡ãœãããå³å¯ã«æé©åãããŠããå ŽåïŒORMã®ãã€ãã¹ãå®è£ ïŒãéèšã¯ãŸã£ããã€ã³ã¹ã¿ã³ã¹åãããªãå¯èœæ§ããããŸã
- ãã«ãããã§ã®ã€ãã³ããœãŒã·ã³ã°-å®è£ ã¯å¿ èŠãããŸããã§ãããç£æ»ãã°ã¯éåžžã«é »ç¹ã«å®è£ ãããŸãã