日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Domain Driven Design and Development In Practice--转载

發布時間:2025/4/5 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Domain Driven Design and Development In Practice--转载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文地址:http://www.infoq.com/articles/ddd-in-practice

Background

Domain Driven Design (DDD) is about mapping business domain concepts into software artifacts. Most of the writings and articles on this topic have been based on Eric Evans' book "Domain Driven Design", covering the domain modeling and design aspects mainly from a conceptual and design stand-point. These writings discuss the main elements of DDD such as Entity, Value Object, Service etc or they talk about concepts like?Ubiquitous Language, Bounded Context and Anti-Corruption Layer.

The objective of this article is to cover the domain modeling and design from a practical stand-point on how one would go about taking a domain model and actually implementing it. We will look at the guidelines, best practices, frameworks and tools that the technical leads and architects can use in the implementation effort. Domain Driven Design and Development is also influenced by several architectural, design, and implementation aspects such as:

  • Business Rules
  • Persistence
  • Caching
  • Transaction Management
  • Security
  • Code Generation
  • Test Driven Development
  • Refactoring

This article talks about how these different factors affect the implementation project throughout its lifecycle and what the architects should look for in realizing a successful DDD implementation. I will start off with a list of characteristics a typical domain model should have, and when to use a domain model in an enterprise (versus not using a domain model at all or using an anemic domain model).

The article includes a sample loan processing application to demonstrate how design aspects and development best practices discussed here, can be used in a real-world domain driven development project. The sample application uses frameworks like Spring, Dozer, Spring Security, JAXB, Arid POJOs and Spring Dynamic Modules in implementing the loan processing domain model. The example code will be in Java, but it should be fairly easy to understand for most developers, regardless of language background.

Introduction

A domain model offers several benefits some of which are:

  • It helps the team create a common model, between the business and IT stakeholders in the company, that the team can use to communicate about the business requirements, data entities, and process models.
  • The model is modular, extensible and easy to maintain as the design reflects the business model.
  • It improves the reusability and testability of the business domain objects.

On the flip side, let's see what happens when IT teams don't follow a domain model approach for developing medium to large size enterprise software applications.

Not investing in a domain model and development effort leads to an application architecture with a "Fat Service Layer" and an "Anemic Domain Model" where facade classes (usually Stateless Session Beans) start accumulating more and more business logic and domain objects become mere data carriers with getters and setters. This approach also leads to domain specific business logic and rules being scattered (and duplicated in some cases) in several different facade classes.

Anemic domain models, in most cases, are not cost-effective; they don't give the company a competitive advantage over other companies because implementing business requirement changes in this architecture take too long to develop and deploy to production environment.

Before we look at different architectural and design considerations in a DDD implementation project, let's take a look at the characteristics of a rich domain model.

  • The domain model should focus on a specific business operational domain. It should align with the business model, strategies and business processes.
  • It should be isolated from other domains in the business as well as other layers in the application architecture.
  • It should be reusable to avoid any duplicate models and implementations of the same core business domain elements.
  • The model should be designed loosely coupled with other layers in the application, meaning no dependencies on the layers on either side of domain layer (i.e. database and facade layers).
  • It should be an abstract and cleanly separated layer enabling easier maintenance, testing, and versioning. The domain classes should be unit testable outside the container (and from inside the IDE).
  • It should be designed using a POJO programming model without any technology or framework dependencies (I always tell the project teams I work with in my company, that the technology we use for software development is Java).
  • The domain model should be independent of persistence implementation details (although the technology does place some constraints on the model).
  • It should have minimum dependencies on any infrastructure frameworks because it will outlive these frameworks and we don't want any tight coupling on any external framework.

In order to achieve a better Return On Investment (ROI) on software development efforts, the senior management in Business Units and IT has to commit to the investment (of time, money, and resources) in business domain modeling and its implementation. Let's look at some of the other factors that are required for implementing a domain model.

  • The team should have regular access to business domain subject matter experts.
  • IT team (modelers, architects, and developers) should possess good modeling and design skills.
  • Analysts should have good business process modeling skills.
  • Architects and developers should have strong Object Oriented Design (OOD) and Programming (OOP) experience.

Role of Domain Driven Design in Enterprise Architecture

Domain modeling and DDD play a vital role in Enterprise Architecture (EA). Since one of the goals of EA is to align IT with the business units, the domain model which is the representation of business entities, becomes a core part of EA. This is why most of the EA components (business or infrastructural) should be designed and implemented around the domain model.

Domain Driven Design and SOA

Service Oriented Architecture (SOA) is gaining more and more momentum in the recent past to help the teams build software components and services based on the business processes and to speed up the time to market for the new products. Domain driven design is a key element of SOA architecture because it helps in encapsulating the business logic and rules in domain objects. The domain model also provides the language and context with which the service contract can be defined.

An SOA effort should include the design and implementation of the domain model if one doesn't already exist. If we put too much emphasis on the SOA services and ignore the importance of domain model, we will end up with an anemic domain model and bloated services in the application architecture.

An ideal scenario is the one where DDD effort is implemented iteratively with developing the application layer and SOA components at the same time as these are the direct consumers of domain model elements. With a rich domain implementation, SOA design will become relatively simple by providing a shell (proxy) to the domain objects. But if we focus too much on the SOA layer without a decent domain model in the back-end, the business services will be calling an incomplete domain model, which can result in a brittle SOA architecture.

Project Management

A domain modeling project typically includes the following steps:

  • Model and document business processes first.
  • Select a candidate business process and work with the business domain experts to document it using the Ubiquitous Language.
  • Identify all the services that are required for the candidate business process. These services can be atomic (single step) or orchestrated (multi-step with or without work-flow) in nature. They can also be business (e.g. Underwriting or Funding) or infrastructure (e.g. E-mail or Job Scheduling).
  • Identify and document the state and behavior of the objects used by services identified in the previous step.

It's important to keep the model at a high-level initially focusing on the core elements of the business domain.

From a project management stand-point, a real-world DDD implementation project comprises the same phases as any other software development project. These phases include:

  • Model the domain
  • Design
  • Development
  • Unit and Integration Testing
  • Refine and refactor the domain model based on the design and development (Continuous Integration (CI) of model concepts).
  • Repeat the above steps using the updated domain model (CI of domain implementation).

An agile software development methodology is a great fit here because agile methodologies focus on the delivery of business value just like DDD focuses on the alignment of software system with business model. Also, with the iterative nature of DDD, agile methodologies such as SCRUM or DSDM are better frameworks to manage the project. Using SCRUM (for project management) and XP (for software development purposes) methodologies is a good combination for managing a DDD implementation project.

This project management model of DDD iteration cycle is shown in Figure 1 below.


Figure 1. DDD Iteration cycle diagram (Click on the screen shot to open a full-size view.)

Domain driven design effort begins where domain modeling ends. Ramnivas Laddadrecommends the following steps?on how to go about implementing a domain object model. He emphasizes on putting more focus on domain objects than services in the domain model.

  • Start with domain entities and domain logic.
  • Start without a service layer initially and only add services where the logic doesn't belong in any domain entity or value object.
  • Use Ubiquitous Language,?Design by Contract?(DbC), Automated Tests, CI and Refactoring to make the implementation as closely aligned as possible with the domain model.

From the design and implementation stand-point, a typical DDD framework should support the following features.

  • It should be a POJO (or POCO if your company is a .NET shop) based framework.
  • It should support the design and implementation of a business domain model using the DDD concepts.
  • It should support concepts like Dependency Injection (DI) and Aspect Oriented Programming (AOP) out of the box. (Note: These concepts are explained in more detail later in the article).
  • Integration with unit testing frameworks such as?JUnit,?TestNG,?Unitils?etc.
  • Good integration with other Java/Java EE frameworks like JPA, Hibernate, TopLink etc.

Sample Application

The sample application used in this article is a home loan processing system and the business use case is to approve the funding request of a home loan (mortgage). When a loan application is submitted to a mortgage lending company, it first goes through the Underwriting process where the underwriters approve or deny the loan request based on customer's income details, credit history and other factors. If the loan application is approved by underwriting group, it goes through Closing and Funding steps in the loan approval process.

Funding module in the loan processing system automates the process of disbursement of funds to the borrower. The funding process typically starts with mortgage lender (typically a bank) forwarding the loan package to a title company. The title company then reviews the loan package and schedules a date with seller and buyer of the property for closing the loan. Borrower and the seller meet with the closing agent at the title company to sign the paperwork to transfer the title of the property.

Architecture

A typical enterprise application architecture consists of the following four conceptual layers:

  • User Interface?(Presentation Layer): Responsible for presenting information to the user and interpreting user commands.
  • Application Layer:?This layer coordinates the application activity. It doesn't contain any business logic. It does not hold the state of business objects, but it can hold the state of an application task's progress.
  • Domain Layer:?This layer contains information about the business domain. The state of business objects is held here. Persistence of the business objects and possibly their state is delegated to the infrastructure layer.
  • Infrastructure Layer:?This layer acts as a supporting library for all the other layers. It provides communication between layers, implements persistence for business objects, contains supporting libraries for the user interface layer, etc.

