Saturday, May 24, 2014

What's Groovy about Grails!

This post is a written version of my short presentation about Groovy and Grails. The advantage is that I can link to some external resources to give you more information to pursue. I expect that you have some computer programming experience, and you know what variables, statements, functions, and subroutines are. Many folks in my audience have a structured or procedural programming background so I am going to argue in favor of the object-oriented concepts that Grails depends on.


Why Groovy and Grails?


Grails is a framework for building web applications, especially those with a database behind them. Grails significantly reduces the amount of work necessary to move information from the user to the database and back again, allowing you to focus on implementing the business rules to manage that data. Groovy is the language that Grails relies to simplify the amount of programming necessary.

Grails is popular underneath many applications. For example it is a required component of the Ellucian Banner XE product line where it replaces Oracle Forms and PL/SQL as the application framework.

Ellucian's reasoning for migrating to Grails clearly applies to similar scenarios in other organizations: PL/SQL is a structured, procedural programming language locked into the database. Grails is an open environment, Groovy is a robust object-oriented programming language, and the whole package is extensible with new technologies such as AJAX and client-side development using Backbone or Ember.

Grails


Grails provides three important benefits: Groovy is a dynamic language to use that simplifies managing data. A paradigm of "Convention over configuration" simplifies implementing the application in the Grails framework. And the model-view-controller (plus service) paradigm ensures the separation of concerns through modularity of the application. In my presentation I spend more time talking about MVC+S, but you can follow the link to see that part.


Pivotal is the company behind Grails and has built it on top of several standard components: the Java virtual environment, Hibernate data access, the Spring MVC framework, i18n localization, and the log4j logging framework. You really do not need to learn the details of these frameworks, Grails isolates you from them as much as possible.

Grails builds on top of the Spring MVC model with "convention over configuration." Spring is another product from Pivotal. There are minimal configuration files for a Grails application. You are expected to name components and their elements correctly, and place them into the right locations in the project. Grails will read the components to configure the application. For example, Grails will match a view to a controller because they share the same name.

Groovy


Groovy is a member of the C family of languages and shares the similar syntax. Groovy is compiled into Java byte-code and must operate within the constraints of the Java Virtual Machine. But in contrast to languages like Java, Groovy is dynamic and not strongly typed. A dynamic language is easy to use and can be much faster for building applications, but without strong typing it does open the door for variable type mismatches that only show up at runtime.

Object-oriented Programming


Although not strongly typed, Groovy is very-much an object-oriented language. Object-oriented environments provide stronger support for the fundamental principles of software design, especially Robert Martin's First Five Principles: SOLID (Martin). The Single Responsibility Principle, Open for Substitution and Closed for Modification, the Liskov Substitution Principle, Independent Interfaces, and Dependency Inversion have all been identified as ensuring success at building reliable, adaptable, and maintainable software: RAM.

In some ways Groovy is a superset of Java, and the compiler can actually compile Java code alongside of Groovy statements. Groovy programs can use all Java library classes, including all of the classes in the core Java API. Remember though that Groovy is not strongly typed, and they compiler will not always make sure that you are passing the right type of objects in the method calls to instances of library classes.

Classes


All computer programming is about organization. Structure programming and procedural programming both rely heavily on functions and shared, global data. The problem is when a data structure or process is changed there is no indication of what other data and functions in the application may be affected. In the C language we would have data and functions in completely isolated from each other in separate files, and brought together when the program is built:

double accountBalance;

void deposit(double amount) {

@tab;accountBalance = accountBalance + amount;
}

void printBalance() {

@tab;printf("The account balance is %d", accountBalance);
}

If you don't know C then you didn't catch that the printBalance method will crash, because it thinks that accountBalance is an integer when it tries to format it with %d. But at some point the variable was changed to a double and we missed updating the function. We solved some of this problem in the real world with scoping: we kept related data and functions together in separate modules and made sure functions external to those modules did not access data directly. Then if we changed something, we knew where to look for dependent functions:

double accountBalance;

void deposit(double amount) {

@tab;accountBalance = accountBalance + amount;
}

void printBalance() {

@tab;printf("The account balance is %f", accountBalance);
}

