Hacker News new | past | comments | ask | show | jobs | submit login

So I've finally been learning to write Android Java... and honestly, as a C#/Python developer, I figured it would be easy to pick up. Holy crap, how do you people live like this?

Yeah, I'll be trying out Go for Android. Give me an excuse to learn Go. Still don't like the idea of going without generics and exceptions, but maybe it'll surprise me. I figure we're all just biding our time until Rust is ready.





You are still stuck using the GUI toolkits of the platforms in their native tongues. I think Qt and Mono (so C++ and C# respectively) are the only toolkits that support both of them with one code base.


Perhaps not so much a Serious UI Toolkit(TM), but anything that eventually compiles down to GL would work too. This is how play-clj does it: binding to libgdx, which eventually calls some OpenGL methods.

While I did jokingly say "Serious UI Toolkit", there's more than a few awesome applications on Android that have very, very simple UI widget requirements. Particularly games, which according to the article, they're focusing on.


JUCE also does.

http://www.juce.com/


Kivy does too.

http://kivy.org/


It sounds like Rust, right now, can build a library that you can use in an NDK app. Go, right now, can build a service or utility that you can use in any Android app.

http://goo.gl/mkCaJd

It isn't integrated, and as they note as one of the gaps, doesn't currently support CGO (meaning you can't compile C code or libraries in with your Go executable), but it has worked quite well for some time.


Rust is a browser development language. Maybe he doesn't want to bother with memory management. Besides, is there a modern IDE for Rust (automated refactoring etc.)?


>Rust is a browser development language.

That's a ridiculous assertion.


> Maybe he doesn't want to bother with memory management.

Who is "he"? The poster michael was replying to said s/he was waiting for Rust to be viable.


We build every Rust commit against Android already: http://buildbot.rust-lang.org/builders/auto-linux-64-x-andro...

I'm pretty sure that was contributed by Samsung.


Plus, Rust doesn't have exceptions any more than Go does.


Rust doesn't have exceptions, but its error handling is less ugly than go. Functions that can encounter errors return a `Result` by convention. If you then want to propagate errors, you can do so nicely with the try! macro, which converts a successful `Result` into its value, or returns the error of an unsuccessful `Result`. Thus the following go and rust are semantically the same:

    val, err := error_prone()
    if err != nil {
        return nil, err
    }
    
    let val = try!(error_prone());
Personally, I find that error handling isn't that bad in go. I think it's at least no worse than exceptions. Exceptions make it too easy, for me at least, to just mindlessly propagate the error. Sometimes that's the right thing to do, but in go it's a lot less repulsive to handle the error since to propagate the error you would need handling code anyway.

Rust strikes a nice balance. You have to explicitly handle every error, but if you go with the by far most common handling code, you get some nice sugar that makes it mostly painless.


I find that propagating the error is what I want to do at least 95% of the time.

Part of the problem with Java exceptions is too many people feel obliged to catch exceptions, when they should be propagated.

Ideally, the only catches would be in the top-level loops (request / response dispatch for server, event loop for GUI, arguments for command-line).


That's not been my experience, often it helps to add more context to errors as they propagate through the layers. Unless you control the entire stack of function calls top to bottom as part of your application, I think it's ogyrn bad form for one library to bubble up another library's errors directly. It's effectively leaking implementation details and it means the clients of your library may also have to import your dependencies to handle the errors.


The failure mode of a component is a function of how it's implemented. When a library couldn't connect to a server or couldn't open a file, you gain nothing by wrapping that exception, unless it's to indicate the semantic nature of the server or what the file is used for - and these things are normally obvious from the stack trace method names.

Wrapping exceptions as they bubble up is only helpful if the wrapped exception adds context that aids in diagnosing the issue. Otherwise it's just boilerplate that obfuscates and gives a certain type of developer warm fuzzies. "Exposing implementation" is a non-counterargument - the component failed because its implementation preconditions were violated, you need to address those implementation preconditions to fix the problem!

You don't need to import dependencies unless you intend to catch the specific originally thrown exceptions, and that's not normally what happens in the top loop; it normally logs, dumps or transmits the exception message and possibly its stack trace. These operations are normally only rely on the base exception type, so there's no need to catch a more specific exception.

Problem languages for this approach, though, are C++ (where the culture makes a single base class for exceptions awkward) and Java (where throws clauses, a deeply misguided feature, may force dependency imports unless you specify 'throws Exception' - or my preference, wrap in RuntimeException).

PS: I should add the other fundamental problem with the Java throws clause is that it uses static types to analyze dynamic data flow in a language with polymorphism, which makes it a usability disaster. When the code being invoked is indirectly accessed via polymorphic references, exception flow checking falls apart. There's a reason Google Guava's Function and Predicate interfaces don't throw. But that's enough of my bugbears.


> "Exposing implementation" is a non-counterargument - the component failed because its implementation preconditions were violated, you need to address those implementation preconditions to fix the problem!

I don't think this is necessarily true; assuming an XML parsing library that throws exceptions on malformed XML, you are more likely to have simply supplied generally invalid XML than to have hit an implementation-specific exception type.

So, the exception is only implementation-specific in the sense that it was created by an implementation of the class of software you wanted.

But really, in my mind the issue of not wrapping exceptions means all of your client code is now tied to the transitive library, which means the implementation can't be changed without breaking API compat.


Better libraries express their dependencies in a pluggable way, which makes them more testable as well as composable.

The top-level application is usually a composition of libraries.

So in practice, I'm sanguine about apparently transitive dependencies. I prefer when exceptions from one library's plugged-in dependency flow through unmolested, as I see the libraries as mostly a flat dependency of the larger application. If you pull in dependencies transitively without paying much attention to them, you're sowing seeds for trouble with versioning, security scope, risk of stale projects if they're open source, etc.

I think of this as a corollary of Spolsky's law of Leaky Abstractions. Passing through exceptions means not trying to fool anyone into thinking they can work with the high-level abstraction without understanding anything about what's going on underneath.

Ideally the standard library provides base classes that act as core categories for different kinds of exceptions - IO, programmer error, data format error, etc. - so that general code can be written after a fashion when necessary. But I think you're fooling yourself if you think that such general code can be written the majority of the time, much less all the time. What's underneath always leaks through, one way or another, and if you try to ignore the thing that's underneath, you'll end up with brittle inefficient code.

Where high-level wrapping exceptions are justified is where there is an obvious chokepoint in the design - where the interface between several layers is very narrow. But this typically is at the junction between a service and a client - e.g. a web front end and back end, or async job queuing service, etc. - something where there is a service loop and probably service-specific logging of original exceptions, anyway.


> Passing through exceptions means not trying to fool anyone into thinking they can work with the high-level abstraction without understanding anything about what's going on underneath.

Except this is not what happens in reality, very few people see an internal exception type and go investigate the details.

Sure it's shitty practice, but it seems orthogonal to whether the internal exception types are exposed.

I'm not saying people should just ignore what is underneath, I just think that as a library developer, you significantly constrain what you can do without breaking API compat by exposing internal exceptions.

You could take a hard line stance and say that it should be a breaking change and people should go and re-evaluate the library after the change, etc, and then rewrite their code to deal with new exceptions. But in reality it just means that library will no longer get updated, and will effectively become stale for no good reason.


Well said. While I dislike Microsoft, the guy they hired from Borland to design C# definitely got the "checked exceptions suck" thing right.

The "finally" clause is underused in most Java programs and the "catch" clause is overused.


Unfortunately they will not be mirroring the Android SDK in Go, but only the NDK bits. It's noted in the document that it would be too much of a bear to keep up with the official SDK, and an automated tool would generate crappy, non-idiomatic Go.

I think Dart or another JVM language are the only hope for getting away from Java on Android. Dart is maybe a longshot at this point though.


The problem with Android isn't Java though, it's the Android API being an inconsistent hacked together in a hurry trainwreck. Everything they've added since 3.x has been an enormous improvement, but they never shook off the baggage of the initial push to release.


Funny I had the exact opposite impression after using Java years ago. I felt like Android's API redeemed Java in my eyes a bit. I never liked Java much but the emulator, the debugger, a documented API, lots of example, developer blogs all made it very easy to get started and I create a rather complicated app pretty quickly.

Looking back I wouldn't mind developing on Android again but I wouldn't want to necessarily do anything with Java by itself.


Have to agree, I thoroughly despised Java until I started developing for Android, it suited the Application Framework and made the language fun, developing fully functional apps with ease and speed.


Tell me about it. I'm constantly using the autocomplete to look through all options to complete a method when it should be consistent with other similar things. For instance, you set OnClickListeners but you add TextChangeListeners. This is just a simple example, and yeah it's a small thing, but it's the damn mental baggage of not relying on my brain's quick search to find similar things and having to spend the extra time that really wears on you after hours of it.

The level of hackery even drips down to their own documentation and code examples. There is a line in an old example for a TabPager I believe that said "It relies on a trick." How is this acceptable API writing and role-modeling from Google?


Fair enough. Even some of the newer APIs feel slopped together to be honest. Android development does feel like a constant battle with framework bugs.


All android APIs tend to have a large number of methods, but there will be absurd omissions. Example, the WebView has no way to return its HTML contents. So it's difficult to implement your own caching mechanism. Or an even more absurd example, the android YouTube player has no .stop() -- it is simply inconceivable that a media player lacks a way to stop a video, but there it is.


Back when I was writing a client for a REST website, the default HTTP library lacked POST. The recommendation was that every app which wanted to POST should bundle the ~2MB apache HTTP library, which seemed a little painful given that other than that, our app was ~50KB :(


> Example, the WebView has no way to return its HTML contents. So it's difficult to implement your own caching mechanism.

That's a feature to me. Respect my Cache-Control headers!


Look at it like this: if you need an IDE to get code written, things have gone off the rails. Most Android developers would be absolutely useless without code completion ..


I think it's "riskier" for Google to stick with anything Java related at this point. Even if it takes 5 years to make the switch, I think they should do it. They don't know what Oracle is going to do in the future against them. The recent win for Oracle has already showed them that they made a mistake not starting supporting Go 2-3 years ago when Oracle first sued them. This could end up costing them soon, but it could also get a lot worse. I think they can't afford not moving off Java. Plus, look how much excitement Apple caused with Swift for developers. They could do the same with Go for Android.


Dartlang is more appealing for mainstream programmer than GO, already has an IDE with debugging intellisense etc. and already has Android backend (see Dartlang source code)


Golang gets intellisense with with gocode. Go has some debugging with gdb and awesome profiling with pprof. While there isn't an official IDE, there are plugins for eclipse and IntelliJ. Go's approach makes it easier to use your favorite editor to code.


Given Google's relationship with Jetbrains for Android Studio how about Kotlin. Cut out Java entirely: Kotlin -> ART.

Kotlin seems approachable and modern. Also compiles down to JS.


They have already paid Oracle. That case is settled. How could it get worse?


No they haven't; the case is still ongoing, remanded to the district court.


Scala is also a good option. The g8 template for Android apps is at:

https://github.com/jberkel/android-app.g8


I thought about Scala, but the Scala plugin for Android Studio is rumored to be buggy and Scala doesn't integrate well with Gradle build system. At least I couldn't get it to work and I gave up after a while. If they (Google) wanted Scala to be supported on Android, they would make sure it isn't such a pain. And some documentation - all I could turn to for help is a handful of random blog entries etc.


This Libgdx sample worked better for me, although I had to remove a bunch of ios bits to get it to work on my non-mac.

https://github.com/ajhager/libgdx-sbt-project.g8


Thanks for the tip. Did you get it to work with Android Studio? (I guess guidelines for IntelliJ Idea would apply)


If you're writing C#, it's hard to believe you'd find Java challenging.


My guess is that that's his point. Java is easy to pick up, but the Android API is such a hurriedly-hacked-together piece of nonsense that it hurts.

Case in point: To make a list on Android, you need to jump through hoops, assign stuff to a "Tag" property (a field intended for hacks and workarounds), typecast your ass of, or if you don't do all that your list will perform absolutely shitty. So, the easy flow is a crappy, slow, buggy list. The "best practice" (which is not the easy flow, because hey, why would we make good stuff easy) is a "View Holder Pattern" [0] that involves using intended-for-hacks framework features.

On top of that, to my feeling there's also a big difference in quality between the enterprisey Java ecosystem and the Android ecosystem. Android-o-world is full of not-entirely-good advice and bad examples. Jumping into Android reminded me of past PHP experience: lots of well-meaning, but ultimately not-very-experienced people set the tone. Enterprisey Java might have AbstractFactoryFactoryProviders, but at least they have no buggy/wrong/hacky/insane code with 300 stackoverflow upvotes.

[0] https://developer.android.com/training/improving-layouts/smo...


> Case in point: To make a list on Android, you need to jump through hoops, assign stuff to a "Tag" property (a field intended for hacks and workarounds), typecast your ass of, or if you don't do all that your list will perform absolutely shitty. So, the easy flow is a crappy, slow, buggy list. The "best practice" (which is not the easy flow, because hey, why would we make good stuff easy) is a "View Holder Pattern" [0] that involves using intended-for-hacks framework features.

You don't have to do that. For a list with homogenous items you can use a regular ol' ListAdapter, implement getView sensibly (i.e. re-use views, which is very little work) and it will perform just fine. We tried this with a list of 2,000 items (each item had two TextViews and an ImageView) and it was completely fluid on a Samsung Galaxy Ace.

> Android-o-world is full of not-entirely-good advice and bad examples. Jumping into Android reminded me of past PHP experience

I could not agree with this more. I'd say somewhere around 2/3 of StackOverflow Android answers are downright wrong.


I dislike Android as much as the next guy, but you have to do some extra work to make UITableViews perform well in iOS as well.


You very, very rarely have to use the Tag property to make a list. You either use Tag as a View-cache system (the View Holder Pattern, which is total overkill these days), or because your data object model is broke as hell (aka, you suck at object design).

Everyone else just uses CursorAdapter which is easy to use and ties in nicely with things like Loaders and ContentProviders.


I'm reading into his comment that he dislikes the tedium of Java's verbosity e.g., getters, no var/auto, no LINQ, no delegates, etc.


That stuff plus the terrible state of datetimess and the lack of obvious operator overrides like being able to test string equality with ==.


Java's datetime API and (to some extent) collections were a cultural shock to me (coming from a .NET background) :)

That's why there are all these crutches like Joda, Guava etc.


You could always try the Xamarin way. Basically the same APIs, but with nicer languages (C# or F# instead of Java).


Yeah writing java for Android is a pretty awful experience. But it's not going away soon - this Go release will only have access to the things you can already do in C++ on Android. Namely, OpenGL, audio, and touch input. That's about it.

Anything GUI or system-related you have to do in Java. You won't be able to use Go to run other apps, enable wifi, receive GPS locations, communicate over bluetooth, etc. etc.

Qt is worth a look, but it's still not quite ready.


As a C# developer, have you looked at Xamarin? I have done several apps with it, shared code between iOS and Android. I highly recommend you give them a try.


Another .NET dev here in the same boat as OP. I really want to play with xamarin but the cost puts me off :(


> Holy crap, how do you people live like this?

The hole point is getting advantages. Lucky us that it's hard; others won't keep pace!




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: