<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Marcin Hoppe</title><subtitle type="html">Marcin Hoppe on software development, .NET technology and the Web.</subtitle><id>http://devlicio.us/blogs/marcin_hoppe/atom.aspx</id><link rel="alternate" type="text/html" href="http://devlicio.us/blogs/marcin_hoppe/default.aspx" /><link rel="self" type="application/atom+xml" href="http://devlicio.us/blogs/marcin_hoppe/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.31106.3070">Community Server</generator><updated>2006-09-28T16:06:00Z</updated><entry><title>MSDN Tester Center</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/10/26/msdn-tester-center.aspx" /><id>/blogs/marcin_hoppe/archive/2007/10/26/msdn-tester-center.aspx</id><published>2007-10-26T07:09:08Z</published><updated>2007-10-26T07:09:08Z</updated><content type="html">&lt;p&gt;MSDN has&amp;nbsp;just opened a new site for testers: &lt;a href="http://msdn2.microsoft.com/en-us/testing/default.aspx" target="_blank"&gt;MSDN Tester Center&lt;/a&gt;. It looks promising (there are a couple of videos, some articles, and lots of links).&lt;/p&gt; &lt;p&gt;I think that test engineer role is still&amp;nbsp;not appreciated throughout the industry. That&amp;#39;s a pity because it makes it hard for developers to choose a career path in testing. I think Microsoft got it right: their SDET positions attract lots of talented people. I hope more companies will follow this path in the future.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=38739" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author></entry><entry><title>Visual Studio as an editor. Only an editor</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/10/02/visual-studio-as-an-editor-only-an-editor.aspx" /><id>/blogs/marcin_hoppe/archive/2007/10/02/visual-studio-as-an-editor-only-an-editor.aspx</id><published>2007-10-02T12:45:23Z</published><updated>2007-10-02T12:45:23Z</updated><content type="html">&lt;p&gt;Today I&amp;nbsp;learned&amp;nbsp;how &lt;a href="http://www.jpboodhoo.com/blog/" target="_blank"&gt;Jean-Paul Boodhoo&lt;/a&gt;&amp;nbsp;structures&amp;nbsp;&lt;a href="http://www.jpboodhoo.com/blog/DirectoryStructureForProjects.aspx" target="_blank"&gt;directories in his projects&lt;/a&gt;&amp;nbsp;and &lt;a href="http://www.jpboodhoo.com/blog/NAntStarterSeries.aspx" target="_blank"&gt;compiles his code with NAnt&lt;/a&gt;.&amp;nbsp;I use&amp;nbsp;a similar approach so the&amp;nbsp;posts&amp;nbsp;reinforced my confidence that this is the right way to go (one might even say that such a layout is very&amp;nbsp;ALT.NET-ish). What&amp;nbsp;I liked&amp;nbsp;the most, however, were not the folder structure ideas themselves, but an idea to use Visual Studio merely as a code editor (with ReSharper it might even be a really good editor).&lt;/p&gt; &lt;p&gt;The benefits, for me, include:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;reduced compile time for large projects,&lt;/li&gt; &lt;li&gt;flexibility of code structure and layout,&lt;/li&gt; &lt;li&gt;ease of including and excluding folders with source code to compile&amp;nbsp;for different targets (you can easily exclude test code, for instance).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;What Jean-Paul suggests and that I haven&amp;#39;t tried out yet is to use a single C# project to keep all the source code files (including tests, if I understood him well) and making&amp;nbsp;a developer responsible for clean separation of components. It&amp;#39;s worth noting that it doesn&amp;#39;t force an entire project to be compiled to a single assembly. &lt;a href="http://nant.sf.net" target="_blank"&gt;NAnt&lt;/a&gt; is really showing its&amp;nbsp;flexibility in tasks like these.&lt;/p&gt; &lt;p&gt;I had a chance&amp;nbsp;to use such an approach on two projects that I have been on and my experience is that &lt;strong&gt;delivery&lt;/strong&gt; of those projects was a superior experience. Automated testing and deployment are much easier to set up when one abandons Visual Studio.&lt;/p&gt; &lt;p&gt;By the way, have you read an article &lt;a href="http://www.charlespetzold.com/etc/DoesVisualStudioRotTheMind.html" target="_blank"&gt;&amp;quot;Does Visual Studio Rot the Mind?&amp;quot;&lt;/a&gt; by&amp;nbsp;&lt;a href="http://www.charlespetzold.com/" target="_blank"&gt;Charles Petzold&lt;/a&gt;? Absolutely&amp;nbsp;fantastic piece of well-thought Visual Studio criticism.&lt;/p&gt; &lt;p&gt;P.S. Did anybody except for me noticed that &lt;a href="http://www.hanselman.com/" target="_blank"&gt;Scott Hanselman&lt;/a&gt; is now &lt;a href="http://www.hanselman.com/blog/BlueBadge.aspx" target="_blank"&gt;working for Microsoft&lt;/a&gt;?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=38563" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="Delivery" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/Delivery/default.aspx" /></entry><entry><title>Jon Skeet writes a book: "C# in Depth"</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/09/20/jon-skeet-writes-a-book-quot-c-in-depth-quot.aspx" /><id>/blogs/marcin_hoppe/archive/2007/09/20/jon-skeet-writes-a-book-quot-c-in-depth-quot.aspx</id><published>2007-09-20T20:18:00Z</published><updated>2007-09-20T20:18:00Z</updated><content type="html">&lt;p&gt;Have you ever been to the &lt;a href="http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/topics" target="_blank"&gt;microsoft.public.dotnet.languages.csharp&lt;/a&gt;&amp;nbsp;newsgroup? If you have been there for more than a few moments you must have noticed an individual answering even the toughest C# questions like crazy, &lt;a href="http://www.yoda.arachsys.com/" target="_blank"&gt;Jon Skeet&lt;/a&gt;. Jon is a C# MVP and maintains a &lt;a href="http://msmvps.com/blogs/jon.skeet/" target="_blank"&gt;blog&lt;/a&gt; and a &lt;a href="http://www.yoda.arachsys.com/csharp/" target="_blank"&gt;collection of very interesting articles&lt;/a&gt; about various aspects of C# programming.&amp;nbsp;Two things you can always expect from his posts&amp;nbsp;are thoroughness and accuracy, both taken to the extreme.&lt;/p&gt; &lt;p&gt;A couple of days I noticed that this fine gentleman is working on a book entitled &lt;a href="http://manning.com/skeet/" target="_blank"&gt;&amp;quot;C# in Depth&amp;quot;&lt;/a&gt;, which is going to be published by &lt;a href="http://manning.com/" target="_blank"&gt;Manning&lt;/a&gt;&amp;nbsp;(at work I use &lt;a href="http://manning.com/neimke/" target="_blank"&gt;one of their books&lt;/a&gt; and I must admit that it is&amp;nbsp;one of the most useful books that we have at the office). Jon&amp;#39;s book is targeted at C# developers who have not yet mastered the&amp;nbsp;entire&amp;nbsp;set&amp;nbsp;of new features introduced in C# versions&amp;nbsp;2 and 3 (including LINQ magic!). It&amp;#39;s interesting to see a book devoted to C# programming language and not really to .NET class libraries or the runtime. I personally lacked such a book on my shelf.&lt;/p&gt; &lt;p&gt;On a similar note, an &lt;a href="http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/csharp%20language%20specification.doc" target="_blank"&gt;unified C# 3.0 language spec&lt;/a&gt; was recently published. It is a definitive document for anyone who would like to master C#. I find this spec&amp;nbsp;to be extremely well written, very readable and very informative. I even started to think about reading it cover to cover (well, maybe except for the grammar).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=38452" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="C#" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/C_2300_/default.aspx" /></entry><entry><title>New Job and New Topics</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/08/10/new-job-and-new-topics.aspx" /><id>/blogs/marcin_hoppe/archive/2007/08/10/new-job-and-new-topics.aspx</id><published>2007-08-10T08:07:00Z</published><updated>2007-08-10T08:07:00Z</updated><content type="html">&lt;p&gt;After about 3 months of silence I&amp;#39;d like to return to blogging. There are a 
couple of things that happened during my months of blogging silence. I also have 
a few neat ideas to implement here on this blog.&lt;/p&gt;
&lt;p&gt;First and probably the most important thing that happened to me was a job 
change. I began may short career as a software developer at a company that can 
be described as small or medium (we are talking about 100 people here) and that 
company was later bought by a big international corporation (we are talking 
about 15 000 people here). Both companies had their pros and cons but I 
definitely enjoyed the smaller company more. And now I am in a small (or 
medium)&amp;nbsp;company again!&lt;/p&gt;
&lt;p&gt;As of August 1, I am a software engineer at &lt;a href="http://www.kainos.com/" target="_blank"&gt;Kainos&lt;/a&gt;,&amp;nbsp;the largest IT consultancy in Northern Ireland. The 
company exists for over 20 years and is very mature and has very serious 
approach to quality. ISO, TickIT, you name it :). The headquarters are based in 
Belfast and I will be working in Polish branch of the company that opened a 
couple of days ago in the city I live in, Gdansk.&lt;/p&gt;
&lt;p&gt;What is the&amp;nbsp;most important thing for this blog is that I have shifted my 
focus from mainly business logic (which, by the way, was a terrific way to get 
hooked on TDD) to more technology focused position. I have joined the SharePoint 
team and for the last two weeks (well, almost) I am learning MOSS 2007 
development. SharePoint seems to be a very exciting technology and gets a lot of 
buzz nowadays. It&amp;#39;s a fresh product and there is much to be written on it.&lt;/p&gt;
&lt;p&gt;The second thing is that I have never been really very much into Web 
development. I decided to change and learn some things about the Web and 
underlying technologies. It seems to me that now we have quite exciting times 
for this. JavaScript has its renaissance now, probably due to things like AJAX, 
Gmail&amp;nbsp;and Firefox. &lt;/p&gt;
&lt;p&gt;Some of you may think that it is too late for this kind of stuff and that 
this is no longer cool and fresh. I found it interesting only when it matured 
and went mainstream. I think it might be an interesting perspective.&lt;/p&gt;
&lt;p&gt;In the end I&amp;#39;d like to mention that I opened&amp;nbsp;a second blog, &lt;a href="http://justcuriosity.typepad.com/" target="_blank"&gt;Just Curiosity&lt;/a&gt;, which 
will be less technology focused and less in-depth. .NET and development topics 
will remain the domain of this blog.&lt;/p&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=37638" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author></entry><entry><title>How to keep List&lt;T&gt; sorted?</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/05/15/how-to-keep-list-t-sorted.aspx" /><id>/blogs/marcin_hoppe/archive/2007/05/15/how-to-keep-list-t-sorted.aspx</id><published>2007-05-15T08:46:00Z</published><updated>2007-05-15T08:46:00Z</updated><content type="html">Recently I ran into a need to keep a list of integers sorted in ascending order. The list was used as an internal representation of a set, so I didn&amp;#39;t have to create a new class implementing IList or anything similar. The whole issue was to implement adding new elements properly. Of course, I started with writing a routine to find a proper place for a new element, move all subsequent elements and so on. This is quite a bit of code and it is easy to make a mistake here....(&lt;a href="http://devlicio.us/blogs/marcin_hoppe/archive/2007/05/15/how-to-keep-list-t-sorted.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://devlicio.us/aggbug.aspx?PostID=25214" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="C#" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/C_2300_/default.aspx" /></entry><entry><title>TDD Tip: Leave a Broken Test</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2007/04/05/tdd-tip-leave-a-broken-test.aspx" /><id>/blogs/marcin_hoppe/archive/2007/04/05/tdd-tip-leave-a-broken-test.aspx</id><published>2007-04-05T06:28:00Z</published><updated>2007-04-05T06:28:00Z</updated><content type="html">&lt;P&gt;How do you know where to start when you sit in front of your screen in the morning? Half of the developers population will probably start with a cup of coffee, some will visit &lt;A class="" href="http://slashdot.org/" target=_blank&gt;Slashdot&lt;/A&gt; or &lt;A class="" href="http://channel9.msdn.com/" target=_blank&gt;Channel 9&lt;/A&gt; (that's me!). There is, however, a breed of developers, that starts by checking out the fresh code and&amp;nbsp;gets to&amp;nbsp;hacking right away. If you are this kind of developer, this little tip is for you. Procrastinators already know what to do.&lt;/P&gt;
&lt;P&gt;How often do you as yourself a questions like: what do I start with today? Or what was I working on yesterday? How often do you browse your post-it notes to pick the next task and you're lost?&amp;nbsp;If you often find yourself in&amp;nbsp;situations like these, there is a very helpful tip I learned from Kent Beck's &lt;A class="" href="http://www.amazon.com/o/ASIN/0321146530/ref=s9_asin_image_1-hf_favarpcbss_2238_g1/103-8367624-1707049?pf_rd_m=ATVPDKIKX0DER&amp;amp;pf_rd_s=center-1&amp;amp;pf_rd_r=0G4HTDTBBSJNAVPP8G4W&amp;amp;pf_rd_t=101&amp;amp;pf_rd_p=278240701&amp;amp;pf_rd_i=507846" target=_blank&gt;Test Driven Development: By Example&lt;/A&gt;. The trick is: &lt;STRONG&gt;leave a broken test&lt;/STRONG&gt;. The last thing you do before you turn off your screen is to write a test that fails. &lt;STRONG&gt;Name it appropriately&lt;/STRONG&gt; so that you know what behavior it tests and make it fail. Write a &lt;STRONG&gt;failing assert&lt;/STRONG&gt; or just leave &lt;STRONG&gt;Assert.Fail&lt;/STRONG&gt; call. When you sit in front of your IDE&amp;nbsp;next morning&amp;nbsp;and start with running your tests, you will have a clear sign of where you finished yesterday and what you should implement next. This is especially useful to have a test like this on Monday. I don't work during the weekends, so I always find it very helpful to restore the context in a couple of seconds.&lt;/P&gt;
&lt;P&gt;There is a little issue in this method and this issue is teamwork. By no means, don't check in your failing test as others may think it is... well, a broken test. A bug. Something they need to fix ASAP (if you have loose code ownership). They will either blame you (not very likely but possible) or fix it themselves. Either way, leaving a broken test committed into the source code repository is clearly not a good idea. If you have any comments or ideas about this tip, please share!&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=20639" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="TDD" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/TDD/default.aspx" /></entry><entry><title>Persisting Domain Objects with the Serialized LOB Pattern</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2006/11/08/persisting-domain-objects-with-the-serialized-lob-pattern.aspx" /><id>/blogs/marcin_hoppe/archive/2006/11/08/persisting-domain-objects-with-the-serialized-lob-pattern.aspx</id><published>2006-11-08T11:52:00Z</published><updated>2006-11-08T11:52:00Z</updated><content type="html">&lt;P&gt;I have been recently working on a pet application that downloads&amp;nbsp;stock quotes and&amp;nbsp;a bunch of fundamental data&amp;nbsp;from &lt;A href="http://finance.yahoo.com/" target=_blank&gt;Yahoo! Finance&lt;/A&gt;&amp;nbsp;and puts the data into a nice little domain model. After some development I got tired of downloading the data with each run of the application. It really made testing and playing with the app a little bit annoying. Since this is a totally personal project carried out just for the purpose of good fun and exploration of market data available on the Web, I haven't paid much attention to design patterns, layers and other enterprisey stuff. Somewhere in the middle of development&amp;nbsp;it turned obvious that I&amp;nbsp;had to add persistence to an application that was not designed up-front and not prepared for adding such a functionality.&lt;/P&gt;
&lt;P&gt;What saved me was a pretty well developed domain model with lots of small and well defined classes representing quotes, dividends, splits, key ratios&amp;nbsp;and other pieces of the stock exchange mini-world. After a little bit of investigation I managed to&amp;nbsp;change my application so that it had a single root object called Universe that held references to every other&amp;nbsp;single domain object and was a perfect candidate for serialization. Then all I had to do to make my domain model&amp;nbsp;ready to be persisted to a database&amp;nbsp;was to decorate each of the domain classes with the &lt;SPAN style="FONT-SIZE:10pt;BACKGROUND:white 0% 50%;COLOR:black;FONT-FAMILY:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;[&lt;SPAN style="COLOR:teal;"&gt;Serializable&lt;/SPAN&gt;]&lt;/SPAN&gt; attribute. &lt;/P&gt;
&lt;P&gt;The next step was obviously to design the database schema. As the only thing that I was going to store in the database were big chunks of binary data (my serialized graphs of domain objects) that had some sort of identifier. The first idea that came to my mind was:&lt;/P&gt;
&lt;DIV class=code style="FONT-SIZE:10pt;BACKGROUND:white 0% 50%;COLOR:black;FONT-FAMILY:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;CREATE TABLE &lt;/SPAN&gt;[Objects] (&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [ID] &lt;SPAN style="COLOR:blue;"&gt;VARCHAR&lt;/SPAN&gt;(50) &lt;SPAN style="COLOR:blue;"&gt;PRIMARY KEY&lt;/SPAN&gt;,&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Bytes] &lt;SPAN style="COLOR:blue;"&gt;VARBINARY&lt;/SPAN&gt;(&lt;SPAN style="COLOR:blue;"&gt;MAX&lt;/SPAN&gt;) &lt;SPAN style="COLOR:blue;"&gt;NOT NULL&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;);&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;and it turned out to satisfy all my needs.&lt;/P&gt;
&lt;P&gt;Now all I needed was a database gateway that would enable me to&amp;nbsp;save objects&amp;nbsp;to the database,&amp;nbsp;read and delete them. Reading objects from the database turned out to be a&amp;nbsp;two step sequence of an embarrassingly simple SELECT statement and very rudimentary deserialization:&lt;/P&gt;
&lt;DIV class=code style="FONT-SIZE:10pt;BACKGROUND:white 0% 50%;COLOR:black;FONT-FAMILY:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;static&lt;/SPAN&gt; T GetObject&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; id) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; SqlStatement = &lt;SPAN style="COLOR:maroon;"&gt;"SELECT [Bytes] FROM [Objects] WHERE [ID] = @id"&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; T ret = &lt;SPAN style="COLOR:blue;"&gt;default&lt;/SPAN&gt;(T);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;byte&lt;/SPAN&gt;[] bytes = &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Read bytes from the database.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;using&lt;/SPAN&gt; (SqlConnection conn = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlConnection(ConnectionString)) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand cmd = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlCommand(SqlStatement, conn);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.Parameters.AddWithValue(&lt;SPAN style="COLOR:maroon;"&gt;"id"&lt;/SPAN&gt;, id);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt; (reader.Read()) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; bytes = reader.GetSqlBinary(0).Value;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Deserialize read bytes.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;if&lt;/SPAN&gt; (bytes != &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt; &amp;amp;&amp;amp; bytes.Length &amp;gt; 0) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:teal;"&gt;IFormatter&lt;/SPAN&gt; formatter = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:teal;"&gt;BinaryFormatter&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;using&lt;/SPAN&gt; (&lt;SPAN style="COLOR:teal;"&gt;MemoryStream&lt;/SPAN&gt; s = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:teal;"&gt;MemoryStream&lt;/SPAN&gt;()) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; s.Write(bytes, 0, bytes.Length);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; s.Seek(0, &lt;SPAN style="COLOR:teal;"&gt;SeekOrigin&lt;/SPAN&gt;.Begin);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ret = (T)formatter.Deserialize(s);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;return&lt;/SPAN&gt; ret;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Deleting objects from the database was even simpler:&lt;/P&gt;
&lt;DIV class=code style="FONT-SIZE:10pt;BACKGROUND:white 0% 50%;COLOR:black;FONT-FAMILY:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; DeleteObject(&lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; id) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; SqlStatement = &lt;SPAN style="COLOR:maroon;"&gt;"DELETE FROM [Objects] WHERE [ID] = @id"&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;using&lt;/SPAN&gt; (SqlConnection conn = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlConnection(ConnectionString)) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand cmd = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlCommand(SqlStatement, conn);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.Parameters.AddWithValue(&lt;SPAN style="COLOR:maroon;"&gt;"id"&lt;/SPAN&gt;, id);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.ExecuteNonQuery();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Saving objects involved two steps: deleting the old version of an object (in case we were overwriting some old version of the&amp;nbsp;object graph) and then inserting new BLOB to the database. Here goes the last snippet:&lt;/P&gt;
&lt;DIV class=code style="FONT-SIZE:10pt;BACKGROUND:white 0% 50%;COLOR:black;FONT-FAMILY:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;P style="MARGIN:0px;"&gt;&lt;SPAN style="COLOR:blue;"&gt;public&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;void&lt;/SPAN&gt; SaveObject&amp;lt;T&amp;gt;(&lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; id, T obj) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; SqlDeleteStatement = &lt;SPAN style="COLOR:maroon;"&gt;"DELETE FROM [Objects] WHERE [ID] = @id"&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;const&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;string&lt;/SPAN&gt; SqlInsertStatement = &lt;SPAN style="COLOR:maroon;"&gt;"INSERT INTO [Objects]([ID], [Bytes]) VALUES (@id, @bytes)"&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;byte&lt;/SPAN&gt;[] bytes = &lt;SPAN style="COLOR:blue;"&gt;null&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Serialize the object to bytes.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:teal;"&gt;IFormatter&lt;/SPAN&gt; formatter = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:teal;"&gt;BinaryFormatter&lt;/SPAN&gt;();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;using&lt;/SPAN&gt; (&lt;SPAN style="COLOR:teal;"&gt;Stream&lt;/SPAN&gt; s = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:teal;"&gt;MemoryStream&lt;/SPAN&gt;()) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; formatter.Serialize(s, obj);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; bytes = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR:blue;"&gt;byte&lt;/SPAN&gt;[s.Length];&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; s.Seek(0, &lt;SPAN style="COLOR:teal;"&gt;SeekOrigin&lt;/SPAN&gt;.Begin);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; s.Read(bytes, 0, &lt;SPAN style="COLOR:teal;"&gt;Convert&lt;/SPAN&gt;.ToInt32(s.Length));&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// Delete any previously existing object with the same id&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// and save the bytes to the database. Execute both&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:green;"&gt;// statements in one transaction.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;using&lt;/SPAN&gt; (SqlConnection conn = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlConnection(ConnectionString)) {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Open();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlTransaction trans = conn.BeginTransaction(IsolationLevel.Serializable);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;try&lt;/SPAN&gt; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand delCmd = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlCommand(SqlDeleteStatement, conn, trans);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; delCmd.Parameters.AddWithValue(&lt;SPAN style="COLOR:maroon;"&gt;"id"&lt;/SPAN&gt;, id);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand insCmd = &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlCommand(SqlInsertStatement, conn, trans);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; insCmd.Parameters.AddWithValue(&lt;SPAN style="COLOR:maroon;"&gt;"id"&lt;/SPAN&gt;, id);&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; insCmd.Parameters.AddWithValue(&lt;SPAN style="COLOR:maroon;"&gt;"bytes"&lt;/SPAN&gt;, &lt;SPAN style="COLOR:blue;"&gt;new&lt;/SPAN&gt; SqlBinary(bytes));&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; delCmd.ExecuteNonQuery();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; insCmd.ExecuteNonQuery();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; trans.Commit();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;SPAN style="COLOR:blue;"&gt;catch&lt;/SPAN&gt; {&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; trans.Rollback();&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR:blue;"&gt;throw&lt;/SPAN&gt;;&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN:0px;"&gt;}&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;When I got back to the office the next day I picked up &lt;A href="http://www.martinfowler.com/" target=_blank&gt;Fowler's&lt;/A&gt; &lt;A href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Fowler/dp/0321127420/sr=8-1/qid=1162901652/ref=pd_bbs_sr_1/104-7290172-2423122?ie=UTF8&amp;amp;s=books" target=_blank&gt;Patterns of Enterprise Application Architecture&lt;/A&gt; and learned that my beautiful and elegant solution already had a name: the Serialized LOB pattern. How sweet :).&lt;/P&gt;
&lt;P&gt;By the way, extracting relevant data from HTML markup&amp;nbsp;is itself a very interesting topic and recently .NET community was equipped with a very powerful tool that makes it a whole lot easier to parse Web pages: the HTML Agility Pack library, available for free along with the source code&amp;nbsp;at &lt;A href="http://codeplex.com/Wiki/View.aspx?ProjectName=htmlagilitypack" target=_blank&gt;CodePlex&lt;/A&gt;. This is so interesting and so exciting that it probably deserves a post of its own.&lt;/P&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=482" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="Patterns" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/Patterns/default.aspx" /></entry><entry><title>Designing Web Services: Messages vs RPC</title><link rel="alternate" type="text/html" href="/blogs/marcin_hoppe/archive/2006/09/28/Designing-Web-Services_3A00_-Messages-vs-RPC.aspx" /><id>/blogs/marcin_hoppe/archive/2006/09/28/Designing-Web-Services_3A00_-Messages-vs-RPC.aspx</id><published>2006-09-28T14:06:00Z</published><updated>2006-09-28T14:06:00Z</updated><content type="html">&lt;p&gt;The most natural way to create Web services in ASP.NET (this technology is often referred to as ASMX) is to write a facade class or interface using pure OO approach and decorate the class and the public methods with proper attributes (WebServiceAttribute and WebMethodAttribute, respectively). For simple Web services, we may even use ADO.NET DataSet&amp;nbsp;objects (or strongly typed data sets)&amp;nbsp;passed as arguments or as a return value. While this is probably fine for small Web services acting mainly as a very thin gateway to the database, it may not be appropriate for large enterprise Web services that interact with rich business logic layer.&lt;/p&gt;&lt;p&gt;There is also a&amp;nbsp;mismatch between the underlying technology (SOAP and WSDL) that is very much &lt;strong&gt;message&lt;/strong&gt; oriented and the most popular usage style which basically utilizes Web services as&amp;nbsp;yet another&amp;nbsp;&lt;strong&gt;RPC&lt;/strong&gt;&amp;nbsp;(Remote Procedure Call) technology. This kind of approach to designing distributed systems may lead to tight coupling not only between the service and its clients but also between the service and the business logic layer (it probably has something to do with the curious temptation of some&amp;nbsp;developers and architects&amp;nbsp;to transfer serialized business entities across the wire). &lt;/p&gt;&lt;p&gt;The approach one should take when designing new enterprise-class Web service is to think&amp;nbsp;about it in terms of message exchange rather than in terms of distributed objects as we often do now. This may lead us to a whole new world of Web services that support message-based security, asynchronous message exchange scenarios and long-running business processes.&lt;/p&gt;&lt;p&gt;I will try to&amp;nbsp;blog more&amp;nbsp;on&amp;nbsp;topics related to&amp;nbsp;Web services quite often. This post was meant to make a gentle introduction to the way I perceive Web services technologies and their usage. Next posts will probably vary from architecture level musings to code-rich technical posts. More to come soon!&lt;/p&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=165" width="1" height="1"&gt;</content><author><name>Marcin Hoppe</name><uri>http://devlicio.us/members/Marcin-Hoppe/default.aspx</uri></author><category term="Architecture" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/Architecture/default.aspx" /><category term="Web Services" scheme="http://devlicio.us/blogs/marcin_hoppe/archive/tags/Web+Services/default.aspx" /></entry></feed>
