When we say powerful features, we mean it. We all know that MVC is powerful and flexible because its given.... No need to stress that. The fact that "MVC" is in the Quicksilver USP is enough. When we use the words powerful and flexible we are truly talking about the features as well. QS offers so much more than just MVC. So... much... more.
At a high level, here are the 4(+1) core tenets that we stuck to when developing QS:
- Provide MVC
- Native Aspect Oriented Programming(AOP) capabilities
- Provide Automatic Dependency Injection
- Provide fully functioning REST support
- Provide 1-4 easily and transparently as possible meaning there should be no framework artifacts in your actual implementation code getting in your way resulting in an app that becomes extremely dependent on its framework. If we achieved this we can guarantee that your application remains HIGHLY testable which means better and more focused tests, which leads to non-fragile software, which leads to happy customers and ultimately you not having to be a nervous wreck every time a code migration is ordered.
So how did we achieve this? By using Annotations. We took a page from Java/C++ and refer to them as annotations but other popular programming languages have the same feature but named differently e.g. C# calls them Attributes. Although there are many different flavors of annotations from language to language, at the end of the day annotations will provide metadata for your class files, its members and source code. With the release of CF9, you can append this metadata by way of using the cf comments with two asterisks like so:Notice how the property is annotated via a code comment that this factory property should have a type of "path.to.some.factory". What's so cool about this? It's because an annotation is not part of implementation code - code that goes inside an actual method to be run or as a class member. Anything inside this annotation is available to the developer to introspect at runtime but actual implementation code knows nothing about it. This gives developers the ability at "compile" time to introspect source and perhaps churn out automated documentation, run debug level tests when "compilation" is running in debug mode, or in our case build a framework that gives you some really powerful features like the ones I explained above.
My intent on this entry was not to touch on every single one of those points but lets start with one - Automatic Dependency Injection. If you look at the example above we are simply telling the object that it should have a property called "factory" that has a type of "some.path.to.factory". No dependency injection going on here son, zero. That is unless you've installed Quicksilver and have either Lightwire or Coldspring installed in root. QS will by default look to see if you have Lightwire installed if not it looks for Coldspring. We decided to go with Lightwire first since it manages transient objects better than Coldspring. Ok back to the code - you've installed QS and Lightwire and now when you create your object, QS will automatically inject those dependencies for you. No XML, no bean configuration, nothing. Just the simple fact that you've annotated your property with the type is enough, QS takes care of the rest. So when you ask for an object that has property annotations attached with either the @type annotation or even inline property declaration like - property name="factory" type="some.type", you will have a proper object and its correct dependencies.
But what about for our interface based programmers that love properties that are of an interface type? Properties that doesn't have an actual concrete implementation defined as a type? Good fricking question! Here's how QS supports that with an addition annotation.
Simple type your property to the interface then use the @implementation annotation to give the actual concrete type. Your property still stays polymorphic and the world is good to you again.
So now you see the power of QS by way of annotations. QS exposes all of its features through annotations. We grew tired of having framework artifacts littered throughout code. Controllers that needed to instantiate this and extend that. XML configs spanning hundreds and hundreds of lines. With QS you get