Tuesday, April 21, 2020

Developing for Android

I'm frankly surprised that it's taken me so long to get around to making a post of this flavor, but here we are.  Unless you've been living under a rock for the last 10 or so years, you know that Android is the dominant player in the mobile operating system landscape.  Because Android is "open" (sometimes to its own detriment) and capable of running on so many different types of devices, its usage numbers tower over those of iOS.

So what of the prospects of easy, enjoyable development?  I took a brief look at iOS a few years back, and unless things have changed dramatically over the last few years, it's bleak.  It's a very opinionated ecosystem.  I was thrilled at the prospect of Swift when it was announced.  It was initially a very lightweight, terse and flexible language.  I read the entire spec over the course of a few days and couldn't wait to tear into a slew of side projects.  But it became clear to me over the course of a few short weeks that Apple's initial vision wouldn't stick.  The average iOS developer was more than comfortable with the quirks of Objective-C and the ingrained history of Xcode.  Today, Swift looks like a chimera of the original vision and the angular oddity of Objective-C, and Xcode is as opaque and user-unfriendly as ever.  As I mentioned in my earlier entry, JetBrains offered AppCode, which was much more comfortable for me initially, but was clearly losing to Xcode in the game of catch-up.

Now, as for Android, its development prospects seemed to have one major advantage out of the gates.  The default development tool is Android Studio, an IDE created by none other than JetBrains and based on the much-loved IntelliJ environment.  You can also simply use IntelliJ, as it includes all of the Android plugins.  

Android Studio/IntelliJ's simulator
In typical JetBrains fashion, the boilerplate work of laying down the foundation for your app is handled by the IDE.  You can pick from a number of templates to bootstrap the project, and it takes care of generating not only the dependency management (via Gradle), but also setting up the basic stubs, allowing you to immediately run your app via the emulator.  You can also easily download whichever flavor of Android you need.  Bear in mind that these are rather large, and downloading all of the revisions would fill up even the largest hard drive in no time.  

On the surface, developing for Android is a snap.  Once Gradle has pulled down all of your dependencies, you can start the emulator of your choice and boot up/restart your app in seconds.  When it gets down to the nuts and bolts of the actual development, however, I find myself to be a little less impressed.  I've shared my foray into Android land on my GitHub.  It's a pretty vanilla application, using some of the basic components to build a basic experience.

I've mentioned on a few previous occasions that Android has adopted Kotlin as a "native" language, and indeed as its language of the future.  It's probably a wise move given that Oracle and Alphabet/Google are competitors in many ways.  As I've delved deeper into it, I'd say I'm conflicted about Kotlin.  It seems like it's often different for the sake of being different, and it doesn't lend itself to easy adoption coming from a Java background.  I do appreciate its built-in nod to mutability/immutability, and it lifted its closure/lambda syntax directly from Groovy (which is always a plus for me).  But the language can seem unwieldy at times.  For better or worse, it is always going to result in less code than its Java equivalent, but it can be at the expense of clearly capturing the developer's intentions.  Fortunately, this isn't a huge issue with the app that I developed.  The logic is simple, and the flow of things should be pretty clear.

I'd say my main gripe with my development exercise is the default dependence upon XML.  For those of us that have been in the game for a minute, it's easy to recall when XML was the only game in town.  At the time, it was a revelation: it allowed a plain-text representation of any data structure you could think of.  Then JSON came along and ushered in a new era.  The fact that XML is so pervasive in Android development speaks to how long the platform has been around.  Mind you, it's clear to me that Android is undergoing a rapid evolution even as I type this: I don't think that XML will be the way of the future.  But the reality is that it's still the path of least resistance, and in my readings, it's still the most popular way of designing layouts.
A simple XML layout
IntelliJ's visual layout/widget editor
Fortunately, as you can see above, IntelliJ takes some of the guesswork out of how your components/layouts will look.  I still found myself daunted by the tedium of tweaking the XML, setting up the right namespaces and staying ahead of the ruddy trail of deprecations (there are thousands of them).  The sad reality is that it's not an easy ecosystem to jump into, especially at this point.  I would have expected the adoption of Kotlin to have come along with a renewed effort to draw new developers into the fold. 

When I finally got to the point that I had a working application, I looked back and realized that there actually wasn't a whole lot to building something simple, and potentially immediately useful.  It's just a matter of knowing where to look, what to use and how to navigate the common design patterns.  I wouldn't say that Android adheres to my understanding of a standard MVC pattern, but it's not too far off from that.  Google offers a handful of "starter" tutorials, that can be incredibly helpful but I also found to be a little bit incomplete.  I would have loved to have a cloneable repo.  There are a few generous souls that have offered turnkey projects for experimentation, in various states of currentness and working condition.  It's my hope that my little project offers a springboard to the curious. 

Where do we go from here?  I'm still not convinced that going the native route is best.  I plan on delving into React Native next.  Not only does React Native allow a somewhat agnostic approach to developing mobile apps, but it does so within the framework of React's familiar component-based design, using the tried-and-true JavaScript language.  I will report back with my findings. 

Until next time. 

Tuesday, April 7, 2020

Revisiting the Spring ecosystem

