Design

WYSIWTF

Too funny

AJAX/Web 2.0
Design
General
Quotes
Software Development
Thought

Comments (0)

Permalink

Groovy + Annotations + Aspects

I have been doing a lot of digging into Groovy and DSLs lately, getting ready for my OSCON talk next week.

The Groovy language has great built-in support for creating DSLs. Along with its dynamic nature, Groovy has the “use” keyword for working with categories, and coming in 1.1, the ExpandoMetaClass if you want to complete.

“Use”ing Categories

Categories help you do scoped “extension” to normal every day objects. An example is in order:

  1. class TacoCategory {
  2.         static String getTacos(final Integer i) {
  3.                 “${i} tasty tacos”
  4.         }
  5. }
  6.  
  7. use (TacoCategory.class) {
  8.         println 2.tacos     // outputs -> "2 tasty tacos"
  9. }

So, inside the use block, there is now (effectively) a new property on the Integer class, called tacos, that will return a string describing your delectable entree. This is a very powerful technique, and is very useful for developing your own expressive syntax.

One drawback to this technique is that you have to define where you are using it. Use can be extended into closures, but does not always extend into predefined methods.

  1. aClosure = { println 3.tacos }
  2.  
  3. use (TacoCategory.class) {
  4.  aClosure.call()  // outputs -> "3 tasty tacos"
  5. }
  6.  
  7. aClosure.call()  // Exception No such property: tacos for class: java.lang.Integer
  8.  
  9. // However, you can do this from Java (or Groovy):
  10. GroovyCategorySupport.use(TacoCategory.class, aClosure)  // outputs -> "3 tasty tacos"
  11.  
  12.  
  13. //  calling methods on a class:
  14. class A {
  15.         public String getTacos() {
  16.                 4.tacos  // has not been evaluated yet
  17.         }
  18. }
  19.  
  20. println new A().getTacos()   // Exception No such property: tacos for class: java.lang.Integer
  21.  
  22. // but you can do this:
  23. use(TacoCategory.class) {
  24.   println new A().getTacos() // outputs -> "4 tasty tacos"
  25. }

Groovy + Annotations + Aspects = annotated “use” clause

I was talking about Groovy Categories with Blaine Buxton, and was telling him that I did not like having the “use” block inside my DSL code, and wanted a more transparent approach. He suggested that perhaps an Annotation and an Aspect would do what I was looking for.

With the 1.1-Beta1 Release, Groovy has built in support for Java Annotations, and since Groovy compiles down to byte code, there is implicit support for Aspects. Putting these two things together allows us to create an annotation for a more powerful use:

  1. class AnnotatedObject {
  2.  
  3.   @Uses(category=[MeasurementCategory.class])
  4.   public String fourPoundsOfSomething(something) {
  5.     (4.lbs.of(something)).toString()   
  6.   }
  7. }

With a simple annotation, @Uses(category=[list of category classes]), we now can define them for any method we want, without having to put them into the method body.

Here is the Annotation code:

  1. package com.nimblelogic.groovy.dsl;
  2.  
  3. import java.lang.annotation.Inherited;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6.  
  7. @Inherited
  8. @Retention(RetentionPolicy.RUNTIME)
  9. public @interface Uses {
  10.   public Class[] category();
  11. }