Let's look at the application and domain layers in more detail. The Application layer:

  • is responsible for the navigation between the UI screens in the application as well as the interaction with the application layers of other systems.
  • can also perform the basic (non-business related) validation on the user input data before transmitting it to the other (lower) layers of the application.
  • doesn't contain any business or domain related logic or data access logic.
  • doesn't have any state reflecting a business use case but it can manage the state of the user session or the progress of a task.

The domain layer:

  • is responsible for the concepts of business domain, information about the business use case and the business rules. Domain objects encapsulate the state and behavior of business entities. Examples of business entities in a loan processing application are Mortgage, Property, and Borrower.
  • can also manage the state (session) of a business use case if the use case spans multiple user requests (e.g. loan registration process which consists of multiple steps: user entering the loan details, system returning the products and rates based on the loan parameters, user selecting a specific product/rate combination, and finally the system locking the loan for that rate).
  • contains service objects that only have a defined operational behavior which is not part of any domain object. Services encapsulate behavior of the business domain that doesn't fit in the domain objects themselves.
  • is the heart of the business application and should be well isolated from the other layers of the application. Also, it should not be dependent on the application frameworks used in the other layers (JSP/JSF,?Struts, EJB,?Hibernate,?XMLBeans?and so-on).

Figure 2 below shows the different architecture layers used in the application and how they relate to DDD.


Figure 2. Layered Application Architecture diagram (Click on the screen shot to open a full-size view.)

Following design aspects are considered as the main ingredients of the current DDD implementation recipe:

  • Object Oriented Programming (OOP)
  • Dependency Injection (DI)
  • Aspect Oriented Programming (AOP)

OOP is the most important element in the domain implementation. Domain objects should be designed using Plain Java Classes and Interfaces by taking advantage of OOP concepts like inheritance, encapsulation, and polymorphism. Most of the domain elements are true objects with both State (attributes) and Behavior (methods or operations that act on the state). They also correspond to real world concepts and can fit right in with OOP concepts. Entities and Value Objects in DDD are classic examples of OOP concepts since they have both state and behavior.

In a typical Unit of Work (UOW), domain objects need to collaborate with other objects whether they are Services, Repositories or Factories. Domain objects also need to manage other concerns such as domain state change tracking, auditing, caching, transaction management (including transaction retry) which are cross-cutting in nature. These are reusable non-domain related concerns that typically tend to be scattered and duplicated all over the code including the domain layer. Embedding this logic in the domain objects leads to tangling and cluttering of the domain layer with non-domain related code.

When it comes to managing the code dependencies without tight-coupling between objects and isolating cross-cutting concerns, OOP alone cannot provide an elegant design solution for domain driven design and development. This is where design concepts like DI and AOP can be used to complement OOP to minimize tight coupling, enhance modularity and better manage the cross-cutting concerns.

Dependency Injection

DI is a great way to move the configuration and dependency code out of the domain objects. Also, the design dependency of domain classes on Data Access Object (DAO) classes and service classes on domain classes makes DI a "must have" in DDD implementation. DI facilitates a cleaner and loosely coupled design by injecting the other objects such as Repositories and Services into Domain Objects.

In the sample application, the service object (FundingServiceImpl) uses DI to inject the Entity objects (Loan, Borrower and FundingRequest). Also, Entities reference Repositories via DI. Similarly, other Java EE resources like?DataSource, Hibernate?Session Factory?and?Transaction Manager?are injected into Service and Repository objects.

Aspect Oriented Programming

AOP helps in an even better design (i.e. less cluttering in the domain model) by removing the cross-cutting concerns code like auditing, domain state change tracking etc from the domain objects. It can be used to inject collaborating objects and services into domain objects especially the objects that are not instantiated by the container (such as the persistence objects). Other aspects in the domain layer that could use AOP are caching, transaction management and role based security (authorization).

Loan processing application uses custom Aspects to introduce data caching into the Service objects. Loan product and interest rate information is loaded from the database table once (the first this information is requested by the client) and is then stored in an object cache (JBossCache) for subsequent product and rate lookups. Product and rate data is frequently accessed but it's not updated that regularly, so it's a good candidate for caching the data instead of hitting the back-end database every time.

The role of DI and AOP concepts in DDD was the main topic in a recent discussion thread. The discussion was based on a presentation by Ramnivas Laddad where he made the assertion thatDDD cannot be implemented without help of AOP and DI. In the presentation, Ramnivas talked about the concept of "fine grained DI" using AOP to make domain objects regain smart behavior. He mentioned that domain objects need access to other fine grained objects to provide rich behavior and a solution to this is to inject Services, Factories, or Repositories into Domain Objects (by using Aspects to inject dependency at constructor or setter invocation time).

Chris Richardson also discussed about?using DI, objects, and Aspects?to improve the application design by reducing coupling and increasing modularity. Chris talked about "Big Fat Service" anti-pattern which is the result of coupling, tangling and scattering of the application code and how to avoid it using DI and AOP concepts.

Annotations

A recent trend to define and manage Aspects and DI is to use Annotations. Annotations help in minimizing the required artifacts for implementing the remote services such as EJB or Web Services. They also simplify the configuration management tasks.?Spring 2.5,?Hibernate 3?and other frameworks take full advantage of Annotations to configure the components in different layers of a Java enterprise application.

We should take advantage of annotations to generate the boiler plate code where it adds value in terms of flexibility. At the same time, annotations should be used with some caution. They should be used where they are not confusing or misleading in understanding the actual code. A good example of using Annotation is Hibernate ORM mapping where it adds value to specify the SQL table or column name right next to the class or attribute name. On the other hand, details like JDBC driver configuration (driver name, jdbc url, user name, and password) are better suited to be stored in an XML file rather than using Annotations. This is based on the assumption that the database is in the same context. If significant transformations are required between the domain model and the database tables, then the design should take that concern into consideration.

Java EE 5?provides JPA annotations like?@Entity,?@PersistenceUnit,?@PersistenceContext, etc. to add persistence details to plain Java classes. In the context of domain modeling, Entity, Repository and Service are good candidates for using Annotations.

@Configurable?is Spring's way of injecting Repository and Services into a Domain Object. Spring framework extends the "Domain Object DI" idea beyond the @Configurable annotation. Ramnivas recently blogged about the?latest improvements?in upcoming Spring 2.5.2 release (available starting with project snapshot build 379). There are three new aspects (AnnotationBeanConfigurerAspect, AbstractInterfaceDrivenDependencyInjectionAspect, and AbstractDependencyInjectionAspect) to provide simple and more flexible options for Domain Object DI. Ramnivas said the main reason behind introducing the middle aspect (AbstractInterfaceDrivenDependencyInjectionAspect) is to allow domain-specific annotations and interfaces to play a role. Spring also provides other annotations like?@Repository,?@Service, and?@Transactional?to help in the design of the domain classes.

Some of the annotations used in the sample application, Entity objects (Loan, Borrower, and FundingRequest) use @Entity annotation. These objects also use @Configurable annotation to wire the Repository objects. And the Service classes use @Transactional annotation to decorate the service methods with transactional behavior.

Domain model and Security

Application security in the domain layer ensures only authorized clients (human users or other applications) are calling the domain operations as well as accessing the domain state.

Spring Security?(a sub-project in Spring Portfolio) provides a fine-grained access control in both presentation (URL based) and domain (Method Level) layers of the application. The framework uses Spring's Bean Proxy to intercept method invocation and apply security constraints. It offers a role-based declarative security for Java objects using?MethodSecurityInterceptor?class. There is also instance level security in the form of Access Control Lists (ACL's) for domain objects to control the user access at the instance level.

The main advantage of using Spring Security for managing the authorization requirements in the domain model is that the framework has a non-invasive architecture so we can have a clean separation between the domain and security aspects. Also, the business objects are not cluttered with security implementation details. We can write common security rules in one place and apply them (using AOP techniques) wherever they need to be implemented.

In domain and service classes, authorization is managed at the class method invocation level. For example, the "loan approval" method in an Underwriting domain object can be invoked by any user with an "Underwriter" role for loans up to 1 million dollars whereas the approval method in the same domain object for loan applications with a loan amount greater than 1 million dollars can only be called by a user with "Underwriting Supervisor" role.

The following table is a summary of various application security concerns in each layer of the application architecture.

Table 1. Security Concerns in Various Application Layers

LayerSecurity Concern
Client/ControllerAuthentication, Web Page (URL) Level Authorization
FacadeRole based authorization
DomainDomain instance level authorization, ACL
DatabaseDB object level authorization (Stored procedures, Stored functions, Triggers)

Business Rules

Business rules are an important part of the business domain. They define data validation and other constraints that need to be applied on domain objects in specific business process scenarios. Business rules typically fall into the following categories:

  • Data validation
  • Data transformation
  • Business decision-making
  • Process routing (work-flow logic)

The context is very important in DDD world. Context specificity dictates the domain object collaboration as well as other run-time factors like what business rules to apply etc. Validation and other business rules are always processed in a specific business context. This means the same domain object, in a different business context, will have to process different set of business rules. For example, some attributes of a loan domain object (such as loan amount and interest rate) cannot be changed after the loan has been through the Underwriting step in the loan approval process. But the same attributes can be changed when the loan is just registered and locked for a specific interest rate.

