The Daily Parker

Politics, Weather, Photography, and the Dog

Two years for law school

Former law professor Barack Obama makes the case:

“This is probably controversial to say, but what the heck, I’m in my second term so I can say it,” Obama said during a stop at the State University of New York at Binghamton. “I believe, for example, that law schools would probably be wise to think about being two years instead of three years because [….] in the first two years young people are learning in the classroom.”

In the third year, he said, “they’d be better off clerking or practicing in a firm, even if they weren’t getting paid that much. But that step alone would reduce the cost for the student.”

He continued: “Now, the question is, ‘Can law schools maintain quality and keep good professors and sustain themselves without that third year?’ My suspicion is, is that if they thought creatively about it, they probably could.”

The remarks apparently were made off-the-cuff, and no further details were available from the White House. But experts said the notion – although not new itself, as American law schools were two-year endeavors through the 19th century – is gaining traction.

Wow, I wish there had been a two-year plan when I was a law student. For one thing, 1998 would have been a lot more fun for me. I found some of my third-year courses interesting, and in a couple of cases (Wills, Copyright) genuinely useful. But I'd already decided by third year that I had no intention of practicing.

If I'd actually wanted to practice law after earning my JD, then my third year would have been worse than useless. I may have made other choices—clinics instead of content courses, for example—but I'd still have spent a lot of money without gaining a lot of practical experience.

Hanselman's Azure Glossary for the Confused

Microsoft's Scott Hanselman has published one:

IAAS

Infrastructure as a Service. This means, I want the computers in my closet to go away. All that infrastructure, boxes, network switches, even software licenses are a headache. I want to put them somewhere where I can't see them (we'll call it, The Cloud) and I'll pay pennies an hours. Worst case, it costs me about the same but it's less trouble. Best case, it can scale (get bigger) if some company gets popular and it will cost less than it does now.

IAAS is Virtual Machines, Networking and Storage in the cloud. Software you wrote that runs locally now will run the same up there. If you want to scale it, you'll usually scale up.

PAAS

Platform as a Service. This means Web Servers in the cloud, SQL Servers in the cloud, and more. If you like Ruby on Rails, for example, you might write software against Engine Yard's platform and run it on Azure. Or you might write iOS apps and have them talk to back end Mobile Services. Those services are your platform and will scale as you grow. Platform as a service usually hides the underlying OS from you. Lower level infrastructure and networking, load balancing and some aspects of security is abstracted away.

If you're interested in Cloud or Azure development, or you want to understand more about what I do for a living, take a look.

Got some exercise, anyway

After lunch I thought Parker and I could pop around to my second-favorite bar in Chicago, Bucktown Pub, which is about 3 km away. It's a little warm (31°C), so by the time we got there, I was looking forward to cooling off with air conditioning and a gin & tonic.

We left home around 1:15 and got there at 2.

They open at 3.

Oops.

I will now take a shower, and Parker has installed himself directly below the air conditioner.

Git is not Mercurial

I'm pulling the public repository for Orchard again, because I made a mistake with Git that I can't seem to undo. I've set up my environment to have a copy of the public repository, and then a working repository cloned from it. This allows me to try things out on my own machine, in private branches, while still pulling the public bits without the need to merge them into my working copy.

Orchard, which will soon (I hope) replace dasBlog as this blog's platform, recently switched from Mercurial to Git, to which led to this problem.

I may simply not have grasped all the nuances of Git. Git is extremely powerful, in the sense that it will do almost anything you tell it to do, without regard for the consequences. It reflects the ethos of the C++ programming language, which gave everyday programmers ways to screw up previously only available to experts.

My specific screw-up was that I accidentally attempted to push my local changes back to my copy of the Public repository. I had added about six changesets, which I couldn't extract from my copy of public no matter what I tried.

So, while writing this, I just pulled a clean copy of public, checked out the two branches I wanted (1.1 and fw45, for those keeping score at home), and merged with my existing changes.

Now I get to debug that mess...and I may toss it and start over.

Configuring FTP on a moved Azure VM

A couple weeks back I moved an Azure Virtual Machine from one subscription to another. Since then, I haven't been able to connect to the FTP sites that were running on it. I finally spent some time today to figure out why.

First, I forgot to change the FTP firewall support in IIS. The IP address of the VM changed, so I needed to update the VM's external IP address here:

Then, I had to change the FTP firewall support for the FTP site itself. (It looks the same, just on the FTP site instead of on the IIS root node.)