The big advantage of object-oriented languages like Groovy is the binding of data and processes together in classes. A class is a definition of how data and processes work together. A class is a template, it is used to create instances: individual objects that all behave according to the class definition. This Java class formalizes what we tried to accomplish in our structured/procedural programming environments:

public class Account {

@tab;private double balance;

@tab;public void deposit(double amount) {

@tab;@tab;balance = balance + amount;
@tab;}

@tab;public void printBalance() {

@tab;@tab;System.out.println("The account balance is " + balance);
@tab;}
}

Classes are about more than just organization: a class defines a type of data and the processes that work with it. The class can be used to construct as many instances of this type as we want to use. Each instance works exactly the same as all the others, but has its own values for the data.
In object-oriented programming the data in a class is referred to as a field, and processes that use the data are called methods. So when a field or a method needs to be changed the other fields and methods that many be affected are most likely bundled along with it. The compiler can help with this by refusing to compile client-code that accesses private information within a class instance. The fields of a class are almost always made private so the compiler can protect them. Most methods are public so client-code is allowed to use them. Some methods may be used behind the scenes to help complete a process, and they are often kept private.

Let's apply a principle: Bob Martin writes about the Single Responsibility Principle with classes, that each class should be about one responsibility. When the class is about one thing then it is cohesive: all of the fields and the methods are closely related to each other. So classes organize the program into small modules, each doing their own job. When the program is organized we have a much better expectation that it will perform the way it was intended: RAM.

The idea of single responsibility applies to much more than just classes. An application should be about one thing, a module about one thing, of course classes should be about one thing, but also methods should be about one thing, and even statements should be about a single task!

Class Constructors


A constructor is a special method in a class used to initialize object instances when they are created. The name of a constructor method is always the same as the name of the class. Traditionally in OOP we added constructors with different parameters to initialize instances in different ways. It turns out that was a bad idea because the client-code using a class becomes very dependent on those constructors. And what happens if the client-code actually needs to create an instance of a class that was defined after the client-code was written? It would not know about the appropriate constructor!

In languages like C++, Java, and C# this problem is solved by always initializing new objects with a zero-argument constructor, and then setting each one of the properties independently. While it does reduce dependency, it is cumbersome to make a separate call to initialize each property:

def customer1 = new Customer();

customer1.setName('John Smith');
customer1.setAddress('123 Main Street');

Groovy solves this problem by providing a default constructor that accepts a map of values: name=value pairs where each name is a property name and the value is used to initialize it. A single constructor call can initialize all the properties, no matter what the property names actually are:

def customer1 = new Customer( { name: 'John Smith', address: '123 Main Street' })

So the map is contained in the braces and we expect the class to have a name and address property. The braces are actually optional and many programmers do not provide them. Any properties in the class not provided are left at their initial value. And any properties provided that do not exist in the class are ignored.

Properties


Groovy heavily leverages the idea of a property. We already decided that fields in a class should be kept private so we can control access to them through methods. Usually two methods are put in front of a field, a getter to retrieve data and a setter to change data. Sometimes only a getter will be used, making the data read-only. Consider our bank account: we want client-code to be able to read the balance, but we do not want client-code to arbitrarily set a balance. Yet an interest rate we want to be able to both read and change:

public class CheckingAccount {

@tab;private double balance;
@tab;private double interestRate;

@tab;public double getBalance() {

@tab;@tab;return balance;
@tab;}

@tab;public double getInterestRate() {

@tab;@tab;return interestRate;
@tab;}

@tab;public void setInterestRate(double interestRate) {

@tab;@tab;this.interestRate = interestRate;
@tab;}
}


There are many advantages to controlling client-code access. If the field has to change internally it can still be exposed without any change to the client-code: a balance field that changes from a Double to a BigDecimal can be managed behind the getter and setter. Additional functionality like logging can be added without changing the client-code: we can log ever user who looks at the balance in an account. And security can be added without depending on the client-code: we can add logic to restrict who can look at the balance in an account right at the level of the account instead of adding that security everywhere client-code checks the balance.

