Programmer's architectural design path (7): Pull out the framework

Source: Internet
Author: User
The response from the previous blogs was good, but there was still a hard injury: "Can you practice so many theories ?" There are not many articles about similar concepts, but there are also a lot of articles, but I have never been able to get much from them, but it is even more confused in the cloud. It is estimated that this is mainly caused by two reasons: I have a low IQ, but I really love it!

The response from the previous blogs was good, but there was still a hard injury: "Can you practice so many theories ?" There are not many articles about similar concepts, but there are also a lot of articles, but I have never been able to get much from them, but it is even more confused in the cloud. It is estimated that this is mainly caused by two reasons: I have a low IQ, but I really love it!

You're talking about it. I only believe it, and I see it as a reality. "Is it a horse, a donkey, or a slide ?"

According to the architecture you mentioned, build and run the system, and change the requirement to hundreds or thousands of times, with high concurrency and high traffic ...... Sorry, this was a tough task and was not broken across. after the system was refined, it was still refined into steel. That's good!

I believe that there must be successful cases based on the concepts of DDD, TTD, and agile development. Otherwise, they will not be praised by the technical experts standing at the peak. But unfortunately, I am a wild programmer and have no chance to integrate into that circle.

So I used the most stupid method: I made a system myself and developed it strictly according to my own understanding of these concepts. can I come out of this path at the end? After five or more years of exploration and practice, I think I have basically come out.

So, if you want to, just let me know.

Embarrassed

After determining the principles of forgetting the database, we should start from the business layer to build the system.

C # code
  1. /*
  2. Why not start from the UI layer? Don't laugh. I really remember that I have seen a summary and recommendations on this practice. What other terms are there, like "page-driven.
  3. And you just need to think about it. a lot of our development is actually doing this! After the solution is determined, the artist works out and the foreground switches out the static page. the programmer changes the page to dynamic.
  4. The task assessment is like this: "We have finished a page today ".
  5. We will not discuss the advantages and disadvantages of this practice. However, if you need a reason not to start from the UI layer, I think the most powerful is that our system has three versions: desktop pages, mobile phone pages, and mobile apps.
  6. */

At the business layer, we usually extract some terms from the requirements and make them one by one. taking the entrepreneurial home as an example, we should have a Blog class and there are methods in the Blog, for example, GetBlog (int Id) or GetBlogs (int pageIndex, int pageSize) are as follows:

C # code
  1. Class Blog
  2. {
  3. String Title {get; set ;}
  4. String Body {get; set ;}
  5. Blog Get (int Id)
  6. {
  7. Return new Blog ();
  8. }
  9. IList GetBlogs (int pageIndex, int pageSize)
  10. {
  11. Return new List (){};
  12. }
  13. }

This is what I wrote in my book when I first got started with a three-tier architecture.

But I feel this is really awkward! A blog object extracts 10 blogs. a car can provide ten cars. What's the mess? No way ......

I once thought about setting all the Get () methods to static, so that they can be logically a little smoother: some blog instances can be obtained through the blog class. But it is still uncomfortable that the static method of the class will lose the inheritance polymorphism and other features of the object. For example, 10 articles and 10 blogs cannot be reused.

Later, I gradually understood that this practice still comes from the "database-driven" idea. The Blog class actually represents the Blog table in the database. a Blog instance represents a row of data, and some rows are obtained from the table, these rows are encapsulated into Blog classes (it is still messy, right ?). It is estimated that the popularity of Microsoft DataSet has intensified this phenomenon. of course, DataSet itself is no problem and its logic is self-consistent. However, many developers do not accept DataSet and say it has low performance, to use DataReader and encapsulate it yourself, the result will become the "Four Nos" of the above style ".

Entity

In addition to logic chaos, the traditional business-layer architecture also has a big problem: it is difficult to test! How can I test it if it is mixed with a database? My headers are all big. I have to create a small database? In addition, this database has to be inserted/updated, and the benchmark data for testing will change. Therefore, tear down is required for each unit test (back to the benchmark test environment). how can this problem be solved?

C # code
  1. // Of course, I found the hybrid database test method later, but I am very happy that my database test was completely desperate. This leads to the idea and practice of "forgetting databases ".

