Puntata Alla Roulette
Soluzioni per la definizione.Una puntata alla roulette. per le parole crociate e altri giochi enigmistici come CodyCross. Le risposte per i cruciverba che iniziano con le lettere N, NO, R, RO. I consider myself a Wellness Roulette who supports clients alla their journey and hold them accountable to their goals. In order to do that I ask that my clients are forthright with me and I in turn take a jelly belly roulette free approach to keeping them on puntata.
What Can RIV Do For You?
Rapture In Venice, LLC, has been building mobile apps for over 10 years! Working directly with our clients, and through other firms, we’ve built the full gamut of apps from fitness trackers, to visual measurement tools, to auto insurance.
We’re ready to build a solution for you! Contact us to find out what we can do for you.
Need to augment your mobile team with developers? We can do that, too.
Here’s Why: View Navigation Sucks in iOS
The “Here’s Why” series attempts to explain the what’s and why’s of basic iOS concepts and topics. What does this mean? Why is it this way? I’ll attempt to keep the focus on the theory rather than the minutiae of the code so we can learn the fundamentals of the issue to help in future understanding.
In the last few years, a new design pattern has emerged in the iOS space called the Coordinator. The Coordinator pattern is one that aims to remove all app navigation logic (push, present, pop, dismiss, etc.) from the View Controllers and handle it externally, from the outside. It’s separation of concerns as it should be.
But what’s really wrong with doing it in the View Controller?
Before I discovered the Coordinator pattern, I knew something was wrong with how we do navigation. Let’s start simple before we get into the problem areas.
Example #1: Simple Master-Detail (Acceptable)
Let’s say we have a UITableView of video games where, if we tap any one of them, a detailed view of that game is pushed into our navigation controller. The user interacts with that screen and then dismisses it by tapping the back button. When the user taps, we instantiate the detail view and then call navigationController?.push on it. This pushes the screen forward. We return to the list when the user taps the back button in the navigation bar.
This usage is fine. The detail view contains no dismissal logic since it never calls navigationController?.popViewController to dismiss itself. In this way, the detail view has no knowledge of how it’s presented.
Good to go.
Example #2: Not-So-Simple Master-Detail (Questionable)
Now let’s take that same Master-Detail example but, this time, the detail view lets you edit information and has two buttons, “Save” and “Cancel”. This seems similar, but now we’ve introduced a problem: the detail view needs to dismiss itself when one of these buttons are pressed.
We can do this in one of several ways, but here are the primary options:
- We call a delegate or closure on tap.
- We perform an exit segue on tap.
- We call navigationController?.popViewController on tap.
If we use the first method, we’re good to go. In this case, the detail view need not have any knowledge of how it was presented. What I mean here is that the list view presents the detail but the detail view need not care how it’s presented because it isn’t dismissing itself directly. The delegate is defined by the calling code and can decide how to dismiss the view on its own.
Awesome.
Using exit segues isn’t as hot an idea. While the dismissal code is abstracted out of the detail view, it relies on any view that presents it to provide an exit segue route somewhere in the hierarchy. You’ll get this right the first time you use this view in your storyboard, but later on someone who reuses this detail view in a different place will be surprised when they click “Cancel” and nothing happens, for example. The exit segue logic is always a hidden implementation detail which is why I’ve never cared for it. This is why I would prefer adding an onCancel closure so that I can easily check for it (type on<Escape> to see my options) and provide my own logic.
The third option, putting the dismissal code right in the detail view, is the worst idea. Sadly, this is extremely common to see as well. I ran into this problem on an app a while back when dismissals weren’t working because the specific view I was reusing was originally being presented by a UINavigationController but now I was using it as a modal. Calling popViewController directly in the view controller wasn’t dismissing it at all!
You never notice the error in doing things this way until you’re building an app that reuses view controllers a lot, but once I ran into this problem I vowed never to include self-dismissal logic in my view controllers again. When a view was presented, it would always have a closure such as onCancel or onSave that the presenting view controller should implement to handle it. If you tapped a “Cancel” button in my view controller, it would simply call onCancel?() and that’s all.
But even that wasn’t foolproof…
Example #3: Nesting View Controllers (Insanity)
On the most recent app I worked on, I had some complex view navigation logic that threw me into the fires of hell. The hierarchy looked like this:
A -> B -> C -> D
Here, A is on a UINavigationController that pushes B which presents C modally which presents D modally. The trick here is sometimes C needs to reset its data and sometimes it should go away. Also, sometimes B needed to be able to dismiss C or D. Not to get too deep into the weeds, each view controller only knew about its presented view controller and so the logic got hairy fast. I could call closures back one level at a time, but the logic became increasingly opaque and when the wrong thing happened it was hard to trace the logic from beginning to end. (Or in this case, end to beginning.) I’d have to trace through the whole chain of views each time to debug and it was taking up a ton of time.
The problem was that while I was doing the right thing by not having each view controller have its own dismissal logic, the chain as a whole (A, B, C, D) was a conglomerate and, therefore, housing its own dismissal logic anyway. Somehow, this view controller group needed to be treated as one thing and the logic needed to be factored out.
Enter the Coordinator Pattern
Using the Coordinator pattern, this group of view controllers can be completely controlled by one object, a coordinator. I won’t explain the details of the pattern here, but it’s best explained by Will Townsend. Quite simply, when A is presented, a coordinator is created that becomes the delegate to A, B, C, and D. When an action is taken, such as when D needs to dismiss back to B, we do so explicitly by calling a delegate method, perhaps something named onDismissReward(self.reward).
Yeah, that method is long, but it’s clear. :-) Not only is the view controller not having to handle its dismissal logic, but it’s also not relegating that task only to the one before it. It’s asking the coordinator to do it, and the coordinator is intimately familiar with all of A, B, C, and D.
The coordinator then implements this method and, having access to all of the view controllers in the chain, can decide the best way to dismiss back to B having full control of everything. The alternative, having each view controller only know about the next in the chain, would’ve required sequential and nested calls to closures to accomplish the same thing. With a Coordinator, the logic acts in one place and the view controllers merely have to describe what it is they want to have happen. This not only clarifies how this series of view controllers should present and dismiss as a group, but each individual view controller can be controlled easily in other contexts using the same delegate or an additional one. (Extending protocols is a great way to keep the delegate calls to a tight minimum.)
Additionally, because the Coordinator is based off protocols, it’s easy to discover the right thing to do. You don’t have to rely on hidden exit segues nor, really, storyboards at all. In fact, if your entire app uses the Coordinator pattern, you could easily build all your screens in individual XIB’s if you like. You won’t need any segue logic at all.
Conclusion
The Coordinator pattern isn’t for everybody and isn’t needed by every app. For most small apps, inline navigation code is perfectly fine. As your app gets bigger and, most importantly, view controllers get reused in various places, the Coordinator pattern is worth learning. Keep it in the toolbelt, you’re going to find some great uses for it!
No Longer a Hybrid Mobile Developer And No Longer Gone Insane
It’s been about 15 months since I retired from Android so I think it’s time for an update to see how it’s gone, yeah?
Firstly, I’ll say that the response to that blog post was shocking. I had tons of comments/support/criticism from Reddit and Hacker News and I read all of it. Did I make the right choice I’d think to myself and I spent a day re-evaluating based on the feedback.
But, yeah, I haven’t written a single line of Android code since that day.
In the time since, I’ve noticed several changes to my life and well-being, so I’d call the decision a huge success, but there were a few cons, too. Let’s take a look at it all.
Pro: Staying focused on iOS has kept my skills strong and my mind “in the loop”
The primary reason I decided to quit Android is logically the biggest benefit I’ve had from it. After spending 5 or so years toggling between the two platforms, I found I was becoming decidedly “average” at both. My work life was a pendulum where I’d fall behind on the latest and greatest API for iOS and once I caught up I was missing the must-have libraries for Android and, oh by the way, what’s this Kotlin thing?
That’s gone away now. I always feel like I’m progressing in my iOS development skills and keeping up to date with the latest Swift-iness and I’m always improving on how I architect my iOS apps. I can stay focused now.
This was the biggest reason and biggest benefit by far.
Pro: Less clutter
I’m a clean guy. I try to write clean, pretty code. (I was featured in a chapter of Clean Coder by Uncle Bob as a matter of fact.) I maintain a library of tech books to try to not only keep up to date on things but review what’s in the past to pick up on concepts I’ve missed or simply to refresh myself. (I always recommend reading a new iOS How-To book every year.)
The day I quit Android I deleted Android Studio, all my SDK stuff, put my dev phones away, put my Android books in storage, deleted my Android-related Kindle books, and even put my Droid toys somewhere else. Everything around me is iOS and it’s so clean.
And, oh the extra space on my laptop.
Con: Less contract work available
Also an expected consequence, this was the one thing that kept me from making the switch to iOS-only for months (if not years) previously.
And it’s held true.
Over the past year I’ve had to turn down work twice from previous clients because they only had Android work for me. If you’re a contract, you know how hard this is to do! I could’ve caved, but I stood firm and have had consistent work, but I’ll be honest there’s been moments where it’s gotten very hard to find something and it’s led to some sleepless nights.
If I was working on both platforms I’d have twice the work available to me.
Pro: Don’t Need to buy Android devices anymore
I’ve had four Android devices in my lifetime: a Nexus S, Nexus 4, S6 Edge+, and a tablet I can’t even recall what model at the moment. In general, I disliked all of ithem except the Edge+ which was my carry-along phone for about 10 months. The irony is that I started carrying that phone at a time when I was thinking of being a devoted *Android* developer. 2.5 months later I was done with Android completely.
Less devices to buy means more money available for…Nintendo products. :-) OK, and iPhones. (But really, Nintendo.)
Con: I don’t feel cool anymore
There was a time years ago when a developer who could do both iOS and Android was pretty rare. I was proud to be one of the few. Being able to talk to a client about both their platforms at once was invigorating and surely came off as a perk. “We have one guy who can handle both our apps,” they’d say and I even had a few clients where I did product work on both sides at once.
I sorely miss being that cool and now I’m just an iOS guy. Mind you, I still talk about Android whenever I can, but I know as time goes by I’ll be further and further out of date with things and then I’ll feel like I do now when I try to talk Perl.
Sad!
Pro: Time for my kids, my wife, and a healthy work-life balance
Isn’t this what it’s all about? I don’t have to tend to two different sets of dev conferences. I don’t have to study how tables work for two different platforms, I don’t have to have two sets of network libraries in my head at a given time…and lord knows 4 languages: Objective-C, Swift, Java, and Kotlin.
I have more free time to just have fun.
And for that, I’m happy with the choice I made and confident it was the right one now and in the future!
What Can RIV Do For You?
It’s Been Real, Android: Why I’m Retiring From Android
Update 10/13 – Due to the overwhelming response, some updates were made to clarify my positions on things. Also, take note, there’s plenty to like about Android development, too! (No provisioning profiles, amirite?) I only focus on the warts because I’m explaining why I left Android.
This week marks my final week of working on Android. I’ve had my ups and downs with it, but I’m excited to retire from Google’s mobile platform.
Very excited.
OK, story time…
How I Got Started With Android
I began dabbling with Android about a year after boarding the iPhone train. Prior to that, I’d spent a couple years writing Blackberry and Java ME apps. (What are thoooooossseee?) Having become comfortable with iPhoneOS (that’s what it was called back then, look it up…), Android was starting to take off and I was curious to learn it. I taught myself for a while and then took a course from my then co-worker, and now world renowned author, Tony Hillerson.
Around that time, I got tasked to work on an Android bank project with a platform superfan, Josh Jamison. It was my first chance to do daily Android work and…it…went…poorly. The tools were in their infancy and Eclipse was downright awful compared to Xcode. Everything was slower. Compiling, Running. The emulator was freaking useless and Genymotion didn’t exist yet. I didn’t have an Android device of my own to test with, either. I’d been so comfortable with iPhone’s environment and Android just felt so raw.
It was a miserable experience. No matter how hard I tried, I just couldn’t get in a groove. I was an awful Android developer until mercilessly I was moved to another team. (I don’t recall being fired from it, but I wouldn’t be surprised if I was.)
Over the next couple of years, I dipped back in and finally acquired my own hardware. (A Nexus S.) The tooling was improving and re-learning the platform gave me new insights and I started to grok things a lot better. After moving on to Double Encore, I started working on more Android projects and even led one. (Whoa.) Android developers were still a rare breed, but the community was drastically improved.
Soon after, I embarked on my own and turned Rapture In Venice into a full-time consulting studio. To my surprise, I was getting contacted for Android work a little more than I expected! Of course, I took it on.
In the 5 years Rapture In Venice has existed, I’d estimate I’ve spent half that dedicated to Android. I’ve done co-location work for it, built Android apps alongside iOS implementations, ported apps to Android from iOS, and even found time to create my very own app for the Google Play Store.
Even more shocking, I switched to a Samsung S6 edge+ as my personal carry for about 6 months!
That leads me to today…
My Retirement From Android
My decision to officially abandon the platform didn’t happen overnight. In fact, it’s taken two years of consideration and false starts.
For a long while, the “hybrid” mobile developer (knowing iOS and Android) was a rare sight. I took pride that I could do both. As a consultant, I could sell myself on someone who could write both versions of an app for a client. My fluency in both made me an asset for porting jobs. I relished it.
As time wore on, more developers were trying out both sides of the aisle. True hybrids are still rare, but there are many developers who have familiarity with both platforms now. Still, why would I leave one behind? I’ll tell you why.
Over the last couple of years, the unsettling feeling that I’m becoming a mediocre developer for each platform has crept over me. While it’s not true, and I have confidence in both, that feeling comes from the fact that I can only be half-engaged in each community. With each major conference, I can only watch a subset of the talks. With each new feature added to the platforms, it’s 50% harder to remember it all. I miss out on some new concepts while learning others. Even the basics have become unsteady.
Take, as an example, the simple concept of shared user preferences. iOS and Android both support this with NSUserDefaults and…SharedPreferences I believe? It’s funny, I always forget the name of it and have to try a couple autocompletions to recall it. Which one can store arrays? (It’s iOS.) Which one can store data in different buckets? (It’s Android.) Is it setBoolean or putBoolean? Do I call synchronize or commit. (Or apply now?) It’s hard to enough to remember an API clearly, let alone when you’re using two very similar API’s for two very similar platforms.
It’s just gotten too much and it’s hard to keep steady as an expert in both. On top of that, the value of knowing two platforms isn’t as helpful as it used to be. Sure, if I’m lacking work, I have two avenues to find more, but it’s not feasible for me to do both platforms for one client. They can simply use two resources at once nowadays. Apps aren’t as small as they used to be either, so there’s no value in my doing both.
The day-to-day of switching between platforms is also difficult. I’m currently finishing up a project where I’m doing maintenance on both apps for a client at the same time. I’ll switch from iOS to Android multiple times a day. Two different IDE’s, two different languages, and two different concepts of what the UI should behave like. It’s not easy to context-switch in this way. Every feature is implemented two different ways between them, too, so I have to solve every problem twice.
Finally, the biggest hurdle trying to work for both platforms at once is keeping up with new libraries. I spent the first 3 months of 2016 on an Android project with a team using newer programming paradigms I’d not yet experienced such as RxJava. When you’re switching between platforms as a developer you’re trying to get your frame of mind right and it depresses your willingness to check out a new way of doing things. Retrofit? Hang on, I barely remember how to use Volley, so I’ll try just maybe that on the next project…k?
Wait, what is picasso? Oh wow, I hadn’t heard of that one…I was busy learning Swift.
Goodbye, Cruel Android
Once I decided I had to pick one platform and stick to it, the only question left was which one.
As it turns out, that decision was an easy one.
In my opinion, over the last couple years, the Android development environment has broken down. Here’s what I’ve seen:
- Google’s adoption of gradle has been a disaster and proved to me to be a terrible decision. It did help out with some previous deficiencies, namely multiple app targets, but it’s slowed down compilation severely. It also makes for masochistic configuration files with major redundancy and fragmented dependency hosts. Getting an app to compile shouldn’t be a challenge.
- Multidex. My god, Multidex. It’s incomprehensible that Android can’t handle something as simple as keeping track of a few thousand methods, a limit easy to get to as it counts the SDK and your libraries. Multidex kills build times, has led to strange compilation problems, and even needs to be configured differently based on the version of Android you’re running on.
- Fragments are another Android concept that has made life unnecessarily complex for the Android developer. Introduced when tablets came into being, they were better than the classic Activity but have always felt hacked in. This is when Android developers began living off the support libraries. It took years before I used a native Fragment and, even today, I’m not sure that’s even a good idea. I almost wish Android would’ve just redone the concept of Activity/Fragment and started from scratch. Today, some developers stick to using Activities as much as possible while some always use Fragments. You’ll never meet an iOS developer that doesn’t use a view controller, but the most basic of UI concepts in Android make for holy wars.
- Interoperability is another source of unnecessary agony for developers. From the earliest days, the expectation was your application should run activities from other bundles and was expected to share its own with others. As it turns out, very few apps are designed to be used by others…but the architecture still has to handle it. This has led to a difficult environment to pass data between Fragments (using bundles) and special code to handle the simple act of rotating your phone. Passing data around can feel dirty and it takes a lot of effort and care to be sure your activity can be rebuilt from scratch while preserving its state.
- AsyncTask. Years ago Google added this class to the API to “help” developers with background processing. Since then, endless blog posts and discussions have gone into how to use it properly. Google themselves didn’t account for phone rotations, finishing activities, lifecycle changes, and so on. Today, there are endless alternatives to this terribly thought-out helper and it began a trend of many Android tools that were poorly contrived and have led to tons of confusion. (Just look at how many different ways there have been to have a tabbed interface.)
Lastly, the development lifecycle is just so slow. In the beginning, the emulator was nearly unusable. Running an app sometimes didn’t work and you had to spend 2 minutes restarting the thing. Copying the APK takes a while, too. The best way to develop is directly on the hardware, but come on. Genymotion came along and made emulation better for a while, but recently even that became unusable with newer gradle versions and Instant Run.
And, by the way, did they ever get Instant Run to work right?
Maddening.
So there we go…my days of writing Android code are done. I’m still left with an understanding of how it works and I’ll be able to understand Android code for a long time, but I’m truly excited to go back to being laser focused on the latest and greatest iOS has to offer.
Sorry, Nouget. I never knew ya.
Goodbye.
Previous Posts
Buongiorno a tutti!Navigando mi sono imbattuto in un banner pubblicitario che mi ha rimandato ad una pagina che presentava un metodo, a dir loro formidabile per sbancare i casinò on line alla roulette. Nonostante tutto su quella pagina ricordasse uno di quei siti-truffa che esortavano i visitatori a comportamenti azzardati allettandoli con guadagni facili tipo catene di Sant'Antonio e simili (evidenti traduzioni fatte tramite software, testimonial improbabili che ringraziavano l'autore per gli incredibili guadagni etcetc...) mi sono incuriosito. Il metodo proposto consiste nello scegliere un colore, rosso o nero e di puntare un euro su quel colore. Se si vince, iterare l'operazione, se si perde, scommettere di nuovo sullo sullo stesso colore con una puntata doppia. Ripetere questa operazione fino a quando non ci si rifà della perdita.
Ho provato a pensarci un po' e sono giunto a queste conclusioni:
(premetto che in tutte queste considerazioni non ho considerato che alla roulette esista anche lo 0, senza colore, ma credo che non modifichi di molto quanto segue)
Ammettiamo che scelga Nero come mio 'colore fortunato' e che la mia puntata di partenza sia un euro.
Applicando questo metodo, ogni volta che alla roulette esce nero, io guadagnerei un euro: se esce subito nero ho immediatamente vinto, se esce rosso, alla giocata seguente punterei 2€ su nero e potrei vincere 4€, rifacendomi dei tre euro puntati etc... Fin qui, sembrerebbe un metodo infallibile per vincere sempre e comunque.
Il problema è che il casinò impone una puntata massima. Ho visitato un casinò on-line e ho visto che per loro questa è di 300€. Questo vuol dire che alla nona volta che uscisse rosso di seguito, mi troverei impossibilitato a rispettare il metodo che esigerebbe una puntata di 512, costringendomi a puntare solo 300. Se a questo punto uscisse nero, anziché vincere il mio euro garantito, avrei perso 211 euro (-511+300), altrimenti ne avrei persi 811 (-511-300). In media, quindi, al decimo 'rialzo' perderei 511 euro. Un eventualità del genere, cioè di arrivare al decimo rialzo e perdere statisticamente 511 euro, dovrebbe avvenire una volta ogni 1024 vincite da un euro. Giusto? Quindi il sistema, tutto sommato, dovrebbe produrre un 'reddito' statistico.