And here is the Aspect code:

  1. package com.nimblelogic.groovy.dsl;
  2.  
  3. import groovy.lang.Closure;
  4.  
  5. import java.util.ArrayList;
  6. import java.util.List;
  7.  
  8. import org.aspectj.lang.JoinPoint;
  9. import org.aspectj.lang.annotation.SuppressAjWarnings;
  10. import org.aspectj.lang.reflect.MethodSignature;
  11. import org.codehaus.groovy.runtime.GroovyCategorySupport;
  12.  
  13. public aspect UsesAspect {
  14.        
  15.      pointcut allMethods(): call(@Uses * *(..));
  16.    
  17.     @SuppressAjWarnings
  18.     Object around(): allMethods() {
  19.         List< class >  classes = getCategories(thisJoinPoint);
  20.  
  21.         Object result = null;
  22.         if ( classes.isEmpty() ) {
  23.             result = proceed();
  24.         } else {
  25.                 result =
  26.                         GroovyCategorySupport.use(classes,
  27.                             new Closure(thisJoinPoint.getTarget()) {
  28.                                 @Override
  29.                                 public Object call() {
  30.                                     return proceed();
  31.                                 }                         
  32.                             });
  33.         }      
  34.        
  35.         return result;
  36.         }
  37.    
  38.     @SuppressWarnings(“unchecked”)
  39.         private List< class > getCategories(JoinPoint thisJoinPoint) {
  40.         List< class > classes = new ArrayList< class >();
  41.        
  42.         // get class level categories (if any)
  43.         Class cl = thisJoinPoint.getTarget().getClass();
  44.    
  45.         addCategories((Uses) cl.getAnnotation(Uses.class), classes);
  46.        
  47.         // get method level categories (if any)
  48.         if ( thisJoinPoint.getKind().equals(JoinPoint.METHOD_CALL)) {
  49.             MethodSignature sig = (MethodSignature) thisJoinPoint.getSignature();
  50.             addCategories((Uses) sig.getMethod().getAnnotation(Uses.class), classes);
  51.         }
  52.  
  53.         return classes;
  54.     }
  55.    
  56.    
  57.     private void addCategories(Uses uses, List< class > classList) {
  58.         if ( uses != null ) {
  59.                 Class[] classes = uses.category();
  60.                 for(Class cl : classes)
  61.                     classList.add(cl);
  62.         }
  63.     }
  64. }

One thing to note when working with Annotations / Aspects in Groovy: you have to keep track of the build order. I struggled for a while to figure out why I was not seeing the annotation in my Groovy classes. It was because it had not been built yet! I ended up having to split my compilation into 4 parts:

  1. Build the Annotation
  2. Compile the Groovy code
  3. Compile my other Java code (just test code)
  4. Weave the Aspects

Design
General
Grails
Groovy
Java
Software Development
Speaking
Thought

Comments (4)

Permalink

Uncle Bob on XML

I’m trying to catch up to my overflowing Google reader, and have just seen Uncle Bob’s posting on XML “The Hidiocy of XML Languages“:

Look, writing in XML is hideous. It’s wordy, it’s error-prone, it’s arcane, it’s redundant, it’s redundant, it’s redundant, it’s… HIDEOUS! To make matters worse, we have been embedding OTHER languages INSIDE this horrible container. EGAD! YIKES! ZOUNDS! FORSOOTH! This is just plain nuts, stupid, idiotic, retarded, poo-poo-headed, silliness!

All I can say is AMEN!!! And it just gets better.

I’ve never been a fan of XML. Yes, it does have benefits as a data transfer mechanism, though even that is questionable. Take the ACORD standards as an example. This is the standard schema for defining interoperability standards for Insurance Company operations/transactions (Quotes, etc). Fair enough, this can be very useful for companies to work together. However, each insurance company has it’s own way of doing business, and may not use the schema in the same way. ie a Policy for this company (or even Line of Business) may not mean the same as for another. So, how interoperable is that?

XML sucks. Its better than binary, or — shudder — ASN.1, but it still sucks, and should not be used as a language. Thank you Uncle Bob for your rant! It makes me that maybe, just maybe, I’m not as insane as people think when I tell them that I hate writing logic in XML.

Design
General
Software Development
Thought

Comments (2)

Permalink

What is Success in the Enterprise?

I got a comment on my James McGovern::Thought Leadershit blog post earlier today, ostensibly from James himself, that I feel compelled to respond to:

Don’t have such a low threshold for measuring success. Success is Java, .NET, XML, Web Services, SOA, etc. Ruby has potential and an upward trajectory but can’t yet be called successful.

In terms of getting large enterprises whose primary business model isn’t technology involved in Ruby benefits Ruby by the simple fact that this demographic represents 90% (The masses) of all IT folks. More importantly, this same demographic has 590% more capital than the 10% that Ruby currently has. Capital allows folks to accelerate the growth, features and adoption of all the hard work the Ruby community put into it.

