
This is continuation of another post where I introduced the idea of considering the MVC design pattern as inspiration for designing a FileMaker solution.
There have already been some great comments posted on part 1. There have been some very good points made on where there is overlap between FM and MVC and where there isn't. I want to stress that this is an experiment and I want to see where it leads.
What am I looking to gain from MVC when it comes to FileMaker Scripts? In a word. Organization. Here is the basic problem. Open up scriptmaker on any complex system and what do you see? Who the #$#%#% knows? The guy who wrote it knows, that's who! He or she is the only one.
Of course thisn't true for every solution. Some developers work very hard to organize things in a meaningful way. But I have been looking for something that answers two very basic questions for me.
Thankfully we now have script groups with FileMaker 9. This can help, but it now I have another question.
3. "What do I name my Script Folders?"
Again I think the MVC may have something to offer in this area. When I started looking at other programming environments, I realized that the same problems exist there. Where do I put code and how do I find it again? Folder structure is critically important. And the projects that used MVC had a folder structure that made the most sense to me. So I wondered if I could apply some of that thinking to FileMaker.
Controllers mediate between the View and the Model. In FileMaker terms, we are of course talking about scripts. The Controllers respond to actions that the user takes in the system. Again thinking about FileMaker, when the user clicks a button that is attached to a script, the script runs.
Imagine a "Delete Contact" button on a Contact Detail Layout. When the user clicks the button a script is run that checks if it is ok to delete the contact and deletes it if it is. The layout is the View, the script that does that deleting is the Controller and the record it deletes is in the Model.
Controllers are typically represented in Object Oriented languages as classes with methods. For example a Contact Controller would contain all the methods (think FileMaker Scripts) that act on the Contact Model (think FileMaker Record). The method that deletes a Contact record would reside in the Contact Controller.
In FileMaker we don't have classes to contain our scripts, BUT since FileMaker 9 we do have Script Folders. I am in no way suggesting that Script groups are even remotely close to a class in OO terminology, but if our primary purpose is organization then they will do well enough as containers for our Controller Scripts.
Here is an example of how this might look in the ScriptMaker List

We have all of our controllers grouped into a folder, and then the two entities in our solution Contacts and Invoices each have their own Folder. The Contact Folder in this case serves to "contain" all the scripts that are Actions taken on the Contact. Likewise the Invoice Folder contains all the scripts that are Actions taken on Invoices.
At first, I would get confused about whether the Send Invoice To Contact (Invoice ID) belonged in the Contact Controller section or in the invoice section. But I finally got that what it is critical is the Verb Object relationship. Controller scripts act on an object. The Invoice is being sent. It is the object of the verb "Send". So it is a method of the Invoice Controller. Therefore it goes in the Invoice Folder.
Continuing on, let's discuss the Delete Contact method. It serves to point out another interesting thing about MVC. When you first design the Delete Contact (Contact ID) script, you might include all the logic for checking if it is ok to delete the contact in the controller. This seems to be acceptable to MVC.
Now suppose that later on you realize you need that exact same piece of logic in an another controller script. Perhaps you are merging contacts and at the end of that process you need to delete the old contact. What do you do? You could just call the Delete Contact Script from your new controller script, but there might be an even better way.
What if you took the scripts steps that did the actual validation and deletion and moved them to a new script? Where would that go? What would you gain?
What if we built the new script from the Model perspective? We could construct the script in such a way that it could do all the work and simply return a result of pass or fail to the calling script. It didn't change views on the user, and it is not called directly by anything other then Controller Scripts. What we have now is Script that is part of the Model. And we can move it into another section of Model scripts.

