Tag Archives: api design

You are a Web application developer for a company…

I sometimes wonder how software certification test questions are created. In many occations, the questions seem like they are first and foremost made to show off new and fancy functionality in the framework. In other cases, the questions seem to have been thrown in there just to make the test harder to pass, rather than making sure the candidate has actual insight. Funny thing is that when trying the latter, the question may reveal really poor API design. Take, for instance the following example.

You are a Web application developer for a company. Which of the following would you use to define that column2 has a foregin key relationship with column1:

  1. DataColumn column2 = DataSet1.Tables["Orders"].Columns["CustID"];
    DataColumn column1 = DataSet1.Tables["Customers"].Columns["CustID"];
    DataSet1.Relations.Add(relCustOrder);
    DataRelation relCustOrder = new DataRelation("CustomersOrders", column1, column2);
  2. DataColumn column1 = DataSet1.Tables["Customers"].Columns["CustID"];
    DataColumn column2 = DataSet1.Tables["Orders"].Columns["CustID"];
    DataRelation relCustOrder = new DataRelation("CustomersOrders", column2, column1);
    DataSet1.Relations.Add(relCustOrder);

So, the difficulty here lies in remembering the correct parameter order for the DataRelation constructor. First of all, the question of remembering this aspect of the API is not a question of insight. Secondly, when considering the user-friendlyness of the API, this reveals a rediciously poor design. Why? If I, for instance, were to review the code above, the code gives me no clue about the direction of the relationship. Which is the primary key column, and which is the foreign key column? Either I would have to remember the constructor parameter order, look at the database design, or look at some other documentation. Preferably, the code should be able to tell me. Consider the following (fantasy) code:

DataColumn column1 = DataSet1.Tables["Customers"].Columns["CustID"];
DataColumn column2 = DataSet1.Tables["Orders"].Columns["CustID"];
DataRelation relCustOrder = column2.isForeginKeyFor(column1);
DataSet1.Relations.Add(relCustOrder);

Much better. Now, the DataColum class has an instance method I can use to define the relationship in a manner that is both much easier to rembember, and easier to read. But still, this has potential for improvement. Why do I need the last line of code? Columns column1 and column2 belong to a DataTable, and that DataTable belong to the DataSet, then the isForeginKeyFor method should be able to propagate the new relation to the DataSet on its own, like so:

ParentRelations.Add(theNewRelation);

Then, we would get rid of an extra line of boilerplate code, and the code snippet would be like so:

DataColumn column1 = DataSet1.Tables["Customers"].Columns["CustID"];
DataColumn column2 = DataSet1.Tables["Orders"].Columns["CustID"];
column2.isForeginKeyFor(column1);