I recently joined a company that makes use of Mach-II in a few applications. Some of them were created as the developers were learning the framework and employ some obvious un-best practices. The team is made up of people from various skill levels, but I have noticed that about half of the team just absolutely cringes when they hear “Mach-II”. They talk about how difficult it is to troubleshoot and how it is next to impossible to follow application flow. I was very surprised to hear that response, because I think one of the big benefits of using Mach-II is that I can look at a config XML and read the story of my application. I will touch on this in more detail in a bit.
So the other day I had my first experience digging in deeply into one of they apps to solve a problem… and it took me forever to figure out where the hell anything was. I started on the default home event, which only had a filter that announced other events, that had listeners that announced other events and so on until I was *EIGHT* events deep. In each one of these announcements, I had to go find the listener/filter, look into the methods, and search for where I might be going next. It suddenly became overtly clear why the other developers hate Mach-II.
Now, back to why my config files tell a story… first of all, I can’t think of many cases where an app needs to announce 8 events before it gets to a destination. However, troubleshooting this would have been so much simpler if only the developer had been clear in the XML using event-mappings. As a rule, if I ever alter the flow of my application from within a filter/listener, I always have an event-mapping that shows this in my config. That way I can quickly skim the XML and know what possible exits I have. In most cases, it should be pretty obvious where you are going based on that alone, and you don’t even need to open the CFCs to figure it out. Although I certainly do use event-mapping for aliases, more often than not they will look like this:
<event-mapping event="SomeEvent" mapping="SomeEvent" />
It serves no actual functinal purpose other acting as a means to document the flow. Does anyone else use the practice? How do you keep the application flow obvious in your configuration files?
I was talking to Aaron Lynch about this (who uses the same practice) and from that conversation I decided I would open this up for conversation. What I would love to see is some type of optional setting in Mach-II that would enforce this so that all developer on a team had to use this methodology. Maybe something along the lines where when an event is announced from within a CFC and it hasn’t been mapped in the XML it would barf up an exception?
I have no doubt that some people will hate this idea. However, in the bigger picture I would like to see less people hating frameworks, and if we can make things more clear from a troubleshooting/maintanence perspective, I think that there would be less FUD!
Any thoughts on this?
EDIT: Comments were not carried over from my previous blog host. I want to make sure I include comments by Peter Farrell and others. Pasting below:
Before diving into event-mappings, everybody should be using the MachIILogger which shows the what happened during the request at the bottom of the request. You can just read what happened in that — seeing who announced what. Combine that with custom log messages in filters / plugins / listeners — you can really see what is going on.
The social issue on this is a lot of people think that using a framework means you’re going to write quality software. However, the point is that no matter what we do — people can write horrible software and easily abuse the intent of the framework. Using a framework != you’re going to write something great. The framework is just helping automate some of the kludge work and provide a path to walk (meaning you can walk on the asphalt path, wander onto the grass sometimes or get lost in the forest if you not careful).
Another problem is that people new the framework tend to break absolutely everything into an event-handler because they think they are optimizing for maintenance up-front. This is a bad way of doing this. Another thing is people use event-handlers to encapsulate blocks of XML. Subroutines were introduced to handle this situation and when employed they can reduce massive event announcement chains. Subroutines are great for things that cannot stand on their own (think a widget) and are used in many places through out the application (think search form that uses query data to create drop downs with user data).
I always use the rule of “Favor announcing from XML or if you must announce from a filter or listener, be sure to use an event-mapping”. There are times where the event name is dynamic, but in most situations you don’t need this.
So maybe there is merit to adding a runtime “warning” that you’re not using event-mappings. I know that somebody will say that they use event names and only know at runtime so I’ll be up front and say that is an exception to the rule (however you can programmatically create event-mappings using the event-context too).
As Peter points out, the logger helps a lot, and maybe subroutines can alleviate some of this.
I’m personally not in favor of the framework enforcing anything along these lines. I understand the pain, but that’s a REALLY slippery slope and I’d much rather have good examples and educate people in best practices (and this is a great one to add to the wiki) as opposed to the framework explicitly enforcing anything.
Maybe someone wants to build a tool that would make a visual map of the application from the XML? Only half-joking–might be cool.
posted 625 days ago