
This is part 3 of a series of posts on using the MVC design pattern as inspiration for FileMaker design.
One of the other things I really like about some of the MVC frameworks I have seen, is the use of a design pattern called a "Front Controller". A Front Controller serves as a single point of entry to the flow of the code through the system. All the user actions are captured by the Front Controller. The Front Controller uses a series of conditional branches to hand off to the correct Action controller, which then may or may not interact with the model. I think it is called a Front Controller because it conceptually "in front" of everything else. This flow chart lays out the basic idea.

You have probably noticed that many php web sites always "stay" on the index.php page. No matter where you go in the web site, index.php "stays" in the URL. In that case the index.php page is the Front Controller. The stuff that comes after the index.php are the parameters that are passed to the Front Controller. Those parameters "tell" the Front Controller what it should do. Recently there has been push to hide the index.php part of the URL on many sites by using URL re-writing, but it is still there behind the scenes. This very website uses this technique.
One of the advantages to this is that you immediately know where the "head" of the code is. Everything starts with the Front Controller. The Front Controller is responsible for managing the flow of the code. It gives you direction to move in. It serves a similar purpose to the "anchor-buoy" model that many people use for managing the graph.
When I learned about this I immediately thought, "hmm, I wonder if this could work for FileMaker". We can certainly create If-Then conditional script steps to manage the flow. We can also pass parameters to that script. So we can do it. The next question is, "does it help?"
To answer that question, I have started using it my latest projects. So far I like it. When coupled with the general folder structure I outlined in part 2, it really does seem to help imply a direction that code takes as it flows through a system.
Here is the flow of my FM Scripts using a Front Controller.

