Saturday, November 4, 2017

Java Command-Line Interfaces (Part 30): Observations

This series on parsing command line arguments in Java has consisted of 29 posts published over four months and covering 28 distinct open source libraries available for parsing command line arguments in Java. This post collects some observations that can be made from the first 29 posts in this series and provides some general considerations to make when selecting one of the 28 libraries or deciding to roll one's own command-line argument parsing code. Although no one library will be the best fit for every situation, this post will also look at how some libraries may be a better fit than others for specific situations. The post will end with a subset of the original 28 libraries that may be the most generally appealing of the covered libraries based on some criteria covered in the post.

General Observations

There are several observations that can be made after looking at the 28 libraries covered in this series on parsing command line arguments in Java.

  • For most Java developers in most situations, there appears to be very little reason to write custom command line parsing code.
  • The plethora of Java-based libraries for parsing command line arguments in indicative of the vastness of the Java ecosystem.
  • The fact that all 28 covered libraries are open source is a reminder of how fundamental open source is in the Java culture.
  • There are some interesting differences between the libraries covered in this series and the various different approaches are a reminder that there's often more than one way to implement even relatively minor functionality in Java.
  • The large number of libraries for parsing command line arguments in Java, many of which are associated with author statements saying something about the existing libraries not satisfying their needs, is evidence that it's unlikely there will ever be a single language, framework, or library that will be "best" to everyone. If something as simple as a command line parsing library cannot be written to be everyone's favorite, it seems impossible to ever have a larger library, a framework, or a programming language be everyone's favorite. "One size doesn't fit all" when it comes to libraries, frameworks, and programming languages.
  • It's not just technical strength that must be considered when evaluating and selecting a library; its license, distribution mechanism, currency, provider support, and community support also all weigh in on the decision. Even the version of Java it will run on plays a role in the decision.

Evaluation Criteria