Ronald Door has a good walk-through of how to set this up for the first time on a new VM. The problem is, I'd already set it up on the VM, so I thought that I only had to make the configuration changes I've just described.

Flash forward an hour and a lot of swearing later, and I realized one more problem. See, I set up the VM endpoints through the Azure portal when I launched the VM in the new subscription. However, it looks like I configured them incorrectly. And Microsoft updated the portal last week.

I finally decided simply to delete all four FTP endpoints (port 20 and 21 plus my two passive data return ports) and rebuild them. Endpoint setup is on the Endpoints tab of the Virtual Machine cloud service item:

That worked. The FTP spice flows fine now.

I'm troubled that I don't know exactly why it worked, though. The only difference between the current and previous setup is that before, I inadvertently created load-balanced sets for the ports. Since I only have one VM, that may have been my error.

Learning languages es dificíl

The Atlantic's Ta-Nehisi Coates is learning French:

[T]there's no getting away from the basic feeling of complete idiocy. You are aware of being spoken to as though you were a three-year old, even though you have all the pride of an adult. Worse, if you are like me--a monolingual American in a class where virtually everyone speaks a second language and is now working on their third or fourth--you will be the slowest person. When it comes to comprehension. the Spanish and the Italians are going to just destroy you. They simply have an easier time learning to hear the language than you. This is a gift and curse. Many of the Spanish-speaking students have a much harder time learning the accent. It's as if the closeness of the two languages makes it harder--"parce que" must be be "par-ser-kay" and they will have it no other way.

The hardest thing about learning a language is that, at its core, it is black magic. No one can tell you when, where or how you will crossover--some people will even tell you that no such crossover exists. The only answer is to put one foot in front of the other, to keep walking, to understand that the way is up. The only answer is a resource which many of us have long ago discarded. C'est à dire, faith.