public class CheckingAccount {

@tab;private BigDecimal balance;
@tab;private BigDecimal interestRate;

@tab;public double getBalance() {

@tab;@tab;return balance.doubleValue();
@tab;}

@tab;public double getInterestRate() {

@tab;@tab;return interestRate.doubleValue();
@tab;}

@tab;public void setInterestRate(double interestRate) {

@tab;@tab;this.interestRate = new BigDecimal(interestRate);
@tab;}
}


It makes sense to protect every field with getters and setters, even the ones that currently do not need it. If the client-code is restricted to them then we always have the place to add new functionality later. Even inside the methods of a class you should always use the getters and setters for a field to insure that if new functionality is added later it is not accidentally bypassed internally. 

So a field is not a property. The ability to read and possibly write data through the getters and setters defines a property. The property name does not even have to match the field name; the property name comes from the word after get or set. Groovy removes any requirement to make calls to the getter and setter methods. When Groovy reads them it creates a virtual property, which we can use directly to retrieve the value or assign a new value to it (assuming the setter method is defined). This Groovy example sets and then prints the interest rate:

def account1 = new CheckingAccount()
account1.interestRate = 0.03
println "The interest rate is set to ${account1.interestRate}"


Groovy does not require semicolons at the end of each line, and this example incorporates Groovy strings with expression substitution. ${account1.interestRate} is replaced with the value of the interestRate property in the object account1. The content of the braces is not a variable, it is any expression that may be evaluated and the result used in the string.

Closures


Consider the following loop that prints out each element of a collection:

def title = 'Finals'
def scores = [ 95, 87, 82, 78, 91, 89 ]

for (def i = 0; i < scores.size(); i++) {

@tab;println "${title} no. ${i}: ${scores[i]}"
}


Groovy includes a powerful dynamic feature: closures. A closure is very much a function definition, but it can be defined within another function and its scope includes all the variables defined in the enclosing function. A closures are often passed to other functions as a callback. Groovy programmers replace traditional loops with calls to the each method on collections, and the each method takes a closure which it calls for each element in the collection.

def title = 'Finals'
def scores = [ 95, 87, 82, 78, 91, 89 ]

scores.each { score, index ->

@tab;println "${title} no. ${index}: ${score}"
}

The difference is that the code on line eleven is not a loop, it is a call to the method each in the object scores. The method is passed an anonymous closure in braces. The closure has two defined arguments, score, and index. And, on line thirteen it also has access to the variable title in the enclosing code!

Just because I am obsessive and compulsive and I need to be complete in my definitions: an anonymous function is formally referred to as a lambda function, an implementation of the idea of a lambda expression used in calculus. A lambda expression consists of variable declarations and an expression that uses those variables to produce a result. That exactly matches the closure syntax we just defined!

Really Late-Binding


Polymorphism in object-oriented programming takes place when a message is sent to an object, and the object decides how it is going to respond. Almost always the message takes the form of a call to a method or a reference to a property. The idea is that the client-code using the object has an abstract idea of what an object should do, but specific object types may have their own behavior.

Consider a banking system: checking accounts and savings accounts both have similar behavior but but handle the specifics differently. The client-code can "decouple" itself from the specifics of different accounts. It just manages "accounts" without worrying about a specific type of account. It knows that if it asks to have the interest applied to an "account," then whatever that account object really is will take care of itself. Decoupling is critical, it allows us to add new types of bank accounts in the future without having to change the client-code that uses "accounts."

def accounts = [ new CheckingAccount(), new SavingsAccount(), new InvestmentAccount() ]
accounts.each { account ->

@tab;account.applyInterest()
}

Groovy delays checking for specific methods and properties until the program is running, only when a method or property is requested in an object does it look for it. Polymorphic behavior in Groovy does not depend on constructs like inheritance from one class to another. Regardless of the type of the target object, if it has the method or property everything will work.

The Groovy form of polymorphism we call this duck typing: "When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck" (Heim). It may not really have any relationship to a duck, but for my purposes treating it like a duck works just fine. The advantage in Groovy is the dynamic relationship: as long as an object has the functionality I need I can use it, no matter where it came from.

But, there is a disadvantage to duck-typing: the object we are trying to use must support the functionality that we need.  It is up to us to make sure we use an object that supports that functionality where it is needed, the Groovy compiler is not going to notice if we make a mistake.