These are several criteria that may be important to a Java developer when selecting between so many libraries and when weighing whether to use a library or implement one's own command line argument functionality.

  • Is it open source?
    • My simple definition of open source in this context is "source code can be legally viewed by developers using the library." Wikipedia articulates a similar but slightly stricter definition, "[open source code] is source code [that is] made available with a license in which the copyright holder provides the rights to study, change, and distribute the software to anyone and for any purpose."
    • All 28 libraries covered in this series make source code available to developers using the library and so are "open source" by my simple definition and also generally meet the slightly stricter definition on Wikipedia.
  • What is its license?
    • The license under which each library is issued can be significant in determining whether to choose that library. Most users will be most comfortable with open source licenses that are clearly defined and that are most liberal in what they allow.
    • Many of the libraries covered in the series are released under liberal open source licenses, but some are released under less liberal licenses or do not have an explicitly specified license at all.
  • What is its size?
    • Use of a library typically means an additional JAR on the classpath and it may be important in some situations to keep the size of these additional libraries as small as possible for a particular deployment environment.
    • None of these command line parsing libraries are large when compared to libraries such as Spring and Hibernate, but the relative differences in size among these libraries can be large.
  • Are there third-party dependencies?
    • Third-party libraries add to the overall increase in library size and mean more dependencies to manage.
    • Most of the libraries covered in this series do not have additional dependencies, but some of them do.
  • What is the distribution mechanism?
    • Availability as a single JAR via Maven repository is probably the easiest mechanism for most Java developers to acquire a library.
    • There are JARs available in the Maven repository for many of the covered libraries, but some of the libraries require downloading the JAR from a project site or associated article site.
    • The 28 libraries covered in this series tend to be distributed via Maven repository, via project page download (GitHub, SourceForge, library author's site, etc.), and even copy-and-paste in a couple of cases where the "library is a single Java source code file.
  • Documentation
    • The libraries covered in this series are documented in a variety of ways including project documentation, Javadoc documentation, unit tests, and in-code comments.
    • Many of the libraries have the equivalent of a "Quick Start" tutorial, but some have relatively little documentation other than that. Some have no or very few Javadoc comments and others have significant Javadoc-based API documentation. Many of the libraries make their Javadoc-generated documentation available online, but some require downloading the library to see its Javadoc-based documentation.
  • Community
    • With open source projects, it's often advantageous to have a large community that uses the product because a large community means more implicit testing and potentially more blog posts, articles, and forum messages on how to use that project.
    • The sizes of the communities of the libraries covered in this series vary dramatically and it can be difficult to ascertain the size of any given community. However, the number of libraries dependent on a given library and the number of online resources talking about a given library give us an idea of community involvement.
  • Age of Library / Most Recent Update
    • Newer is not always better, but it generally is more compelling to use an open source product that receives current and recent updates than to use a product that has not been updated or changed in many years. It's a bit less of a concern with a small and simple library such as a command line parsing library, but currently supported libraries are still advantageous over potentially abandoned projects.
  • What features does it offer?
    • This is where the libraries covered in the series really differentiate themselves, but it's the criterion that is most difficult to compare between libraries as it really depends on which particular feature is desired.
    • Most of the covered libraries provided most of the features covered in the simple examples in this series. However, some of the libraries provided significant features that were beyond those used in each library's example.
    • For the simple examples used throughout this series, the ease of use of the API provided by the parsing library was probably as important of a feature as any.

The CLI Comparison page on the picocli GitHub page compares and contrasts many of the libraries covered in this series and some libraries not covered in this series. The page compares the libraries in table format by listing each library's respective attributes such as license, minimum Java version supported, style of API, and parsing options supported.

This series has covered 28 different libraries for parsing command line arguments from Java. It's impossible to designate any one of these as the "best" library for this purpose for all people in all situations. Each library is an investment of time and effort by its developer (or developers), but I attempt here to narrow down the list of libraries to the subset that I believe is most likely to appeal to general situations and developers.

Voted Most Likely to Succeed

The following libraries are listed in alphabetical order rather than in my order of preference.

  • Apache Commons CLI
    • In my opinion, Apache Commons CLI offers the least aesthetically appealing API of this narrowed down subset of recommended libraries.
    • Apache Commons CLI benefits from name recognition, from being frequently used by other libraries and products, and from being around for a long time.
      • In environments where it is difficult to justify installation of new libraries, there is better chance of having Apache Commons CLI already available than most of the other libraries.
    • Apache Commons CLI is built into Groovy and so is especially easy for someone to use moving between Groovy and Java.
    • Quality documentation.
    • The Apache License, Version 2, is a well-known, liberal, and corporation-friendly license.
  • args4j
    • args4j offers numerous features and is highly extensible.
    • Command-line arguments are typed.
    • Quality documentation.
    • args4j is currently supported by a familiar name in the open source Java community.
    • The MIT license is a well-known, liberal, and corporation-friendly license.
  • JCommander
    • API consists of easy-to-use combination of annotations and builders.
    • Command-line arguments are typed.
    • Quality documentation.
    • JCommander is currently supported by a familiar name in the open source Java community.
    • The Apache License, Version 2, is a well-known, liberal, and corporation-friendly license.
  • JewelCli
    • The annotated interface approach of JewelCli appeals to me.
    • Command-line arguments are typed.
    • Quality documentation.
    • The Apache License, Version 2, is a well-known, liberal, and corporation-friendly license.
  • picocli
    • Highly readable annotation-based API.
    • Quality documentation.
    • Command-line arguments are typed.
    • One of the more feature-rich libraries covered in this series.
    • Currently supported (has been enhanced with several new features since I started this series of posts).
    • The Apache License, Version 2, is a well-known, liberal, and corporation-friendly license.

Although I listed a subset of five libraries out of the 28 covered libraries, there are reasons that a developer might choose to use one of the 23 libraries not on this narrowed-down list. Several of the libraries not on this list offer unique features that, if important enough to the Java developer, would make those libraries preferable to the 5 listed above.

The next listing associates some of the covered libraries with some of their relatively unique strengths. One of these might be selected, even if it's not in the list of five I just highlighted, if it is something that it's particularly and uniquely strong in and is one of the most important considerations for the relevant application. Many of the listed "traits" are a matter of preference or taste, meaning a library having the listed trait may be seen as a positive by one developer and as a negative by another developer.

TraitDescription / BenefitLibraries with Desired Trait
Color Syntax Color syntax (select environments) picocli
Command Completion Autocompletion of commands (select environments) picocli
Configuration (Annotations) Uses annotations primarily to define command-line options. Airline 2
args4j
cli-parser
CmdOption
Commandline
google-options
jbock
JCommander
JewelCli
MarkUtils-CLI
picocli
Rop
Configuration (API) Uses programmatic APIs (traditional and/or builder) to define command-line options. Apache Commons CLI
Argparse4j
argparser
CmdLn
getopt4j
Jargo
JArgp
JArgs
JCLAP
jClap
JOpt Simple
JSAP
jw-options
parse-cmd
Configuration (Reflection) Uses reflection (but not annotations) to define command-line options. CLAJR
Configuration (XML) Uses or supports use of XML to define command-line options. JCommando
JSAP
Single File Source Enables easy inclusion of "library" in one's project as a source code file that is compiled rather than as a JAR that source is compiled against. CLAJR
picocli
Small JAR Libraries providing minimally required JAR of less than 25 KB in size (applies to version covered in this series). CLAJR
cli-parser
getopt4j
JArgp
JArgs
jClap
jw-options
Rop

There are numerous other characteristics that one might desire in a Java-based command-line parsing library that might narrow down the number of appropriate candidates. These include flexibility of command styles (long and/or short names, styles [GNU, POSIX, Java, etc.]), applicable license, availability of current support, new releases and updates, size of user community, and minimum version of Java that is supported. The tables provided in the previously referenced Java Command Line Parsers Comparison make it easy to compare some of these characteristics for most of the libraries covered in this series.

This series on parsing command line arguments with Java has demonstrated 28 libraries and there are several more publicly available libraries not yet covered in this series. With over 30 libraries available, most developers should be able to find an external library to meet one's needs.

Additional References

1 comment:

@DustinMarx said...

This post concludes this series on parsing command line arguments in Java for now, but I may cover individual forthcoming or current but not already covered Java-based command-line parsing libraries in the future.