does anybody know some http client libraries that have scalable, performant asynchronous support (including transparent handling of various issues, like too many requests pending etc.). A big plus would be if it would implement the CompletableFuture-interface (idk what it was called). Ideally with an easy, fluent api. I started with using unirest (http://unirest.io/java.html), but it behaved poorly under load (also no CompletableFuture-interface implementation).
easy integration into ratpack[1] non-blocking system. Propagation of the async-functionality through various classes without hardcoding an custom library-solution.
[1] https://ratpack.io Also clumsy api, but performant for the required workloads.
My biggest gripe isn't the massive API, it's the existence of the obtrude* methods - allowing a Future to change its completion result after it completes undermines the whole thing.
Retrofit has support for RxJava, both of which are mentioned on the list. If Retrofit deserializes your JSON response payload as type T, then upon making a request it will return an Observable<T> that will either emit the result (if the request succeeds) or emit an Exception (if it fails).
Most Android applications that rely on both Retrofit and RxJava use them together in this manner.
As for too many requests pending, I'm not sure if OkHttp (which Retrofit uses for making requests and is again on that list) is configurable in that regard. If you want to handle it at the application level, you could maybe model the request queue to the network layer as an Observable<Request> and use RxJava's backpressure operators.
For more information on functional reactive programming (which I would call promises or CompletableFuture done better), see http://reactivex.io/
Take it with a grain of salt because it's years since I used it, but the Jetty HTTP Client has a fluent API and can be used completely asynchronously. It doesn't use CompletableFuture, but it works with Java 8 lambdas and wouldn't be hard to adapt.
what did you notice with unirest under load? I've been using it a lot, and other than one or two little quirks I havent noticed perf issues. async calls can be a bit involved but I figured thats just java ;)
The slides which inspired this listing include Guava -- omitted from this list -- an invaluable utility toolbelt that I think is a spiritual re-imagining of Apache Commons (... don't read too much into my phrasing, a lot of Apache Commons also quite good, even if API tastes have changed since then).
I'll also note that Dropwizard, the framework, came about as an quickstart around an opinionated bundling of quality libraries. Dropwizard's appearance has resulted [1] in the development of Spring Boot, which lowered the barrier to generating Spring applications, arguably finally delivering on the 'convention over configuration' promise that Spring has long suggested it could do, but never quite found the sweet spot.
Guava is a notable absence to me. We use it all day every day at work.
Speaking of frameworks that Google uses, I'd have to recommend Dagger over Guice: https://google.github.io/dagger/ People tend to like it more, and it's gaining traction for the kinds of things that people used to default to Guice for.
Java 8 isn't supported quite yet on App Engine :-( Support is in beta, and should hopefully be available "for real" within months, but until it is, we're stuck with the old stuff.
I also wonder what kind of data migration we'll be facing, since all of our persisted data is from Joda DateTimes, not Java 8 ones. Hopefully none.
If your datetime is persisted ISO 8601 form, RFC 3339 form, some other unambiguously parseable string form, in epoch form, or as some database-native reliable datetime type, you'll be fine. But if by any chance it's Java-serialized Joda-Time objects, you're going to want to get them out of that form, as the Java-serialized forms are not compatible.
What kind of crappy library doesn't work on a newer version of Java?
The only thing I can see breaking would be reflection based invocations of new methods on existing interfaces (ex: Foo has a .bar() in Java 7 but not Java 6). You'd have to be doing something pretty unusual for that to bite you.
> What kind of crappy library doesn't work on a newer version of Java?
Oracle middleware libraries (to be fair, mostly acquired)...
I believe the problem was that in Java 8, something related to StringBuilder or string parsing was breaking hard. With Java7 it was ok, so we went with that.
Ah that's not a compatibility issues so much as a change in performance. I think they changed the defaults for String interning. In the vast majority of cases it's be a performance improvement but if you were manually managing lots of small Strings (ex: custom file processor reading misc user input) then it could get out of control.
So I noticed Guava missing and some other's have cited Joda and I think the real reason is that in 2017 between JSR310 and Java 8 the need for Joda doesn't exist in modern Java dev and a lot of the Guava functionality has been added into Java 8. Not all of it, but the biggest and most useful parts.
Some, but not most, of Guava functionality has been added to the standard libraries in Java 8. We'll still be extensively using it even after switching over to Java 8 specific features for Optional, Function, Date, and all the other goodies.
Its so incredibly refreshing when technologies are positioned by saying what they don't do.
When we describe our cool stuff to the world, its natural to go on and on about all the cool stuff it can do. But I'm more inclined to trust technologies that state clearly what they can't or don't do, or are not intended for.
I don't know if there is a name for this effect, but having only nodded at SL4J from a distance, I feel much happier about using it (or choosing not to) after reading this:
> In short, libraries and other embedded components should consider SLF4J for their logging needs because libraries cannot afford to impose their choice of logging framework on the end-user. On the other hand, it does not necessarily make sense for stand-alone applications to use SLF4J. Stand-alone applications can invoke the logging framework of their choice directly.
SLF4J is quality software, but it's quite ironic that it needs to exist at all, considering how much of both the Java mentality and the commercially significant Java EE platform is about coding against a well-defined interface that defines basic contract and semantics and allows the developer/customer/etc to supply their favorite and most-appropriate implementation of choice.
In the case of SLF4J, it was the community (or rather, Ceki Gülcü, the author of now-several logging frameworks, in response to his dissatisfaction with the community-led Apache Commons Logging) who stepped in to provide the 'generic' API, while Sun went and developed an actual 'hardcoded' implementation deliberately different from the popular third-party logging frameworks of the time instead and shipped it with Java 1.4.
I have no problem with this. At least this style of analytics makes it clear to both the reader of the URL and a casual observer that their visit is going to be catalogued as such, and for a careful clicker, easy to bypass.
I find this much more palatable than, say, Medium's pseudorandom tracking hash fragments that are spawned on each link share (harder to grok and recognize, but easy to bypass), or indecipherable URLs where it's impossible to tell where the substantive, deterministic portion ends and the tracking garbage begins.
The linked post is framed as a criticism of Guice but it's actually a criticism of Dependency Injection.
DI is one of those architectural tradeoffs that makes one thing easier (swapping out an alternate implementation) while making another thing harder (following execution paths), and trades imperative, prescriptive, top-down style with declarative, "loosely coupled", componentized, bottom-up style made possible by an overarching helper and externalized decision points that kinda-sorta act like configuration.
In my experience "swapping out an alternate implementation" happens so rarely that it isn't really worth the additional architectural complexity and making debugging harder.
Seems to me like DI (at least the heavy-handed Spring XML style of it) is a solution looking for a problem, but I've only worked at one company that used it heavily so I'd be happy for people to try to change my view.
"Swapping out an alternate implementation" sometimes means you shipped a bunch of components and the customer (who is not you, and doesn't necessarily have a direct line to you) can configure their software to enable or disable features.
By having externalized some of the tight coupling into some config file (like Spring's XMLs), they can go in and say that the AuthorizationFilter is OAuth20Filter instead of OAuth10Filter, or maybe their CookieParser is StrictRFCCompiantCookieParser instead of the WhateverGoesCookieParser.
The same would be doable if you compiled all this into code and only exposed some different config parameter that says "enforceRFC6265Cookies=true/false", but then the customer couldn't use some consultant company's SuperSpecialCustomCookieParser class in its stead, whereas with Spring they can.
But say none of this applies; DI is often used in testing. You can inject a mock class with next-to-no effort without having to figure out what to do about all of those StorageManagers whose hardcoded dependency is your ActuallyRealDatabaseStorageManagerImpl.
> In my experience "swapping out an alternate implementation" happens so rarely that it isn't really worth the additional architectural complexity and making debugging harder.
It happens all the time if you test your code with mocks and stubs.
It's really just a criticism of dependency injection /frameworks/.
Manually wiring dependencies by calling constructors is still dependency injection. This also has the upside that the compiler will check you have satisfied all dependencies, and you can more easily trace execution.
Frameworks like Guice/Spring are often used to hide lots of wiring boilerplate but come at a price of losing typesafety, adding more magic, and hiding some code smells. If your wiring is getting complex perhaps you need more modularity.
Your criticisms seem to only apply to runtime dependency injection frameworks. That's why I like Dagger, and recommended it elsewhere in this thread; it's compile-time dependency injection. So you do get type safety, the compiler does check that you have satisfied all dependencies, etc. Check it out if you haven't used it before.
Yes. If you do something wrong in your wire-up then the code won't even compile. Definitely look into it. Like you, I have a healthy distrust of DI frameworks because of the many errors that get pushed to runtime, but Dagger's not bad.
(Disclosure: I work on Dagger in my 20% at Google.)
What's more, Dagger gives you (compile-time) insights into the graph of dependencies.
For example, we've hooked up our internal code-search tool to give you Dagger cross-references, so if you (e.g.) click on a parameter to an @Inject constructor, you'll see the place that provides that object.
Also, if you click on the @Component, you'll see a visualization of the entire graph.
We're working on surfacing these hooks in the open source repo, which would allow IDEs like Eclipse to gain this functionality as well.
You aren't. 'lightweight' and 'dependency injection' reads like an oxymoron to me. The whole 'implicit dependency injection' seems as terrible an idea as getting an injection sounds. But it's out there so it's always interesting to hear more about it one way or the other.
I don't know your codebase, but I'm going to propose that your (and that blogger's) projects could be even messier without Guice. As the blogger points out, the "simple alternative to DI" is:
BillingService billingService = new BillingService(new BillingModule());
...which looks fine with just a couple layers of depth but becomes pathological with hundreds of objects, especially when they have different lifecycles. At some point the extra transparency you get from manual injection is overwhelmed by the sheer quantity of boilerplate.
To compensate, DI-less solutions end up with service discovery or "bag" classes like DropWizard's io.dropwizard.setup.Environment. Aside from the loss of encapsulation, what if you want to extend the framework with new components? You end up exposing services by setting attributes with text keys...
Having a messy Guice-based project doesn't mean it would be pretty without Guice.
The issue I have with DI frameworks is the annotation scanner scanning all jars in the classloader and annotation magic.
It seems that vanilla Guice does not need to fire up an annotation scanner that hits every jar, so that's good. It's been years for me, but I seem to recall Spring Framework does a brutal amount of jar crawling/annotation scanning by default. Unfortunately, it's very easy to corrupt Guice with annotation scanning - Netflix Governator will introduce a scanner for its magic annotations, for example.
As far as annotation magic is concerned, I think having an agreed-upon convention for DI can really help to keep things manageable and easy while still being able to unit test/inject mocks. For example, my team tries to only inject on constructor args. This makes it a no-nonsense affair to factor out features for a unit under test by passing in mocks for injected dependencies.
Testing complex systems, for me, is the killer app for DI - if I am writing something I need to test, I abhor the new keyword and FactoryFactories in my production code.
To me Guava is still the most essential, general purpose Java library. Not just for its collection package but because of the caching stuff, graph API, and well written general purpose utilities.
But I would also mention Spring 5 which I assume will be released soon, even though many people probably consider it too heavy or opaque at this point. But their major adoption and push towards reactive programming is interesting. And it will be interesting to see if java programmers embrace it. I'm a little skeptical that it provides enough tangible value to justify a more complex mental model, but maybe I'm wrong.
I have been using Google's AutoValue [1] instead of Project Lombok. It does not have as many features, but it makes creating model classes much easier.
The only really comparable replacement is Dagger, which does not provide AOP or any kind of web integration.
Dagger is cool, but Guice is still a better choice for most server-side apps. Maybe that will change in the future? They're pretty similar, so if Dagger "catches up" it won't be too hard to switch.
Vert.x lets you do most of those stuff such as HTTP, futures, P2P, pub-sub and more. It's event-driven and made for concurrency but you can easily run blocking code in it if you want to.
I think you can integrate it with existing projects to get those capabilities.
It also has tools for testing. It's well documented and with great examples (https://github.com/vert-x3/vertx-examples) so it's easy to learn based on my experience.
In casual parlance of terminology, Vert.x isn't really a library in the sense a dependency you pull in because it implements some specific functionality with a handful of method calls.
Vert.x "feels" more like a framework in the sense of giving your thought process and your application an architectural template and invites you to code in a style that it supports; but I also don't think 'framework' is a bad word. Realistically, Vert.x blurs the lines between a runtime, an event bus, a library, a framework, and a platform -- it's quite enjoyable to use, but despite their insistence to the contrary I don't think it's something that one should grab off the shelf and sprinkle into a larger product.
That's a better explanation clarifying its distinction between being a framework and library. Yeah, substantial amount of consideration should be taken before including it in a project. It's good though to have an option when you need it.
I've recently had to reacquaint with Java after 15 years, and Spark was a godsend. It's basically Flask for Java.
From an ease-of-use perspective, the closest I've found for the Java7 hell I currently inhabit is Ninja (http://www.ninjaframework.org), but it packs a lot of stuff that I don't necessarily need - it's more of a Django, let's say.
I've been doing a lot of stuff with DL4J lately and I have to say, I'm pretty impressed. The API seems very sane, it's very flexible, but yet it's easy to get a basic network up and running. The documentation is pretty good and there are a lot of videos from Adam up on Youtube showing off aspects of it. And it has native support for running on Spark with iterative parameter averaging, etc.
I honestly wonder why DL4J doesn't get more love... I'm guessing it's just the halo effect of being associated with "Java" which is no longer cool with the hipster crowd.
Why doesn't DL4J get more love? It's partially a Java/Python thing. A lot of research, maybe most, is being done in Python, even if that isn't ideal when you scale on a cluster. So we built a couple ways to smooth the workflow between Python and the JVM:
DL4J is the only DL library built by a startup without the backing of a major tech company or university. Google's pouring many millions of dollars into TensorFlow marketing, Udacity, etc. Microsoft and Amazon are backing CNTK and MxNet respectively. All those libs are loss leaders to get companies onto a vendor's public cloud, where they'll charge for the DL workloads.
Not trying to be an asshole here, but can a Java evangelist try to convince me to use it over C++ on linux - without invoking the garbage collector. (I've +17 years experience in C++ & Python on Linux & Windows + 18 years C# experience on Windows). In my experience, Java has made a number of poor decisions in the language (i.e. requiring exception specifications, disallowing value types, and the generics implementation is shit). Why use it other than "cross platform?" Build times are crap, almost (but not quite) as bad as C++. Why use it? I'll admit I've zero experience using other JVM hosted languages, so part of why I differentiate the JVM versus Java, the language.
you would use Java when you don't need explicit control of memory layout, and/or hard real time requirement. Java is much simpler to read and write, has many more libraries (which interoperate well together, unlike most C++ libs), and also many more developers to hire from. an all-around good choice.
Java is very good for enterprise development where the code has to be maintained. It's easier to read and contains less gotchas than C++. It is especially good when the team consists of people of varying coding competencies. Also nobody ever gets fired for choosing to develop using Java.
> Java is very good for enterprise development where the code has to be maintained. I often hear this, but I've yet to see an example of "good" enterprise java. Instead, I oft see a pile of shit built on top of some java framework, claiming to be maintainable. C++ may not be the best choice for web development (probably wouldn't be my first choice), but Java hasn't proven great, either.
> C++ may not be the best choice for web development (probably wouldn't be my first choice), but Java hasn't proven great, either.
Really? I feel like Java and the JVM are great for developing web apps with complex requirements, especially if they need to scale. Very few decent web development choices perform as well as the JVM does.
I mean, part of the reason that "enterprises" have "shitty enterprise Java" is because "enterprises" will create "shitty enterprise anything," and the Java implementation often performs better than the alternatives.
> Also nobody ever gets fired for choosing to develop using Java.
This is actually a negative. Java can be great if you have half-way decent people who make good choices with regards to libraries and frameworks and application servers and whatnot, but the choices that come from "nobody ever gets fired for" thinking are by far the worst ones.
Example: IBM WebSphere. "Nobody ever got fired for choosing IBM," but they absolutely should be if they choose this giant shitpile. Anyone who has chosen this shit should be thrown into a wood chipper, unless they specifically chose it waste the maximum amount of time possible. Or, if it was invented to set Soviet computing back 30 years like the IBM 360, except that joke doesn't work anymore because the Cold War ended before Java was even a thing.
Java was inspired by C++, wth three large additions, compile-once run anywhere (ergo JIT), GC, and memory safety. Throw the first two out the window and no wonder you aren't impressed.
I would add to that open source libraries which are (1) of high quality and (2) easy to pull in, e.g. Maven. The C++ ecosystem has no package manager, and people write header only libraries blowing up compilation times. With Maven, I can add Guava, Ehcahe, AWS SDK, etc. and their transitive department in about 60 seconds in a simple, consistent way.
Yeah, Java was inspired by C++, and the designers decided to take the worst ideas and run with them: such as exception specifications. C++ & C# both realized they were a bad idea, and decided to do away with them. Java generics are also fucked up. They could have followed C#, but no, they had to do their own model, and they fucked it up.
It was an honest mistake. I first tried .Net 1.0 while I was an intern at a Fortune 500 Comnpany. I first used it for a software engineering project (back when webforms were preferred).
Former 6+ year C++ programmer here who made the switch in the late 90s.
Fast build times. Removal of problematic/abused features like automatic type conversion and operator overloading. Never having to hunt down a segfault. Good reflection facilities. Well-structured exceptions (despite the 'checked' misfeature). Compiler error messages are almost always intelligible and obvious - when you see them, which is rare, because the IDE just underlines bad code. Add opensource libraries to do almost anything with just a line of xml.
You can work around checked exceptions by not using them, and Lombok eliminates most of the really annoying boilerplate (including checked exceptions with @SneakyThrows). The generics implementation isn't perfect but at least it doesn't require hours of parsing header files on every single build.
I work in finance, and I've cranked up warning levels to the max - I don't have any issues - except getting everyone on board. Once they realize why - it's smooth sailing. It can be hard when there is a language barrier, but you're best to combat it.
So, basically, you didn't actually want anyone to answer your original question, from what I can tell -- you just wanted to repeatedly affirm you were right-all-along?
2. Language agnostic; Common in other languages, but some avoid it by using
strongly typed enumeration instead of integer return type in comparison
functions.
6. Languages with pointer arithmetic, especially that the cast that losses
information is explicit.
8. It not at all obvious that silently ignoring the case failure is correct fix
for this, or if there is any issue here at all. Generally common to languages
with some kind of destructor and exceptions, though harmful in varying degrees.
11. Other languages generally make it impossible to write, or define order of
operations.
I think the most interesting observation you can make is how much of those
problems are caused by some form of implicit conversion between types (also
stopped after 20):
4. int -> bool
9. char -> *char
13. int -> bool
14. bool -> size_t
15. different enums
16. bool -> int
This generally agrees with bug log that I keep. Implicit conversions being one
of the most common source of problems in C/C++. When possible I just treat all
implicit conversions as errors using compiler flags and make all casts
explicit. Unfortunately this is something you can only do when working on new
projects, and hard to enforce in templates.
Other than Android Studio and Gradle, Java build times are actually quite fast. Just yesterday I gave up on compiling Cocos2d-x, after around one hour.
In Java I get to use the full language, not fighting with others about enabling RTTI and exceptions, or making proper use of C++ best practices instead of "C with C++ compiler".
Also unless one is stuck with one OS and one C++ compiler, writing portable C++ code across multiple OSes and compilers is either #ifdefs everywhere or constraining ourselves to the subset of common features.
Right now most commercial compilers for embedded systems are still on C++98.
I recently saw presentations from BMW and Sony, where they mention moving into C++11. Who knows when they will allow C++14 on their codebase, maybe when C++20 gets released, most likely.
If the code needs to be AOT compiled to native code, many third party JDKs do offer support for it, although they are mostly commercial.
Also, the use of header files were already outdated in the 80's, versus what languages like Modula-2 and Object Pascal supported. We will need to wait for C++20 to have proper modules, hopefully.
And best of all, no UB or compiler specific semantics, or change of language semantics between ISO revisions (auto vs decltype).
I still look forward to see value types and the new FFI in Java 10.
When I went back to C++ from Java (for a while), I just pretended it was Java, restricting myself to a rough subset of Java design idioms.
C++ (circa 2000) had too much latitude, too many sharp edges. Java's constrained design vocabulary allows you to focus more on the problem, less on the implementation. I blazed. My code was super maintainable.
I have no idea what C++ is like today.
I eschew meta programming. Huge distraction. Very difficult to grok other people's code. Java's progressive incorporation of declarative, dynamic features is regrettable.
Lombok is something I've been working with for a long time and I can say it's the only library I enjoy pulling in because of just how much it has to offer. Everything and two kitchen sinks.
Using the collections syntax and closures from Apache Groovy makes glue code, testing, and build scripts for the JVM easy to write, but the more recent features like those used in Spock are confusing. The Spock example in the post has the | operator overloaded so a function is called, a function name made up of 6 words separated by spaces (rather than using camelCase), and the label syntax triggering AST transformations to provide a new semantic context...
class HelloSpockSpec extends spock.lang.Specification {
def "length of Spock's and his friends' names"() {
expect:
name.size() == length
where:
name | length
"Spock" | 5
"Kirk" | 4
"Scotty" | 6
}
}
Wouldn't this be more straightforward and readable, without needing to rely on any of the confusing post-Strachan features added to Apache Groovy?...
def HelloSpockSpec () { //length of Spock's and his friends' names
def f = {name, length -> name.size() == length}
assert f("Spock", 5)
assert f("Kirk", 4)
assert f("Scotty", 6)
}
103 comments
[ 2.6 ms ] story [ 257 ms ] threadeasy integration into ratpack[1] non-blocking system. Propagation of the async-functionality through various classes without hardcoding an custom library-solution.
[1] https://ratpack.io Also clumsy api, but performant for the required workloads.
Most Android applications that rely on both Retrofit and RxJava use them together in this manner.
As for too many requests pending, I'm not sure if OkHttp (which Retrofit uses for making requests and is again on that list) is configurable in that regard. If you want to handle it at the application level, you could maybe model the request queue to the network layer as an Observable<Request> and use RxJava's backpressure operators.
For more information on functional reactive programming (which I would call promises or CompletableFuture done better), see http://reactivex.io/
And for more information on RxJava, see https://github.com/ReactiveX/RxJava
Apache's client doesn't have CompletableFuture, but it was easy to add one: https://gist.github.com/tomfitzhenry/4bb032f6a9f56d95f6fb544...
async-http-client is the HTTP client used by Gatling (same developer, in fact).
I'll also note that Dropwizard, the framework, came about as an quickstart around an opinionated bundling of quality libraries. Dropwizard's appearance has resulted [1] in the development of Spring Boot, which lowered the barrier to generating Spring applications, arguably finally delivering on the 'convention over configuration' promise that Spring has long suggested it could do, but never quite found the sweet spot.
[1] https://news.ycombinator.com/item?id=12283230#12286948
Speaking of frameworks that Google uses, I'd have to recommend Dagger over Guice: https://google.github.io/dagger/ People tend to like it more, and it's gaining traction for the kinds of things that people used to default to Guice for.
Oh, and the JODA DateTime/Money libraries.
And as all prior versions of Java are EOL there's no reason not to be using Java 8.
I also wonder what kind of data migration we'll be facing, since all of our persisted data is from Joda DateTimes, not Java 8 ones. Hopefully none.
That's not just for just dates or timestamps either. That's for data period.
It makes a whole lot of things that ought to be simple a lot harder.
http://openjdk.java.net/projects/jdk9/
I wish. When life (or rather a vendor) gives you java 6 libs which barely work on java 7, you make java7 lemonade.
The only thing I can see breaking would be reflection based invocations of new methods on existing interfaces (ex: Foo has a .bar() in Java 7 but not Java 6). You'd have to be doing something pretty unusual for that to bite you.
Oracle middleware libraries (to be fair, mostly acquired)...
I believe the problem was that in Java 8, something related to StringBuilder or string parsing was breaking hard. With Java7 it was ok, so we went with that.
When we describe our cool stuff to the world, its natural to go on and on about all the cool stuff it can do. But I'm more inclined to trust technologies that state clearly what they can't or don't do, or are not intended for.
I don't know if there is a name for this effect, but having only nodded at SL4J from a distance, I feel much happier about using it (or choosing not to) after reading this:
> In short, libraries and other embedded components should consider SLF4J for their logging needs because libraries cannot afford to impose their choice of logging framework on the end-user. On the other hand, it does not necessarily make sense for stand-alone applications to use SLF4J. Stand-alone applications can invoke the logging framework of their choice directly.
In the case of SLF4J, it was the community (or rather, Ceki Gülcü, the author of now-several logging frameworks, in response to his dissatisfaction with the community-led Apache Commons Logging) who stepped in to provide the 'generic' API, while Sun went and developed an actual 'hardcoded' implementation deliberately different from the popular third-party logging frameworks of the time instead and shipped it with Java 1.4.
https://github.com/real-logic
Aeron - Efficient reliable UDP unicast, UDP multicast, and IPC message transport
Simple Binary Encoding (SBE) - High Performance Message Codec
Agrona - High Performance data structures and utility methods for Java
Here is an aeron microbenchmark: https://github.com/benalexau/rpc-bench
Of note is akka uses it for its internal remoting: http://blog.akka.io/artery/2016/12/05/aeron-in-artery
We will be using it for RPC and distributed deep learning: http://engineering.skymind.io/interview-with-adam-gibson-cre...
?utm_source=ycombinator
I find this much more palatable than, say, Medium's pseudorandom tracking hash fragments that are spawned on each link share (harder to grok and recognize, but easy to bypass), or indecipherable URLs where it's impossible to tell where the substantive, deterministic portion ends and the tracking garbage begins.
As a Scala developer, this is a life saver.
http://omaritech.blogspot.com/2014/03/why-google-guice-is-ev...
Am I in the minority here? Do most people really think that the Guice framework approach is a good idea?
DI is one of those architectural tradeoffs that makes one thing easier (swapping out an alternate implementation) while making another thing harder (following execution paths), and trades imperative, prescriptive, top-down style with declarative, "loosely coupled", componentized, bottom-up style made possible by an overarching helper and externalized decision points that kinda-sorta act like configuration.
Seems to me like DI (at least the heavy-handed Spring XML style of it) is a solution looking for a problem, but I've only worked at one company that used it heavily so I'd be happy for people to try to change my view.
By having externalized some of the tight coupling into some config file (like Spring's XMLs), they can go in and say that the AuthorizationFilter is OAuth20Filter instead of OAuth10Filter, or maybe their CookieParser is StrictRFCCompiantCookieParser instead of the WhateverGoesCookieParser.
The same would be doable if you compiled all this into code and only exposed some different config parameter that says "enforceRFC6265Cookies=true/false", but then the customer couldn't use some consultant company's SuperSpecialCustomCookieParser class in its stead, whereas with Spring they can.
But say none of this applies; DI is often used in testing. You can inject a mock class with next-to-no effort without having to figure out what to do about all of those StorageManagers whose hardcoded dependency is your ActuallyRealDatabaseStorageManagerImpl.
It happens all the time if you test your code with mocks and stubs.
Manually wiring dependencies by calling constructors is still dependency injection. This also has the upside that the compiler will check you have satisfied all dependencies, and you can more easily trace execution.
Frameworks like Guice/Spring are often used to hide lots of wiring boilerplate but come at a price of losing typesafety, adding more magic, and hiding some code smells. If your wiring is getting complex perhaps you need more modularity.
What's more, Dagger gives you (compile-time) insights into the graph of dependencies.
For example, we've hooked up our internal code-search tool to give you Dagger cross-references, so if you (e.g.) click on a parameter to an @Inject constructor, you'll see the place that provides that object.
Also, if you click on the @Component, you'll see a visualization of the entire graph.
We're working on surfacing these hooks in the open source repo, which would allow IDEs like Eclipse to gain this functionality as well.
To compensate, DI-less solutions end up with service discovery or "bag" classes like DropWizard's io.dropwizard.setup.Environment. Aside from the loss of encapsulation, what if you want to extend the framework with new components? You end up exposing services by setting attributes with text keys...
Having a messy Guice-based project doesn't mean it would be pretty without Guice.
It seems that vanilla Guice does not need to fire up an annotation scanner that hits every jar, so that's good. It's been years for me, but I seem to recall Spring Framework does a brutal amount of jar crawling/annotation scanning by default. Unfortunately, it's very easy to corrupt Guice with annotation scanning - Netflix Governator will introduce a scanner for its magic annotations, for example.
As far as annotation magic is concerned, I think having an agreed-upon convention for DI can really help to keep things manageable and easy while still being able to unit test/inject mocks. For example, my team tries to only inject on constructor args. This makes it a no-nonsense affair to factor out features for a unit under test by passing in mocks for injected dependencies.
Testing complex systems, for me, is the killer app for DI - if I am writing something I need to test, I abhor the new keyword and FactoryFactories in my production code.
But I would also mention Spring 5 which I assume will be released soon, even though many people probably consider it too heavy or opaque at this point. But their major adoption and push towards reactive programming is interesting. And it will be interesting to see if java programmers embrace it. I'm a little skeptical that it provides enough tangible value to justify a more complex mental model, but maybe I'm wrong.
[1] https://github.com/google/auto/tree/master/value
Dagger is cool, but Guice is still a better choice for most server-side apps. Maybe that will change in the future? They're pretty similar, so if Dagger "catches up" it won't be too hard to switch.
http://vertx.io/
Vert.x lets you do most of those stuff such as HTTP, futures, P2P, pub-sub and more. It's event-driven and made for concurrency but you can easily run blocking code in it if you want to. I think you can integrate it with existing projects to get those capabilities. It also has tools for testing. It's well documented and with great examples (https://github.com/vert-x3/vertx-examples) so it's easy to learn based on my experience.
Anyone here who also experienced using Vert.x?
Vert.x "feels" more like a framework in the sense of giving your thought process and your application an architectural template and invites you to code in a style that it supports; but I also don't think 'framework' is a bad word. Realistically, Vert.x blurs the lines between a runtime, an event bus, a library, a framework, and a platform -- it's quite enjoyable to use, but despite their insistence to the contrary I don't think it's something that one should grab off the shelf and sprinkle into a larger product.
http://sparkjava.com
From an ease-of-use perspective, the closest I've found for the Java7 hell I currently inhabit is Ninja (http://www.ninjaframework.org), but it packs a lot of stuff that I don't necessarily need - it's more of a Django, let's say.
http://netty.io/
CompletableFuture is becoming supported in a bunch of other libraries: https://github.com/AsyncHttpClient/async-http-client/, https://github.com/ben-manes/caffeine , https://github.com/mp911de/lettuce .
I honestly wonder why DL4J doesn't get more love... I'm guessing it's just the halo effect of being associated with "Java" which is no longer cool with the hipster crowd.
https://gitter.im/deeplearning4j/deeplearning4j
Why doesn't DL4J get more love? It's partially a Java/Python thing. A lot of research, maybe most, is being done in Python, even if that isn't ideal when you scale on a cluster. So we built a couple ways to smooth the workflow between Python and the JVM:
Model Import from Keras (and TensorFlow and Theano) https://deeplearning4j.org/model-import-keras
Keras API for Deeplearning4j (WIP) https://github.com/crockpotveggies/dl4j-examples/tree/keras-...
DL4J is the only DL library built by a startup without the backing of a major tech company or university. Google's pouring many millions of dollars into TensorFlow marketing, Udacity, etc. Microsoft and Amazon are backing CNTK and MxNet respectively. All those libs are loss leaders to get companies onto a vendor's public cloud, where they'll charge for the DL workloads.
Really? I feel like Java and the JVM are great for developing web apps with complex requirements, especially if they need to scale. Very few decent web development choices perform as well as the JVM does.
I mean, part of the reason that "enterprises" have "shitty enterprise Java" is because "enterprises" will create "shitty enterprise anything," and the Java implementation often performs better than the alternatives.
This is actually a negative. Java can be great if you have half-way decent people who make good choices with regards to libraries and frameworks and application servers and whatnot, but the choices that come from "nobody ever gets fired for" thinking are by far the worst ones.
Example: IBM WebSphere. "Nobody ever got fired for choosing IBM," but they absolutely should be if they choose this giant shitpile. Anyone who has chosen this shit should be thrown into a wood chipper, unless they specifically chose it waste the maximum amount of time possible. Or, if it was invented to set Soviet computing back 30 years like the IBM 360, except that joke doesn't work anymore because the Cold War ended before Java was even a thing.
I would add to that open source libraries which are (1) of high quality and (2) easy to pull in, e.g. Maven. The C++ ecosystem has no package manager, and people write header only libraries blowing up compilation times. With Maven, I can add Guava, Ehcahe, AWS SDK, etc. and their transitive department in about 60 seconds in a simple, consistent way.
I think the whole eco-system (including dependency management with maven) is definitely worth acknowledging the value of.
As far as I remember C# came out in 2000.
https://blogs.msdn.microsoft.com/dotnet/2017/02/13/happy-15t...
Fast build times. Removal of problematic/abused features like automatic type conversion and operator overloading. Never having to hunt down a segfault. Good reflection facilities. Well-structured exceptions (despite the 'checked' misfeature). Compiler error messages are almost always intelligible and obvious - when you see them, which is rare, because the IDE just underlines bad code. Add opensource libraries to do almost anything with just a line of xml.
You can work around checked exceptions by not using them, and Lombok eliminates most of the really annoying boilerplate (including checked exceptions with @SneakyThrows). The generics implementation isn't perfect but at least it doesn't require hours of parsing header files on every single build.
I don't miss C++ at all.
https://software.intel.com/en-us/articles/the-ultimate-quest...
I estimate that 70% of those errors just cannot happen in Java.
1 - Language agnostic
2 - Agnostic - Java doesn't have memcmp but the same issue returning (-1, or < 0) could happen
3 - Agnostic (with the exception that java would throw for out of bounds)
4 - Agnostic
5 - Agnostic - Its a windows complication (you can write C++ without DllMain even in windows)
6 - C++
7 - C++
8 - C++
9 - C++
10 - C++
11 - C++
12 - Agnostic
13 - Agnostic
14 - Agnostic
15 - C++
16 - Agnostic
17 - Agnostic (java has similar optimizations)
18 - Agnostic (inefficient code happens in any language)
19 - C++
20 - C++ (maybe java would throw instead?)
... This is longer than I thought.
9 of the first 20 are C++ only.
6. Languages with pointer arithmetic, especially that the cast that losses information is explicit.
8. It not at all obvious that silently ignoring the case failure is correct fix for this, or if there is any issue here at all. Generally common to languages with some kind of destructor and exceptions, though harmful in varying degrees.
11. Other languages generally make it impossible to write, or define order of operations.
I think the most interesting observation you can make is how much of those problems are caused by some form of implicit conversion between types (also stopped after 20):
This generally agrees with bug log that I keep. Implicit conversions being one of the most common source of problems in C/C++. When possible I just treat all implicit conversions as errors using compiler flags and make all casts explicit. Unfortunately this is something you can only do when working on new projects, and hard to enforce in templates.Other than Android Studio and Gradle, Java build times are actually quite fast. Just yesterday I gave up on compiling Cocos2d-x, after around one hour.
In Java I get to use the full language, not fighting with others about enabling RTTI and exceptions, or making proper use of C++ best practices instead of "C with C++ compiler".
Also unless one is stuck with one OS and one C++ compiler, writing portable C++ code across multiple OSes and compilers is either #ifdefs everywhere or constraining ourselves to the subset of common features.
Right now most commercial compilers for embedded systems are still on C++98.
I recently saw presentations from BMW and Sony, where they mention moving into C++11. Who knows when they will allow C++14 on their codebase, maybe when C++20 gets released, most likely.
If the code needs to be AOT compiled to native code, many third party JDKs do offer support for it, although they are mostly commercial.
Also, the use of header files were already outdated in the 80's, versus what languages like Modula-2 and Object Pascal supported. We will need to wait for C++20 to have proper modules, hopefully.
And best of all, no UB or compiler specific semantics, or change of language semantics between ISO revisions (auto vs decltype).
I still look forward to see value types and the new FFI in Java 10.
When I went back to C++ from Java (for a while), I just pretended it was Java, restricting myself to a rough subset of Java design idioms.
C++ (circa 2000) had too much latitude, too many sharp edges. Java's constrained design vocabulary allows you to focus more on the problem, less on the implementation. I blazed. My code was super maintainable.
I have no idea what C++ is like today.
I eschew meta programming. Huge distraction. Very difficult to grok other people's code. Java's progressive incorporation of declarative, dynamic features is regrettable.
My production code is a mix of Java and Scala, and I found Groovy to hit sweet spot for testing.
[1] https://github.com/google/guava/wiki/EventBusExplained
[1] https://github.com/google/guava/wiki/ListenableFutureExplain...