Monthly Archives: April 2009

Model-View-Controller in Stone

We are using a Model-View-Controller design pattern for our web pages. Of course this can mean different things to different people. I was surprised to learn from Wikipedia [a resource that professors tell students not to reference, but that I find ever so helpful] that this design pattern was first described 30 years ago. I was not surprised to learn it originated in the Smalltalk community. For us, it means we are using the implementation of the M-V-C pattern by InterSystems with their Zen AJAX platform.

As we have seen with the rise and massive changes to relational theory, there are a) those who study and adhere to design patterns rigidly, b) those who accept them without question and feel good about using a popular pattern, and c) those who take a practical approach regarding any such theories, constantly applying and reforming them as makes sense.

So as to blend two of the worlds in which I live, I will refer to a) above as the Doctrinalists, b) as the Pietists, and c) as the Kuyperians. I’m going to go out on a limb and guess that some of you might not be familiar with Abraham Kuyper, so if you wish to familiarize yourself, perhaps check out what Princeton Theological Seminary has to say.

Whenever there is a question about how to approach pretty much anything and one of the possible answers is to approach it from a Kuyperian perspective, then in my tradition that would be the right answer. Sure we have our Doctrinalists and our Pietists, but the Kuyperians are the smart ones, as we all know.

While I will try to lay out a simple example of using M-V-C, making this theory more concrete, our approach is not exactly firmed up enough to be cut in stone. So, this could hardly be called my Stone Lecture on Model-View-Controller (assuming you have all read Kuyper’s Stone Lectures at some point in your education, right?).

One very cool feature we have is that we can source our metadata in classes, and project this to the MulitValue DICTionary, the SQL Schema, a Model for use with AJAX (InterSystems Zen platform), and anything else we need in terms of metadata. We can read and write a good old fashioned record by reading it in as an object and executing a save on that object. Very cool, but even better, we can execute a save on a form object in JavaScript, where that form is bound to a Controller tied to a Model.

In the simplest case, this Model could be the persistent class, the same one used to read and write records, aka the File. This is where some of the doctrinalists might get concerned. If our File is the Model and our form were bound to that, then we would have a pretty tight link between the View and the Model. There is a Controller in the midst, however, and the minute it becomes an issue that the Model is also the persistent class, we could write a new, non-persistent Model. I have tried to encourage other SnupNow developers to work with non-persistent Models, but to date I am the only one who has written these. That is about to change, knock on wood, but that is a more complex scenario so the M-V-C example given here will be a simple File-Form.

The form fields are bound to properties in the Controller, which relate directly the properties of the Model. The Model has the logic to read and write records from one or more files, which for a simple persistent class Model, the case we will be showing here, is inherited logic. So, the only reads and writes are written in JavaScript. A record is read when the modelId of the Controller is set and is written when the form is saved.

OK, it’s time for an example. The following example shows a file and a page for maintaining information about a collection of trolls, those little dolls with long hair and not-exactly-attractive facial features. We will write a little web page application that looks like the following (apologies for Template words on the clipboard, but it’s just an example).

troll

This is where those who are not SnupNow developers or really don’t want to know how to make this work can cut out, while those who want to know how to write a little MV (MultiValue) M-V-C (Model-View-Controller) web application using the tools used by the SnupNow project can check this out in more detail.

Notice how the logic for each button is written in JavaScript that is able to interact with the server-side, maintaining an MV file by way of the class used to define that file.  After compiling the following class, we can do a LIST DICT S.Troll to see the dictionary from the MV colon prompt. After compiling the page class after this, we can launch it in a browser and start maintaining the file. This could be done even more simply using a dynaForm, rather than a form, component from InterSystems, but that quickly becomes too simple once any logic needs to be added, so this is a good starting point for the basic Create-Read-Update-Delete (CRUD) functions performed on a single file.

To expand beyond a simple file, we would then introduce a separate Model class from the persistent class so that the following two classes could remain simple but the Model could be as complex as needed.

I opted not to trim the following back to what is essential for showing M-V-C, but to put in fully functioning classes, pretty much the way I would write them right now. Ask questions. There will be a test next Tuesday.

Persistent Class and the M in M-V-C, aka the File:

Class S.Troll Extends (%Persistent, %Populate, %XML.Adaptor, %MV.Adaptor, %ZEN.DataModel.Adaptor) [ Language = mvbasic ]
{

Parameter VERSIONPROPERTY = “Version”;

Property Version As %Integer(MVATTRIBUTE = 1);

Property Name As %String(MVATTRIBUTE = 2, MVWIDTH = 40);

Property HairColor As %String(MVATTRIBUTE = 3, MVWIDTH = 20);

Property TrollType As %String(MVATTRIBUTE = 4, MVWIDTH = 10);

Property GotchaDate As %MV.Date(FORMAT = 3, MVATTRIBUTE = 5, MVTODISPLAY = “D4/”, MVWIDTH = 11);

Property Description As %String(MAXLEN = “”, MVATTRIBUTE = 6, MVWIDTH = 60);

Property Tags As list Of %String(MAXLEN = “”, MVATTRIBUTE = 7, MVWIDTH = 20, SQLPROJECTION = “table”,  SQLTABLENAME = “TrollKeywords”);

XData MVAdditionalDictItems
{
<DictItems>

<DictItem Name=“@ID”>
<Attr>D</Attr>
<Attr>0</Attr>
<Attr>.</Attr>
<Attr>ID</Attr>
<Attr>13L</Attr>
<Attr>S</Attr>
</DictItem>

<DictItem Name=“@”>
<Attr>PH</Attr>
<Attr>Name HairColor TrollType GotchaDate Description Tags</Attr>
</DictItem>

<DictItem Name=“TrollId”>
<Attr>D</Attr>
<Attr>0</Attr>
<Attr>.</Attr>
<Attr>ID</Attr>
<Attr>13L</Attr>
<Attr>S</Attr>
</DictItem>

</DictItems>
}

}

Zen, AJAX, Page Class with the <form> as the View, using a page template not shown here:

Class Playground.dawnw.TrollCRUD Extends Util.Template.Page [ Language = mvbasic ]

{

Parameter PAGENAME = “Troll Create-Read-Update-Delete MVC Example”;

Property ClipboardTitle As %ZEN.Datatype.string [ InitialExpression = “My Trolls” ];

Property ClipboardInstructionsName As %ZEN.Datatype.string [ InitialExpression = “Template” ];

XData vcontentPane
{
<pane xmlns=http://www.intersystems.com/zen&#8221;>
<tabGroup id=“tabGroup” showTabBar=“true” >
<tab id=“tab1” title=“tab1” caption=“My Trolls”>
<pane paneName=“Tab1Pane”/>
</tab>
<tab id=“tab2” title=“tab2” caption=“List of All Trolls”>
<pane paneName=“Tab2Pane”/>
</tab>
</tabGroup>
</pane>
}

XData Tab1Pane
{
<pane xmlns=http://www.intersystems.com/zen” xmlns:s=http://www.snupnow.com/component” >
<dataController id=“source” modelClass=“S.Troll”  />

<s:form controllerId=“source” id=“signupForm” 
    groupClass=“snupform” enclosingClass=“snupencform” hintClass=“formhint” 
    width=“570px” labelClass=“formlabel”
    invalidMessage=“There seems to be a little problem here”>
<label controlClass=“componentTitle” enclosingClass=“componentHeader” 
    value=“Troll Information” />
<s:fieldSet id=“firstFieldset”
groupClass=“snupfs” enclosingClass=“snupencfl”>

<text label=“Troll ID” id=“ID” name=“ID” 
    dataBinding=“%id” size=“60”
    onchange=“zenPage.reloadForm();”
    hint=“Leave blank when entering a new troll” 
    />

<text label=“Name” id=“Name” name=“Name” 
    dataBinding=“Name” size=“60”
    />

<text label=“HairColor” id=“HairColor” name=“HairColor”
    dataBinding=“HairColor” size=“60”
    />

<radioSet label=“TrollType” id=“TrollType” name=“TrollType”  
    dataBinding=“TrollType” 
    valueList=“Standard,Tiny,Off-brand”
    />

<dateSelect label=“GotchaDate” id=“GotchaDate” name=“GotchaDate” 
    dataBinding=“GotchaDate”
     />

<textarea label=“Description” id=“Description” name=“Description”
    dataBinding=“Description”
    rows=“6” cols=“56”
    />

<textarea label=“Tags” id=“Tags” name=“Tags”
    dataBinding=“Tags”
    hint=“Place one tag on each line”
    rows=“4” cols=“56”
    />

</s:fieldSet>

<hgroup>
<button caption=“New” onclick=“zenPage.newItem();” />
<spacer width=“10”/>
<button caption=“Save” onclick=“zenPage.saveItem();” />
<spacer width=“10”/>
<button caption=“Cancel” onclick=“zenPage.cancel();” />
<spacer width=“10”/>
<button caption=“Delete” onclick=“zenPage.deleteItem();” />
<spacer width=“10”/>
<button caption=“Lookup” onclick=“zenPage.reloadForm();” />

</hgroup>

</s:form>

</pane>
}

Method saveItem() [ Language = javascript ]
{
    var form zen(‘signupForm’);
    var controller zen(‘source’);
    form.save();
    saveError controller.getError();
    // We will assume the error is a Version mismatch to handle concurrency for this simple example
    if (saveError != )
    {
        controller.setModelId(controller.modelId);
        zenPage.reloadForm();
        alert(“Rats! That didn’t work because someone else changed this information first. Their changes are here now, so you can try again at this time. \n\n”saveError);
    }
    zenPage.newItem();
    zen(‘ID’).setProperty(‘readOnly’,false);
    zen(‘ID’).focus();
    return
}

Method reloadForm() [ Language = javascript ]
{
    var id zen(‘ID’).getValue();
    var form zen(‘signupForm’);
    form.reload(id);
    return
}

Method newItem() [ Language = javascript ]
{
    var controller zen(‘source’);
    controller.createNewObject();
    var form zen(‘signupForm’);
    zen(‘ID’).setProperty(‘readOnly’,true);
    form.reset();
    return
}

Method cancel() [ Language = javascript ]
{
    var form zen(‘signupForm’);
    form.reset();
    var controller zen(‘source’);
    controller.setProperty(‘modelId’,);
    return
}

Method deleteItem() [ Language = javascript ]
{
    var controller zen(‘source’);
    var id=controller.getModelId();
    controller.deleteId(id);
    controller.createNewObject();
    return
}

}
 

Advertisements

Full Deck Plus a Joker

I turned 53 today, 35 in hex. While I might be inclined to tell folks I’m 35, and then explain how that is, I would rather tell people I’m 53. If I looked like this at 35, I would not be aging well.

For those looking for tech talk, I will get back to that, I promise, but this entry is about my health and the number 53. I like prime numbers, and 53 is even an Eisenstein prime (google it, then feel free to roll your eyes).

Someone suggested that 53 was one of those boring birthdays, compared to those numbers divisible by 10, for example. I have frequently let people know that there are no uninteresting integers. The proof is quite simple. Take the set of all uninteresting positive integers. Now take the smallest number in this set. Well, that would be an interesting number, wouldn’t it? Therefore, this set is empty. There are no uninteresting positive integers, therefore, there are no uninteresting integers (final steps in the proof are left to the reader).

I’m delighted to be 53. I don’t know if I am an optimist dressed as a pessimist or the other way around. I see the world through rose-colored glasses, while anticipating the worst case scenario for everything. I think that simply makes me a mom. 

I am working hard, putting in a lot of hours on this project, while also taking time to avoid smelling any flowers (allergies) and also avoid eating flour. I avoid wheat, rye, and barley, eating gluten-free so as to avoid the mini-anaphylaxic shock I apparently have been sending myself into every time I have done any physical activity for the previous 30+ years.

While it has occasionally been suggested otherwise, particularly by my youngest daughter, a beautiful Phi Beta Kappa who I now know reads this blog, I am playing with a full deck. I was very ill after moving to NW Iowa, but I now have proof that my ailments were not all in my head. It took a while to nail this down, but I am allergic to cows, pigs, and other things in the air around here.

A biochemist told me that with this genetic trait, the worst thing in the world for me to encounter are dead skin cells from pigs. You might think it would not be hard to avoid pig dander. I’m guessing you are avoiding such as you read this. However, I live in a county with a very high concentration of pigs and cows, perhaps the largest or second-largest in the country. I forget the exact figures, but the point is that pig and cow dander are in higher concentrations in the air around here than most other places in the world. I am allergic to the air here. How ’bout them apples?

There are not a lot of cultural events in small cities, especially outside of the school year, but this year I know to skip attending the 4H events at the fairground, including the wet pig contest. I always thought they were greased pigs, but not in the contest they have here. Yes, it is quite entertaining if you ever get a chance and are not HLA DQ2 or DQ8 or whatever it is that I am. For maximum enjoyment, don’t bring your PETA friends along. 

Now that I know what prompted my body to rachet down some rather key features, such as the production of adrenaline, I can mitigate this. 

Right now, after being gluten-free for approximately 9 months, I am feeling better than I have in years.

52 was a nice number because I like cards. Pinochle is my favorite card game, but a full Pinochle deck is only 48 cards. Euchre, a traditional card game of my alma mater, uses only 24 cards. So, maybe you guessed it, I don’t always play with a full deck. As is the case for many 50-something females, my brain and body are not always functioning at 100%. They sometimes trip me up, playing little practical jokes on me. Now that I’m feeling a lot healthier, however, I’ll think of the mental nuances at 53 as me simply playing with a full deck plus a joker.

Conan Said He Loves Me

The SnupNow start-up is being funded primarily by sweat equity and assistance from a number of partners. When dollars are required, they come from a small loan from me. You might wonder if I am wealthy or not, whether I am inclined to risk other people’s money or not, or just how we will succeed in writing software for a $0 – low dollar investment when books like Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software by Rosenberg, Startup: A Silicon Valley Adventure by Kaplan, and dot.bomb: My Days and Nights at an Internet Goliath by Kuo, among many other books have documented software companies with considerable funding that tanked anyway.

I have stayed away from many business-related topics here since my primary audience is the project team that needs to focus right now on writing software, but here is my current thinking related to funding. I would still like to avoid seeking funding, and I have one scenario in mind where I can avoid it, so we shall see. However, it is likely funding will be required.

Why? We are planning to write the alpha delivery of the software without funding, in spite of how slow that is moving. It is unlikely that we can sustain development beyond the initial alpha or beta version without paying developers, as we will need to pick up the pace once we have customers requesting enhancements. We will need to pay for hosting, the database, and our version control software. It is also unlikely that we can both sufficiently market and support a production environment without funding. 

When? Once we have had people using the alpha version, before we have a lot of customers to support, we will want an injection of cash to get us to the next level. I will want to be very sure that we will be able to pay back any loan or provide the expected return-on-investment for any angel investor before I will ask for funding. I err on the side of being too fiscally conservative, even if more risk-tolerant than my husband. He paid cash for our first house.

What? My scratch-paper figures say we should look for no less than $1.3 million, but that we really can do it for that figure, low as it might seem to some (high to others, I’m sure). It is much harder to write down anything that doesn’t seem like B.S. that proves an ROI. I cannot prove the future. I need to back up whatever figure we determine and hone my pitch by working with Snupnow LLC owners and others.

Where? Once I have the relevant information gathered and am armed with a tight pitch, then I’ll look locally for starters, using the local Small Business Development Center and other resources to find the proper people and venues.

How? Even when we have a good presentation and a schedule of events and opportunities to make the pitch, I know I will have some anxiety regarding How.

After I get into the groove, I’ll do fine, I tell myself. I am an introvert, but as a noisy introvert, I can flip a bit and at least simulate an extrovert, perhaps even become one. 

I had a very difficult oral exam in a graduate school course in mathematics. I got a very high score on it, which surprised the professor and pleased me. The next day he heard me mention that I had to head back to Grand Rapids to meet with the Board of Calvin College so they would approve me to teach Mathematics and Computer Science the following year. His inappropriate, but oddly understandable, response was “Don’t worry, you do very well with middle-aged men.” He said it with an edge that was clearly intended to indicate that my high score the previous day came from my manipulation of him personally, rather than my knowledge or intelligence. While a typical feminist reading this might find this offensive, for some reason I was not offended at the time, nor can I drum up any negative feelings today. We had had an hour of intense mathematics together in his office the previous day. We both knew that I knew the material, that I did not snow him. He intended this sexist statement as a compliment, which is how it has stuck in my brain. 

With business relationships, as with other relationships, you have an impression very soon after meeting someone whether you will enjoy doing business with them, even if sometimes getting it wrong at first. In addition to requiring a solid business plan, funding will depend on finding people who want to do business with me and with whom I want to do business. I often prefer doing that dance with women than men in the business world. There are too many added nuances with men. In the case of finding funding in Northwest Iowa, I am more likely to be talking with men.

I am not an expert in such matters, but it seems that men require more ego-stroking. Women are happy to get to even-up in the relationship quite quickly. Men are more likely in those first few minutes of meeting me to want to have a one-up relationship. I don’t know if that is true for all of their business relationships, nor do I know if it might be peculiar to me, but I suspect it is a male-female issue. I didn’t give that one-up position to Obama or Romney when I shook their hands and asked them each a question one-on-one early in the presidential campaigns (one advantage to living in Iowa), and I don’t give that position easily.

Men have the added feature, however, that they can more easily think they are in a one-up position when I think I am in an even-up position. That is when things work out best. The man has to feel personally one-up, while professionally even-up for this to work. What I do for that comes naturally to me, which might be where my professor’s statement about middle-aged men comes from. I am not sure I can describe this transaction, but it goes something like this. If I like the person (I am not inclined to fake it), then I somehow let him know that, which usually feeds his ego. With women it is a more two-way transaction, something that makes us both comfortable, rather than a “try to make sure he feels like a man while working with you even-up” approach. There are some women who work with men by trying to make themselves look or act more like a man. I don’t play that game. I have enough manly traits as it is. I happily play the part of a woman, provided you treat me like an equal. In some circles, this is contradictory, even impossible. Did I mention where I lived?

When someone else has money they might use to fund my company, then they get the one-up position, right? Well, I really don’t know if those who might provide funding for a project, whether male or female, want to feel they are in an even-up relationship with those they are funding, but they will certainly want to believe I can come through for them. I am anticipating it is somewhat like a customer – vendor relationship, where the vendor wants to attract and keep the customer. The vendor gives the customer some benefits in the relationship (since I know some of my readers, I will have to add “no, not that kind of benefits”, apologies to the grown-ups reading this), but wants to ensure the customer knows they are competent. So, I think I have to aim for even-up, even if also obviously needing to be humble and thankful for any audience I might have. I have never asked for money before. I’m not sure how this will go.

While I would want to focus on the reasons why someone might want to invest in this business when pursuing funding, these relationship issues will surely weigh on my mind. After meeting a person, whether giving a pitch in a group setting or talking one-on-one, I will review whether our speed dating was successful. I will likely know more intuitively about whatever limbic resonance we might have shared than whether they think the business plan to be viable.

I do not know if I can do anything at all to substantially improve this first impression that people have when they meet me. Some people will like me and some will not. I doubt I can improve that ratio much. For those inclined to like me, I can work to improve their initial impression by dressing appropriately and saying the right things, but for those with whom I have no chemistry, nothing I would do to prepare would be sufficient, I suspect.

My professor gave me something valuable with that possibly sexist statement. I use that in my positive self-talk. “You do very well with middle-aged men.” I can use this for men from 30’s through 70’s.  Sure it might have been more accurate when I was in my mid-20’s than now in my early 50’s and when I weighed 60% of what I weigh now (I keep working on that), but my brain has that quotation lodged in there, and I use it. I add to it a statement from a friend who told me an executive of her company said I was an enigma as I was both a woman’s woman and a man’s woman.

Will this help when pursuing funding? I don’t know.  I am definitely concerned about how this funding thing will all work out.

We were coming out of a Jack Stack restaurant, my favorite barbeque chain in the Kansas City area, a couple of weeks ago. My daughter, carrying her baby, whispered something at the same time I noticed. “That’s Conan O’Brien.” She had been irritated that a car pulled up right to the door, blocking our path a bit. While the rest of our family walked past the driver’s side, I casually went to the passenger’s side of the car where Conan was standing. This was the mid-west and “my people” are not fan-types. We give celebrities their space. I didn’t shake his hand, ask for a picture or autograph or otherwise bother the man, but had to think quickly to decide what might work for him. As I passed within inches of him, I said loud enough for my family to hear it “I love you” and kept walking. He turned around and said more loudly “I love you, too.” We were close to our car by then, and I turned and said “Aw, I’m just a girl from Iowa” to which he said “I’m just a boy from Boston, so it should work out.” 

Good, it should work out then.