It's been quite a while since I posted last.  Between now and then, I've chiefly spent my time in the Node.js ecosystem, working primarily with GraphQL.  I'll post some insights about that experience later, but needless to say, it's been a very interesting ride.  Over the years, I've made sure to revisit the familiar waters of Spring and the JVM, but it wasn't until lately that I decided to take a deeper dive and see which trends were taking hold.  

I had long ago resigned myself to the reality that Groovy was likely on its way toward the great garbage collector in the sky.  I've had an eye on Kotlin since its inception, and was excited to see it gain a foothold as a first-class language for Android.  I've heard tell of it being adopted in organizations where Groovy had previously held favor.  And finally, Java itself has been evolving steadily, adding features both useful and baffling.  I mean, I still don't understand the purpose of "default implementations" on interfaces, unless the old commandment forbidding multiple inheritance was thrown out the window.

Spring, on the other hand, has only intensified its standing as the go-to JVM add-on, providing everything you could possibly need for about every scenario.  You can look back about 5 years on this blog to see me extolling the virtues of the ready-made JPA/rest combination.  During that interval, Spring has continued to evolve along with Java, while adding robust support for Kotlin and apparently continuing to support Groovy, which warms my heart.

As I dove in to the coding exercises we'll look at later in this installment, I was very interested in the Spring Initializr project.  There have been any number of ways to bootstrap projects over the years, from simply copying an existing project, to running lazybones to the current solution, which seems like a complete no-brainer, especially if you use IntelliJ.  



In addition to being able to choose between Maven and Gradle, you can select your language of choice.  Sure, Groovy is at the bottom of the list... but it's still there!  The real beauty of this process, however, is that it puts all of the available Spring libraries at your fingertips and picks out the necessary dependencies for you.  Mind you, this had already become exceedingly easy with Spring Boot, as those projects are mostly packaged as "starters" that aggregate all the necessary odds and ends. 



So, diving right into what I hope to accomplish with this installment of the blog: mainly, I wanted to get caught up on where things stand in Spring-land.  How easy is it to spin up a simple CRUD-enabled service layer?  And secondly, I wanted to compare and contrast the path of least resistance in all three of the Spring Initializr languages: Java, Kotlin and Groovy. 



So without further ado, here are links to the examples that I cooked up:


Kotlin

Kotlin is a relatively-new language.  When I first took a look at it, it seemed to me like it was an attempt by JetBrains (makers of IntelliJ, WebStorm and other excellent tools) to grab a chunk of Groovy's popularity.  The earliest iterations of the language copped most of Groovy's popular features, including the beloved "Elvis Operator."  After spending some hands-on time with the language, though, the differences between it and Groovy are many.  I could write a lot about the differences, but we'll save that for another time.  What you'll notice most about Kotlin is that, by design, it emphasizes null-safety.  So if a reference is allowed to be null, it needs to be called out like so: var foo: String?. Additionally, there's an emphasis on thinking about mutability.  Much like JavaScript's const/var nomenclature, Kotlin has val/var

Getting down to brass tacks with the example app I created, there are a few things to highlight.  One thing I found nice was how easy it was to mash multiple classes into a single .kt file.  Take the repositories for example:

Spring Data repositories can be defined in as little as a single line, as above.  Being able to combine them all into a single file makes a lot of sense in this scenario.  The same can be said of the shorthand for creating a class with fields: 


@Entity

class System(var name: String, @Id @GeneratedValue var id: Long? = null)  



In "plain old Java," this would take many more lines to accomplish.  In Groovy too, for that matter.   



One gotcha that you'll notice is the need for the lateinit var construct.  This is necessary for any injected properties and basically tells the compiler and its null safety policing mechanisms to chill out.  This isn't necessarily an indictment on Kotlin as a language, but speaks to the fact that they didn't have IoC/Dependency injection in mind when they started putting the language together.  



In conclusion, I don't really have too many criticisms around Kotlin as a language. Groovy is much more amenable to developers with a Java background, but Kotlin isn't exactly inaccessible.  It just has a tendency to be a little... different at times.  Any seasoned Java developer will agree that Maps can be an integral part of coding.  The authors of Groovy recognized this and made an excellent shorthand ([foo: 'bar']).  Kotlin has a top-level function toMap(..) and a to operator, which is still more succinct than Java (toMap("foo" to "bar")), though Java has made some inroads in that department in recent years.  We'll get to that later.  Lastly, I couldn't really figure out which way the wind was blowing vis-a-vis unit testing.  I did my examples with JUnit, which was easy enough, but kotest looks pretty cool and appears to be a very active project.   

Java

What can we say about good ol' Java that hasn't already been said?  In terms of sheer hours, I've spent the vast majority of my career writing Java.  I maintain that the language really lost its way when it added generics.  For my money, Java 1.4 was the pinnacle of the language as it was first envisioned.  It was unabashedly object-oriented, and balanced from the perspective of typing.  I understand why generics were added, but Sun's solution just didn't really do it for me.  With type erasure, a cavalier coder could end up in a heap of trouble.  The more recent addition of lambdas didn't bother me as much, though it really brings into question what Java is trying to be as a language.  OO?  Functional?  Or really, just the Frankenstein monster that I sometimes imagine it to be in my mind.

