Tuesday, September 30, 2008

Initial Microsoft Live Mesh Musings

I just started using Microsoft Live Mesh after hearing about it from Joe Shirey.  For those not familiar with Live Mesh, you can read more here, here, and here.

I have to say that overall I am very impressed with the promise of these services from Microsoft.

That said, the user experience leaves something to be desired.  I will do a more thorough review once I have been using it for a few months to give people a better feel for what Mesh is doing.  I also hope to have some time to be able to play with the Developer SDK, but that is probably wishful thinking =]

I am using Vista with UAC and Microsoft One Care.  Here are the few issues that I ran into when installing and synchronizing my first folder:

Installation

  • I had to turn off my Microsoft One Care firewall as the firewall wasn't allowing Mesh to install properly.  I even tried to allow the application access to the Internet, but the initial wait time for the firewall dialog and the UAC killed the installer even when I tried to run it again.  Tried this a couple times.  Had to just turn off the firewall and then re-run the installer.
  • Mesh takes forever to start up immediately after installing.  I have a reasonably fast machine and it took a few minutes, so I wasn't sure if the installation was successful or if the firewall had screwed things up.  A dialog letting me know that it would take a while would be nice.  Microsoft is generally good about these things, so I imagine this level of usability is at the end of the list of things to do.

General Usability

  • There are few/no cancel buttons on some of the dialogs.  I just had to wait for the web operation to time out (which took like a minute or two).  I had a modal dialog on my screen with no way to do anything to it.
  • Mesh takes a while to get going.  Again, more feedback would be nice.
  • Mesh doesn't provide detailed messages in terms of what has been synchronized.  It just tells you X folders and Y files were uploaded.  A little more detail (although hidden from the default UI) would be nice.

Overall, I think this technology has great promise, and I look forward to other good software+ services from Microsoft (the Microsoft marketing people are in my head and I can't get them out!).

 |  Fernando Cardenas  |  #    |  Comments [2]  | 
 Tuesday, September 23, 2008

What is Software Architecture?

I was in a meeting with the AppVenture development team, and we sought to answer this question so that we could build a tool to help software architects design and communicate architectures. 

We needed to define architecture so that we could determine what needed to be communicated.  So using Single Responsibility and the Separation of Concerns principles as our guide for architectural layers, we defined architecture as all the software layers and the way those layers interact in terms of dependencies.  One interesting finding is that our notion of architecture uses a composite pattern. 

This leaves us with a simple conceptual model:

Architecture

Figure 1. The conceptual model for architecture.

 

Using this simple conceptual model as our guide, we could create this simple architecture:

SampleArchitecture

Figure 2. The AppVenture Simple Architecture (ASA)

 

Let's call this architecture the AppVenture Simple Architecture (ASA). So in this architecture, we have three architectural layers (this is probably the simplest architecture I can think of): a UI architectural layer, a Domain architectural layer, and a Repository architectural layer.  In the ASA, the UI layer would probably have a sub-architecture (which is of type Architecture) that has a different manifestation for each UI technology.  This UI sub-architecture would have another model that could resemble this for an ASP.NET Web Application:

UIArchitecture

Figure 3. The UI sub-architecture for an ASP.NET Web Application.

 

In this instance, the UI Architectural Layer has a sub-architecture (shown in Figure 3) that contains three architectural layers: a Master Page architecture layer, an Aspx Page architectural layer, and an Ascx User Control architectural layer.  One interesting thing to note here is that in Figure 3, the Ascx User Control architectural layer depends on the Domain architectural layer from the ASA architecture (Figure 2).  That dependency exists in these models to illustrate that in this architecture, the Aspx pages do not contain any dependencies to the Domain.  What this design decision means is that Aspx pages are simply containers for Ascx user controls.

I would love to hear your thoughts on this model and see which architectures do _not_ fit into this model.

 |  Fernando Cardenas  |  #    |  Comments [3]  | 
 Thursday, August 28, 2008

AppGen and the Speed of Change in Business

In a previous post, I talked about the AppGen Revolution, and now I want to talk about how fast the business changes its mind and how AppGen aligns itself nicely with the needs of the business and the developer.

But first: why should we care that our development aligns itself with the needs of the business?  At the end of the day we developers/architects get paid when the company for which we work makes money (or saves money – but I prefer to think of the glass as half-full  =P). 

Businesses make money when we build the right application and bring it to a receptive marketplace.  The last statement cannot be overemphasized.  Notice there is not a single mention of technology or architecture.  Can we use terrible technology and/or an ailing architecture and still make money?  Maybe.  Depends on the marketplace.  We have all seen technically inferior products reign supreme and superior products die.  The market is truly a strange and whimsical place.

You may be thinking: as a developer it is hard it is to deal with the way businesses operate.  The only constant in this world is change.  Changing requirements, changing their minds about the way things should work once they see the way the software was built, changing deadlines, changing colors, sizes and shapes of buttons  =]  So we try to build the software to adapt to those changes in a manageable way.  We may even create new development methodologies and notions (XP, Crystal Clear, Scrum, TDD, BDD, etc.) to help manage this change in new ways.

