I currently work at a small company where we mostly work with Java 8 and Spring (Boot). I learned a lot in the eight weeks of development I did now.
The framework is really awesome in the way how they do things. Something like the Spring Data CrudRepository. I find it fascinating to see how I only define a method in an interface which then just works. Only issue: damnVeryLongMethodNamesWhereAColumnIsLikeVeryAwesomeButIWantToOrderWithThatAndThenDoThisAndThat();
But then just annotate a method. It is fun, and is really fun to explore and learn to work with the framework. I am loving my job and the way my career starts.
My personal goals currently are to get into Java and Spring. Just so I should be able to build a whole project by myself as a developer (with the designs from a designer). If that goal is reached, I want to start working on my knowledge on .NET Core as that is the 'other camp'.
For now: Using IntellJ + Java 8 + Spring = AWESOMENESS.
So we use java 8 and lambda there. We don't really use lombok, but our data domain is generated and does more boilaplate generation than that. Lamda expressions are powerful if you don't stick to legacy java collection API. It make code much shorter lighter/readable if you don't abuse it. Don't do a 10 deep deep lambda expression in a one liner or in a single method like you wouldn't do a 10 folded loops neither.
We enforce absolutely itf/impl separation because that the most powerfull tool at our disposal to keep a multiperson project really modular. And for that we need both interfaces and impl in separate mvn projects. The impl project has scope runtime, so only spring with its classpath scanning actually see it. But then the itf are needed to access the impl. Pending Java9, or using even more complex OSGI, I don't know of a way to enforcing the rule that you do not access other modules implementation.
We ensure that most objects ref are never null in our business domain so we can alway do things like a.getB().getC().setD(ddd) without having to check if B/C/D exist and if there a collection in the middle we can then write a.flatMap(A::getB).flatMap(B::getC).forEach(c -> c.setD(xxx)) if we want to update everything deep in a complex object tree structure with a one liner.
Object relationnal mapping is nice, but from experience it is extremely easy to get very low performance out of it for any non trivial work. The generated DB is also hard to maintain and evolve in production, to write the migration scripts and all. I'd advise to design the DB completely separately from the code, to optimize it for the queries you need and check with you DBA how to get the most out of it. You'd map you data objects structures to the actual queries inputs/ouputs rather than tables. Because that's what matter. You'll get several order of magnitude better performance.
spring itself is really valuable as well as annotations but they tend to lead to subtle bugs on the occasion and quite subtle performance problem too. It is common from one person to strugle for 2 day to map a basic property file to a spring bean because it doesn't work for some reason while it is done in 5 minutes with getResource and the use of the proper parser of choice (JaxB, Jaxson...). We do use spring for dependency injection among service, it is our prefered choice for itf/impl pattern we use but we try to avoid it inside components. This make the code more straightforward and easier to understand, keep the number of beans to wire under control so that you server doesn't take 30 second just for spring initialization at boot time and slow your whole day to day dev activities too much.
I'd say in the end this depend a lot of your applications, your requirements and all. We are sentisitive to performance because basically a single client already ask for 6000TPS for our service and if this service is a success in the company, we will be soon at 15K-30Ktps, growing 50-60% a year. Soon the amount of servers to buy, replace and the power consumption requirement are costing much more than the easier dev practices that hurt performance too much.
But that depend of each project. What are the requirements, the size of team, the expected code size base, the kind of stuff you do and so on...
Thanks for your reply.
I wonder what you mean by “multi person project”. We do work on projects in a scrum team with 3-6 developers. At that size, there is absolutely no issue with not having interfaces. Less interfaces means less code to maintain and less complexity when understanding and navigating through the code.
Same goes for JPA and performance, we’ve actually had very complex queries modeling a kind of hierarchy and using lazy loading, it was very fast and very handy.
So, basically, I would not start optimizing for theoretical modularity nor performance without actual issues or requirements.
"So, basically, I would not start optimizing for theoretical modularity nor performance without actual issues or requirements."
And you are right. Because you don't need it, apparently.
On our side we have requirements for performance and scalability.
With the experience, you know what works and what don't.
So yes when I think about a multi person product I think dozen, hundred, not 3-6. Sure each team/project maybe 1-10 persons, but you may have 20 at the same time.
When a product is successful there, it means it is used wordwide by millions of end users. We need to be able to serve the internet. 10% decrease in performance means several millions euros for the machines, the electricity and so on.
That's the biggest issues of advices, what works, what not. But what are the circonstances ?
For you, all that fuss would make you less productive because you are a small team and there no req. for performance. You don't need modularity because the code base is small. For my company, your methods would work for a prototype, no more.
For a company like airbus or thales that design auto pilots au make lot of embedded devices software, your methods of mine would make absolutely no sense. Each line of code is validated and revalidated. The same product has several implementation running at the same time by different teams and languages so that if one autopilot fail, the other one can be used instead.
For many startups and geeks, using Java and so on would again make no sense. They would do it in haskell or lisp and would go 10 time faster than you, 100 time than my company.
That the whole argument about theses thing. Nothing absolute.
Excellent article. Thanks for taking the time to write this. Lombok is something new to me :D
Just saw the broken formatting starting at the Lombok section, now it’s fixed. 😉
I feel the same way, Java 8 and spring boot absolutely blew my mind, I used to have a closed mind towards Java due to previous experiences and now I am truly enjoying it, loved your post :)
And what about the client side? JSTL? or what?
We actually use Angular 4 with Typescript which pretty much looks like Java/Spring Code. If you don’t want to use rich clients, maybe Vaadin or Thymeleaf might be an option. Vaadin allows rapid prototyping but if you need to implement UX requirements and designs 100% accurately you might get in some trouble.
Nice article. I see a small typo above. I believe 'boostrap' should be 'bootstrap'.
Great, thanks for the feedback, I corrected the typo!
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.