Implementing Design by Contract in ColdFusion using Coldspring AOP

I have been playing around with implementing Design by Contract in ColdFusion using Coldspring's AOP functionality.

ColdContract is a Coldspring AOP Advice which allows Design by Contract assertions to be added to ColdFusion components and for those assertions to be executed during program execution.

Design by Contract assertions are a mechanism for defining the specification of software components, in such a way as to allow the implementation of the specification to be tested in-line with program execution. This provides a difference (and arguably quicker) method of implementing TDD to Unit Testing.

Assertions are added to components using meta data attributes as shown below:

  1. <!---

  2. /**
  3. *
  4. * Copyright (c) 2008 David Beale (http://www.BealeARTS.co.uk)
  5. *
  6. **/
  7. --->
  8.  
  9. <cfcomponent displayname="Stack"
  10. hint="A FILO Stack example showing the use of ColdContract assertions. Stack items cannot be objects (Components)."
  11. invariants="this.getNumberOfItems() gte 0, this.getNumberOfItems() eq arrayLen(variables.stack)"
  12. >
  13.  
  14. <!--- INIT --->
  15.  
  16. <cffunction name="init"
  17. hint="Constructor"
  18. access="public"
  19. returnType="Stack"
  20. output="false"
  21. >
  22. <cfreturn this />
  23. </cffunction>
  24.  
  25.  
  26. <!--- PUBLIC --->
  27.  
  28. <cffunction name="push"
  29. hint="Push an item onto the stack"
  30. access="public"
  31. returnType="void"
  32. output="false"
  33. preconditions="not isObject(arguments.item)"
  34. postconditions="this.getNumberOfItems() eq oldThis.getNumberOfItems() + 1"
  35. >
  36. <cfargument name="item" hint="Item to add" type="any" required="true" />
  37.  
  38. <cfset arrayAppend(variables.stack, arguments.item) />
  39. <cfset variables.stackIndex++ />
  40.  
  41. </cffunction>
  42.  
  43.  
  44. <cffunction name="pop"
  45. hint="Pop an item off the stack"
  46. access="public"
  47. returnType="any"
  48. output="false"
  49. preconditions="this.getNumberOfItems() gt 0"
  50. postconditions="this.getNumberOfItems() eq oldThis.getNumberOfItems() - 1, not isObject(cfreturn)"
  51. >
  52.  
  53. <!--- LOCALS --->
  54. <cfset item = '' />
  55.  
  56. <cfset item = variables.stack[variables.stackIndex] />
  57. <cfset arrayDeleteAt(variables.stack, variables.stackIndex) />
  58. <cfset variables.stackIndex-- />
  59.  
  60. <cfreturn item />
  61. </cffunction>
  62.  
  63.  
  64. <cffunction name="getNumberOfItems"
  65. hint="Get the number of items on the stack"
  66. access="public"
  67. returnType="numeric"
  68. output="false"
  69. >
  70. <cfreturn arrayLen(variables.stack) />
  71. </cffunction>
  72.  
  73.  
  74. <!--- PRIVATE --->
  75.  
  76. <cfset variables.stack = arrayNew(1) />
  77.  
  78. <cfset variables.stackIndex = 0 />
  79.  
  80. </cfcomponent>

3 Responses to “Implementing Design by Contract in ColdFusion using Coldspring AOP”

  1. radekg Says:

    I have the feeling I have seen it somewhere…
    http://riait.co.uk/2008/06/25/pre-and-postconditions-for-cfml-functions/

  2. Kurt Bonnet Says:

    Very cool approach. Thanks for blogging this!

  3. David Beale Says:

    @radekg

    Wow! What can I say, great minds think alike :-)


Leave a Reply

Copyright © 2005, David Beale

  • Valid XHTML 1.0!
  • Valid CSS
  • Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0