Ask HN: Enterprise Java guy needs advice on what to transition to
I have made my living doing Java enterprise development for big companies for the past 10+ years. I can sense the world is changing (much like when I transitioned from C/C++ to Java) and that I need to make a change. Frankly I am tired of all the complexity and over engineering of enterprise Java. For all the effort, I find most apps are large (1+ MLOC), monolithic, hard to understand and maintained by large groups of onshore/offshore resources who just keep the stuff running by sheer numbers and have no pride in their craft. I want to do something better as I still have about 20 years left in my working life. I have played around with Python and like it but not sure how it will scale up to a large project. Any advice appreciated, especially from those who have already made the transition.
56 comments
[ 2.0 ms ] story [ 107 ms ] threadAlso, there are a lot of interesting infrastructure projects written in Java (Hadoop, Lucene, Cassandra etc). It's pretty easy to get started in any of them.
If you really want to do a new language then I doubt you'll find many people arguing against Python. But the real action is in Javascript (both server & clientside)
But then that is just me.
Disagreed. Theres much more that needs to be programmed. Think of devices, health information systems, traffic routing etc.
"Most things are web nowadays" is often said, but just wrong.
Beyond that I would agree with earlier commentators that the real action over the next few years will be in JavaScript. Both server and clientside. The former being particularly interesting.
Try various things, and pick one that actually gets you excited, and makes you think "wow, this is so cool" - not something that makes you think "well, the market seems to be moving in this direction, so there'll probably be decent money there".
For one off stuff I usually use ruby nowadays, and if mobile would not be my thing, I'd definitely be delving in to Rails (have some previous experience here) and Node.js.
I've done some projects in Django but didn't really dig that as much. There's a ton of Python frameworks out there though, and Python the language is pretty cool to work with and a breath of fresh air if Java has been your mainstay for the last decade.
As far as scaling to a big enterprise project, not sure yet.
Given your java background have you compared groovy/scala/erlang to python yet?
While I do code android applications I am going through the same evaluation process for my server side development.
Groovy is nice in that I get to re-use Spring/Hibernate EJB, etc while having the features of an object oriented scripting language DSL and Grails has a good set of MVC features.
Python seems a little rough if you are re-using legacy java however jython does function and I guess one could build up jython stuff to handle legacy java enterprise.
Scala and Erlang seem interesting both attempting to solve same and similar problems in different ways implementation language wise.
Zed Shaw has some notes on enterprise coding with python, which are worth a read. I would also not rule out new C++ frameworks as Google still uses a lot of C++ in enterprise with good results.
If by scaling you mean how to organize a large codebase, IMO, it is not hard at all and usually the python codebase is much smaller than a similar java project.
I'd stay away from Groovy etc.
Also, please get over that "scaling" stuff. PHP scales just fine. Rails scales just fine. Python scales just fine.
This should get you away from the overengineering that Java seems to attract and there are plenty of Rails jobs out there (certainly more than there are Grails jobs anyway).
Whilst you are at it pick up some new technologies such as mongodb.
It would be good for your soul (and skill as a programmer) to try something new, completely new. You could of course also learn ObjectiveC++ and become an iPhone developer. Whatever you pick make sure that it puts fear in your heart, something that will challenge you. A mountain to climb rather than molehill.
There are various interesting technologies that COULD replace Java or at least JEE in the future, and it is certainly a good idea to learn them or do projects in your spare time. But beside Java, I don't think that there is any technology that you can be sure that it will be still around in 5-10 years.
If you are just sick of Java and need some change, then try to find a new job where you can work with whatever you like. Java changes pretty slowly, and you can still change your mind a few years later and find a Java job. But if you need to decide for a language as a career-choice, stick with Java, at least for a few more years.
I don't really see why you have to bind yourself so hard to a language/platform/whatever. You don't have to be a "Java programmer" or a "Python programmer". Instead aim to become someone who can move around and choose whatever is best for the job, or whatever the job might require. In the end it's just programming, different types of programming sure but never forget that you're basically doing the same thing in a different way. When you see that you realize languages are just tools for you to use, not the other way around.
The first step IMO would be to expand your horizon, see what else is out there. Try out the exotic languages you see everyone rave about, give Python a blast or drive Ruby for a while. Do things in Erlang or Haskell just because it's different from Java and mix web development with low level or simply make a game or a program you've always needed.
When you know what's out there, when you've gotten your feet wet, then you can focus in on something a bit more. The thing that has kept my interest in programming alive is I've always done what's fun, and I can only imagine that's even more important for someone with 10+ in the business actually working with it. So choose something you feel is fun, oddly for me the funniest things are the new and different stuff (Haskell for example).
Long story short: Don't be an "X programmer", be a "programmer" and go where the fun is!
Best of luck to you.
In addition to reusing my previous expertise, there are four thing I really like about it:
* Convention over Configuration makes things so much simpler * Groovy Language has a lot of great features, allowing for much more concise code (though it does take some time to get used to dynamic typing) * Plugin ecosystem - over 500 plugins on various topics allow you to get things done much quicker. The plugin architecture is wonderful and allows you to compose your from reusable blocks, which could have their own UI. Best actual (as oppoed to theoretical) code reusability I've ever seen * GORM (object relational mapper) is a thing of beauty. It's fairly implementation-agnostic, so you can use it with Relational DBs, switch to Mongo or Reddis as the persistence backend fairly easily.
Definitely recommend you check it out. In terms of jobs, it's not as big of a community as Java yet, but I definitely see many jobs advertising those skills.
I'd recommend taking a look at JRuby. It works nicely with Java libraries and loading Java classes. You don't have to deal with dependency injection. Variables aren't typed, values are. Class and instance methods are managed in the same class declaration. Classes can be easily extended. Classes are loaded into constants at runtime - instance objects are created (and constructor called) by calling the "new" method on a class constant (hence no dependency injection required). Class methods can't be called by an instance objects and vice versa.
While JRuby would be new to you, it's on a familiar platform. http://jruby.org/
Suppose you have two different ways of gaining information about a logged in user. Let's say one goes to LDAP, and the other goes to an RDBMS. You'll be using one or the other depending on where the software is installed.
So in Java, you create an interface that defines the methods you'd need to identify and retrieve a User, and you write an LDAP and an RDBMS implementation. The code deals only with the interface, never the implementation directly. So if you want to switch them, you just create a setter (assuming we're using setter injection) and notify your DI container of which implementation should be injected.
I definitely get it that in a language with duck typing, there's no need for the interface/implementation gymnastics. You can just pass whatever class you want, and as long as it responds to those method calls, you're golden. So in that sense, DI isn't really an issue.
But what about the nice decoupling you get - is there any easy way to swap out a particular implementation in Rails? I'm trying not to think too much in Java here, it's more of a general problem, definitely doesn't mean I'd necessarily want to force DI onto a language that takes a completely different approach to things...
Sorry to get so technical here, just seems like you might have some insights into this.
Implementations aside, when you do DI in Java, it serves two purposes: 1) instantiates an object and 2) wires it into another object. Remember that in Java, each class is in it's own file. In ruby, you can break classes into several files, but you don't have to. Ruby simply reads class declarations at runtime and instantiates those classes into constants. This means that your classes are always available. If you've defined a class method, you can call SomeClass.some_class_method. If you want to work with an instance of that class, you would call SomeClass.new - to which you can pass args to a constructor.
In your instance, you could have three classes - User, UserLdap, and UserDb. You might call User.find( person ), and in the find method you would test your conditional on whether to use UserLdap or UserDb. If you had common methods you wanted to share between the two, you could place those in User and extend that class for use with an instance object. Another option for sharing methods cold be to place them in a module, which you can then include in your class.
It's hard for me the make a recommendation for your specific problem at hand. My best advice is to read up and Ruby a little and begin to put what you learn into practice. Here's a couple of recommendations:
http://www.humblelittlerubybook.com/
http://mislav.uniqpath.com/poignant-guide/
My light bulb moments were realizing that all class declarations are loaded as constants at runtime and class & instance methods are also managed in the same class declaration. HTH.
I'm kind of following you - unfortunately, I don't know ruby well enough to understand what you mean when you say class declarations are loaded as constants at run time, but I'll definitely look into it.
I think there's a third purpose to DI that you didn't mention. The container does instantiate an object and inject it ("wire it") into another object, but the real benefit is that you can externally configure which object to swap in. That last part might matter less in a language that doesn't have to be compiled but it can still be valuable if you have a lot of different implementations that need to be swapped in/out in different deployments.
The method you described for person - testing a conditional - do you mean you'd create a method with a conditional, and choose which implementation to use based on that conditional? I've done this, and it certainly works, but it isn't really a placement for DI (this sounds more like a factory method, though again I don't think that those really exist to the same extent in ruby since duck typing is much more flexible than static typing). My problem with this approach (if I understand it right, which I'm not sure I do) is that this would lead to a very long series of conditionals to load the right class. In rails, I'd probably be looking to pull them out into a yaml file (something like the applicationContext file in Spring).
Let's say I create a class called User. When ruby sees that declaration, it creates a constant called User to contain that object. When I create a new instance:
user = User.new
"User" is a constant whose value is the object/class. "new" is a method that calls the constructor (if one exists) and creates a new instance. The same applies when you call something like:
User.find
You're not calling find() on an instance, you're calling it on the object that's loaded into the constant "User". The class declaration "class User" is saying User is the name of the class; User is also the constant in which it's stored. It's also what allows you to reopen a class on the fly to extend it with more methods.
"I think there's a third purpose to DI that you didn't mention. The container does instantiate an object and inject it ("wire it") into another object, but the real benefit is that you can externally configure which object to swap in."
True, but I've never found myself switching objects out on a regular basis.
As you mentioned, the conditional approach probably isn't the best. What I'm assuming now is that you're based on your deployment, you might use a different bean factory configuration file? And this works as long as UserLdap and UserDb implement the same interface?
That being said, instead of sprinkling conditionals throughout user, you can dynamically assign User initially.
User = UserDb
OR
User = UserLdap
and as long as UserDb or UserLdap had a find() method, you could then call
User.find
Remember, User is now a constant that references the same value as UserDb or UserLdap
Does that help clarify?
It does help clarify this, thanks. It does still leave the problem that you have to specify the "type" in the code and can't swap it out. That said, I think this could probably be handled easily with a yaml file (just specify the class you want to instantiate every time a user is created)? I may try that some time.
You'll get a fun development environment, a less formal language. The big plus for you is that JRuby has wonderful Java integration, so you'll be able to use all the Java libraries and infrastructure you've learnt over the years where they make sense for your project.
Go might be more interesting if you are coming from C. Go and C++ are pretty much antithetical.
For some reason Go also seems to interest people coming from Ruby.
Managing a substantial Python (or Ruby) project is easier than you'd imagine because there is so much less code and configuration. There is also less "architecture astronautism" with all the layers of abstraction hiding what's really going on. You can still have some of that, but in my experience, it's pretty rare.
The biggest issue when stepping outside the JVM (in my opinion anyway), is dependency management. The libraries you want may often not be pure Python or Ruby, but have C/C++ stuff in there too. This can make setting up an environment on multiple OS platforms tricky, since you need to install (and maybe even compile) all that stuff. There's something to be said for throwing a jar on a classpath and being done. However, I suspect you'll find these languages cut development time so much that you're still ahead of the game after burning a little extra time installing some dependencies.
Performance-wise, both Python and Ruby are probably "fast enough", certainly when developing apps that are not used by large numbers (i.e. web-scale numbers) of people. Internal apps in particular run perfectly fine with no exotic caching, partitioning, parallelization, etc... There are also plenty of companies out there that operate very busy, successful public websites with both Ruby and Python, so in general, the performance should be the least of your worries. Obviously, if you're looking to do scientific simulation or some other compute-heavy work, your mileage may vary.
Editors are another thing that trip people up going to Ruby and Python from Java. Take my advice: ditch your IDE and use a regular text editor with syntax highlighting. There's no way I write Java code without an IDE, but for languages like Ruby and Python, it's not necessary and the IDE just gets in the way. Keeping an interpreter window open when dealing with a library you haven't used before is far more productive. You can create some fake classes, try out some methods, and once you have a feel for the thing, move over to your editor and code up what you want. That beats the pants off autocomplete any day (and the inevitable compile, run, test cycle that goes with it).
EDIT: Oh, and learn JavaScript if you don't already know it. It's only going to get more important.
If this is the type of thing you want to move away from, then I don't think that the problem is teams that use Java - the problem seems to be working for large enterprises.
I suggest that as a first step, ignore any questions of language/platforms/tools and instead think about what type of company you would like to be working for: a small start-up, a more-established medium size business, etc. Do you want to work in a place where the primary business product is software (i.e. a software development company), a place where software is something that is done in support of the primary product being sold, or are you interested in consulting for others?
Once you decide what type of environment you'd like to work in, then the rest of the decisions follow naturally from that.
As a single anecdote, I work for a medium-to-large software-as-a-service company business where most of our work is in Java, but we are very far from the notion of monolithic apps with 1M LOC and offshore teams.
The language/tools are not the problem, it's the people/organization.
The language is a problem, because Java was specially created for this type of organizations. And it is not surprising that Java attracts this type of people (fungible crowds having no pride in their craft).
But I'm not sure one can be a good programmer if Java (or any other mediocre language) is the only thing she knows.
JRuby and Jython are both good stepping stones to ruby and python, which would give you an idea of if you want to head in those directions full time.
I'm partial to Groovy myself, and I'd consider it more a superset of Java (though technically its not). You can reuse as much or as little of Java as you want - even in the same file - while picking up the new idioms.
Groovy, JRuby and Jython will all help you dispense with much of the boilerplate cruft you see in traditional Java, without giving up the power/libraries you're used to. And they all have good webstacks (Grails, Rails, Django, for example).
Moving off the JVM, if you're looking in to web work, PHP - as much as it has a bad rep in certain quarters - is where a lot of work is. The code quality of projects you may find tends to be hit or miss, but it's certainly possible to write clean, elegant and scalable code in PHP (and I've seen some pretty piss-poor rails in my day as well - nothing's perfect). Have you considered looking at .NET as well?
As someone else said, the 'scalable' thing - don't fret about it. Anything is scalable, and each platform will have different techniques - they all have pros and cons, which may not always be apparent until you dig more deeply in to the constraints of a particular language or platform.
Find a couple platforms that are of some interest, and focus on finding some communities for those platforms (Django, Rails, Zend Framework, Grails, ASP.NET, whatever). Getting a feel for how the community thinks about problems, what they focus on (features, security, etc) will give you a sense of what you're comfortable with.
Which is more important - a new language or a new career path? In other words, would "Enterprise Python" or "YC Java" provide more of the change you are seeking? From your post, I get the sense it is the latter. Good luck.