This area is where AppGen fits.  By being able to 1) model a business domain, 2) model the user interface in a technology-agnostic way, and then 3) generate working applications to get feedback from users in a matter of hours is truly revolutionary.  I believe that the reason Agile methodologies all work so well is that they are meant to focus on delivering working software.  AppGen always delivers working software and does it in the most rapid way possible.

 |  Fernando Cardenas  |  #    |  Comments [4]  | 
 Wednesday, August 27, 2008

Review: Microsoft Windows Live OneCare

Overall: 4 out of 5

Highs: protects 3 computers, great price, low resource utilization

Lows: VPN configuration required, requires Auto Updates to be installed automatically or goes red

When I upgraded to Vista, I was looking to find a product for a fancy firewall (my favorite firewall company was purchased and their product has taken a wrong turn) and an anti-virus that didn't use too many resources (tried a few and they were too invasive).  Enter Microsoft Windows Live OneCare.  I tried the demo and once it expired, I immediately purchased the product.  It just sits there and does its job quietly and uses a minimal amount of system resources.  I like it because I rarely notice it and it gives me quite a few firewall options.  Did I mention that my subscription covers three (3) computers?  Pretty cool.  However, there is always room for improvement.  Here are a few suggestions:

  1. If a network zone is set as "Home or Work," the firewall should allow VPN connections.  By default, the firewall doesn't allow this, so you have to change it on every computer.  Not sure what the security issue is to not allow outbound VPN traffic, but I assume that there is some security best practice of which I am unaware.
  2. If I don't want to automatically install updates, OneCare goes red and constantly reminds me that I am unprotected.  That is fine; I just wish that I could turn off that message and make it green/orange again since I want to know what is getting installed before it gets installed.  For now I just install everything that is critical and hope my machine doesn't get hosed.  Which reminds me...  I better get that backup working sooner rather than later.

Overall a great product.  I will gladly continue my subscription until something much better comes across my desktop.

 |  Fernando Cardenas  |  #    |  Comments [5]  | 
 Thursday, August 14, 2008

The AppGen (Application Generation) Revolution

The newest/greatest improvement in software development is AppGen.  In large applications, it can decrease your development effort by weeks or months and increase code quality, all the while maintaining the flexibility of architecture and coding standards you require.

AppGen is short for Application Generation.  And like the name implies, it is a method for modeling and generating entire applications from models.  These models can be graphical or textual or both.  There are tools out there that generate apps out of the box, or you can roll your own AppGen using by combining existing technologies (code generation, UML, MDA, DSL, and other TLAs in one or more combinations).  Most approaches generate 80-90% of an application’s code, and then a developer adds custom logic after generation.  Some try and generate all the code.

AppGen works great for large projects and small projects. On big projects you can create tens or hundreds of functioning screens, the entire data layer, and tens of thousands of lines of code in less than a week.  On small projects, you can go from design to deployment in hours.  We were able to model, generate, and integrate production-ready code from Foundations (our AppGen offering) into the e-commerce portion of our website in only 3 hours.  It took longer to properly install the SSL certification path on our website than to do the custom e-commerce code (that could be because I am an IT hack, but still).

If you aren’t using AppGen in your development process, you should go and figure out if AppGen is right for you. 

[You should ask your doctor first about using AppGen. AppGen is not for everyone and can cause increased levels of free time, general happiness and Halo 3 scores.  Make sure to see a project manager if your happiness or free-time continues for more than 4 hours.]

There are plenty of great AppGen tools out there.  Probably one of them can help you.  We recently publically released our first version (plus some updates) and are excited about the future of our tools and AppGen in general.  Take a look at our video demo to AppGen in action.  If you aren’t sure about how effective AppGen is or the quality of code that gets generated, download the sample code for an app that was created in less than one hour.

This post is the first of many on AppGen and how to increase developer/architect success on software projects, and I hope to speak with you soon about AppGen and its practical application.  Drop me an email or post a comment and tell me what you think!

P.S. – I checked on Wikipedia, and AppGen redirects to IDE.  To put it simply, I think that AppGen is the next generation of IDEs, and many of us will start using AppGen tools as pre-processors to our IDEs until AppGen gets integrated in.

 |  Fernando Cardenas  |  #    |  Comments [2]  | 
 Monday, November 19, 2007

Synchronizing Contacts in Outlook 2003 using an Add-in

