Archive for January, 2005

Appropriate uses of web services

We have a client application at work that we give to our
clients so that they can sync their contacts and appointments from our system
into Outlook.  There is an Outlook api to do this, so its fairly
straightforward. The way our stuff works is the user installs the client
application and clicks the ‘Sync’ button.  The client app then accesses a
web service that we have exposed that will return the users contacts and
appointments in the form of datasets. 

The client app then processess the
app and add the necessary information to Outlook.

It would seem, based
on Rockford Lhotka’s definition of a web
service
, that we are
misusing webservices.  I know that web services are most useful at interop
between different systems, but I think they can also be useful, even when you
are targeting specific uses of your web service. Using a web service could just
happen to be the easiest way to transfer information, as in our case. 

The
client application COULD make a direct connection to the database, but using a
web service as an intermediary seems a little more secure, IMO.

We could also write an entire client/server application that
transfers the data in an application specific way, but that would take a
considerable amount of time compared to the ease of making a simple web
service.

So, while other applications might have a difficult time
using our exposed web service, that was never the intent, and I think thats an
acceptable reason sometimes.

 

RssReader for C#

There is an Rss
Reader class
available on the CodeProject.  I
used this in our app to aggregate some Yahoo news feeds, among others, and its
really cool, you can define sort of a repeater that has content place holders,
so you can completely customize the look of the feed.

What do you use to write blog entries?

I’m wondering what app you guys use to write your blog
entries? I’m currently using the beta of Visual Blogger, but its still got quite
a few bugs, it can be quite aggravating sometimes. I would like something that
makes good, clean markup.  I also think it would be cool if we could put
this WYSIWYG editor on our backend to
replace the simple textarea for editing/creating posts, its free and it
generates xhtml markup, which I think is pretty cool.

So what do you guys use?

Larry on robustness

Larry
Osterman
has a great post
on the idea of “robustness”

The problem with “robustness” is
that defining what robustness is is situational - the very qualities that
define the robustness of a system depend on how and where it’s deployed. 
Thus it is meaningless to consider robustness without first describing the
scenario.

Larry always has good
stuff…..

Powerful code generator

Sean
McCormack
, maker of the Zanebug NUnit GUI, also has a code
generation tool called
Codus.

Some of the sweet things about Codus is the auto generation
of data access objects, strongly typed collection classes, mock objects, nunit
tests, zanebug tests, as well as web services that match the generated data
access objects.  There is built-in support for Access and SqlServer,
however in his DbType enumerator, I saw options for MySql, DB2, and Oracle, but
I didn’t see these as options in his front end application, so maybe he is
working on adding those dbs. 

I really love the feature that is has where it makes a VS
solution file, and opens it up for you; so from clicking the ‘Generate’ button,
your next step is to fire up NUnit (or Zanebug) and run the brand new tests on
your brand new objects! Pretty cool stuff….

Using generics you could definitely trim the number of lines
of code needed, especially in the collection classes, without sacrificing any of
the advantages of being strongly typed.  Here is one of my collection
classes, using generics, which contains around 30 lines of code, but it has all
the functionality of CollectionBase.  It inherits from another custom class
cObjectCollection<T> that contains other custom implementation,
QuickSort(), Filter(), Serialize(), etc..  This is the ArtistCollection
class for our music management software.

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">using style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
System; />

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">using style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
System.Collections.Generic;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">using style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
System.Configuration;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">using style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
System.Text;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">using style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
Ben;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> 

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> 

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">namespace style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">
Ben.Data

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">{

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">    style="COLOR: blue">public class style="COLOR: teal">ArtistCollection : style="COLOR: teal">cObjectCollection< style="COLOR: teal">Artist>

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">    {

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
public style="COLOR: teal">ArtistCollection() : style="COLOR: blue">base()

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
{

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
ConnectionString = Setting( style="COLOR: maroon">“DSN”);

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
DatabaseType = style="COLOR: teal">DbAgent.ParseDbType(Setting( style="COLOR: maroon">“DbType”));

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
ConnectionType = style="COLOR: teal">DbAgent.ParseConnectionType(Setting( style="COLOR: maroon">“ConnectionType”));

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
IdField = style="COLOR: maroon">“ArtistID”;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
TableName = style="COLOR: maroon">“Artist”;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
ParentIdField = style="COLOR: maroon">“GenreID”;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
}

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> 

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
public style="COLOR: teal">ArtistCollection(int
genreId) : this()

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
{

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">           
ParentId = genreId;

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">       
}

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">  style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"> style="mso-spacerun: yes">    }

style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes">}

 

Thanks Brendan

Visual Blogger test post on the new blog :-)

Scrollable divs and Firefox

Firefox does not support scrollable divs with the mouse wheel.

