画布 1
dddsample-core
  com
    aggregator
      HandlingReport
      HandlingReportErrors
      HandlingReportErrors_Exception
      HandlingReportService
      HandlingReportService.wsdl
      HandlingReportServiceService
      ObjectFactory
      package.html
        Generated from the upstream Aggregation Service WSDL 其他服务的公共 api
      package-info.java
      SubmitReport
      SubmitReportResponse
    pathfinder
      api
        GraphTraversalService
        package.html
          Public API for the pathfinder application.
        TransitEdge
        TransitPath
      config
        PathfinderApplicationContext
      internal
        GraphDAO
        GraphDAOStub
        GraphTraversalServiceImpl
        package.html
          Internal parts of the pathfinder application.
      package.html
        This is the pathfinder application context, which is separate from "our" application and context.
Our domain model with cargo, itinerary, handling event etc does not exist here.
The routing domain service implementation works against the API exposed by this context.
It is not related to the core application at all, and is only part of this source tree for developer convenience.
  se
    citerus
      dddsample
        工具和对象模型按照领域模型的边界进行垂直切分
        interfaces
          booking
            facade
              dto
                CargoRoutingDTO.java
                  final field
                    immutable 的数据结构
                  all args constructor
                  getter
                  注意反序列化框架反序列化问题
                LegDTO.java
                LocationDTO.java
                RouteCandidateDTO.java
                package.html
                  immutable
                    在开放窗口里其他的对象，可能 modified on the runtime
                  no behavior
                  accross aggregate boundaries
                  particular section of domain model(relevant data)
                    这样就和 session 解耦了，可以让一些 field 不用全量加载
                  只有分层很多，才有维护多套相似类的必要
              internal
                package.html
                  Internal parts of the remote facade API.
                BookingServiceFacadeImpl.java
                  repo
                    facade 里就可以有 repo 了，但不会具体写 query，只做读操作
                  BookingService bookingService
                    facade 层只能引用 application 层的服务
                  no transaction
                  service method
                    返回 dto
                    实例化 assembler，调用 assembler
                      尽量只做转化，no if-else
                    list all
                      repo.findAll
                    request for id
                    update
                      service.change
                  setters
                assembler
                  CargoRoutingDTOAssembler.java
                    更加适合使用简单工厂方法
                  ItineraryCandidateDTOAssembler.java
                  LocationDTOAssembler.java
                  package.html
                    DTO assemblers.
              BookingServiceFacade.java
              package.html
                Remote service facades with supporting DTO classes and assemblers. Sits on top of the domain service layer, and forms the boundary of the O/R-mapper unit-of-work scope when sending data to the user interface.
            web
              BookingDispatcherServlet.java
                // The booking web application should be standalone,
// and not use the main application context as parent.
              CargoAdminController.java
                包含 facade
                原始 http request
                servlet request binder
                业务请求体 RegistrationCommand
              RegistrationCommand.java
              RouteAssignmentCommand.java
                内部包含 LegCommand
              package.html
                Web user interfaces for booking, routing and re-routing cargo.
          handling
            file
              package.html
                Handles event registration by file upload.
              UploadDirectoryScanner.java
                工具类
                  文件工具类
            ws
              package.html
                Web service interface for registering handling events.
              HandlingReportServiceImpl
                applicationEvents
                  applicationEvents. receivedHandlingEventRegistrationAttempt
                  这里有个领域事件的例子
            HandlingEventRegistrationAttempt.java
            HandlingReportParser.java
            package.html
              Interfaces for receiving handling events into the system.
          tracking
            CargoTrackingController.java
            CargoTrackingViewAdapter.java
              View adapter for displaying a cargo in a tracking context.
              领域模型的集合
                把领域模型的值通过包装过的 display 方法显示出去
            TrackCommand.java
              return ToStringBuilder.reflectionToString(this, MULTI_LINE_STYLE);
              allargsconstructor
              getter
            TrackCommandValidator.java
              对 spring validator 的实现
            package.html
              Public tracking web interface.
        infrastracture
          message 不在 service 层，而在基础设施层。把支撑和非支撑的结构区别出来，再按照领域进行垂直划分。
          messaging
            jms
              CargoHandledConsumer
                直接调用 application service
                通过 eventservice 发出事件
                message 里可以带有字符串消息，也可以带有领域对象
              JmsApplicationEventsImpl
                消息消费者，集成了各种 queue 和底层 service。类似于对 mq 封装的一个服务
                应用层定义的接口也可以在这层被实现，只要它不是编排，而是正交能力。
              package.html
                Asynchronous messaging implemented using JMS. This is part of the infrastructure.
          persistence
            hibernate
              CargoRepositoryHibernate.java
              HandlingEventRepositoryHibernate.java
              HibernateRepository.java
              LocationRepositoryHibernate.java
              VoyageRepositoryHibernate.java
              package.html
                Hibernate implementations of the repository interfaces. This is part of the infrastructure.
            概要
              extends HibernateRepository
                继承 session 获取方法
              implements CargoRepository
                定义操作接口，非泛型，但可泛型
              带有 repository 注解
                通常认为，repository 是 ddd 提出，被 spring 采纳的注解，表名具有【管理存储抽象和实现】的 component。
repository 和 dao 的差别没有定论，通常认为它们都是 DAL 层的实现。
一般认为 dao 是与数据库无关的，只有它的 impl 与数据库有关。
而 repository 里有很多【富请求对象】和【类 collection 操作的方法】，而 dao 里的参数和返回值比较单调。
这一层通常是内聚和协议管理实现得最好的一层。其内部实现只实现 query 的拼装逻辑。
              接收和操作领域对象
          routing
            package.html
              Communicates with the Pathfinder external routing service.
            ExternalRoutingService.java
              领域层定义的领域服务可以在这层被实现。只要它不是编排，而是正交能力。
        domain
          repo 是跟着 domain model 走的，并不放在单独的 repo 文件夹下面
          model
            cargo
              Cargo
                implements Entity<Cargo>
                  entity 有 id，也有 lifecycle
                private TrackingId trackingId;
                private Location origin;
                private RouteSpecification routeSpecification;
                private Itinerary itinerary;
                private Delivery delivery;
                specifyNewRoute
                  不经过 db，但可以用业务逻辑改变自身状态
                it is the root of the Cargo-Itinerary-Leg-Delivery-RouteSpecification aggregate.
              CargoRepository
                Cargo find(TrackingId trackingId);
                List<Cargo> findAll();
              Delivery
                derivedFrom
              HandlingActivity
              Itinerary
              Leg
              package.html
                The cargo aggregate. Cargo is the aggregate root.所以一个 aggregate 是一个文件夹。
              RouteSpecification
              RoutingStatus
              TrackingId
                implements ValueObject<TrackingId>
              TransportStatus
            handling
              CannotCreateHandlingEventException
              HandlingEvent
                event 可以被 store，也可以被 listen，这两个顺序很重要。
这虽然是个 event，但也是个聚合根。
              HandlingEventFactory
                领域能力围绕 aggregate root 摆放，可以脱离富血对象的限制，但不会脱离 aggregate 的边界的限制。
              HandlingEventRepository
              HandlingHistory
              package.html
                The handling aggregate. HandlingEvent is the aggregate root.
              UnknownCargoException
              UnknownLocationException
              UnknownVoyageException
            location
              Location
              LocationRepository
              package.html
              SampleLocations
              UnLocode
            voyage
              CarrierMovement
              package.html
                The voyage aggregate. Voyage is the aggregate root.
              SampleVoyages
              Schedule
              Voyage
              VoyageNumber
              VoyageRepository
            package.html
              The domain model. This is the heart of the application. Each aggregate is contained in
its own subpackage, along with the repository interface, factories and exceptions where
applicable.
Event 和 Entity 都是独一无二可被存储的。
每个 aggregate 最好只有一个 Entity/Event，其他内部对象都是 ValueObject，或者 Specification
          service
            package.html
              Domain services. Those services that may be implemented purely using the domain layer have their implementations here, other implementations may be part of the aplication or infrastructure layers.
              纯粹使用领域层的服务的实现可以放在这里，也可以放在 application 包或者 infrastructure 里。
