112
Grails Worst Practices Burt Beckwith

Grails Worst Practices

Embed Size (px)

DESCRIPTION

Slides from my Greach 2014 talk

Citation preview

Page 2: Grails Worst Practices
Page 3: Grails Worst Practices

3

Title Text

Our Services

Our services start with a foundation of planning, interaction design, and visual design. We are expert builders with a passion for protoyping, architecture and development to help bring your product to life.

Page 4: Grails Worst Practices
Page 5: Grails Worst Practices

All of the topics discussed here are important, and 100% serious

Page 6: Grails Worst Practices
Page 7: Grails Worst Practices

Important Concepts:

Easier is better

Page 8: Grails Worst Practices

Finishing tasks faster is better

Important Concepts:

Page 9: Grails Worst Practices

Use the first solution that you think of

Important Concepts:

Page 10: Grails Worst Practices

Minimize the time you spend at work

Important Concepts:

Page 11: Grails Worst Practices

Get others to do your work for you

Important Concepts:

Page 12: Grails Worst Practices

Lazy is good

Important Concepts:

Page 13: Grails Worst Practices

If there's a problem, fix it if and when you have to

Important Concepts:

Page 14: Grails Worst Practices

Cover your tracks

Important Concepts:

Page 15: Grails Worst Practices

Be more like your dog

Important Concepts:

Page 16: Grails Worst Practices

http://cuteoverload.files.wordpress.com/2014/03/cute-smiling-animals-2.jpg

Page 17: Grails Worst Practices

Grails Can Be Frustrating

Page 18: Grails Worst Practices

http://www.flickr.com/photos/alexchoi/351267249/

Page 19: Grails Worst Practices

Facebook uses it, and they have over 1,000,000,000 users

Try to think like a PHP developer

Page 20: Grails Worst Practices

Sure, we can use O-O principles, but we aren't required to, so why bother?

Try to think like a PHP developer

Page 21: Grails Worst Practices

Controllers

Page 22: Grails Worst Practices

It's how scaffolding is generated, so it must be the best way

One controller per domain class

Page 23: Grails Worst Practices

Always trust generated code

Corollary:

Page 24: Grails Worst Practices

They're your interface between the client and the application

Put most of your code in controllers

Page 25: Grails Worst Practices

If Grails doesn't want us to have Groovy code in scriptlets (and to call GORM, etc.) then why is it allowed?

Do a lot of work in GSPs

Page 26: Grails Worst Practices

Eventually you'll hit the maximum GSP size limit, but that's a problem for later

Do a lot of work in GSPs

Page 27: Grails Worst Practices

Don't worry that it's difficult to test code in GSPs

Do a lot of work in GSPs

Page 28: Grails Worst Practices

“@BurtBeckwith What is the advantage of using TagLibs over writing code on the view?”

Do a lot of work in GSPs

Page 29: Grails Worst Practices

“@BurtBeckwith What is the advantage of using TagLibs over writing code on the view?”

Do a lot of work in GSPs

Page 30: Grails Worst Practices

Luckily for us, there's a cool new @grails.transaction.Transactional annotation that can be used in controllers. ¡Genial!

Transactions are important

Page 31: Grails Worst Practices

Unfortunately, @Transactional cannot be used in GSPs

Transactions are important

Page 32: Grails Worst Practices

Someone should create a JIRA enhancement request for that.

Transactions are important

Page 33: Grails Worst Practices

Someone should create a JIRA enhancement request for that.

Transactions are important

Until then, usewithTransaction

Page 34: Grails Worst Practices

If all of your business logic is in controllers, who needs services?

Don't waste time with services

Page 35: Grails Worst Practices

Idiomatic Groovy

Page 36: Grails Worst Practices

Use def everywhere. It's so easy to type.

Always use optional types

Page 37: Grails Worst Practices

If the Groovy runtime can figure out what's going on, so can your coworkers.

Always use optional types

Page 38: Grails Worst Practices

They will impress your friends who don't know Groovy

Prefer closures to methods

Page 39: Grails Worst Practices

Don't bother rewriting performance-critical code in Java or in Groovy with @CompileStatic

Write the grooviest code possible

Page 41: Grails Worst Practices

Code Reuse

Page 42: Grails Worst Practices

