How to handle functions deprecation in library? - java

I'm working on a Java library and would like to remove some functions from it. My reasons for this is public API and design cleanup. Some objects have setters, but should be immutable, some functionality has been implemented better/cleaner in different methods, etc.
I have marked these methods 'deprecated', and would like to remove them eventually. At the moment I'm thinking about removing these after few sprints (two week development cycles).
Are there any 'best practices' about removing redundant public code?
/JaanusSiim

Set a date and publicize it in the #deprecated tag. The amount of time given to the removal depends on the amount of users your code has, how well connected you are with them and the the reason for the change.
If you have thousands of users and you barely talk to them, the time frame should probably be in the decades range :-)
If your users are your 10 coworkers and you see them daily, the time frame can easily be in the weeks range.
/**
* #deprecated
* This method will be removed after Halloween!
* #see #newLocationForFunctionality
*/

Consider it this way, customer A downloads the latest version of you library file or frame work. He hits compile on this machine and suddenly he see thousands of errors because the member file or function does no longer exist. From this point on, you've given the customer a reason why not to upgrade to your new version and to stay with the old version.
Raymond Chen answers this the best with his blog about win32 API,
Though, our experience in our software house has been, once the API has been written we have to carry the API to the end of the product life cycle. To help users to new versions, we provide backwards compatibility with the old commands in the new framework.

It depends on how often the code is rebuild. For example, if there are 4 applications using the library, and they are rebuild daily, a month is a long enough time to fix the deprecated calls.
Also, if you use the deprecated tag, provide some comment on which code replaces the deprecated call.

Use #deprecated tag. Read the Deprecation of APIs document for more info.
After everyone using the code tells you they have cleaned up on their side, start removing the deprecated code and wait and see if someone complains - then tell them to fix their own code...

Given that this is a library, consider archiving a version with the deprecated functions. Make this version available in both source code and compiled form, as a backup solution for those who haven't modernized their code to your new API. (The binary form is needed, because even you may have trouble compiling the old version in a few years.) Make it clear that this version will not be supported and enhanced. Tag this version with a symbolic symbol in your version control system. Then move forward.

It certainly depends at which scale your API is used and what you promised upfront to your customers.
As described by Vinko Vrsalovic, you should enter a date when they have to expect the abandon of the function.
In production, if it's "just" a matter of getting cleaner code, I tend to leave things in place even past the deprecating date as long as it doesn't break anything.
On the other hand in development I do it immediately, in order to get things sorted out quickly.

You may be interested in examples of how deprecation works in some other projects. For example, here follows what the policy in the Django project for function deprecation is:
A minor release may deprecate certain features from previous releases. If a feature in version A.B is deprecated, it will continue to work in version A.B+1. In version A.B+2, use of the feature will raise a PendingDeprecationWarning but will continue to work. Version A.B+3 will remove the feature entirely.