Even though all the domain specific business rules should be encapsulated in the domain layer, some application designs put the rules in facade classes, which leads to domain classes becoming "anemic" in terms of business rules logic. This may be an acceptable solution in small size applications, but it is not recommended for mid-size to large enterprise applications that contain complex business rules. A better design option is to put the rules where they belong, inside the domain objects. If a business rule logic spans two or more Entity objects, then it should become part of a Service class.

Also, if we are not diligent in the application, design business rules will end up being coded in the form of several switch statements in the code. And over time as the rules get more complex, developers don't take time to refactor the code to move "switch" statements into a more manageable design. Hardcoding the complex routing or decision-making rules logic in the classes leads to longer methods in the classes, code duplication, and ultimately a rigid application design which will become a maintenance nightmare in the long run. A good design is to place all the rules (especially complex rules that change frequently as the business strategy changes) into a Rules engine (using a rules framework like?JBoss Rules,?OpenRules, orMandarax) and invoke them from the domain classes.

Validation rules are usually implemented in different languages like Javascript, XML, Java code, and other scripting languages. But due to the dynamic nature of business rules, scripting languages such as?Ruby,?Groovy, or?Domain Specific Languages?(DSL) are a better choice to define and manage these rules. Struts (Application layer), Spring (Service) and Hibernate (ORM) all have their own validation modules where we can apply the validation rules on the incoming or outgoing data objects. In some cases, validation rules can also be managed as Aspects (link AOP rules article here) that can be weaved into different layers (e.g. Service and Controller) of the application.

It's important to keep in mind the unit testing aspect when writing the domain classes to manage business rules. Any changes in the rules logic should be easily unit testable in isolation.

The sample application includes a business rule set to validate the loan parameters are within the allowed product and rate specifications. The rules are defined in a scripting language (Groovy) and are applied on the loan data passed to FundingService object.

Design

From a design stand-point, the domain layer should have a well defined boundary to avoid the corruption of the layer from non-core domain layer concerns such as vendor-specific translations, data filtering, transformations, etc. Domain elements should be designed to hold the domain state and behavior correctly. Different domain elements are structured differently based on state and behavior. Table 2 below shows the domain elements and what they contain.

Table 2. Domain elements with state and behavior

Domain ElementState/Behavior
Entity, Value Object, AggregateState and Behavior
Data Transfer ObjectState only
Service, RepositoryBehavior only

Entities, Value Objects, and Aggregates which contain both state (data) and behavior (operations), should have clearly defined state and behavior. At the same time, this behavior should not extend beyond the limits of the object's boundaries. Entities should do most of the work in the use case acting on their local state. But they shouldn't know about too many unrelated concepts.

Good design practice is to only include the getters/setters for the attributes that are required to encapsulate the state of domain objects. When designing the domain objects, only provide setter methods for those fields that can change. Also, the public constructors should contain only the required fields instead of a constructor with all the fields in the domain class.

In most of the use cases, we don't really have to be able to change the state of an object directly. So, instead of changing the internal state, create a new object with the changed state and return the new object. This is sufficient in these use cases and it also reduces design complexity.

Aggregate classes hide the usage of collaborating classes from callers. They can be used for encapsulating complex, intrusive, and state-dependent requirements in the domain classes.

Design Patterns that Support DDD

There are several design patterns that help in domain driven design and development. Following is a list of these design patterns:

  • Domain Object (DO)
  • Data Transfer Object (DTO)
  • DTO Assembler
  • Repository: The Repository contains domain-centric methods and uses the DAO to interact with the database.
  • Generic DAO's
  • Temporal Patterns: These patterns add time dimension to rich domain models.?Bitemporal framework, which is based on Martin Fowler's?Temporal Patterns, provides a design approach to dealing with bitemporal issues in the domain models. The core domain objects and their bitemporal properties can be persisted using an ORM product such as Hibernate.

Other design patterns that are used in DDD include Strategy, Facade, and Factory. Jimmy Nilsson discussed Factory as one of the domain patterns in his?book.

DDD Anti-Patterns

On the flip side of the best practices and design patterns, there are some DDD smells that architects and developers should watch out for when implementing the domain model. As a result of these anti-patterns, domain layer becomes the least important part in application architecture and facade classes assume a more important role in the model. Following are some of these anti-patterns:

  • Anemic domain objects
  • Repetitive DAO's
  • Fat Service Layer: This is where service classes will end up having all the business logic.
  • Feature Envy: This is one of the classic smells mentioned in Martin Fowler's?book?on Refactoring where the methods in a class are far too interested in data belonging to other classes.

Data Access Objects

DAO's and Repositories are also important in domain driven design. DAO is the contract between relational database and the application. It encapsulates the details of database CRUD operations from the web application. On the other hand, a Repository is a separate abstraction that interacts with the DAOs and provides "business interfaces" to the domain model.

Repositories speak the Ubiquitous Language of the domain, work with all necessary DAOs and provide data access services to the domain model in a language the domain understands.

DAO methods are fine-grained and closer to the database while the Repository methods are more coarse-grained and closer to the domain. Also one Repository class may have multiple DAO's injected. Repositories and DAO's keep the domain model decoupled from dealing with the data access and persistence details.

The domain objects should depend only on Repository interfaces. This is the reason why injecting the Repository instead of a DAO results in a much cleaner domain model. DAO classes should never be called directly from the client (Services and other consumer classes). The clients should always call the domain objects which in turn should call the DAO's for persisting the data to the data store.

Managing the dependencies between domain objects (for example, the dependency between an Entity and its Repository) is a classic problem that developers often run into. The usual design solution to this problem is to have the Service or Facade class call a Repository directly and when invoked the Repository would return the Entity object to the client. This design eventually leads to the afore-mentioned Anemic Domain Model where facade classes start accumulating more business logic and domain objects become mere data carriers. A good design is to inject Repositories and Services into domain objects using DI & AOP techniques.

Sample application follows these design principles in implementing the loan processing domain model.

Persistence

Persistence is an infrastructural aspect from which the domain layer should be decoupled. JPA provides this abstraction by hiding the details of the persistence implementation from the classes. It is annotation driven so no XML mapping files are required. But at the same time, the table and column names are embedded in the code which may not be a flexible solution in some cases.

With grid computing products such as Oracle?Coherence, WebSphere Object Grid, andGigaSpaces?that offer data grid solutions, the developers don't even need to think about a RDBMS when they model and design the business domain. The database layer is abstracted from domain layer in the form of an in-memory Object/Data Grid.

Caching

When we talk about the state (data) of the domain layer, we have to talk about the aspect of caching. Frequently accessed domain data (such as products and rates in a mortgage loan processing application) are good candidates for caching. Caching speeds up the performance and reduces the load on the database server. Service layer is ideal for caching the domain state. ORM frameworks like?TopLink?and?Hibernate?also provide data caching.

Loan processing sample application uses JBossCache framework to cache product and rate details to minimize the database calls and improve application performance.

Transaction Management

Transaction management is important to keep the data integrity and to commit or rollback the UOW as a whole. There has always been a debate about where the transactions should be managed in the application architecture layers. There are also the cross-entity transactions (that span multiple domain objects in the same UOW) that affect the design decision of where the transactions should be managed.

Some developers prefer managing the transactions in the DAO classes which is a poor design. This results in too fine-grained transaction control which doesn't give the flexibility of managing the use cases where the transactions span multiple domain objects. Service classes should handle transactions; this way even if the transaction spans multiple domain objects, the service class can manage the transaction since in most of the use cases the Service class handles the control flow.

FundingServiceImpl class in the sample application manages transactions for the funding request and executes multiple database operations by calling the Repositories and commits or rolls back all database changes in a single transactions.

Data Transfer Objects

DTO's are also an important part of the design in an SOA environment where the Domain object model structurally is not compatible with the messages that are received and sent from a business service. The messages are typically defined and maintained in as XML Schema Definition documents (XSD's) and it's a common practice to write (or code generate) DTO objects from the XSD's and use them for data (message) transfer purposes between domain and SOA service layers. Mapping the data from one or more domain objects to a DTO will become a necessary evil in distributed applications where sending the domain objects across the wire may not be practical from a performance and a security stand-point.

From a DDD perspective, DTO's also help maintain the separation between Service and UI layers where DO's are used in the domain and service layers and DTO's are used in the presentation layer.

Dozer?framework is used for the assembly of one or more domain objects into a DTO object. It is bi-directional which saves a lot of extra code and time when converting domain objects into DTO's and vice-versa. The 2-way mapping between DO and DTO objects helps eliminate the separate DO -> DTO and DTO -> DO translation logic. The framework also correctly handles the type and array conversion.

The sample application uses Dozer mapping files (XML) to split the FundingRequestDTO object into Loan, Borrower, and FundingRequest Entity objects when the request comes in for fund processing. The mapping also takes care of the aggregation of the funding response data from the Entities into a single DTO object on the way back to the client.

DDD Implementation Frameworks

Frameworks like Spring and Real Object Oriented (ROO), Hibernate, and Dozer aid in designing and implementing a domain model. Other frameworks that support DDD implementation areJMatter,?Naked Objects,?Ruby On Rails,?Grails, and Spring Modules?XT Framework.