Copy and paste

Page 43: Grails Worst Practices

Copy and paste. A lot.

Page 44: Grails Worst Practices

If it works, keep using it

Copy and paste. A lot.

Page 45: Grails Worst Practices

When you copy and paste, you don't have to deal with taglibs, templates, helper classes, etc.

Copy and paste. A lot.

Page 46: Grails Worst Practices

If it got a lot of votes on Stack Overflow, it belongs in your code

Copy and paste. A lot.

Page 47: Grails Worst Practices

If buggy code was copied and pasted in several places, be sure to try to find and fix all of them

Copy and paste. A lot.

Page 48: Grails Worst Practices

Testing

Page 49: Grails Worst Practices

I don't get paid more if I write more code, do you?

Testing is not worth it

Page 50: Grails Worst Practices

You spend all that time writing tests, and then something changes and they fail

Testing is not worth it

Page 51: Grails Worst Practices

If you don't have tests, you can't get yelled at for breaking the build

Testing is not worth it

Page 52: Grails Worst Practices

If you must write tests, wait until the end of the project. There's always extra time for tests and documentation

Delay testing where possible

Page 53: Grails Worst Practices

If you must write tests, always use unit tests because they run the fastest.

Always write unit tests

Page 54: Grails Worst Practices

It is not at all important to test persistence with a real database

Always write unit tests – especially for persistence

Page 55: Grails Worst Practices

If that were true, then why does Grails let you unit test domain classes?

Always write unit tests – especially for persistence

Page 56: Grails Worst Practices

All they do is complain about failed builds, usually because of failed tests

Don't bother with CI servers

Page 57: Grails Worst Practices

Security

Page 58: Grails Worst Practices

Don't bother with Spring Security or Shiro, just implement it yourself. It's fun and easy!

Security is difficult

Page 59: Grails Worst Practices

Don't bother with Spring Security or Shiro, just implement it yourself. It's fun and easy!

Security is difficult

Page 60: Grails Worst Practices

Always store passwords in the database without using complicated hashing algorithms

Security is difficult

Page 61: Grails Worst Practices

It's important to be able to email users their passwords when they forget them

Security is difficult

Page 62: Grails Worst Practices

And if you get hacked, it's not like they're going to steal your money, right?

Security is difficult

Page 63: Grails Worst Practices

Store passwords in source control

Page 64: Grails Worst Practices

This is called "security by obscurity" and it always works

Store passwords in source control

Page 65: Grails Worst Practices

I doubt that it's true that there are ~10,000 Amazon S3 production credentials in GitHub:

Store passwords in source control

https://github.com/search?q=production+SECRET_ACCESS_KEY%3A+%22A&type=Code&ref=searchresults

Page 66: Grails Worst Practices

Data Access

Page 67: Grails Worst Practices

Don't bother checking hasErrors(). Let the error page handle expected user mistakes.

Always use failOnError:true

Page 68: Grails Worst Practices

The users will probably figure it out. And besides, all they ever do is complain. They're so negative.

Always use failOnError:true

Page 69: Grails Worst Practices

Exceptions aren't expensive, especially not in Groovy

Always use failOnError:true

“The Exceptional Performance of Lil' Exception”

Page 70: Grails Worst Practices

Always use failOnError:true

