Tuesday, May 30, 2006
The world's most misunderstood programming language
I really enjoyed reading this post by Douglas Crockford, 'The world's most misunderstood programming language'. I have always dismissed JavaScript as a kind of toy language that I've more suffered than enjoyed working with. I never realised it was so powerfull, probably for all the reasons that Mr Crockford enumerates in his article. I've been very interested in object oriented programming for a long time now, but I'd never heard of stuff like 'closures', 'lamda expressions' or 'functional programming' until recently. JavaScript it turns out is like 'Lisp in C syntax' with all those cool features. I guess this is all bourne out by the current interest in AJAX and more powerfull browser based apps.
Wednesday, May 24, 2006
Making raw web service calls with the HttpWebRequest class
Sometimes it's really nice to be able to make a raw call to a web service by manaully putting together your own SOAP envelope. The System.Net.HttpWebRequest class makes it really easy. There are a number of good reasons to do this. Maybe you want to call a web service without having to create a proxy class with wsdl.exe, or maybe you want to have more control over the creation of the SOAP envelope or you don't want to have to rely on the XmlSerializer. Maybe you want to create the xml by doing xslt transforms rather than serializing a .net type.
First you need to create the envelope xml, this function takes a string of xml data as the content and inserts it into a soap envelope.
Just open your web service in IE by typing the url into the Address bar to see what the structure of the soap:Body should be.
static string _soapEnvelope =
@"<soap:Envelope
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body></soap:Body></soap:Envelope>";
private static XmlDocument CreateSoapEnvelope(string content)
{
StringBuilder sb = new StringBuilder(_soapEnvelope);
sb.Insert(sb.ToString().IndexOf("</soap:Body>"), content);
// create an empty soap envelope
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(sb.ToString());
return soapEnvelopeXml;
}
Next you create the HttpWebRequest object. The url is the url of the .aspx file and the action is your namespace plus the web method, e.g: 'mikehadlow.com/adder'.
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
Insert the envelope into the web request.
private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
Then you can call .GetResponse on the HttpWebRequest object to call the web service. You get the response back by getting the response stream with the GetResponseStream method of the webResponse object.
Here's it all put together:
static string _url = "http://mikehadlow.com/myService.asmx";
static string _action = "http://mikehadlow.com/myWebMethod";
static string _inputPath = @"C:\mike\Play\input.xml";
static string _outputPath = @"C:\mike\Play\output.xml";
static void Main(string[] args)
{
string content = File.ReadAllText(_inputPath);
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(content);
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
File.WriteAllText(_outputPath, FormatDocument(soapResult));
}
Tuesday, May 23, 2006
Intellisense isn't always right
I've found myself becoming almost too reliant on intellisense in VS2005. I almost didn't do the obvious thing today, just because intellisense didn't understand it. I wanted to increment the last two digits of a reference string. It's looks something like:
"UKDRNY500011106"
and I needed to change it to:
"UKDRNY500011107"
so I wanted to write this
return policyRef.Substring(0, 12) + (int.Parse(policyRef.Substring(12, 2)) + 1).ToString("00");
If you try and type that line of code into VS, when you get to the '.' before ToString, intellisense doesn't suggest 'ToString' or anything. It doesn't recognise that the expression in brackets is an integer value. But if you type it anyway, it compiles and runs just fine. The silly thing is that I almost didn't write it because intellisense didn't suggest it.
Thursday, May 04, 2006
Where do role-based security checks go in my Application?
I recently had to help a team who had problems with their role based security implementation. They weren’t sure where to locate role based security checks in their application. Their current design wasn't working. They held users, roles, use cases and method names in a database. The method names described web service methods and they mapped onto particular use cases that applied to particular roles. Each user was assigned a role. This way they could do a lookup as each method was called and find out if the logged on user was allowed to run it. If they weren't, the web service threw an exception, which the application caught and used to alert the user that they were doing something illegal. Of course, it's better to enforce role-based rules at the UI. A button that the user isn't allowed to click should be invisible to them, or disabled, rather than allowing them to click it and get an error message. To that end, the other part of their security mechanism linked use-cases to control names, so that controls could be enabled or disabled depending on whether the user belonged to a role assigned to that control's use case.
There were several problems with this model. The first and most obvious one was that there were two different mechanisms to do the same thing; the method access based checks and the control-based checks. Both enforced access rules to certain bits of functionality, but had two different implementations and two different schemas in their security database. There was ample opportunity for support people to configure conflicting rules for the UI and the web services.
The second problem, and probably a more fundamental one was the assumption that use cases mapped exactly to web service method calls. For example, my method call, 'Save Customer', would map to a particular use case. But what if one use case said that only an admin person could change a customer's credit status, while another one said that a clerical user could change a customer's address. Does it make sense in our application design to split Save Customer into several use case based calls? Probably not. There was a real danger that the security design would have driven out a very awkward physical implementation.
A further assumption was that they wouldn't have data related security requirements. For example, say that the accounts department could only update one type of customer, but another type could only be updated by the call center. The customer type is defined by a property of customer, but of course they both use the same Save Customer call. And imagine the customer types can be user defined, there's no way you can implement that with a static security model.
I think the fundamental problem with the whole approach was not seeing role based security roles for what they are: business rules. Just like a customer's credit limit, whether a user of a particular role can edit a customer is a business rule. Like all business rules in our Domain Driven application design, the role based security checks should be implemented in our Business Entities (Business Objects, or whatever you call them). If the rules are expressed as properties of our domain entities, Customer.CanEdit, for example, you can both bind them to the UI, by binding the CanEdit property to the Save button's Enabled property, and apply them at lower levels of the application architecture. You could query Customer.CanEdit in your Data Access Layer before running the customer update, or query the same property in your web service.
Putting rule based security checks in your domain objects also makes sense from the point of view of application design. Since they are business rules they sit nicely alongside the other rules that apply to a particular entity and can interact with them if need be. You can code rules that maybe intersect a user rule, a property of the entity and another entity. Best of all you can do it all in the same place.
Wednesday, April 12, 2006
How to drive on Mars
I've been geeking out today with the research channel, enjoying this excellent lecture by Mark Maimone, Exploring Mars by 4-Wheel Drive. He's a machine vision researcher on the NASA Mars Exploration Rovers project, responsible for writing the autonomous driving software that guides the rovers. It's amazing technology. It's all basically done by taking sterio pictures and then building a terrain map from them, then working out a safe path through obstacles. What a job, having your software guide a robot on another plannet. It makes writing business applications seem somewhat mundane to say the least!
Monday, April 10, 2006
Windows.Forms databinding doesn't work for domain objects.
As you can see from one of my recent posts, I'd like to use databinding in our application to bind our domain objects to our forms. It's really boring having to write lots of code to shunt domian object properties to gui control properties and back again. The data binding built in to Windows.Forms at first looks quite promissing. You can write stuff like this:
nameTextBox.Bindings.Add(new Binding("Text", myCustomer, "Name"))
... which will handle all the shunting of values to and from your domain object. The problem comes when you want to validate what the user types in. What I'd really like to do is to throw an exception from my domain object's property setter and then have some neat way of wiring it up to a Windows.Forms.ErrorProvider. Instead the data binder simply catches the exception and refuses to tab away from the control. Your user has no idea what's wrong or what they need to do to fix it.
OK, so we'll just extend the Binding class to override the bit that catches the exception. Microsoft have ruled this out by making all the internal workings of the Binding class private and there's no extensible mechanism for plugging in your own Binding implementation. There's a good post by Martin Robins on all this. I understand that the data binding has been fixed in dotnet 2.0, but we're still stuck with 1.1 here so there's nothing for it but to spin our own crappy event driven solution to notify validation exceptions.
The Research Channel
I just discovered The Research Channel. It's got loads of free video presentations of really interesting stuff. That's my evenings sorted for a while :)
Thursday, March 23, 2006
Microsoft doesn't do Encapsulation.
Microsoft has a big problem with encapsulation. It's tools don't support it, it's advice goes against it and your average VB.NET programmer has little idea what it means. I'm currently working on an enterprise application, written in VB.NET and working alongside a team of VB.NET developers. Now, back in a past life, I too was a VB developer (although with a strong interest in Java and C++) and I wrote applications around recordsets, but over the last three years, since I started doing C#, I've been infected by reading lots of Martin Fowler, Eric Evans, Rocky Lhotka and the Domain-Driven-Development agile crowd. Now I want to write Domain-Driven object-oriented applications. I've managed to steer my current team away from datasets but I just can't get them to understand why encapsulation is good and that's mainly because Microsoft don't seem to get it either. So what do I mean?
Take the XML Serializer that's used by web services. In order to serialize an object, it has to be written in a particular way. It has to have a default public constructor and all its properties have to be gettable and settable. Here's an example Person object that can be XML serialized:
class Person
{
string _name;
int _age;
public Person()
{
}
public string Name
{
get{ return _name; }
set{ _name = value; }
}
public int Age
{
get{ return _age; }
set{ _age = value; }
}
}
So what's the problem? Well, say we want to have a business rule, such as 'a person's name must be at least have at least one character. How do we enforce this? Well we can write some validation on the Name property setter:
public string Name
{
get{ return _name; }
set
{
if(value == null) throw new ArgumentNullException();
if(value.Length == 0) throw new ApplicationException("Name must be at least one character");
_name = value;
}
}
But that doesn't stop a developer writing:
Person myPerson = new Person();and never setting the Person property. Now you have an invalid person object floating around in your application. You've effectively given up the power that object oriented development gives you to create classes that enforce their rules. Business rules about a Person are now leaking into the rest of the application. Without a parameterised constructor, and read only properties, you have to start relying on convention; rules like: "you must not store a Person object to the database without first setting it's Name property". The object can't protect itself so the developer has to start remembering a ever increasing list of do's and don'ts. My mental stack usually overflows after a handfull of arbitary rules. When I suggested writing properly encapsulated business classes to my team I came up against three main sticking points: 1. You can't pass encapsualted objects over web services (our communications layer is a web service). 2. You can't use form data binding with encapsulated objects (how do you start the new Person form with a blank name?) 3. You can't restore an encapsulated object from the database. Although I can answer all three objections: 1. Web services aren't meant for internal application communication. That's what remoting is for. 2. See my ealier post on using a nested builder class to solve the form databinding issue. 3. You can use reflection to restore the internal state of an object. (Hey, but that's three times slower than a property access! Perfomance old chap!) It was a step to far. It's not the way that Microsoft suggests working in most of it's architectural publications and it's not the way that it's tools support. You tend to have to work around the default behaviour. The little that I've read about LINQ (and it is only a very little) suggests that it wont support persisting the internal state of an object either. I was very pleased to see Rocky Lhotka feels the same pain that I do. Update: I was wrong about DLinq. Of course I should have read a little more about it before commenting:) Today I read the DLinq overview. DLinq uses attributes on domain classes to specify the object relational mapping and those attributes support internal field access, so it can persist the external state of a domain object without invoking property accessor business rules. Actually reading about it made me slightly more enthusiastic. So long as they get around to implementing polymorphic types and many-to-many relationships, I could probably live with attributed domain objects, although it smells of ORMapping in the domian layer, something that I'm against, being a big fan of layered de-coupled architectures.
Tuesday, March 21, 2006
Stevey's Drunken Blog Rants
I've really been enjoying reading Steve Yegge's blog, and that's not only because it's got the word 'rant' in the title:) He's an opinionated amazon software engineer and I seem to agree with most of what he says. Although that could be because I'm easily led.
Thursday, March 16, 2006
To stored procedure or not to stored procedure?
I've just been reading this post by Frans Bouma 'Stored Procedures are bad m'kay' where he rebuts some of the usual arguments about why you should use stored procedures; security, performance, encapsulating database access. I've been doing enterprise application development with SQL Server for around ten years now and every application I've worked on we've used stored procedures. I was told that stored procedures are good on my SQL Server 6.5 course all those years ago and have never really questioned that view. And I'm not alone. Pretty much every developer I've met over the years has shared this belief that stored procedures are god's own data access tool. On my current project, any suggestion not to use them would be met with horror.
Hmm, but I'm begining to question this view, just like Frans Bouma. A couple of things are begining to sway me away from procs. Firstly, Frans makes a good case for rebufing the security and performance concerns, but I think more importantly there is the shift of emphasis in application development away from the relational data model towards the object oriented domain model. This shift is much more advanced in the Java world than it is the Microsoft camp, but us lot are begining to listen to the Java people. If you start to believe that the database should be merely a data persistence tool then the whole API argument with lots of business logic in the procs starts to look less viable. Instead the Elephant in the room these days is the often quoted 'object relational impedence missmatch'. Maintaining all that data access code and all those CRUD stored procedures becomes a major headache. On my current project I've mitigated this to a certain extent by building a code generator that builds all our CRUD procedures and .net wrapper code for us (probably re-inventing the wheel to a certain extent, now that I've discovered Code Smith) but it's still a headache. I haven't used NHibernate or any other OR tools, but I'm getting keener to try. Anything that automates all that boring data access stuff has to be worth a try. So, stored procedures? Well I wouldn't be at all surprised if I'm not using in them in a year or so.
Subscribe to:
Posts (Atom)