
Introduction of the Friends project
This is the beginning of the course that will go through the process of building an entire product. We start off by scratching out the initial project outlines, creating the Android client project, and setting up the CD.
In this video we go through the process of creating a signing configuration (keystore) and how to use it to sign a release version of an application.
In this lecture, we are going through the steps required to make automated publishing to Google Play Store. We will introduce the deployment pipeline to enable continuous delivery so that once we push our work on the remote repository, it will be deployed (in this case on Google Play)
In this lecture, we set up the deployment script to run both Unit and UI tests as a requirement before publishing to Play Store. The UI tests are leveraging the Firebase Test Lab to run on a real physical device, and we walk through the actual setup required on the Firebase Console side to be able to run the tests.
A little side note: the configuration that we are writing in the video will most probably be slightly outdated at the time you are learning this, and that is because most of the things inside the script that run the GitHub action are actions that are maintained and changed over time. I will try to keep the script up to date in the GitHub repository, but also here in the resources section. There is a downloadable file named `deploy.yml`. So make sure you look into it when writing your own, and don't hesitate to reach out to me if you end up having problems.
Also, find some useful links mentioned in the video in the external resources section.
In this lecture, we set up the UI testing dependency and we write our first UI test. We start from the test before any actual UI is written so that we can use the test to guide us toward what to work on next.
In this lecture, we start working on the Signup screen so that we can have a form to create an account. We get an initial grasp of how it feels to write UI using Jetpack Compose, and it seems super fun.
In this lecture, we are working around a bug we found (and reported) in the JetpackCompose testing SDK.
Next, we apply some UI improvements on the SignUp screen, and ultimately, we are setting up the JUnit5 to be ready to jump straight into the sign-up business logic right in the following lecture.
In this lecture, we are test-driving the credentials validation as part of the signup business logic. We use regex to verify if the email and the password are valid as a sign-up arguments
In this lecture, we are test-driving the signup. We manage to cover the positive path for creating an account. We ended up emerging a few components with different responsibilities. We observe the design evolving nicely.
In this lecture, we introduce the Jetpack Compose Navigation and leverage it to navigate from the SignUp towards the Timeline screen upon successful account creation.
In this lecture, we introduce Koin as a dependency injection container, and we managed to complete the UI test that verifies displaying of the error message when the user attempts to create a duplicate account.
In this episode, we write more tests to make sure the UI is reacting properly to the different states, particularly backend errors, offline errors, or bad credentials.
In this lecture, we are working on making the signup screen look nice and polished. We introduce some animation which seems to be quite easy with Jetpack Compose. We made a nice improvement by decoupling the screen state from the actual composable into a standalone class.
In this lecture, we work on resetting the bad email and bad password error state from the corresponding composable upon its value gets changed (i.e the user continues to type).
In this lecture, we are preparing the business logic to allow us to show an indication for a long-running operation. We start off by making sure the ViewModel sends to the UI a state that represents an ongoing operation that might take some time. Later on, we will decide how we are going to represent that in the UI.
In this lecture, we make sure we display a blocking loading while a long-running operation is going on. We also make sure the blocking loading composable animates nicely between showing and hiding and with that we are wrapping up the signup screen, getting us ready to focus on the Timeline.
In this lecture, we start working on the Timeline. We directly jump into the business logic and start emerging some of the essential parts like the ViewModel as a bridge between the UI and the domain, and the Post as a domain model.
In this lecture, we are emerging the algorithm for fetching the timeline posts for a given user.
The idea is that the timeline should include the posts of the user itself and the posts of the folks the user is following.
In this lecture, we are completing the refactoring that we started in the previous lecture. We are pushing the data from the shipping code toward the tests so that the abstractions will live in the shipping code, and the data will stay in the tests.
In this lecture, we are handling the negative cases when loading the timeline. We emerge another collaborator and align the levels of abstraction nicely.
At this point, we start working on the timeline UI. We do the required wiring and we put our focus on the navigation between the signup and the timeline
In this video we start shaping the Timeline which gets capable of showing the posts in a scrollable list
The timeline now allows us to navigate to the posts composer which at this moment doesn't do anything.
The TimelineViewModel is delivering all the UI states to the observers (the screens), and the loading of the timeline is done in the background thread
The Timeline shows the loading indicator, as well as the error messages. We managed to improve the InfoMessage to handle the showing/hiding by itself and removed the duplication from the screen states.
In this lecture, we start working on creating the posts.
The posts are dealing with 2 elements of randomness (postId and timestamp) that we need to be able to control from the tests. So some interesting ideas are popping up. We already had a chance to do a little refactoring, leaving some more refactoring for the following episode!
In this lecture, we continue the refactoring we've started in the previous one - dealing with the elements of randomness.
The Post consists of "postId" and "timestamp" which are the elements of randomness, and we have to be able to control them for testing purposes.
In this lecture, we almost finish the post-creation business logic. We figured out a bunch of duplicated test doubles that we want to consolidate in the following episode. A lot of refactoring, a lot of reasoning, and a lot of fun!
Just as we planned in the previous lecture, In this lecture, we are dealing with some duplication for the test doubles, and wrapping up the business logic behind creating a post.
All the required UI states are delivered to the observers, and all the operations are offloaded from the main thread.
In this lecture, we start working on the UI of the Post composer. We have significant progress but still a lot to do to complete it.
In this lecture, we are adding contract tests to make sure the PostCatalog implementations behave the way their clients expect.
In this lecture, we complete the happy path for composing a post, and we make sure the user can create as many posts as they want to.
We finalized the Post Composer and made It fully functional. The first half of the app is almost done!
In this lecture, we are finally addressing the storage of the logged-in user data. Additionally, we are touching a bit on the Friends section of the app, and we have a good intro for the following lecture!
In this lecture, we are introducing bottom navigation so that we can navigate between the timeline and the friends sections of the app
In this lecture, we start working on the business logic to load the friends.
We start test-driving the code by introducing yet another technique in the TDD world called TDD ZOMBIES.
Check out the resources section for more information about the TDD ZOMBIES
In this lecture, we are focusing on the not-so-common output/result that might occur.
Those are the situations when the backend throws an error on us, or the user's device might be in an offline state.
These are legitimate situations and we need to handle them properly.
In this lecture, we complete the business logic to load the content for the People section, so that we can focus next on the UI. Or can we?
In this lecture, we are getting back on the right track, recovering from a design mistake we've done in some of the previous episodes.
This lecture complies with the well-known sentence: "Make the change easy (note this might be hard). Then make the easy change"
In this lecture, we start building the UI for the Friends section. It seems like it will take us a bit of time, but we have a great start.
In this lecture, we continue our journey into the FriendsScreen composable and we started shaping the list of friends nicely.
Meanwhile, we made a decision on the uncertainty we had in the previous video to exclude the user who owns the account from the friend list.
In this lecture, we are dealing with the different screen states in the Friends Screen. We introduce a pull-to-refresh mechanism for the list, as well as error messages for the error states.
In this lecture, we are working on storing and restoring the state over process death by leveraging the SavedStateHandle from the "androidx.lifecycle" package.
In this lecture, we are adding the functionality to toggle the following between the users, so that they can follow and unfollow each other.
The content in the Timeline depends on the friends a user follows.
In this lecture, we work on showing the current following state for the friends (Follow, Unfollow) and showing a little progress indicator when toggling the friendship.
In this episode, we wrap up the error handling for updating the following for friends, and also wrap up the initial set of functionalities planned for the initial version of the Android client of the app.
Next up: We will be focusing on the backend!
The objective of this course is the eXtreme Programming practices, particularly the technical ones. By the end of the course, you'll become comfortable with Test-Driven Development, Refactoring, Evolutionary Design, and Continuous Integration.
The instructor happens to work on an Android application throughout the course, but the technical knowledge, the practices, and the tips you will get from the lectures are applicable regardless of the language or the technology you are using.
As an extra, if you are an Android developer, you will also learn the basics of Jetpack Compose, and you'll get comfortable writing UI by using it. The course is targeting students with various experiences. There is certainly a lot of learnings in this course for both junior and senior developers.
By the time this course was created initially, certain technologies like Jetpack Compose were not stable. However, as they were evolving, they were being updated and re-explained in the course, even though the main focus of the course is not a particular technology, but rather good software development practices.
What's also very important, this course takes into consideration the gender and race-neutral position and makes sure that all the students feel welcome and comfortable following it. The instructor is going to be available for help throughout the entire course, as well as after finishing it.