I poked around in the target=_blank>extensive bug database trying to find this listed, but the
number of bugs is just too daunting. This really sucks, because we develop our
stuff to work on ie as well as Firefox, so whenever we run into a div with a
scroll bar, the screen just kind of jumps around. I’m surprised that I haven’t
heard much about this problem from other people, as the mouse wheel has become
invaluable to me, I hate having to move my mouse to the scroll bar, and manually
move it down……

Goodger leaves Mozilla for Google

Hmm, is this the sound of a Google web browser rumor starting up again?? Ben Goodger has left the Mozilla Foundation where he was a lead engineer of the Firefox browser. Coincidence? I think not…….

CSci 101 Part III

Now we’ve seen a slow way to generate the fibonacci numbers, and we’ve seen why its so slow, now we’ll try to do better.  Here’s my proposed improvement to our recursive function that we made the first day:

static long Fibo(long n)

{

//

      // check the base cases

      //

      if (n <= 1)

      return 0;

      if (n == 2)

            return 1;

 

      //

      // initialize our array of fibonacci numbers

      //

      long[] numbers = new long[n];

      numbers[0] = 0;

      numbers[1] = 1;

 

      //

      // calculate the 2nd through nth

      // fibonacci numbers in the array

      //

      for (long i = 2; i < n; i++)

      {

            numbers[i] = numbers[i - 1] + numbers[i - 2];

      }

 

 

      return numbers[n - 1];

}

So what we’re doing here is that instead of making recursive calls to the Fibo function, we are just storing the fibonacci numbers in an array of length n. We don’t have the recursion tree at all now, as there are no recursive calls.  All we have is the overhead of the array, and a loop that will loop n times.  During each loop interation, we simply add the two previous numbers in the array, and put the result in the current array position.  Using this function we can easily get the 50th, 100th, or 1000000th fibonacci number, no problem.  Go ahead, try it!  The response is nearly immediate!  However, there is one more little thing we can change to make the function even better. 

In the code above, we maintain an array of the 0 to nth fibonacci numbers, when really, all we need is the current number, and the previous number, in order to generate the next one.  So we can remove the overhead costs that are associated with the array:

static long Fibo(long n)

{

//

      // check the base cases

      //

      if (n <= 1)

      return 0;

      if (n == 2)

      return 1;

 

      //

      // initialize our loop varibles

      //

      long x = 0;

      long y = 1;

      long current = 0;

 

 

      //

      // calculate the 2nd through nth

      // fibonacci numbers, but without

      // the array overheard

      //

      for (long i = 2; i < n; i++)

      {

            current = x + y;

            x = y;

            y = current;

      }

 

      return current;

}

Here, instead of an array of length n, we simply have x, y, and current.  We still have the loop that will iterate n times, but each time the loop adds x and y and then puts the value of y into x, and the new value into y.  We can store all the values we need in just three variables! 

I ran some tests and compared the results of the 3 different functions, heres what I found:

  10 20 30 40 50
Slow 125000 62500 312500 37484375 4.18E+09
Better 140625 78125 31250 31250 0
Best 93750 109375 46875 78125 0

So you can see that the difference in the functions is trivial when finding the 10th or 20th fibonacci number.  However, the difference  becomes very noticeable when generating the 40th number, and once we get to the 50th, the difference is staggering.  I went and ate dinner while the slow function was processing the 50th number!  The numbers provided are the number of “ticks” the functions took.  I ran each function 10 times for each value.  The difference between the faster two functions is negligible, as the only optimization we used there was to reduce the amount of memory needed, not processing time.  These results clearly show how much slower tree recursion can be than an iterative function.

Thanks for reading, I hope you’ve enjoyed the series!

CSci 101 Part II

Okay, so yesterday we saw one
way
to generate the “nth” fibonacci number using recursion. The
recursion that we used is also called “tree recursion“,
the reason for this being that we made two recursive calls inside the
function.  If you were to draw a diagram of the function calls, the diagram
would take on the shape of a tree, because every node would have two
branches, like this:

src="http://dotnetjunkies.com/WebLog/images/dotnetjunkies_com/barblog/2293/r_fibo.GIF"
width=640 border=0>

If you tried to use this function to find the 35th fibonacci
number, you probably realized that it can take quite a bit of time.  The
reason for this is that we are computing the same value many times over. 
Consider what happens when you call Fibo(4).  The function is going to add
Fibo(3) + Fibo(2).  Fibo(3) will, in turn, call Fibo(2) + Fibo(1). So
you can see that we are calling Fibo(2) twice, which is a waste.  Its
not a big deal for only the 4th fibonacci number, but when you put in 50, the
extra work can definitely start to make a difference.

See if you can come up with a way to speed up the function,
and I’ll post my ideas tomorrow, along with a performance comparison of a
few different functions.  Thanks for reading!