Saturday, April 30, 2011

The Highly Useful Java TimeUnit Enum

Although it is part of the java.util.concurrent package, the TimeUnit enum is useful in many contexts outside of concurrency. In this post, I look at how the TimeUnit enum can be used even in code that does not directly deal with concurrent functionality before examining how this enum is an example of many broader concepts in Java development.

Most of us who have probably seen (or implemented, but we'll blame the other developer for it now) code like that shown in the next code listing. In this code listing, a number of provided milliseconds is converted to a whole number of days by dividing by a previously determined single hard-coded number (86400000, the number of milliseconds in one day).

   /**
    * Convert provided number of milliseconds into number of days.
    *
    * @param numberMilliseconds Number of milliseconds to be converted into days.
    * @return Number of days corresponding to number of provided milliseconds.
    */
   private static long convertMilliSecondsToDaysViaSingleMagicNumber(final long numberMilliseconds)
   {
      // 86400000 = 86400 seconds in a day multipled by 1000 ms per second
      return numberMilliseconds / 86400000;
   }

There are some problems with the approach taken by the above code listing. The most obvious issue may be the use of the magic number 86400000. Although most of us recognize 86400 as the number of seconds in a day, this may not be obvious to everyone and then there's the issue of it being 1000 times greater than that number. The comment in the code listing helps by explaining the underlying meaning of the numbers, but wouldn't it be nice if the code spoke more clearly for itself?

The next code listing shows an arguable slight improvement. Rather than using a single hard-coded number, individual hard-coded numbers are used that are more readable because they are separate. A reader of the code has a better chance of seeing how the number was constructed.

   /**
    * Convert provided number of milliseconds into number of days.
    *
    * @param numberMilliseconds Number of milliseconds to be converted into days.
    * @return Number of days corresponding to number of provided milliseconds.
    */
   private static long convertMilliSecondsToDaysViaMoreExplanatoryMagicNumbers(final long numberMilliseconds)
   {
      // 60 seconds in minute, 60 minutes in hour, 24 hours in day, and
      // one thousand milliseconds in a second
      return numberMilliseconds / (60 * 60 * 24 * 1000);
   }

Even though the individual numbers might make it easier to see what's happening in the conversion, the comment still might be useful in ensuring that the proper function is understood well. Magic numbers are also still involved and most code analysis tools will report issues with their use. The next code example attempts to deal with the issue of magic numbers.

   private final static int NUMBER_MILLISECONDS_IN_SECOND = 1000;
   private final static int NUMBER_SECONDS_IN_MINUTE = 60; 
   private final static int NUMBER_MINUTES_IN_HOUR = 60;
   private final static int NUMBER_SECONDS_IN_HOUR =
      NUMBER_SECONDS_IN_MINUTE * NUMBER_MINUTES_IN_HOUR;
   private final static int NUMBER_HOURS_IN_DAY = 24;
   private final static int NUMBER_MINUTES_IN_DAY =
      NUMBER_HOURS_IN_DAY * NUMBER_MINUTES_IN_HOUR;
   private final static int NUMBER_SECONDS_IN_DAY =
      NUMBER_HOURS_IN_DAY * NUMBER_SECONDS_IN_HOUR;
   private final static int NUMBER_MILLISECONDS_IN_DAY =
      NUMBER_SECONDS_IN_DAY * NUMBER_MILLISECONDS_IN_SECOND;

   /**
    * Convert provided number of milliseconds into number of days.
    *
    * @param numberMilliseconds Number of milliseconds to be converted into days.
    * @return Number of days corresponding to number of provided milliseconds.
    */
   private static long convertMilliSecondsToDaysViaDefinedConstant(final long numberMilliseconds)
   {
      return numberMilliseconds / NUMBER_MILLISECONDS_IN_DAY;
   }

The approach in the code above is commonly seen in Java code. The "magic" numbers are now defined as constants that can be reused in more than just one place. Although this is arguably an improvement, TimeUnit allows us to make a further improvement to this code.

   /**
    * Convert provided number of milliseconds into number of days.
    *
    * @param numberMilliseconds Number of milliseconds to be converted into days.
    * @return Number of days corresponding to number of provided milliseconds.
    */
   private static long convertMillisecondsToDaysViaTimeUnit(final long numberMilliseconds)
   {
      return TimeUnit.MILLISECONDS.toDays(numberMilliseconds);
   }

This code takes advantage of TimeUnit's MILLISECONDS enum constant and toDays(long) method to easily perform this conversion is a standardized and highly readable way. There isn't a magic number in sight!

The above example demonstrates how TimeUnit can be used even when concurrency is not involved. Besides MILLISECONDS, other time unit representations provided by TimeUnit include DAYS, HOURS, MICROSECONDS, MINUTES, NANOSECONDS, and SECONDS. These cover the most commonly used time units one would need.

The methods on the TimeUnit enum allow easy conversion from the unit represented by the enum constant to a different unit of time. There is a general conversion method TimeUnit.convert(long, TimeUnit) that can be used for this purpose. More specific methods are also available for converting to specific types of time units so that the second parameter need not be applied. These methods include the already demonstrated toDays(long) as well as toHours(long), toMicros(long), toMillis(long), toMinutes(long), toNanos(long), and toSeconds(long). Although most of this enum was introduced with J2SE 5, the methods toMinutes(long), toHours(long), and toDays(long) were introduced with Java SE 6.

The enum constants and methods on TimeUnit defined so far are not specifically associated with concurrency and are generally useful. The TimeUnit enum offers three additional methods of interest. TimeUnit.sleep(long) provides a more readable Thread.sleep(long, int). The enum constant of the TimeUnit implies the applicable unit of time, so only a base number needs to be provided. The implication here, of course, is that more obvious numbers can be provided for sleeping rather than needing to worry about expressing a large number in milliseconds or even remembering that the method requires the time be specified in milliseconds.

Two other related useful methods available in TimeUnit are TimeUnit.timedJoin(Thread,long) [convenience method for Thread.join] and TimeUnit.timedWait(Thread,long) [convenience method for Object.wait].

I have used this post to demonstrate how TimeUnit is most obviously useful: it helps developers to write clear code without use of magic numbers for converting between different time measurement units. This is handy in its own right because different APIs often expect different time units. However, TimeUnit has benefits beyond its obvious intended functionality benefits. The TimeUnit enum shows off the power of Java enums and how this power can be leveraged. I look at this next.

Most of us who transitioned from C++ to Java missed having an enum in versions of Java prior to J2SE 5. Fortunately, the wait was worth it as the Java enum is far superior to the C++ enum. There are numerous ways in which the Java enum is better than the C++ enum, but one of the main advantages is the ability to implement methods on the enum. This was shown in the above example where a toDays(long) method allowed for easy conversion of milliseconds via the MILLISECONDS.toDays(long) call. A Java enum is much more than simply an encapsulation of a finite set of integral values. The ability to add behaviors to these enum constants is very powerful.

There are two main approaches for defining methods on an enum. One approach is to define a method at the overall enum level and override it individually at each enum constant's level. The other approach is to implement the method once for the entire enum and all of its enum constants with no need to override the single definition. In other words, one approach is to write an implementation of a method for each enum constant and the other approach writes a method that all the enum constants share. The TimeUnit enum demonstrates both approaches. Its general convert method and all of the convenient toXXXXX methods (where XXXXX are things like Hours or Days) are written specifically for each enum constant and the parent method at the overall enum level throws an AbstractMethodError if not properly overridden by each enum constant (fortunately it always is!). The remaining public methods (timedWait, timedJoin, and sleep) are written with the second approach: a single method implementation exists for each of these that is used by any enum constant defined for TimeUnit.

Besides its usefulness in providing highly readable time unit conversions and besides its usefulness in demonstrating the significant advantages of the Java enum, TimeUnit provides an example of one other "often true" principle in Java: highly and generally useful classes (or enum in this case) can often be found in the SDK where you might least expect it. Although the usefulness of TimeUnit is obvious in concurrent applications, its usefulness goes beyond concurrent functionality. This is not the only case where a more generally useful construct is available in the JDK in a more particular package. I have often seen this in projects I've worked on as well. Often a team will put together a nice class or enum for their own use that is more generally applicable, but which ends up remaining in their rather particular package instead of being in a more generally accessible package.

When we build our own time conversion routines, we typically see hard-coded numbers (or constants defined as) with values such as 1000, 60, and 24. So, it is not surprising that the source code for TimeUnit defines these as constants that it uses in its own conversions. Eventually, the rubber must hit the road and these conversions must take place with these hard numbers. The difference is that use of TimeUnit allows us to have those numbers defined and used outside of our direct code in a well-tested and standardly available enum. It is also interesting to note that hard-coded integers were used in early versions of TimeUnit, but were eventually replaced with internally defined constants:
// Handy constants for conversion methods
static final long C0 = 1L;
static final long C1 = C0 * 1000L;
static final long C2 = C1 * 1000L;
static final long C3 = C2 * 1000L;
static final long C4 = C3 * 60L;
static final long C5 = C4 * 60L;
static final long C6 = C5 * 24L;

This post has been lengthy already, but I'd like to stuff one more thing in. This is a simple Groovy script that uses TimeUnit to demonstrate how many hours, minutes, seconds, milliseconds, microseconds, and nanoseconds are in a single day.

showTimeUnitConversionFactors.groovy
#!/usr/bin/env groovy
// showTimeUnitConversionFactors.groovy
import java.util.concurrent.TimeUnit
println "IN A SINGLE DAY"
println "\tHours:   ${TimeUnit.DAYS.toHours(1)}"
println "\tMinutes: ${TimeUnit.DAYS.toMinutes(1)}"
println "\tSeconds: ${TimeUnit.DAYS.toSeconds(1)}"
println "\tMilliseconds: ${TimeUnit.DAYS.toMillis(1)}"
println "\tMicroseconds: ${TimeUnit.DAYS.toMicros(1)}"
println "\tNanoseconds:  ${TimeUnit.DAYS.toNanos(1)}"

The output of running this Groovy script is shown next:



Conclusion

The TimeUnit enum is obviously useful for converting between units of time in a highly readable and standardized approach. Its value goes beyond that, however, because this SDK enum is an example of the power of the Java enum and demonstrates multiple ways to harness that power.


Additional Resources

There are several other really insightful blog posts regarding TimeUnit. These include The usefulness of java.util.concurrent.TimeUnit, Java TimeUnit: More than just a unit of time, Finding the difference between two dates in Java, and Time Unit Conversion in Java.

Wednesday, April 27, 2011

All I Want for Java 8 is...

With Java 7 considered practically a done deal (I've had it installed on my home computers as the primary JRE for weeks now), many of us are starting to dream about what might come with Java 8. In this post I briefly look at what I'd like to see in Java 8 before looking at some other folks' wish lists for Java 8. I'll end this post with my ideas on what it most likely to go into Java 8.


My Java 8 Wishlist

Full Runtime Generics Support

I think the thing I would most like to see in a future version of Java (and the sooner the better) is reified generics. Although there are many minor syntactic sugar changes that would be nice, the erasure of generics type erasure would be most welcome.

JMX 2.0 Features

In the first response comment to Julian Exenberger's DZone-syndicated version of Java 8.0 Wishlist, Jonathan Fisher states that he'd like, among other things, "Annotation based JMX." I was disappointed when it was announced in the summer of 2009 that JMX 2.0 would be deferred until Java 8. Unfortunately, the relevant Java Specification Request (JSR 255) is in the Inactive state. There are numerous proposed features of JMX 2.0 that I'd like to see. Like Fisher, I'd appreciate annotation-based JMX. Other nice JMX 2.0 features included improved querying and the associated support for JMX web services.

Improved Date/Time Support

In the beginning, there was Date. This class had more than its share of problems and now 2/3 of its constructors (four out of six) are deprecated and nearly all of its methods are deprecated (the exceptions being largely methods overriding Object or implementing the Cloneable and Comparable interfaces).

The Calendar interface and its primary implementation class (GregorianCalendar) were attempts to address the problems associated with Date (though there are arguments for situations when Date is preferable to Calendar).

Unfortunately, Calendar has issues of its own and is not particularly pleasing to use because it sacrifices usability in the name of generality and flexibility (a benefit which is seldom applied because most of us use GregorianCalendar anyway). Many Java developers have found the Joda Time library to be a refreshing approach to handling dates and times in Java.

Many of us were excited at the prospect of Java 7 delivering an improved date/time approach via JSR 310 ("Date and Time API"). Sadly, JSR 310 was not included in Java 7, but it sounds like there's the possibility that it could be part of Java 8. The reference implementation of JSR 310 is the ThreeTen project. It is summarized with this text: "ThreeTen provides a modern date and time library for Java and is the reference implementation for JSR 310. It includes many of the lessons of the Joda-Time project and aims to standardise date and time concepts in computing." I'd love to see JSR 310 implemented in Java 8.


Others' Java 8 Desires

The previously mentioned post Java 8.0 Wishlist outlines some of Julian Exenberger's most desired features for Java 8. These include properties, operator overloading, "finish autoboxing" (methods on literals), and "[making] JavaFX useful." Some of the people commenting on this post vehemently don't want properties or operator overloading. Other people stated their own desired features in comment on this post. These included annotations for checking preconditions and postconditions, modularization, "complete JavaFX," JRE on more platforms, and cleaned up SDK/libraries.

My guess is that one of the most sought-after features for Java 8 is "closures." Indeed, one of the best ways to identify which features are most likely to be most desired for Java 8 is to see what is "most missed" from the proposed but dropped Java 7 additions. I blogged that features such as closures, properties, reified generics, beans binding, operator overloading, and BigDecimal syntax that were dropped from Java 7. The Java.net poll on these features had almost half the respondents state that closures was their most-missed feature dropped from Java SE 7.

Charles Nutter would like to see Java 8 add coroutines and he has initiated that effort.


What's Likely to Make Java 8?

We will hopefully have a better idea of what will be in Java 8 by JavaOne 2011. However, we have some information that provides hints as to what we're most likely to see in Java 8. First, Mark Reinhold's famous Plan B gives us a good idea of initial tentative ideas for Java 8: modularity, "Lambda expressions (informally, 'closures')," Java types annotations, and more small language enhancements ("Project Coin 2").

Another good source of what is likely to really be in Java 8 is the article Looking Ahead to Java SE 7 and 8: A Discussion with Oracle’s Java Language Architect, Brian Goetz. In this article, Goetz talks about tentative Java 8 features such as "upgrades to the core Java libraries to more easily express parallel calculations on collections" and "virtual extension methods" (allows adding of " methods to interfaces that specify a reference to a default implementation").


Conclusion

Java is one of the most used programming languages in the world and the sheer size of its developer base means that there will be a wide disparity of opinions on which features Java would most benefit from. However, I believe that dynamic languages on the JVM (such as Groovy) have influenced many of us to favor closures and that is one feature that sounds destined for Java 8.

Tuesday, April 26, 2011

JavaOne 2011 Speculations

I typically prefer my blog posts to be heavier on the "cogitations" side and lighter on the "speculations" side. This post, however, is almost 100% pure speculation on some of the issues and story lines that may unfold related to JavaOne 2011. Before this week, the biggest speculations related to JavaOne 2011 surrounded its dates and its location. However, with the dates announced this week as October 2-6, 2011, and the location announced as San Francisco, speculation around dates and location is no longer necessary. Therefore, I move onto other JavaOne 2011 speculations in this post.


O Google, Where Art Thou?

One of the most significant stories leading up to last year's JavaOne was Google's withdrawing from participation. Although the conference turned out to be a huge success in terms of quantity and quality of technical content, this content would undoubtedly have been enhanced by the availability of Google-led presentations.

Due to its timing, Google's withdrawal from JavaOne 2010 not only meant the loss of their employee's presentations, but also meant that the slots which their employees' presentations had held were left largely unfilled with alternative content. While the best case would be to have Google participation in JavaOne 2011, the worst case would be for Google to submit abstracts, be accepted, and then withdraw again, preventing certain slots from being filled with technical content. I don't envision Google doing something like the latter because most reasonable people would see such intentional deception as a violation of the company philosophy "You can make money without doing evil.". Instead, my guess is that they'll either not allow employees to submit abstracts at all or else will allow them to present if they submit abstracts that are accepted. I doubt we'll see another withdrawal of participation like we did in JavaOne 2010: it'll likely either be participation as planned or no participation at all.

Last year, Google not only had employees as speakers, but was also a significant sponsor. In fact, they continued to be listed as a sponsor on the web site, on conference materials, and on conference signs and banners throughout the conference. So far, only Intel ("Diamond") is listed as a sponsor of JavaOne 2011.

I have no way of knowing whether Google will participate in JavaOne 2011. However, if I had to hazard a guess one way or the other, I'd have to guess that Google won't participate in JavaOne because the original cause of their JavaOne 2010 withdrawal ("Oracle’s recent lawsuit against Google") is still unresolved and is not likely to be resolved before closing the call for papers. I think it's more likely that Google won't sponsor the conference and won't have any employees speaking than that they'd either sponsor the conference or allow employees to speak at JavaOne 2011.


MySQL?

Last year, there was a MySQL Sunday held in conjunction with Oracle OpenWorld 2010 and JavaOne 2010. Will there be a MySQL Sunday this year? If so, will it be held in conjunction with Oracle OpenWorld 2011 or with JavaOne 2011? JavaOne 2011 is being advertised as exclusively Java:
JavaOne 2011 is exclusively yours. This year’s JavaOne conference brings Java experts and enthusiasts an extraordinary week of learning and networking focused entirely on all things Java.

Many Java developers use MySQL, but is that "Java enough" to make the cut?


What Will the Activities Be?

The Mason Street Tent had several activities that were likely dominated by JavaOne attendees last year. However, there were some major events that were intended for both conferences. With the completely separate conferences scheduled for 2011 at the same time in the same city, will all the activities be separate as well? Or, will the technical tracks and content be separate with shared activities?


Deals for Those Who Wish to Attend Oracle OpenWorld and JavaOne?

With two totally separate conferences, will there still be reduced pricing for someone wishing to buy passes to both conferences as compared to the price of paying for each conference separately? Would it make sense to purchases passes, even at a reduced rate, to these simultaneous conferences? Problems last year in trying to attend sessions in both included the physical distance and the misaligned session start and stop times between the two conferences. With this year's conferences being intentionally separate, it's likely that the times will be no better aligned than they were last year.


What Will be the Big Announcement(s)?

Many previous JavaOne conferences have been associated with significant announcements. JavaFX has seemed to dominate recent years' JavaOne conferences and it continued to be a major topic at last year's JavaOne 2010. However, last year's big announcement related to JavaFX was the dropping of JavaFX Script and making JavaFX more friendly (new API) to Java and other JVM-based languages. I'm still not convinced that JavaFX has gained significant traction in the Java community, but I thought this direction is the most likely to give it a chance. I suspect we'll hear more about how this work is progressing and will hear sales pitches and evangelism for JavaFX 2.0 at JavaOne 2011.

It is highly likely that Java 7 will be a major topic at JavaOne 2011. I hope that Java 8 will also receive significant coverage because the turnaround for it should be significantly shorter than that for Java 7 based on Mark Reinhold's presentation last year. We might even be fortunate enough to get some more information on Java 9!

Although JavaFX and Java 7 are obvious candidates for major announcements at JavaOne 2011, there are numerous other Java frameworks, libraries, and tools that might receive significant attention.


Separate But Equal?

It sounds like Oracle OpenWorld and JavaOne will be two completely separate conferences in 2011 despite being held in the same city on the same dates. With such a setup, there's little question that Oracle OpenWorld will still be the bigger of the two conferences. It will have more attendees, it will get the Moscone Center, and it will be the conference most well-known by residents of the city. Many JavaOne attendees last year did not like attending the "lesser" conference held in the shadow of the bigger and more well-known conference. I mostly go to conferences such as this for the technical content and was not disappointed. Perhaps the most significant issue I had with JavaOne being the lesser conference was the less audience-friendly environment in the hotel presentation rooms as compared to the Moscone. However, in most rooms, I was able to see most of the slides and only had trouble with things on the bottom of slides. It might be worth warning JavaOne 2011 speakers to avoid using the bottom margin of their slides as much as possible.

I actually kind of liked walking between the hotels and getting some limited outdoors exposure between sessions in different buildings. With Mason Street blocked off, it was easy to get between the three buildings and it was nice to clear my head as I walked between buildings. The weather in San Francisco is late September was beautiful and it should be nice in early October as well. The locations of the rooms were somewhat confusing at first, but I quickly learned where they were and became fairly adept at getting from one session to another.

By most measures, a JavaOne held simultaneously with an Oracle OpenWorld will be deemed the lesser of the two conferences. That doesn't mean that JavaOne still won't be a fabulous, content-rich conference with enthusiastic participants. I am also reminded that last year I thought the JavaOne 2010 keynote was far more interesting than the Oracle OpenWorld 2010 keynote.


Conclusion

I'm looking forward to JavaOne 2011. The mixture of technical content with great locale makes this a great experience.

Monday, April 25, 2011

Posts of Particular Interest: Java and JavaOne, PHP, PowerShell,

In this post, I reference and briefly some posts of particular interest to me in recent weeks. Posts referenced here cover topics such as Java (JavaOne, JMX, Java Memory), PHP, and PowerShell.


Top Java Memory Problems

Michael Kopp's The Top Java Memory Problems – Part 1 provides a nice overview of common memory issues in Java applications. Specifically, he covers memory leaks related to thread local variables, mutable static fields and collections, circular/bi-directional references, JNI, improper equals/hashCode implementations, and classloaders.


Three Free E-books on Beginning Java (and Five on PHP)

Klint Finley's post 3 Free E-Books on Java for Beginners references three freely available e-books about Java. I was already aware of Bruce Eckel's Thinking in Java (as usual, he offers the second newest edition free of charge), but he also mentions How to Think Like a Computer Scientist: Java Edition and Introduction to Programming in Java.

In a related post called 5 Free E-Books and Tutorials for Learning PHP, Finley outlines five freely available PHP resources. As I recently posted, I have plans to start learning and working with PHP, so this post interests me.


Best JVM Replacement Language is Java? (and the Play Framework)

In the post And the best JVM replacement language for Java is: Java?, Mark Watson talks about some of the strengths of Java and discusses things he does "to make Java more agile." He also mentions early satisfaction with the Play framework. In one of the feedback comments on this post, Steven states, "I had to leave Java for the Rails-type frameworks because of the productivity gains. I have to say that with Play! you get the best of both worlds."


Accessing JMX on the Web with Jolokia

In the post Jolokia + Highcharts = JMX for human beings, Tomasz Nurkiewicz writes about using Jolokia ("HTTP/JSON bridge for remote JMX access") in conjunction with Highcharts ("free for noncommercial") to display JMX-provided JVM metrics in a web browser application. There are generic tools such as VisualVM and JConsole that can do some of this, but the flexibility and customizability of an approach like that demonstrated by Nurkiewicz can provide significant advantages in certain situations.


Actors and GPars

Vaclav Pech's Dr. Dobb's Journal article JVM Concurrency and Actors with GPars discusses how GPars (Groovy Parallel Systems) allows actors to be used on the JVM to simulate continuations. As Pech demonstrates this, he also covers highly-related topics such as basics of the actor model, an introduction to GPars for use in Groovy or Java or any JVM language, and lists other features provided by GPars.


PowerShell Language Licensed Under the Community Promise

The Windows PowerShell Blog post PowerShell Language now licensed under the Community Promise states:
The PowerShell team is excited to announce that starting today we are licensing the language specification for Windows PowerShell 2.0 under the Microsoft Community Promise. This means that now anyone can implement PowerShell on any platform they want to.
The specification is available for free download as a docx file.


JavaOne 2011 Formally Announced

There were multiple posts on JavaOne 2011's formal announcement. The JavaOne 2011 post in The Java Source blog and the JavaOne Conference Blog post JavaOne 2011 - October 2nd to 6th in San Francisco confirm that JavaOne 2011 will be held October 2-6, 2011, in San Francisco. This announcement also headlines the DZone Daily Dose and is featured in Java.net's "Spotlights" section.


Conclusion

There's much going on in the world of software development in general and the world of JVM development in particular. The posts I cited above are evidence of this and it is particularly exciting to see fresh new posts on subjects such as JMX, JVM actors with GPars, in-depth coverage of Java memory issues, and so forth.

JavaOne 2011 Formally Announced!

I stated in February that it appeared that JavaOne 2011 would be held in conjunction with Oracle OpenWorld in the first week of October. Very shortly after that particular post, there was some public speculation that the event might be changed in terms of location and/or dates. Based on Tori Wieldt's ("The Java Source") blog post JavaOne 2011, the decision has been made to continue holding JavaOne 2011 the same week as Oracle OpenWorld (2-6 October 2011). The JavaOne Conference Blog post JavaOne 2011 - October 2nd to 6th in San Francisco also confirms this.

Both of the aforementioned posts call out some preliminary details about JavaOne 2011. In particular, it is stated that "we expect to open the call for papers on April 27th and close on Monday May 23rd."

Wieldt's post states some improvements coming to JavaOne 2011 that at least partially address common criticisms of JavaOne 2010. These include acknowledgement of JavaOne being held at the same time as Oracle OpenWorld, but stating "JavaOne is being run as a separate, standalone conference, with its own fully dedicated conference space." This might be disappointing to the small number of people who actually attended sessions in both conferences last year, but I think most of us largely attended one conference or the other. The only time I went to Oracle OpenWorld was for the keynotes.

Other planned improvements for JavaOne 2011 include larger session rooms, increased exhibitor space, more time slots for content, more time and space allowed for collaboration, and "direct involvement from community representatives in planning/steering the event." The JavaOne 2011 main page currently states:
Java community take notice: JavaOne 2011 is exclusively yours. This year’s JavaOne conference brings Java experts and enthusiasts an extraordinary week of learning and networking focused entirely on all things Java.

JavaOne 2011 is now definitely scheduled for October 2-6, 2011, in San Francisco. Registration is now open.

On the Value of Reading Blog Comments

A link to Andy Lester's Perlbuzz post Slipping away from the Perl community is currently featured on reddit Programming. Although I generally try to minimize my exposure to Perl, I find this post and its reddit reference interesting for several reasons. One of the reasons the referenced post interests me is that the post itself talks about a legitimate problem in the blogosphere in general and in our industry in particular. I'll only briefly look at this issue in this post. The reddit reference interests me because of the value of the comments. It is what I learned from these comments that interests me enough to write this post. As a side note, it's nice to see new reddit posts again after Amazon EC2 going down last week and taking reddit with it.

In "Slipping away from the Perl community," Andy Lester's articulates what many of us who have used online resources since the early 1990s have observed: online civility seemingly continues to move to a new low. One of the things I learned from a comment on the reddit reference to this post is that there is a term for this particular phenomenon: Eternal September. Wikipedia describes "Eternal September" as "a slang expression, coined by Dave Fischer, for the period beginning September 1993" that "encapsulates the belief that an endless influx of new users (newbies) since that date has continuously degraded standards of discourse and behavior on Usenet and the wider Internet."

Although there are no comments on the "Slipping away from the Perl community" post itself as of this writing, the number of comments on the reddit reference to the post is approaching 400. Skimming through some of these comments, I have learned a few new things besides the term "Eternal September." One of the interesting things I picked up from a comment is the availability of Modern Perl in various forms at no cost. Although I only use Perl in rare circumstances these days, the three or four books I have on it are somewhat dated. Of course, they still apply for the most part, but it is nice to have another resource available with a more modern perspective on Perl.

Another comment on the reddit reference pointed me to a blog post that I don't recall reading before: Steve Yegge's Ancient Languages: Perl. Yegge is one of the flew bloggers I've read who is more verbose than I am and this post is no exception. In this post, Yegge explains why "if I ever start my own company, Perl won't be allowed there" despite Yegge's opening statement, "I like Perl."

There are numerous other comments on this post that I found interesting either because they reiterated my beliefs, challenged my beliefs with credibility, or presented something I had not thought about before. There are, of course, some of the very types of comments the original post was about (mean spirited). At a very high level, the comments remind one that there are still many developers using Perl, there are many developers who formerly used Perl, there are many developers who feel something else (often Ruby or Python) is now better than Perl, and there are many developers who feel Perl is still the best thing going.

One final observation that is clearly made from the fact that the post itself has zero comments and the reddit reference to it has nearly 400 comments is evidence of the own downside of aggregation sites and syndication. In Trouble in the House of Google, Jeff Atwood describes the unfortunately side effect of syndication that sometimes leads to the syndicated version of StackOverflow ranking higher in a Google search than does the original content. For comments, it is even worse because the comments are not likely to be reproduced in both places (syndicated and original versions). This example is the best (worst?) I've seen of this with essentially an infinite ratio (400 to 0) of comments on the aggregate reference as compared to the original post.

My blog is syndicated on JavaWorld and I appreciate that because it brings significant attention and traffic. Similarly, references from reddit and DZone also drive traffic. The unfortunate side effect, however, is that sometimes some really useful comments are added to the JavaWorld syndicated version or to the DZone or reddit references that are therefore not easily associated with one another or with my original post. I try to identify a comment on one of these forums that is interesting enough to reply to in my blog to ensure it is called out at the source. However, I know that I miss many of these comments altogether. Because comments can often be as useful (and in some cases even more useful) as the original post itself, it'd be nice to have them all in once place. Comments can also correct or address the misunderstandings, misstatements, falsities, typos, logic holes, speculations, and questions that might occur in the original blog post.

I have had several situations on my own blog where feedback comments have provided me with new information. Some recent examples include numerous comments on my post JDK 7: New Interfaces, Classes, Enums, and Methods.

Conclusion

More than once, I've found comments to be as useful as the post itself. The lesson learned is that comments can be well worth the read (or at least skim when there's nearly 400 of them!). I have found comments that refer me to related resources or similar posts often lead me to what I'm looking for or teach me something new. We're often told to "read the fine print." I suggest that when reading blogs, "read the comments."

Saturday, April 23, 2011

Peeking at Office 2007 Document Contents with Groovy

The Microsoft Office 2007 suite of products introduced default support of documents stored in an XML format. Specifically, Office (2007) Open XML File Formats were introduced. Although introduced in conjunction with Office 2007, conversion tools were provided so older versions of these products could also read and write this XML-based format. As documented in Walkthrough: Word 2007 XML Format, there is more than just XML to the new format. Many of the XML files are compressed and the overall format is a compressed ZIP file (albeit typically with a .docx) file extension of numerous content files.

Because Java's JAR file is based on the ZIP format and because Java provides numerous useful constructs for dealing with JAR (and ZIP) files, it is easy to use Groovy to manipulate the contents of a Office 2007 file. In this post, I demonstrate a simple Groovy script that displays a content listing for one of these Office 2007 files.

In Walkthrough: Word 2007 XML Format, Erika Ehrli provides some steps one can take to see the contents of an Office 2007 file. These steps include creating a temporary folder, saving a Word document into that newly created temporary folder, adding a ZIP extension to the saved file, and double clicking on it to open it or extract its contents (the .zip extension makes this automatic). Today's more sophisticated zip-oriented tools can open it without these steps and I'll later show a screen snapshot of doing just that.

For my example, I'm using a draft version (originally written in Word 2003) of my Oracle Technology Network article "Add Some Spring to Your Oracle JDBC." This November 2005 article has not been available online since the merge and consolidation of Oracle articles with Sun-hosted articles, but I still had my draft that I'm using as the example here. The following screen snapshot demonstrates saving the article from Word 2003 as a Word 2007 document.


The next screen snapshot shows that the Word 2007 file is stored with a .docx extension.


As discussed previously, this is really a ZIP file, so it can be opened with ZIP-friendly tools. The next screen snapshot display some of the contents of this Word 2007 format file via the 7-Zip tool.


In Groovy code, I can use classes from the java.util.zip package to similarly view the contents of an Office 2007 file. The next Groovy code listing shows how this might be implemented.

showContentsOfficeFile.groovy
#!/usr/bin/env groovy
// showContentsOfficeFile.groovy

import java.util.zip.ZipEntry
import java.util.zip.ZipFile

if (!args || args.length < 1)
{
   println "Please provide path/name of Office file as first argument."
   System.exit(-1)
}
def fileName = args[0]

def file = new ZipFile(fileName)
def entries = file.entries()
entries.each
{
   def datetime = Calendar.getInstance()
   datetime.setTimeInMillis(it.time)
   // Use GDK's String.format convenience method here!
   print it.name
   println " created on ${datetime.format('EEE, d MMM yyyy HH:mm:ss Z')}"
   print "\t   Sizes (bytes): ${it.size} original, ${it.compressedSize} compressed ("
   println "${convertCompressionMethodToString(it.method)})"
}


/**
 * Convert the provided integer representing ZipEntry compression method into
 * a more readable String.
 *
 * @param newCompressionMethod Integer representing compression type of a 
 *    ZipEntry as provided by ZipEntry.getMethod().
 * @return A String representation of compression method.
 */
def String convertCompressionMethodToString(final int newCompressionMethod)
{
   String returnedCompressionMethodStr = "Unknown"
   if (newCompressionMethod == ZipEntry.DEFLATED)
   {
      returnedCompressionMethodStr = "Deflated"
   }
   else if (newCompressionMethod == ZipEntry.STORED)
   {
      returnedCompressionMethodStr = "Stored"
   }
   return returnedCompressionMethodStr
}

The output of the above script when run against the Word 2007 file mentioned previously is shown next.


The Groovy code shown above produces output similar to that provided by the 7-Zip output shown earlier with details such as content names, normal and compressed sizes, and modification date. I was a little concerned that my Groovy script was returning a 1980 modification date for the contents of this Office 2007 file, but then noticed that 7-Zip reports the same modification date. It's not null, but it's not much more useful.

The Groovy code demonstrates use of java.util.zip.ZipFile and java.util.zip.ZipEntry to access the innards of the Microsoft 2007 file. Another Groovyism demonstrated by the above script is the use of the GDK's Calendar.format(String) method. This convenience method is a "shortcut for SimpleDateFormat to output a String representation of this calendar instance."


Conclusion

The example in this post demonstrates a simple script for viewing contents of a Microsoft 2007 file. This viewing of Microsoft 2007 format contents is nothing that cannot already be done via simple tools. The real potential in accessing these via Groovy is, of course, the ability to write custom scripts to programatically manipulate these contents or to do other things based on these contents.

Wednesday, April 20, 2011

NetBeans 7.0 Released!

It was announced today that NetBeans 7.0 has been released and is available for download. This release of NetBeans includes Project Coin support, GlassFish 3.1 support (embedded with the "Java EE" or "All" download bundles), Maven 3 support, JUnit 4.8.2 integration, HTML5 support, and new PHP support. In the enterprise Java space, NetBeans 7.0 provides "improved support for CDI, REST services and Java Persistence."

There is no Ruby on Rails support built-in to NetBeans 7.0.

Other coverage of the NetBeans 7.0 release is available in Oracle Have Released NetBeans 7.0 with Support for the JDK7 Developer Preview and HTML5, NetBeans 7.0 Adds JDK 7, HTML 5 Support; Drops Ruby on Rails, Oracle Announces NetBeans IDE 7.0 with Support for JDK 7 Developer Preview, and Java 7 and NetBeans 7.

Tuesday, April 19, 2011

Making White Image Backgrounds Transparent with Java 2D/Groovy

I occasionally need to convert the background color of a particular image to be transparent so that the image looks better on medium with backgrounds of colors other than the image's original background color. More specifically, I typically need to convert an image with a white background to have a transparent background so that it blends more naturally with a non-white background. The next screen snapshot shows the difference in appearance between an image with a white background on a non-white background and an image with a transparent background.


There are numerous tools that support conversion of a background in an image to be transparent (assuming the image format supports transparency). However, I have wanted a simple command-line script to do this so that I don't need to open a tool, load a file, select the color to covert, and then save the new image with the transparent background. I figured that someone had already done this in Java and my idea was to "port" the Java to Groovy. In this post, I show a Groovy script that does perform this conversion based on an easy-to-follow example of how to do this in Java that is available in the StackOverflow thread How to make a color transparent in a BufferedImage and save as PNG.

PhiLho and corgrath provide Java code examples illustrating conversion of a background color to a transparent background for an image in the StackOverflow thread How to make a color transparent in a BufferedImage and save as PNG. With these illustrative code examples in place, the most difficult part of the task is already completed. The next Java code listing contains my very slight adaptation of the code provided by them and is provided mainly for easy comparison to the ported Groovy code to be shown later.

ImageTransparency.java
package dustin.examples;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.imageio.ImageIO;

import static java.lang.System.out;

/**
 * Class containing code for converting an image's white background to be
 * transparent, adapted with minor changes from StackOverflow thread "How to
 * make a color transparent in a BufferedImage and save as PNG"
 * (http://stackoverflow.com/questions/665406/how-to-make-a-color-transparent-in-a-bufferedimage-and-save-as-png).
 */
public class ImageTransparency
{
   /**
    * Main function for converting image at provided path/file name to have
    * transparent background.
    *
    * @param arguments Command-line arguments: only one argument is required
    *    with the first (required) argument being the path/name of the source
    *    image and the second (optional) argument being the path/name of the
    *    destination file.
    */
   public static void main(final String[] arguments) throws Exception
   {
      if (arguments.length < 1)
      {
         out.println("A source image file must be provided.");
         System.exit(-1);
      }

      final String inputFileName = arguments[0];
      final int decimalPosition = inputFileName.lastIndexOf(".");
      final String outputFileName =
           arguments.length > 1
         ? arguments[1]
         : inputFileName.substring(0,decimalPosition)+".copy.png";

      out.println("Copying file " + inputFileName + " to " + outputFileName);

      final File in = new File(inputFileName);
      final BufferedImage source = ImageIO.read(in);

      final int color = source.getRGB(0, 0);

      final Image imageWithTransparency = makeColorTransparent(source, new Color(color));

      final BufferedImage transparentImage = imageToBufferedImage(imageWithTransparency);

      final File out = new File(outputFileName);
      ImageIO.write(transparentImage, "PNG", out);
   }

   /**
    * Convert Image to BufferedImage.
    *
    * @param image Image to be converted to BufferedImage.
    * @return BufferedImage corresponding to provided Image.
    */
   private static BufferedImage imageToBufferedImage(final Image image)
   {
      final BufferedImage bufferedImage =
         new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
      final Graphics2D g2 = bufferedImage.createGraphics();
      g2.drawImage(image, 0, 0, null);
      g2.dispose();
      return bufferedImage;
    }

   /**
    * Make provided image transparent wherever color matches the provided color.
    *
    * @param im BufferedImage whose color will be made transparent.
    * @param color Color in provided image which will be made transparent.
    * @return Image with transparency applied.
    */
   public static Image makeColorTransparent(final BufferedImage im, final Color color)
   {
      final ImageFilter filter = new RGBImageFilter()
      {
         // the color we are looking for (white)... Alpha bits are set to opaque
         public int markerRGB = color.getRGB() | 0xFFFFFFFF;

         public final int filterRGB(final int x, final int y, final int rgb)
         {
            if ((rgb | 0xFF000000) == markerRGB)
            {
               // Mark the alpha bits as zero - transparent
               return 0x00FFFFFF & rgb;
            }
            else
            {
               // nothing to do
               return rgb;
            }
         }
      };

      final ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
      return Toolkit.getDefaultToolkit().createImage(ip);
   }
}

A first cut at a Groovy port of the above Java class is shown in the next Groovy code listing.

makeImageTransparent.groovy
#!/usr/bin/env groovy
// makeImageTransparent.groovy

import java.awt.Color
import java.awt.Graphics2D
import java.awt.Image
import java.awt.Toolkit
import java.awt.image.BufferedImage
import java.awt.image.FilteredImageSource
import java.awt.image.RGBImageFilter
import javax.imageio.ImageIO

/*
 * Script containing code for converting an image's white background to be
 * transparent, adapted with minor changes from StackOverflow thread "How to
 * make a color transparent in a BufferedImage and save as PNG"
 * (http://stackoverflow.com/questions/665406/how-to-make-a-color-transparent-in-a-bufferedimage-and-save-as-png).
 *
 * Command-line arguments: only one argument is required
 * with the first (required) argument being the path/name of the source
 * image and the second (optional) argument being the path/name of the
 * destination file.
 */

if (args.length < 1)
{
   println "A source image file must be provided."
   System.exit(-1);
}

def inputFileName = args[0];
def decimalPosition = inputFileName.lastIndexOf(".")
def outputFileName = args.length > 1 ? args[1] : inputFileName.substring(0,decimalPosition)+".copy.png"

println "Copying file ${inputFileName} to ${outputFileName}"

def input = new File(inputFileName)
def source = ImageIO.read(input)

def color = source.getRGB(0, 0)

def imageWithTransparency = makeColorTransparent(source, new Color(color))

def final BufferedImage transparentImage = imageToBufferedImage(imageWithTransparency)

def out = new File(outputFileName)
ImageIO.write(transparentImage, "PNG", out)



/**
 * Convert Image to BufferedImage.
 *
 * @param image Image to be converted to BufferedImage.
 * @return BufferedImage corresponding to provided Image.
 */
def BufferedImage imageToBufferedImage(final Image image)
{
   def bufferedImage =
      new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
   def g2 = bufferedImage.createGraphics();
   g2.drawImage(image, 0, 0, null);
   g2.dispose();
   return bufferedImage;
}

/**
 * Make provided image transparent wherever color matches the provided color.
 *
 * @param im BufferedImage whose color will be made transparent.
 * @param color Color in provided image which will be made transparent.
 * @return Image with transparency applied.
 */
public static Image makeColorTransparent(final BufferedImage im, final Color color)
{
   def filter = new CustomImageFilter(color)
   def ip = new FilteredImageSource(im.getSource(), filter)
   return Toolkit.getDefaultToolkit().createImage(ip)
}

/**
 * Was 'anonymous inner class' in Java version.
 */
public class CustomImageFilter extends RGBImageFilter
{
   private int markerRGB

   public CustomImageFilter(final Color color)
   {
      // the color we are looking for (white)... Alpha bits are set to opaque
      markerRGB = color.getRGB() | 0xFFFFFFFF
   }

   public int filterRGB(final int x, final int y, final int rgb)
   {
      if ((rgb | 0xFF000000) == markerRGB)
      {
         // Mark the alpha bits as zero - transparent
         return 0x00FFFFFF & rgb
      }
      else
      {
         // nothing to do
         return rgb
      }
   }   
}

The (slightly) adapted Groovy script above will convert the white portions of the provided image to be transparent and will save the new image with transparent portions (assumed to be background) to a new PNG file (of either provided name or of default based on source file's name).

Although the above Groovy script is sufficient for my most common need, there are numerous improvements that can be made to this script to make it more usable. Groovy's CLI support could be leveraged to allow more options or more granular options to be specified. Colors other than white could be used as the source color to the changed to be transparent. Formats that support transparency could be specified rather than using PNG by default.


Conclusion

One of the advantages of using Java or an alternative JVM language is access to the rich Java SDK and access to the insight and previous experience of a large Java/JVM community. In this post, I've attempted to demonstrate how these advantages were leveraged to come up with a useful script in a very small amount of time.

Monday, April 18, 2011

Software Development Posts of Interest - 18 April 2011

There have been numerous insightful blogs and articles on Java and other software development in recent days. I reference and summarize some of these in this post because I think they're worth a look.


Tips for Making a Developer's Life Easier

In the post Some tips to make a developer’s life easier, Bob Belderbos writes about "best practices of development" he has gained from "experience I gained building apps." He outlines six tips that I'd categorize as "general development tips" that apply to various types of software development.


Oracle Open Office and Oracle Cloud Office

Gavin Clarke's Ellison's Oracle washes hands of OpenOffice is interesting for a variety of reasons. An obvious reason for reading this post is provided in the first sentence: "Oracle is turning OpenOffice into a purely community project, and no longer plans to offer a commercial version of the collaboration suite loved by many." Another point of interest is Clarke's mention of the seeming abandonment of Oracle Cloud Office. Finally, Clark's statement about JavaFX is interesting:
Among the ideas Oracle had lined up for OpenOffice under its control: a call to rewrite it using the closed-source JavaFX language for interface development that nobody cares about but Oracle.


To Do or Not To Do for a New JVM Language

Sven Efftinge addresses those thinking about designing JVM languages in a post called Dear Java Killers and discusses "seven most important Dos and Don'ts you should consider when developing a language for the Java community". As is often the case with the best blog posts, the feedback comments add significantly to the discussion.


Ceylon

Gavin King's "Introducing the Ceylon Project" presentation was highlighted in Marc Richard's post Gavin King unveils Red Hat's Java killer: The Ceylon Project. Richard analyzes what he likes about what he has seen related to Ceylon. Ceylon has already been the subject of significant discussion.

In the post The rationale for Ceylon, Red Hat's new programming language, Ryan Paul examines the reasons for King and Redhat to pursue a successor to Java. He also points out that many in the Scala community wonder why they don't simply use Scala instead of developing yet another new language for the JVM.

Gavin King has commented on the surging interest in Ceylon in the posts Ceylon and Ceylon presentation: a clarification. He also answers questions about Ceylon in Alex Blewitt's interview post Ceylon JVM Language.

Several in the Scala community seem at least a little put off by the idea of Redhat working on a new JVM language instead of using Scala. An example is the post Ceylon: Interesting for the Wrong Reasons. Post author Lachlan O'Dea argues that he'd be likely to pick Ceylon over Java, he thinks Scala is superior to what Ceylon will offer. Toward the end of his post, he states:
You may wonder, "if you think Scala is so good, then use it and be happy, why worry about Ceylon?" Well, I worry because I think Ceylon is worse than Scala, but it could win anyway. That actually seems to be the more common outcome in these situations. I would much prefer a world with Scala jobs in demand than one with Ceylon jobs in demand. So, yes, it’s all about me being selfish. I would say to all Scala fans: don’t be afraid to be a little selfish and evangelise for the better outcome.

I'm not the only one who has noted that the Scala enthusiasts seem more concerned about Ceylon than they have been about other alternative JVM languages that have come about since Scala. The only reasonable explanations for this different reaction must have to do with the major player involved with Ceylon (Redhat).


Devops

The term "devops" has started gaining some traction recently. I ran across two posts this week that provide nice introductory overviews of the "devops" concept. In What Is This Devops Thing, Anyway?, Stephen Nelson-Smith (guest blogging on Patrick Debois's blog) describes the devops movement as a "multi-disciplinary approach" and states:
The Devops movement is built around a group of people who believe that the application of a combination of appropriate technology and attitude can revolutionize the world of software development and delivery. The demographic seems to be experienced, talented 30-something sysadmin coders with a clear understanding that writing software is about making money and shipping product.

Nelson-Smith also focuses on the idea of "sysadmin coders" and states that the concept is an acknowledgement that "there is no one IT skill that is more useful or more powerful than another." He adds, "To solve problems well you need all the skills. When you build teams around people who can be developers, testers, and sysadmins, you build remarkable teams."

Dan Ackerson's post DevOps Entrenched – Tide Begins to Turn references a description of devops stating that devops helps "improve cooperation between developers and sysadmins." The concepts of devops may be best summarized in a sentence in this post: "Developers and Sysadmins are joining forces and forming 'Delivery Teams' – working together to ship high quality products to customers faster than ever."


JVM Interaction via File Locking and Groovy

Brock Heinz's blog is named in Groovy closure style as "thoughts.each { println it }". His post Inter JVM Communication demonstrates using Groovy in conjunction with Groovy GDK's version of java.net.Socket to determine if two instances of the same application are running. Kovica left a comment stating that use of FileChannel would be effective for this situation and pointing to Kovica's post on that very subject. I took concepts from both to come up with this marriage of Groovy and FileChannel use:

#!/usr/bin/env groovy
def timeoutMs = args ? args[0] as Integer : 10000
def lockFile = new File("dustin.lock")
def fileChannel = new RandomAccessFile(lockFile, "rw").getChannel()
def fileLock = fileChannel.tryLock()
if (fileLock)  // non-null (Groovy Truth) means not locked by another instance
{
   println "Busy working ..."
   Thread.sleep(timeoutMs)
}
else
{
   println "This application is already running!"
}

The following snapshot shows how the lock works when the script is run separately and nearly at the same time.



Conclusion

In this post, I referenced and briefly summarized posts that I found to be particularly interesting in recent days. I am especially interested to see what the future holds for Ceylon and for the devops movement.

Saturday, April 16, 2011

Why PHP Will Be My Next Language

I've never liked PHP.

I first looked at PHP over decade ago and did not like what I saw. No, my response was stronger than that. I vehemently loathed what I saw. The syntax was ugly, nearly all samples of PHP code seemed unmaintainable, and the liberal intermixing of PHP/HTML/JavaScript/SQL syntax (Tim Bray referred to it in On PHP as "Spaghetti SQL wrapped in spaghetti PHP wrapped in spaghetti HTML, replicated in slightly-varying form in dozens of places") offended my JSP sensitivities. Everything about PHP smelled like a language for hackers, not for real software developers. Even the story of PHP's nerdy recursive acronym (PHP Hypertext Preprocessor) seemed to irritate me. It was loathing at first sight.

Although I form very strong opinions regarding software development as I learn lessons from experience, I also endeavor to keep an open mind and be willing to even change my mind sometimes, especially if the thing I have formed an opinion about changes. I blogged about an example of this in How I Learned to Stop Worrying and Love Java's Ternary Operator. Several observations have led me to think that I need to look closer at PHP again and that perhaps my opinion of PHP may improve. In this post, I look at these interrelated observations that have led me to decide to give PHP another look.


Prevalence

PHP has become a highly prevalent programming language on the web. PHP Usage Stats indicate a general upward trend in PHP usage. On the current TIOBE Programming Community Index (April 2011), PHP is the fifth-most popular programming language. I see .php in URLs all over the place. Both anecdotal and more objective evidence indicates that PHP has become a widely popular language. Knowing the basics of PHP and having some PHP experience cannot help but make a developer's skills more generally applicable and add a meaningful tool to the developer's tool set.


Rounding Out the Top Five

As I mentioned above, PHP is the fifth most popular language on the Tiobe Programming Community Index. It happens to be the only one of the top five that I have never used in any significant way. I've used the first four (listed in order they appear on the index: Java, C, C++, and C#) significantly more than PHP. I've worked quite a bit with Java, C++, and C, and have worked enough with C# to feel comfortable with it, but I have not put similar effort into using or learning PHP because of my initial adverse response to it.


Web 2.0 is PHP's Home Turf

The web has become home turf for PHP. Both Facebook and Amazon Elastic Compute Cloud, for example, provide PHP libraries and APIs as primary exposure mechanisms. The Facebook open source page states regarding PHP, "PHP is an incredibly popular scripting language which makes up the majority of our code-base. Its simple syntax lets us move fast and iterate on products." The Facebook SDKs and Tools page features the open source (generally Apache 2 license) PHP SDK. The other listed Facebook SDKs are either for mobile devices operating systems or for the JavaScript SDK or Python SDK. The C# SDK is not listed presumably because it's in alpha release. Facebook stopped supporting its "official" Java SDK in February 2008 reportedly because of the availability of third-party Facebook Java APIs such as facebook-java-api. Even the movie The Social Network featured PHP code in some scenes.

I've been reading the book Host Your Web Site In The Cloud: Amazon Web Services Made Easy: Amazon EC2 Made Easy. All the examples in this book are in PHP. The Amazon Web Services PHP Developer Center contains more articles and references on using PHP with Amazon Web Services (including the AWS SDK for PHP). There is a series of articles on developerWorks regarding Cloud Computing with PHP.

Drupal's adoption for Whitehouse.gov's 2009 overhaul was big news for highly popular Drupal. Although use of Drupal does not require thorough knowledge of PHP, knowledge of PHP can be very helpful when using Drupal because PHP is an integral part of Drupal's technology stack. An example is the ability to include PHP snippets that can be inserted into a Drupal application (JavaScript snippets and SQL snippets are the other allowed code snippets).


Not Just for Hackers Anymore

I think that many of us who dabbled a bit with PHP years ago have been left with a stubborn impression that PHP is for hackers. In Holub on Patterns, Allen Holub wrote, "A determined individual can write garbage code in any language." I have found this to be true in any programming language that I have used in any significant way, but it seemed pervasive in PHP code even without needing to spend much time in that environment. I have reason to believe that things may have been improved or may be improving in PHP.

PHP 5 introduced true object-oriented principles. "Design patterns" and "PHP" have even started to be used in the same sentence. I was encouraged to see that the book PHP in Action talks about subjects such as objects, design, unit testing, and refactoring in relation to PHP.

I had already decided to try PHP out again, but was even more motivated to do so after reading Why PHP was a Ghetto. Post author Kenny Katzgrau writes about "why the non-PHP development world generally has such disdain for PHP and the community surrounding it." His list of reasons all apply, but I also think he nails the main reason when he writes, "PHP code bases tend to be hacky and unmaintainable." None of this was a surprise to me because it certainly has been the opinion of just about every non-PHP developer I have known, but I was also encouraged to read this:
PHP was a ghetto. But the development of frameworks like Zend and CodeIgniter have greatly pushed the language development into the right direction. ... The fact is, a PHP applications can be as well-written as an application in any other language, and probably have the additional advantage of speed. The widespread use of MVC-style development in the PHP world is a relatively recent phenomena though, and admittedly, we can probably thank Rails for it.

Because Katzgrau seems to understand the source of disdain for PHP in the past, I'm hoping that his positive assessment of where it is today and the direction it is moving is correct. It sure sounds promising!

One of the reasons I like to learn new languages every once in a while is to adopt practices from those languages in my coding and to better "think outside of the box." I have to admit that I have not previously been interested in learning any PHP because I didn't want to learn any of that or be tainted by any of those practices. I'm less fearful now of the negative influence of immersing myself in this language now.


Practicality

In the previously mentioned blog post Why PHP Was a Ghetto, post author Kenny Katzgrau wrote, "I’m no PHP fanboy — in fact, I’m very language-agnostic. I write PHP more often because, you guessed it, people pay me to." In the end, my renewed interest in PHP comes down to my believing that it offers the most obvious practical advantages at this point in time. Had I not gotten into Groovy, I probably would have dived into Python as my next major language, but Groovy is fulfilling my outside-of-the-web-browser scripting needs nicely. I also have significant interest in Scala and Clojure, but I think there are more practical advantages to learning PHP better at this point.

In many ways this is analogous to human languages. Although there may be many appealing features to languages such as Italian, French, Japanese and so forth, I feel that learning Spanish is the most practical "second language" for those of us who are primarily English speakers living in the western United States. There is little question that Spanish is the most common spoken and written language encountered on a daily basis in the western United States after English. Even if I was attracted to languages other than Spanish, the most practical move would be to improve my Spanish vocabulary and speaking and listening skills. It's the language that I'd have the most opportunity to use and take advantage of on a regular basis. For me, PHP is like this in the computer programming world. I already know several widely prevalent programming languages in Java, C, and C++, but PHP is an obvious "major language" that I am likely to run into repeatedly in the future.


PHP's Fit

PHP is obviously known as web scripting language. The PHP FAQ states, "PHP is an HTML-embedded scripting language." Although PHP does now offer command line scripting support, I'm not interested in it for that. I have a difficult time imagining where I'd use PHP for command line scripting over Groovy, Python, or even Perl. In fact, I'd probably use shell scripting before I'd use PHP command line scripting. It's definitely on the web that PHP offers its greatest potential and benefit.


NetBeans PHP Support

A minor factor influencing my decision to start learning PHP in earnest is the availability of PHP code support in NetBeans 7.0 (available in previous versions as well). I use NetBeans frequently for my Java and Groovy development, so it is nice to continue using a tool I'm comfortable with to work with PHP. Although there is a "PHP only" download option for NetBeans, I already use the "All" version that includes PHP.


Conclusion

Despite a general disdain toward PHP from most of we non-PHP developers, it is obvious that PHP has been wildly successful in the web browser space. I still don't know if I'll learn to love or even like PHP, but I want to believe. I certainly think I can benefit from a certain level of comfort with such a prevalent language. I also believe that basic familiarity with PHP can open up new software development opportunities. Learning Groovy has provided me with several practical advantages that I use on a near daily basis, but some of the new languages I have learned before have offered less concrete advantages for regular use. I'm hoping learning PHP will provide me the types of benefits that learning Groovy provided. I doubt that I'll ever use PHP as much as I use Java/Groovy, but I do look forward to learning more about a language that is largely new to me.