9/4/09

Remove unused code! The simplest rule to follow

If your codebase contains anything unused, be it a class, enum, method, property, or even commented out old code, just get rid of it!

Before applying any adavanced programming techniques like OOP, just follow this simple rule. In other words, before even considering being funcy with virtual methods, Adaptor design pattern, or having a religious war over naming convensions, just make sure the code base contain only and exactly the "live" codes. If not, leave the whiteboard there and go back to the desks!

This is a simple programming principle, which is extremely easy for everyone to understand, yet often not being followed up with.

4/13/09

Building Saas application in .NET


Take advantage of ASP.NET single sign-on

If your application is going to be comparmentalized into multiple sections, consider using third domain (sub-domain) such that you have

http://foo.myapp.com
http://bar.myapp.com

then make sure to enable cross-sub-domain SSO by writing the ASP.NET forms authentication cookie against "myapp.com" domain (as against a specific sub-domain such as "foo.myapp.com" or "bar.myapp.com"). This provides extension points for additional ASP.NET web applications while using the same login sessions.

Consider using third-party single sign-on integrations
Try not to build your own identify server. That is: do not implement your own "login" page that takes password that you manage. You want to stay away from that. Instead, use external identity servers including Windows Live!, Yahoo BBAuth, OpenID, etc. This is a win-win for developers as well as users.

Use XML schema-driven business objects
After many tries with different approaches, I am convinced that using XML Schema (XSD) with tool generated C# wrapper is the best way to capture business objects. For any new web application, I create a folder called "Entities", and I create three files:

mybusinessobjects.xsd
mybusinessobjects.cs
generate.bat

mybusinessobjects.xsd will contain all of the data type definitions of the application's business objects. For example, if your application is about student enrollment process, then you will define Studen, Course, Semester, etc. in this XML schema.

mybusinessobjects.cs is not manually created but created by running XSD.exe tool, that takes XML schema file and produces a C# class definitions. generate.bat is for running XSD.exe and it looks like this

xsd.exe mybusinessobjects.xsd /n:MyApp.Entities

By executing this line, you will easily get C# object representations of all of the things you defined in mybusinessobjects.xsd, placed in the namespace, "MyApp.Entities"

These tool-generated C# classes are in-memory "storage" for your business objects, and they can be serialized to XML (and deserialized from XML) very easily.

This serializability between XML and C# is very convenient and flexible. For example, you can write UI that takes C# object model and set it to DataSource of ASP.NET Repeater control. Or, you can deserialize it to XML and pass it through XSLT to produce another XML, which can be consumed by an existing code. It opens up possibilities to working with your business objects.

Use XML to communicate with Database
After many attempts to use DataSet in ADO.NET, I am settled with this approach. The idea is to use very stable stored procedure interface, and use XML as input and output parameters, and all variations are captured in XML input/output. For example, many of the stored procedures have the same signature of:

sp_foo(userId, languageId, xml)

which returns string (which is xml output)

Note: there will be some stored procedures that must deviate from this pattern

With this interface, you can easily build Data Access layer that can be used by Business Logic layer to update data and retrive data to/from database.