service 恰好是跨越领域边界的。
            RoutingService
          shared
            这个对象可以通过自己的动词实现对象和对象之间的串并联操作，最终通过 isSatisfied 表达出来
            experimental
              DomainEvent
                所有的 DomainEvent 的实现，都可以携带有领域对象，但如果携带了领域对象，则本事件就要考虑存储和外泄的问题了-不能跨领域上下文传递这类事件
              Entity
              Identity
              package.html
              ValueObject
              ValueObjectSupport
            AbstractSpecification
            AndSpecification
            DomainEvent
              A domain event is something that is unique, but does not have a lifecycle.
The identity may be explicit, for example the sequence number of a payment,
or it could be derived from various aspects of the event such as where, when and what has happened.
              sameEventAs
            DomainObjectUtils
              nullSafe
                actual value, if it's not null, or safe value if the actual value is null.
            Entity
              sameIdentityAs
                Entities compare by identity, not by attributes.
            NotSpecification
            OrSpecification
            package.html
              Pattern interfaces and support code for the domain layer.
              share 层是设计 ddd 特有的领域层的公用模式接口的地方。
所有的 model 模型，都派生自这里面的接口
            Specification
              isSatisfiedBy
              and
              or
              not
            ValueObject
              sameValueAs
                Value objects compare by the values of their attributes, they don't have an identity.
          package.html
            The domain model, services and repository interfaces. This is the central part of the
application. The ubiquitous language is used in classes, interfaces and method signatures,
and every concept in here is familiar to a expert in the cargo shiping domain.
There is no infrastructure or user interface related code here, except for things like
transactional and security metadata which is likely to be relevant to a domain expert
("Either all of foo succeeds or none of it does", "In order to do bar you need to be a Supervisor", and so on).
这个文件夹下的词汇对领域专家来讲是熟悉的。
这里不依赖任何 infrastructure 层的代码（
除了一些和领域专家相关的事务性或者安全元数据相关的操作）。
        config
          DDDSampleApplicationContext
            beanfactory
        application
          impl
            BookingServiceImpl
              private final CargoRepository cargoRepository;
              private final LocationRepository locationRepository;
              private final RoutingService routingService;
            CargoInspectionServiceImpl
              private final ApplicationEvents applicationEvents;
              private final CargoRepository cargoRepository;
              private final HandlingEventRepository handlingEventRepository;
            HandlingEventServiceImpl
            package.html
          util
            DateTestUtil
            package.html
            SampleDataGenerator
          ApplicationEvents
            为什么接口在这一层定义，实现却在 infrastructure 层定义呢？因为 infrastructure 层解决所有 io 介质相关的问题，所有的接口的语义可以留在各层，但实现统一收拢到 infrastructure 层。
这个接口留在这个圈层中，证明事件是个应用层概念-哪个接口留在哪个圈层中，就表明概念的归属哪个圈层。
这里的方法很像一个生产者，但方法的实现看起来都像是消费者
理论上可以存在一个 DomainEvents，存在于领域层，内部领域事件可以在任意层发送。
          BookingService
          CargoInspectionService
          HandlingEventService
          package.html
            This is the application layer: code that's needed for the application to
performs its tasks. It defines, or is defined by, use cases.
It is thin in terms of knowledge of domain business logic,
although it may be large in terms of lines of code.
It coordinates the domain layer objects to perform the actual tasks.
This layer is suitable for spanning transactions, security checks and high-level logging. 这一层就是用例实现层。它对领域知识的理解很薄。它用 coordinates 的方式来编排领域层的对象。
这一层要做的：transaction、安全检查、高层日志。
        这里其实代替了 biz 层，而且有事务，可以对 repo 进行写操作。
所以经典的事件调度和事务编排可以在这一层实现，这种事务上移是一种范式上的转变。