Spring takes care of instantiating and wiring together the domain classes such as Services, Factories, and Repositories. It also injects Services into Entities using @Configurable annotation. This annotation is Spring specific, so other options for achieving this injection is to use something like Hibernate Interceptor.

ROO is a DDD implementation framework built on "domain first and infrastructure second" philosophy. The framework was developed to reduce the boiler-plate coding of the patterns found in web application development. When using ROO, we define the domain model, and then the framework (based on?Maven?Archetypes) generates the code for Model-View-Controller (MVC), DTO's, Business Layer Facade and DAO layers. It even generates the stubs for unit and integration tests.

ROO has some very useful practical implementation patterns. For example, it distinguishes the state managed fields, the persistence layer uses field-level access, and the public constructors only reflect the mandatory fields.

Development

A model is no good without the actual implementation. The implementation phase should include automating the development tasks as much as possible. To see what tasks can be automated, let's look at a typical use case involving the domain model. Following is the list of steps in the use case:

Request In:

  • Client calls a Facade class sending data as an XML document (which is XSD compliant); Facade class initiates a new transaction for the UOW.
  • Run validations on the incoming data. These validations include the primary (basic/data type/field level checks) and business validations. If there are any validation errors, raise appropriate exceptions.
  • Translate the descriptions to codes (to be domain friendly).
  • Make the data formatting changes to be domain model friendly.
  • Make any separation of attributes (like splitting a customer name into first and last name attributes in a Customer Entity object).
  • Disassemble the DTO data into one or more domain objects.
  • Persist the state of domain objects.

Response Out:

  • Get the state of domain object(s) from datastore.
  • Cache the state if necessary.
  • Assemble the domain object(s) into application friendly data objects (DTO).
  • Make any merge or separation of data elements (such as combining first and last names into single customer name attribute).
  • Translate the codes into descriptions.
  • Make the data formatting changes necessary to address the client data usage requirements.
  • Cache the DTO state if necessary
  • Transaction commits (or rolls back if there was an error) as the control flow exits.

The following table shows different objects that carry the data from one layer to another in the application.

Table 3. Data flow through the application layers

LayerFrom ObjectTo ObjectFramework
DAODatabase Table(s)DOHibernate
Domain DelegateDODTODozer
Data TransferDTOXMLJAXB

As you can see there are few layers in the application architecture where same data flows through in different forms (DO, DTO, XML, etc). Most of these objects (Java or XML) that hold data as well as other classes like DAO, DAOImpl, and DAOTest are infrastructural in nature. These classes and XML files that have boiler-plate code and structure are great candidates for code generation.

Code Generation

Frameworks like ROO also create a standard and consistent project template (using Maven plugin) for new projects. Using a pre-generated project template, we can achieve consistency in the directory structure on where to store the source and test classes, configuration files, and dependencies on internal and external (third-party) component libraries.

It could be overwhelming when we consider the myriad of classes and configuration files needed to develop a typical enterprise software application. Code generation is the best way to go about this problem. Code generation tools typically use some kind of template framework to define the templates or mappings from which a code generator can generate the code.?Eclipse Modeling Framework?(EMF) has several sub-projects that aid in the code generation of various artifacts required in a web application project. Model Driven Architecture (MDA) tools like AndroMDA use EMF to generate the code based on architecture models.