As you can see I have placed a "Button Click, Commit Record" script above the Front Controller (maybe "Front" is the wrong word now). I have found this to be practical, because sometimes I need to do some stuff on Button Click, like commit a record. So all of my buttons are set to run this script (if they need to commit a record first). The script commits the current record and then passes the parameters on to the Front Controller, which branches to the right action controllers accordingly.
One interesting way to think about this Button Script is that it is a "Child" of the Front Controller. It inherits all of the behavior of the Front Controller but then adds it own, like Committing the record first. It extends the Front Controller. If you needed needed a button Controller that didn't commit the record you could create one for that purpose as well.
There is no question that using this method takes a little to longer to use because you are having to create a branching section of the front controller for every action. But there are other benefits that fall out of this pattern that make up for it. Here are just a few.
If all of your user actions pass through a small number of scripts or a single script, then it becomes trivial to add things like valid login checks, and logging of actions. You simply place the code in the front controller. If for example a user has incorrectly logged in to the system, your front controller can check for this and boot the user if necessary.
You can quickly mock up all actions your system will need to make during development. You can write "stubs" or little place holder script steps in your front controller to help you flesh out the design of a system. Every Branch in the front controller becomes a "feature" that you need to complete.
The Front Controller becomes excellent documentation. The flow of the code is very clear for anybody who cares to read it. It is not buried across many disconnected scripts.
I should also point out that in a very complex system with many modules it would be perfectly ok to have a Module Controller that encapsulated the branching of each module. In that case the Flow would go Front Controller -> Module Controller -> Action Controller -> Model.
One thing that seems to become clear for me over the course of this experiment, is that the strict use of the term MVC will prove problematic. We need to come up with a more FM centered vocabulary for this concept. Ibrahim made this comment on the very first post I made on the topic. Other people like Geoff Coffey have made great comments to me back channel about the MVC concept and were it falls apart in relation to FileMaker.
So please make suggestions on Names for this Design Pattern as it applies to FM scripts or FM as whole. I have been kicking around names like "Controller Script" or "Flow Controller Script".
I will get to writing up a post on Layouts and how they fit in here, but to be honest I am not clear on it yet--beyond the obvious fact that they are part of the view.
Comments
Abstracting the Front Controller
Hi Todd,
Thanks for posting this. It has been a great discussion. I've had this bookmarked for a while and finally had a chance to read through it all.
We have used a "front controller" for quite some time but haven't really adopted the whole MVC methodology. At first we were happy with the controller script as it gave us a single point of entry, but soon grew tired of always adding the ifs and else ifs and branches everywhere. So we dreamt of a more parameter driven controller but came unstuck as there is no 'perform script by calculation' script step to help us out. The zippscript plugin provided the solution as it can call a script by name and that name can be dynamically constructed. We now pass in parameters such as source table, destination table, current record id, action and others I can't remember and have the controller script call whatever subscript is required. The controller script is very lightweight now and is nearly totally parameter driven. All we have to do is ensure the subscripts are there to run and pass in the action we are expecting as a parameter.
Thanks for the great discussion.
Regards
Andrew
Not sold on script triggers
Hello Andrew,
Thanks for your comments!
I have tried script triggers for this... but I couldn't live with the fragility it introduced. If you change the name of your script you need to go back through all the starting points and change them. If you use the branching technique you don't have this problem at all.
I see the front controller as an abstraction layer between the interface and the functionality. If you place a script name in a parameter on button you have tightly bound that button to the name of the script. I don't like this. I want to use the Front Controller to capture what the user requested and then decide what script to call to carry out the users request. This is less tightly coupled.
You also open yourself up to hacking. Since now somebody can run ANY script in your system, by passing the right parameters to your controller. With branching only, the scripts you want to run can be run as part of your controller mechanism.
In every other implementation of a Front Controller I have every seen, the action controller scripts MUST be registered. Think about the havoc this would cause if a PHP solution allowed you to run ANY php script in the system if you had the name of the php script. That would be very bad. Maybe this doesn't matter in most FileMaker solutions, but we have begun locking every solution down super tight. We are trying to make it extremely difficult for any one to use solutions we have built without our consent.
I really don't mind the Ifs. I think of it as "registering" my scripts. It really doesn't take that long to setup.
It also gives me some pretty useful documentation. Every major function in the system is right there to see. I also use it to document what is NOT done yet. I can put the branches in place for functions that aren't complete yet, maybe with simple "Not Done Yet" messages.
Thanks again for you comments
Re: Not sold on script triggers
Hi Todd,
Thanks for responding... all good points.
The fragility is certainly a flaw. Things have come undone with our controller when subscript names have been changed in the past but we are pretty strict with our naming conventions now and introduced context controllers that may or may not use zippscript to provide more flexibility. So it could catch someone else working on our solution(s) in the future or even new staff and limits our ability to go in and change script names without carefully considering any impacts.
Not so good with analysers either as it is near impossible to report on dependencies.
We don't actually pass a "script name" to run as a parameter, we pass a whole heap of parameters to provide a context and an action such as new, delete etc. So yes the action is tightly coupled with the button but the script name and/or context is not, as I could copy the delete button from the person context where it may just delete the record, and paste it in the organisation context and then it would run the delete function within the organisation context (if there was a subscript for this function in that context) which may see if there are any related people and branch out depending on the result of that check. The master controller script really just runs any required preprocessing such as validation of the current record, security checks, audit logs and may run any generic non context sensitive functions in situ such as a show all, or uses zippscript to pass parameters on to the appropriate context controller.
Having said that though the idea of "registering" the usable scripts is appealing... but I think I may consider putting that at the context controller level. The self documenting is also appealing. At one point we mucked around with having a table of tables with a related table of functions and tied this to a security module and the controller script used the passed in parameters to interrogate the functions table and execute the matching script (by name) if found or return an error. It sort of worked for basic things, used the idea of registering as the function could exist but execute a generic "not ready yet script" and was great for documentation as you could have a related change history and descriptions and comments that could be reported on... but it was a bit slow and unwieldy so we threw it out. Oh the things we do to try and make life easier ;-).
I'm not so worried about the hacking as the malicious user would need access to the system in the first place to call the script and they could do far worse things if they had access anyway.... or am I missing something there?
All good stuff to think about though as I am having a good look at things we have been and are doing and re-evaluating the reasons we went down those paths. I've seen the MVC model presented before but the data was all in one table and I wasn't sure if that was a requirement or not... but it didn't seem like a good idea at the time and sort of turned me off. It seems that there is a lot more to it though.
Thanks
Andrew
Strict MVC can't be applied to FM
Thanks again
One of the things that this experiment proved to me was that Strict MVC can't really be applied in any realistic sense to FileMaker design. (It does not require all of the model to be in one table, by the way)
BUT... What this experiment did re-affirm for me was the fact that the Front Controller pattern part of MVC *DOES* work for FileMaker. It works really really well.
We have changed the name internally to "Main Controller", since "Front" didn't seem to make much sense in FileMaker terms.
I intend to write up a wrap up of this experiment as soon as I can.
Thanks
Todd
go dispatch
OK...this is cool. I very much like how you clearly define the flow. I've been doing variations on this for some time, but without quite the clarity and a bit more ad-hoc.
I have a main script, what you call your Controller Script, named "go". It is a dispatcher script that simply passes the parameters on to the next module controller.
Each script group is named by the module (eg Contacts, Invoices, etc.) and generally the following basic verb-based scripts:
go - the module dispatcher
nav - a module navigator, which moves between places
new
edit
delete
find
search
pick
select
in addition, any module-specific scripts are located in the group. I don't see file upload here so I'll send you a screen shot offline.
I've been calling this approach a "dispatcher" pattern, and sometimes "go dispatch".
Thanks again for an interesting discussion.
- Russ
Comments on MVC Part III
Todd,
Again thanks for starting this post ... sorry if this is a little long!
I have been building solutions for clients and selling, somewhat packaged up FileMaker solutions. Inspector is one of those packaged up solutions. The main framework has evolved over time since the introduction of FileMaker 7. I agree with you, it is difficult to dive into someone else's work and try to understand how things and where things are is a challenge.
I never got into the separation model because I just did not like the idea of having multiple files to code and manage. So i took the SESSION model approach. Where everything happens from one record. I'll talk a lille bit about this here and then come back to what I am using now and how it relates to what you are talking about here.
Lets say you have SUBJECTS, CLASSES, TEACHERS, STUDENTS, AND ENROLLMENTS. If you are using the "anchor-buoy" methodology and you are on a layout based on SUBJECTS that the only way to show a list of enrolled students for a particular class offered in that subject would be to store a foreign key of the class id in the SUBJECT table and then show a portal of students for the selected class.
The frustrating things were that: I would need to create additional keys fields and store them inside each of the tables so that I could see data the might be 2, 3 or 4 hops away. Then my data tables were becoming messy with so many fields. in the end I might have half the fields of my data structure in each of the data tables. This was too messy for me.
The other way to deal with this was to continually present the user with new windows. I want to see a list of students for a particular class, in particular subject then I would make sure to have some kind of meaningful title and just show that data in a new window. Adding more windows was not a good choice in my opinion.
So the solution I opted for was that I would create one table that would create a new record for each login... I could then also use this data to preform stats on how many times users logged in and such things. But the all the UI stuff gets presented in one window (for the most part). One set of global id fields that map to a data table. This way when I put the SUBJECT key field in that global I can then see all the classes in a portal that are for that subject, and if I put in another global the CLASS ID then I can also show all the students in that class. For the most past this has worked out just great, because everything is in context and you can then mix and match stuff as you see fit. Oh now I need to show all the teachers that teach all the classes for English ... this is easy to do ... most of the layout stuff can be just duplicated and because it all works from the context of Session nothing needs to be changed in terms of scripting. I can copy and past whole blocks of things and with a few minutes work, I can re-organize and have ready an entirely new layout that can server a different purpose.
Some of the drawbacks that I have found with this solution is that when you are looking for a related field you better have a good way to name each one of these tables (and in some ways even the graph had - a functional naming convention... Maybe I get into this topic in another post).
The other drawbacks have been that of dealing with portals, and because you are in this session record a user can't use the native FileMaker finds and sorts. But I got around this problem by allowing the user to take them to a detail record or a list view of all the records.
It has been a continual evolution, and what is interesting about the timing of your post Todd is that just a few months ago I wanted to tackle the way in which I pass parameters. What I was previously doing was setting global memory variables in buttons, and when you get to the script and your parameters are there waiting for you. I am still not sure wether or not that was a good or bad thing! But I used it, and now I felt like I wanted to have a tighter parameter passing methodology.
I opted to use the custom functions that Geoff and Jesse (from sixfriedrice) came up with. So I re-tooled my template with that as the underpinning and as I was re-tooling I was remembering something that Geoff showed me a while back when we were looking at xCode and, I think it was Project Builder - this notion of a First Responder.
What I ended up with was a script that acts as a First Responder (much like what you have been talking about here as well) ... and a set of parameters that can be sent to this script. Inside this script, as in your diagram. The branching happens in the script and it can determine if the sub branch can get called. Much in the same way as you have it the first responder gets called and in it is an action parameter ... and when it reaches that point it then dispatches the highlight script and the highlight script receives the parameters and knows what do to and where to do it... so in my solution I think I have the model ( what record gets the highlight ) embedded inside the action, if I am understanding this correctly.
I like the way you are splitting things out on your end. I think if I were to adopt your approach what would happen is that would have a script for each model (TABLE) / controller (ACTION). Tiny and compact scripts ... Hummm I like it.
Looking forward to more discussions on this subject.
In thinking of a name I came up with: Data - Interaction - Scripting
Vince
thanks for that!
Hi Vince,
Thanks for taking the time to post your thoughts.
I also use the Session Table pattern. Usually I mix it in with what I refer to as the "Standard FM View Pattern". Which is the normal FM way of doing things with a list view, detail view, find etc.
I call these two patterns "View Patterns", because they describe the primary pattern in which the user "Views" and interacts with FileMaker data.
Sounds like your script pattern is very similar to a front controller. Except that you might have more than one. I am going to stick with a single script for now. The power that this gets you is kinda cool. Security, Logging, and Navigation can all be made simple by having one script that handles the main flow.
Many people I have talked to worry about the one script getting heavy. But that is easily answered by having "sub controllers" that are called from the main controller.
This is very interesting....
Controllers - getting to the Heart of MVC!
Main controller, switch, entry point, or index (because this is often the "default" document name in some directories), whatever it's called has some advantages (when used to control other controllers):
1. you can point to another controller that is bogus or point to nothing. This flexibility allows you to:
a. shut off portions for debugging
b. shut off modules/features in a multi-module solution, if the client purchases a "lite" version.
c. it's easy to turn on or point to a feature when it's ready.
2. going through a central controller allows:
a. to trap for access levels before proceeding, if needed (if you didn't come from the main controller, you are bounced back there from other controllers)
b. multiple developers to work on distinct modules independantly - don't turn on a module until ready. This is probably one really great reason to use MVC, even if you are a one-person-shop, sometimes you may use plug-ins or call in assistance.
3. add a default (main menu and/or layout or??) if parameter branch is NOT directly called [ 'IsEmpty ( Get ( ScriptParameter ) )' ]
4. capture "navigation history", as you are always going to main controller, but passing function parameters that can be archived.
Beverly
Security and MVC
Beverly,
Well it certainly is tempting to start thinking in very granular terms of what this or that privilege can do and all, but then we have such a great security model already - albeit not as comprehensive at the field level but nonetheless this would be a huge undertaking. Then I feel like I am back in the separation model (even if I have never really used it). To me it sounds like in theory this would be great but in reality it might be a different story.
Do we then make it a rule to run very few scripts with full access?
Do we let the user execute all the scripts and put the logic inside the scripts (Fat Security Scripts)?
MVC - maybe there is one that is missing ... where does security fit into all of this ... at the model level?
Hummm..It would be great to have a few get functions that let you ask if you have read or write access to a table or field.
Anyway things to think about.
Vince
Exactly!
I think the Front Controller concept may end up being the most important contribution from MVC. It can be really useful.
One other thing that just came up on another thread was keeping Scripts from being able to be run from another file. Since we can ensure that nothing gets run unless it is coming down through the proper flow, this architecture handles this problem as well.
Using "Services" scripts
In this moment I'm in the process of rewriting some parts of Eikonsys to make it multilingual. Basically I'm using same the technique I showed during DevCon 2006 with a few enhancements.
During this process I rearranged all "common use" scripts in a folder called services. Those scripts are controller scripts, accoding with the definitions we are making here, however, there are no "Front Controller" script that make calls to other scripts, only this folder. Anytime I need to use one of the Service Scripts just call it and pass the proper parameters, if any.
As you say, having a long script can be a problem.
In my case, I had one Service Script called "Delete Portal Row", used – as its name implies – to delete portal rows. Depending of the parameter I passed, it checked into the proper context if the user has the right privileges to delete the portal row, if the record is editable or not (I use the terms open/closed), etc. It was a very long script with many If - End If parts, at least one for each module.
When a customer has a problem related to this script I usually login remotely into the system (via FM Pro, not remote desktop) and it takes eons to load all the script steps. In this upgrade I decided to create individual scripts for each module and a "Controller Script", stored in the Services folder, that will branch accordingly. This will make troubleshooting a lot easier because I'll only have to go to the specific "Delete" script and won't have to wade through all the long old script just to fix a few lines.
Almost forgot...
Main controllers or regular controllers sure help with that little thing called "TRANSACTIONS"!
The transactions are probably part of the MODAL (get/set data), but the controller can be used to test the branches: commit or rollback.
Yes absolutely
In terms of MVC then absolutely they are MODEL. But after kicking this around for several days I beginning to wonder if making such a clear distinction on Model scripts for FileMaker. The line seems pretty blurry unless you say the Controllers only branch, and Modal scripts only effect data. At the very least I think I start with get and set stuff in Action Controllers, and then abstract them out to the MODEL as needed. Don't know for sure yet...