Meta-Programming (Prototypal Programming)


I could argue that the most important feature of Groovy is its support of the Prototype Design Pattern (Gamma). Every object created in Groovy has an instance of a prototype class attached to it, in Groovy it is called a metaclass.

So when a method or property is requested, the sequence of events is to first check the object to see if it has the property or method. If it doesn't then the metaclass instance is checked. And if the metaclass instance doesn't have it, then ask the metaclass instance to provide it. Asking the metaclass is the key to immense power: the meta class may not have the specific resource requested but it can map the request to a pattern, do some work, and provide a response.



As an example, the model classes that are used to map to database tables rely on these "phantom" methods. We will design a Customer class that maps to a Customer table below in this article. The class does not inherit from anything, and it has no methods to look up customers. Yet it will still respond to a findCustomer method call that takes an index and looks for it in a customerId column. How does it work? The metaclass instance that Grails attaches to our Customer sees a request for a method that begins with the word find and follows the pattern findSomething, so it translates the request into a database search operation that locates the customer!

About Reflection


So all of the dynamic features of Groovy are handled at runtime. The Java Virtual Machine provides reflection, a way that the program can examine any object an runtime and find out its class, properties, and methods. When a property or method is used, Groovy uses reflection to locate the property or method dynamically and use it. In the Groovy environment we feel that the advantage of using reflection for duck-typing at runtime outweighs the burden of having to take the time to locate the properties and methods.

A Deeper Dive into Grails


What makes Grails development so simple is that almost all components rely on map collections. When a form is submitted from a user in a browser the fields all arrive as a map of name=value pairs. A model object can be created just by passing that map to the class constructor. When a database query is made each row returned is a map, which again simplifies creating the model object.

Controller


The controller classes are the entry points to the Grails application, and their closures/methods define actions. The naming convention is to use SomethingController, where "something" is a descriptive name of what the controller does.

The framework uses a Representational State Transfer (REST) model. The format of a URL is http://server/application/controller/action. The server is a normal reference to a computer on the network, either a name or an address. The application is the name that tells the web service which application to route the request to. The application reads the controller class to send the request to, and the action identifies which closure or method to invoke.

The actions in a controller may be either named closures (assigned to a field), or a method. The general action of a closure is to initiate some process corresponding to the action and then decide what the user sees next. By default Grails looks to a view that has the same controller and action name as the request.

Services


Combining the selection of a process and the routing of the view into a controller really violates the Single Responsibility Principle, so Grails separates the routing into the controller and the process into a service class. Similar to the controller classes, the naming convention is SomethingService.

Controller classes are all singletons. That means that the methods in a service need to be re-entrant as multiple requests to the web site could enter the singleton simultaneously. Generally we do not have to do anything other than avoid using instance data: make everything a local variable inside the methods and there will not be any conflicts.

So if the service is a singleton, how does the model see it? Through a feature called dependency injection, which is an implementation of the "D" Bob Martin's First Principles: Dependency Inversion. We only have to do one thing in the controller class: declare a field with the same name as the service class, except with a lower-case initial character of course. Grails makes sure that field has a reference to the singleton instance when the controller runs!

class CustomerService {
@tab;Customer search(customerId) {
@tab;@tab;return Customer.findCustomer(customerId) @tab;} }

class CustomerController {
@tab;def customerService
@tab;def showCustomer() {
@tab;@tab;render { model: [ customer: customerService.search(params.customerId) ] } @tab;} }

Pay attention to the hookup here. The form fields arrive in the controller as properties of the params map, in this case the one property we expect is customerId. We ask to render, so the default Groovy Server Page is showCustomer.gsp. We pass that page a model (in the map passed to render). The model contains one map pair, customer that is assigned the result of asking the service to search for the customer. The service is injected into the controller because the customerService field has the same name as the CustomerService class.

In other languages I would have to do a lot of the setup and finding parameter values myself. Grails makes it simple and I can tie everything together in just a few lines!

Models