Anyhow, as far as the Java portion of this coding exercise goes, there are a few things I'd like to point out.  Since I'd stepped back from primarily doing Java and JVM work, a library by the name of Project Lombok emerged.  This has factored mightily into the Spring ecosystem from the looks of it, and I'll admit that it makes writing Java a lot less of an exercise in boilerplate coding.  The Groovy fanboy in me would question the need of such a thing when the problems have already been solved, though.  I suppose that it would be a way to get around the tedium of writing getters and setters all day in an organization that absolutely insisted upon code being written in Java (they exist).  In the Java code example I wrote, I mainly used the @Data annotation, which dynamically creates getters and setters, and adds a custom equals(), toString() and hashCode().  There is a lot more to Project Lombok than this.  It's really very cool, and employs some idiomatic trickery to accomplish some nifty things.  Bear in mind that you'll need a plugin for your IDE to make it play nicely. 

The other thing I'd like to touch on briefly is a feature that stormed in around Java 1.8: double brace expressions.  This makes working with things like Maps and Collections a bit less painful.  Here's a snippet from one of my tests:

new HashMap<String, String>() {{ put("projection", "fullTitle"); }}

In one line, I was able to accomplish what would have taken multiple statements before.  The shorthand here activates something similar to an anonymous inner class, and executes statements within the scope of the instance.  It's not as nice as the Groovy and Kotlin examples above, but it's certainly an improvement.

I also tossed in a Java lambda for good measure:

@Bean
ApplicationRunner loadTestData(EsrbRatingRepository esrbRatingRepository, 
SystemRepository systemRepository, TitleRepository titleRepository) {
   return (ApplicationArguments args) -> {
      EsrbRating rating = esrbRatingRepository.save(new EsrbRating("E", "Everyone"));
      System system = systemRepository.save(new System("Atari 2600"));      
      Title title1 = new Title(system, rating, "California Games");      
      Title title2 = new Title(system, rating, "Pitfall!");
      Title title3 = new Title(system, rating, "Tank Commander");
      titleRepository.save(title1);      
      titleRepository.save(title2);
      titleRepository.save(title3);   
  };
}

This just populates the H2 database with some sample data.  As you can see, it creates a bean, which is actually just a lambda that uses the outer scope from the factory method.  I'm still a bit iffy on the inclusion of lambdas in Java, when an anonymous Runnable worked just fine before.  But they certainly could have done it worse. 

Groovy

Ah, good old Groovy.  I spent a good many years in Spring/Groovy land, and jumping back in was like sliding on a well-worn glove.  I don't have a lot to highlight with this one, though I'd recommend lining it up with the Java project.  Even with the Lombok annotations, the superiority of Groovy shines through.  I acknowledge that it's purely a matter of opinion, but having started writing Java in the late '90s, I find Groovy to be a very thoughtful evolution of its principles.  One thing you'll notice is that I prefer to use a field/method/variable type on the left as opposed to def.  This is a purely opinionated move, and I prefer it over Kotlin which uses var/val, and requires looking to the right to determine the type (var id: Long? = null).  

I'd also like to point out how great the Spock framework is.  It has a minuscule learning curve and makes mocking a snap.  I can't say with any certainty how popular it still is, but it's clearly being maintained regularly.  The difficulty going forward is that it requires a separate spock-spring dependency to play well with all of Spring's testing apparatus, and I could see Spring starting to evolve faster than the potentially dwindling Groovy/Spock community.  I sort of hate to say it, but a huge part of my affinity for Groovy is how nicely Spock plugs into it.  Though Spock is also an excellent option for Java codebases as well.  I also looked at doing the Kotlin tests with Spock, but to "properly" test the code requires some odd-looking code. 

Spring

To wrap things up, I wanted to touch briefly on Spring and some of my observations coming out of this exercise.  Above all, I'm really flabbergasted at how awesome the framework continues to be.  It truly frees the developer from having to repeatedly churn out boilerplate code for common exercises.  spring-data-rest is my favorite example of this.  

Spring has really jumped on the HATEOAS/HAL bandwagon, which to me is a bit of a double-edged sword.  One of the challenges I immediately encountered in these examples was how to return immediately useful data to the client.  For a complex object representation (like most enterprise relational DBs), this means a ton of links.  Spring's solution to this is Projections, which allow you to expose a more fleshed-out object.  Without a projection, it would be up to the client to follow the links in order to have something fully-hydrated.  Even with Projections, there's no straightforward way to configure a default projection.  The projection has to be requested by the client as a parameter on the query string.  I can think of a handful of ways to hack around this limitation, but why should that be necessary?  

I haven't dug into the topic much, but I'm guessing there are lots of libraries in the JavaScript/native world that take care of navigating links and building full objects for the developer.  Even then, it seems to me that one HTTP request is better than a bunch of them.  It's worth noting that this isn't a problem for a proper NoSQL/document DB where everything is self-contained.  Food for thought.

Anyway, it was nice to be able to do this exercise and to get back to blogging.  I say this every time, but I hope to do more soon. Stay tuned.