Wednesday, December 16, 2015

Undocumented Google Calendar URL Parameter #2

While looking up information about the sprop parameter for Google Calendars, I found a Japanese page with information about adding events to Google Calendar that included the add parameter. The add parameter allows you to define additional attendees. I've tried this with email addresses. You can specify multiple email addresses by separating them with commas. Here is an example:

add=guest@gmail.com,visitor@gmail.com

I'm still looking for a parameter that allows you to specify notification times.

Undocumented Google Calendar URL Parameter #1

While doing some looking into ColdFusion components and research into RFC 5545, Google Calendars, and Yahoo! Calendars, I did some experimenting to see how much I can specify for a calendar event via URL in Google Calendars. I quickly found the action, text, desc, dates, and location parameters. Some additional looking found the sprop and trp parameters.

I opened up a new calendar event and tried to find ways to specify other portions of the form through URL parameters. I eventually found that I could use the recur parameter and specify a full RDATE or RRULE property and value string in URL-encoded format. For instance, if you wanted to create an event that repeated monthly on the second Sunday, you could add:

recur=RRULE%3AFREQ%3DMONTHLY%3BWKST=SU%3BBYDAY%3D2SU
to the URL. That's a URL-encoded form of the following.
RRULE:FREQ=MONTHLY;WKST=SU;BYDAY=2SU

I didn't find this documentation anywhere else, so I'm posting it here for someone else to find.

I'm still looking for ways to specify reminders and attendees. If you know how to do either of these, let me know.

Tuesday, February 3, 2015

Discoveries in Familiar Languages #1

I love it when I'm working in a familiar programming language and find something new, particularly if that something new gives me more power or simplifies a pattern I've been using for a while. Such a discovery happened today.

Many-to-many relationship maintenance

I am constantly setting up and maintaining many-to-many relationships. I often set up the junction table to prevent duplication of relationships by adding a unique index on the appropriate key columns. Here's an example of such a junction table in MS SQL Server.

 CREATE TABLE [dbo].[ContactsGroups](  
  [keyContactGroup] [int] IDENTITY(1,1) NOT NULL,  
  [keyContact] [int] NOT NULL,  
  [keyGroup] [int] NOT NULL,  
  CONSTRAINT [PK_ContactsGroups] PRIMARY KEY CLUSTERED ([keyContactGroup] ASC) ON [PRIMARY]  
 )  