def thing = new Thing(params)try { thing.save(failOnError:true) // handle success case}catch (e) { // handle error case}

def thing = new Thing(params)thing.save()if (thing.hasErrors()) { // handle success case}else { // handle error case}

Page 71: Grails Worst Practices

Always use failOnError:true

def thing = new Thing(params)try { thing.save(failOnError:true) // handle success case}catch (e) { // handle error case}

def thing = new Thing(params)thing.save()if (thing.hasErrors()) { // handle success case}else { // handle error case}

Obviously better

Page 72: Grails Worst Practices

Database transactions are difficult

Page 73: Grails Worst Practices

But you've probably heard that they're important. I sure have.

Database transactions are difficult

Page 74: Grails Worst Practices

Is there even any helpful information available?

Database transactions are difficult

Page 75: Grails Worst Practices

Is there even any helpful information available?

Database transactions are difficult

http://2013.gr8conf.eu/Presentations/Grails-Transactions

Page 76: Grails Worst Practices

Speaking of convenience, have you seen GORM for REST? It's almost like giving your users direct access to your database:

import grails.rest.*

@Resource(uri='/books')class Book { String title}

GORM for REST

Page 77: Grails Worst Practices

Don't use http://grails.org/plugin/ spring-security-rest

If you do use REST ...

Page 78: Grails Worst Practices

Always use collections for one-many and many-many relationships

Page 79: Grails Worst Practices

http://www.infoq.com/presentations/GORM-Performance

Always use collections for one-many and many-many relationships

Page 80: Grails Worst Practices

Cache as much as possible

Page 81: Grails Worst Practices

Cache Everything

If a little caching is good, then a lot is great

Page 82: Grails Worst Practices

But don't overthink it – just use grails.hibernate.cache.queries=true in Config.groovy

Cache Everything

Page 83: Grails Worst Practices

Don't worry that Hibernate query cache considered harmful?appears to contradict this advice

Cache Everything

Page 84: Grails Worst Practices

It's better to make several queries that are easy to understand, and sort and filter the data in your code

Don't bother optimizing queries

Page 85: Grails Worst Practices

def getAverageAgePerPlan() {

def planAgeBarData = []

Insurer insurer = ...

insurer.plans.each { plan -> int ageTotal = 0 for (Person person : plan.customers) { ageTotal += person.age }

int avgAge = plan.customers.isEmpty() ? 0 : ageTotal / plan.customers.size()

planAgeBarData << [plan.name, avgAge] } planAgeBarData}

Page 86: Grails Worst Practices

Don't share

Page 87: Grails Worst Practices

Don't share

Don't write blog posts with information that others could use

Page 88: Grails Worst Practices

Don't share

Don't create plugins – users will only complain about bugs and missing features

Page 89: Grails Worst Practices

Don't share

Let them figure things out on their own, just like you had to.

Page 90: Grails Worst Practices

Don't report bugs (someone else will at some point)

Don't share

Page 91: Grails Worst Practices

And if you do report a bug, don't bother trying to fix it with a patch or pull request

Don't share

Page 92: Grails Worst Practices

Don't bother reading books

Page 93: Grails Worst Practices

Don't bother reading books

Page 94: Grails Worst Practices

Don't bother with the mailing lists

Page 95: Grails Worst Practices

Don't bother with the mailing lists

http://grails.org/Mailing%20lists

Page 96: Grails Worst Practices

Don't bother with the mailing lists

http://grails.org/Mailing%20lists

http://grails.1312388.n4.nabble.com/

Page 97: Grails Worst Practices

Don't bother with the mailing lists

http://grails.org/Mailing%20lists

http://grails.1312388.n4.nabble.com/

http://grails.markmail.org/search/?q=

Page 98: Grails Worst Practices

Don't bother reading release notes and "What's New" pages

Page 99: Grails Worst Practices

Don't bother reading release notes and "What's New" pages

http://grails.org/Release+Notes

What's new in Grails 2.3?

Page 100: Grails Worst Practices

Don't Follow @grailsframework

Page 101: Grails Worst Practices

It's mostly a bunch of Graeme's Instagram photos of his lunch

Don't Follow @grailsframework

Page 102: Grails Worst Practices

Some miscellaneous items:

Page 103: Grails Worst Practices

Some miscellaneous items:

Don't bother using packages, just put everything in the default package

Page 104: Grails Worst Practices

Some miscellaneous items:

Don't worry about documenting your code

Page 105: Grails Worst Practices

Some miscellaneous items:

Don't worry about writing self-documenting code

Page 106: Grails Worst Practices

Some miscellaneous items:

Prefer jar files in the lib directory to dependencies in BuildConfig.groovy

Page 107: Grails Worst Practices

Some miscellaneous items:

Prefer println to logging

Page 108: Grails Worst Practices

Some miscellaneous items:

Store whatever you want in the HTTP session, especially domain class instances and query results. Memory is inexpensive.

Page 109: Grails Worst Practices

And whatever you do ...

Page 111: Grails Worst Practices

¡Gracias!

Page 112: Grails Worst Practices

http://cuteoverload.files.wordpress.com/2014/03/cute-smiling-animals-251.jpg