Placeholder Image

字幕表 動画を再生する

AI 自動生成字幕
  • In the first part, you learned the core concepts of clean architecture as it pertains to Flutter.

    最初のパートでは、Flutterに関連するクリーンアーキテクチャのコアコンセプトを学んだ。

  • We also created a bunch of empty folders, which you can see on the side right now, for presentation, domain, and data.

    また、プレゼンテーション用、ドメイン用、データ用の空のフォルダもたくさん作った。

  • This is for the Number Trivia app we are building.

    これは私たちが作っている数字トリビアアプリのためのものです。

  • And now it's time to start filling in these empty folders with actual code, of course, using test-driven development.

    そして今、これらの空のフォルダを実際のコードで埋め始める時だ。もちろん、テスト駆動開発を使って。

  • Hello, welcome to ResoCoder, where you are getting prepared for real app development by building better, faster, more stable apps.

    ResoCoderへようこそ。ResoCoderでは、より良く、より速く、より安定したアプリを開発することで、本格的なアプリ開発の準備をすることができます。

  • So subscribe and hit the bell if you want to grow your coding skills.

    コーディングのスキルを伸ばしたいなら、ぜひ購読してベルを鳴らしてほしい。

  • So, of course, whenever you are building an app, you should start with the UI and user experience first, but I've done that homework for you.

    だからもちろん、アプリを作るときはいつでも、まずUIとユーザー・エクスペリエンスから始めるべきだ。

  • As you've seen in the previous tutorial, the app looks something like this.

    前のチュートリアルで見たように、アプリは次のようになる。

  • The app looks like this, the actual coding process, though, will happen from the innermost stable layers and will progress toward the outer layers.

    アプリはこのように見えるが、実際のコーディング作業は、最も内側の安定したレイヤーから始まり、外側のレイヤーに向かって進んでいく。

  • So in the case of clean architecture, as it was proposed by Uncle Bob, we can see that we should start from the domain layer, particularly from entities.

    つまり、ボブおじさんが提唱したようなクリーン・アーキテクチャの場合、ドメイン層、特にエンティティから始めるべきだということがわかる。

  • So we are going to create an entity right now.

    だから、今すぐエンティティーを作ろう。

  • Before we do that, though, before we can create an entity for the number trivia, we have to add some packages over to pubspec.yaml, because we are going to be using quite a lot of packages to make things easier for us, of course.

    その前に、トリビア番号のエンティティを作成する前に、pubspec.yamlにいくつかのパッケージを追加しなければならない。

  • And with that, I have to tell you to make sure you check out the written tutorial from the link in the description, where you can find all of the code written in this video, all of the links, and all of that good stuff.

    説明文のリンクから、このビデオで書かれたすべてのコード、すべてのリンク、その他すべての良いものを見つけることができます。

  • And go through this lesson at your own pace.

    そして、自分のペースでこのレッスンを進めてください。

  • This pubspec.yaml file is one of the few things which I'm going to just copy and paste over on video so that I don't bore you to death.

    このpubspec.yamlファイルは、皆さんを退屈させないために、ビデオでコピー&ペーストする数少ないもののひとつです。

  • So let's just delete all of these unnecessary comments.

    だから、不要なコメントはすべて削除しよう。

  • We'll just clutter up the pubspec.yaml file.

    pubspec.yamlファイルを乱雑にするだけだ。

  • And then the dependencies and dev dependencies will be the following.

    そして、依存関係と開発依存関係は次のようになる。

  • So we have getit, which is the service locator.

    サービス・ロケーターであるgetitがある。

  • I've added all of the dependencies right now so that we later do not have to come back to this yaml file and just lose time on that.

    後でこのyamlファイルに戻ってくる必要がなく、時間を無駄にすることがないように、今、依存関係をすべて追加した。

  • So we have getit.

    だから、私たちにはゲットがある。

  • Then we have flutter block for state management, equatable for value equality.

    そして、状態管理のためのフラッター・ブロックと、値の等化のためのイコータブルがある。

  • Then we are going to touch on some functional programming concepts.

    その後、関数型プログラミングの概念に触れる。

  • Then for remote API, we have connectivity and HTTP packages, of course.

    それからリモートAPIについては、もちろんコネクティビティとHTTPパッケージがある。

  • And for local cache, we are going to be using just simple shared preferences.

    そしてローカル・キャッシュには、シンプルな共有プリファレンスを使用する。

  • As for dev dependencies, these are the ones which do not get packaged together with your app once you build it.

    dev dependenciesについては、アプリをビルドしても一緒にパッケージ化されないものです。

  • We have flutter test.

    フラッターテストもある。

  • This was here even before I think by default.

    これはデフォルトだと思う。

  • And then we have Mockito for creating mocks.

    そして、モックを作成するためのMockitoがある。

  • We are going to get to all of this as we progress forward with this tutorial.

    このチュートリアルを進めていくうちに、これらすべてを理解できるようになるだろう。

  • But just so that you have all of the packages already present, we've added them over here.

    しかし、すでにすべてのパッケージが揃っているように、ここに追加した。

  • And I'm just going to delete all of the other comments so that they don't clutter up pubspec.

    そして、パブスペックを散らかさないように、他のコメントはすべて削除するつもりだ。

  • And here we go.

    そして、これだ。

  • The pubspec.yaml file is completely finished.

    pubspec.yaml ファイルは完全に完成しました。

  • All right.

    分かった。

  • So let's now move on to creating the actual entity.

    それでは、実際のエンティティの作成に移ろう。

  • The first question we have to ask ourselves is what kind of data will the NumberTrivia operate with?

    最初の疑問は、NumberTriviaはどのようなデータを扱うのか、ということだ。

  • Well, of course, with NumberTrivia entities.

    まあ、もちろん、NumberTriviaのエンティティでは。

  • So we can create a new file under the domain entities.

    そこで、ドメイン・エンティティの下に新しいファイルを作成することができる。

  • Let's call it NumberTrivia.dart, of course.

    もちろん、NumberTrivia.dartと呼ぶことにしよう。

  • And now we have to take a look at the JSON response from the API because based on that response, we are going to model our class here.

    APIからのJSONレスポンスを見て、そのレスポンスに基づいてクラスをモデリングする。

  • So if you go to numbersapi.com forward slash 42 or some other number and then question mark JSON, so it's a query parameter, you will obtain the following response.

    つまり、numbersapi.comのフォワード・スラッシュ42やその他の数字にクエスチョンマークを付けてJSONにアクセスすると、クエリー・パラメーターとして次のようなレスポンスが返ってくる。

  • And of course, this link is also available from the written tutorial.

    もちろん、このリンクは書かれたチュートリアルからも利用できる。

  • So this is the response which we will be operating with throughout our app.

    つまり、これが私たちのアプリ全体を通して操作することになるレスポンスなのだ。

  • And we need to model our NumberTrivia entity so that it can contain this kind of data.

    そして、NumberTriviaエンティティをモデル化して、この種のデータを格納できるようにする必要がある。

  • So what do we actually really need from this JSON object?

    では、このJSONオブジェクトから実際に何が必要なのだろうか?

  • Well, we need the text, obviously, because that's the core, so to say, functionality of our NumberTrivia app.

    NumberTriviaアプリの核となる機能だからだ。

  • We are going to store the number, but then we have two interesting fields, which are found and type.

    番号を保存するつもりだが、次に2つの興味深いフィールドがある。

  • We are not going to need those at all because found is completely irrelevant for our case, and the type will be always trivia.

    ファウンドは今回のケースにはまったく関係ないし、タイプは常にトリビアになるからだ。

  • And why is found completely irrelevant?

    そして、なぜまったく関係ないことがわかったのか?

  • Well, if I search for a number other than 42, so for example, some complete gibberish long number, which doesn't have any entry in the numbers API and search for that, you can see that found is false, but we still obtain some kind of a reasonable response that this is an uninteresting number.

    さて、42以外の数字を検索してみよう。例えば、数字APIにエントリーがないような、まったくちんぷんかんぷんな長い数字を検索してみると、foundが偽であることがわかる。

  • So we can still display even this message to the user in the app.

    だから、このメッセージさえもアプリでユーザーに表示することができる。

  • We do not need to worry at all whether or not the number was found.

    番号が見つかったかどうかを心配する必要はまったくない。

  • So the bottom line is that we need the text and number fields to map to properties in our app.

    要するに、テキスト・フィールドと数値フィールドをアプリのプロパティにマッピングする必要があるということだ。

  • So let's create a class, NumberTrivia, which will extend Equatable.

    そこで、Equatableを継承するクラスNumberTriviaを作成しよう。

  • And let's import Equatable here.

    ここでEquatableをインポートしよう。

  • This is so that value equality is made simple because by default, Dart supports only referential equality.

    デフォルトでは、Dartは参照対等のみをサポートしているからである。

  • So even two objects which contain completely the same data will not be equal unless they are referencing to the same point in memory.

    そのため、完全に同じデータを含む2つのオブジェクトであっても、メモリ上の同じポイントを参照していない限り、等価にはならない。

  • With Equatable, this is completely changed.

    エクイタブルを使えば、これは完全に変わる。

  • When two objects contain the same values, the same data, they will be equal.

    2つのオブジェクトが同じ値、同じデータを含むとき、それらは等しくなる。

  • And we do not need to override equal operator or hash code, anything like that.

    また、等号演算子やハッシュ・コードなどをオーバーライドする必要もない。

  • Equatable does that for us.

    エクイタブルはそれをやってくれる。

  • So it saves us a bunch of boilerplate.

    だから、定型文の手間が省ける。

  • And now we need to store the text and number.

    そして今度は、テキストと番号を保存する必要がある。

  • So final string text, and then final int number.

    つまり、最終的な文字列はテキスト、そして最終的な数値はint。

  • And of course, we need to put them into constructor.

    そしてもちろん、コンストラクターにそれらを入れる必要がある。

  • So we can just hit control dot, at least in VS code, and create constructor for all of these fields here.

    だから、少なくともVSのコードでは、コントロール・ドットを押すだけで、ここにあるすべてのフィールドのコンストラクタを作成できる。

  • But we are not just going to have this kind of a constructor with unnamed arguments.

    しかし、このような無名の引数を持つコンストラクターだけを持つつもりはない。

  • We want to have them named.

    私たちは彼らに名前をつけてもらいたい。

  • And of course, we are going to make them required.

    そしてもちろん、我々はそれを義務付けるつもりだ。

  • So we need to import meta package.

    そこでmetaパッケージをインポートする必要がある。

  • So meta dot Dart.

    だからメタ・ドット・ダート。

  • And let's just make these required.

    そして、これらを必須としよう。

  • And also this one will be required here.

    そして、これもここで必要になる。

  • And we mustn't forget to pass these over to the super constructor, because Equatable needs to know which properties to make equality happen on.

    そして、スーパーコンストラクタにこれらを渡すことを忘れてはならない。Equatableは、どのプロパティで等価性を実現するかを知る必要があるからだ。

  • So we are going to pass them in as a list.

    そこで、リストとして渡すことにする。

  • So we pass in text and also number to the super constructor, which is Equatable.

    そこで、スーパーコンストラクタであるEquatableにテキストと数値を渡す。

  • And you may have noticed that we didn't do any test driven development here.

    そしてお気づきかもしれないが、ここではテスト駆動開発をしていない。

  • That's because this class is really, it doesn't have any logic.

    それは、このクラスが本当に、ロジックを持たないからだ。

  • There is why we aren't writing any tests for this number trivia entity.

    私たちがこの数字のトリビアの実体のテストを書いていない理由がそこにある。

  • Should you have any logic inside your entity, you would write test even for entity, but that's not the case with this one.

    エンティティの中に何かロジックがあれば、エンティティのテストも書くだろうが、この場合はそうではない。

  • All right, now let's talk about use cases.

    では、ユースケースについて話そう。

  • They are where the business logic gets executed.

    ビジネスロジックが実行される場所だ。

  • And sure, there won't be much logic in the number trivia app, because all a use case will do is to get data from a repository.

    ユースケースが行うのは、リポジトリからデータを取得することだけだからだ。

  • So just so you can see that, here we go with the diagram.

    この図を見てほしい。

  • We have use case here.

    ここにはユースケースがある。

  • It will get data from the repository and they will communicate together through these entities.

    リポジトリからデータを取得し、これらのエンティティを通じて相互に通信する。

  • And we have created just one such entity called number trivia a few moments ago.

    そして、私たちは先ほど、ナンバー・トリビアと呼ばれるそのような存在のひとつを作り上げた。

  • And we are going to have two use cases in our finished app, getConcreteNumberTrivia and getRandomNumberTrivia.

    完成したアプリでは、getConcreteNumberTriviaとgetRandomNumberTriviaの2つのユースケースを用意する。

  • By looking at this diagram, as I've already said, you know that use cases get data from repositories, and then they pass that data, which in this case are entities, over to the presentation logic holders and to the whole presentation layer.

    この図を見れば、すでに述べたように、ユースケースはリポジトリからデータを取得し、そのデータ(この場合はエンティティ)をプレゼンテーション・ロジック・ホルダーやプレゼンテーション・レイヤー全体に渡すことがわかる。

  • So it kind of makes sense that when a use case is communicated with repositories, the repository should return an entity, right?

    だから、ユースケースがリポジトリと通信されるとき、リポジトリがエンティティを返すのは理にかなっているよね?

  • But because we have to allow for asynchronous operations, we are going to wrap this entity, which in this case is number trivia, into a future.

    しかし、非同期操作を許可しなければならないので、このエンティティ(この場合は数字の豆知識)をfutureにラップすることにする。

  • But that's not the actual case of what we are going to do.

    しかし、それは実際にやろうとしていることではない。

  • We have to think about error handling as well, because is it the best choice to let exceptions freely propagate?

    例外を自由に伝播させることが最善の選択なのか?

  • Having to remember, and when you have to remember something, you know that that's not cool.

    覚えておかなければならないこと、そして何かを覚えておかなければならないとき、それがクールでないことがわかる。

  • We have to remember to cache them somewhere else in the code if we let exceptions just nicely propagate at their own peril.

    例外をそのまま放置しておくと危険なので、コード内のどこかにキャッシュしておく必要がある。

  • I do not think that this is the best choice.

    これが最善の選択だとは思わない。

  • Instead, we want to catch exceptions as early as possible inside the repository here, and then return failure objects from the repository methods.

    その代わりに、ここではできるだけ早い段階でリポジトリの内部で例外をキャッチし、リポジトリのメソッドから失敗オブジェクトを返したい。

  • So unlike exceptions, you will not have to try and catch all of these exceptions.

    そのため、例外とは異なり、これらの例外をすべてキャッチしようとする必要はない。

  • You will have failure objects, which are returned as regular objects, return types from methods.

    通常のオブジェクトとして返される失敗オブジェクトや、メソッドから返される型がある。

  • There will be no special error flow, nothing like that.

    特別なエラーフローはない。

  • It will be just like a regular data flow without any kind of try-catch-finally blocks in the rest of the app from the repository upwards.

    リポジトリから上のアプリの残りの部分では、try-catch-finallyブロックのようなものはなく、通常のデータフローのようになる。

  • So to recap, repository and then subsequently use cases will return both number trivia objects, and also they will return failure objects from their methods.

    まとめると、リポジトリとそれに続くユースケースは、数字のトリビア・オブジェクトを返し、またメソッドから失敗オブジェクトを返す。

  • So how is something like that possible?

    では、どうしてそんなことが可能なのか?

  • How can we return number trivia or failure from the same method?

    同じメソッドから数字のトリビアや失敗を返すには?

  • Welcome functional programming, and that's why we have imported the darts package over to our app.

    ようこそ、関数型プログラミングへ。それが、ダーツ・パッケージを私たちのアプリにインポートした理由です。

  • This functional programming darts package allows us to simply use an either type.

    この関数型プログラミング・ダーツ・パッケージは、単純にどちらかの型を使うことができる。

  • While I will not pretend that I am some functional programming pro, at least not yet, you don't need to know any really advanced stuff about either type, which is a functional programming concept, will allow us to return either number trivia or failure, which we are going to create next.

    少なくともまだ、私が関数型プログラミングのプロであるかのようなふりをするつもりはないが、関数型プログラミングの概念であるどちらの型についても、本当に高度なことを知る必要はない。

  • Obviously, we still do not have any failure classes.

    もちろん、まだ失敗クラスはない。

  • So let's define them right now.

    では、今すぐ定義してみよう。

  • We are going to create an error subfolder under core, and this will hold failures.dart.

    coreの下にerrorサブフォルダーを作成し、ここにfailures.dartを格納する。

  • And the failure here will be really only a simple class.

    そして、ここでの失敗は、本当に単純なクラスだけだろう。

  • It will be abstract actually, because then later on, we are going to create some concrete implementations of failure objects.

    これは抽象的なもので、後で失敗オブジェクトの具体的な実装を作るからだ。

  • And again, we are not writing this in test-driven development manner, because there is nothing to test in an abstract class.

    抽象クラスにはテストするものがないからだ。

  • So this will be abstract class failure.

    つまり、これは抽象的なクラスの失敗ということになる。

  • Let's again extend equitable, so that the class is extending failure later on, should they have any fields like message or some error code or something like that, their equality will be able to be checked based on those fields.

    equitableを再び拡張して、このクラスが後で失敗したときに、メッセージやエラー・コードなどのフィールドがあれば、そのフィールドをもとに等質性をチェックできるようにしよう。

  • So for that, to use equitable in this abstract base class, we have to have a constructor here, which will accept a list of properties, which will equal const dynamic, which will be an empty list.

    そのため、この抽象基底クラスでequitableを使うには、コンストラクタを用意する必要がある。コンストラクタはプロパティのリストを受け取り、そのリストはconst dynamicと等しく、空のリストになる。

  • And then we will pass this list of properties over to the super constructor.

    そして、このプロパティのリストをスーパーコンストラクタに渡す。

  • This is nothing really to worry about.

    これは本当に心配することではない。

  • This is just what's going on with this Dart analyzer.

    このダート・アナライザーで起こっているのはまさにこれだ。

  • This is just simply the way that things work with equitable.

    これは単に、エクイタブルで物事がうまくいく方法なのだ。

  • So we pass in properties over to the super constructor.

    そこで、スーパーコンストラクタにプロパティを渡す。

  • And again, this is only an abstract class.

    繰り返すが、これは抽象的なクラスに過ぎない。

  • We are going to create concrete classes in the next parts of this course.

    このコースの次のパートでは、具体的なクラスを作成します。

  • Then as you hopefully remember from the last part, and as is signified by this diagram here, a repository from which a use case gets its data is both inside the domain layer and inside the data layer as well at the same time.

    前編を思い出してほしいが、この図に示されているように、ユースケースがデータを取得するリポジトリは、ドメインレイヤーの中にあると同時にデータレイヤーの中にもある。

  • Or to be more precise, the definition of a repository, or as we are going to call it, a repository's contract is present in the domain layer.

    より正確には、リポジトリの定義、あるいはこれから呼ぶように、リポジトリの契約はドメイン層に存在する。

  • This upper half of this gradient is pink or what is this color or whatever.

    このグラデーションの上半分はピンク色で、これは何色なんだ?

  • And then the concrete implementation of a repository, this green side of the gradient is in the data layer.

    そして、リポジトリの具体的な実装は、この緑色のグラデーションのデータ層にある。

  • This will allow for total independence of the domain layer.

    これにより、ドメイン層の完全な独立が可能になる。

  • But there is also another benefit, which we haven't talked about yet.

    しかし、まだ話していない別のメリットもある。

  • And that is testability.

    そして、それがテスト可能性である。

  • That's right.

    その通りだ。

  • Testability and separation of concerns go together extremely well.

    テスト容易性と懸念事項の分離は非常に相性が良い。

  • And this is the absolute beauty of clean architecture because it really complements test-driven development because without architecture, you cannot even test anything because spaghetti code, believe it or not, cannot be tested.

    なぜなら、アーキテクチャがなければ、何もテストすることができないからだ。

  • How will this allow for this?

    これによってどのように可能になるのか?

  • This will be an abstract repository class, will allow us to write tests, test-driven development style, of course, for the use cases, even without having an implementation of the repository.

    これは抽象的なリポジトリクラスとなり、リポジトリの実装がなくても、もちろんユースケースに対してテスト駆動開発スタイルでテストを書くことができる。

  • Something like this is called mocking.

    こういうのをコケにするっていうんだよ。

  • And we are, of course, going to get to that later on.

    もちろん、それについては後で説明するつもりだ。

  • For now, let's create the so-called contract of the repository.

    とりあえず、リポジトリのいわゆるコントラクトを作ってみよう。

  • Inside the domain folder, under repositories, let's create a new file, NumberTriviaRepository.dart.

    domainフォルダのrepositoriesの下に、新しいファイルNumberTriviaRepository.dartを作成します。

  • And inside of here, we will have an abstract class, NumberTriviaRepository.

    この中にNumberTriviaRepositoryという抽象クラスがあります。

  • And this class will have the following interface.

    そして、このクラスは次のようなインターフェイスを持つ。

  • We want to have two methods here, one for getting concrete number trivia, for which we have to pass in a number.

    ここでは2つのメソッドを用意したい。1つは具体的な数字のトリビアを得るためのメソッドで、数字を渡す必要がある。

  • And don't worry, I will come back to the return types in just a bit.

    リターン・タイプについては、また後ほど。

  • So getConcreteNumberTrivia, int number.

    というわけで、getConcreteNumberTrivia, int number.

  • If I could write number.

    もし私が数字を書けるとしたら。

  • And then, of course, it's going to have getRandomNumberTrivia, which will not have any parameters.

    そしてもちろん、パラメータを持たないgetRandomNumberTriviaもある。

  • So let's just rename concrete to random.

    だから、コンクリートはランダムという名前に変えよう。

  • And what is going to be its return type?

    その戻り値の型は?

  • Well, we are going to use that either type, which I have described previously.

    さて、前回説明したどちらのタイプも使うことになる。

  • So let's go bit by bit.

    では、少しずつ行こう。

  • It will, of course, still return a future, because it will be an asynchronous operation to get the concrete or data sources.

    もちろん、コンクリートやデータソースを取得するための非同期操作であるため、フューチャーを返すことに変わりはない。

  • And what's interesting is the type which the future will wrap.

    そして興味深いのは、未来が包むタイプだ。

  • It will be either, which comes from the darts package.

    それはダーツのパッケージから来るものだ。

  • So let's import that.

    だから、それを輸入しよう。

  • And then, either gets two type parameters.

    そして、どちらかが2つの型パラメーターを取得する。

  • One is left, so L, and R for right, of course.

    ひとつは左だからL、右はもちろんR。

  • And the left side is always, for this kind of error handling, the failure.

    そして左側は、この種のエラー処理では常に失敗である。

  • So let's import failure here.

    だから、ここで失敗を輸入しよう。

  • And the right side is always the success kind of data.

    そして右側は常に成功のデータだ。

  • So in this case, it will be the entity number trivia.

    というわけで、今回はエンティティ・ナンバーのトリビアとなる。

  • And we, of course, need to import even that right over here.

    そしてもちろん、その権利さえもこちらに輸入する必要がある。

  • And then this return type will be the same for getRandom number trivia.

    そして、この戻り値の型はgetRandom number triviaでも同じになる。

  • We will cover this in greater detail later on, how to actually work with this either type.

    これについては後ほど詳しく説明する。

  • But for now, just know that this function, this method, will return either a failure, which is the left side, or number trivia, which is the right side.

    しかし今は、この関数、このメソッドは、左側が失敗、右側が数字のトリビアを返すということだけ知っておいてほしい。

  • And this way, we do not have to deal with catching exceptions anywhere else in the app than in the repository, which will convert the exceptions into failures.

    こうすることで、アプリ内のリポジトリ以外の場所で例外をキャッチする必要がなくなり、例外は失敗に変換される。

  • And let's use the nifty little extension for VS Code to fix import, so they will be in the relative manner.

    そして、VS Codeの便利な拡張機能を使ってインポートを修正しよう。

  • Okay, although this part is getting quite long and information-packed already, I do not really wanna leave you hanging.

    さて、この部分はすでにかなり長くなっていて、情報も満載なのだが、私は本当にあなたをぶら下げたくはない。

  • So we are finally going to write some tests while implementing the getConcreteNumberTrivia use case.

    それではいよいよ、getConcreteNumberTriviaユースケースを実装しながらテストを書いていこう。

  • And in the next part, we are gonna add the getRandomNumberTrivia use case.

    そして次のパートでは、getRandomNumberTriviaユースケースを追加する。

  • So definitely stay tuned for that and subscribe to this channel if you do not want to miss it, and also hit the bell button, so that you will get notified about all the new videos.

    もし見逃したくなければ、このチャンネルを購読してください。

  • As is the case with test-driven development, we are going to write the test before writing the production code.

    テスト駆動開発と同じように、本番コードを書く前にテストを書こう。

  • So this will ensure that we aren't gonna add a bunch of unneeded functionality.

    そうすることで、不要な機能を追加しないようにするのだ。

  • This is the YAGNI principle, you ain't gonna need it, which is one of the most powerful things about test-driven development, because it forces you to really think about what you write, because you really do not want to test unnecessary logic.

    これはYAGNIの原則であり、テスト駆動開発で最も強力なことのひとつである。

  • It even doesn't make sense.

    意味さえない。

  • You cannot write unnecessary logic with test-driven development, because you really just do not even think about writing something for future-proofing your code.

    テスト駆動開発では、不必要なロジックを書くことはできない。なぜなら、コードを将来にわたって使えるようにするために何かを書こうとは思わないからだ。

  • And that is the perfect thing about test-driven development.

    そしてそれこそがテスト駆動開発の完璧な点なのだ。

  • So let's get right to it.

    では、さっそく本題に入ろう。

  • Writing the test in Dart apps happens inside the test folder.

    Dartアプリでのテストの記述は、testフォルダ内で行われる。

  • We have a widget test here, we can delete that right now.

    ウィジェットのテストがあるので、今すぐ削除できる。

  • So move to trash.

    だからゴミ箱に移動する。

  • And usually, what we are going to do too, is that test folder structure follows the production code folder structure.

    そして通常、私たちもそうするつもりだが、テスト・フォルダー構造は本番コードのフォルダー構造に従う。

  • So we are going to create all of these folders.

    そこで、これらのフォルダをすべて作成する。

  • So core will go here.

    だから、コアはここに行く。

  • Then also new folder features.

    それから、新しいフォルダーの機能もある。

  • Inside the features folder will be another folder called number trivia.

    featuresフォルダの中には、ナンバー・トリビアという別のフォルダがある。

  • And right now, we are going to write only the use case, so the domain folder would be enough to create here.

    そして今は、ユースケースだけを書くつもりなので、ドメイン・フォルダーはここに作れば十分だろう。

  • But we are going to create all of the other folders as well, so also data.

    しかし、他のフォルダもすべて作成するつもりなので、データも同様だ。

  • And then presentation, just so that we have everything we need for future lessons.

    そして、今後のレッスンに必要なものをすべて揃えるためのプレゼンテーション。

  • So we have data, domain presentation.

    だから、我々はデータ、ドメインのプレゼンテーションを持っている。

  • Inside the domain, we are going to have the use cases folder, and this is where we are going to write our first test.

    ドメインの中に、ユースケース・フォルダーを作り、ここに最初のテストを書く。

  • Tests in Dart are always named the same way as is the production code file, but we append test to the end.

    Dartのテストは、常にプロダクション・コード・ファイルと同じ名前を付けますが、末尾にtestを付けます。

  • So because the production code file will be called get concrete number trivia, the test will be called get concrete number trivia test.dart.

    つまり、プロダクション・コード・ファイルはget concrete number triviaという名前になるので、テストはget concrete number trivia test.dartという名前になる。

  • And again, you can get all of this code from the written tutorial, which is available from the link in the video description.

    繰り返しになるが、このコードはすべてチュートリアルから入手することができる。

  • Writing the test requires a bit of a setup.

    テストを書くには、ちょっとした準備が必要だ。

  • We know that the use case should get its data from the number trivia repository, for which we currently have only the contract, the abstract class.

    このユースケースは、現在、抽象クラスであるコントラクトしか持っていないナンバー・トリビアのリポジトリからデータを取得する必要がある。

  • Because we have only the abstract class, we are going to mock it so that we can add some functionality to it only for this test.

    抽象クラスしかないので、このテストのためだけに機能を追加できるように、モックを作成する。

  • And mocking something also allows us to check whether or not some methods have been called on that object.

    また、何かをモックすることで、あるメソッドがそのオブジェクト上で呼び出されたかどうかをチェックすることもできる。

  • And overall, it really allows for nice testing experience.

    そして全体的に、本当に素晴らしいテスト体験ができる。

  • So without further ado, let's create a class, mock number trivia repository, which will extend mock, which comes from the makito.dart package.

    それでは早速、makito.dartパッケージのmockを継承したクラス、mock number trivia repositoryを作ってみましょう。

  • And then it will, of course, implement first, it needs to implement the number trivia repository.

    そして、もちろん、まずはナンバー・トリビアのリポジトリを実装する必要がある。

  • Let's import even that.

    それさえも輸入しよう。

  • So extending this new class with mock allows us to mock it, of course.

    だから、この新しいクラスをモックで拡張すれば、もちろんモックができる。

  • And then we implement the interface from the number trivia repository abstract class.

    そして、ナンバー・トリビア・リポジトリの抽象クラスからインターフェースを実装する。

  • Let's now also import the flutter test package.

    flutter testパッケージもインポートしよう。

  • So flutter test.dart will go here.

    だからflutter test.dartはここに置く。

  • And now we have to think about how will the use case, which we currently do not even have a file for, and that is perfectly fine with test-driven development, how will the use case operate with the repository?

    そして今、私たちはユースケースをどうするか考えなければならない。ユースケースは現在ファイルすら持っていないが、テスト駆動開発では全く問題ない。

  • Well, of course, it's going to get that repository passed in through the constructor so that later on we can use the getit package to do some nice dependency injection thingies.

    もちろん、コンストラクターを通してリポジトリが渡されるので、後でgetitパッケージを使って依存性注入を行うことができる。

  • This is called loose coupling, and loose coupling is absolutely crucial for test-driven development, because without loose coupling, you cannot test anything, basically.

    これはルース・カップリングと呼ばれるもので、ルース・カップリングはテスト駆動開発にとって絶対に不可欠である。

  • And to pass this mocked version of a repository into the now not yet existent use case, we are going to use a method called setup, which is available for every test that you write in Dart.

    そして、このリポジトリのモックバージョンを、まだ存在しないユースケースに渡すために、Dartで書くすべてのテストで利用できるsetupというメソッドを使います。

  • And the setup method runs before every single test.

    そして、セットアップ・メソッドはすべてのテストの前に実行される。

  • So let's first create void main, because all of the tests run inside this main method.

    すべてのテストはこのメイン・メソッドの中で実行されるからだ。

  • And then we have the setup method here, in which we are going to initialize all the objects we need.

    セットアップ・メソッドでは、必要なオブジェクトをすべて初期化する。

  • But first, we actually have to create the variables in which the objects in question will be stored.

    しかしその前に、問題のオブジェクトが格納される変数を作らなければならない。

  • So what do we want to have here?

    では、私たちはここで何をしたいのか?

  • Well, the now not yet existent get concrete number trivia use case.

    さて、今はまだ存在しない具体的な数字のトリビアのユースケースだ。

  • So we are going to just call it use case.

    だから、ユースケースと呼ぶことにする。

  • And then also the mock number trivia repository will be stored here, so that we can then later on get it and do some mocking on this instance.

    そしてまた、モック・ナンバー・トリビア・リポジトリーもここに保存され、後でそれを取得してこのインスタンスでモックを行うことができる。

  • So inside setup, we're going to first initialize or instantiate, to be precise, the mock number trivia repository.

    セットアップの中で、まずモック・ナンバー・トリビア・リポジトリーを初期化する。

  • So let's create a new instance, just like that.

    それでは、このように新しいインスタンスを作成してみよう。

  • And then we're going to also instantiate the use case.

    そして、ユースケースをインスタンス化する。

  • So get concrete number trivia use case will be instantiated, and the mock number trivia repository will be passed in.

    具体的な数字トリビアのユースケースがインスタンス化され、模擬数字トリビアのリポジトリが渡される。

  • Of course, it doesn't make any sense to continue with writing the test, because currently, it doesn't even compile.

    もちろん、このままテストを書き続けても意味がない。現状ではコンパイルすらできないのだから。

  • So even before writing the actual test, we can do another step in the test driven development, because we have arrived in the red phase.

    つまり、実際のテストを書く前であっても、テスト駆動開発のもう1つのステップを踏むことができるのだ。

  • TDD works in red, green refactor phases.

    TDDは赤、緑のリファクタリング段階で機能する。

  • Red phase is obvious, because we have red squiggly lines.

    レッドフェイズは明らかだ。

  • So we have to fix something in the red phase.

    だから赤の段階で何かを修正しなければならない。

  • And now we want to arrive into the green phase.

    そして今、私たちはグリーン・フェーズに入りたい。

  • And then later on, we will refactor.

    そして後でリファクタリングする。

  • And we are going to arrive into the green phase, which is without errors, by creating the actual get concrete number trivia class.

    そして、具体的な数字を得るためのトリビア・クラスを作成することで、エラーのないグリーン・フェーズに入ろうとしている。

  • So let's create it under domain use cases here.

    それでは、ドメイン使用例の下に作成してみよう。

  • So new file, get concrete number trivia dot dart.

    というわけで、新しいファイル、具体的な数字のトリビア・ドット・ダーツを手に入れよう。

  • And this will be just a simple class for now, get concrete number trivia.

    具体的な数字のトリビアを得る。

  • And it will accept a final number trivia repository called repository into its constructor.

    そして、コンストラクタにrepositoryと呼ばれる最終的な数字のトリビア・リポジトリを受け入れる。

  • So once we import it and create a constructor for missing fields, and fix import so that they are relative, this is the kind of class we have now.

    インポートして、足りないフィールドのコンストラクタを作り、インポートを修正して、フィールドが相対的になるようにすれば、このようなクラスになる。

  • And this is perfectly enough for this test to not complain anymore about non-existent get concrete number trivia use case.

    そして、このテストは、存在しない具体的な数字を得るトリビアのユースケースについて、これ以上文句を言う必要がない。

  • And I probably have a typo here.

    そして、おそらくここにタイプミスがある。

  • Of course, get concrete.

    もちろん、コンクリートで固めてね。

  • So we have to rename that concrete.

    だから、コンクリートの名前を変えなければならない。

  • Now we are talking.

    今、私たちは話している。

  • So now we can test it, anything yet.

    これでテストができる。

  • So let's move on right on to that.

    では、その話に移ろう。

  • The nature of our number trivia app is really simple.

    数字トリビアアプリの性質は実にシンプルです。

  • So there will not be a lot to test here in the use case, because really, all it will do is to just get the number trivia data from the repository.

    というのも、このユースケースでテストすることはそれほど多くないからだ。

  • And that's basically about it.

    基本的にはそんなところだ。

  • It will just get the entity or the failure, of course, from the repository.

    もちろん、リポジトリからエンティティや障害を取得するだけだ。

  • To start writing a test, you can either just write test, and then write should get trivia for number from the repository.

    テストを書き始めるには、ただテストを書いて、それからリポジトリから数字のトリビアを取得する必要がある。

  • Or I have a nice little snippet, which I have created myself, and that is AAA test, which is the arrange, act and assert test.

    あるいは、自分で作成した小さなスニペットで、AAAテスト(arrange、act、assertテスト)がある。

  • So this test should get trivia for the number from the repository.

    だからこのテストは、リポジトリから数字のトリビアを取得する必要がある。

  • And now, of course, we have already the repository instance present in here, which is the mocked instance of the repository.

    そしてもちろん、ここにはすでにリポジトリのインスタンスが存在しており、これはリポジトリのモック・インスタンスである。

  • But we do not have the trivia and we do not have a number.

    しかし、我々はトリビアを持っていないし、数字も持っていない。

  • So let's these variables, we want to have final T number, which is the test number, which we are going to try to get from the repository.

    これらの変数に、最終的なT番号を設定しよう。これはテスト番号で、リポジトリから取得しようとするものだ。

  • So T number is equal to just one.

    つまり、Tナンバーは1つだけということになる。

  • And then final T number trivia is equal to a new instance of number trivia.

    そして、最終的なTナンバー・トリビアは、ナンバー・トリビアの新しいインスタンスに等しい。

  • This is what is going to be returned from the repository.

    これがリポジトリから返されるものだ。

  • We want to have a regular instance of it here.

    ここで定期的に開催したい。

  • So it accepts a number, which will be the T number, or we can actually just pass one in here.

    つまり、Tナンバーとなる数字を受け取るか、あるいはここに1つだけ渡すことができる。

  • It doesn't really matter.

    そんなことはどうでもいいんだ。

  • And then the text will be again, it doesn't matter what the text is.

    そして、またテキストになる。テキストが何であるかは問題ではない。

  • So now in the arrange phase of this test, what we want to do is to provide some functionality to the mocked instance of the repository.

    さて、このテストのアレンジ・フェーズでやりたいことは、リポジトリのモック・インスタンスに機能を提供することだ。

  • So when, and this is really nice, the syntax that is here, because you can really read it as an English sentence and it will all make sense.

    だから、この構文は本当に素晴らしい。

  • So when mock number trivia repository, get concrete number trivia is called on it with any argument.

    そのため、モック・ナンバー・トリビア・リポジトリーでは、任意の引数で具体的なナンバー・トリビアの取得が呼び出される。

  • So it doesn't matter whether or not the number is one or two or three, it can be really anything.

    だから、数字が1でも2でも3でも、本当に何でもいいんだ。

  • So any is a matcher.

    つまり、エニーはマッチャーなのだ。

  • Then answer, because it's asynchronous, so you cannot call then return, but you have to call then answer.

    非同期なので、コールしてからリターンすることはできないが、コールしてからアンサーしなければならない。

  • And the answer will be asynchronous.

    そして、答えは非同期となる。

  • And what do we want to answer?

    私たちは何に答えたいのか?

  • Well, the return type of get concrete number trivia is an either and the right side of the either type is number trivia and the left side is failure.

    さて、具体的な数字のトリビアを取得する戻り値の型はどちらかであり、どちらかの型の右側は数字のトリビア、左側は失敗である。

  • Well, in the test, it doesn't really matter what we return.

    まあ、テストでは何を返そうが関係ない。

  • We can return really either failure or the number of trivia.

    私たちは、本当に失敗するか、トリビアの数を返すことができる。

  • In this case, let's return the number trivia.

    今回は数字のトリビアを返そう。

  • So we want to return the right side of the either type.

    だから、どちらかの型の右側を返したい。

  • This is how we really use it.

    これが本当の使い方だ。

  • And then later on, you can also check whether or not the side of the returned object is left or right.

    そして後で、返されたオブジェクトの側面が左か右かをチェックすることもできる。

  • If it's left, you know that it's a failure.

    左なら失敗だとわかる。

  • If it's right, you know that it's a successful object returned.

    それが正しければ、オブジェクトが正常に返されたことがわかる。

  • So right, let's import darts here.

    では、ここでダーツを輸入しよう。

  • We want to return right the number trivia.

    数字のトリビアに戻りたい。

  • So to go through this again, when the mock number trivia repository, get concrete number trivia method is called with any argument, any number, then always answer with the success response, so to say.

    もう一度説明すると、モック・ナンバートリビア・リポジトリー、具体的なナンバートリビア・メソッドを任意の引数、任意の数字で呼び出すと、常に成功のレスポンスが返ってくる。

  • So the right side of the either with number trivia contained inside of it.

    つまり、どちらかの右側に数字のトリビアが含まれているのだ。

  • All of this is available from the written tutorial.

    これらはすべて、書かれたチュートリアルから入手できる。

  • So definitely, if you want to learn at your own pace, check that out from the link in the video description.

    だから、自分のペースで学びたい人は、ビデオの説明文にあるリンクからチェックしてほしい。

  • Now we move on to the act phase of the test, which is usually really simple.

    さて、テストの演技段階に移るが、これは通常、実にシンプルなものだ。

  • So we just want to store the result of calling the use case.

    つまり、ユースケースを呼び出した結果を保存したいだけなのだ。

  • And we want to call the use case, which is asynchronous.

    そして、非同期のユースケースを呼び出す。

  • So we want to call await use case dot execute.

    そこで、awaitユースケースのドット実行を呼び出したい。

  • And of course, there is no such method yet, because we have not implemented it, because we are doing test-driven development.

    もちろん、テスト駆動開発をしているので、まだそのような方法はない。

  • So we want to call execute on that use case and pass in the number, the number here.

    そこで、このユースケースでexecuteを呼び出し、番号を渡す。

  • Now comes the assert part of the test.

    いよいよテストのアサートの部分だ。

  • So what do we want to check for?

    では、何をチェックすればいいのか?

  • Well, we expect that the result of the execute method on the use case will really be the same thing as was just returned from the mock number trivia repository, because again, the stuff that use case does is really simple.

    さて、ユースケースのexecuteメソッドの結果は、モック・ナンバー・トリビア・リポジトリーから返されたものと本当に同じものだろう。

  • It just gets the data from the repository.

    リポジトリからデータを取得するだけだ。

  • And in the case of number trivia app, it doesn't do anything more than that.

    そして、数字トリビアアプリの場合、それ以上のことは何もしない。

  • So therefore, we expect the result to be right.

    だから、結果が正しいことを期待している。

  • And inside of it, we expect that there will be the number trivia present.

    そして、その中には数字のトリビアが存在すると予想される。

  • And then we also want to verify using the Mockito package.

    そして、Mockitoパッケージを使って検証したい。

  • We want to verify that mock number trivia repositories get concrete number trivia was called with the number.

    モック・ナンバー・トリビアのリポジトリが、具体的なナンバー・トリビアが番号とともに呼び出されたことを検証したい。

  • This is pretty important, because imagine that we pass in the number into the use case.

    これはかなり重要なことで、ユースケースに数字を渡すことを想像してほしい。

  • So just to make it more visually concrete, let's pass in number 20.

    そこで、より具体的にするために、20番をパスしてみよう。

  • But somehow in the use case, some smart guy decided that he will always pass the number 42 over to get concrete number trivia in the repository.

    しかし、どういうわけかユースケースにおいて、ある賢い男が、リポジトリの具体的な数字のトリビアを得るために、常に42という数字を渡すことに決めた。

  • If we did not have this verification here, we would find out about it, of course, because the response would be not correct.

    もし、ここでこの検証をしていなければ、もちろん、そのことがわかるだろう。

  • But this verification adds another layer of protection to our code against these kinds of errors, which do not just pass the correct arguments to the methods of the dependencies of the use case or any other class there is.

    しかし、この検証は、ユースケースや他のクラスの依存関係のメソッドに正しい引数を渡すだけではない、この種のエラーからコードを保護するもうひとつのレイヤーを追加する。

  • So let's again, revert back to the number.

    そこでもう一度、数字に話を戻そう。

  • And finally, we are just going to verify no more interactions are happening in the on the mock number trivia repository, because once we call execute, the use case should not do anything more with the repository.

    そして最後に、モック・ナンバー・トリビア・リポジトリでこれ以上インタラクションが起こらないことを確認します。

  • There is again, no point in even running this test, because it's not going to run since it doesn't even compile.

    コンパイルさえしていないのだから、このテストを実行する意味はない。

  • We have a compilation error here that execute is not present on the use case.

    ユースケースにexecuteが存在しないというコンパイルエラーが発生しました。

  • This test really acts like a documentation for the functionality, which we are about to implement.

    このテストは、これから実装しようとしている機能のドキュメントのような役割を果たす。

  • So let's jump right into that.

    では、さっそくその話に飛び込もう。

  • We're going to go to get concrete number trivia and start writing the implementation of execute method.

    具体的な数字のトリビアを取りに行き、executeメソッドの実装を書き始める。

  • So it will return future either, which contains failure or number trivia.

    つまり、失敗か数字のトリビアを含む未来のどちらかを返すことになる。

  • So we need to import all of these types over here.

    だから、これらのタイプをすべてインポートする必要がある。

  • Once we give this method a name, execute.

    このメソッドに名前をつけたら、実行する。

  • So let's import darts, let's import failures, and let's import number trivia.

    だから、ダーツを輸入し、失敗を輸入し、数字のトリビアを輸入しよう。

  • Now based on the test, we know that execute method should take in a number, which is a named parameter.

    さて、テストに基づいて、executeメソッドは名前付きパラメータである数値を受け取るべきだとわかった。

  • So therefore, we know what we need to do.

    だから、何をすべきかは分かっている。

  • It will have a named required, of course.

    もちろん、名前が必要だ。

  • So we need to import meta also, meta.dart, required number, which is an integer.

    そこで、meta.dartもインポートする必要がある。meta.dartは整数であることが必要だ。

  • And it's going to just call the repository that get concrete number trivia with the number.

    そして、具体的な数字のトリビアを取得するリポジトリを番号で呼び出すだけだ。

  • And of course, we need to return a weight, whatever was gotten from the repository.

    そしてもちろん、リポジトリから取得したウェイトを返す必要がある。

  • So this function needs to be itself asynchronous.

    そのため、この関数自体が非同期である必要がある。

  • All right.

    分かった。

  • So this is the implementation for the execute method.

    これがexecuteメソッドの実装だ。

  • And now all we need to do is to run the test.

    あとはテストを実行するだけだ。

  • I have a handy shortcut, keyboard shortcut for running all of the dart tests.

    すべてのダーツテストを実行するための便利なショートカット、キーボードショートカットがある。

  • So I will show you how to do that.

    だから、その方法を紹介しよう。

  • If you are using VS Code, of course, in IntelliJ, this would be completely different.

    もちろん、IntelliJでVS Codeを使っているなら、これはまったく違う。

  • But in VS Code, go to file, preferences, keyboard shortcuts, and now search for dart run all tests.

    しかし、VS Codeの「ファイル」→「環境設定」→「キーボード・ショートカット」で、「dart run all tests」を検索してほしい。

  • And for this command, just set some key binding.

    このコマンドでは、キーバインディングを設定するだけだ。

  • I have shift, alt, and left square bracket.

    シフト、オルト、左の角括弧を持っている。

  • So once you have this shortcut, you can run all of the tests with shift, alt, and left square bracket.

    このショートカットがあれば、シフト、オルト、左の角括弧ですべてのテストを実行できる。

  • We have only one test, of course.

    もちろん、テストはひとつしかない。

  • And it's going to pass.

    そして可決される

  • So we should get trivia for the number from the repository.

    というわけで、リポジトリから背番号のトリビアを入手しよう。

  • This is only a simple test.

    これは簡単なテストに過ぎない。

  • That's because the functionality of the get concrete number trivia use case is also simple, but it in our code.

    というのも、具体的な数字のトリビアを得るユースケースの機能もシンプルだが、私たちのコードではそうなっているからだ。

  • And the other way to run a test is to go over to the debugging tab here in VS Code.

    テストを実行するもうひとつの方法は、VS Codeのデバッグ・タブに移動することだ。

  • Now tap on this configure or fix launch.json here icon.

    ここで、このconfigureまたはfix launch.jsonアイコンをタップする。

  • Ignore .NET if something like that pops up.

    .NETを無視してください。

  • And we want to add configuration.

    そして、コンフィギュレーションを追加したい。

  • So dart run all tests.

    だからダートはすべてのテストを実行する。

  • All right.

    分かった。

  • And with this configuration present in the launch.json file, you can now select dart run all tests from the dropdown in the debug tab of VS Code.

    launch.jsonファイルにこの設定があれば、VS Codeのデバッグ・タブでdart run all testsを選択できる。

  • So once you do that, you can run all tests even by clicking this green start debugging button.

    そうすれば、この緑のデバッグ開始ボタンをクリックするだけで、すべてのテストを実行できる。

  • And again, it will pass because the same test was run again.

    そしてまた、同じテストが再び実行されたため、合格となる。

  • In the next part, we are going to add another use case for getting the random number trivia.

    次のパートでは、乱数のトリビアを得るための別のユースケースを追加する。

  • And also we are going to refactor this code and also the new use cases code so that it will be more robust.

    さらに、このコードと新しいユースケースのコードをリファクタリングして、より堅牢にするつもりだ。

  • So definitely stay tuned for that.

    だから絶対に期待していてほしい。

  • And if you don't want to miss the next part and also more tutorials like this, definitely subscribe to this channel and also join the notification squad by hitting the bell button to make sure you grow your Flutter coding skills because here on ResoCoder, I am determined to provide you with the best app development tutorials and resources out there.

    そして、もしあなたが次のパートやこのようなチュートリアルを見逃したくないのであれば、ぜひこのチャンネルを購読し、ベルボタンを押して通知部隊に加わり、あなたのFlutterコーディングスキルを確実に成長させてください。

  • If this video helped you with understanding at least just a bit test-driven development process, and do not worry, we are going to write many, many more tests throughout this series.

    このビデオを見て、テスト駆動開発プロセスを少しでも理解していただけたなら、このシリーズを通して、もっともっとたくさんのテストを書いていきますので、ご心配なく。

  • Give this video a like and also share it with our developers who will surely benefit from it as well.

    このビデオに「いいね!」を押して、開発者たちにもシェアしてください。

  • Leave a comment if you have anything to say, any questions regarding this test-driven development, I will try to answer them to my best ability.

    このテスト駆動開発について何か言いたいことや質問があれば、コメントを残してください。

  • Follow me on Instagram, I go under the name ResoCoder everywhere so that you get some behind-the-scenes news from what I am currently doing, and see you in the next video.

    インスタグラムで私をフォローしてください。私はどこでもResoCoderという名前で活動しているので、私が今やっていることの舞台裏のニュースを得ることができます。

In the first part, you learned the core concepts of clean architecture as it pertains to Flutter.

最初のパートでは、Flutterに関連するクリーンアーキテクチャのコアコンセプトを学んだ。

字幕と単語
AI 自動生成字幕

ワンタップで英和辞典検索 単語をクリックすると、意味が表示されます