Suppose, for a moment, that your company has a public Outlook folder that contains a bunch of contacts, and you want to synchronize your local contacts folder with this public folder, maybe so you could conveniently synchronize your PDA as well.  But you don’t want all of the contacts in the public folder, just certain ones.  Furthermore, you want to keep this list up-to-date with a push of a button.  How would you go about it?

You might think this is a simple problem, but the particulars of your setup might require a more complex solution than you originally suspected.  In this posting, I will give some advice on completing this task and even present a useful function that isn’t normally available.

DISCLAIMER

This posting and the accompanying code within are presented in the hope that they may be useful, but WITHOUT ANY WARRANTY.  AppVenture, Inc. is not liable for any results of using this code, especially if you run it, without testing, on a production system.

The Setup

Let’s describe the specifics of our situation before we get started.  Mail is accessed from an Exchange server through Outlook 2003.  The Exchange server contains a public folder (called “ContactFolderName”) that contains Contacts.  A user may mark certain contacts for synchronization; this is stored in the “Categories” field as a list of comma-separated usernames, one for each interested user.  Contacts also contain an ID, stored in the field User4. Why User4?  It’s unobtrusive and unlikely to already be used—but if it is being used for something else, pick another field.

Most users have only create, read and update permissions on this folder – no delete.  Administrators, however, will also be using this program, so we must act as if the user does have delete permission.

Our objective is to write a plugin that finds the marked contacts and copies them to our local contacts folder, updating them if they were already present.  We must avoid duplicates everywhere and must never delete from the public folder.

Our development environment is Visual Studio 2005, using Visual Basic and the Visual Studio Tools for Office (VSTO). 

Creating an Outlook Addin

