How to Validate Forms with Clean Architecture (You're Doing it Wrong)

  Рет қаралды 45,918

Philipp Lackner

Philipp Lackner

Күн бұрын

Learning clean architecture can be tough. In this video I'll show you how you can solve the very common problem of validating forms by properly following the clean architectural guidelines.
⭐ Get certificates for your future job
⭐ Save countless hours of time
⭐ 100% money back guarantee for 30 days
⭐ Become a professional Android developer now:
pl-coding.com/premium-courses...
Subscribe to my FREE newsletter for regular Android, Kotlin & Architecture advice!
pl-coding.com/newsletter
Join this channel to get access to perks:
/ @philipplackner
Get the source code for this video here:
github.com/philipplackner/Cle...
Join my Discord server:
/ discord
Regular programming advice on my Instagram page: / _philipplackner_
Checkout my GitHub: github.com/philipplackner
You like my free content? Here you can buy me a coffee:
www.buymeacoffee.com/philippl...

Пікірлер: 96
@sideness4938
@sideness4938 2 жыл бұрын
Thanks for including the test part. That's always missing in dev videos!
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Glad to help!
@lalobarrios16
@lalobarrios16 2 жыл бұрын
Hi Phil, Thank you for this great content. Just a quick revision when you do the following: if(hasError) { state = state.copy( emailError = emailResult.errorMessage, passwordError = passwordResult.errorMessage, repeatedPasswordError = repeatedPasswordResult.errorMessage, termsError = termsResult.errorMessage ) return } The state should be modified regardless of an error here. While I was watching the video at the end you get the toast and the emailError is still not null because of hasError being false. So the state modification should get extracted out of that block and placed before the hasError check: state = state.copy( emailError = emailResult.errorMessage, passwordError = passwordResult.errorMessage, repeatedPasswordError = repeatedPasswordResult.errorMessage, termsError = termsResult.errorMessage ) if(hasError) { return }
@yasserakbbach7342
@yasserakbbach7342 2 жыл бұрын
Nice catch 👌
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Correct, thanks :)
@abdremo
@abdremo 2 жыл бұрын
@sh3r1p49
@sh3r1p49 2 жыл бұрын
Another quality tutorial from Phillip! Thank you man!
@rileyfarro6801
@rileyfarro6801 2 жыл бұрын
You speak calmly and you remind me of Bob Ross, but showing expertise in Android development. What a great video 😁
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Hahaha thanks mate!
@arielapp9469
@arielapp9469 2 жыл бұрын
Great video. Regarding unit testing, isn't it better to use interface impl pair for the use cases? Also, when asserting values, when you use assertEquals, the first parameter should be the value you expect, and the second value should be the value that you test. Regardless, when you test booleans, you can use assertTrue and assertFalse.
@s-w
@s-w 2 жыл бұрын
I prefer to create an after text changed listener on the edit texts that saves all the edit texts each time any text is changed. All the text is then tested in the use case and the returned messages are reviewed within the UI with a "when" bracket that will only show one message at a time. When there are no messages to show, the last option in the "when" bracket will enable the button to be clickable.
@Rafael-hk9pg
@Rafael-hk9pg Жыл бұрын
So you change the state based on the message and not on a Event.. ?
@s-w
@s-w Жыл бұрын
The state changes any time any of the edit texts change. If there's an issue, the variable in the state for that edit text will have a message or it will be null if it passes the chack. So the when statement will stop at the first variable with a message and do what you want it to do in that instance. If there are only nulls remaining in the state, the else branch in the when statement can make the confirm button enabled. But you have to make sure to make it disabled each time the text changes until all the data is validated.
@StevdzaSan
@StevdzaSan 2 жыл бұрын
Nice video bro 👌 I like the use of Channels, they seem quite good in a combination with Compose.
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Thanks bud! Yeah it's the only real way to receive events in the composable (other than SharedFlow)
@ChrisCologne84
@ChrisCologne84 5 ай бұрын
@@PhilippLackner Why you use a Channel and not a StateFlow or mutableStateOf?
@liosha2007
@liosha2007 2 жыл бұрын
Thanks a lot. Very interesting and useful video 👍
@AfriandiHaryanto
@AfriandiHaryanto 2 жыл бұрын
One of my favorites about kotlin is, its Sealed Class. And I think it suits best for this kind of case. I created sealed class with children of every possible outcome, make domain layer don't care about wording and let presentation layer map it.
@PhilippLackner
@PhilippLackner 2 жыл бұрын
I love it too
@AfriandiHaryanto
@AfriandiHaryanto 2 жыл бұрын
@@PhilippLackner Wow, it's an honor to get replied by you. 😂 I had been watching many of your videos to learn android..
@bajrangchapola6748
@bajrangchapola6748 2 жыл бұрын
Great content again. Thanks for making such wonderful video. Complete this video by making network call handling success and failure case. How to propagate error to UI .
@emmanuelpregnolato5026
@emmanuelpregnolato5026 2 жыл бұрын
Excellent as always. We could add on the TextFields a maxLines = 1 and singleLine = true otherwise we could have many lines or an ' '
@pereyrarg11
@pereyrarg11 Жыл бұрын
very helpful, Thank you!
@mr-re1ax
@mr-re1ax 11 ай бұрын
Duuuuuuude! This is supper cool example! Respect!!!
@chips056
@chips056 2 жыл бұрын
Hello there, great and pretty complete video! Thank you for your hard work Philipp I have a question: how do you End-to-End test it? I explicitly followed this video and the one with testing (linked to your Note app) and whenever I ask the test to click on the Submit button and check if I have a new Text() displayed (with the explicit error), my test fails since it doesn't seem to reload the layout. Did it already happen to somebody?
@Ayor88
@Ayor88 3 ай бұрын
I've mix this video and the "This Is My FAVORITE Error Handling Class" one to valid custom user input and it work greats !
@shreyashachoudhary480
@shreyashachoudhary480 Жыл бұрын
Amazing quality content!
@czerewacz
@czerewacz 2 жыл бұрын
Super PRO Champions League content Phillipp! Thanks!!
@kokolight2
@kokolight2 2 жыл бұрын
I have a weird question. Is there any chance that when using a state hosted in the viewmodel or in a data class as we did in this tutorial, the UI is rendered slower? For example, when I am creating a Switch, if I create the state in the same file of the Switch composable, the switch toggles fast. But whenever I host the state in the viewmodel as you described here, looks like it has a minor delay when I click the Switch. Do you know anything that can affect that? By the way, awesome tutorial!
@kaletsugas
@kaletsugas 9 ай бұрын
Hi Philipp, does this way of using state recomposes everything whenever you type a character on the textfields? Is there a more optimized way?
@mustafaammar551
@mustafaammar551 2 жыл бұрын
Very cool video Thank you Bro You are the best 👍👍👍🔥🔥🔥
@moldovanpeter5123
@moldovanpeter5123 2 жыл бұрын
Hi, can you tell me an exact case when should we use SharedFlow (I watched some previous videos and you use them only for 1 observer(UI)), you mentioned it must have multiple observers. I just want to have a more accurate overview because there is another video where you compare LiveData vs Flows but also falls into the 1 observer category. Thanks.
@dkk0011
@dkk0011 2 жыл бұрын
Hi @Phil, Any way can we improve recomposition, Here for any one of field value change all other fields also effecting .
@adriencuisse9641
@adriencuisse9641 2 жыл бұрын
Setting error messages in the use case is definitely not clean architecture, interactor response should only contains litterals like boolean error flags, the presenter is responsible for error strings, and it's not in application layer.
@sebastianpalm3495
@sebastianpalm3495 8 ай бұрын
really really good video one gently critic the error message should disappear when the user is editing the input field. Thanks a lot for the video!! :))
@mattgraves3709
@mattgraves3709 2 жыл бұрын
We should step into DDD with a solid Use Case in MVVM, then convert to vertical slice architecture with a few independently buildable and testable modules...then we are styling Phil.
@Rafael-hk9pg
@Rafael-hk9pg Жыл бұрын
How do you handle a 'loading' state? When the submit button is pressed, I would like to show a spinner and disable all input fields
@yesayasoftware
@yesayasoftware 2 жыл бұрын
Philipp this is a very nice tutorial that... Thanks
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Glad you liked it!
@vijayjangid8967
@vijayjangid8967 23 күн бұрын
Thanks Philipp
@sh3r1p49
@sh3r1p49 10 ай бұрын
Hi Phillip, How could you handle multiple fields for example 5 swipeable pages with 10 fields on each page?
@06rokib
@06rokib Ай бұрын
What is the way to make the error messages support translation? Context can not be passed in use cases since these are designed to be independent of the platform.
@rohithkumar8755
@rohithkumar8755 2 жыл бұрын
Hii phil, thanks for the tutorial iam facing the issue like after succesful validation it is showing toast message pls provide me the solution.thanks
@lucachrist5146
@lucachrist5146 6 ай бұрын
Hey great Video, how can I reset the Flow so I can validate the next inputs after
@ubersticks
@ubersticks 2 жыл бұрын
Is it a good idea to expose mutable state from the ViewModel? Perhaps use "private set"?
@taknikiniga
@taknikiniga 2 жыл бұрын
unable to import mutableStateOf in my xml android project any alternative
@azemzejnilovic2893
@azemzejnilovic2893 2 жыл бұрын
Do you have this but without Jetpack?
@gadeern1586
@gadeern1586 Жыл бұрын
Thank you for the great content 🌻 But if we need to access the string resources what the use case will looks like?
@jeghamaymen
@jeghamaymen Жыл бұрын
i am using a pure java and kotlin module for the domain layer so i'm doing the validation in the datasource class (data layer) and injecting that in the usecase class...
@OrlanDroyd
@OrlanDroyd 2 жыл бұрын
Great 👌
@L4szcZ
@L4szcZ 4 ай бұрын
Your example shows that you are using strings in usecase. I think what you missed is that we need to map useCase to presenter object. Beacuse in standard compay project you would like to have strings in string resources.
@smiley-zu5hn
@smiley-zu5hn Жыл бұрын
Hi I hope you can Answer my question. I am following your steps but at the last part I get lost because I have an layout xml and I dont know how to connect it and use the validations. I hope you can help me thank you. New subscriber
@dev_jeongdaeri
@dev_jeongdaeri 2 жыл бұрын
Super cool 😎
@bitwisedevs469
@bitwisedevs469 2 жыл бұрын
I think it is supposed to be assertEquals(false, result.successful)? Since the second param is `actual`
@harisiqbal3986
@harisiqbal3986 2 жыл бұрын
Hi Phillip, which theme you are using for android studio
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Xcode dark
@amineayachi335
@amineayachi335 2 жыл бұрын
thanks
@hariharanrc6192
@hariharanrc6192 2 жыл бұрын
Bro can you teach about how to use socket io using mvvm clean architecture pattern as there was no videos about socket io. It may help ful for my career as I came to android development by seeing your videos and I am be an good android developer because of you bro. If you don't mind can you teach us about socket io?
@gondaimgano
@gondaimgano 2 жыл бұрын
I wish Jetpack Compose could have a Form widget just like Flutter which could remove the amount of boilerplate code to create such.
@RenatoSousaRS
@RenatoSousaRS 2 жыл бұрын
very nice!!!
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Thanks!!
@joojitaold
@joojitaold 2 жыл бұрын
22:00 What should I do if I have a large number of textfields? Should I repeat the proccess for each one still?
@PhilippLackner
@PhilippLackner 2 жыл бұрын
If you strictly want to follow clean architecture, yes. However, you might be able to reuse some use cases, for example if the logic for validating first names and last names is the same, then you might just use one ValidateName use case
@joojitaold
@joojitaold 2 жыл бұрын
@@PhilippLackner wow thanks for responding so quickly
@NghiaNguyen-vn9wl
@NghiaNguyen-vn9wl Жыл бұрын
Could you guide full test course for android?
@MaxTurchin
@MaxTurchin 2 жыл бұрын
Hello! Why are you using JUnit4 over 5? Thanks for your videos!
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Doesn't give you many benefits, but requires some setup. In the end I want to run tests, that's it. And JUnit4 works perfectly for that. And AFAIK, JUnit5 doesn't work for instrumented tests
@miltonpimentel3769
@miltonpimentel3769 2 жыл бұрын
Hey, I'm from Brazil and I love your videos, but I always miss something. unit test A suggestion, whenever possible add unit tests
@PhilippLackner
@PhilippLackner 2 жыл бұрын
I have a whole playlist about testing
@jeromealtariba7339
@jeromealtariba7339 2 жыл бұрын
Hi nice thks. Didn't understand your comment on "abstracting the test on valid Email to avoid using Patterns in the validation class". What do you mean by that ?
@PhilippLackner
@PhilippLackner 2 жыл бұрын
The Patterns class comes from the Android framework. In local unit tests as we did it here, you can't use Android dependencies, so you need to write some kind of abstraction (interface) for this pattern stuff. For example like this: interface PatternValidator { fun isValid(pattern: String): Boolean } class EmailValidator: PatternValidator { override fun isValid(pattern: String): Boolean { return Patterns.EMAIL_ADDRESS.matcher(pattern).matches() } } Then you can pass a PatternValidator to your use case and use it without having the Patterns import in the use case. That way it stays unit testable.
@jeromealtariba7339
@jeromealtariba7339 2 жыл бұрын
@@PhilippLackner very clear thks
@jeghamaymen
@jeghamaymen Жыл бұрын
@@PhilippLackner how can we avoid using string ressources in the usecase where this should only be in a pure kotlin module ?
@aguiarroney
@aguiarroney 2 жыл бұрын
Why did you choose channel instead of LiveData? Great video, by the way!
@pa1shetty
@pa1shetty 2 жыл бұрын
It will be emitted when activity re-creates ( scree rotation, theme change) . Correct me if I'm wrong.
@leryan07
@leryan07 Жыл бұрын
You were right, I was doing it wrong lol
@MohammedElotol
@MohammedElotol 2 жыл бұрын
Great work! it is better to call it EmailValidator instead of ValidateEmail
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Nah, that's kind of the convention for a use case, since you can execute them. It therefore makes more sense to think of them like a function, not like a class
@MohammedElotol
@MohammedElotol 2 жыл бұрын
@@PhilippLackner good point of view
@gofudgeyourselves9024
@gofudgeyourselves9024 2 жыл бұрын
ok bro
@ExploraByte
@ExploraByte 2 жыл бұрын
Thanks for a great video and great content, can you make a video on how to implement firebase auth and firebase with clean architecture and jetpack compose
@tiltedbybox6118
@tiltedbybox6118 2 жыл бұрын
Btw your instagram links are broken everywhere on youtube (video desc and on channel social media buttons)
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Thanks man, because I changed the name. I'll fix it later. Appreciated
@jellybeast4408
@jellybeast4408 2 жыл бұрын
where is the link from 11:52? also your insta link is dead 😸 luv ur videos btw!
@kawsarhossain8931
@kawsarhossain8931 2 жыл бұрын
⭐⭐⭐⭐⭐
@quantumgaming7
@quantumgaming7 2 жыл бұрын
Thanks but I’m never gonna use this 😂😂😂 it is actually way too overkill just to validate Authentication fields and if the forma is very big then the number of files gonna overkill just for a single form submission.
@PhilippLackner
@PhilippLackner 2 жыл бұрын
Overkill in a small app? Yes. Necessary to make big apps scale further? Absolutely.
@aliffridzuan88
@aliffridzuan88 2 жыл бұрын
bloc architecture...
@kajosan79
@kajosan79 Жыл бұрын
What a nasty manner of not putting a space between if and the parenthesis.
@animehub883
@animehub883 3 ай бұрын
when programming , show me the best practices, u not doing that , don't like that attitude sheesh
@user-vv8wq7wm8n
@user-vv8wq7wm8n 8 ай бұрын
channel shouldn't' be use here right ?? its bug prone.
@jjhoninatan55sabadi
@jjhoninatan55sabadi 2 жыл бұрын
on UseCase you could use "operator fun invoke()", than call on ViewModel like function: validateEmail(email)
@bboydarknesz
@bboydarknesz 2 жыл бұрын
I think this would be more readable way for MVVM when click button and Submit is success, then action. Instead handle the next action on top and hard to read. ex: Button(onClick = { viewModel.onEvent(Event.Submit) { gotoNextFragment() } }) but I don't know, I try it but not very clean in VM. WDYT? waiting for you video if you like this way. :D thank youu
@PhilippLackner
@PhilippLackner 2 жыл бұрын
But not every event you send to the VM returns success/failure, so that would only help for those that have
@nipunkumarit2168
@nipunkumarit2168 2 жыл бұрын
Return me ❤️❤️❤️
5 Fatal Coroutine Mistakes Nobody Tells You About
18:15
Philipp Lackner
Рет қаралды 86 М.
Should You Use Compose State or StateFlow in Your ViewModels?
13:59
Philipp Lackner
Рет қаралды 74 М.
Survive 100 Days In Nuclear Bunker, Win $500,000
32:21
MrBeast
Рет қаралды 101 МЛН
1,000 Diamonds! (Funny Minecraft Animation) #shorts #cartoon
00:31
toonz CRAFT
Рет қаралды 40 МЛН
Fast and Furious: New Zealand 🚗
00:29
How Ridiculous
Рет қаралды 45 МЛН
Smart Sigma Kid #funny #sigma #memes
00:26
CRAZY GREAPA
Рет қаралды 2,7 МЛН
Architecture: The Domain Layer - MAD Skills
8:48
Android Developers
Рет қаралды 56 М.
This Is My FAVORITE Error Handling Class
28:57
Philipp Lackner
Рет қаралды 28 М.
Everything you need to know about Kotlin 2.0 🟣
11:05
Stevdza-San
Рет қаралды 62 М.
This is the Only Right Way to Write React clean-code - SOLID
18:23
THIS Compose-State Mistake Leads to Problems In Your Code
7:58
Philipp Lackner
Рет қаралды 40 М.
ViewModels & Configuration Changes - Android Basics 2023
18:46
Philipp Lackner
Рет қаралды 110 М.
Survive 100 Days In Nuclear Bunker, Win $500,000
32:21
MrBeast
Рет қаралды 101 МЛН