too bad you are not using .Net :(
The built in Obsolete attribute generates compiler warnings.

Related

Programmatic static-checking in OpenJML

The manual for OpenJML (http://jmlspecs.sourceforge.net/OpenJMLUserGuide.pdf) intimates that static-checking of Java compilation units can be done programmatically.
Unfortunately, the manual entry for static-checking (Section 5.2.4) is empty, and no specific examples appear to be given for this.
Does anyone know of a simple example?
Unfortunately I cannot help you out for OpenJML, even in the new version of the manual, the section you refer to is empty.
However, you could try other tools such as the KeY program verifier with which you can statically prove your JML annotations correct, either using KeY as a front-end or also programmatically as a back-end. The code at the page referred to, which presents the programmatic usage of the symbolic execution API of KeY may be look quite intimidating at the first glance, but it contains a lot of boilerplate which you might actually not need because the available all options are explained.
For verification (aka "static checking"), you could look into the "key.core.example" package in the current source distribution which should get you started.
As for my knowledge, OpenJML and KeY are the currently only actively maintained tools for statically checking JML annotations. There were others, such as ESC/Java2 and KRAKATOA, but they seem to be outdated. KeY is actively maintained, but does not cover all of the Java language in contrast to OpenJML (maybe there will be LLVM or bytecode versions in the future, since there are corresponding plans, then the situation might improve).

Is there an automatic way to generate a list of interface changes?

I am developing/maintaining a Java library, and would like to keep track of backwards-incompatible changes between releases. This list could contain changes in class declarations, method signatures etc.
For example, if I (accidentally) changed a constructor by adding a parameter, then I would like to have it included in the list and be warned about the change.
// before
public MyCar(String name) { ... }
// after (some accidental change)
public MyCar(String name, long mileage) { ... }
// an application using my library depending on this constructor would be broken
// when it updates to the new version
Is there an automated way to generate this list? It feels like something that IntelliJ or Gradle should be able to do.
My team has tried reviewing pull requests and maintaining a CHANGELOG manually (which seems to be a common approach), but that's prone to human errors. I seek an automated way that can ideally be part of the build system.
I've always maintained the compatibility list manually but sometimes I forget something.
A quick look around shows several open source libraries but they haven't had new versions released in nearly 10 years. So I don't know if they would work with new Java 7 or 8 features.
Note: I've never used any of these!
CLIRR - apache project used by some other apache projects to show what has changed (example output from apache commons-lang here. last updated in 2005 doesn't even build with Maven 2 (or 3)
JDiff javadoc doclet comparator. Might support Java 5. Last updated in 2008
Japitools - apparently was used by the GNU Classpath project to compare their APIs for signature compatibility with different versions of the Sun Java class libraries. Doesn't look like it's been updated since 2006
There's a better way to do it.
Preserve backwards compatibility for a time by annotating your methods with #Deprecated, and indicate when they'll be unsupported. Then add the #deprecated piece to your Javadoc and that will automatically generate a list of deprecated features that the end user needs to care about.
This has the added benefit of allowing you to introduce when a feature was introduced (#since), and when a feature will be removed, without having to fuss too much with a lot of other tools.
Since you've added a more concrete code example, I'll add one more note: those sorts of changes...are the result of a conscious design decision, and it brings to the forefront two issues:
Regression testing (as in, a test should have caught this)
Ease of transition into the newer API (as in, if I need to suddenly give a new parameter to this to gain functionality, isn't it a new thing rather than it being attached to the old, legacy thing?)
Those issues can't be teased away with any conventional tools; that requires an earnest conversation about the amount of time it takes to transition from one API to another. If you find that you need to introduce new functionality to the core, then you had better make darn certain that hasn't broken the legacy case.
This is what it means to have an API - you have to have the older version lurking around for a while.

Javadoc #author tag good practices

I'm wondering about best practices when creating Javadocs. I have a project with many files. Code has been created by many developers. Each file has an annotation #author, so it is obvious who has created a particular class.
But when some other developer adds new code to a file, modifies it, etc., how should he inform the rest of the team that he has created some new function or has modified existing code? In other words, how should we "keep the Javadocs compatible with reality"? ;)
Add his name to the existing #author tag? Then, it is easier to identify who to ask in case of any doubts.
Add an #author tag to each new method, inner class, etc.?
Of course, since we use SVN, it is easy to investigate who has made what, but for keeping things clear this Javadoc stuff should be taken into consideration as well.
What's the best way to use these #author tags?
I would say that for most purposes #author is unwanted noise. The user of your API shouldn't - and probably doesn't - care, or want to know, who wrote which parts.
And, as you have already stated, SVN already holds this information in a much more authoritative way than the code can. So if I was one of the team, I would always prefer SVN's log and ignore the #author. I'd bet that the code will get out of sync with reality, whatever policy you adopted. Following the Don't Repeat Yourself principle, why hold this information in two places?
If, however, there is some bureaucratic or policy reason that this information MUST be included in the code, have you considered automatically updating the #author tag in the code on check in? You could probably achieve this with an SVN hook. You could for example list all the developers who changed a given file in the order they changed it; or who changed it most; or whatever. Or, if the #author is mandated in (source) code you release to the outside world, you could consider adding the #author automatically as part of the release build (I suspect you could get this information out of SVN somehow).
As for adding more than a single class level #author tag (or other comment), I'd say you'd be accumulating a lot of unhelpful noise. (Again, you have SVN.)
In my experience it is much more useful to identify a historical change (say a change to a line of code, or a method), then to work out which change set this relates to (and which track ticket). Then you have the full context for the change: you have the ticket, the change set, you can find other change sets on the same ticket, or around the same time, you can find related tickets, and you can see ALL the changes that formed that unit of work. You are never going to get this from annotation or comments in code.
You may want to consider why you want author tags in the source. The Apache Foundation do not and I agree.
https://web.archive.org/web/20150226035235/www.theinquirer.net/inquirer/news/1037207/apache-enforces-the-removal-of-author-tags
To my best understanding this is a cargo cult way of working from when sources were printed on paper. With modern version control systems this information and more can be found in the history anyway.
You can have more than one #author tag. In case you make some big changes to a class, just add a new #author tag with your own name in it. There's no need to mark the changes you've done or to put your name around the changes, as the revision history should be able to display that clearly.
In really big and long-running projects with lots of developers, it is useful to know ho is responsible for given code, who can provide you with extra information and such. In that case it would be handy to have such an informationin the file using #author tag. Not marking who created the file or who made some major contributions, but who is a contact person for that code. Those might be very different people as original author may be already on different project or left the company years ago.
I think on huge project that approach may be handy, however there is a caveat. Keeping every single file's author information is very difficult as there is huge amount of files and sooner or later will fail. More and more files will have outdated information and developers will no longer trust this #author as source of information and will just ignore it.
Solution, which may work, is not to keep #author on every single file, but only per module (high level packages). Javadoc has a feature, where you can document not only files but whole packages (See this question for more detail).
This is however a special case and as long as your project is not that big or old, I reccomend ommiting the author information.
I completely agree that it is unnecessary and you probably shouldn't add it. However I still add it, I see it like adding a signature to a painting, or adding it to a stamp on a piece of metal in a computer helped design. You wrote that piece of code, and adding your name shows that you are proud of it and that you are confident of its quality, even if it does nothing else. Even if it's changed in the future, you laid the foundations for everything built on top of it, and should it really be rewritten completely, the tag can be changed, removed or expanded. I agree that it is redundant thanks to version control, but having your name in version control isn't nearly as satisfying. If someone just adds a "final" or formats the code, their name will be in version control, even if they hardly contributed at all. I also agree that it is noise, in that it doesn't add anything to the code, however is it really even slightly noticeably annoying? I don't think so. If you are reasonable about it, I think it can make a project "more friendly", if that makes sense.
It is the year 2021 and When I am replying to this question it is nearly 8 years from the first publish. The world is a little bit different place and it is using microservices at full throttle. Therefore I would sum up the overall mood around authorship like this: it is pointless. Let me explain it on a few points:
Most widespread software or organisation projects are developed by multiple authors, not individuals anymore.
Majority of software is versioned in Git, CI/CD and cloud is reachable reality.
Advanced IDEs visualise greatly code changes. Code changes are more important than the overall class source code.
Handling bugs caused by code changes are far more important than handling bugs caused by the usage of the wrong class version.
Unless the software is a library, IP/commercial software, framework with regular releases, authorship has no meaning.
It is highly probable that the authors of the source code you use/work on are not working or never work in your organisation.
Maintaining an appropriate ratio of author contribution in author declaration leads to additional effort with 0 gain. Nobody want that.
Therefore knowledge of simple code edits and appropriate line changes are more important than knowledge of the whole class.
Here is my opinion on class authorship digested to the short article.
It's very handy to have #author tag and have multiple authors. Even Oracle's Documentation outlines that it's good practice to have #author on top of class to give credit to particular author who did the job and also to track down things if someone needs to be spoken to during development process. If there are multiple authors they can be listed in order they contributed on a particular java file/class. Yes, there are plugins and with git structure, you can check can see author's name hanging around in the code precisely, but this idea will be controversial though. Because, sometimes multiple authors edit same line of code and might not show two authors editing same line of code. I have plugin enabled, it never shows 2 authors name for editing same line of code. With big companies, it's handy to have this practice set up.
If it is company code, I would not do that: we have VCS. Instead, if it is a blog post or code snippets of my personal repo, I would proudly add this and hoping some copy-paste guy will find my code useful and accidentally, copy my name as well :)
Just my type of humour, I guess.
Building off of this answer and digging through links from posts from 2004 I found this (pasted below). It's from Dirk-Willem van Gulik who was one of the founders of the Apache Software Foundation so I assume he had some input on the decision to stop using #author tags.
List: xml-cocoon-dev Subject: Re: #author tags (WAS: RE: ASF
Board Summary for February 18, 2004) From: Dirk-Willem van Gulik
<dirkx () asemantics ! com> Date: 2004-02-27 10:33:32
Message-ID: 63E38432-6910-11D8-BA7E-000A95CDA38A () asemantics ! com
On Feb 27, 2004, at 12:45 AM, Conal Tuohy wrote:
I don't think the ASF should discourage developers from keeping useful
metadata about the code inside the source files. What better place to
put the metadata than in the code? This makes it more likely to be
used and kept up to date than if it was stored somewhere else, IMHO.
One way to look at this is that #author tags are in a way factually
'wrong'; in most cases it just signals which person wrote the first
skeleton of that code; but subsequently it was fixes, peer-reviewed
and looked at by a whole community. Also do not forget the many
people in your community which help with QA, Documentation,
user-feedback and so on. To put one person in the (hot) seat for
what is essentially a group effort is not quite right.
Looking through the CVS logs of a few tomcat files: each block of 30
lines seems to have had commits of at least 5 persons; with a median
of 6 and an average of 9. The average number of #author tags on
those arbitrary blocks is about 0.5. And that is not counting QA,
docs, suggestions of mailing lists, bug resolutions, user support.
I.e. those things which make tomcat such a great supported product.
Secondly what we 'sell' as the ASF brand is a code base which is peer
reviewed, quality controlled and created by a sustainable group which
will survive the coming and going of volunteers. One where knowledge
is generally shared and not just depended on one single individual.
This is one of the key reasons why large companies, governments, etc
have a lot less qualms about using apache than using most other open
source; we mitigate the worry that it depends on a single person,
and can implode or fork without warning, right from the get-go.
Finally - a lot of developers do live in countries where you can get
sued. The ASF can provide a certain level of protection; but this is
based on the KEY premisse that there is oversight and peer review.
That what we ship is a community product; and that everything is
backed by the community and cannot be attributed to a single person.
Every commit gets peer review; ever release requires +1s' and are
backed by the community as a whole. #author tags are by necessity
incomplete and thus portrait the situation inaccurately. Any hint or
suggestion that parts of the code are not a community product makes
defence more complex and expensive. We do not want to temp anyone -
but rather present a clean picture with no blemishes or easy go's.
And to give this a positive slant; be -proud- of this culture; be
proud of being part of something larger of incredible quality. Each
of you did not just write a few pesky lines of code surrounded by an
#author tag; but where instrumental in getting the -whole- thing work
! And if you are ever trying to understand why cocoon made it this
far, and other commercial/open-source projects did not, then do look
there; quality and a sense of long term stability.
Take Care, Have fun,
Dw
While tracking this down I came across a few blog posts against this and some in favor. That's a very small sample size but I think it is fair to say this was at least a controversial change -- some folks wanted them to stay. That said, in 2022 I don't really ever see them used. (Remember, this mail is from 2004.) You even mentioned it yourself about SVN history (but now maybe Git is the more common tool) and even in this mail they mention the CVS logs (another source control tool). Maybe the source control tools of today are easier to use, who knows.
I feel like there still might be some oddball use cases that make sense but I don't think the standard idea of "I wrote (or modified) this so I'm putting myself as the #author" is necessary. I currently have a question on Code Review about using it for Creative Commons attribution and (in my opinion) I think it's a good use but I would hardly call that a well-accepted good practice (but I don't think it hurts).

Java Look and feel - how to break a dependency on sun.swing.SwingUtilities2

I am maintaining some code the implements a customized Look and Feel in Java. While doing a recent upgrade of Java version (for other reasons) I found that the Look and feel broke due to a field not found on
sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET;
This is in a class that is closely based on BasicMenuItemUI.layoutMenuItem() circa Java 6u02 (here's the source). I have found that Oracle have re-factored their code to include a MenuItemLayoutHelper in the new target version I am using, Java 6u31.
I could just use the MenuItemLayoutHelper but that doesn't solve the problem it just puts it off until the next time the Java internals are changed around. Therefore, I have discounted this as a solution.
I am after some advise on how to achieve a left to right layout similar to BasicMenuItemUI without needing to know the parents' maximum text offset (removing the bad dependency on sun.swing.SwingUtilities).
As albfan said, you can't. You either have to depend on the code, copy the class and use it in your program, not use it at all and use a third party library, or not use that feature.
Ok it may have been a while but I figured out I could just use my own constant instead of sun.swing.SwingUtilities2.BASICMENUITEMUI_MAX_TEXT_OFFSET as long as it was used consistently in the offending code. By no means an ideal solution.
On the upside bad imports from sun packages has gone into the coding rule checks.

Is it safe to use Project Lombok? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
In case you don't know Project Lombok helps with some of the annoyances of Java with stuff like generating getters and setters with annotations and even simple JavaBean like generation with #Data. It could really help me, especially in 50 different event objects where you have up to 7 different fields that need to be constructed and hidden with getters. I could remove almost a thousand lines of code with this.
However, I'm worried that in the long run, it will be a regretful decision. Flamewars will erupt in the ##Java Freenode channel when I mention it, providing code snippets will confuse possible helpers, people will complain about missing JavaDoc, and future commiters might just remove it all anyway. I would really enjoy the positive, but I'm worried about the negative.
So: Is it safe to use Lombok on any project, small or large? Are the positive effects worth the negatives?
TL; DR:
Yes, it's pretty safe to use and I'd recommend using it. (May 2022)
Original Answer
Just started using Lombok today. So far I like it, but one drawback I didn't see mentioned was refactoring support.
If you have a class annotated with #Data, it will generate the getters and setters for you based on the field names. If you use one of those getters in another class, then decide the field is poorly named, it will not find usages of those getters and setters and replace the old name with the new name.
I would imagine this would have to be done via an IDE plug-in and not via Lombok.
UPDATE (Jan 22 '13)
After using Lombok for 3 months, I still recommend it for most projects. I did, however, find another drawback that is similar to the one listed above.
If you have a class, say MyCompoundObject.java that has 2 members, both annotated with #Delegate, say myWidgets and myGadgets, when you call myCompoundObject.getThingies() from another class, it's impossible to know if it's delegating to the Widget or Gadget because you can no longer jump to source within the IDE.
Using the Eclipse "Generate Delegate Methods..." provides you with the same functionality, is just as quick and provides source jumping. The downside is it clutters your source with boilerplate code that take the focus off the important stuff.
UPDATE 2 (Feb 26 '13)
After 5 months, we're still using Lombok, but I have some other annoyances. The lack of a declared getter & setter can get annoying at times when you are trying to familiarize yourself with new code.
For example, if I see a method called getDynamicCols() but I don't know what it's about, I have some extra hurdles to jump to determine the purpose of this method. Some of the hurdles are Lombok, some are the lack of a Lombok smart plugin. Hurdles include:
Lack of JavaDocs. If I javadoc the field, I would hope the getter and setter would inherit that javadoc through the Lombok compilation step.
Jump to method definition jumps me to the class, but not the property that generated the getter. This is a plugin issue.
Obviously you are not able to set a breakpoint in a getter/setter unless you generate or code the method.
NOTE: This Reference Search is not an issue as I first thought it was. You do need to be using a perspective that enables the Outline view though. Not a problem for most developers. My problem was I am using Mylyn which was filtering my Outline view, so I didn't see the methods. Lack of References search. If I want to see who's calling getDynamicCols(args...), I have to generate or code the setter to be able to search for references.
UPDATE 3 (Mar 7 '13)
Learning to use the various ways of doing things in Eclipse I guess. You can actually set a conditional breakpoint (BP) on a Lombok generated method. Using the Outline view, you can right-click the method to Toggle Method Breakpoint. Then when you hit the BP, you can use the debugging Variables view to see what the generated method named the parameters (usually the same as the field name) and finally, use the Breakpoints view to right-click the BP and select Breakpoint Properties... to add a condition. Nice.
UPDATE 4 (Aug 16 '13)
Netbeans doesn't like it when you update your Lombok dependencies in your Maven pom. The project still compiles, but files get flagged for having compilation errors because it can't see the methods Lombok is creating. Clearing the Netbeans cache resolves the issue. Not sure if there is a "Clean Project" option like there is in Eclipse. Minor issue, but wanted to make it known.
UPDATE 5 (Jan 17 '14)
Lombok doesn't always play nice with Groovy, or at least the groovy-eclipse-compiler. You might have to downgrade your version of the compiler.
Maven Groovy and Java + Lombok
UPDATE 6 (Jun 26 '14)
A word of warning. Lombok is slightly addictive and if you work on a project where you can't use it for some reason, it will annoy the piss out of you. You may be better off just never using it at all.
UPDATE 7 (Jul 23 '14)
This is a bit of an interesting update because it directly addresses the safety of adopting Lombok that the OP asked about.
As of v1.14, the #Delegate annotation has been demoted to an Experimental status. The details are documented on their site (Lombok Delegate Docs).
The thing is, if you were using this feature, your backout options are limited. I see the options as:
Manually remove #Delegate annotations and generate/handcode the delegate code. This is a little harder if you were using attributes within the annotation.
Delombok the files that have the #Delegate annotation and maybe add back in the annotations that you do want.
Never update Lombok or maintain a fork (or live with using experiential features).
Delombok your entire project and stop using Lombok.
As far as I can tell, Delombok doesn't have an option to remove a subset of annotations; it's all or nothing at least for the context of a single file. I opened a ticket to request this feature with Delombok flags, but I wouldn't expect that in the near future.
UPDATE 8 (Oct 20 '14)
If it's an option for you, Groovy offers most of the same benefits of Lombok, plus a boat load of other features, including #Delegate. If you think you'll have a hard time selling the idea to the powers that be, take a look at the #CompileStatic or #TypeChecked annotation to see if that can help your cause. In fact, the primary focus of the Groovy 2.0 release was static safety.
UPDATE 9 (Sep 1 '15)
Lombok is still being actively maintained and enhanced, which bodes well to the safety level of adoption. The #Builder annotations is one of my favorite new features.
UPDATE 10 (Nov 17 '15)
This may not seem directly related to the OP's question, but worth sharing. If you're looking for tools to help you reduce the amount of boilerplate code you write, you can also check out Google Auto - in particular AutoValue. If you look at their slide deck, the list Lombok as a possible solution to the problem they are trying to solve. The cons they list for Lombok are:
The inserted code is invisible (you can't "see" the the methods it generates) [ed note - actually you can, but it just requires a decompiler]
The compiler hacks are non-standard and fragile
"In our view, your code is no longer really Java"
I'm not sure how much I agree with their evaluation. And given the cons of AutoValue that are documented in the slides, I'll be sticking with Lombok (if Groovy is not an option).
UPDATE 11 (Feb 8 '16)
I found out Spring Roo has some similar annotations. I was a little surprised to find out Roo is still a thing and finding documentation for the annotations is a bit rough. Removal also doesn't look as easy as de-lombok. Lombok seems like the safer choice.
UPDATE 12 (Feb 17 '16)
While trying to come up with justifications for why it's safe to bring in Lombok for the project I'm currently working on, I found a piece of gold that was added with v1.14 - The Configuration System! This is means you can configure a project to dis-allow certain features that your team deems unsafe or undesirable. Better yet, it can also create directory specific config with different settings. This is AWESOME.
UPDATE 13 (Oct 4 '16)
If this kind of thing matters to you, Oliver Gierke felt it was safe to add Lombok to Spring Data Rest.
UPDATE 14 (Sep 26 '17)
As pointed out by #gavenkoa in the comments on the OPs question, JDK9 compiler support isn't yet available (Issue #985). It also sounds like it's not going to be an easy fix for the Lombok team to get around.
UPDATE 15 (Mar 26 '18)
The Lombok changelog indicates as of v1.16.20 "Compiling lombok on JDK1.9 is now possible" even though #985 is still open.
Changes to accommodate JDK9, however, necessitated some breaking changes; all isolated to changes in config defaults. It's a little concerning that they introduced breaking changes, but the version only bumped the "Incremental" version number (going from v1.16.18 to v1.16.20). Since this post was about the safety, if you had a yarn/npm like build system that automatically upgraded to the latest incremental version, you might be in for a rude awakening.
UPDATE 16 (Jan 9 '19)
It seems the JDK9 issues have been resolved and Lombok works with JDK10, and even JDK11 as far as I can tell.
One thing I noticed though that was concerning from a safety aspect is the fact that the change log going from v1.18.2 to v1.18.4 lists two items as BREAKING CHANGE!? I'm not sure how a breaking change happens in a semver "patch" update. Could be an issue if you use a tool that auto-updates patch versions.
UPDATE 17 (Mar 17 '21)
There is some drama unfolding between the Lombok developers and an OpenJDK developer around JDK 16. The JDK developers argue that Lombok is taking advantage of unpublished JDK internals via loopholes the JDK team would like to close, but have intentionally left open for various reasons.
They have stated their concern (about the safety of Lombok) as such:
All access to internals will remain available as before, provided that
the client application explicitly allows it, acknowledging that it is
knowingly taking on any maintenance (or security) issue this might
entail.
While Lombok might think they're deceiving OpenJDK, all they're doing
is announcing that it is their intention to deceive their own users.
There may come a day soon where Lombok will not be able to find any more creative solutions around the JDK's security restrictions. Even if they do, the safety of using Lombok in your project may be in question.
UPDATE 18 (May 11 '22)
A recent comment asked for a summary, so I put that at the top.
The short answer is it's perfectly safe to use and I'd highly recommend using it if we're writing Java code.
Given that support for JDK 17 has been out for awhile and was released less than a month after the JDK was officially released, the safety of Lombok sticking around is high. And you can always de-lombok if you need to.
As a consultant, I get to see how a lot of different companies write code. Every client I've had for the past 5 years has used Lombok. These have all been Fortune 1000 companies. It speeds development and makes it less error prone.
That said, you still need to keep up on the latest features of the JDK. Consider using the Java record keyword to make your objects immutable instead of some Lombok feature. Use Lombok where it makes sense. Use the Lombok config options to prevent usage of it in ways you don't agree with.
So unless something major happens, this will probably be my last update to this answer. Thanks for all the votes. I'm glad it helps.
It sounds like you've already decided that Project Lombok gives you significant technical advantages for your proposed new project. (To be clear from the start, I have no particular views on Project Lombok, one way or the other.)
Before you use Project Lombok (or any other game-changing technology) in some project (open source or other wise), you need to make sure that the project stake holders agree to this. This includes the developers, and any important users (e.g. formal or informal sponsors).
You mention these potential issues:
Flamewars will erupt in the ##Java Freenode channel when I mention it,
Easy. Ignore / don't participate in the flamewars, or simply refrain from mentioning Lombok.
providing code snippets will confuse possible helpers,
If the project strategy is to use Lombok, then the possible helpers will need to get used to it.
people will complain about missing JavaDoc,
That is their problem. Nobody in their right mind tries to rigidly apply their organization's source code / documentation rules to third-party open source software. The project team should be free to set project source code / documentation standards that are appropriate to the technology being used.
(FOLLOWUP - The Lombok developers recognize that not generating javadoc comments for synthesized getter and setter methods is an issue. If this is a major problem for your project(s), then one alternative is to create and submit a Lombok patch to address this.)
and future commiters might just remove it all anyway.
That's not on! If the agreed project strategy is to use Lombok, then commiters who gratuitously de-Lombok the code should be chastised, and if necessary have their commit rights withdrawn.
Of course, this assumes that you've got buy-in from the stakeholders ... including the developers. And it assumes that you are prepared to argue your cause, and appropriately handle the inevitable dissenting voices.
Go ahead and use Lombok, you can if necessary "delombok" your code afterwards http://projectlombok.org/features/delombok.html
Personally (and therefore subjectively) I've found that using Lombok makes my code more expressive about what I'm trying to achieve when compared to IDE/own implementations of intricate methods such as hashcode & equals.
When using
#EqualsAndHashCode(callSuper = false, of = { "field1", "field2", "field3" })
it's much easier to keep Equals & HashCode consistent and keep track of which fields are evaluated, than any IDE/own implementation. This is especially true when you're still adding / removing fields regularly.
The same goes for the #ToString annotation and its parameters which clearly communicate the desired behavior regarding included / excluded fields, usage of getters or field access and wether or not to call super.toString().
And again by annotating an entire class with #Getter or #Setter(AccessLevel.NONE) (and optionally overriding any divergent methods) it's immediately clear what methods will be available for the fields.
The benefits go on and on..
In my mind it's not about reducing code, but about clearly communicating what you desire to achieve, rather than having to figure it out from Javadoc or implementations. The reduced code just makes it easier to spot any divergent-method implementations.
I read some opinions about the Lombok and actually I'm using it in some projects.
Well, in the first contact with Lombok I had a bad impression. After some weeks, I started to like it. But after some months I figure out a lot of tiny problems using it. So, my final impression about Lombok is not so positive.
My reasons to think in this way:
IDE plugin dependency. The IDE support for Lombok is through plugins. Even working good in most part of the time, you are always a hostage from this plugins to be maintained in the future releases of the IDEs and even the language version (Java 10+ will accelerate the development of the language). For example, I tried to update from Intellij IDEA 2017.3 to 2018.1 and I couldn't do that because there was some problem on the actual lombok plugin version and I needed to wait the plugin be updated... This also is a problem if you would like to use a more alternative IDE that don't have any Lombok plugin support.
'Find usages' problem.. Using Lombok you don't see the generated getter, setter, constructor, builder methods and etc. So, if you are planning to find out where these methods are being used in your project by your IDE, you can't do this only looking for the class that owns this hidden methods.
So easy that the developers don't care to break the encapsulation. I know that it's not really a problem from Lombok. But I saw a bigger tendency from the developers to not control anymore what methods needs to be visible or not. So, many times they are just copying and pasting #Getter #Setter #Builder #AllArgsConstructor #NoArgsConstructor annotations block without thinking what methods the class really need to be exposed.
Builder Obssession ©. I invented this name (get off, Martin Fowler). Jokes apart, a Builder is so easy to create that even when a class have only two parameters the developers prefer to use #Builder instead of constructor or a static constructor method. Sometimes they even try to create a Builder inside the lombok Builder, creating weird situations like MyClass.builder().name("Name").build().create().
Barriers when refactoring. If you are using, for example, a #AllArgsConstructor and need to add one more parameter on the constructor, the IDE can't help you to add this extra parameter in all places (mostly, tests) that are instantiating the class.
Mixing Lombok with concrete methods. You can't use Lombok in all scenarios to create a getter/setter/etc. So, you will see these two approaches mixed in your code. You get used to this after some time, but feels like a hack on the language.
Like another answer said, if you are angry about the Java verbosity and use Lombok to deal with it, try Kotlin.
Lombok is great, but...
Lombok breaks the rules of annotation processing, in that it doesn't generate new source files. This means it cant be used with another annotation processors if they expect the getters/setters or whatever else to exist.
Annotation processing runs in a series of rounds. In each round, each one gets a turn to run. If any new java files are found after the round is completed, another round begins. In this way, the order of annotation processors doesn't matter if they only generate new files. Since lombok doesn't generate any new files, no new rounds are started so some AP that relies on lombok code don't run as expected. This was a huge source of pain for me while using mapstruct, and delombok-ing isn't a useful option since it destroys your line numbers in logs.
I eventually hacked a build script to work with both lombok and mapstruct. But I want to drop lombok due to how hacky it is -- in this project at least. I use lombok all the time in other stuff.
Update to specifically mapstruct+lombok: the two libraries work out of the box with each other nowadays. The problem will still exist for other annotation processors though.
There are long-term maintenance risks as well. First, I'd recommend reading about how Lombok actually works, e.g. some answers from its developers here.
The official site also contains a list of downsides, including this quote from Reinier Zwitserloot:
It's a total hack. Using non-public API. Presumptuous casting (knowing
that an annotation processor running in javac will get an instance of
JavacAnnotationProcessor, which is the internal implementation of
AnnotationProcessor (an interface), which so happens to have a couple
of extra methods that are used to get at the live AST).
On eclipse, it's arguably worse (and yet more robust) - a java agent
is used to inject code into the eclipse grammar and parser class,
which is of course entirely non-public API and totally off limits.
If you could do what lombok does with standard API, I would have done
it that way, but you can't. Still, for what its worth, I developed the
eclipse plugin for eclipse v3.5 running on java 1.6, and without
making any changes it worked on eclipse v3.4 running on java 1.5 as
well, so it's not completely fragile.
As a summary, while Lombok may save you some development time, if there is a non-backwards compatible javac update (e.g. a vulnerability mitigation) Lombok might get you stuck with an old version of Java while the developers scramble to update their usage of those internal APIs. Whether this is a serious risk obviously depends on the project.
I know I'm late, but I can't resist the temptation: anybody liking Lombok should also have a look at Scala. Many good ideas that you find in Lombok are part of the Scala language.
On your question: it's definitely easier to get your developers trying Lombok than Scala. Give it a try and if they like it, try Scala.
Just as a disclaimer: I like Java, too!
I have used Lombok in almost all my projects for one year but unfortunately removed it. In the beginning it was a very clean way of development but setting up the development environment for new team members is not very easy and straightforward. When it became a headache I just removed it. But it is a good work and needs some more simplicity to setting up.
My take on Lombok is that it merely provides shortcuts for writing bolilerplate Java code.
When it comes to using shortcuts for writing bolilerplate Java code, I would rely on such features provided by IDE -- like in Eclipse, we can go to menu Source > Generate Getters and Setters for generating getters and setters.
I would not rely on a library like Lombok for this:
It pollutes your code with an indirection layer of alternative syntax (read #Getter, #Setter, etc. annotations). Rather than learning an alternative syntax for Java, I would switch to any other language that natively provides Lombok like syntax.
Lombok requires the use of a Lombok supported IDE to work with your code. This dependency introduces a considerable risk for any non-trivial project. Does the open source Lombok project have enough resources to keep providing support for different versions of a wide range of Java IDE's available?
Does the open source Lombok project have enough resources to keep providing support for newer versions of Java that will be coming in future?
I also feel nervous that Lombok may introduce compatibility issues with widely used frameworks/libraries (like Spring, Hibernate, Jackson, JUnit, Mockito) that work with your byte code at runtime.
All in all I would not prefer to "spice up" my Java with Lombok.
When I showed the project to my team the enthusiasm was high, so I think you should not be afraid of team response.
As far as ROI, it is a snap to integrate, and requires no code change in its basic form. (just adding a single annotation to your class)
And last, if you change your mind, you can run the unlombok, or let your IDE create these setters, getters, and ctors, (which I think no one will ask for once they see how clear your pojo becomes)
Wanted to use lombok's #ToString but soon faced random compile errors on project rebuild in Intellij IDEA. Had to hit compile several times before incremental compilation could complete with success.
Tried both lombok 1.12.2 and 0.9.3 with Intellij IDEA 12.1.6 and 13.0 without any lombok plugin under jdk 1.6.0_39 and 1.6.0_45.
Had to manually copy generated methods from delomboked source and put lombok on hold until better times.
Update
The problem happens only with parallel compile enabled.
Filed an issue:
https://github.com/rzwitserloot/lombok/issues/648
Update
mplushnikov commented on 30 Jan 2016:
Newer version of Intellij
doesn't have such issues anymore. I think it can be closed here.
Update
I would highly recommend to switch from Java+Lombok to Kotlin if possible.
As it has resolved from the ground up all Java issues that Lombok tries to work around.
I have encountered a problem with Lombok and Jackson CSV, when I marshalized my object (java bean) to a CSV file, columns where duplicated, then I removed Lombok's #Data annotation and marshalizing worked fine.
I haven't tried using Lombok yet - it is/was next on my list, but it sounds as if Java 8 has caused significant problems for it, and remedial work was still in progress as of a week ago. My source for that is https://code.google.com/p/projectlombok/issues/detail?id=451 .

Categories