.
, a number of lower-level tactical patterns are used that are of a technical nature, that is, these patterns are used to solve technical problems. These templates are:
, -
,
,
,
,
,
and
. That they will be discussed in this article.
is expressed through these templates in an explicit
. The software model must fully demonstrate the richness of a
in
. If the concept is not expressed using a
, then it should not be represented in the model. If the design is carried out using tactical templates, not paying attention to a
, this means that a lightweight DDD approach is used.
.
used to model it. Such -
can differ greatly in their form over the entire life cycle, however, they can always be uniquely identified and found upon request. For this purpose, unique identifiers are used, the creation of which must be considered first of all when designing an
.java.util.UUID
class that allows you to generate a so-called universally unique identifier in four different ways (time-based, DCE security, name-based, randomly generated UUIDs).046b6c7f-0b8a-43b9-b35d-6489e6daee91
. That is 36 byte string.
at the boundary of the
.APM-P-08-14-2016-046B6C7F
.PM
is a separate design management context; P
- project; 08-14-2016
- the date of creation; 046B6C7F-
is the first segment of the UUID. When such identifiers come across in various
, developers immediately see where they came from.
(for example, using
, as shown in the previous article).
, for example, you can specify a number of attributes (e-mail, account number), which will enable you to define a unique identifier of an external
that can be used as a local identifier. You can also copy some additional state (property) from the external
to the local
.
attribute of the type long
or int
is usually created, a unique identifier is created in the database, and it is used as the primary key. Then the display of this key in the attribute is enabled using ORM tools. Such a surrogate identifier is usually hidden from the outside world, since it is not part of the domain model.
in the subject area. It is quite obvious that the
BankingAccount exists, and to identify it, the use of the account number AccountNumber arises. However, this number is unique only in a separate bank and may be repeated in other banks. (You can use an IBAN number, but this number is mainly used only in banks of the European Union.) That is, in addition to the account number, you can also use the UUID segment. Then our identifier will consist of PFM-A-424214343245-046b6c7f
, where:PFM
- context nameA
- Account424214343245
- account number accountnumber046b6c7f
- part of the UUID-
. It is necessary to examine in detail this very important DDD pattern.-
. To find out if a concept is a
, you need to find out if it has the most of the following characteristics:
.-
instead of
where possible.-
are made mutable. To deny access to fields, the setters methods are usually made private, and the object's constructor is made public, into which all objects that are attribute
are passed. Creating a -
must be an atomic operation.-
it is very important to define an equality check operation. In order for two -
be equal, it is necessary that all types and values ​​of attributes be equal.-
must be
. Since they should not violate the property of immutability, they can return objects, but cannot change the state of an object. public class Money implements Serializable { private BigDecimal amount; private String currency; public Money (BigDecimal anAmount, String aCurrency) { this.setAmount(anAmount); this.setCurrency(aCurrency); } … }
{50 000 }
. Individually, these attributes either describe something else or do not mean anything concrete. This is particularly the case for 50,000 and to some extent for dollars. That is, these attributes form a conceptually
that describes the amount of money. Such integrity of the concept in the domain plays a very important role. It is important to understand that the types of
and the
themselves are named according to a
in their
.
, the nouns of this language are reflected in objects, and the verbs are reflected in the behavior of these objects. Very often there are verbs or some actions that cannot be attributed to an
or an -
. If there is such an operation in the domain, it is declared as
(it differs from the
, which is the client). There are three characteristics of
:
;
. This leads to the creation of an
. Business logic should be distributed over
and
. Only if this cannot be done by following a
, then you need to use
. The main thing is that its interface accurately reflects a
.
from one payer account to the recipient. It is completely unclear in which object to store the translation method, therefore the
used:
necessary.
is what happened in the past tense. Therefore, the name of the
reflects the past time, and the name itself must be assigned in accordance with a
in a
.
very often projected immutable, as well as -
, their functions are
.
modeled as an object whose interface expresses its purpose, and the properties reflect its reason.
timestamp. Next, you must specify the important properties that carry information about what happened. An important property is the identifier of the
or
in which the
generated (accountId). It is also possible for subscribers to be important some parameters of the transition
from one state to another.
be published, and so that they can be processed, you can use the
template, or the -
.
, then you can not use different infrastructure components (they should not exist within the scope of the domain model), but you can simply add the implementation of the
pattern to the model.DomainEventPublisher
object that will store, register all subscribers and publish the
. In this case, the publication for subscribers will go synchronously in a separate cycle and in a single transaction. And each subscriber will be able to work out the
separately.
is a concept of the scale of the
, and not of a separate
. Therefore, it is possible to perform asynchronous
forwarding to
external
using the messaging infrastructure.
notifications is the opposite of publishing using a typical messaging infrastructure. “Publisher” does not support a number of registered “subscribers”, because nothing is sent to interested parties. Instead, the approach requires that REST clients themselves request notifications using a URI resource.
, and that this
reflect the true situation in the model in which it was published.
within a
. This repository is used by the domain model and is also used by an external component that publishes unpublished
using a message passing mechanism. But with this approach, customers need to de-duplicate incoming messages so that when they resend the same event, clients correctly process it.
inside the model are named containers for a certain group of domain objects that are closely related to each other. Their goal is to weaken the links between classes that are in different
. Since the
in the DDD approach are informal or generalized sections, they should be correctly named. The choice of their names is a function of a
.
, which facilitates support and refactoring of modeling concepts. If connectivity is necessary, then you need to fight for acyclic dependencies between peer modules (peers are
that are located on the same level or that have the same weight in the project).
better not to make
static model concepts, since they should change depending on the objects they organize. com.bankingsystems
. It is desirable that the name of this segment be based on the name of the
: com.bankingsystes.pfm
com.bankingsystems.pfm.domain
model can be placed in this section domain. Like this: com.bankingsystems.pfm.domain.account <<Entity>>BankingAccount <<ValueObject>>AccountId
naming would be:om.bankingsystems.resources
om.bankingsystems.resources.view
-
(view storage)om.bankingsystems.application
om.bankingsystems.application.account
-
(submodule of
)
are used to aggregate related domain objects and are separated from objects that are not connected or are loosely connected.
often span multiple modules, because they usually combine all the concepts in one model first, if there are no clear boundaries of contexts.
is the most difficult of all tactical tools DDD.
is a cluster of
objects or
. That is, these objects are considered as a whole from the point of view of changing data.
has a root (Aggregate Root) and a border within which invariants must always be satisfied.
must be made through it
, which is a
globally unique identifier. All internal objects
have only local identity, they can refer to each other as they please. External objects can only store a link to
, and not to internal objects.
, , , .
, , ,
.
,
.
, .
, . ,
-
,
. As mentioned above, they are easier to maintain, test, etc.
can keep the link as the roots of others
. Nor does it put this
within the boundaries of the consistency of the first
. Link does not generate holistic
.
only one change should occur
.
, rather than storing direct links as objects (or pointers). Thus: the memory of objects decreases; they load faster; they are easier to scale.
, then the principle of total consistency should be used. Final consistency can be achieved through publications.
. ,
,
,
, .ustomerId
. ustomer –
, (, , ). , , – .
. , , . . , .
, all invariants must be satisfied.Inquiry
- a specific request for a credit report from other organizations.
is
. He has a global identity. If you need to reference this
, you can only use the identifier
.
report, everything must be deleted
- history and query records.
, .
. . ( : , , , .) , . , . ( , ).
.
.
– , .
.
,
( ).
, . . ( -
) . .-
-:
, .
,
.
.
, , .
, .
, .
, ,
.
- .
:
, , , .
, , , , DDD.
HashMap<ObjectId,Object>
. . , , .
, .
, , ,
save()
. For example:
. , .
, . save()
put()
. .
.
.
.
-
.
-
.
.
, , , ,
.
, ,
, .Source: https://habr.com/ru/post/316890/
All Articles