Practical use of N-tier architecture

I am a .NET web developer for a small organization. We have several experienced developers here, but we don’t have those who worked in larger, more organized software stores. We are all fine, but I think I want to structure my code better with a little space to ask for advice.

It comes to this. At some point, someone from our organization decided that we would use web services whenever we needed any kind of access to data, regardless of the case. Thus, our hardware architecture is organized in such a way that it is the only way to access our databases. This sounds great in theory, but the problem is that most of our applications look like this:

Code spaghetti error in aspx.cs β†’ web service that does nothing but call a stored procedure

In addition, there is not much separation. Whenever I start trying to explore best structural practices, I end up reading about things like dependency injections, dirty properties, and class factories, my head starts to float, and I move on to something else in frustration.

Here is a basic example of my surprise. So let me say that I need to make a page to select employees from the list, edit them and update the database. Is it better to return the web service Employee object to get and accept the Employee object for updating? Or is it better for an Employee object to call a web service to populate itself?

In other words: Employee emp = svc.GetEmployee (42); vs Employee emp = new Employee (42);

The second example seems that it is better to organize updates (update the corresponding properties and call emp.Update ()), but the problem is, what if I need to get a list of employees? It would be incompatible to do Employee emp = new Employee (id); for a single employee, but for svc.GetAllEmployees () for a list.

It seems to me that I'm a little confused, so I'm going to stop trying to explain and hope that someone will understand my confusion. I appreciate any advice anyone can offer. Thanks!

+4
source share
1 answer

As with any case, there are several different approaches you can take. (So, I hope there will be many good and different answers here, because this is definitely an important question.)

One question that you should probably ask yourself about your design is, "how much logic will you need to use between applications?" Going with the small GetEmployee example you gave, it looks like you want to know where to place the models in your domain. Are these models used in multiple applications? Is business logic shared between applications?

If so, you might want your domain models behind the web service. Perhaps create a rich domain for these services with its access to data and external dependencies (remember that the dependency injection application, the best design decisions should be in the domain beyond the service level, since this is the core of the entire system).

Then, of course, how do you access this logic? Again, there are many options. My personal favorite design is a kind of request / response system that abstracts the level of service. Something as cool as NServiceBus for a really disconnected asynchronous system, something simple like Agatha to just abstract the actual service and inject the request / response logic into the code or maybe play with ServiceStack (something I had in mind) or another project, etc. Hell, you can just collapse the regular old WCF or even the SOAP service level and nothing more. It depends on you.

At this point, you are looking at a fairly procedural system at the service level. This is not scary. Think of a service level, such as an MVC site. You send him a request filled with some kind of incoming viewmodel, he makes his domain material in all his object-oriented kindness and returns a view in the form of some XML representation of the outgoing view model. You now have a repeating pattern. Your client applications are just great views for your domain. The deeper they are, the more interchangeable and interchangeable they are, the better.

This allows you to encapsulate various "business activities" in a work unit at the service boundary. Given the request from the client application, all of this succeeds, or all of this fails. Wrap it with good error handling and an application-level error / error error log to provide you with all the information about failed requests. (Imagine that each request can be serialized into a string and included in the error message. Now you have everything you need to recreate the error in a simple string, rather than asking users β€œwhat did you click?” To try to recreate the errors .)

If instead the background server really has nothing to do with different applications, and each application is completely its separate separate entity. At this point, you really do not need to share all this logic behind the service level, and it is quite possible that you should not try to make any overlaps. Is data only available behind the service? What about access to the file system or an external web service?

If the only service is data access, then you can store your models and data stores in your client applications, as if you are used to it, and simply replace your repository implementations with realities that are internally referenced and accessed by the service level. (This will be the second option in your GetEmployee example.) Correctly abstracted repositories of access to access and access to services can be replaced trivially depending on where the application should live.

Of course, this relies a bit on a true approach based on consistency, which can be dangerous. Effectiveness implications must be considered Some part of the logic or unit of work on the back-end can hit the database several times to do several things. If this happens through a service, this adds overhead for each database call. Thus, you will want to consider this in each case.

Probably, I can get angry at this stage, therefore, in order to return to something specific, in fact the whole thing is that I ask myself some questions about your domain. How persistent and ignorant can you be? Do your applications affect business domain logic? Do you need to access other external dependencies that are not related to the database for the service? There is no universal design that has always been the right answer. You may be able to experiment with various projects and homogenize a design suitable for your developers and your environment.

+3
source

Source: https://habr.com/ru/post/1339761/


All Articles