The stored procedure has to be written such that it can take incoming XML and parse it to obtain necessary inputs for the procedure, and be able to form XML output. (Luckly, DBA I work with is very good at this that I don't need to know how its done exactly...)

Use SQL Data Services
This is another approach for solving data storage needs for a SaaS application. Instead of your maintaining database for your self, completely offload that task to cloud computing. Though I have not used it for commercial development project, I am convinced that SQL Data Services provides sufficient data storage capabilities to web-based application. The benefit is clear: you do not need to maintain your own database tier in your data center (and if you use Azure, where you host your ASP.NET application, then you don't need data center all together!); you pay as much as you use so it is cost-effective.

Use YUI (Yahoo! UI) for your page development
I have used YUI for both work and hobby and works great. It gives you browser neutrality right from the beginning. Let these experts at Yahoo! to solve browser compatibility issues and just focus on solving your own problem. YUI can be a bit tricky to use in ASP.NET, but many of the components in YUI can be used easily in simpler cases.

Use HttpHandler for AJAX server
It is possible, and often done, to use regular ASP.NET pages (.aspx) to implement server-side logic that returns XML (or JSON) output to a client-side script. Howerver, it makes more sense to implement such server-side logic using HttpHandler, which is more efficient than ASP.NET pages, and fits well with the model of "client script (UI) - server logic (BLL)". Essentially, client script is acting as user interface, and if you follow strict sepration of UI and Logic, then your server-side logic should not have anything to do with UI, such as page controls. HttpHandler is nothing but an end-point responding to an Http request, where returned output may not necessarily HTML but XML, JSAN, image, document, etc.

Enable Google Analytics right away
No further discussion on this. Just do it.

Pay attentions to security from the beginning
With web application, you want to start with "locked" down application instead of you lock it down as you go by. Read up "cross-side scripting" and "SQL injection" first and make sure we have no holes for that. Compile a list of Query string being passed around, Cookies saved to the user's machines, input fields that user can type in, and make sure each item is being evaluated to ensure that these cannot be exploited.

Build exception and error handling infrastructure
First thing you have to do is to define "application exceptions" at your Business Logic layer. Any Business Logic has an error condition that is created because of "user". For example, with Student Enrollment application, if one of the business rules states that "You cannot sign up for a class unless pre-requisites are completed", then you have an exception. Yes, UI can try to make sure that it will never be in such condidtion, but who knows? Business logic layer should NOT rely on UI does good job and never create such situation. Instead, Business Logic should throw "application error".

This is one of the most important use of Exception handling. You will define your own "application exception" that can be presented to the user and "user" can modify his/her behavior to fix the issue. This is in contrast to "system exception" where it is due to system error and not user. For example, if disk space run out and causes IO exception, user can do absolutely nothing to remedy that.

So, you deal with two large groups of exceptions: Application Exception and System Exception. Now, how do you handle them and where? The answer is: at each page, look at method that make call to Business Logic layer and wrap it around with try block, then create one catch block to handle application exception, and anthor one for system exception. The way you handle two kinds of exception is different: for application exception, tell user why and what user should to do avoid receiving the same exception (example: show message like "You are not allowed to enroll this course because you have not completed HIS101"). In contrast, for system exceptions you want to show something like "A system error encountered. The error has been reported to system administrator. If this problem continues, please contact xxx-xxxx. Error Code: 2231".

When handling system exception, your catch code must log the error to somewhere (such as text log file or event log). Ideally, you generate a unique Error Code value, and write it to the event log with the detailed error information, and also show it to the end user. This way, when user calls for a help, technical person at our end can locate the related error event log.

Use WF and WCF right from the beginning
There are features in Workflow Foundation and Communication Foundations that let you implement your application features easily and effectively. WF comes with sequential workflow and state machine workflow that models many real-world workflow. For example, "student enrollment" is a perfect example for sequential workflow that takes multiple input values to produce a result (student has sign up, system accept it, schedule bill, etc.)

WCF opens up possibilities to "extentions" such as web-service, REST based API, working with additional back-end engines, etc. The boilerplate code for hand-shaking, security, throttling and bufferin, are all taken care of for you.

Engage users as soon as possible
In another word, engage in Agile software development model. I strongly recommend using User Stories methodology to drive the whole development process. Good applications solve real user problems, and to do so developers need to know what the problems users are facing. Sometimes users don't know how to describe the problems, and/or they may not understand the best way to solve it. The chances are, the application you built today will be ineffective tomorrow and you will have to make constant changes to the application. So, stay small and address core issues first, then present it to the users to see if it is indeed solveing the users problem. Do not waste time working on bells & whistle since users can go without them for a while.

Integrate with Facebook and other social media as much as possible
Consider creating a Facebook application that provides an interface to your web application. At minimum, Facebook app has iFrame mode where you can show your web application interface embedded in Facebook. Of course, if you can integrate more, that would be nice. Facebook is an organic solution delivery mechanism where solical graph drives the distribution of solutions. If your application solves a problem for one Facebook user, then chances are, it will be useful to other Facebook users, and the initial "case" of one user solving his/her problem can proliferate to other users with similar problems. Forget the classic "you come to our website and sign up to get good stuff" model.

That's it for now...

3/31/09

How to program well (part 1 of n)

Be sure to clearly define "programming interface" of your function.

Writing a function is a simple part of programming in any language yet it is an essential part of programming and having good functions are very important to produce high quality software. I've seen too many pooly written functions and decided to document what not to do and what to do.

When I say, pooly written function, these are functions with no clear "interface contract". Here, I am not talking about what is inside of the function (ie. implementation). I actually don't care about implementation (well, it should work, but it is really up to programmer to implement the function however he/she sees appropriate). It is more about "interface".

There are several important rules about writing good functions

Function name should have a single action word
A function should do one thing, or a unit of things that is cohernt
Etc..

However, the issue I see most offten with pooly written functions are lack of clear documentation about its arguments.

Function arguments should have acceptable values (or domain)

For instance, if function Foo takes an integer argument, it must clearly state whether 0 is acceptable, negative value is acceptable, whether it has upper/lower limits, etc. Usually function should accompany documetation that describe these details. Amazingly, many professional progammers just don't do this...

Next, function should "enforce" these domains by using Assertions and throwing Exceptoins. I would recommend setting up both, but sometimes throwing exceptions is sufficient, but not doing either is bad. Without this enforcement, problem would occur down the code stream and it is probably more time consuming to toubleshoot. With enforcement of input values at the function entry, it is much easier to understand what went wrong.... client code deviated from "interface contract" (ie. was never supposed to pass negative value, but it did).

(I will update this entry)

2/27/09

SQL Data Services (SDS) Tutorial (Part2)

This blog entry is the second part of the SQL Data Services (SDS) Tutorial.

This article is based on CTP release of SQL Data Services.

Let's get us started. You begin by opening "SDS Exlorer" from Windows Start menu.

First of all, delete the text in Query text area so that you can disregard Query stuff for now. (I will discuss Query in future)

Next, set the address to
https://[your_authority].data.database.windows.net/v1/
where [your_authority] is the actual authority id yours (read Part 1 of this Tutoria if you don't have one). In this example, I use my test authority called "yoshi".



Then, click "Get" button.


You receive information about your Authority (if you get alot more information that what I got above, don't worry. Its called "metirics metadata" and we will cover this later)

Now, without changing the value in Address, click "Query" button.


This time, you receive an XML element called "EntitySet" with nothing in it. This measn that your Authority is empty. In order to make this Authority useful, we need to add a Container. Let's do that.

Without changing the Address, Click "Container" button. You will get a template in the main text area. SDS Explorer generated GUID value for you as Id of the new Container, which is about to be created. I changed this to "bookmarks" because that's the application I want to build.


When you are happy with the name of Container, click "Create" button.

As usual, it is not appearent if the requst succeeded or not, so open the "Request/Response" window and check HTTP "Response".


The status says "Created" so that's a good sign!

Now, let's talk about an important concept called "Scope" in SDS. If you look at the Address bar right now, you see:

https://yoshi.data.database.windows.net/v1/bookmarks

This is in the format of:

https:[your authority id].data.database.windows.net/v1/[your container id]
... and you are in "container scope".

Understanding "Scope" is important because all operations you perform using SDS Explorer works within the context of the current Scope. For example, if you make a simple HTTP GET request while Authority is the scope, you will get metadata information about the Authority; while Container is the scope, you will get metadata information about the Container.

Take a look at the output results of clicking "Get" and "Query" buttons while we are in bookmarks container scope.

Result of "Get":


Result of "Query":


You observe some metadata information about my "bookmarks" container, and my container is still empty because I haven't added anything. We will cover working with Container in future. For now, let's validate that our Authority indeed contains my newly created container.

Go back to Authority scope by either clicking on "Go up" button (looks like a folder icon) in Address bar or manually type in:

https://yoshi.data.database.windows.net/v1/

And then click "Query" button.


This time, we get EntitySet with one element called Container. This container is the "bookmarks" container that I just created.

You have successfully created a Container and now you can do a lot of things with it. I will talk about working with Container in future.

2/25/09

SQL Data Services (SDS) Tutorial

This blog entry is for you if you are new to SQL Data Services and want to get started.

This article is based on CTP release of SQL Data Services.

I assume that you have:
SQL Data Services account
SQL Data Services SDK installed on your machine

When you start SDS Explorer from Windows "Start" menu, it looks like this.



Without doing anything, just click "Query" button at the lower right corner.

You will receive a popup window asking User and Password.



For User field, provide the solution name you specified while you were signing up for SDS. You should have also received a password at the same time. Once you get passed authentication, SDS Explorer will tell you that it is "working...", and moment later you should see this.



Your output may be different from what I have here, but the idea is the same and simple: you get listing of all of the "Authorities" under "Service" that you have permissions to access.

You can create as many Autorities as you want, but you cannot delete them (I am not sure if this is a limitation during CTP or permanent policy).

Next, let's create a new Authority.

Click "Authority" button, which is one of the buttons under "Template" label, which will give you this screen:


At this momenty, you haven't done anything to SDS data center. You are simply preparing for a request to create a new authority. Notice that SDS Explorer generated a GUID value for you as Id of the new authority. You could use this GUID or specify something more user friendly. For example:


I changed the Id value to "yoshi" (Note. I have not confirmed this but it appears that Authority Id must be unique within the global namespace. My attemp to create Authority with typical id values like "testauthority" and "authorityexample" fails).

What you are doing here is to define a XML payload which will be sent to the server using HTTP POST request, which we will see next.

Once you are happy with the name of the new Authority, click on "Create" button.

Now you have successfully created a new Authority. Unfortunatley, SDS Explorer doesn't make it obvious that the operation succeeded. In order to get a positive confirmation, you should check the HTTP Request/Response data, which is available in a small window that shows up by clicking "Request - Response" button toward the bottom.


The "Request" tab shows you that in order to create a new Authority, SDS Explorer made a HTTP POST request against the "Service"

POST https://data.database.windows.net/v1/ HTTP/1.1

It passed XML payload that act as input for this operation

<?xml version="1.0" encoding="utf-8"?>
<s:Authority xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:s="http://schemas.microsoft.com/sitka/2008/03/">
<s:Id>yoshi</s:Id>
</s:Authority>

And the "Response" tab shows that the server successfully created the Authority.

POST https://data.database.windows.net/v1/ HTTP/1.1
Status: Created

Now, lets check to see if we will see our new Authority in the list of Authorities available under this Service. You can use the folder-looking icon of Address bar to "go up one level".

While the address bar contains value

https://data.database.windows.net/v1/

Click on "Query" button. You should see this now.


My new Authority called "yoshi" is now available.

I will write more tutorial on this subject later but with this article, you have seen some of the essential SDS concepts:
* SDS Explorer is a handy tool to work with SDS
* You can Query againt https://data.database.windows.net/v1/">https://data.database.windows.net/v1/ to retrieve listing of Authorities
* You can add your Authority by making HTTP POST request with XML payload (this pattern is called REST)

2/9/09

StringBuilder.AppendFormat vs String.Format

I am a bit ashamed of not knowing this until now…

String.Format()

Actaully creates an instance of StringBuilder and delegates all its formatting work to AppendFormat() method to the StringBuilder

So, the following is bad coding:

// creates a string that looks like “item=abc,item=xyz,”
StringBuilder sb = new StringBuilder();
foreach(object obj in myCollection)
{
sb.Append(string.Foramt(“item={0},”, obj));
}

If this loops 1000 times, 1000 StringBuilder instances will be created (calls ctor, allocates memory from managed heap, etc) in the loop

Instead, something like below would be more efficient

StringBuilder sb = new StringBuilder();
foreach(object obj in myCollection)
{
sb.ApppendFormat(“item={0},”, obj);
}

This uses only one instance of StringBuilder

From now on, you will see me using StringBuilder.AppendFormat more, except simpler cases (because one line of String.Format is still more readable!)

2/4/09

You shouldn't blog when your last post is one year ago

Wow, my last post was over a year ago...

Writing blogs require such energy and these days you get to say what you want to say mostly in Facebook and Mixi (my other Japanese only SNS).

Oh well...

This blog on blogger is meant for "tech" related posts - I don't want to discuss these stuff with my Japanese friends who are not interested in tech stuff and also they don't read English! Facebook is for English-speaking friends but FB is just not the kind of place to talk about tech stuff (or maybe..)

Anyway, maybe I start writing more random crap on this blog rather than trying to be too informative, which I have tried and failed so many times.

OK, see you next year!