What's the difference? The scripts that are in the model only interact with the Data. They are tightly bound to the data. The user never directly interacts with them. They do something to the data and return a result.
What I find so cool about taking this approach is that either is OK--put all your code in the Controller Scripts or else abstract out what you can and place it in Model Scripts. Even better is the fact that you can start by doing it the first way and re-factor the code to the model as needed. You don't need to try to guess what you are going to need when you begin. You let the course the project takes and the needs dictate what you do.
When the code is in the controller scripts, it is called having a Fat Controller and Skinny Model. When the code moves to the model, the Model is called "Fat" and the Controller is "Skinny".
It seems to me that there can be a natural migration from one stage to the other as project progresses and more is learned about what can be safely refactored to the model. I find this acceptance of change as being very refreshing.
Getting back to my three questions from the top of this post.
I now have my answers
You can easily add to this hierarchy, if necessary. For example, I have two Folders that I added to the top of this Hierarchy in my latest project. I add an Application Folder that contains the all Controllers that are not specific to any of the entities of a particular solution. And then I have another folder called "Solution" that contains all of the Controllers and Model scripts that are specific and bound to this particular solution.
Another folder level I add is Library. Scripts that go in the Library folders don't belong anywhere else. They are typically low level scripts that may serve more like custom functions.
There is another Controller concept that I want to discuss, the "Front Controller. "But I think I will leave that for another day.
Comments
I *like* this folder approach!
Again, most of my experience is with the web, so I'll give an example of MVC with "flow"
index = main controller (calls other controllers in subdirectories grouped as "modules" - logical groups of actions)
login = folder with the login stuff (except the raw data)
c_login = controller for the login stuff (calls "M" and "V" pages)
v_loginform = show the form, "action" goes back to the c_login controller to process
m_getlogin = action called by c_login controller to test if the login passed by the form was valid and controller branches back to v_loginform or another "module"
[login probably also includes the "signup" actions and processes]
home = common and main elements and approriate "C", "M" and "V" as needed
contacts = a module
c_contact (contacts controller)
v_findContactform (search for contact)
m_getContacts (query) which the controller branches to the appropriate view based on found count:
v_contactlist or v_contactdetail or back to v_findContactform
....
you can begin to see the pattern.
While I don't currently place the "C", "M" and "V" in subfolders, rather than prepending the "c_", "m_" or "v_" the subfolders would seem to be a more logical choices (for the web and in FMP scripting).
Also, pulling the "M" actions on data, as you have with delete, into separate subscripts, it very MVC!
Very interesting topic
I find this a very interesting discussion. Thanks for starting it and sharing, Todd.
Like Ibrahim wrote in his comment to part 1, I have less formal professional database training and more experience based on what I have learned works in FM.
I frequently use the Separation Model, at least as I understand it. For me this means data resides in (a) separate file(s), and the 'view' and 'control' reside in the UI file, which holds the majority of the scripts, TO's, etc. Data files hold only TO's and scripts that are required to deliver certain pieces of data. I find putting the majority of scripts in the UI file a huge time saver, but as you write, the all in one place approach creates a problem: how does anyone else understand your logic and where to look for answers. To this end, I segment my scripts into groups much as you have described: contacts, invoices, etc.
But recognizing the universality of the action they are to perform, I find I can broaden the context of the script, branching within it to perform certain actions if called from contacts, and others if called from invoices. The basic actions (delete or new) are the same. The concept of MVC (new to me) seems to say this approach may be good for me, but not necessarily good for the next programmer to understand -- even with heaps of commenting.
If I understand the approach you suggest with MVC, the 'universal' action [delete record, for example] is contained within a universal delete script in the control section. The specifics of when it is OK to do so is contained within the specific sub-section [contacts, invoices] in the Model section. These scripts would contain the rules that must be evaluated before the control 'delete' script would be called. In this organization, you are separating the action from the rules governing the action, which I think should simplify the organizational structure of scripts as well as simplify the overall structure of the database.
Good food for thought. Thanks.
Try this...
I used to do exactly what you describe above. I would have a single Script which would do different things when it was called from Contacts vs when it was called from Invoices. But I found it difficult to decipher in the long run. If I am interested in modifying the "Delete Contact" behavior, I don't want to be confronted with all this logic having to do with Invoices.
But the MVC inspired approach you would do things a little differently... not much, but a little. Behaviors are grouped together based on their Verb Object relationship. Things that act on the same Object are grouped together.
The approach your describing sounds more like you group things based on the Verb. All of your delete behaviors are grouped together. As I said I have tried this, approach, but it left me feeling like I had to jump all over the place to find out a particular object ( like contacts) are handled.
Thanks for your comments