This is a pretty typical, very simple junction table. When I need to maintain this many-to-many relationship, I've typically taken a two-step process: DELETE and INSERT. Here is an example of those two queries as they would appear in ColdFusion.

 <cfquery datasource="..." result="qry_updateContact_groups">  
 DELETE FROM [ContactsGroups]  
 WHERE ([keyContact] = <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keyContact#" />)  
 <cfif ListLen(Form.keysGroups) GT 0>  
  AND ([keyGroup] NOT IN (<cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keysGroups#" list="true" />))  
 </cfif>  
 </cfquery>  
 <cfif ListLen(Form.keysGroups) GT 0>  
  <cftry>  
   <cfquery datasource="..." result="qry_updateContact_groups">  
   INSERT INTO [ContactsGroups] ([keyContact], [keyGroup])  
   SELECT <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keyContact#" />, [Groups].[keyGroup]  
   FROM [Groups]  
   LEFT JOIN (  
    SELECT [keyGroup]  
    FROM [ContactsGroups]  
    WHERE ([keyContact] = <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keyContact#" />)  
   ) [ContactsGroups]  
    ON ([ContactsGroups].[keyGroup] = [Groups].[keyGroup])  
   WHERE (  
    [Groups].[keyGroup] IN (  
     <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keysGroups#" list="true" />  
    )  
   ) AND (COALESCE([ContactsGroups].[keyGroup], 0) = 0)  
   </cfquery>  
   <cfcatch><!--- An exception is thrown when nothing is inserted. ---></cfcatch>  
  </cftry>  
 </cfif>  

As you can see, this involved performing a LEFT JOIN to exclude items that already exist in the table. Today, while looking up a related issue (see the comments in the <cfcatch> block), I found a much easier way to write the same INSERT query.

  <cftry>  
   <cfquery datasource="#Request.ds.site#" result="qry_updateContact_groups">  
   INSERT INTO [ContactsGroups] ([keyContact], [keyGroup])  
   SELECT <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keyContact#" />, [keyGroup]  
   FROM [Groups]  
   WHERE ([keyGroup] IN (<cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keysGroups#" list="true" />))  
   EXCEPT  
   SELECT [keyContact], [keyGroup]  
   FROM [ContactsGroups]  
   WHERE ([keyContact] = <cfqueryparam cfsqltype="cf_sql_integer" value="#Form.keyContact#" />)  
   </cfquery>  
   <cfcatch><!--- An exception is thrown when nothing is inserted. ---></cfcatch>  
  </cftry>  

Note the use of the EXCEPT keyword. This operates very similarly to the UNION keyword, but performs practically the opposite operation. Instead of creating a result set with the results of the first query followed by the results of the second query, it creates a result set with the results of the first query excluding results matching those of the second query. It performs the same task I was doing before, but it's more concise and (bonus!) more readable.

Sunday, May 25, 2014

Confessions of a Type 2 Developer

I recently read an article that divided workers into two types and illustrated the second type with a story about a child building a sand castle. I can't remember if this was a blog post or a Facebook post. I'll try to outline the gist of what I remember about the two types of workers.

Two Types of Workers

We visit a small, undeveloped village built about a mile away from a small river. Every day, the men of the village go down to the river and retrieve water, filling cisterns with what they bring back. These cisterns are used to draw water for the people to drink or water their crops. Most of the men (we will call them Type 1 Workers) carry back enough water to fill one cistern each. However, there is one man (we call him a Type 2 Worker) who only brings back for his family to drink and they have to rely on water others retrieve to water their crops.

The Type 1 Workers scoff at the Type 2 Worker because his contribution is so much smaller. However, one day, we see that the Type 2 Worker has completed a project that completely upsets the balance. He's built a wooden channel that diverts water from the river directly to the village. There is no more need for people to walk a mile to the river and back to get water.

The tables have turned now. The Type 1 Workers feel short-changed because they have been performing so much more work for so long, but now the Type 2 Worker is getting the attention because of his project. The Type 1 Workers have been working a lot longer and a lot harder, but the Type 2 Worker has invalidated the need to do that anymore and is getting more attention for his time-saving project.

The illustration that accompanied this story was about a child who had built a sand castle some ways up from the high tide mark. However, he wanted to have a moat and realized that, whenever he brought water up from the sea, the water was quickly absorbed by the sand. In an effort to keep water in his moat, he started digging a channel from the level of the sea to his castle. It wasn't long before more people joined in and helped him build his channel to keep water in the moat around his castle.

Two Types of Developers

As in the story above, there are also two types of developers. Most developers are Type 1 Developers who, familiar with an existing set of tools and overwhelmed by deadlines, stick with the techniques they know and write their code using those techniques. A few developers are Type 2 Developers who, frustrated with copying, pasting, and tweaking code over and over again, search for ways to simplify the process. These Type 2 Developers are meeting some of the same deadlines, but they are willing to risk missing the deadline in order to divert a little time here and there to build automation and write templates that they see as time-savers in the future. "If I can get this right, this process will be a lot easier."

I am a Type 2 Developer. I love to build tools. I was building tools from the time I was asked to build a menu-driven console application with no functions longer than ten lines (including whitespace). Where most of my classmates built switch-case statements that ran hundreds of columns wide in order to fit within the line count limitation, I built a template object that allowed me to simply write menuObject.AddCommand(funcToRun, keyTrigger) and the object handled the rest once I wrote menuObject.GetCommand(). One of my first development jobs was in a shop that used C/C++. When I was confronted with functions over 3,000 lines long, I started finding ways to reduce the line count. Since then, I have consistently looked for opportunities to build tools that reduce development time.

The trade-off is that I sometimes spend so much time working on the time-saving device that I start running into problems with my deadlines. Of course, one such as myself is never quite happy with the time-saving device. "I wonder if I can get it to do this." "I wish it could do that faster." "Let me see if I can use this technique I just read about."

There is a great sense of joy when you develop a time-saving device and other developers discover it and like what you've done. If you find yourself writing the same code over and over again and tweaking it only slightly, try finding a way to automate it and experience the euphoria that results when you use your automation time and time again.

Monday, March 31, 2014

Raising the Minimum Wage

One of the political issues receiving a lot of attention of late has been the minimum wage. It is hard to discuss changes in the minimum wage without also talking about the poverty line, the costs of living, and a sustainable wage.

Several of your news sites have been showing how, though the minimum wage is about five times what it was in the 1960's, it actually has less buying power than minimum wage did in the 1960's. Federal minimum wage has not kept up with inflation. Some people want to index minimum wage against inflation. As inflation reduces the value of the minimum wage, the minimum wage is increased to compensate.

I don't think this is a viable solution. This means that minimum wage will always be behind inflation and others who make more than minimum wage will start to find their incomes resembling minimum wage more and more. While minimum wage might be indexed with inflation, most people's salaries are not. According to this WorldAtWork study, cost-of-living adjustments (COLAs) are only awarded by 11% of U.S. companies. Most companies provide pay increases for exceptional work or promotions. This means that your average, "middle-class" worker will watch the value of that salary decrease because it is not being adjusted with inflation.

Another reason why indexing the minimum wage with inflation is not a viable solution is because increasing the minimum wage will help drive up inflation. The costs of so many things that we rely on to provide for our families are affected by the payroll costs of companies paying people the minimum wage. If the minimum wage goes up, the payroll costs will go up and so will the prices of many things these companies sell.

Another driving factor for inflation is interest. Banks and other lenders run on the assumption that we will always be able to generate more wealth. There is the combination of a belief that there is an infinite amount of resources and that people will be able to devise technologies to gather those resources more efficiently. With more resources being introduced into the system, more currency can be introduced to the system. Thus, the banks and lenders can charge interest and create money because the people will be able to generate the resources to pay that interest.

Deflation?

You guessed it, deflation is the opposite of inflation. Instead of the same product costing more money, now it costs less. Now your dollar can buy more food. Believe it or not, it's happened before: the late 1800's. It was bad for indebted people on a subsistence living, particularly farmers. They were producing the same amount of crop, but the crop wasn't bringing in the money to pay off their loans because the crop wasn't worth as much.

Many people currently making minimum wage are also in debt. They have car payments and credit cards. If they started getting paid less, even if it meant that they could buy more foodstuffs with that money, they still wouldn't be able to make the car payments and credit card payments.

What can we do?

I read a news story last November: Swiss head to polls to vote on salary cap for CEOs. This petition would essential index the highest salaries with the lowest salaries. That seems to be a more reasonable and effective solution to the problems affecting wage-earners in the United States because it addresses the increasing class disparity. The problem is, an effective implementation would affect the CEOs most and they have the power, whether with their own money or that of their companies, to persuade legislators to keep such a bill tabled.

In short, I don't think an increase in the minimum wage of and by itself will help the financial situation of the low wage-earners at all. I think it will pull more people into poverty. I think something else should be done to reduce the gap between low wage-earners and high wage-earners for such a wage increase to have any meaning. I think we need to find a way to bring the United States off the course towards plutocracy and back towards democracy.

Wednesday, March 26, 2014

Good Coding Practices and the Real World

I was reading a blog post by Adam Cameron, An Insight Into the Mind of a CFML Developer, and, like Adam, had some similar thoughts to what Adam and others from the development community said. The essential gist of the comment that started this was, "ColdFusion used to be such a simple language; why did you (the developers) have to make it so complicated that an amateur can't master it anymore?"

It was attractive because it was easy and easy to make a database enabled application.
ColdFusion is still an easy language to learn; that has not changed. It is easier to make a database-enabled application in ColdFusion than it is in any other server-side scripting language. I've made database-enabled applications in ASP and PHP, too; ColdFusion makes it easier to develop database-enabled applications than either of those.

I think the community has ruined CF.
Everyone is entitled to their opinion. I think that ColdFusion has improved a lot from where it was. I've worked with CF5, CFMX7, ACF9, and ACF10. With a college education primarily using C++ and field experience in C/C++ and Delphi, I watched ColdFusion as it grew. Saying that CF has been ruined is like telling someone they're ugly because they don't look like a baby anymore. ColdFusion is no longer a child. It's more of a teenager: a bit gangly, still growing into adulthood as it attempts to mimic some of the more mature languages.

Ya all want to code in java script make everything OO, put everything in a cfc.
I love the black-box effect that object-oriented programming affords. Apparently, this poster does, too, but doesn't realize it. On the one hand, the poster says that he likes how easy it is to make a database-enabled application, yet doesn't like object-oriented programming. Object-oriented programming is at the core of modern, reusable code; it allows you the developer to simplify the tasks you do all the time.
Of course, that previous paragraph is making the assumption that developers want to make things easier for themselves. I specialize in tool-building, in making it easier for my co-workers and myself to complete tasks. Some developers like "job security", though. They don't want to build on their skills because doing so raises expectations. They don't want to make it easier to do tasks because doing so raises expectations. They don't want to make it easier for others to do the task because doing so reduces demand. In maintaining low expectations, these developers have allowed themselves to remain gainfully employed while stagnating developmentally.

make a bunch of simple stuff terribly complex.
This appears to be the proof of stagnation. Any developer truly interested in growth will realize the shortcomings of his own tools. You design a tool to do the best you can possible design it to do and, down the road, realize that you need it to do more or that you can make it work more efficiently. So you revisit your tool, apply lessons learned, and make it more powerful, more efficient, faster. This is as true of a developer working on his own tools as one who writes an IDE. C++ as a language has not changed significantly in the past few decades, but the compilers and libraries available for it have changed dramatically.
Phone gap mobile apps just add to that.
A ColdFusion developer is not required to build websites that double as mobile applications. With all the programming experience that I have, I still haven't written mobile applications or responsive websites. I have not been required to do so to this point. Would I like to? Yes! Am I terrified of it? To a certain extent. Why? Because I haven't done it yet. Treading into unfamiliar territory can be daunting, but it's the recluse who never steps out of his comfort zone because he's confronted with the vastness of the outside world.

CF should be simple, auto generate everything, and make all the jquery bs and the ajax that goes with it be behind the scenes.
Again, the disconnect between wanting a language that's easy to use and not wanting something that's object-oriented. ColdFusion does offer this. Compared to other languages, ColdFusion makes it super simple to make AJAX-enabled applications. You can generate an AJAX-enabled webpage without writing WSDL or any JavaScript using ColdFusion because of ColdFusion's UI tags. If the programming community is disgruntled with the quality of ColdFusion's implementation of these UI tags, the programming community has the same right to free speech that you have; if you don't want to hear it, you don't have to.

CF was once easy and simple and I could hire an 8th graded to code it, and it worked great.

ColdFusion is still easy. ColdFusion is still simple. You can still hire an eighth-grader to code in it and they would probably do a better job of it. Why? Eighth-graders are still adventurous. Got a problem with your computer? Consult your nearest ten-year-old. They're not bound by the fences that most adults have built for themselves: "I don't understand this new-fangled technology." "I don't think it can do that." "I've tried going in there and I just can't understand it." "People will think I'm stupid if they see me reading the manual."

Let me put this a different way. When I first started with ColdFusion, I found the ColdFusion UI tags and used them. I liked how they simplified things. Then I wanted them to do something more or do something a little different. They disappointed. I ended up writing my own custom tags to simplify display, grouping, and aggregation of data in a grid. I wrote my own tab control and then revisited it to utilize the jQuery UI Tabs widget. I wrote my own custom tag to handle pagination. I started using the jQuery UI Dialog widget. I started with the ColdFusion UI tags and migrated as more was required.

I have my qualms with ColdFusion and I'm not afraid to say that. I do take issue with developers who have lost the desire to continue improving themselves. I hope that such developers do not become the educators of future developers.

Saturday, March 15, 2014

Does it matter?

Warning: The contents of this blog post contain religious comments, so it may offend some readers.

My religious beliefs would be classified by many people as "fundamental Christianity", thereby labeling me as a Fundamentalist. Much of the theology claims to be based on the Bible, but I will admit that I find parts of the theology simply to be rejection of beliefs commonly held by Protestant Christians, Catholic Christians, or both. Sometimes, these portions of our theology can best be recognized by the visceral reactions Fundamentalists have to the conflicting theologies commonly held by Protestants and Catholics.

When did Christ die?

Specifically, the Protestants and Catholics both believe that Jesus Christ was crucified on Friday, thus Good Friday. Partly to reject this belief and partly to line up the sign of Jonah, that Jesus would be "three days and three nights in the heart of the earth", Fundamentalists generally believe that Christ was actually crucified on Wednesday or Thursday.

Did Christ die on Friday?

The Protestants and Catholics believe that Christ died on Friday. This is supported by the use of the Greek word παρασκευη (pa-ra-skew-ay), translated "preparation", in all four gospels. The word is used today to mean Friday, though that definition was apparently introduced to Greek after Christ's death. Also, Mark uses the word προσαββατον (pro-sab-ba-ton), translated "[the day] before Sabbath", in reference to the day when Christ died. Luke also mentions that sabbath was starting when Christ was buried.

Did Christ die on Thursday?

Some Fundamentalists believe that Christ died on Thursday. They explain that, since Christ died on Passover, the following day was the first day of מצה (Matzah). The first and seventh days of Matzah are sabbaths and God commanded the Israelites to have a holy convocation on those days and perform no servile work. They were allowed only to do the work necessary to prepare food for themselves. Since you could call the first day of Matzah a sabbath and since John refers to this sabbath as an especially important sabbath (literally, "mega-sabbath"), then it is reasonable to say that the day prior would be called a preparation day without it being Friday. The inclusive counting employed by Jews and Greeks allows for Christ to have been buried at the end of the day Thursday and resurrected Saturday evening or early Sunday morning.

Did Christ die on Wednesday?

Some Fundamentalists believe that Christ died on Wednesday. Luke writes that the women with him (Matthew lists Mary the Magdalene and Mary, Zebedee's wife and mother of James and John; Mark lists Mary the Magdalene and Mary the mother of Joses) saw where Christ was buried, bought spices, and prepared them. Those who defend a Wednesday crucifixion postulate that the women did not have time to buy the spices and prepare them prior to the sabbath (Thursday, the first day of Matzah), so they must have bought the spices and prepared them the day following (Friday). After narrating that the women bought and prepared the spices, Luke then writes that they rested on the sabbath "in obedience to the commandment". These Fundamentalists also claim that "three days and three nights" would not be counted inclusively, but indicate that they must be counted as 72 hours, so Christ was resurrected late Saturday afternoon, 72 hours after having been buried.

Contradictions

  • Though the count is different in different gospels, the imagery of the Passover lamb being brought into the house on the tenth day of the first month prior to being killed on the fourteenth seems prophetic of Jesus' entry into Jerusalem. John's gospel includes the imagery of Palm Sunday and the count lines up with Jesus entering on the tenth (five days before Passover, counted inclusively). John mentions that Jesus had supper with Lazarus in Bethany the night before. Bethany is traditionally held to be about 1.5 miles away from Jersualem. If Jesus died on Wednesday, the tenth would have been a sabbath; the walking distance allowed on the sabbath was 2,000 ells, (about 3,000 feet). The distance to Jerusalem from Bethany would have been about 5,300 ells (about 8,000 feet). The people probably wouldn't have been welcoming Jesus with palm fronds; the rabbis would have arrested or stoned Jesus for walking too far on the sabbath.
  • Ephemeris charts indicate that it is unlikely Passover would have fallen on Thursday in any of the potential years when Christ would have died.
  • When Christ was walking with the two men from Emmaus, they said that it was the third day since the events in Jerusalem had occurred. It is unquestioned that this conversation happened on Sunday. Nothing of great significance is recorded in the Bible happening between Christ's death and Christ's resurrection. If Christ was killed on Wednesday, Sunday would have been the fifth day; if Thursday, Sunday would have been the fourth day.
  • When Christ says that he will be "in the heart of the earth three days and three nights", that is the literal translation of the phrase. However, it has another translation: "under the control of the people of the earth". This allows for the count of three days and three nights to start with Christ's arrest, not His death; if He died on Friday, then Sunday would have been the third day.
  • The Old Testament uses two different Hebrew words translated into English as "sabbath": שבת (sha-bat, shabbat) and שבתון (sha-ba-tohn, shabbaton). You'll notice the similarity between these words, that the second essentially has a suffix attached. That suffix is similar to English's "-like", as in "friendly-like" or "animal-like", thus rendering it "shabbat-like". The Old Testament only uses shabbat in reference to the weekly sabbath and only once to a holy day; it only uses shabbaton in reference to the holy days. No work at all is allowed on a shabbat while no servile work is allowed on a shabbaton except that required to prepare food. A fast is ordered for Yom Kippur, no food is eaten that day, and it is the only holy day referred to as shabbat in the Old Testament. Similarly, the Greek word σαββατον outside of the gospels only refers to a week or the weekly sabbath; why should it be different here?
  • The Sunday of Christ's resurrection was also the day when the wave sheaf offering was presented. According to the Talmud, the wave sheaf was traditionally gathered at dusk the previous evening. This means that the wave sheaf would have been gathered at dusk immediately following the sabbath and the type of Christ as the wave sheaf offering strongly suggests that He would have been resurrected at dusk immediately following sabbath.
  • John indicates that Nicodemus was able to prepare seventy pounds of spices before burying Christ. Nicodemus was rich; the women would not have been preparing nearly this amount. If Nicodemus could do it, wouldn't it be plausible for the women to have bought and prepared their spices the same day and waited until after the sabbath to take them to the tomb?

When did God speak the Ten Commandments?

Another name for the Ten Commandments is the Decalogue, the "Ten Words". This alternate word lines up more closely with the term the Jews use, which translates as the "Ten Sayings". Just as Fundamentalists have been arguing about which day of the week Christ was killed, so Jews argued about which day of the week the Israelites fled Egypt and which day of the week God spoke the Decalogue. Here's a summary of material from the Talmud.

The rabbis say that Revelation, God speaking the Ten Sayings, occurred on the sixth of Sivan; Rabbi Jose says it was the seventh of Sivan. Everybody agrees that the Israelites arrived in the wilderness of Sinai on the first of Sivan and that Revelation was a sabbath.

Rabbi Jose says that the first of Sivan fell on Sunday, but the rabbis say it fell on Monday. The rabbis say there were only two days of purification; Rabbi Jose says, "Moses added a third day on his own authority." It also says that the third day of the week was the third day of the month; this seems to agree with Rabbi Jose.

The rabbis teach that the firstborn of Egypt were killed on Wednesday night, the first day of Matzah was Thursday, so the first of Iyar (the second month) was a sabbath and the first of Sivan (the third month) was Sunday. Oh, wait… the first of Sivan must have been Monday, so Iyar was full (30 days long), not defective (29 days long). But if Iyar was defective, then the first of Sivan was Sunday and Rabbi Jose is correct.

But the tabernacle was raised on the first day of the first month of the second year, which was also the first day of the week (Sunday). Rabbi Jose would say that there were seven defective months in that first year, but that isn't plausible; even more so, the rabbis would say that there were eight defective months in that first year. Tradition teaches that the fifteenth of Nisan (the first day of Matzah) fell on Friday, so the first of Iyar fell on Sunday and the first of Sivan fell on Monday. That works out for the rabbis.

You can see that this controversy over days of the week is nothing new to Fundamental Christianity.

Does it matter?

Everyone has their opinion and, because many of the facts are missing, ambiguous, or unsupported, everyone is able to build up a set of arguments to prove their point. However much you might present a different set of information or a different interpretation of the information available, you will not convince someone already convinced of a particular viewpoint. "A man convinced against his will is of the same opinion still."

So here is the question: Does it matter? Does it matter which day of the week Christ died on? Does it matter which day of the week the Israelites left Egypt? Does it matter which day of the week the first of Sivan fell during the first year of the exodus?

Have you drawn lines in the sand? As I look to see what lines I may have drawn in the sand, I suggest you look at those you've drawn. Which ones make sense? Which ones did I draw to retaliate?