I've recently had the opportunity—requirement, actually—to hold conversations in Spanish, a language I have (in theory) spoken since childhood. Nothing has frustrated me more in the past two weeks than trying to express college-level concepts using my first-grade vocabulary. I also have the horrible habit shared by most Americans: I care too much about the grammar, which makes me stop and re-work what I'm trying to say. In reality, communication may not require remembering exactly how to conjugate an -ar verb in the past subjunctive (e.g., I would have conjugated it if I'd remembered how).

TNC's entire post is worth a read if you've ever tried to do this.

States change their minds about USA/AMR merger

Last week the Justice Department and several states, including Texas and Florida, sued to stop the American—US Airways merger. Today a couple of them realized their error:

Political and business officials in Florida, Texas and North Carolina are asking the U.S. to reconsider its suit to block the proposed merger of American Airlines and U.S. Airways, saying the combined company would benefit their local economies.

Florida, Texas and North Carolina...are home to large hubs for both airlines.

American Airlines, which sought Chapter 11 protection in late 2011, is one of the largest private employers in Miami-Dade County. The carrier operates around 70 percent of the flights at the Miami airport, making it a dominant hub for flights to and from Latin America. Local officials have long promoted Miami as the “Gateway to the Americas.”

Yeah, I didn't understand that four of the six states who joined the Justice Department suits (these three plus Arizona) contain four of the five largest hubs of the two airlines—including the airlines' headquarters (American in Texas and US Airways in Arizona).

Even though I thought there would be a challenge to the merger, after I thought about how the challenge actually went down, it didn't make any sense. Obviously the people who depend on American and US Airways for their livelihoods agree.

Bike-sharing NIMBYs

Chicago has recently rolled out a several hundred DIVVY bike sharing stations, similar to the Citi Bike scheme in New York. For a small annual fee, or a moderate per-hour charge, you can take a bike from any DIVVY bike station and ride it to any other station within two hours. (The two-hour time limit keeps the bikes in circulation.) The city has a hundred or so stations now, with a couple thousand bikes.

Of course, not everyone is happy about the bikes, which help cut pollution, reduce traffic and noise, and are greenhouse-negative. A three-unit condo association near Wrigley Field sued the city yesterday because they don't want Those People on their block:

David Kolin and his wife, Jeannine Cordero, learned Tuesday that the area in front of their North Side condo building soon would be home to a Divvy bike-sharing station, one of hundreds the Chicago Department of Transportation is installing across the city.

"We don't think it's appropriate in a residential area to have this thing set up," said Kolin, an attorney. "It's not a very attractive thing to have. It's led to crowds already."

"It's hideous," added Cordero, also a lawyer. "It's less than 20 steps from our front door."

"We are aware of the request from a few residents to relocate the Divvy station away from their building on Pine Grove Avenue near Addison Street," CDOT spokesman Pete Scales said in a statement. "This residential street location was determined to be the safest for customers near the busy intersection of Addison and Lake Shore Drive. It is located in the public way, close to the curb on the street, and not on any private property."

It would have to be a pair of attorneys, wouldn't it? You don't like the bike rack on the city street in front of your house...why?

All I can say is, Mr Kolin and Ms Cordero: STFU.

Integrating Multiple CRMs with One Azure Cloud Service

(This is cross-posted with the 10th Magnitude Tech Blog.)

Part 1: The Challenge

We developed efox, a Microsoft Windows Azure PaaS application, for our customer Holden International over the course of the last year. Our biggest challenge in the first release was to integrate their flagship sales training application, efox, with SalesForce. But from the beginning of the SalesForce integration effort, we had a constraint we couldn’t ignore: Not only would efox have to integrate with SalesForce, but it would also have to integrate with Oracle Siebel CRM, Microsoft Dynamics, and whatever other CRM application Holden’s customers want to throw at it.

At first glance it looks like a simple problem. Lots of applications, after all, integrate with CRMs. There are also lots of tools to help: SalesForce has a decent SDK, Microsoft has Windows Identity Foundation, most providers (including SalesForce) support OAuth...been there, coded that.

In a typical integration, the custom application extends the service provider’s application. For example, SalesForce has tools to create custom SalesForce extensions that extend SalesForce functionality. An application can run as a SalesForce user and share data with SalesForce transparently, using OAuth and the SalesForce REST API. This is, in fact, how the previous version of efox worked.

efox inverts the problem. Yes, it’s easy to integrate an application with one CRM; but it’s hard to integrate with all of them—simultaneously. At any moment, efox could have several hundred concurrent users going to half a dozen different CRM systems. The application therefore needs to treat each user’s session and each CRM request as a discrete unit.

In this and two succeeding posts, I’ll outline how we solved the architectural problem of separating the UI and back end to abstract away the specific CRM implementation from everything else; how we use ASP.NET MVC 4 routing to let people click a button in their CRM system to launch efox; and how we added single sign-on (SSO) using SAML to allow each user SSO access to efox—or not.

Part 2: The Architectural Solution

Before trying to implement an solution, we first designed the application to handle any arbitrary CRM integration we cared about.

First we created an interface, ICrmIntegration, that exposes these basic operations:

IEnumerable<Account> Accounts(Guid userId);
IEnumerable<Contact> Contacts(int accountId);
SalesPlan GetSalesPlan(string crmOpportunityId, Guid userId);
CrmLoginResult Login(string userName, string password, out string message);
IEnumerable<Opportunity> Opportunities(int accountId);
void Save(SalesPlan salesPlan);

The application uses Factory classes to retrieve objects from the database. We created new Integrated_Factory classes (like IntegratedSalesPlanFactory) that are aware of CRM integration classes and aware of the concrete Factories. Instead of calling the concrete factories, the UI now calls the Integrated factories, which decide whether to retrieve objects from the database or from the user’s ICrmIntegration.

This design completely abstracts the concrete CRM integrations away from the application’s UI. A controller class needing to retrieve a list of Account objects for the user calls IntegratedAccountFactory.Find(userId). That method calls the IntegrationFactory to get the user’s CRM integration (an ICrmIntegration implementation). If IntegrationFactory returns null, meaning the user isn’t integrated with a CRM system, then the IntegratedAccountFactory calls the regular AccountFactory instead. Otherwise it calls the Accounts method on the integration object to retrieve the list of accounts from the user’s CRM system.

Here’s the code in IntegratedAccountFactory:

public static IEnumerable<Account> Find(Guid userId)
{
	var tenantId = AccountFactory.TenantId(userId);
	if (!tenantId.HasValue) return AccountFactory.All(userId);

	var integration = IntegrationFactory.Instance.Find(tenantId.Value, userId);

	return (null == integration) ?
		AccountFactory.All(userId) :
		integration.Accounts(userId);
}

The UI neither knows nor cares whether the particular user gets her accounts from efox, from SalesForce, or from a squirrel; all it cares about is getting a list of accounts. In a sense, this is a classic bridge pattern.

I'll have a couple more posts on efox's CRM integration over the next few weeks. Next up, I'll talk about how CRM integration looks to the end user, then after that, about how we integrated single sign-on (SSO) with multiple identity providers. Check back in a week or so for Part 3.