This posting won’t address how to create an addin for Outlook because there are plenty of articles that address just that. (See http://support.microsoft.com/?kbid=302901 ).  It assumes that you have already created the infrastructure needed, i.e., there is a button that, when clicked, calls btnLaunch_Click (below).

Finding the desired contacts

Before we can copy any contacts, we have to find the ones we’re interested in, and before we can do that, we have to get their folder.  Fortunately, getting the folder is easy, because we know right where it is: \\Public Folders\All Public Folders\ContactFolderName . So, first we get the namespace, and then we create the publicFolder variable as a MAPIFolder, and get the public contact folder from the namespace (with a little error handling just in case).

Next, we have to look through the folder to find the items we want.  There are several ways of doing this.  We could loop through every item in the folder, but that’s expensive and slow when there are thousands of contacts in the folder.  We could use a Find, but find can’t perform ‘like’ searches, meaning we’d still have to iterate through a bunch of items.

Instead, we’re going to get a little more complex, and create an AdvancedSearch (see http://msdn2.microsoft.com/en-us/library/aa220071(office.11).aspx ).  Getting the path is easy – just ask the folder for it, and don’t forget the single quotes! – but determining the field for the filter can be much harder because the schema is pretty large, and not all the names in the schema correspond to ContactItem property names.  Fortunately, there’s an easy way to determine what to use.  Start up Outlook and go to any folder.  Right-click on the background of the folder and choose “Filter…”.  Go to the ‘Advanced’ tab and choose the field you want; in our case, “All Contact Fields” -> “Categories”.  Then, choose your criterion (“contains”), fill in the value and hit ‘Add to List’.  Next, click on the “SQL” tab and then check “Edit these criteria directly.”  There it is!  Copy this straight into the code and replace the value as above in the code, and pay attention to the quotation marks. (You can close Outlook now).

Public Sub btnLaunch_Click(ByVal Ctrl As CommandBarButton, ByRef CancelDefault As Boolean) Handles btnLaunch.Click

Dim namespace As Microsoft.Office.Interop.Outlook.NameSpace

namespace = applicationObject.Session

Dim publicFolder As MAPIFolder = Nothing


Try
publicFolder = namespace.Folders("Public Folders").Folders("All Public Folders").Folders("ContactFolderName")
Catch ex As COMException
MessageBox.Show("Unable to find Contact folder", "Missing Folder", MessageBoxButtons.OK, MessageBoxIcon.Error)
Throw ex
End Try


Dim filter As String = """urn:schemas-microsoft-com:office:office#Keywords"" LIKE '%" + _

namespace.CurrentUser.Name + "%'"


Dim search As Search = applicationObject.AdvancedSearch("'" + publicFolder.FolderPath + "'", filter)

End Sub

Retrieving the Search Results

All well and good, you say.  But our previous function ended a bit abruptly, and we haven’t accomplished our goal yet!  Fear not, for now it is time to ProcessSearchResults.

We ended our btnLaunch_Click function seemingly prematurely for a very good reason: to give the AdvancedSearch time to complete.  Because AdvancedSearches run in the background, if we had tried to get the results right away, we might have missed some, or even gotten none at all!  Fortunately, AdvancedSearch fires an event when it’s finished: AdvancedSearchComplete, so all we have to do is have our ProcessSearchResults function handle it, and our addin will proceed when it’s done.

NOTE: Other addins or even the user could run AdvancedSearches that would cause ProcessSearchResults to execute, so you should use a tag – which this code does not – to ensure you’re getting the right search back.  See the link on AdvancedSearch above for more information.

We again get ahold of the namespace and then we ask for the results of the search. Then, we find our destination folder (our local contacts folder, in this case) and use ClearContactsFromFolder to delete the old contacts from it.  We ensure that it’s only the public folder contacts by checking to see if the contact has a non-empty User4 field.

Private Sub ProcessSearchResults(ByVal SearchObject As Microsoft.Office.Interop.Outlook.Search) Handles applicationObject.AdvancedSearchComplete

namespace = applicationObject.Session

Dim searchResults As Results = SearchObject.Results
Dim contactsFolder As MAPIFolder = namespace.Folders("Mailbox - " + _namespace.CurrentUser.Name).Folders("Contacts")

ClearContactsFromFolder(contactsFolder)

CopyContactsToFolder(searchResults, contactsFolder)

While Marshal.ReleaseComObject(SearchObject) > 0

End While

SearchObject = Nothing

MessageBox.Show("Contacts Synchronized!")
End Sub

Public Sub ClearContactsFromFolder(ByRef folder As MAPIFolder)

Dim itemInFolder As Object = Nothing

For Each itemInFolder In folder.Items
Try
If Not itemInFolder Is Nothing Then
Dim itemclass As OlObjectClass
itemclass = CType(itemInFolder.class, OlObjectClass)
If itemclass = OlObjectClass.olContact Then
Dim newOlContactItem As ContactItem = CType(itemInFolder, ContactItem)

If Not newOlContactItem.User4 Is Nothing And Not newOlContactItem.User4 = String.Empty Then
newOlContactItem.Delete()
End If
End If
End If
Catch
End Try
Next
End Sub

Then, we copy the contacts to our destination folder using CopyContactsToFolder (see below for code and discussion) and notify the user that we’re done!

Copying contacts is a pain when accessing Outlook programmatically.  For some reason, although ContactItem has a Copy function, it only copies to the same folder.  Now, if we had full permissions on the public folder, this could work, because we could create a copy of the ContactItem and then Move it to our desired folder.  Unfortunately, a Move is a copy followed by a delete, but we don’t have delete permissions on this folder in all cases! 

Strangely, and don’t try this at home, a Move that fails due to delete permissions results in a folder-to-folder copy!  Why not use that?  Two reasons: first, some users will have permission to delete, and we don’t want to remove things from the public folder, and second, although we could perform another copy-and-move if we detected that the user had delete permissions, this is trouble just waiting for a network outage.

So, what is the solution?  Create a new ContactItem in a folder the user controls (their default contacts folder), copy all the values over, and move it to the destination folder (the same in our particular case, but it doesn’t have to be).  And that’s what CopyContactsToFolder does: it takes in a results object, goes through each one, creates a new instance, copies over all the fields, saves the new instance and moves it to the desired folder.  It’s a doozy, but it copies every ContactItem field available (and that can be assigned to) in the ContactItem interface.

A brief note on why ‘item’ is an Object and not a ContactItem: the search results that I dealt with when originally writing this addin contained items that acted like ContactItems for all intents and purposes, but couldn’t be cast into the ContactItem class.  So, they’re just plain Objects in this code; if you’re certain that all your results will be ContactItems, feel free to change this (it will certainly get rid of a lot of warnings about late binding!).

Copying Contacts

(Download source for entire function)

Public Sub CopyContactsToFolder(ByRef contacts As Results, ByRef folder As MAPIFolder)
Dim item As Object
For Each item In contacts
Try
Dim newItem As ContactItem = _
CType(applicationObject.CreateItem(OlItemType.olContactItem), ContactItem)
newItem.Account = item.Account
newItem.Anniversary = item.Anniversary
newItem.AssistantName = item.AssistantName
.
.
.
newItem.UserCertificate = item.UserCertificate
newItem.WebPage = item.WebPage
newItem.YomiCompanyName = item.YomiCompanyName
newItem.YomiFirstName = item.YomiFirstName
newItem.YomiLastName = item.YomiLastName

newItem.Save()

If Not folder Is _namespace.GetDefaultFolder(OlDefaultFolders.olFolderContacts) Then
newItem.Move(folder)
End If

Catch
End Try
Next
End Sub

ContactSync.vb (11.15 KB)
 |  Appventure  |  #    |  Comments [1]  |