Last post May 13, 2011 11:18 AM by abhisheks
May 10, 2011 10:16 AM|RobstaMeade|LINK
I hope this is both the correct forum, and that maybe someone can offer some information on my question.
I've been building up a series of libraries that are used within the applications we develop at work, I've worked hard to separate them based on the following structure:
The problem I initially encountered was that I was creating say the following;
for an application, and more often than not we would also need a web service. The web service had its own little set of files for handling the getting/setting of the data.
To me this felt wrong. Surely if I have a DataAccess library specifically for the getting/setting of data which resides in between the Business and DataSource layers I should make every attempt to use it for the WebService too - why re-invent the wheel
Without going into all the detail, the structure of these services were almost identical, aside from one made calls to stored procedures, and one made calls to web services. I took each method in turn and passed in a
dataDelivery parameter, this being an integer value representing my DataDelivery enum (sqlserver, webservice, file etc). Within the data services I would then simply determine the desired delivery by means of a case statement. At this stage, I felt
everything in my World was good. The code felt tidy, clean and simple.
I had began to notice however that when I wanted to publish the web services that referenced the data access library I had to comment out some code initially in the data access library that was reference those very same web services. Once this was done,
the data access library would build, I could publish my web services, then uncomment the code in the data access library (as the web services now existed, or the methods within), and then a rebuild of the web services and another publish - job done.
I had been working like this for several months and saw no particularly large issue with the way it was devised, until I had a meeting with my manager and he raised the question about the cyclic dependency between the web services and data access library.
I've argued my case and feel I have run out of answers. I now pose the question to your goodselves having had a nose around the web and stumbling across mixed opinions - but without any really good reasons for/against.
So - can anyone tell me, is the design bad? I appreciate it raises the odd issue when publishing, but this isn't a huge show stopper. The only way I can see of avoiding the problem would be to have TWO data access libraries, one that the web service uses,
and one that the application uses, but being that the names of the methods are all going to be identical, and its only
where the data comes from that is going to be different it seems a bit, well, odd...
I'm not one for jargon, to be honest I get lost with it... the very fact that I've managed to mention
cyclic dependency surprises me! So, can anyone give me a straight forward response without phrases like
tightly coupled and loosely coupled which will no doubt send me off around the internet in search for their definitions too!
Thanks in advance for your time and any help/advice,
May 11, 2011 02:00 PM|abhisheks|LINK
I highly recommend reading those books. You can read parts of those books to get answer to your questions.
These books exclusively deal around the area you are having.
I can't call your design bad idea, but there seems to be room for refactoring where you don't have to comment out your code evertime you publish it for two services that you mentioned.
May 12, 2011 11:46 AM|RobstaMeade|LINK
Thanks for the reply and suggested reading.
It's actually only the one web service that gets published, but yes, the issue is the same that the references in code to a web service that does not yet exist causes a problem.
May 12, 2011 02:27 PM|atconway|LINK
OK let me not try to use any fancy words here like requested but I agree in principal cyclical dependency is not a good situation to have. Even
if you have a workaround it is still not ideal, and anytime it happens to me I try to re-think the structure to correct the problem. A used car dealer can put sawdust in a transmission to help it not leak and shift smoother, but in the end there is
still a problem.
I read your post several times trying to get a mental picture and do not understand why the data access library needs to reference the web service and the web service needs to access the data access library. Regardless, there are a couple of ways to fix
1. Consolidation: Place all of the code from both layers into a service and logically divide within it (different classes, namespace, interfaces, etc). Then there is only a single reference and no more issues with cyclical dependency.
2. Refactor: You could further refactor the code and take out the code both layers depend on and place it in yet another .dll, service, etc that they could both reference. If you don't know what it means to refactor code, it is just the process
of removing common code typically needed or physically existing in more than 1 location, down to a single more abstract location for re-use (there is probably a better definition if you want to research more). Point being you could refactor that code both
layers are dependent on in each layer into a new separate entity or layer.
By the way I am not necessarily siding with your manager, but it is true from an 'Architectural' standpoint (and the topic of this forum) that cyclical references are not a good idea. Hopefully this helps a bit!
May 13, 2011 08:30 AM|RobstaMeade|LINK
Thank for the reply and info - and lack of fancy words (chances are I am already doing what some of the jargon often means, I just dont keep
up with it all!)..
I will take some time and have a think about the solution and how to break it apart, without duplicating things...
Regarding the not understanding the requirement for them to reference each other I've put a little diagram of it all together (simplified)...
In the above, the only thing that "talks" to the database are the data services. When a call is made from a business object to a data service a parameter of
dataDelivery is passed, this is an enum offering either SQLServer or WebService. If the SQLServer is selected the web services are bypassed completely, handy if you are running the app on the lan for example. If however WebService is selected the
call then goes to the web service, returns a dataset (in the scenario of Getting data), which in turn is returned to the data service, the business object maps the data from the dataset into the object which is then used within the web app..
The methods in the data services which handle the dataDelivery parameter looked something like this:
Public Function GetWardsByHospitalID(ByVal dataDelivery As Integer, ByVal hospitalID As Integer) As DataSet
Dim dataSet as DataSet
Select Case dataDelivery
' populate dataSet here from SQLServer
' populate dataSet here from WebService
I've obviously left a fair chunk of the above code out, but hopefully you get the idea... in the web service is makes a call to the data service, call the same named method, but this time passing SQLServer as the dataDelivery method...
May 13, 2011 09:49 AM|abhisheks|LINK
Can you elaborate a little bit more on the flow from let's say organization to dataservice to webservice and organization to dataservice to webservice. I am still not clear as to where and why you would need to comment out the code to push it to server.
I don't want to speculate. If you can give more details...it would be helpful
May 13, 2011 10:36 AM|RobstaMeade|LINK
Okey dokey... lets say on the web site I want to populate a drop down menu will all of the hospitals... the process might go something like this:
We'll assume the population of the drop down is from the page load, and that we are choosing to get our data via a WebService.
So, there area where there is the necesity to comment out calls to the web service is at step 2 above, assuming the WebMethod being called doesn't exist, or is not being changed.
So, if I was adding a new method to the HospitalDataService, perhaps GetHospitalByHospitalID for example, I'd add it to the HospitalDataService with the code all there to do what it needs to, but it wont build because the WebMethod doesn't yet exist in the
publish Hospital.asmx WebService.
I therefore comment out the lines which reference that specifically in the new method. The DataAccess library now builds without error. I can then add the WebMethod to the WebService which references the newly build DataAccess library. I publish the built
WebService with the new WebMethod. I return to my DataAccess library, update the WebReference, and uncomment the references to the previously non-existant WebMethod (which now exists). The DataAccess library can now be rebuilt. The WebService subsequently
needs to be rebuilt referencing the updated DataAccess library. The WebService is published for the last time.
Originally, waaaay back in the day, I had separate data access code for both the main data access library AND the web service, but as a huge chunk of this was my common sql data access methods, connection string generation and so on it seemed daft having
this duplicated, which necessitated me making changes twice. So I merged it all into one and added the
dataDelivery parameter on the method calls, and then evaluated this value in a SELECT CASE statement.
Does this make it any clearer? Hope so :)
May 13, 2011 11:18 AM|abhisheks|LINK
String Name(or dataParameter that you are passing)
Public Class HospitalWebService
public sub New()
implement name(can hardcode the value)
Public Class HospitalSQLService
public sub New()
implement name(can hardcode the value)
you can probably put common code to both service in some common base class or use IService to abstract out your common logic .
Now the call from your dataservice might look like
callhospitaldataservice(byval dataparameter as integer)
you can even pass IService rather than dataparameter as integer
callhospitaldataservice(byval pService as IService)
call servicemethods here
you can instantiate Iservice at business layers or even before business layer, by passing in the concrete class that you are trying to call
now whenever you add a new method you can add it to hospitalsqlservice without affecting hospitalwebservice code logic. When you want to put it in both places, you can always move it to the base class or interface. Hope it helps.