GRAILS Domain Classes and GRAILS plugins can provide phenomenal examples of declarative programming where a simple declaration adds lots of functionality without any coding. Still the programmer is faced with choices, for example, custom domain class validation can be either done by hand (with curlies) or in a nice reusable way using more functional and declarative programming.
Here is a simple domain class to start:
1: class Meeting {
2: Date start
3: Date end
4: String title
5: }
Looks like little ventured, little gained, but these looks are very deceiving. The above domain class is a feature rich hibernate DAO. You can do with it things like:
Meeting.findAllByStartBetween(new Date() -7, new Date())
orMeeting.findByTitleLikeAndStartGreaterThan(…)
On a side note: this is a true Groovy magic. These methods do not really exists, in Groovy a class responds to a method, it does not necessarily have a method.Add the following plugins to your grails project: audit-trail, spring security core, and searchable. Add simple declarative changes to the Meeting class:
1: @gorm.AuditStamp
2: class Meeting {
3: Date start
4: Date end
5: String title
6:
7: static searchable = true
8: }
New magic has happened: Meeting class has new fields representing (these names are configurable) whoCreated, createdDate, whoUpdated, updatedDate and obviously finding all Meetings that I have created in last 7 days is as simple as calling
Meeting.findAllByWhoCreatedAndStartGreaterThan(...).
The searchable plugin allows you to do things like Meeting.search(...) or easily search across different domain classes with a similar declarative configuration. GRAILS/GORM provides you with a phenomenal declarative power!The list of plugins that can be added goes on and on and the functionality you can add to your domains in this declarative fashion is boundless.
GOING BACK TO EARTH: By default all fields are not nullable and GRAILS has no way of knowing that some data does not make sense, for example start Date should be always before end Date! So lets make the corrections:
1: class Meeting {
2: Date start
3: Date end
4: String title
5:
6: static constraints = {
7: end nullable: false, validator: {value, record ->
8: if (value && record.start && value < record.start) {
9: 'endDateNotAfterStart'
10: }
11: }
12: }
13: }
The new version provides a custom validation for the end date. The logic simply returns a message string (to be translated by GRAILS i18n infrastructure) if the end date was entered, start date was entered, and end date is not after start date.(Side note on Groovy: notice that not all paths return a value in the validating closure, this seems to be Groovy’s take on partial functions. As I understand this, Groovy allows this type of coding to support less verbose code and the concept of partial functions is not fully supported as such.)
It is imperative to have curlies. The alarm bell starts ringing: I have imperative logic which now is a part of my domain class, yuck! Can I make code improvements and get rid of these curlies?
Note that each time I have a domain class with start and end timestamps I will probably need to write a similar closure on that domain class and I will have to write separate unit test for it, I will have to maintain the code in many places. So yes, if I could 'declare' endAfterStart validation on my domain class the code would benefit:
1: class Meeting {
2: Date start
3: Date end
4: String title
5:
6: static constraints = {
7: end nullable: false, validator: ValidationUtil.endAfterStart.curry('start')
8: }
9: }
10: }
11:
12: class ValidationUtil {
13: static def endAfterStart={String startDateFieldName, Date endDate, record ->
14: if (endDate && record."$startDateFieldName" &&
15: endDate < record."$startDateFieldName") {
16: 'endDateNotAfterStart'
17: }
18: }
19: }
Note that Groovy is clunky with functional programming terms, ‘curry’ should be really called ‘partial’. But the logic is clear, I am declaring my validation by using a function (Groovy closure) declared in a reusable (hopefully unit tested) utility class. Expected signature of validating closure is: {value, record -> . . .}
The declared reusable validation needs additional information so its signature is: {startTimestampFieldName, value, record -> . . .}
So I need to convert one signature to another in functional terms this is called partial application. Groovy calls it (incorrectly) curry.Now my domain class is purely declarative. Is it better for it? I believe so!
I think you should see a benefits of this declarative improvement! I hope to write more about curlie evil in future posts.
Next bashing of curlies
There was a recent discussion on the groovy user list about the incorrect naming of curry, so you are not alone.
ReplyDeleteIt hadn't occurred to me your use of curry for validation, thanks for that!
c programming with samples
ReplyDeleteDynamic array of structures
Nice Post!
ReplyDeleteWorried About QuickBooks Error ?Get in touch with QuickBooks expert for instant solution.Dial on QuickBooks Phone Number 1-855-652-7978.