Android and iPhones and Web, oh my
It's regularly asked why J2ObjC purposely avoids translating UI code; after all, wouldn't it be wonderful if a tool existed where a developer can drop in Android source and out pops an iOS app? Our usual response is that world-class apps need user interfaces that are tightly integrated with each platform, and that common-denominator attempts to span platforms provide degrades user experiences. As I found when working on Swing many years ago, customers notice the smallest deviations from a platform's UI standards and generally find them off-putting. But non-compromising UIs are just one of the reasons we focus on translating shared logic.
The pressure for platform-independent apps is due to the cost and effort to create separate versions for each platform. This is especially true for the non-UI parts of the app, where the logic is identical but must be rewritten in different languages for Android, iOS, and browsers. Software development is expensive, and this sort of redundancy is wasteful, risky, and perhaps most important to developers, mind-numbingly boring. The Don’t Repeat Yourself principle is very applicable when building apps for multiple platforms.
Additionally, there are hidden costs due to differences between an app on different platforms: missing functionality, unique bugs, etc. Your marketing people will (should) argue that this weakens the app's brand; in other words, its reputation among its current and potential customers. When an app behaves differently on different platforms, it’s often perceived as being lower-quality than its competitors.
J2ObjC was created to help address the problems associated with independent releases, without sacrificing the requirement for world-class, platform-specific user experiences. It's goal is to provide a GWT-like translator and runtime, so iOS apps can be designed to share as much Java code as possible without compromising best-of-breed user interface designs. The key word in the previous sentence is designed, because as software engineers know, reusability needs to be an important design goal and not just an afterthought.
We’ve found that test-driven development really helps support code reuse, because there is a huge overlap between testable and portable code. If code is hard to test, it's also likely to be difficult to use on other platforms; UI and networking code in particular are difficult to unit test easily. By writing tests as the design is being implemented, this difficulty encourages hard-to-test code to be isolated from more easily tested code. Often, the design can be improved to further isolate hard-to-test code and thereby increase sharing, such as using dependency injection or mock objects in tests. Software development is challenging enough without sticking to designs that create unnecessary work.
Hopefully this clarifies J2ObjC's objectives. It's why we consider it more of a compiler than a source translator, since the output that matters most is what winds up in each app build, not how pretty the intermediate Objective-C looks (though it's very useful to inspect generated code). It's why the JUnit and Mockito libraries were added before many JRE classes. And it's why we open-sourced J2ObjC; the software engineering community developed all these best practices we rely on, and as community members it's important we help improve them further.