You should noodle this thought and even if you agree slightly, you should amplify it in your next blog entry…

I slightly agree with the above, mostly with the demographics and the problems those demographics cause. Not sure about the math…. However, what I really want to address is not the demographics… those are a causal by-product the misunderstanding evident in these statements:

Don’t have such a low threshold for measuring success. Success is Java, .NET, XML, Web Services, SOA, etc. Ruby has potential and an upward trajectory but can’t yet be called successful.

My definition of success in the enterprise has absolutely nothing to do with the technology used. Technology is nothing more than an enabler for the solutions set forth by the organization to accomplish its goals. Java, .Net, XML, Web Services, SOA, and yes, even Ruby are all just tools (and fads) that we have at our disposal at this point in time that help accomplish these goals. They are not the success factors themselves.

I am much more concerned with providing value and efficiencies to the organization. Solving problems matters more then the technology used.

What I value more than the programming language

  1. Right sized solutions to the right problems. It is so easy to build the wrong sized solution, buts worse when its not even the right problem.
  2. Simplicity Simplicity is a mindset. But lets not mistake it for “Do the simplest thing that could possibly work.” Do the simplest thing that can be maintained for 10 years.
  3. Maintainability I am sick and tired of hearing about brand spanking new projects using Struts, because thats what people know. But, on the other hand, if you can see struts still being used (and supported) at the EOL for your project, by all means. Typically I prefer to weigh my decisions on what is the latest, with the most likelyhood to succeed. Failing that (which most frameworks do), I want to know how bad (unreadable) the frameworks code is… good sign of how easy it will be to fix problems when you are on your own.
  4. Flexibility I want flexibility in my language, my IDE, my organization, and not least of which: my system’s architecture.
  5. Structure But, you cannot be all flexibility. Think of your app as a piece of Bamboo. Simple, elegant, solid, and flexible in the wind.
  6. Understanding The team must be able to read my code. Everyone (devs, admins, users, everyone) must understand the vision of the app. Without this, you have people doing things that will invariably be incongruent with the vision and goals of the team and organization.

In essence, I want everyone to think about what they are doing, and try to come up with the simplest, most maintainable system they can. I think that that is difficult in every language, and in fact I think it transcends language. This is the Silver Bullet problem (there isn’t one). So, all I can do is try to design the system the best I can, and then use a language that gives me the best Thought to Expression ratio for my solution.

Thought to Expression Ratio

I’ve mentioned this a couple of times before. Thought to Expression Ratio is a very subjective measure of how much expression is needed to convey a thought, with a ratio of 1:1 being perfect expression of a thought and 1:0 being the no expression capable of the thought.

As an example, remember the old saying “A picture is worth a thousand words”. Now, if only we had a programming language that could do that. Well, we do in a way. This is were Domain Specific Languages come into play. We can bring the programming system closer to the thoughts of the organization, and in so doing, raise the Thought to Expression ratio. And right now, there are few languages that give me the flexibility to define a DSL easily, with Ruby being the one with the most interest pointed in its direction.

Durability

By day I am a Enterprise Java developer/architect. By night I play with Ruby, and Smalltalk, and other languages that intrigue me. Why? Because Java will not be around forever. Java is indeed the next COBOL. In fact, so is Ruby. And C++, and VB, and .Net. and ….

I am a proponent of Ruby, though not as much as one might think given some of my previous posts. I value the flexibility that Ruby gives me, but I also hate the sheer power with which Ruby allows a person to write the most horrendously ugly code this side of perl. Indeed, this is what could very well be the downfall of Ruby.

Success

In the end, success on an Enterprise application can only be determined by the organization and teams involved. This is a hard problem, especially the more stakeholders involved in the definition of success. And, to me, that has nothing to do with the languages involved.

Agile
Design
General
Java
Ruby
Self
Software Development
Thought

Comments (2)

Permalink

Epigrams on Programming

Just ran across Alan Perlis’s Epigrams on Programming:

This one goes with my recent rant on interfaces:

The string is a stark data structure and everywhere it is passed there is much duplication of process. It is a perfect vehicle for hiding information.

Design
General
Software Development
Thought

Comments (0)

Permalink