I am working on an Android project where MVVM is the architecture being used. There is a use case where a Flow in my Repository needs to be updated based on the results of a callback which is triggered when something in my Data Source changes. The most appropriate choice for this problem seems to be callbackFlow. However, it is still experimental. I am very tempted to use callbackFlow, however, I understand that any future changes might break some code and I don't want that to happen in a production app. Considering the above scenario, what should be a replacement for callbackFlow? Or should I consider going ahead with callbackFlow?
callbackFlow is runtime stable - it works just as it is supposed to and it exists exactly because it is exactly the right tool to use in many cases.
I understand that any future changes might break some code and I don't want that to happen in a production app"
The only change that would affect how it functions is when upgrading your version of coroutines. That has nothing to do with runtime stability.
Related
I've recently had some tasks requiring that I need to log an Android app for some events, like adding to cart, checkout, signing in to the app, pressing on a specific button, etc... to Facebook and Firebase platforms.
Since these are non-functional requirements, I figured out it could be a good idea to start implementing the AOP (Aspect Oriented Programming) method, so events can be intercepted without changing any code in the app.
I've made my research and found out that you could implement AOP using either the AspectJ lang (which is compiled to Java Bytecode and can talk to java directly), or AspectJ annotations like #Before #After and #Around to intercept the pointcuts.
However, I have read some articles like This one And This one, they don't seem to be working for me, the code before of after the pointcut calls do not get invoked at all. I feel like I might have something missing or outdated in the build.gradle aspect code that is mentioned in the first article (which is 8 years old really).
I won't be providing any code here since I've tried the exact same examples in the tutorials and didn't work for me.
I'm asking for someone recently implemented AOP in his Android app.. And could provide me with some steps that I can follow, so I can get the code in the aspects invoked and working.
Also, I've seen some people on the internet trying to implement the aspects in another Android module, and some in another src directory, if someone would explain the difference? And since I'm using Firebase and Facebook dependencies to log the events, wouldn't making the aspects in a different module affect me in any way?
Also, if anyone knows if I'm approaching the best way here to log the events (for Firebase and Facebook), or there could be better? I've went to AOP since I don't feel like changing the existing code to log some events is ideal.
Please, and thank you.
I'm in the process of updating my Kotlin Android app to use Coroutines 1.5.2 (previously used 1.4.3).
In 1.5.2, any uses of GlobalScope.launch are now flagged with an inspection as "delicate":
https://blog.jetbrains.com/kotlin/2021/05/kotlin-coroutines-1-5-0-released/#globalscope
Let's say I know what I'm doing (in some cases I need a scope that won't go away with the containing activity / fragment).
How do I mark these uses so they don't get flagged? The following options are suggested, but none seem good.
Option 1 - Add #DecliateCoroutinesApi to the method. This makes the method also "delicate" and any call to that now get the inspection, so that achieves nothing.
Option 2 - Add #DecliateCoroutinesApi to the class. Seems like overkill.
Option 3 - Add #OptIn(DelicateCoroutinesApi::class) to the method. Almost good, but requires a special compiler switch -Xopt-in=kotlin.RequiresOptIn. Kind of messy.
Any suggestions?
If you really know what you're doing, option 3 should be the way to go. #OptIn is indeed experimental but that compiler flag is a small price to pay to use experimental features via #OptIn in general. You could also not use the compiler flag, and keep the warning about the #OptIn annotation itself, but that's even messier IMO.
That said, you should really think twice about using GlobalScope. Most of the time you can instead create a scope that you control yourself (with a dispatcher and maybe a Job/SupervisorJob as well, so you can cancel coroutines when appropriate).
You can even delete the GlobalScope, to keep just the async call (CoroutineScope.async).
When I try to use UInt I get this warning message:
This declaration is experimental and its usage should be marked with '#kotlin.ExperimentalUnsignedTypes' or '#OptIn(kotlin.ExperimentalUnsignedTypes::class)'
Aso the same happens when I try to create inline classes (which is what UInt is):
The feature "inline classes" is experimental
Those features can be really helpful but these warning messages are just stopping me from using them in case something will break the code in the future. Is this fear realistic?
Experimental features are released by Kotlin for the community to try out and provide feedback. They are by definition not completely Stable features, and hence
may not have backward compatibility
be at an early or late stage of the evolution process
may be completely changed or even dropped in a future release
Hence you should definitely not use experimental features in critical projects as
they are not stable and may have issues
in case the experimental feature gets modified or dropped in a future release, you'll have the extra work of refactoring that when you upgrade Kotlin to a newer release
That being said, in case the project where you intend to use UInt is not critical, go ahead and use it, but just be wary of the above.
The stability of Kotlin components is very well explained here.
So my company is very strict and tedious when it comes to bringing in new libraries. We do have RXJava though and I really want to use that in order to replace some of the async tasks that are a pita, and to make a really solid auto suggest without firing off long network calls on every text change.
My question is this:
Given some code like this
final EditText etSearch = (EditText) findViewById(R.id.crew_search_box);
Observable<EditText> searchTextObservable = ViewObservable.text(editText);
Can I set my observable to accomplish this same thing WITHOUT using RXAndroid and only using RXJava?
I am new to RX so forgive me if this is really just an out-there question.
Sure you can!
First of all, since you're mentioning ViewObservable: it's no longer there when you update your dependencies. ViewObservable and WidgetObservable have been moved, for various reasons. The initial 1.x release of RxAndroid meant a major refactor in terms of what is in there compared to the 0.x releases. You can read more about that here.
If you don't want to add RxAndroid as a dependency (or RxBinding) for that matter, just refer to the implementation details of the classes you're interested in and copy that into your own project. There's probably no need to make any modifications, but of course making copies means that you don't get the benefits of improvements either.
All RxAndroid (and RxBinding) really does is expose a bunch of convenience methods and implementations relevant to Android (surprise, surprise) that makes the lives of many a little easier. No one is, however, forcing you to use them. You can maintain your own code that you're interested in in parallel. Not sure that makes a lot of sense, but hey, it's possible.
You could always code review the parts of RxAndroid that you want and include only them. To be honest RxAndroid will implement view observables better than you will on your own.
Recently I’ve been rethinking my android architecture project, trying to adapt it to a more “clean architecture”, specifically, the kind of design suggested by “Uncle Bob”.
Which it involves several layers of abstractions, a nice isolation of responsibilities and a very strong dependency inversion achieved by dependency injection; which, ultimately, leads to a very decoupled-portable system. A perfect candidate to be tested by unit testing and integration testing.
In my android implementation I’ve ended up having three different modules or layers:
-domain: entities, interactors, presenters (pure java module)
-data: (acts as a repository to supply the data to the domain) (android library module)
-presentation: ui related stuff, fragments, activities, views, etc (android application module)
So, I’m trying to figure out what would be the best approach on the iOS ecosystem.
I’ve tried creating a project with multiple targets to achieve the same solution:
-domain: command line target (which seems very weird but I think is the most pure swift target available)
-data: cocoa touch framework
-presentation: cocoa touch framework
With this approach I can use these targets in the way I did with android modules. But the first caveat I’ve found it is that I need to add manually every new file to the dependent target.
But my knowledge is very limited in projects with multiple targets. I mean I’ve never created an iOS application with multiple targets. So I don’t know even if the solution would be use a framework (cocoa touch/cocoa) as a target instead of a command line module for the domain layer.
Any thought would be really appreciate.
Thanks!
Uncle Bob's Clean Architecture absolutely applies to iOS, Swift, and Obj-C. Architecture is language agnostic. Uncle Bob himself codes mostly in Java but in his talks he rarely mentions Java. All his slides do not even show any code. It is an architecture meant to be applied to any project.
Why am I so sure? Because I've studied MVC, MVVM, ReactiveCocoa, and Clean Architecture for 2 years. I like Clean Architecture the best, by far. I tested it by converting 7 Apple sample projects to using the Clean Architecture. I've used this approach exclusively for over a year. It works out better every time.
Some of the benefits are:
Find and fix bugs faster and easier.
Extract business logic from view controllers into interactors.
Extract presentation logic from view controllers into presenters.
Change existing behaviors with confidence with fast and maintainable unit tests.
Write shorter methods with single responsibility.
Decouple class dependencies with clear established boundaries.
We also added a router component so we can use multiple storyboards. No more conflicts.
Writing unit tests is greatly simplified too because I only need to test the methods at the boundaries. I don't need to test private methods. On top of that, I didn't even need any mocking framework because writing your own mocks and stubs becomes trivial.
I've written my experience for my last 2 years studying iOS architecture at Clean Swift I also put together some Xcode templates to generate all the Clean Architecture components to save a ton of time.
UPDATE - To answer #Víctor Albertos's question about dependency injection in the comment below.
This is a really great question and demands a long detailed answer.
Always keep the VIP cycle in mind. In this case, the doSomethingOnLoad() method is not a boundary method. Rather, it is an internal method invoked only within CreateOrderViewController. In unit testing, we test a unit's expected behavior. We give inputs, observe outputs, then compare the outputs with our expectations.
Yes, I could have made doSomethingOnLoad() a private method. But I chose not to. One of the goals of Swift is to make it easy for developers to write code. All the boundary methods are already listed in the input and output protocols. There is really no need to litter the class with extraneous private modifiers.
Now, we do need to test this behavior of "The CreateOrderViewController should do something on load with this request data" somehow, right? How do we test this if we can't invoke doSomethingOnLoad() because it is a private method? You call viewDidLoad(). The viewDidLoad() method is a boundary method. Which boundary? The boundary between the user and view controller! The user did something to the device to make it load another screen. So how do we invoke viewDidLoad() then? You do it like this:
let bundle = NSBundle(forClass: self.dynamicType)
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
let createOrderViewController = storyboard.instantiateViewControllerWithIdentifier("CreateOrderViewController") as! CreateOrderViewController
let view = createOrderViewController.view
Simply calling the createOrderViewController.view property will cause viewDidLoad() to be invoked. I learned this trick a long time ago from someone. But Natasha The Robot also recently mentioned it too.
When we decide what to test, it is very important to only test the boundary methods. If we test every method of a class, the tests become extremely fragile. Every change we make to the code will break many, many tests. A lot of people give up because of this.
Or, think about it this way. When you ask how to mock CreateOrderRequest, first ask if doSomethingOnLoad() is a boundary method that you should write test for. If not, what is? The boundary method is actually viewDidLoad() in this case. The input is "when this view loads." The output is "call this method with this request object."
This is another benefit of using Clean Swift. All your boundary methods are listed at the top of the file under explicitly named protocols CreateOrderViewControllerInput and CreateOrderViewControllerOutput. You don't need to look elsewhere!
Think about what happens if you were to test doSomethingOnLoad(). You mock the request object, then assert that it equals to your expected request object. You are mocking something and comparing it. It's like assert(1, 1) instead of var a=1; assert(a, 1). What's the point? Too many tests. Too fragile.
Now, there is a time when you do mock CreateOrderRequest. After you've verified the correct CreateOrderRequest can be generated by the view controller component. When you test CreateOrderInteractor's doSomething() boundary method, you then mock CreateOrderRequest using interface dependency injection.
In short, unit testing is not about testing every unit of a class. It is about testing the class as a unit.
It is a mindset shift.
Hope that helps!
I have 3 series of draft posts in Wordpress on different topics:
In-depth look at each of the Clean Swift components
How to break up complex business logic into workers and service objects.
Writing tests in Clean Swift iOS architecture
Which one of these do you want to hear more first? Should I bump up the series on testing?
In my opinion Clean Architecture is a set of ideas, rules, principles... to make a code better.
[Android Clean Architecture]
With this approach I can use these targets in the way I did with android modules.
You are able create a target[About](application target or framework target...) but it depends on your needs
If you read Architecting Android...Reloaded from Fernando Cejas
you might have seen that I used android modules for representing each layer involved in the architecture.
A recurring question in discussions was: Why? The answer is simple… Wrong technical decision
The idea is that is not necessary to use some build components to implement Clean Architecture