We will be having another installment of the Charleston SC Java Users Group meeting tonight. I will giving an introduction to Grails presentation.
Swing by if you are going to be in the area!
You can get directions and more info here.
We build awesome here.
We will be having another installment of the Charleston SC Java Users Group meeting tonight. I will giving an introduction to Grails presentation.
Swing by if you are going to be in the area!
You can get directions and more info here.
I have been working on a project for the past couple months in my spare time. The problem is that with a new baby, the Java Users Group, maintaining my design patterns references (Version 1, Version 2), this blog, and work I have had no time over the past month to actually work on it. The other night I managed to find some time to work on this for a while, only to realize that I had stopped in mid-implementation with only a class diagram and my memory to work from. I should have documented the requirements better from the beginning but since the application is for me and I planned on finishing it quickly I didn’t see a need.
So I found myself the other night with a pretty complex class diagram with no explanation of what the various classes, attributes, and associations signify. Oops. So to figure this out I came up with a method of supplementing the class diagram that ended up working pretty well for me. I have not seen this used anywhere else so I’ll stamp my great big ™ on it. Hopefully you will all find this as useful as I did.
Lets just work through a quick and dirty contrived example:
While it is pretty easy to implement this actual data model, it is considerably more difficult to apply business rules to the application based on just this. So I took my diagram and worked backwards in a couple parts:
Part 1: Class cases
This part defines the cases when each class will be created, updated, and/or destroyed. The notation is simply to use the class name followed by a description. Each description should start with the words created, updated, or destroyed so that a quick glance will tell the meaning of the line. If creation, updating, or destruction does not occur, just leave it off.
So in our scenario, we would have:
Person
|
Feedback
|
Meeting
|
Attendee
|
Part 2: Relationship cases
This part defines the cases that relationships would be created, updated, or destroyed. While this will prove useful for all associations, it will prove more useful for those where the association exists independently of the classes involved. The descriptions are the same as in part one in that they should each begin with the words created, updated, or destroyed. However, the notation is a bit different in that the relationship must be captured in the notation. To signify this we will use the two (or more) objects involved in the relationship, connected by a line. I used a slightly different notation as it is plain-text compatible, however using the UML connector notation would work just as well.
To define a one to one relationship, you would simply link the two objects with a line:
To define a one to many relationship between two objects you would use an open bracket at the end where the many relationship is:
To define a many to many you could use a couple different notations:
Finally, to note realizations you use the same notation, only with a dashed line:
So in our case this would yeild:
Person – – – Feedback
|
Person —-< Attendee >—- Meeting
|
Attendee —– Feedback
|
By using this notation I can document the purpose of each class and relationship as well as the conditions in which is created, updated, or destroyed. By working from this I can now quickly determine what business rules I need to implement in order to maintain the proper relationships and objects within the system. While this is a pretty simple feat with this contrived example, it becomes significantly more complex when you have 20+ classes and the same number of associations and references.
Closures (aka Blocks) are essentially blocks of code that can be passed as arguments to a function or method. Unlike method pointers, anonymous classes, and other similar things, closures have the unique ability to be able to see the value of variables in the same scope they were created in. For example, if you declare a variable on one line and a closure on the next, the closure will have visibility of the variable when the closure executes, assuming it is passed into the closure.
Martin Fowler has a great example of this. To pull only certain items out of a collection in Java you’d have to do something like this:
public static List<Item> getItemsWeCareAbout(List<Item> orig) { List<Item> toReturn = new ArrayList(); int val = 230; for (Item item : orig) { if (item.meetsConditionWeCareAbout(val)) { toReturn.add(item); } } return toReturn; }
However, the same code in Ruby can be done like this:
def items_we_care_about(orig) val = 230 return orig.select { |i| i.meetsConditionWeCareAbout val } end
The Ruby version utilizes closures in that we can pass a block of code into the select method. The actual closure is the code within the curly braces ({..}). This code simply says that each item ( |i| ) that returns true from the meetsConditionsWeCareAbout method should be included in the return collection. Also note that the variable declared in the method is passed into the closure, meaning that the closure has visibility into the variable each time it is executed, not just when it was defined.