So I was wondering, can I isolate database operations? At this time, I should have started to contact the ORM, and their operation methods enlightened me: the "change" in the "add, delete, modify, query" of the relational database is gone. Update is "alienated" into a process of "Load"-> "modify"-> "Savae" (refer to the example in "forgot database ). So, can we "change" first? Through continuous evolution, I finally formed an Entity project, responsible for only changing the object state, and completely did not involve functions such as object loading and storage.

The biggest benefit of doing so is to solve the problem of Entity unit testing. Because (at least temporarily) you no longer need to consider these objects and storage issues, I only need to create a new object during the test, instead of getting it from the database, this is much more convenient!

Query (Repository)

What should I do if I add, delete, and query an object? Technically, we can only rely on the ORM tool. I use nhib.pdf. In short, with nhib.pdf, we can establish a ing between the object and the database structure ). Then, you can call the session through the NHibernate session. save (), session. delete (), session. load () and session. query () and other methods to store, delete, or load/retrieve objects in the memory (C # Project.

C # code
  1. /// Why is nhib.pdf?
  2. /// 1. my project started earlier. it should have been several years ago. At that time, Entity Framework was not mature, so there was no way to choose nhib.pdf
  3. /// 2. I want to see the world outside the Microsoft framework. As a matter of fact, I now know that in the Java World, My practices are almost mainstream, such as SSH. Of course, I have not studied much about the Java world, and there may be some differences. I found out my own framework and thought it would be good to use it.

However, at the system architecture level, there is another method: Repository mode.

Repository, literally, is a Repository. I think this concept is very relevant, just like a car is stored in a warehouse. We use a warehouse administrator to retrieve one or more cars. In this case, the "code ing to the real world" is a logical and self-consistent feeling, instead of the way a car looks like a dozen cars.

At the code level, it looks like this:

C # code
  1. Class BlogRepository
  2. {
  3. IList GetBlogs (int pageIndex, int pageSize)
  4. {
  5. Return new List (){};
  6. }
  7. Blog Get (int Id)
  8. {
  9. Return new Blog ();
  10. }
  11. }

However, the understanding and use of Repository are controversial. There are probably two mainstream types:

1. it is considered that Repository is similar to a set or an object that encapsulates a set. So it is used in Entity.

2. the Repository is considered to be a type of "aggregation root", which is tied with the retrieved/stored object and should be placed outside the Entity.

I didn't even use Repository explicitly, so I won't discuss this concept abstraction. Let's talk about it in the future.

We "add" and "delete" directly use the NHibernate session mechanism, but abstracted the "select" separately, it is also abstracted into a project named Query.

Service

Now, let's look back at it. The concept of operating system data should be as follows:

Premise: all objects are stored directly on the disk, and then:

1. when we need some objects, we can extract them from the disk and load them into the memory.

2. perform some operations and modifications.

3. finally, store the data to the disk.

So the question is, who will do the above steps? Note that all the things we are talking about are in the business layer. Therefore, according to the three-tier architecture, the UI layer should call the BLL layer, while our UI layer uses MVC. therefore, should this work be done in the Controller?

However, after reading our source code, you will find that we have added a Service layer between the UI layer and the BLL layer. In fact, it is the loading, modification, and storage work performed by the Service layer. I very much agree with this point of view: we must not layer layers for the sake of hierarchy. So what does the Service layer mean?

It is mainly used for frontend and backend separation. In the early stages of development, I had imagined recruiting a dedicated front-end developer, regardless of the specific business logic of the background and the interaction with the database, only page presentation and interaction. So there is a problem here. I don't want her to be a simple artist. I just need to plot the slice into an html static page. I hope she will use VS for development in the same way, using Razor to make a view is also responsible for page interaction and jump, so she has to create an Action in the Controller and write code in the Action. Therefore, she writes code in the Action to obtain data for presentation. different business logic needs to be called based on the data returned by the page. So how can we obtain these data calls? Wait for the background developer to finish the task? This is undoubtedly very economic.

Therefore, we abstracted a ServiceInterface. the front-end and back-end developers can first establish a series of interfaces and then implement their own implementations. So there is:

1. UIDevService: The front-end developer's "simulation" implementation. you can see it by looking at the source code. it contains some very simple and crude logic. For example, if you need a ViewModel object, you can simply add a new object.

2. ProdService: the real business logic implementation is always connected to the database.

This actually means an interface-oriented interface. The frontend and backend depend on the ServiceInterface interface, regardless of its specific implementation.

C # code
  1. // From this we can see that a complicated architecture is a helpless choice.
  2. // If all our developers are at the full stack level, you can directly plug them into the database, so we don't need to worry about this.
  3. // The reality is that most developers have their own specializations. after all, there are too few full-stack programmers.

Of course, after isolating the UIDevService, there are other benefits, such as more convenient unit testing. We will talk about this later.

Upload the image. Let's take a look at it first. I can't understand it. I will discuss it in detail later:

ViewModel

There is also a ViewModel in our project. our developers have proposed more than once: why can't we directly use Entity?

I understand his doubts very well. I tried to extract the Article attribute in an Entity and put it in an ArticleViewModel one by one. How worried is this? Full?

In fact, I am also a developer. I typed this framework with a letter or a letter. I will definitely be lazy if I can be lazy! Just like I didn't use Repository in the past, I even had a two-tier architecture, but in the end I had no good experience. To put it simply, there are two main reasons for the existence of ViewModel:

1. requirements for frontend and backend separation. If Entity is used directly, do front-end developers have to wait for background developers to set up Entity first? Is Entity immediately affected by changes in front-end development? If you are interested, you can observe our ui.task.zyfei.net. sln solution. all projects in the BLL layer are not included at all. we have completely achieved physical isolation!

2. ViewModel and Entity cannot correspond to 100%. Everyone who has tried it should understand it. For example, in our home startup project, there is a list of "latest blog posts". it is a collection of blogs. how do you get it? You said that I can use IList But there is another logic in this small square: if the current user is a blog blogger, the modification link is displayed. So how do you get the "current user" data? Of course, this is a big proposition. You can certainly do it through various means. the simplest thing is to use ViewBag. The combination of ViewBag and Enitty can solve almost all problems, but sometimes it is too ugly!

Finally, we should jump out and think about this issue from the perspective of architecture. What is ViewModel? What is its responsibility? Who should build it ?......

In my opinion, ViewModel is essentially a DTO for page rendering, so it should not have any internal logic and should be built by front-end developers. Front-end developers should thoroughly get rid of the Entity constraints in the business layer, and boldly combine various abstract combinations based on the page presentation rules, so that the ViewModel truly shines!

MVC

After talking about the above, MVC has nothing to say. The Controller calls the Service and obtains the ViewModel for the View to use. Of course, there are many details, such as the mvc route test, the implementation of switching services using Autofac, and performance optimization using Session Per Request. Let's talk about it in the next section.

Here is the last ppt I made. it's ugly. let's see it first!

Tool

Those who have read the source code must have noticed that there is a Tool project folder in the project. The most important thing is the BuildDatabase project. This project shoulders the dual responsibility of building development and integration test databases, and helps generate environment database updates, which is a powerful test-driven guarantee. For more information, see (testable documentation)

Pit to be filled

The framework is pulled out in this way, but there are still many pitfalls in it. with some ideas, we need to dig them out first and then fill in them slowly:

1. UI

• CurrentUser processing: It is also a headache because it will be used in a large amount, so we want to reuse it. if we want to reuse it, it will hurt our brains.

• Get-Post-redirdbms: There are also a bunch of pitfalls. Because Http is stateless, there is a problem of data transmission during Redirect.

• MVC Route: once heartbroken, when the page is complex, the url will not be able to jump to the specified action; or a slight change will cause the previous route rule to crash.

• Partial View, EditTemplate, and Child Action: you don't know how long it takes to get dizzy.

• Unit test

• Other performance optimizations

2. Service

• Improved Performance: SessionPerRequest. This must be put at the beginning, because it profoundly affects many things of the page architecture we mentioned below.

• UIDev and Prod switching: use Autofac

• The specific implementation of SessionPerRequest is mixed with the UI and NHibernate. I really don't know where to put it.

• Why Query is not used in the Repository mode

• ViewMode Map: use Automapper

• Unit test: Query needs to be stirred into the database again ......

3. BLL

• Performance problems with large sets of Entity. Because of the 1: n relationship ing between objects, a pile of set data is pulled out, for example, all the articles of an Author, all comments, Agree, and Disagree of an Article. If you want to do this, you cannot afford more memory.

• Entity polymorphism application. It's a big pitfall. I think it's a miracle that I can climb out.

• Unit test of Entity. Due to the complex object relationship between Entity, unit testing is a disaster.

• Entity NHMap unit test. There is no problem in Entity, but how do you ensure that the Entity database is correctly mapped? Only unit tests can be performed, or databases cannot be bypassed!

4. Tool

• BuildDatabase: super tedious and super difficult

• Other cleanup Statistics tools

There were so many pitfalls!

This reminds me of the days and nights when I burst my hair and throw my mouse. I have been skeptical more than once. Am I wrong? These messy MVC, test-driven, object-oriented ...... There is no way to make my development more efficient and smooth at all. it seems that I am getting stuck. I used the traditional method to drag controls to add, delete, modify, and query databases. why? Not the same? And the development may have been completed long ago !......

But the joy of solving the problem again and again makes me unable to give up on the surprise of another world. This may be the technical path and the path of life. Is that true?

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.