Model classes are almost always maps from a Groovy object to a database table. This is handled with a Grails Object Relational Mapping (GORM) layer on top of the Hibernate data-access layer. Grails simplifies the work with a metaclass instance behind every model object. Quite literally the most that we need to do is define a class and list the properties it should have. If the names and data types line up with the table in the database, everything will work:

class Customer {
@tab;String customerName @tab;String address @tab;String city @tab;String stateOrProvince @tab;String postalCode }

Of course we usually want to be much more precise. The property names in our class may not be an exact match for the column names in the table. A common issue is that Grails automatically adds an id property to the model class that is the primary key in the database, but we usually want to have more descriptive names in the tables. Notice that we did not add an id field in the definition but it is really there, Grails takes care of it.

The model class has constructs to define what that mapping is, in this case we are interested in the mapping where among other things property names can be mapped to table columns. All of the configuration constructs in a model class are closures with "phantom" methods. The metaclass behind the controller will take care of these method calls for us. In this case we are invoking an id method cal and passing it a map that defines the mapping to a specific table column. The metaclass translates that into a configuration that maps the id property to the desired column:

static mapping = { @tab;id column: customerId }

Of course most relational databases have foreign key constraints between some of the tables; a sales order always has a reference back to the id of the customer it belongs to. Grails supports these with additional closures that define one-to-one, one-to-many, and many-to-many relationships between the tables. Of course getting these correct is important, if they are off from what the database really does inserts, updates, and deletes suddenly do not work right. But when they are defined correctly Grails (and GORM) takes care of a lot of stuff for us: deleting a sales order will automatically cascade into a delete of all the items that make up the sale.

Grails supports two design models: domain-driven and database-driven. In the domain-driven model the database is created from the model class definitions, right down to the foreign key constraints. In a database-driven design the model classes must be crafted to precisely match an existing schema.

Views


And finally we get to the views. Grails views are usually defined as Groovy Server Pages, which are HTML documents with some Groovy extensions. Java Server Pages can also be used for views. The Groovy stuff (or Java stuff) is processed before the page is sent back to the user; what the user sees is strictly HTML

The controller will select the view that should be rendered, and it will pass the model information required to the view. By default the controller selects a Groovy Server Page that has the same name as the action, in the directory with the name of the controller. In most cases, the view should simply take that information and format it for the user; the view is strictly in the "presentation layer" of the application. Moving data as a map comes into play again here: the name=value pairs in the map can line up with the names of the fields in an HTML form making it very simple to quickly initialize those form fields.

It is possible that a view could go back to the model objects looking for more information, or even embed some support for the business rules within the presentation. Most of the time doing so violates the single responsibility model, and most likely is stepping on the responsibility of a controller. Pay attention to situations like this, they always lead to brittle application code.

Beyond Grails


This article is an overview of what Grails has to offer, and an argument for why object-oriented programming helps us build better software in business environments. Once you get into Grails there are many subtle things that we need to master: the intricacies of creating model relationships, using i18n to provide localized versions of an application, and so on.

Where do we go from here? Well, there are a lot of other technologies out there that comfortably plug into the Grails environment. You may want to start with the Grails plugins at https://grails.org/plugins/. Many of these plugins simplify some of the things that you may want to do in a Grails application.

There are also some technologies that are technically outside of the Grails environment that you may want to incorporate into your application. AJAX is a technology that allows client-side JavaScript to communicate with the Grails server without changing the page that the user is viewing. Without changing pages all the time the application will function more like a desktop program.

In order to manage the page using JavaScript you may want to look at the jQuery library. And if the client-side scripting is getting complex then turn to Backbone or Ember, MVC frameworks that run on the client.


References

See the references page.

3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. We will be transitioning to Banner XE at work sometime in the future, so I appreciate this overview of Grails.

    This presentation from UNM with Banner table examples is also quite useful.

    http://techdays.unm.edu/archive-2014/Groovy-and-Grails.pptx

    ReplyDelete
  3. clients needed progressively and JAVA was there yet it had some significant limitations(computers where slower in those days and JAVA was truly outlined in those days to work with applications) it was recently not a fun encounter in the event that you can streak back in time you will ran destinations that would crash on you or that just took perpetually to accomplish something locally (i think there are some administration destinations that still are running that way ;)
    Java

    ReplyDelete