When it comes to writing the delegate classes in domain layer I have seen developers writing these classes manually (mostly writing the first one from scratch and then following "Copy And Paste" pattern to create the required delegate classes for other domain objects. Since most of these classes are basically facades to domain classes they are good candidates for code generation. Code generation option is a good long-term solution even though it involves some initial investment (in terms of coding and time) to build and test the code generator (engine).

For the test classes generated, a good option is to create abstract methods for the methods with complex business logic in the main class that need to be unit tested. This way, developers can extend the generated base test class and implement custom business logic which cannot be auto-generated. The same goes for any test method that has testing logic which cannot be auto-created.

Scripting languages are a better choice for writing code generators as they have less overhead and they support template creation and customization options. If we take advantage of code generation in a DDD project, we only need to write a few classes from scratch. The artifacts that must be created from scratch include:

  • XSD
  • Domain Object
  • Service

Once we define the XSD and Java classes, we can code generate all or most of the following classes and configuration files:

  • DAO interface and implementation class
  • Factories
  • Repositories
  • Domain Delegate (if needed)
  • Facade (including EJB and WebService classes)
  • DTO's
  • Unit Tests for the above classes (including test class and test data)
  • Spring configuration files

Table 4 below lists different layers in a web application architecture and what artifacts (Java classes or XML files) can be generated in that layer.

Table 4: Code generation in DDD implementation project

Layer/FunctionPatternCode You WriteGenerated CodeFramework
Data AccessDAO/Repository??DAO Interface,
DAO Implementation class,
DAOTest,
Test Seed Data
Unitils,
DBUnit
DomainDODomain classDomainTest??
PersistenceORMDomain ClassORM Mappings,
ORM Mapping Test
Hibernate,
ORMUnit
Data TransferDTOXSDDTOJAXB
DTO AssemblyAssemblerMappingDO-DTO MappingDozer
DelegateBusiness DelegateCode to translate DO's to DTO's????
Facade??Facade??Remote Service,
EJB,
Web Service
ControllerMVCController Mapping FilesStruts/Spring MVC??
PresentationMVCView configuration filesSpring MVC??

Delegate layer is the only layer that has knowledge of both Domain Objects and DTO's. Other layers such as Persistence layer should be unaware of DTO's.

Refactoring

Refactoring is changing or restructuring the application code without changing the functionality or behavior of the application. Refactoring can be either design or code related. Design refactoring is done to continually refine the model and refactor the code to improve the domain model.

Refactoring plays an important role in the DDD project due to its iterative and evolutionary nature of domain modeling. One way to integrate refactoring tasks into the project is to add it in each iteration of the project before calling the iteration done. Ideally, refactoring should be done before and after every development task.

Refactoring should be done with strict discipline. Use the combination of refactoring, CI, and unit testing to make sure the code changes didn't break any functionality and at the same time the changes did help with the intended code or performance improvements.

Automated tests play a vital role in refactoring the application code. Without good automated developer tests and?Test Driven Development?(TDD) practices, refactoring can be counter-productive since there will be no automated way to verify that the design and code changes made as part of refactoring effort didn't change the behavior or break the functionality.

Tools like?Eclipse?help in implementing the domain model in an iterative way with refactoring as part of the development effort. Eclipse has features like extracting or moving a method to a different class or pushing down a method to a subclass. There are also several code analysis plugins for Eclipse that can help in managing the code dependencies and identifying the DDD anti-patterns. I rely on plugins like?JDepend,?Classycle, and?Metrics?when I do the design and code review of projects, to assess the quality of domain and other modules in the application.

Chris Richardson talked about?applying code refactoring?to transform a procedural design into an OO design using refactoring features provided by Eclipse.

Unit Testing/Continuous Integration

One of the goals we talked about earlier is that the domain classes should be unit testable (during the initial development as well as later when refactoring the existing code) without too many dependencies on the container or other infrastructure code. TDD approach helps the team in finding any design problems early in the project as well as verifying that the code is in alignment with domain model. DDD is ideal for Test-First development because the state and behavior are contained in domain classes and it should be easy to test them in isolation. It is important to test the state and behavior of domain model and not focus too much on the implementation details of data access or persistence.

Unit testing frameworks like JUnit or TestNG are great tools to implement and manage the domain model. Other testing frameworks like?DBUnit?and Unitils can also be used to test domain layer especially to inject test data into DAO classes. This will minimize writing extra code for populating test data in unit test classes.

Mock objects also help in testing the domain objects in isolation. But it's important to not go crazy with using mock objects in the domain layer. If there are other easy ways to test domain classes, you should use those options instead of using mock objects. For example, if you can test an Entity class using a real DAO class in the back-end (instead of a mock DAO implementation) with an in-memory HSQL database instead of the real database; it will make the domain layer unit tests run quicker which is the main idea behind using mock objects any way. This way, you will be testing the collaboration (interaction) between domain objects as well as the state (data) exchanged between them. With mock objects, we will only be testing the interaction between the domain objects.

All unit and integration tests created during the development phase (with or without using TDD practices) will become part of the automated test suite once the development tasks are done. These tests should be maintained and executed frequently in the local and higher development environments to find if the new code changes introduced any bugs into domain classes.

Eric Evans covers CI in his?book?saying that CI effort should always be applied within a Bounded Context and it should include the synchronization of people as well as code. CI tools likeCruiseControl?and?Hudson?can be used to set up an automatic build and test environment to run the application build script (created using a build tool such as?Ant?or Maven) to checkout the code from a SCM repository (like?CVS,?Subversion?etc), compile the domain classes (as well as the other classes in the application) and if there are no build errors, then automatically run all the tests (unit and integration). CI tools can also be setup to notify the project teams (via e-mail or RSS feeds) if there are any build or test errors.

?

Deployment

Domain models are never static; they change as business requirements evolve during the lifecycle of the project and new requirements come up in the new projects. Also, as you develop and implement the domain model you constantly learn and improve, and you want to apply the new knowledge to the existing model.

Isolation is the key when packaging and deploying the domain classes. Since domain layer has dependencies on DAO layer on one side and Service Facade layer on the other (see the application architecture diagram in Figure 2), it makes lot of sense to package and deploy the domain classes as one or more modules to manage these dependencies elegantly.

While design patterns such as DI, AOP and Factories minimize the coupling between the objects at design time and make the application modular,?OSGi?(formerly known as Open Services Gateway initiative) addresses modularity at runtime. OSGi is becoming a standard mechanism to package and distribute the enterprise applications. It nicely handles the dependencies between the modules. We can also use OSGi for domain model versioning purposes.

We can package DAO classes in one OSGi bundle (the DAO bundle), the service facade classes in another bundle (service bundle), so when DAO or Service implementations are modified or a different version of the application is being deployed, thanks to OSGi, no application restarts are required. We can also deploy two different versions of the same domain class if we have to support the existing and new versions of certain domain objects for backward compatibility.

To take advantage of OSGi capabilities, the application objects have to be registered with OSGi platform before being consumed (i.e. before the client can do a lookup for them). This means that we have to use OSGi APIs to do the registration but we also have to deal with failure scenarios as services are started and stopped using OSGi container.?Spring Dynamic Modulesframework helps in this area by allowing any type of object to be exported and imported in the application without any code changes.

Spring DM also provides test classes to run OSGi integration tests outside the container. For example,?AbstractOsgiTests?can be used to run integration tests directly from the IDE. The setup is handled by the testing infrastructure so we don't have to write a MANIFEST.MF file for the test, or do any packaging or deployment. The framework supports most of the OSGi implementations currently available (Equinox,?Knopflerfish?and?Apache Felix).

Loan processing application uses OSGi, Spring DM, and Equinox container to manage the module level dependencies and the deployment of domain and other modules. LoanAppDeploymentTests shows the use of Spring DM test module.

Sample Application Design

The domain classes used in the loan processing sample application are listed below:

Entities:

  • Loan
  • Borrower
  • UnderwritingDecision
  • FundingRequest

Value Objects:

  • ProductRate
  • State

Services:

  • FundingService

Repositories:

  • LoanRepository
  • BorrowerRepository
  • FundingRepository

Figure 3 shows the domain model diagram for the sample application.


Figure 3. Layered Application Domain Model (Click on the screen shot to open a full-size view.)

Most of the DDD design concepts and techniques discussed in this article are applied in the sample application. Concepts like DI, AOP, Annotations, Domain Level Security, and Persistence are used. Also, I used several open source frameworks to help in DDD development and implementation tasks. These frameworks are listed below:

  • Spring
  • Dozer
  • Spring Security
  • JAXB (Spring-WS for marshalling and unmarshalling the data)
  • Spring Testing (for unit and integration testing)
  • DBUnit
  • Spring Dynamic Modules

The domain classes in the sample application are deployed as an OSGi module using Equinox and Spring DM frameworks. The following table shows the module packaging details for the sample application.

Table 5. Packaging and Deployment Details

LayerDeployment Artifact NameModule ContentsSpring Configuration File(s)
Client/Controllerloanapp-controller.jarController, Client Delegate classesLoanAppContext-Controller.xml
Facadeloanapp-service.jarFacade (Remote) Service, Server Delegate classes, XSD'sLoanAppContext-RemoteServices.xml
Domainloanapp-domain.jarDomain classes, DAO, Common DTO'sLoanAppContext-Domain.xml, LoanAppContext-Persistence.xml
Frameworkloanapp-framework.jarFramework, Utility, Monitoring (JMX) classes, AspectsLoanAppContext-Framework.xml, LoanAppContext-Monitoring.xml, LoanApp-Aspects.xml

?

Conclusion

DDD is a powerful concept that will change the way modelers, architects, developers, and testers will look at the software once the team is trained in DDD and start to apply "domain first and infrastructure second" philosophy. As different stakeholders (from IT and business units) with different backgrounds and areas of expertise are involved in the domain modeling, design and implementation effort, to quote Eric Evans, "it's important not to blur the lines between the philosophy of design (DDD) and the technical tool box that helps us fulfill it (OOP, DI, and AOP)".

Advancing Frontiers

This section covers some of the emerging approaches that impact the DDD design and development. Some of these concepts are still evolving and it will be interesting to see how they will affect DDD.

Architecture rules and Design by Contract enforcement plays an important role in the governance and policy enforcement of domain model standards and implementation best practices. Ramnivas?talked?about using the Aspects to enforce the rule of creating a Repository object only through Factories; this is an easy to violate design rule in domain layer.

Domain Specific Languages (DSL) and Business Natural Languages (BNL) are gaining more attention in the recent years. One can use these languages to represent business logic in the domain classes. BNL's are powerful in the sense that they can be used to capture business specifications, documenting the business rules, and as executable code as well. They can also be used to create test cases to verify the system works as expected.

Behavior Driven Development?(BDD) is another interesting concept that has been discussed lately. BDD helps focus development on the delivery of prioritized, verifiable business value by providing a common vocabulary (Ubiquitous Language) that spans the divide between Business and Technology. By using terminology focused on the behavioral aspects of the system rather than testing, BDD attempts to help direct developers towards a focus on the real value to be found in TDD at its most successful. If practiced correctly, BDD can be a great complement to DDD where the development of domain objects is positively influenced by BDD concepts; after all domain objects are supposed to encapsulate state and behavior.

Event Driven Architecture?(EDA) is another area that could play a role in domain driven design. For example, an event model to notify of any state change in the domain object instance would help in handling the post-event processing tasks that need to be triggered when the state of a domain object changes. EDA helps in encapsulating the event based logic from getting embedded in core domain logic. Martin Fowler documented about?Domain Event?design pattern.

Resources

  • Domain-Driven Design, Tackling Complexity in the Heart of Software, Eric Evans, Addison Wesley
  • Applying Domain-Driven Design and Patterns, Jimmy Nilsson, Addison Wesley
  • Refactoring to Patterns, Joshua Kerievsky, Addison Wesley
  • Can DDD be Adequately Implemented Without DI and AOP?

The?sample application code?can be downloaded?here.

轉載于:https://www.cnblogs.com/davidwang456/p/4520483.html

總結

以上是生活随笔為你收集整理的Domain Driven Design and Development In Practice--转载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

337p日本欧洲亚洲大胆裸体艺术 | 91污视频在线观看 | 国产精品久久久久久久久久妇女 | 日韩大陆欧美高清视频区 | 成人影片在线免费观看 | 国产视频一区二区三区在线 | 精品国产伦一区二区三区观看说明 | 亚洲一区二区高潮无套美女 | 欧美综合在线观看 | 日韩 在线观看 | av成人在线网站 | 久久精彩视频 | 国产最新精品视频 | 99亚洲精品在线 | 中文不卡视频 | 免费久久99精品国产 | 婷婷色网址| 亚洲女同videos | 久久综合九色欧美综合狠狠 | 国产啊v在线观看 | 国产精品黄色在线观看 | 日韩中文字幕亚洲一区二区va在线 | 欧美一区二区三区在线视频观看 | 美女网站黄在线观看 | 成人观看视频 | 五月激情婷婷丁香 | 色综合久久99 | 成年人在线电影 | 亚洲好视频 | 色噜噜在线观看视频 | 亚洲成人免费在线观看 | 日韩精品一区二区三区丰满 | 久久99视频精品 | 国产成人一区二区在线观看 | 激情av资源 | 婷婷综合亚洲 | 香蕉视频网站在线观看 | 久久精品视频在线免费观看 | 日韩区欠美精品av视频 | 丁香六月婷婷开心 | 亚洲综合小说电影qvod | 日韩欧美极品 | 日韩精品中文字幕一区二区 | www.天天色.com| 在线免费视频a | 国产中文字幕在线免费观看 | 九九九视频在线 | 久99久中文字幕在线 | 久久看免费视频 | 国产精品一区二区无线 | 国产精品不卡在线播放 | 夜又临在线观看 | 成人久久毛片 | 丁香婷婷基地 | 香蕉精品视频在线观看 | 日韩精品一区二区三区免费观看视频 | 色妞久久福利网 | 成人av在线网 | 精品国产欧美一区二区三区不卡 | 国产精品一区二区在线播放 | 最新av在线播放 | 国产精品v欧美精品v日韩 | 91精品国产自产老师啪 | 久精品视频免费观看2 | 国产一级在线观看 | 国产又粗又猛又黄又爽的视频 | 99色资源 | 草久草久| 成人av免费 | 亚洲国产影院av久久久久 | 高清国产午夜精品久久久久久 | 麻豆视频在线播放 | 在线免费观看黄色 | 国产精品大尺度 | 在线观看国产 | 狠狠色网 | 四虎成人精品永久免费av九九 | 婷婷av电影 | 在线观看网站av | 五月在线 | 午夜色婷婷 | 久久久久福利视频 | 国产精品久久久久久久午夜 | 欧美性生交大片免网 | 亚洲精品视频在线观看免费 | 国产精品久久久电影 | 黄色av一区二区 | 日日麻批40分钟视频免费观看 | 亚洲精品欧美专区 | 亚洲精品在线观看网站 | 欧美性性网| 国产免费高清 | 久久久网页 | 日韩一二三 | 久久免费精品视频 | av资源网在线播放 | www.久久久.cum | 在线综合色 | 免费在线电影网址大全 | 六月婷婷久香在线视频 | 亚洲国产精品电影在线观看 | 狠狠综合久久av | 一级久久精品 | 最近中文字幕高清字幕在线视频 | 天天操天天干天天摸 | 免费视频久久久 | 天天操天天爱天天干 | 日韩特级毛片 | 欧美在线观看视频 | 久久久久高清毛片一级 | 全黄网站 | 日韩av电影一区 | 精品国产乱子伦一区二区 | 久久久在线免费观看 | 51久久成人国产精品麻豆 | 首页av在线 | 97网| 偷拍精偷拍精品欧洲亚洲网站 | 六月激情丁香 | 欧美午夜视频在线 | 草久久精品 | 国产精品伦一区二区三区视频 | 色婷婷视频 | 精品亚洲一区二区三区 | 91人人爱| 麻豆视屏 | 欧美一级黄大片 | 九九九在线观看视频 | 中文字幕一区在线观看视频 | 日本黄色免费电影网站 | 99视频在线免费看 | 久久精品高清 | 在线电影播放 | 国产91精品看黄网站在线观看动漫 | 国产成人av在线影院 | 久久与婷婷 | 黄色国产高清 | 亚洲欧美日韩国产一区二区三区 | 成人一区二区三区在线 | 有没有在线观看av | 日本色小说视频 | 97视频人人 | 免费网站看v片在线a | www.夜夜骑.com | 在线观看免费国产小视频 | 成人片在线播放 | 亚洲精品电影在线 | 99精品久久久久久久 | 91成人短视频在线观看 | av在线影片| 日韩在线看片 | 毛片网在线 | ,久久福利影视 | 天天操天天色天天射 | 粉嫩av一区二区三区免费 | 欧美一二三区在线观看 | 青春草视频 | 国产美女主播精品一区二区三区 | 99久久精品免费看国产 | 免费看的黄色网 | 久久r精品 | 久碰视频在线观看 | 综合婷婷久久 | 久草视频在线免费看 | 成人亚洲免费 | 亚洲欧美视频在线观看 | 狠狠干2018| 热热热热热色 | av成人在线电影 | 九九久久在线看 | 国产精品成人国产乱一区 | 日韩精品一区二区三区第95 | 成年美女黄网站色大片免费看 | v片在线看 | 在线看国产 | 久草在线资源观看 | 亚洲片在线观看 | 免费人成在线观看网站 | 99久久网站| 五月天欧美精品 | 成人一级视频在线观看 | 天天色播| 国产精品久久久久999 | 麻豆传媒视频在线播放 | 亚洲国产精品一区二区久久,亚洲午夜 | 91麻豆精品国产91久久久无限制版 | 天天色天天上天天操 | 日韩欧美区| 亚洲成人精品在线 | 麻豆一区二区三区视频 | 91香蕉国产在线观看软件 | 日本在线观看黄色 | 激情网第四色 | 日韩免费视频观看 | 国产午夜三级 | 国产69精品久久app免费版 | 最近日本字幕mv免费观看在线 | 亚洲人人av | 日本中文字幕高清 | 中文字幕第一 | 98涩涩国产露脸精品国产网 | 欧美大片在线观看一区 | 99久热在线精品视频成人一区 | 夜夜婷婷 | av在线免费在线观看 | 少妇啪啪av入口 | 亚洲天天 | 免费网址你懂的 | 亚洲日本va在线观看 | 高清av免费观看 | 日日综合 | 91天天操 | 久久久国内精品 | www.夜色.com | 天天躁日日躁狠狠躁av中文 | 日韩精品免费一区二区在线观看 | 久久国产精品系列 | 少妇bbb| 日韩在线播放欧美字幕 | 亚洲一区二区视频在线 | 在线观看av不卡 | 国产精品久久久久久久免费观看 | 精品国产视频在线观看 | 五月丁婷婷| 亚洲高清国产视频 | 久久成人福利 | 五月天.com | 国产免费一区二区三区最新 | 午夜精品久久久久久久久久久久 | 91精品国自产在线观看欧美 | 国产亚洲精品精品精品 | 黄色网在线免费观看 | 国产96在线| 91免费视频网站在线观看 | 丁香视频五月 | 国产精选在线 | 欧美精品久久久久性色 | 深夜福利视频在线观看 | 中文字幕 影院 | 欧美综合在线视频 | 九九精品在线观看 | 久久少妇av| 久久精品com | 91视视频在线直接观看在线看网页在线看 | 91综合视频在线观看 | 又黄又爽又刺激的视频 | 国产黄色av网站 | 97人人人人 | 97人人人人| 国产高清不卡一区二区三区 | 亚洲一级二级三级 | 久久影视中文字幕 | 亚洲网站在线看 | 色噜噜狠狠狠狠色综合久不 | 黄色av观看| av网站在线观看免费 | 国产精品午夜久久久久久99热 | 黄污在线观看 | 人人玩人人添人人澡97 | 午夜精品久久久久久久99婷婷 | 噜噜色官网 | 亚洲国产剧情av | 精品国产日本 | 国产区在线视频 | 午夜视频免费在线观看 | 婷婷综合| 亚洲国产精品一区二区久久,亚洲午夜 | 国产精久久久久久久 | 成人午夜在线观看 | 亚洲国产网址 | 日韩天天干| 五月婷婷激情五月 | jizzjizzjizz亚洲| 天天摸日日操 | 在线免费av网 | 国产第一页福利影院 | 国产精品一区二区精品视频免费看 | 毛片3| 欧美a在线免费观看 | 午夜久久久精品 | 国产中文字幕一区二区三区 | 久久精品香蕉 | 麻豆激情电影 | 日韩精品黄 | 久久激情影院 | 欧美日本不卡高清 | 亚洲精品视频第一页 | 91久久国产露脸精品国产闺蜜 | 亚洲欧美日韩精品一区二区 | 亚洲国产影院av久久久久 | 91香蕉视频在线下载 | 午夜三级理论 | 久久久久久看片 | 色婷婷www | 欧美伦理电影一区二区 | 成人免费网视频 | 国产精品综合在线观看 | 91电影福利 | 精品免费99久久 | 国产成人精品综合 | 婷婷久久综合九色综合 | 热久久视久久精品18亚洲精品 | 美女一二三区 | 国产免费又黄又爽 | 国产97视频在线 | 午夜久久久久久久久久影院 | 国内外成人免费在线视频 | 国产99久久久国产精品成人免费 | 国产精品成人国产乱 | 日韩精品一区二区三区在线视频 | 精品一区二区综合 | 精品国偷自产国产一区 | 日韩在线三级 | 欧美一级片| 五月婷婷婷婷婷 | 久草在线| 人九九精品 | 色婷婷www | 免费视频18| 国产精品久久99综合免费观看尤物 | 亚洲精品久久久蜜桃直播 | 天天爱天天操 | 日韩四虎| 在线99视频 | 亚洲成人av电影在线 | 91成人精品视频 | 日韩免费福利 | 国产精品永久在线观看 | 欧美精品二区 | 成人在线播放免费观看 | 日韩色中色 | 91av电影在线 | 一区二区三区免费在线 | www久久99 | 六月激情久久 | 91成年人视频 | 美女免费视频观看网站 | 国产男女免费完整视频 | 国产黄视频在线观看 | 爱射综合| 免费三级大片 | 六月丁香综合网 | 国产精品一区二区三区在线播放 | av综合站 | 欧洲在线免费视频 | 中文字幕无吗 | 在线 国产 亚洲 欧美 | 99re亚洲国产精品 | 黄网站app在线观看免费视频 | 97人人艹| 亚洲精品国产精品久久99 | 欧美福利久久 | 国产在线更新 | 我要色综合天天 | 亚洲综合成人av | 欧美在线观看视频一区二区三区 | 久久国产精品久久精品 | 国内精品久久久久久久影视简单 | 免费高清av在线看 | 精品国产免费人成在线观看 | 国产精品久久99综合免费观看尤物 | www91在线观看 | 天天操狠狠操 | 少妇bbbb| 亚洲精品视频在线看 | 免费观看91视频 | 亚洲色图 校园春色 | 91亚洲激情| 久久三级视频 | 日日摸日日添夜夜爽97 | 国产精品18久久久久久vr | 日韩三级成人 | 国产黄色网 | 91亚洲国产成人久久精品网站 | 天天综合日日夜夜 | 亚洲精品视频免费在线 | 日本黄区免费视频观看 | 最近2019年日本中文免费字幕 | 日日摸日日碰 | 日韩视频专区 | 美女黄久久 | 激情影院在线 | 伊人久久电影网 | free. 性欧美.com | 粉嫩aⅴ一区二区三区 | 免费成人在线电影 | 久久最新网址 | 国产在线色视频 | bbbbb女女女女女bbbbb国产 | 69性欧美| 美女天天操 | 激情五月激情综合网 | 热热热热热色 | 中文字幕欲求不满 | 97视频在线免费 | 免费看黄色毛片 | 五月激情六月丁香 | 91免费视频国产 | 亚洲少妇激情 | 97国产人人| 国产高清成人在线 | 国产午夜一区二区 | 最新婷婷色 | 日韩av高清在线观看 | 99热在 | 国产视频中文字幕在线观看 | 国产3p视频 | 99久久久| 国产午夜麻豆影院在线观看 | 一级性视频 | 国偷自产中文字幕亚洲手机在线 | www久久精品 | 成人91在线观看 | a级国产乱理论片在线观看 特级毛片在线观看 | av免费在线观看1 | 国产视频1| 欧美日韩精品在线免费观看 | 久久久精品二区 | 99久精品视频 | 国产精品av在线 | 人人超碰人人 | 一本大道久久精品懂色aⅴ 五月婷社区 | 97香蕉久久超级碰碰高清版 | 免费在线a | 日日夜夜免费精品 | 国产一区二区在线免费 | 在线播放第一页 | 久久手机精品视频 | 日韩特黄av| 欧美 亚洲 另类 激情 另类 | 国产一级不卡视频 | 国产小视频在线观看 | 亚洲精品国产精品国自 | 亚洲午夜久久久久 | 欧美一区二区三区激情视频 | 亚洲国产免费看 | 亚洲资源在线 | www.com.日本一级 | 国产精品久久久久国产精品日日 | 国产精品久久久久三级 | 99超碰在线播放 | 成人综合日日夜夜 | 久久综合狠狠综合久久狠狠色综合 | 中文字幕在线视频一区 | 免费视频91 | 免费视频国产 | 成人免费观看视频大全 | 欧美专区日韩专区 | 在线观看911视频 | 久久er99热精品一区二区 | 97精产国品一二三产区在线 | 99精品99 | av在线影片 | 日韩av影视在线观看 | 一区av在线播放 | 亚洲 中文 欧美 日韩vr 在线 | 91av视频在线观看免费 | 日韩精品资源 | 日本狠狠色 | 日韩资源在线播放 | 日韩丝袜 | 久久久久久久久久久久影院 | 免费日韩在线 | 韩国av在线| 日韩 在线a| 亚洲免费视频在线观看 | 五月婷香蕉久色在线看 | 日韩精品2区 | 国产免费一区二区三区网站免费 | 国产成人在线一区 | 中文字幕免费高 | 91麻豆精品国产91久久久无限制版 | 久久伦理影院 | 国产成人久久精品77777综合 | 国产淫片 | 久久精品视频2 | 久久国产精品99久久久久久丝袜 | 韩国av免费观看 | 国产精品久久久久久久久久久久 | 97超碰在线播放 | 中文字幕免费国产精品 | 粉嫩一区二区三区粉嫩91 | 色综合色综合久久综合频道88 | 黄色影院在线观看 | 中文字幕精品一区二区精品 | 99爱国产精品 | 久久99这里只有精品 | 欧美黑人猛交 | 五月婷香蕉久色在线看 | 国产成人一二三 | 亚洲精选久久 | 中文字幕久久精品亚洲乱码 | 97超碰色偷偷 | 九九热re| 精品人妖videos欧美人妖 | 亚洲高清视频在线观看免费 | 国产精品一区二区免费视频 | 日韩视频一区二区三区在线播放免费观看 | 国产日韩欧美在线影视 | 蜜桃av人人夜夜澡人人爽 | 亚洲精品国产精品99久久 | 操操操日日日干干干 | 不卡的av在线播放 | 性色av一区二区三区在线观看 | 精品视频www | 久久a久久| 婷婷伊人综合亚洲综合网 | 国产精品精品国产 | 天天插天天狠天天透 | 久久精品视频国产 | 亚洲欧美日韩中文在线 | 亚洲最新av在线网站 | 国产精品久久久久久久av大片 | 欧美日韩国产三级 | 精品久久网 | 成 人 黄 色 视频播放1 | 精品免费一区 | 免费看一级黄色大全 | av片免费播放 | 国产美女视频网站 | 正在播放 国产精品 | av一级在线观看 | 91av免费看 | 亚洲天堂毛片 | 精品欧美一区二区在线观看 | www国产一区 | 日韩免费播放 | 在线观看完整版免费 | 在线看福利av | 黄色av网站在线观看 | 亚洲资源片 | 亚州精品成人 | 欧美老人xxxx18 | 国产91精品一区二区 | 欧美资源 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 日韩av在线不卡 | 久久激情五月婷婷 | 中文字幕免费高 | 在线观看视频你懂 | 成年人国产视频 | 亚洲欧洲国产精品 | 久久一二三四 | 欧美性色综合网 | 色香网 | 亚洲成人动漫在线观看 | 不卡国产视频 | 成人动态视频 | 日日夜夜人人精品 | 久久精品专区 | av韩国在线 | 久久久久综合精品福利啪啪 | 久久久999精品视频 国产美女免费观看 | 91久久久久久久 | 91精品综合| 97视频亚洲 | 精品国产黄色片 | av高清免费在线 | 99热精品国产 | 国产自制av | 国产精品久久久久久久久久久久午 | 国产aaa大片 | www色av| 五月婷婷综合激情 | 欧美日韩免费一区二区三区 | 国产成人精品一区二区在线 | 综合久久久久久久 | 国产精品一区二区美女视频免费看 | 波多野结衣电影一区二区三区 | 国产亚洲视频在线免费观看 | 免费99精品国产自在在线 | 天天视频色 | 免费视频久久久 | 91九色视频导航 | 久久xx视频 | 日韩成人精品一区二区三区 | 在线观看蜜桃视频 | 日本成址在线观看 | 久久99精品久久久久久 | 国产无区一区二区三麻豆 | 六月丁香六月婷婷 | 日本黄色免费在线观看 | 国产精品久久电影网 | 91亚洲精品久久久久图片蜜桃 | 激情视频在线高清看 | 三级av网| 久久久久高清毛片一级 | 午夜黄色| 欧美激情精品久久久久久 | 中文字幕精品www乱入免费视频 | 久久精品毛片基地 | 国产女人18毛片水真多18精品 | 精品9999 | 亚洲精品久久激情国产片 | 黄色小网站免费看 | 91桃色在线免费观看 | 性色大片在线观看 | 中文字幕一区二区三区在线观看 | 在线观看亚洲免费视频 | 国产第一页在线观看 | www.夜色.com| 97成人精品视频在线播放 | 免费成人av在线看 | 日韩黄色一级电影 | 99久久99视频只有精品 | 久久xx视频 | 色a网| 免费看的视频 | 精品欧美在线视频 | 成人免费观看完整版电影 | 国产免费资源 | 中文区中文字幕免费看 | 9797在线看片亚洲精品 | 伊人天堂网 | 五月综合激情 | 久久欧洲视频 | 欧美日韩一区二区免费在线观看 | www.综合网.com| 97国产| 国产精成人品免费观看 | 久久久久观看 | 91中文字幕| 国产精品在线看 | 丁香在线 | 色在线高清 | 久久久久久久久影视 | 综合色中色 | 国产福利精品一区二区 | www.av在线.com | 国产中文字幕视频在线观看 | 免费在线播放视频 | 成人黄色电影在线 | 免费网站在线 | 亚洲国产一区二区精品专区 | 亚洲精品在线国产 | 国产日韩精品在线观看 | 国产无遮挡猛进猛出免费软件 | 日本公妇色中文字幕 | 日韩大片免费在线观看 | 日日麻批40分钟视频免费观看 | 一区二区三区在线观看中文字幕 | 久草电影免费在线观看 | 国语黄色片 | 狠狠狠色狠狠色综合 | 欧美嫩草影院 | 婷久久| 久久九九久久 | 黄色毛片视频免费观看中文 | 久久综合久久综合九色 | 永久免费精品视频网站 | 国产精品精品久久久 | 精品在线二区 | 久草在线一免费新视频 | 色婷婷亚洲精品 | 国产综合精品一区二区三区 | 日韩美精品视频 | 97国产电影 | 亚洲人成人在线 | 久热超碰 | 人人爽人人爽人人爽学生一级 | av片在线观看免费 | 久久国产精品免费一区二区三区 | 99视频在线免费观看 | 欧美一级高清片 | 久久在线视频精品 | 九九热精| 99国产精品久久久久老师 | 天天天天色射综合 | 国产精品亚 | 久久久免费播放 | 国产资源站 | 亚洲精品国偷拍自产在线观看蜜桃 | 久久精品国产一区二区 | 在线观看日韩精品 | 国产精久久久 | 色婷婷狠狠五月综合天色拍 | 精品专区 | 在线看片成人 | av中文字幕第一页 | 国产精品免费在线观看视频 | 超碰av免费| 久草视频精品 | 久草在线这里只有精品 | 亚洲一区网站 | 99热官网| 九九影视理伦片 | 一区二精品 | 国产精品白丝jk白祙 | 欧美一区二区三区在线观看 | 天堂av在线网站 | 在线视频欧美精品 | 日本激情视频中文字幕 | 免费午夜av | 一区二区中文字幕在线 | 久久久九色精品国产一区二区三区 | av.com在线 | 国产精品原创视频 | 97视频一区 | 亚洲国产日韩在线 | www.在线看片.com | 成人avav| 色综合婷婷久久 | 中文字幕一区二区在线播放 | 人人玩人人添人人澡超碰 | 亚洲不卡在线 | 日本少妇久久久 | 成人在线观看日韩 | 日韩精品三区四区 | 人人插超碰| 三级性生活视频 | 亚洲精品97 | 天天干天天操人体 | 天天综合日 | 成人h视频在线 | 综合天天 | 亚洲成人第一区 | 欧洲一区二区三区精品 | 久久成人综合视频 | 99精品观看| 国内精品免费久久影院 | 激情综合网五月激情 | 人人舔人人爽 | 精品av在线播放 | 欧美地下肉体性派对 | 精品欧美一区二区在线观看 | 在线观看视频三级 | 成人精品99 | 91亚色在线观看 | 日韩一区二区三区免费电影 | 999热视频 | 久久永久免费视频 | 9久久精品 | 午夜视频在线观看一区二区 | 天天摸夜夜操 | 中文字幕亚洲精品在线观看 | 在线不卡中文字幕播放 | 久久99精品波多结衣一区 | 手机看片国产日韩 | 国产中文字幕第一页 | 日本中文字幕网址 | 亚洲综合激情五月 | 日韩中文字幕在线观看 | 国产成人av网| 亚洲精品在线视频观看 | 成年人黄色免费看 | 视频99爱 | 亚洲精品小区久久久久久 | 国产二区免费视频 | 婷婷视频在线播放 | 91av视频免费观看 | 国产网站在线免费观看 | 久久久国产精品一区二区中文 | 国产精品永久免费在线 | 久久精品波多野结衣 | 亚洲一级片免费观看 | 国产精品video爽爽爽爽 | 国产1区2区 | 日本99干网| 久久九九免费视频 | 久久国产网站 | 91成人精品 | 精品国产91亚洲一区二区三区www | 一区二区三区高清在线 | 在线观看国产www | 国产电影黄色av | 日韩视频在线播放 | 免费看片成年人 | 日韩一区二区三区免费视频 | 超级碰碰碰免费视频 | 热热热热热色 | 亚洲在线精品视频 | 伊人五月综合 | 91黄色免费网站 | 在线观看视频福利 | 在线不卡视频 | 超碰免费97| 国产精品久久久久久久久久直播 | 91人人爽人人爽人人精88v | bbw av| 96精品视频| 国产亚洲激情视频在线 | 国产网红在线观看 | 亚洲成人二区 | 99免费精品视频 | 国产人成一区二区三区影院 | 精品国产一区二区三区四区vr | 久久国产精品电影 | 日韩免费在线观看 | 在线久草视频 | 久久国产网站 | 久久国产一区 | 国产色视频一区二区三区qq号 | 久久好看 | aaa日本高清在线播放免费观看 | 黄色视屏在线免费观看 | 蜜桃视频日韩 | 韩国一区二区三区视频 | 在线电影a | 亚洲污视频| 丁香婷婷射 | 99视频这里只有 | 久草在线中文888 | 国产精品久久久久四虎 | 日韩一区二区免费视频 | 欧美日韩三级 | 久久男人中文字幕资源站 | 日本二区三区在线 | 久久免费福利视频 | 色婷婷免费 | 久久久久女人精品毛片九一 | 精品国产一区二区三区久久久 | 天天操操 | 综合天堂av久久久久久久 | 一本一本久久a久久精品综合 | 婷婷久久久 | 亚州精品在线视频 | japanesexxxhd奶水| 日本三级久久久 | 欧美亚洲免费在线一区 | 欧美成人精品三级在线观看播放 | 在线国产日韩 | 精品国产乱码久久久久久浪潮 | 99视频国产在线 | 香蕉久久久久 | 91福利国产在线观看 | 亚洲精品美女久久久久网站 | 97视频一区 | www.五月天婷婷.com | 中文字幕在线视频一区 | 国产99久久九九精品免费 | 黄污在线观看 | 久久免费av电影 | 五月天,com| 国产精品九九久久久久久久 | 精品极品在线 | 999成人免费视频 | 五月婷婷丁香六月 | 91在线国内视频 | 久久嗨 | 日本性高潮视频 | 伊人精品在线 | 日韩精品字幕 | 日韩理论在线观看 | 国内毛片毛片 | 手机在线视频福利 | 国产黄色精品在线 | 欧美狠狠操 | 99超碰在线播放 | 伊人六月 | 黄视频色网站 | 欧美与欧洲交xxxx免费观看 | 欧美日韩在线视频观看 | 深夜免费小视频 | 三上悠亚一区二区在线观看 | 国内精品久久久久久 | 亚洲精品免费观看视频 | 久久久久久久国产精品 | 久久综合久久综合久久综合 | 中文字幕字幕中文 | 亚洲午夜久久久影院 | 黄色在线观看污 | 色婷婷免费视频 | 欧美日韩精品电影 | 在线观看中文 | 国产小视频福利在线 | 国产精品女人久久久久久 | 一区 二区 精品 | 日韩av电影中文字幕 | 91麻豆视频网站 | 国产精品麻豆果冻传媒在线播放 | 97在线视频免费 | 精品成人免费 | 美女久久视频 | 操老逼免费视频 | 亚洲国产精品成人va在线观看 | www.成人sex| 黄色成人免费电影 | 狠狠干在线 | 丁香六月色 | 国产精品久久久久久一区二区 | 99久国产 | 久久电影中文字幕视频 | 欧美精品一区在线 | 欧美日韩免费一区二区 | 在线亚洲精品 | 91久久久国产精品 | 成人免费在线观看电影 | 久久爱资源网 | 天干啦夜天干天干在线线 | 91在线91| 91在线www| 亚洲激情校园春色 | 亚洲精品在| 国产精品 中文字幕 亚洲 欧美 | 天天操夜夜干 | 亚洲黄色高清 | 91成人精品一区在线播放69 | 69久久99精品久久久久婷婷 | 久草精品免费 | 欧美影院久久 | 成人a在线观看高清电影 | 亚洲欧美日韩精品久久久 | 欧美色综合天天久久综合精品 | 国产色婷婷精品综合在线手机播放 | 一区二区精品在线 | 99国产精品免费网站 | 精品福利视频在线观看 | 成人午夜剧场在线观看 | 亚洲黄网址 | 成人国产精品久久久久久亚洲 | 99日精品 | 日日摸日日碰 | 九九一级片| 久久伊人八月婷婷综合激情 | 日韩中文字幕视频在线观看 | 亚洲综合一区二区精品导航 | 精品久久久久久一区二区里番 | 国产高清网站 | 欧美人zozo| 成人天堂网 | 91福利专区 | 国产精品欧美激情在线观看 | 成人精品一区二区三区电影免费 | 国产亚洲精品久久19p | 国产午夜精品av一区二区 | 国内外成人在线 | 日韩在线观看你懂的 | 成人免费在线观看电影 | 国色天香第二季 | 欧美日韩久久不卡 | 中文字幕一区二区三区久久蜜桃 | 天天干 天天摸 天天操 | 国产亚洲欧洲 | 国产日本三级 | 97超碰色偷偷 | 欧美视频一区二 | 三级黄色理论片 | 91漂亮少妇露脸在线播放 | 69久久久 | 丁香狠狠 | 极品国产91在线网站 | 毛片网免费 | 麻豆传媒视频在线 | 久久国产精品系列 | 亚洲精品视频在线免费播放 | 日本精油按摩3 | 免费看片日韩 | 国产在线观看h | 97碰碰碰 | 精品国产一区二区三区久久久久久 | 亚洲天堂激情 | 亚洲最新毛片 | 欧美激情视频一区二区三区 | 国产成人精品国内自产拍免费看 | 男女男视频 | 8x成人在线 | 成人免费视频网站在线观看 | 日本九九视频 | 成人av片免费看 | 亚洲国产精品成人av | 激情中文在线 | 黄色网址中文字幕 | 久久久免费精品视频 | 久久久久久久久久久精 | 日韩另类在线 | 日本午夜在线亚洲.国产 | 91色欧美 | 亚洲午夜久久久久久久久久久 | 国产亚洲精品久久久久久久久久久久 | 在线观看一级 | 精品亚洲免费视频 | 伊人久久精品久久亚洲一区 | 亚洲日日日 | 久久精品首页 | 在线免费成人 | 在线视频中文字幕一区 | 激情深爱.com | 伊人视频 | 五月婷婷在线播放 | av电影在线免费 | 亚洲激情在线观看 | 五月婷在线 | 香蕉网站在线观看 | 国内精品久久久久久久久久久 | 91av在 | a视频免费 | 综合色伊人 | 国产精品第72页 | 极品久久久 | 91免费网址 | 草久视频在线观看 | av在线永久免费观看 | 久久视频二区 | 超碰人人在线观看 | 韩国在线视频一区 | 91麻豆精品国产91久久久无需广告 | 国产日韩精品一区二区 | 亚洲免费观看在线视频 |