//
you're reading...
General

Convention over configuration

At work, we’ve been making a lot of use of EmberJS; a Javascript MVC/SPA library that has really started to grow on me.

Part of the design philosophy behind it, like Ruby-on-Rails and ASP.NET MVC, is that rather than writing a configuration for things you just have to follow the conventions and things are “magically” picked up.

For example; when we add a new route and controller to our project it gets named App.NewsRoute and App.NewsController.  All I have to do is make sure the JavaScript is included and it’ll automatically get used when the user navigates to our /news route.  Similarly, we also don’t have to provide a custom route or controller.  If the default implementation of a route is fine then we don’t have to create the App.NewsRoute at all, It Just Works.

Sometimes this can be extremely frustrating, Ember is still a pre-release product and the documentation is rapidly evolving.  Making it difficult to know where to put things.  The most frustrating experience we had was getting an error from Ember telling us to add a serializer alias, but not being able to find out how to do this.

But, I digress.   This blog post is actually about…reporting!

Having recently spent the last 3-4 weeks working heavily in this environment (over 200 commits between three developers in this time frame) I’ve moved back to my reporting project and was quickly met with a deluge of thoughts along the lines of: “ugh, I gotta do this manually?”

There are some things I’ve already done to make it easier to load up and work with reports.  But, for the most part its been a manual process.  I need to make calls to this static method or to that extension method in the report script.

Here is where my thoughts about convention over configuration began to enter my head.

“What if, instead of having to write all the code to not only set up a custom control but having to write the marshaling code to get it to execute on the right thread, I could just do it ‘auto-magically?'”

“Why do I need to write method calls to set up the custom chart palette on each report where a chart is used?  Why can’t I just have some other code find it for me?”

And thus, was born Conventions.

Conventions allow me to do several things without having to actually write manual code in each report to do it!

The one I’m happiest with, is that I now have the ability to write a <name>Setup function to setup the contents of my custom controls AND it automatically gets called on the right thread! I can’t stress just how important that second part is, if you’re not careful you’ll wind up with the object only half-constructed and things behaving incredibly weird.

public void MyCustomControlSetup(BulletGraph graph)
{
  /* This function gets called during report setup
     passing in the instance of my custom control.  It
     is automatically marshaled to the correct thread
     for Windows Forms.
  */
}

The snippet above demonstrates all I have to do to get my code called at report runtime correctly. The name of the method just needs to be the name of the ActiveReports CustomControl followed by Setup. It also needs to accept an instance of the same type as the CustomControl is set to use.

If you’ve used the scripting feature in ActiveReports, you’re already partially familiar with the convention approach. When handling events the method in your code just needs to be named a certain thing and the event will automatically be handled. This just takes it to another level.

Unfortunately, there isn’t a way of making it work with without some input from the script developer. What stops that from working is the lack of access to the object that is the instance of the compiled script. However, all I need to do to access it is make available an extension method that accepts the code:

public void ActiveReport_ReportStart()
{
  rpt.RegisterScript(this);
}

This one line of code gives me access to the report (rpt) and the object that contains the code methods/properties (this).

A few other things I’ve done with Conventions so far:

  • Introduce additional “events” that allow me to distinguish from getting all my data, doing data binding, and ‘post’ data-bind event.
  • Automatically hook up custom chart palettes based on what report is loaded and being able to “fall-back” to other palettes defined for the containing report or at the repository level. All just by placing a specially named file containing the palette next to the report.
Advertisements

About James

I am a Senior Developer/Consultant for InfoPlanIT, LLC. I previously spent over 7 years as a Product Manager for what eventually became ComponentOne, a division of GrapeCity. While there, I helped to create ActiveReports 7, GrapeCity ActiveAnalysis, and Data Dynamics Reports.

Discussion

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archive

%d bloggers like this: