Friday, July 15, 2011

Worship word: presents

Theologians (and I'm sure some who might read this post will be irritated) speak of the attributes of God. This is a useful way to try to understand what He has told us about Himself in the Bible, but it can sometimes get so theoretical and dry that it threatens to suck the life out of the Living God Himself.

Consider God's attribute of immutability. That this attribute is His is undeniable. 1 Samuel 15:29 and Malachi 3:6 say so explicitly. But note that these passages say that God's mind does not change, i.e., His plans and purposes for today are the same as they were yesterday and as they will be for all eternity.

What does this have to do with worship? You see, theologians get snagged on this concept. They extend it beyond this idea of immutable purpose to mean that things that happen have no impact on Him. But the Bible tells us that God takes pleasure in our worship, it tells us that He seeks worshipers. When we worship, we bring presents to the God of the universe, and He is affected by them. He created us for relationship, and our worship is an expression of that relationship. Think of it - the creator God is moved by my efforts to have relationship with Him.

I am always amazed that so wonderful a woman as Bethany chooses to love me - how much more amazing is the love of the God of Gods.

Monday, July 11, 2011

Learning

I have been writing web pages for a long time now. I started teaching HTML in 1999, and have worked for most of the last decade on projects that revolved around web pages. One would think that I probably knew most of the details of HTML - it is not a particularly complex language. Even if I didn't know all of the esoterica, surely I had all of the broad strokes, right? Well...

I was working on the accounting application within mypeoplematter. When the user needs to enter a transaction, they select an account from their chart of accounts. I am using a standard select list, which translates into a drop-down list in the web browser:



The list was too long (the basic chart of accounts has over 50 accounts in it), and there was no indication of the type of account (income / expense / bank / liability) in the list. I wanted to layout the list so that the account type was on the far-right, with the account name left-justified, but this is not supported by the HTML spec, so I was looking around the web for other ideas.

I found someone's code that had provided something like this, and was looking through it to try and understand what they did. In the midst of the code, there was something about optgroups. I didn't know what that was, so I googled it. Turns out, you can group items in select lists using optgroup. Over a decade of experience, and here was something new. Not only that, but it solves my problem perfectly. By the way, for programmers who find this, I will post at the end a small class that extends the standard .NET DropDownList to support retrieving the optgroup from the data source.




But my real point here is not about optgroups. My point is about knowledge. It seemed entirely reasonable to me to assume that I knew most of the features of HTML 4 - it is, after all, pretty simple. But here was something I had simply never encountered. It was a humbling moment. And of course, it made me realize that this experience is probably much more common than I realize. It is probably so for all of us. I know this is true: it just pays to be reminded:
It is not the things we know that give us the most trouble; it's not even the things we know we don't know; it's the things we don't know we don't know that are the biggest issue.
Humility doesn't always come easy for me. It's helpful to be reminded.

Programmers - here, in its entirety, is my DropDownList extension - it doesn't format well on my blog site, but if you select it and paste it into a text editor, it's all there:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using MyPeople.Extensions;

/// 

/// This class extends the built-in DropDownList to provide support for retriving the name of an optgroup from the database.
/// 
namespace MyPeople.WebControls {
    public class OptGroupDropDownList : DropDownList {
        public OptGroupDropDownList() { }

        /// 
        /// The field in the datasource that provides the value for the optgroup. IF not set, then the list behaves as the built-in dropdownlist.
        /// 
        public string OptGroupField {
            get {
                object o = ViewState["OptGroupField"];
                return (o == null) ? "" : (string)o;
            } // get
            set {
                ViewState["OptGroupField"] = value;
            } // set
        } // OptGroupField

        protected override void RenderContents(HtmlTextWriter writer) {
            if (String.IsNullOrEmpty(OptGroupField)) {
                base.RenderContents(writer);
            } else {
                bool useOptGroup = !String.IsNullOrEmpty(OptGroupField);
                String lastOptGroup = null;
                ObjectDataSource ds = Page.MuchBetterFindControl(DataSourceID);
                IEnumerable objs = ds.Select();
                foreach (object item in objs) {
                    String text = DataBinder.Eval(item, DataTextField, DataTextFormatString);
                    String val = "";
                    if (!String.IsNullOrEmpty(DataValueField)) {
                        val = DataBinder.Eval(item, DataValueField, "{0}");
                    } // if
                    bool sel = false;
                    if (!String.IsNullOrEmpty(SelectedValue)) {
                        sel = val == SelectedValue;
                    } // if

                    if (useOptGroup) {
                        string thisGroup = DataBinder.Eval(item, OptGroupField, "{0}");
                        if (thisGroup != lastOptGroup) {
                            if (lastOptGroup != null) writer.WriteLine("");
                            writer.WriteLine("", thisGroup);
                            lastOptGroup = thisGroup;
                        } // if
                    } // if
                    writer.WriteLine("", System.Web.HttpUtility.HtmlEncode(text), System.Web.HttpUtility.HtmlEncode(val), sel ? " selected='selected'" : "");
                } // foreach

                if (useOptGroup) {
                    writer.WriteLine("");
                } // if
            } // if
        } // RenderContents
    } // class OptGroupDropDownList
} // namespace


Monday, July 04, 2011

Naming

Happy 4th of July. It is a good thing to celebrate the birthday of the greatest nation in all of history. Not perfect, but the best we humans have done thus far.

I am working a bit today, mostly because we are going to be going away for a few days later this week and wanted to finish a particularly useful piece of code for the accounting report system. Along the way, I discovered a flaw in my design. These are always frustrating; especially when, as in this case, the design flaw touches on several aspects of the software and thus testing the fix is more time-consuming and tedious. But this design flaw was particularly frustrating, because there were signs of the problem that I overlooked. The most significant sign that I had a problem in my design was to be found in the names that I was using.

Briefly, the flaw was that I was only requiring that a single item be configured where I in fact needed two related items. As I went through my code making the change, I found that I had been confused all along, as I sometimes used one name when describing the configured item, while at other times I use another name. The two names accurately described the two items I needed, but I missed the hint until just today.

I mention this because this is one of those principles of programming that I have developed over my career: if I don't know what to name something, then I don't understand it. And if I don't understand it, I haven't fully investigated it. Normally, if I have trouble with a name, I back away from the code and attempt to clarify my understanding before I move forward. In this particular case, I let my (mistaken) belief that I knew what I needed obscure the hint that the naming issue was giving me.

I love this for another reason. The issue of naming is one of those things that touches on multiple disciplines. The centrality of naming is one of the reasons that I have confidence in the Genesis story - the God who made us understands that if we cannot name something, we don't understand it. So, one of His first tasks for man was to name the animals. It matters not to me whether you believe in the historicity of the Genesis account; it is difficult to deny the insight of the second chapter of Genesis in this matter.

This issue of naming touches in the political realm as well. One of the great powers of the media is that it often gets to name the forces within our society. The power of naming allows the namer to define the item named. It is why politicians look to name bills. The name of the bill becomes its meaning, even if they are not in fact the same thing. To name is to define and to control understanding.

Finally, I have found this principle true in my own life. Early in my adult life, I was struggling with some personal issues. I flailed away, trying to get a handle on what I was doing, until a friend gave me a name. In retrospect, the name was only partly accurate. But at the time, the name gave me something to address. In addressing the name, I found the ability to overcome the underlying issue and to move past a continuing area of struggle.

I recommend it as a life principle. If you do not understand what is happening in life, try to name it. The process of naming can often bring the understanding that has heretofore eluded you.

It also works if you write software...

Tuesday, June 28, 2011

Being left handed

I am, in case you didn't know, left-handed. I love being left-handed, the greatest men in history were predominantly left-handed (so were some of the worst). Even God is left-handed. Don't believe me? He must be, since the Bible says that Jesus is sitting on His right hand.

Anyways, there are many, many places in which being left-handed puts me at a disadvantage. Some are trivial - did you know that the printing on pens and pencils is upside-down if you hold them in your left hand? Some are minor - scissors are built so that when held in your right hand, the top blade does not obscure your view of the cut line - when held in the left hand, you must look over the blade to see your cut line. Some can be dangerous - in fact left-handers may actually live shorter lives.

Here's one I'll bet no one has noticed before. The shortcut keys for the common editing commands undo, cut, copy, and paste use the shortcuts Z, X, C, and V respectively. All of those keys are on the left side of the keyboard. So, when I am using my mouse and I want to use one of those common shortcuts, I must take my hand off of the mouse, press the desired key chord, then return to the mouse. If I have a difficult series of edits to make (this is common when I am programming) this can be very inefficient. Sometimes I even move the mouse to the right side of the keyboard for a few minutes (another advantage to being left-handed is that most of us can use out right hands fairly well for common tasks).

Probably not the biggest issue in my life, but it sure can be irritating. I can only hope that all that movement reduces the risk of repetitive motion injuries.

Model-View-Controller

I have read all about this pattern for doing UI work, but I have never seen a great need to adopt the pattern. Both Builder and Visual Studio invite you to place all of your response code directly into the UI element class, and I have gladly taken the invitation. To be honest, I had never seen a good reason to do any differently. Oh, I would wrap some concepts into external (or even internal) classes, but the basic approach has worked fine for me.

The last couple of days I have been working on the configuration assistant for the accounting system at mypeoplematter. This is an ASP Wizard control with (as of now) 11 pages, some of which feature expanding windows that allow the user to configure things like bank accounts. Very quickly the number of buttons and their callbacks became unmanageable. So I built a controller class that provided a framework for each page. Then each "page" in the wizard got its own Controller-derived class to actually handle the work. My form class was left with just a little code to abstract out navigation events, and 4 general-purpose button events that it forwards to the controllers.

The Controller class has an interface with 7 methods:
virtual public void OnEnter(secure_accounting_ConfigAssistant page);
virtual public void OnExit(secure_accounting_ConfigAssistant page);
virtual public bool SkipMe(secure_accounting_ConfigAssistant page);
virtual public void OnSelect(secure_accounting_ConfigAssistant page, object sender);
virtual public void OnShowEditor(secure_accounting_ConfigAssistant page);
virtual public void OnSaveEditor(secure_accounting_ConfigAssistant page);
virtual public void OnCancelEditor(secure_accounting_ConfigAssistant page);

It provides (empty) default implementations so that derived classes need only override the methods they need. I built a small caching mechanism to keep track of controllers throughout postbacks.

The resulting code is so clean that I will use it in every Wizard I build from here one, and probably for multi-tab pages as well. I can find the implementation of a given event handler by going to the appropriate controller and looking through at most 7 methods, rather than the over 60 that I would have needed without the controller abstraction.

Having said all that, I still do not see how MVC (or MVVC) would simplify my pages that perform a single function. Now, I have done some abstracting - most of my data entry pages have FillPage() and Gather() methods that handle the populating and retrieval from these pages. But since the pages themselves perform only a single function, I do not see the benefit to be gained from adding a controller class.

Any thoughts?

Thursday, June 23, 2011

Demonstration

--- From my "Worship Words" series ---

Last week was Vacation Bible School. One of the things I love about VBS is all the songs with lots of hand motions and dancing. The reason we do it this way is because adding the actions helps the kids to stay interested and to learn. When we make big hand motions and sing about how big or powerful God is, the motions reinforce the message.

Our word today is “demonstration.” One aspect of our role as worship leaders is that of demonstrating what we are saying to the congregation. When we raise our hands in surrender, when we clap with joy, when we dance (or bounce) to a song of celebration, our actions reinforce the message we are singing. The principle we use when teaching children applies to adults as well – many people in our congregation are learning about God and how to worship Him by watching us. Let us demonstrate our words with our actions, just like we did last week at VBS.

Monday, June 20, 2011

UpdatePanels and Wizards

At the heart of my new website is a little control that does a dynamic lookup of a name as you type in a text box. Internally, I call it a PartyLookup (as the core table it searches is the Party table). Today, I am trying to add one of these controls to a rather nasty page: it has a wizard inside an update panel all in a modal popup extender. This all worked when the popup window did not have a wizard, but the page is complex enough that I decided I needed to break it up into 2 steps, hence the wizard. But my lookup control stopped working, as the dynamic javascript I generate to handle the AJAX calls was not getting emitted via the partial postback when I changed wizard steps (the lookup control is on the second page).

I searched Google for an hour, trying everything I could find. Finally, the following 2 changes worked:

For javascript I generate in the server-side code, I needed to use
ClientScript.RegisterClientScriptBlock, rather than Page.ClientScript.RegisterClientScriptBlock. This is a mysterious fix, but it works.

Second, for script that I want to include from an external source, I needed to add:
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

Together, these two calls seem to have gotten my control working in this new environment. We will see...

Saturday, June 18, 2011

Tax increases and subsidies

As anyone who knows me can attest. I am a fiscal conservative politically. My first presidential vote was for Ronald Reagan, and I considered it the best gift a young voter could have been given. I am against tax increases, period.

But I don't understand Grover Nordquist's position on the ethanol subsidies and other similar issues. I want the government to simplify the tax code, and I want the government to stop picking winners and losers. Subsidies go against both. Technically, ending a subsidy has the same effect as raising taxes, but when you have such a narrowly defined subsidy, the elimination of it feels more like a reform to me.

And these are the sorts of reforms we need. Eliminate preferences for one style of business over another. Eliminate preferences for one behavior over another. Let Americans decide what they want to buy without a parental government telling them what is best for them.

Besides, the ethanol subsidy is immoral...

Friday, June 10, 2011

Worship word: approach

My wife and I head the worship team at our church. We get to be on stage occasionally, but mostly this involves us training our young team. It's a lot of fun, and I always tell my pastor that I hadn't meant to sign up for youth ministry.

One of the things I do is what I call a "worship word." Every week at practice, I take a couple of minutes and do a short teaching around a single word and its application to worship. I'm going to start posting them here every Thursday or Friday. This week's word was "approach."

-----
The Bible tells us that we are to "boldly approach the throne of grace." It is here that we meet the God who gives grace and mercy and help. As worshipers, we do this in part when we worship. Through our singing and playing, we approach the throne of the God who meets with us. I am coming to a new understanding of the remarkable nature of our relationship with this God. He is the one who dwells in inapproachable light, whom if we were to look upon him we would die; and yet we can approach him because he invites us. Just as the shed blood of Christ opens the way for us to share in his table, so it has purchased for us an invitation to approach the inapproachable God.

As a worship team, we have an additional gift. Not only do we approach God, but we are given the task of leading others as they approach him to. Our leadership in worship is intended to open the door for the congregation to follow us into the presence of the God of the Universe. What a wonderful, inexpressible opportunity!

Javascript and .NET PostBacks

I always find it interesting when I suddenly find a use for a feature of a toolkit that I never needed before. This is the story of one such event, which just happened today.

Some background: I'm working on the accounting portion of my new company's product. It is almost ready to unveil; I just have to finish a couple of data entry screens and generate the core reports. Currently, I'm working on the bank account reconciliation page.

I want it to be nicely interactive - when you check an item off, I want to immediately update the item counts and totals so that the user can see their progress toward balanced. The most effective way to do this is to use javascript, and so that is what I did.

It worked great. But I have a handful of things that require a server round-trip, or a post back. When these happened, my totals were reset. This makes sense, the server-side couldn't possibly know what all had happened since it last sent the pages. This means that I have to figure out what the user had been doing, and have my server-side code reproduce the calculations the client-side was doing (I know I could have stored the values in hidden fields, I chose not to and I'm glad, because then this story wouldn't have happened).

Where to do these calculations? The answer is to handle them in Page_Load. I've done lots of coding in Page_Load, but never in response to a post-back. My pages mostly look a lot like this:

protected void Page_Load(object sender, EventArgs e) {
    if (IsPostBack) {
    } else {
        // Lots of code here to load the page from 
        // query strings and other stuff.
    }
}

I almost never had any code in the side of the if statement when IsPostBack was true. I had about decided I never would. But here was a case where I needed to fill my page only on a post-back.

Nothing really profound, but I just think it is interesting when something new comes up for me.

Thursday, June 09, 2011

Back again

I have been trying to figure out how the blog fits in my life. Basically, it hasn't for a couple of years now.

But I love to write, and writing helps me to organize my thoughts. So I have a new plan. I'm going to try and post at least 3 times a week. The posts will be as varied as my interests - one may be something new that I discovered about programming while working; another may come from politics or religion; others may just be from everyday life. I will try to make it all interesting, and hopefully the blog will be discovered again. But even if not, this will be the place where I can look back an remember what has happened.

But this post has another, more sinister purpose (cue music) - I want to get a link back to my new company's web site in place. So, here is a shameless plug/postback to the site in an effort to get Google to notice it. You can find my company at: www.mypeoplematter.com. The company makes church management software that runs in a browser. It is designed primarily for smaller churches - it doesn't have all of the bells and whistles of the well-established packages. But it is my experience that most churches don't want all of those things. They just need a few features: contact management, donation tracking, directories and communications, and accounting. When I finish the accounting piece in the next few weeks, I will have all of these features. And my pricing is designed for smaller churches, just a minimal monthly subscription fee, tiered based on church size. A church of under 120 will pay just $25/month for the entire package, only $15/month if they don't need accounting.

Anyways, that's what's up. If you're still out there, it's nice to be speaking again.

Thursday, April 16, 2009

Religion and the brain

Michael Gerson reviews research on the interaction of religion and the brain here.

This study is the most balanced I have yet seen. The author of the study is himself a skeptic, but admits that his research does not disprove the reality of religious experience. Neither does it prove it. How you interpret the findings will undoubtedly be influenced greatly by whether or not you are already religious.

I am just always happy when a skeptical scientist if honest enough to admit that science isn't the end-all of truth. I'll admit it about religious truth, glad to have a reciprocation.

Wednesday, April 08, 2009

Religion in the public square

There is an interesting point in this article. The authors argue that one of the primary reasons that religion flourished in the United States is that the first amendment introduced competition into the religious community. By removing from the church the explicit support of the state, the constitution force the church to compete amongst itself for people.

This puts a very different spin on the classic complaint about American Christianity: that the variety of denominations is a bad thing by definition. I would contend, in light of Micklethwait and Wooldridge's argument, that this very competition has been the lifeblood of Christianity in America.

Not to say that it is all good. It is one thing to compete as compatriots; it is another to undermine other churches in the pursuit of growth. But to the extent that churches have simply sought for the best way to reach people (both believers and non-believers) then I say - compete on. Just remember, in the end, we're all on the same side.

Monday, January 19, 2009

Inauguration

Tomorrow is the inauguration of our new President, Barack Obama. I am honored and overwhelmed that I live in a country where a transition in power is invariably accomplished without violence. Even though I did not vote for him, beginning tomorrow he is my president, and I will pray for him with the same fervor that I have for those I supported. And it is my supreme desire that he be remembered through history as a great president, for his successes and failure will impact my lives, and the lives of nearly every person on the planet.

Good luck, President Obama.

Friday, January 02, 2009

Earth Hour

Apparently, this March 29 has been set aside by the global warming (or is it "climate change") alarmists for the "Earth Hour". The plan, as I understand it, is for everyone to turn off their lights for one hour (from 8-9 pm) to symbolize that we all can make a difference (if you want to read more, you can read it here).

Of course, turning off our lights for an hour does nothing of the sort. Moving out of the city, and choosing to live without electricity, farming instead of purchasing; these might make a difference. But probably not, as China, India, and some day Africa will more than happily use the resources you give up.

Besides, I am convinced that this is all alarmist hoo-hah. So I propose a different action during Earth Hour. I am going to turn on all the lights at my house, run whatever climate control system is appropriate at maximum comfort levels, and generally use as many resources as I can. My point is to show that one hour of behavior modification is meaningless. No one will notice my action, just like the actions of all the Earth Hour sillies will go unnoticed.

Anyone want to join me?

Monday, December 01, 2008

The benefits? of losing the presidency

By the time Mr. Obama is finished, every major Democratic politician will be in his cabinet. Already there are 2 openings in the Senate, 2 governorships, and a House seat. In Arizona, where hour Democratic governor will be leaving to serve in the Obama administration, her replacement will be a Republican.

I think the impact is greater because President Bush has served for so long. It means there is a backlog of good people to serve, since all the stars in waiting have been in holding patterns. I think Mr. Obama may very well suck all the Democratic talent into his administration. It isn't much, but it is something.

I wonder how much of an impact it has on the national picture over the next few years when this happens.

Friday, November 21, 2008

Thanksgiving in Alaska

Have you seen this yet?


More wonderful is the hysterical commentary on the video, brilliantly summarized here.

I wouldn't expect the editorial board of the NY Times, or LA Times, which have yet to realize that no one reads paper any more, to understand that this image is not so horrible. And MSNBC still can't figure out why no one watches.

I just want to say that I am thankful that the turkey I will eat this Thanksgiving was once alive (actually, we are having Turducken). You may choose to put your head in the sand if you wish (but I would avoid the little funnel behind Governor Palin if I were you), but this is the reality behind most of our protein in the world. I love it that the Governor (oh that she were VP-elect) does not find this disturbing - she's clearly more of a man than anyone at The Times or MSNBC.

Wednesday, November 05, 2008

Dow plummets 500 on news of Obama win

The Dow was down 500 points today, giving back all of its gains from yesterday.

This surprised me. Normally the markets have expected news built into them; and while I was hoping McCain would win, I figured there was a better-than-average chance that Obama would. I expected the market to drop a little at the start of the day, then move up again as the uncertainty of an election went away.

What this tells me is that the market expects Obama to be very, very bad for business over the next 4 years, and so yesterday's rally was little more than wishful thinking. If Obama is indeed a socialist at heart (and Europe sure seems to think so), then the market is right. An Obama administration is going to take money away from anyone who produces it, and give it to every slacker that they think will vote for them in 4 years. This could be a very, very difficult time to make money.

The good news here is that it appears that the Republicans will have enough votes to filibuster the worst atrocities, assuming they have the strength of character (I am thinking a much more colorful term) to do the right thing in the face of a hysterial lefist media. Given that congressional republican gave us this mess by acting like democrats in the first place, I am not too hopeful in the long term.

There's always the 2010 mid-terms.

The Arizona propositions

Hey, I was 8-for-8.

President Obama

Congratulations.

I did not vote for you, but in January you will be my president. I will pray daily for you, not that you do what I want, but that what you do succeeds. Because, although you do not have the same letter (R or D) after your name as I, you are the president of my country, which remains a shining light for all the world.