Addison Wesley : Domain-Driven Design: Tackling Complexity in the Heart of Software

Table of Contents
Domain-Driven Design: Tackling Complexity in the Heart of Software
By Eric Evans
Publisher : Addison Wesley
Pub Date : August 20, 2003
ISBN : 0-321-12521-5
Pages : 560


Cộng đồng phát triển phần mềm công nhận rằng việc mô hình hóa miền là trung tâm của thiết kế phần mềm. Thông qua mô hình hóa miền, các nhà phát triển phần mềm có thể diễn đạt chức năng phong phú và chuyển đổi chức năng đó thành việc triển khai phần mềm thực sự phục vụ nhu cầu của người dùng. Mặc dù tầm quan trọng của nó là rõ ràng, tuy nhiên, có rất ít tài liệu thực tiễn cho thấy cách thức tích hợp mô hình hóa miền hiệu quả vào quy trình phát triển phần mềm.

Thiết kế dựa trên miền đáp ứng nhu cầu đó. Nó cung cấp cho người đọc một phương pháp hệ thống để thiết kế dựa trên miền, trình bày một bộ rộng rãi các thực hành thiết kế tốt nhất, các kỹ thuật dựa trên kinh nghiệm và các nguyên tắc cơ bản giúp phát triển các dự án phần mềm đối mặt với các miền phức tạp. Kết hợp thực hành thiết kế và phát triển, Thiết kế Dựa trên Miền bao gồm nhiều ví dụ trong Java - các nghiên cứu điển hình lấy từ các dự án thực tế minh họa cho việc áp dụng thiết kế dựa trên miền vào phát triển phần mềm trong thế giới thực.

Người đọc sẽ tìm thấy một cái nhìn tổng quan về thiết kế theo miền, nhấn mạnh các nguyên tắc, thuật ngữ và các hệ quả chính. Cuốn sách trình bày một tập hợp các cách làm hay nhất và các mẫu chuẩn cung cấp ngôn ngữ chung cho nhóm phát triển. Ngoài ra, cuốn sách cũng nhấn mạnh cách mà việc tái cấu trúc trong mô hình miền, kết hợp với các chu kỳ lặp thường xuyên của phát triển Agile, dẫn đến cái nhìn sâu sắc hơn về các miền và cải thiện giao tiếp giữa chuyên gia miền và lập trình viên. Dựa trên nền tảng này, cuốn sách sau đó đề cập đến thiết kế theo miền cho các hệ thống phức tạp và các tổ chức lớn hơn.

Các chủ đề cụ thể được đề cập bao gồm:

  • Tách biệt miền

  • Thực thể, đối tượng giá trị, dịch vụ và mô-đun

  • Vòng đời của một đối tượng miền

  • Biểu diễn các quy trình dưới dạng đối tượng miền

  • Tạo ra các hàm không có tác dụng phụ

  • Đường nét khái niệm

  • Lớp độc lập

  • Mở rộng đặc điểm kỹ thuật

  • Áp dụng các mẫu phân tích

  • Liên quan đến các mẫu thiết kế trong mô hình

  • Duy trì tính toàn vẹn của mô hình

  • Xây dựng tuyên bố tầm nhìn lĩnh vực

  • Chọn mục tiêu tái cấu trúc

  • Các lớp trách nhiệm

  • "Tạo ra một khuôn khổ thành phần có thể gắn vào"

  • Mang lại sự kết hợp giữa các cấu trúc quy mô lớn và ngữ cảnh hạn chế

Với cuốn sách này trong tay, các nhà phát triển hướng đối tượng, nhà phân tích hệ thống và nhà thiết kế sẽ có được sự hướng dẫn cần thiết để suy nghĩ sâu sắc về các miền, tạo ra các mô hình miền phong phú và chính xác, và chuyển đổi những mô hình này thành các triển khai phần mềm chất lượng cao, bền vững.


Table of Contents
Domain-Driven Design: Tackling Complexity in the Heart of Software
By Eric Evans

Publisher : Addison Wesley
Pub Date : August 20, 2003
ISBN : 0-321-12521-5
Pages : 560
Copyright
Praise for Domain-Driven Design
Foreword
Preface
Contrasting Three Projects
The Challenge of Complexity
Design Versus Development Process
The Structure of This Book
Who Should Read This Book
A Domain-Driven Team
Acknowledgments
Part I: Putting the Domain Model to Work
Chapter One. Crunching Knowledge
Ingredients of Effective Modeling
Knowledge Crunching
Continuous Learning
Knowledge-Rich Design
Deep Models
Chapter Two. Communication and the Use of Language
Ubiquitous Language
Modeling Out Loud
One Team, One Language
Documents and Diagrams
Explanatory Models
Chapter Three. Binding Model and Implementation
Model-Driven Design
Modeling Paradigms and Tool Support
Letting the Bones Show: Why Models Matter to Users
Hands-On Modelers
Part II: The Building Blocks of a Model-Driven Design
Chapter Four. Isolating the Domain
Layered Architecture
The Domain Layer Is Where the Model Lives
The Smart UI "Anti-Pattern"
Other Kinds of Isolation
Chapter Five. A Model Expressed in Software
Associations
Entities (a.k.a. Reference Objects)
Value Objects
Services
Modules (a.k.a. Packages)
Modeling Paradigms
Chapter Six. The Life Cycle of a Domain Object
Aggregates
Factories
Repositories
Designing Objects for Relational Databases
Chapter Seven. Using the Language: An Extended Example
Introducing the Cargo Shipping System
Isolating the Domain: Introducing the Applications
Distinguishing ENTITIES and VALUE Objects
Designing Associations in the Shipping Domain
AGGREGATE Boundaries
Selecting REPOSITORIES
Walking Through Scenarios
Object Creation
Pause for Refactoring: An Alternative Design of the Cargo AGGREGATE
MODULES in the Shipping Model
Introducing a New Feature: Allocation Checking
A Final Look
Part III: Refactoring Toward Deeper Insight
Chapter Eight. Breakthrough
Story of a Breakthrough
Opportunities
Focus on Basics
Epilogue: A Cascade of New Insights
Chapter Nine. Making Implicit Concepts Explicit
Digging Out Concepts
How to Model Less Obvious Kinds of Concepts
Chapter Ten. Supple Design
Intention-Revealing Interfaces
Side -Effect-Free Functions
Assertions
Conceptual Contours
Standalone Classes
Closure of Operations
Declarative Design
A Declarative Style of Design
Angles of Attack
Chapter Eleven. Applying Analysis Patterns
Example
Earning Interest with Accounts
Example
Insight into the Nightly Batch
Analysis Patterns Are Knowledge to Draw On
Chapter Twelve. Relating Design Patterns to the Model
Strategy (A.K.A.Policy)
Composite
Why Not FLYWEIGHT?
Chapter Thirteen. Refactoring Toward Deeper Insight
Initiation
Exploration Teams
Prior Art
A Design for Developers
Timing
Crisis as Opportunity
Part IV: Strategic Design
Chapter Fourteen. Maintaining Model Integrity
Bounded Context
Continuous Integration
Context Map
Relationships Between BOUNDED CONTEXTS
Shared Kernel
Customer/Supplier Development Teams
Conformist
Anticorruption Layer
Separate Ways
Open Host Service
Published Language
Unifying an Elephant
Choosing Your Model Context Strategy
Transformations
Chapter Fifteen. Distillation
Core Domain
An Escalation of Distillations
Generic Subdomains
Domain Vision Statement
Highlighted Core
Cohesive Mechanisms
Segregated Core
Abstract Core
Deep Models Distill
Choosing Refactoring Targets
Chapter Sixteen. Large-Scale Structure
Evolving Order
System Metaphor
Responsibility Layers
Knowledge Level
Pluggable Component Framework
How Restrictive Should a Structure Be?
Refactoring Toward a Fitting Structure
Chapter Seventeen. Bringing the Strategy Together
Combining Large-Scale Structures and BOUNDED CONTEXTS
Combining Large-Scale Structures and Distillation
Assessment First
Who Sets the Strategy?
Six Essentials for Strategic Design Decision Making
Conclusion
Epilogues
Looking Forward
Appendix The Use of Patterns in This Book
Pattern Name
GLOSSARY
References
PHOTO CREDITS

Copyright

Nhiều tên gọi được các nhà sản xuất và người bán sử dụng để phân biệt sản phẩm của họ được coi là thương hiệu. Khi những tên gọi đó xuất hiện trong cuốn sách này và Addison-Wesley biết về một yêu cầu thương hiệu, các tên gọi đó đã được in với chữ cái đầu in hoa hoặc in toàn bộ chữ hoa.

Tác giả và nhà xuất bản đã cẩn thận trong việc chuẩn bị cuốn sách này, nhưng không đưa ra bất kỳ bảo đảm nào, rõ ràng hay ngụ ý, và không chịu trách nhiệm về lỗi hoặc thiếu sót. Không chịu trách nhiệm về thiệt hại ngẫu nhiên hoặc theo hậu quả liên quan đến hoặc phát sinh từ việc sử dụng thông tin hoặc chương trình có trong đây.

Xem trang 517 để biết thông tin về bản quyền ảnh.

Nhà xuất bản cung cấp giảm giá cho cuốn sách này khi đặt hàng số lượng lớn cho các giao dịch mua sỉ và bán hàng đặc biệt. Để biết thêm thông tin, vui lòng liên hệ:

Bán hàng cho Doanh nghiệp và Chính phủ tại Hoa Kỳ (800) 382-3419 corpsales@pearsontechgroup.com

Đối với các đơn hàng ngoài Hoa Kỳ, vui lòng liên hệ:

Bán hàng quốc tế (317) 581-3793 international@pearsontechgroup.com

Truy cập Addison-Wesley trên web: www.awprofessional.com

Dữ liệu phân loại theo ấn phẩm của Thư viện Quốc hội

Evans, Eric, 1962– Thiết kế hướng miền: giải quyết các phức tạp trong lõi của phần mềm / Eric Evans. p. cm. Bao gồm tài liệu tham khảo và mục lục. ISBN 0-321-12521-5 1. Phát triển phần mềm máy tính. 2. Lập trình hướng đối tượng (Khoa học máy tính) I. Tiêu đề. QA76.76.D47E82 2003 005.1–dc21 2003050331

Bản quyền © 2004 bởi Eric Evans

Tất cả các quyền được bảo lưu. Không phần nào của ấn phẩm này được phép sao chép, lưu trữ trong hệ thống truy xuất, hoặc truyền tải, dưới bất kỳ hình thức nào, hoặc bằng bất kỳ phương tiện nào, điện tử, cơ khí, photocopy, ghi âm, hoặc hình thức nào khác, mà không có sự đồng ý trước của nhà xuất bản. In tại Hoa Kỳ. Xuất bản đồng thời tại Canada.

Để biết thông tin về việc xin phép sử dụng tài liệu từ công trình này, xin vui lòng gửi yêu cầu bằng văn bản đến:

Công ty Giáo dục Pearson, Inc. Phòng Quyền và Hợp đồng 75 Phố Arlington, Suite 300 Boston, MA 02116 Fax: (617) 8487047

Văn bản in trên giấy tái chế

Một Hai Ba Bốn Năm Sáu Bảy Tám Chín Mười—CRW—0706050403

Xuất bản lần đầu, tháng 8 năm 2003

Dedication

Gửi Mẹ và Bố


    Praise for Domain-Driven Design

    "Cuốn sách này xứng đáng được đặt trên kệ của mọi lập trình viên phần mềm có tư duy."

    Kent Beck

    "Eric Evans đã viết một cuốn sách tuyệt vời về cách bạn có thể làm cho thiết kế phần mềm của mình phù hợp với mô hình tâm trí của bạn về miền vấn đề mà bạn đang giải quyết."

    "Cuốn sách của anh ấy rất phù hợp với XP. Nó không phải là về việc vẽ hình ảnh của một miền; mà là cách bạn nghĩ về nó, ngôn ngữ bạn sử dụng để nói về nó, và cách bạn tổ chức phần mềm của mình để phản ánh sự hiểu biết ngày càng nâng cao của bạn về nó. Eric nghĩ rằng việc học về miền vấn đề của bạn có khả năng xảy ra vào cuối dự án của bạn cũng như vào đầu, vì vậy việc tái cấu trúc là một phần quan trọng trong kỹ thuật của anh ấy."

    Cuốn sách này rất thú vị. Eric có nhiều câu chuyện thú vị, và anh ấy có một cách diễn đạt rất hay. Tôi xem cuốn sách này như là tài liệu thiết yếu cho các nhà phát triển phần mềm - nó sẽ trở thành một tác phẩm kinh điển trong tương lai.

    Ralph Johnson, tác giả của Design Patterns

    "Nếu bạn không nghĩ rằng bạn đang thu được giá trị từ khoản đầu tư của mình vào lập trình hướng đối tượng, cuốn sách này sẽ cho bạn biết những gì bạn đã quên làm."

    Ward Cunningham

    "Những gì Eric đã nắm bắt được là một phần của quy trình thiết kế mà các nhà thiết kế đồ vật giàu kinh nghiệm luôn sử dụng, nhưng mà chúng ta đã không thành công trong việc truyền đạt điều này cho phần còn lại của ngành. Chúng ta đã chia sẻ những mảnh ghép của kiến thức này... nhưng chúng ta chưa bao giờ tổ chức và hệ thống hóa các nguyên tắc xây dựng logic lĩnh vực. Cuốn sách này rất quan trọng."

    Kyle Brown, tác giả của sách Lập trình Java Doanh nghiệp với IBM WebSphere

    "Eric Evans thuyết phục lập luận về tầm quan trọng của mô hình miền như là trọng tâm chính của phát triển và cung cấp một khung công tác vững chắc cùng một tập hợp các kỹ thuật để thực hiện điều đó. Đây là một trí tuệ vượt thời gian, và sẽ tồn tại lâu dài sau khi các phương pháp đang thịnh hành lớp lang đã trở nên lỗi thời."

    Ðave Collins, tác giả của cuốn Thiết kế Giao diện Người dùng Hướng đối tượng

    "Eric kết hợp kinh nghiệm thực tế trong việc mô hình hóa và xây dựng các ứng dụng kinh doanh vào một cuốn sách thực tiễn và hữu ích. Được viết từ góc nhìn của một chuyên gia đáng tin cậy, những mô tả của Eric về ngôn ngữ phổ quát, lợi ích của việc chia sẻ mô hình với người dùng, quản lý vòng đời đối tượng, cấu trúc ứng dụng logic và vật lý, cũng như quy trình và kết quả của việc tái cấu trúc sâu là những đóng góp quan trọng cho lĩnh vực của chúng ta."

    Luke Hohmann, tác giả của Beyond Software Architecture


      Foreword

      Có nhiều yếu tố khiến phát triển phần mềm trở nên phức tạp. Nhưng cốt lõi của sự phức tạp này là sự tinh vi thiết yếu của miền vấn đề. Nếu bạn đang cố gắng thêm tự động hóa vào các doanh nghiệp phức tạp của con người, thì phần mềm của bạn không thể tránh được sự phức tạp này—tất cả những gì nó có thể làm là kiểm soát nó.

      Chìa khóa để kiểm soát sự phức tạp là một mô hình miền tốt, một mô hình vượt ra ngoài tầm nhìn bề mặt của một miền bằng cách giới thiệu một cấu trúc cơ sở, điều này cung cấp cho các nhà phát triển phần mềm sự hỗ trợ cần thiết. Một mô hình miền tốt có thể vô cùng quý giá, nhưng không phải là thứ dễ dàng để tạo ra. Rất ít người có thể làm điều đó tốt, và rất khó để dạy.

      Eric Evans là một trong số ít người có khả năng tạo ra các mô hình miền một cách xuất sắc. Tôi đã nhận ra điều này khi làm việc với anh ấy—một trong những khoảng thời gian tuyệt vời khi bạn gặp một khách hàng có kỹ năng hơn cả mình. Sự hợp tác của chúng tôi ngắn ngủi nhưng thực sự thú vị. Kể từ đó, chúng tôi vẫn giữ liên lạc, và tôi đã quan sát quyển sách này từ từ hình thành.

      Thật sự xứng đáng để chờ đợi.

      Cuốn sách này đã phát triển thành một tác phẩm thỏa mãn một tham vọng lớn: mô tả và xây dựng một từ vựng về chính nghệ thuật mô hình miền. Cung cấp một khung tham chiếu qua đó chúng ta có thể giải thích hoạt động này cũng như dạy kỹ năng khó học này. Đây là một cuốn sách đã cho tôi nhiều ý tưởng mới khi nó hình thành, và tôi sẽ rất ngạc nhiên nếu ngay cả những người có kinh nghiệm lâu năm trong mô hình khái niệm cũng không nhận được một loạt ý tưởng mới từ việc đọc cuốn sách này.

      Eric cũng củng cố nhiều điều mà chúng ta đã học được qua nhiều năm. Đầu tiên, trong mô hình miền, bạn không nên tách rời các khái niệm khỏi việc triển khai. Một người lập mô hình miền hiệu quả không chỉ có thể sử dụng bảng trắng với một kế toán viên, mà còn có thể viết Java cùng với một lập trình viên. Phần nào đó điều này đúng vì bạn không thể xây dựng một mô hình khái niệm hữu ích mà không xem xét các vấn đề triển khai. Nhưng lý do chính mà các khái niệm và việc triển khai thuộc về nhau là: Giá trị lớn nhất của một mô hình miền là nó cung cấp một ngôn ngữ phổ quát liên kết các chuyên gia miền và công nghệ với nhau.

      Một bài học khác bạn sẽ rút ra từ cuốn sách này là các mô hình miền không được mô hình hóa trước và sau đó mới được triển khai. Giống như nhiều người, tôi đã từ chối cách suy nghĩ phân pha "thiết kế, rồi xây dựng." Nhưng bài học từ kinh nghiệm của Eric là những mô hình miền thực sự mạnh mẽ phát triển theo thời gian, và ngay cả những người mô hình hóa dày dạn kinh nghiệm cũng nhận ra rằng họ có được những ý tưởng tốt nhất sau các phiên bản ban đầu của một hệ thống.

      Tôi nghĩ và hy vọng rằng đây sẽ là một cuốn sách có ảnh hưởng to lớn. Một cuốn sách sẽ thêm cấu trúc và sự gắn kết cho một lĩnh vực rất trơn trượt trong khi dạy cho nhiều người cách sử dụng một công cụ quý giá. Mô hình miền có thể có những hậu quả lớn trong việc kiểm soát phát triển phần mềm—dù trong ngôn ngữ hay môi trường nào mà chúng được triển khai.

      Một suy nghĩ cuối cùng nhưng quan trọng. Một trong những điều tôi rất tôn trọng về cuốn sách này là Eric không ngại nói về những lúc anh ấy không thành công. Hầu hết các tác giả thích duy trì một vẻ ngoài không quan tâm và toàn năng. Eric làm rõ rằng, như hầu hết chúng ta, anh ấy đã nếm trải cả thành công lẫn thất bại. Điều quan trọng là anh ấy có thể học hỏi từ cả hai điều này - và điều quan trọng hơn đối với chúng ta là anh ấy có thể truyền đạt những bài học của mình.

      Martin Fowler Tháng 4 năm 2003


        Preface

        Các nhà thiết kế phần mềm hàng đầu đã công nhận mô hình miền và thiết kế là những chủ đề quan trọng trong ít nhất 20 năm qua, nhưng thật bất ngờ là rất ít tài liệu đã được viết về những gì cần phải làm hoặc cách thực hiện nó. Mặc dù chưa bao giờ được diễn đạt một cách rõ ràng, một triết lý đã nổi lên như một dòng chảy ngầm trong cộng đồng đối tượng, một triết lý mà tôi gọi là thiết kế theo miền.

        Tôi đã dành cả thập kỷ qua để phát triển các hệ thống phức tạp trong nhiều lĩnh vực kinh doanh và kỹ thuật. Trong công việc của mình, tôi đã áp dụng các phương pháp tốt nhất trong thiết kế và quy trình phát triển khi chúng xuất hiện từ những người đi đầu trong phát triển hướng đối tượng. Một số dự án của tôi rất thành công; vài dự án không thành công. Một tính năng chung ở các dự án thành công là một mô hình miền phong phú, đã phát triển qua các lần lặp thiết kế và trở thành một phần không thể thiếu của dự án.

        Cuốn sách này cung cấp một khung khổ để đưa ra các quyết định thiết kế và một từ vựng kỹ thuật để thảo luận về thiết kế miền. Đây là sự tổng hợp của các phương pháp tốt nhất được chấp nhận rộng rãi cùng với những hiểu biết và kinh nghiệm riêng của tôi. Các nhóm phát triển phần mềm đối mặt với các miền phức tạp có thể sử dụng khung này để tiếp cận thiết kế được điều khiển bởi miền một cách có hệ thống.


          Contrasting Three Projects

          Ba dự án nổi bật trong ký ức của tôi như những ví dụ sống động về cách mà thực tiễn thiết kế miền có thể ảnh hưởng đáng kể đến kết quả phát triển. Mặc dù cả ba dự án đều cung cấp phần mềm hữu ích, chỉ có một dự án đạt được các mục tiêu đầy tham vọng và sản xuất phần mềm phức tạp tiếp tục phát triển để đáp ứng nhu cầu liên tục của tổ chức.

          Tôi đã thấy một dự án được khởi đầu nhanh chóng bằng cách cung cấp một hệ thống giao dịch dựa trên web đơn giản và hữu ích. Các nhà phát triển đã làm việc một cách vội vàng, nhưng điều này không cản trở họ vì phần mềm đơn giản có thể được viết mà không cần quá chú ý đến thiết kế. Kết quả của sự thành công ban đầu này là kỳ vọng cho việc phát triển trong tương lai trở nên rất cao. Đó là khi tôi được yêu cầu làm việc trên phiên bản thứ hai. Khi tôi xem xét kỹ lưỡng, tôi thấy họ thiếu một mô hình miền, thậm chí là một ngôn ngữ chung trong dự án, và bị ràng buộc bởi một thiết kế không có cấu trúc. Các nhà lãnh đạo dự án không đồng ý với đánh giá của tôi, và tôi đã từ chối công việc này. Một năm sau, đội ngũ đã gặp khó khăn và không thể phát hành được phiên bản thứ hai. Mặc dù việc sử dụng công nghệ của họ không phải là một tấm gương tốt, nhưng chính logic kinh doanh đã khiến họ lạc lối. Phiên bản phát hành đầu tiên của họ đã trở nên cứng nhắc sớm và trở thành một di sản khó bảo trì.

          Việc gỡ bỏ giới hạn này về độ phức tạp đòi hỏi một cách tiếp cận nghiêm túc hơn đối với việc thiết kế logic miền. Đầu sự nghiệp của mình, tôi đã may mắn tham gia vào một dự án nhấn mạnh đến thiết kế miền. Dự án này, trong một lĩnh vực ít nhất cũng phức tạp như dự án đầu tiên, cũng bắt đầu với một thành công ban đầu khiêm tốn, cung cấp một ứng dụng đơn giản cho các nhà giao dịch tổ chức. Nhưng trong trường hợp này, việc giao hàng ban đầu đã theo sau bằng những gia tốc phát triển liên tiếp. Mỗi vòng lặp mở ra những tùy chọn mới thú vị để tích hợp và phát triển chức năng của phiên bản trước đó. Nhóm đã có thể phản ứng linh hoạt và mở rộng khả năng theo nhu cầu của các nhà giao dịch. Đường đi lên này hoàn toàn có thể quy cho một mô hình miền sâu sắc, được tinh chỉnh liên tục và thể hiện qua mã. Khi nhóm có được những hiểu biết mới về miền, mô hình đã trở nên sâu sắc hơn. Chất lượng giao tiếp không chỉ cải thiện giữa các lập trình viên mà còn giữa các lập trình viên và các chuyên gia miền, và thiết kế - xa hơn là việc tạo ra một gánh nặng bảo trì ngày càng nặng nề - đã trở nên dễ dàng để sửa đổi và mở rộng.

          Thật không may, các dự án không thể đạt được chu kỳ tích cực như vậy chỉ bằng cách xem trọng các mô hình. Một dự án trong quá khứ của tôi bắt đầu với những khát vọng lớn lao để xây dựng một hệ thống doanh nghiệp toàn cầu dựa trên mô hình miền, nhưng sau nhiều năm thất vọng, nó đã hạ thấp tham vọng và chấp nhận sự thông thường. Nhóm đã có công cụ tốt và hiểu biết tốt về doanh nghiệp, đồng thời chú ý cẩn thận đến việc mô hình hóa. Nhưng một sự phân chia vai trò phát triển không hợp lý đã làm cho việc mô hình hóa bị tách rời khỏi việc triển khai, khiến cho thiết kế không phản ánh được phân tích sâu sắc đang diễn ra. Dù sao đi nữa, thiết kế của các đối tượng kinh doanh chi tiết không đủ nghiêm ngặt để hỗ trợ việc kết hợp chúng trong các ứng dụng phức tạp. Việc lặp đi lặp lại không mang lại cải tiến nào cho mã nguồn, do trình độ kỹ năng không đồng đều giữa các nhà phát triển, những người không có nhận thức về thân bài phong cách và kỹ thuật không chính thức để tạo ra các đối tượng dựa trên mô hình cũng hoạt động như phần mềm thực tế. Khi thời gian trôi qua, công việc phát triển trở nên kẹt trong sự phức tạp và nhóm mất đi tầm nhìn đồng nhất về hệ thống. Sau nhiều năm nỗ lực, dự án đã sản xuất ra phần mềm hữu ích, nhưng nhóm đã từ bỏ tham vọng ban đầu cùng với sự tập trung vào mô hình.


            The Challenge of Complexity

            Nhiều yếu tố có thể làm dự án đi chệch hướng: thủ tục hành chính, mục tiêu không rõ ràng và thiếu nguồn lực, chỉ để kể tên một vài yếu tố. Nhưng chính cách tiếp cận thiết kế chủ yếu xác định mức độ phức tạp của phần mềm có thể trở nên như thế nào. Khi độ phức tạp vượt quá tầm kiểm soát, các nhà phát triển không còn hiểu rõ phần mềm đủ để thay đổi hoặc mở rộng nó một cách dễ dàng và an toàn. Ngược lại, một thiết kế tốt có thể tạo ra cơ hội để khai thác những tính năng phức tạp đó.

            Một số yếu tố thiết kế là công nghệ. Rất nhiều nỗ lực đã được thực hiện trong việc thiết kế các mạng, cơ sở dữ liệu và các khía cạnh kỹ thuật khác của phần mềm. Nhiều cuốn sách đã được viết về cách giải quyết những vấn đề này. Rất nhiều nhà phát triển đã trau dồi kỹ năng của họ và theo dõi từng bước tiến kỹ thuật.

            Tuy nhiên, độ phức tạp đáng kể nhất của nhiều ứng dụng không phải là kỹ thuật. Nó nằm trong lĩnh vực chính, hoạt động hoặc kinh doanh của người dùng. Khi độ phức tạp trong lĩnh vực này không được xử lý trong thiết kế, thì công nghệ hạ tầng có được thiết kế tốt đến đâu cũng sẽ không còn ý nghĩa. Một thiết kế thành công phải hệ thống giải quyết khía cạnh trung tâm này của phần mềm.

            Nền tảng của cuốn sách này có hai phần:

            1. Đối với hầu hết các dự án phần mềm, trọng tâm chính nên đặt vào miền và logic miền.

            Các thiết kế miền phức tạp nên được dựa trên một mô hình.

            Thiết kế hướng miền vừa là một cách suy nghĩ vừa là một tập hợp các ưu tiên, nhằm mục đích tăng tốc các dự án phần mềm có phải xử lý các miền phức tạp. Để đạt được mục tiêu đó, cuốn sách này trình bày một tập hợp phong phú các thực hành, kỹ thuật và nguyên tắc thiết kế.


              Design Versus Development Process

              Sách thiết kế. Sách quy trình. Chúng hiếm khi tham chiếu đến nhau. Mỗi chủ đề đều phức tạp theo cách riêng của nó. Đây là một cuốn sách thiết kế, nhưng tôi tin rằng thiết kế và quy trình là không thể tách rời. Các khái niệm thiết kế phải được thực hiện thành công, nếu không chúng sẽ chỉ còn lại là những cuộc thảo luận học thuật.

              Khi mọi người học các kỹ thuật thiết kế, họ cảm thấy hào hứng với những khả năng. Sau đó, thực tế rối rắm của một dự án thực tế ập xuống họ. Họ không thể kết hợp các ý tưởng thiết kế mới với công nghệ mà họ phải sử dụng. Hoặc họ không biết khi nào nên từ bỏ một khía cạnh thiết kế cụ thể vì lợi ích của thời gian và khi nào cần kiên quyết tìm ra một giải pháp sạch sẽ. Các nhà phát triển có thể và thực sự nói chuyện với nhau một cách trừu tượng về việc ứng dụng các nguyên tắc thiết kế, nhưng tự nhiên hơn là nói về cách những việc thực tế được hoàn thành. Vì vậy, mặc dù đây là một cuốn sách về thiết kế, tôi sẽ vượt qua ranh giới nhân tạo đó vào quy trình khi cần thiết. Điều này sẽ giúp đặt các nguyên tắc thiết kế vào bối cảnh.

              Cuốn sách này không gắn liền với một phương pháp cụ thể nào, nhưng nó được định hướng theo gia đình mới của "Quy trình phát triển Agile." Cụ thể, nó giả định rằng có một vài thực hành đã được triển khai trong dự án. Hai thực hành này là điều kiện tiên quyết để áp dụng phương pháp trong cuốn sách này.

              1. Phát triển là một quá trình lặp đi lặp lại. Phát triển lặp đi lặp lại đã được khuyến khích và thực hành trong nhiều thập kỷ, và nó là một thành phần chính của các phương pháp phát triển Agile. Có nhiều cuộc thảo luận tốt trong tài liệu về phát triển Agile và Lập trình cực đoan (hoặc XP), trong số đó có "Surviving Object-Oriented Projects" (Cockburn 1998) và "Extreme Programming Explained" (Beck 1999).

              Các nhà phát triển và các chuyên gia miền có mối quan hệ chặt chẽ. Thiết kế theo miền tập hợp một khối lượng lớn kiến thức thành một mô hình phản ánh sự hiểu biết sâu sắc về miền và tập trung vào các khái niệm chính. Đây là sự hợp tác giữa những người hiểu biết về miền và những người biết cách xây dựng phần mềm. Bởi vì phát triển là một quá trình lặp lại, sự hợp tác này phải tiếp tục trong suốt vòng đời của dự án.

              Extreme Programming, được nghĩ ra bởi Kent Beck, Ward Cunningham, và những người khác (xem Extreme Programming Explained [Beck 2000]), là phương pháp Agile nổi bật nhất và là phương pháp mà tôi đã làm việc nhiều nhất. Trong suốt cuốn sách này, để làm cho các giải thích trở nên cụ thể, tôi sẽ sử dụng XP làm cơ sở cho việc thảo luận về sự tương tác giữa thiết kế và quy trình. Các nguyên tắc được minh họa có thể dễ dàng được điều chỉnh cho các phương pháp Agile khác.

              Trong những năm gần đây, đã có một cuộc nổi dậy chống lại các phương pháp phát triển phức tạp làm nặng nề các dự án với những tài liệu tĩnh vô nghĩa và kế hoạch cùng thiết kế quá tỉ mỉ. Thay vào đó, các quy trình Agile, chẳng hạn như XP, nhấn mạnh khả năng đối phó với sự thay đổi và không chắc chắn.

              Lập trình cực đoan công nhận tầm quan trọng của các quyết định thiết kế, nhưng nó kiên quyết phản đối việc thiết kế trước. Thay vào đó, nó nỗ lực đáng khen ngợi trong việc giao tiếp và cải thiện khả năng của dự án để thay đổi hướng đi một cách nhanh chóng. Với khả năng phản ứng đó, các nhà phát triển có thể sử dụng "điều đơn giản nhất có thể hoạt động" ở bất kỳ giai đoạn nào của dự án và sau đó liên tục cải tiến thiết kế, thực hiện nhiều cải tiến nhỏ, cuối cùng đạt được một thiết kế phù hợp với nhu cầu thực sự của khách hàng.

              Chủ nghĩa tối giản này đã trở thành một liều thuốc cần thiết cho một số sự thừa thãi của những người yêu thích thiết kế. Các dự án đã bị cản trở bởi những tài liệu cồng kềnh mà ít mang lại giá trị. Họ đã phải chịu đựng "tê liệt phân tích," với các thành viên trong nhóm quá sợ hãi trước một thiết kế không hoàn hảo đến nỗi không thể tiến bộ chút nào. Điều gì đó cần phải thay đổi.

              Thật không may, một số ý tưởng quy trình này có thể bị hiểu sai. Mỗi người có một định nghĩa khác nhau về "đơn giản nhất". Tái cấu trúc liên tục là một chuỗi các thiết kế nhỏ; các nhà phát triển không có nguyên tắc thiết kế vững chắc sẽ tạo ra một mã nguồn khó hiểu hoặc thay đổi - điều ngược lại với tính linh hoạt. Và mặc dù sự lo ngại về các yêu cầu không lường trước thường dẫn đến việc thiết kế quá mức, nhưng nỗ lực để tránh thiết kế quá mức có thể phát triển thành một nỗi sợ khác: nỗi sợ làm bất kỳ tư duy thiết kế sâu nào.

              Thực tế, XP hoạt động tốt nhất cho các nhà phát triển có khả năng thiết kế nhạy bén. Quy trình XP giả định rằng bạn có thể cải thiện một thiết kế bằng cách tái cấu trúc, và rằng bạn sẽ làm điều này thường xuyên và nhanh chóng. Tuy nhiên, những lựa chọn thiết kế trong quá khứ khiến việc tái cấu trúc trở nên dễ dàng hơn hoặc khó khăn hơn. Quy trình XP cố gắng tăng cường giao tiếp trong nhóm, nhưng các lựa chọn mô hình và thiết kế có thể làm rõ ràng hoặc gây nhầm lẫn trong việc giao tiếp.

              Cuốn sách này kết hợp giữa thực hành thiết kế và phát triển, minh họa cách thức thiết kế hướng miền và phát triển Agile hỗ trợ lẫn nhau. Một cách tiếp cận tinh vi về mô hình miền trong bối cảnh quy trình phát triển Agile sẽ tăng tốc độ phát triển. Mối quan hệ giữa quy trình và phát triển miền làm cho cách tiếp cận này thực tế hơn bất kỳ phương pháp nào về "thiết kế thuần túy" trong một môi trường cách biệt.


                The Structure of This Book

                Cuốn sách được chia thành bốn phần chính:

                Phần I: Đưa Mô Hình Miền Vào Sử Dụng trình bày các mục tiêu cơ bản của phát triển theo miền; những mục tiêu này thúc đẩy các thực hành ở các phần sau. Bởi vì có rất nhiều phương pháp phát triển phần mềm, Phần I định nghĩa các thuật ngữ và đưa ra cái nhìn tổng quan về những tác động của việc sử dụng mô hình miền để thúc đẩy giao tiếp và thiết kế.

                Phần II: Các Thành Phần Cơ Bản của Thiết Kế Hướng Mô Hình cô đọng những thực hành tốt nhất trong mô hình miền hướng đối tượng thành một tập hợp các thành phần cơ bản. Phần này tập trung vào việc thu hẹp khoảng cách giữa các mô hình và phần mềm thực tiễn, đang chạy. Việc chia sẻ những mẫu chuẩn này mang lại trật tự cho quá trình thiết kế. Các thành viên trong nhóm dễ dàng hiểu công việc của nhau hơn. Việc sử dụng các mẫu chuẩn cũng góp phần cung cấp thuật ngữ cho một ngôn ngữ chung, mà tất cả các thành viên trong nhóm có thể sử dụng để thảo luận về các quyết định mô hình và thiết kế.

                Nhưng điểm chính của phần này là tập trung vào những loại quyết định giữ cho mô hình và việc triển khai thống nhất với nhau, mỗi bên tăng cường hiệu quả của bên kia. Sự thống nhất này đòi hỏi sự chú ý đến chi tiết của các yếu tố cá nhân. Việc xử lý cẩn thận ở quy mô nhỏ này đem lại cho các nhà phát triển một nền tảng vững chắc để áp dụng các phương pháp mô hình hóa trong các Phần III và IV.

                Phần III: Tái cấu trúc để có cái nhìn sâu sắc hơn đi xa hơn các khối xây dựng đến thử thách lắp ghép chúng thành các mô hình thực tiễn mang lại giá trị. Thay vì nhảy ngay vào các nguyên tắc thiết kế huyền bí, phần này nhấn mạnh quá trình khám phá. Các mô hình giá trị không xuất hiện ngay lập tức; chúng đòi hỏi một hiểu biết sâu sắc về miền nghiên cứu. Hiểu biết đó đến từ việc tham gia vào thực tiễn, thực hiện một thiết kế ban đầu dựa trên một mô hình có thể khá ngây thơ, và sau đó lặp đi lặp lại quá trình chuyển đổi nó. Mỗi lần nhóm đạt được cái nhìn sâu sắc, mô hình sẽ được biến đổi để tiết lộ kiến thức phong phú hơn, và mã sẽ được tái cấu trúc để phản ánh mô hình sâu sắc hơn và làm cho tiềm năng của nó có thể được sử dụng trong ứng dụng. Sau đó, thỉnh thoảng, việc bóc vỏ này dẫn đến cơ hội để bứt phá đến một mô hình sâu hơn nhiều, kèm theo là sự thay đổi thiết kế sâu sắc.

                Khám phá vốn dĩ là mở, nhưng nó không nhất thiết phải ngẫu nhiên. Phần III đi sâu vào các nguyên tắc mô hình có thể hướng dẫn các lựa chọn trong quá trình này, và các kỹ thuật giúp định hướng cuộc tìm kiếm.

                Phần IV: Thiết kế chiến lược liên quan đến các tình huống phát sinh trong các hệ thống phức tạp, các tổ chức lớn và các tương tác với các hệ thống bên ngoài và hệ thống kế thừa. Phần này khám phá một bộ ba nguyên tắc áp dụng cho toàn bộ hệ thống: bối cảnh, chưng cất và cấu trúc quy mô lớn. Các quyết định thiết kế chiến lược được đưa ra bởi các đội, hoặc thậm chí giữa các đội. Thiết kế chiến lược cho phép các mục tiêu của Phần I được hiện thực hóa trên quy mô lớn hơn, cho một hệ thống lớn hoặc một ứng dụng phù hợp với một mạng lưới rộng lớn trong toàn doanh nghiệp.

                Trong suốt cuốn sách, các cuộc thảo luận được minh họa không bằng những vấn đề đơn giản hóa quá mức hay "trò chơi", mà bằng những ví dụ thực tế được điều chỉnh từ các dự án thực sự.

                Nhiều phần của cuốn sách được viết dưới dạng một tập hợp "mẫu". Người đọc nên có khả năng hiểu nội dung mà không cần lo lắng về phương pháp này, nhưng những ai quan tâm đến phong cách và định dạng của các mẫu có thể muốn đọc phần phụ lục.

                Tài liệu bổ sung có thể được tìm thấy tại http://domaindrivendesign.org, bao gồm mã ví dụ bổ sung và thảo luận của cộng đồng.


                  Who Should Read This Book

                  Cuốn sách này được viết chủ yếu dành cho các nhà phát triển phần mềm hướng đối tượng. Hầu hết các thành viên trong nhóm dự án phần mềm đều có thể hưởng lợi từ một số phần của cuốn sách. Nó sẽ có ý nghĩa nhất đối với những người hiện đang tham gia vào một dự án, cố gắng thực hiện một số điều này trong quá trình thực hiện, và đối với những người đã có kinh nghiệm sâu sắc với những dự án như vậy.

                  Một số kiến thức về mô hình hướng đối tượng là cần thiết để tận dụng cuốn sách này. Các ví dụ bao gồm sơ đồ UML và mã Java, vì vậy khả năng đọc những ngôn ngữ đó ở mức cơ bản là quan trọng, nhưng không cần thiết phải thành thạo các chi tiết của chúng. Kiến thức về Lập trình cực đoan sẽ mang lại góc nhìn cho các cuộc thảo luận về quy trình phát triển, nhưng tài liệu nên dễ hiểu cho những người không có kiến thức nền tảng.

                  Dành cho các lập trình viên phần mềm trung cấp - những độc giả đã biết một chút về thiết kế hướng đối tượng và có thể đã đọc một hoặc hai cuốn sách về thiết kế phần mềm - cuốn sách này sẽ lấp đầy những khoảng trống và cung cấp cái nhìn về cách mô hình đối tượng phù hợp vào thực tế trong một dự án phần mềm. Cuốn sách sẽ giúp các lập trình viên trung cấp học cách áp dụng các kỹ năng mô hình hóa và thiết kế tinh vi vào các vấn đề thực tế.

                  Các nhà phát triển phần mềm nâng cao hoặc chuyên gia sẽ quan tâm đến khung tổng quát của cuốn sách trong việc xử lý lĩnh vực này. Cách tiếp cận hệ thống trong thiết kế sẽ giúp các lãnh đạo kỹ thuật hướng dẫn đội ngũ của họ theo con đường này. Ngoài ra, thuật ngữ nhất quán được sử dụng xuyên suốt cuốn sách sẽ giúp các nhà phát triển nâng cao giao tiếp với đồng nghiệp của họ.

                  Cuốn sách này là một câu chuyện, và nó có thể được đọc từ đầu đến cuối, hoặc từ đầu của bất kỳ chương nào. Độc giả từ nhiều nền tảng khác nhau có thể muốn đi các con đường khác nhau qua cuốn sách, nhưng tôi khuyên tất cả độc giả nên bắt đầu với phần giới thiệu của Phần I, cũng như Chương 1. Ngoài ra, phần cốt lõi có lẽ là các Chương 2, 3, 9 và 14. Một người đọc lướt, người đã có sự hiểu biết nhất định về một chủ đề, nên có thể nắm được các điểm chính bằng cách đọc các tiêu đề và văn bản in đậm. Một độc giả rất nâng cao có thể muốn lướt qua Phần I và II và có lẽ sẽ quan tâm nhất đến Phần III và IV.

                  Ngoài nhóm độc giả chính này, các nhà phân tích và quản lý dự án kỹ thuật tương đối cũng sẽ được lợi từ việc đọc cuốn sách. Các nhà phân tích có thể tận dụng mối liên kết giữa mô hình và thiết kế để đóng góp hiệu quả hơn trong bối cảnh của một dự án Agile. Các nhà phân tích cũng có thể sử dụng một số nguyên tắc của thiết kế chiến lược để tập trung và tổ chức công việc của họ tốt hơn.

                  Các quản lý dự án nên quan tâm đến việc nhấn mạnh cải thiện hiệu quả của đội ngũ và tập trung vào việc thiết kế phần mềm có ý nghĩa đối với các chuyên gia kinh doanh và người dùng. Và vì các quyết định thiết kế chiến lược có mối liên hệ với tổ chức đội ngũ và phong cách làm việc, nên những quyết định thiết kế này nhất thiết liên quan đến sự lãnh đạo của dự án và có ảnh hưởng lớn đến quỹ đạo của dự án.


                    A Domain-Driven Team

                    Mặc dù một nhà phát triển cá nhân hiểu về thiết kế hướng miền sẽ thu được những kỹ thuật và góc nhìn thiết kế quý giá, nhưng những lợi ích lớn nhất đến khi một nhóm cùng nhau áp dụng phương pháp thiết kế hướng miền và đưa mô hình miền vào trung tâm cuộc thảo luận của dự án. Bằng cách này, các thành viên trong nhóm sẽ chia sẻ một ngôn ngữ làm phong phú thêm giao tiếp của họ và giữ cho nó gắn kết với phần mềm. Họ sẽ tạo ra một triển khai rõ ràng theo đúng mô hình, mang lại sức mạnh cho việc phát triển ứng dụng. Họ sẽ chia sẻ một bản đồ về cách công việc thiết kế của các nhóm khác nhau liên quan đến nhau, và họ sẽ chú ý một cách hệ thống vào những đặc điểm và giá trị nổi bật nhất đối với tổ chức.

                    Thiết kế theo hướng miền là một thách thức kỹ thuật khó khăn nhưng có thể mang lại lợi ích lớn, mở ra cơ hội ngay khi hầu hết các dự án phần mềm bắt đầu cứng nhắc thành di sản.

                    graphics/fminf01.jpg

                    graphics/fminf02.gif


                      Acknowledgments

                      Tôi đã làm việc trên cuốn sách này, dưới một hình thức nào đó, trong hơn bốn năm, và nhiều người đã giúp đỡ và ủng hộ tôi trong suốt quá trình này.

                      Tôi cảm ơn những người đã đọc bản thảo và góp ý. Cuốn sách này đơn giản là không thể thực hiện được nếu không có phản hồi đó. Một vài người đã dành sự chú ý đặc biệt cho các bài đánh giá của họ. Nhóm Patterns Silicon Valley, do Russ Rufer và Tracy Bialek dẫn dắt, đã dành bảy tuần để xem xét bản dự thảo hoàn chỉnh đầu tiên của cuốn sách. Nhóm đọc của Đại học Illinois do Ralph Johnson dẫn dắt cũng đã dành vài tuần để xem xét một bản dự thảo sau đó. Những cuộc thảo luận dài và sôi nổi của những nhóm này đã có ảnh hưởng sâu sắc. Kyle Brown và Martin Fowler đã đóng góp phản hồi chi tiết, những hiểu biết quý giá, và sự hỗ trợ tinh thần vô giá (trong khi ngồi trên một cái cá). Những bình luận của Ward Cunningham đã giúp tôi củng cố một số điểm yếu quan trọng. Alistair Cockburn đã khuyến khích tôi ngay từ đầu và giúp tôi tìm ra cách thức trong quy trình xuất bản, cũng như Hilary Evans. David Siegel và Eugene Wallingford đã giúp tôi tránh được những tình huống xấu hổ trong các phần kỹ thuật hơn. Vibhu Mohindra và Vladimir Gitlevich đã rất tỉ mỉ kiểm tra tất cả các ví dụ mã.

                      Rob Mee đã đọc một số cuộc khám phá ban đầu của tôi về tài liệu, và đã cùng tôi suy nghĩ những ý tưởng khi tôi đang tìm kiếm một cách để diễn đạt phong cách thiết kế này. Sau đó, anh ấy đã xem xét một bản thảo muộn hơn cùng tôi.

                      Josh Kerievsky chịu trách nhiệm cho một trong những bước ngoặt lớn trong sự phát triển của cuốn sách: Anh ấy đã thuyết phục tôi thử nghiệm định dạng "Alexandrian", điều này đã trở nên rất trung tâm trong cách tổ chức cuốn sách. Anh ấy cũng đã giúp tôi tổng hợp một số tài liệu hiện có trong Phần II thành một hình thức mạch lạc lần đầu tiên, trong quá trình "chăn dắt" tích cực trước hội nghị PLoP vào năm 1999. Điều này đã trở thành một hạt giống mà xung quanh đó phần còn lại của cuốn sách hình thành.

                      Tôi cũng cảm ơn Awad Faddoul vì hàng trăm giờ tôi đã ngồi viết trong quán cà phê tuyệt vời của anh. Nơi tạm trú đó, cùng với việc lướt ván buồm, đã giúp tôi tiếp tục đi tới.

                      Và tôi rất biết ơn Martine Jousset, Richard Paselk và Ross Venables đã tạo ra một số bức ảnh đẹp để minh họa cho một vài khái niệm chính (xem ghi công ảnh trên trang 517).

                      Trước khi tôi có thể hình dung ra cuốn sách này, tôi đã phải hình thành quan điểm và hiểu biết của mình về phát triển phần mềm. Sự hình thành đó một phần lớn nhờ vào sự hào phóng của một vài người tuyệt vời đã đóng vai trò như những người hướng dẫn không chính thức đối với tôi, cũng như bạn bè. David Siegel, Eric Gold và Iseult White, mỗi người theo một cách khác nhau, đã giúp tôi phát triển cách suy nghĩ về thiết kế phần mềm. Trong khi đó, Bruce Gordon, Richard Frey-berg và Judith Segal, cũng theo những cách rất khác nhau, đã giúp tôi tìm ra con đường của mình trong thế giới công việc dự án thành công.

                      Những khái niệm của riêng tôi tự nhiên phát triển từ một tập hợp các ý tưởng đang tồn tại vào thời điểm đó. Một số đóng góp đó sẽ được rõ ràng trong văn bản chính và được tham chiếu khi có thể. Những ý tưởng khác thì cơ bản đến mức tôi thậm chí không nhận ra ảnh hưởng của chúng đối với tôi.

                      Người hướng dẫn luận văn thạc sĩ của tôi, Tiến sĩ Bala Subramanium, đã giới thiệu cho tôi về mô hình hóa toán học, mà chúng tôi đã áp dụng cho động học phản ứng hóa học. Mô hình hóa là mô hình hóa, và công việc đó là một phần của con đường dẫn đến cuốn sách này.

                      Ngay cả trước đó, cách suy nghĩ của tôi đã được hình thành từ cha mẹ tôi, Carol và Gary Evans. Và một vài thầy cô đặc biệt đã khơi dậy sự quan tâm của tôi hoặc giúp tôi xây dựng nền tảng, đặc biệt là Dale Currier (một giáo viên toán cấp ba), Mary Brown (một giáo viên viết tiếng Anh cấp ba) và Josephine McGlamery (một giáo viên khoa học lớp sáu).

                      Cuối cùng, tôi cảm ơn bạn bè và gia đình tôi, cũng như Fernando De Leon, vì sự khích lệ của họ trong suốt chặng đường.


                        Part I: Putting the Domain Model to Work

                        graphics/fminf03.gif

                        Bản đồ Trung Quốc thế kỷ mười tám này đại diện cho toàn thế giới. Ở giữa và chiếm hầu hết không gian là Trung Quốc, được bao quanh bởi các biểu diễn sơ sài của các quốc gia khác. Đây là một mô hình thế giới phù hợp với xã hội đó, đã cố ý quay vào bên trong. Thế giới quan mà bản đồ đại diện hẳn không hữu ích trong việc đối phó với người ngoại quốc. Chắc chắn nó không phục vụ gì cho Trung Quốc hiện đại. Bản đồ là những mô hình, và mỗi mô hình đại diện cho một khía cạnh nào đó của hiện thực hoặc một ý tưởng có liên quan. Một mô hình là một sự giản lược. Nó là một cách diễn giải thực tế mà trừu tượng hóa các khía cạnh liên quan đến việc giải quyết vấn đề hiện tại và bỏ qua chi tiết không cần thiết.

                        Mỗi chương trình phần mềm liên quan đến một hoạt động hoặc sở thích nào đó của người sử dụng. Khu vực chủ đề mà người sử dụng áp dụng chương trình là miền của phần mềm. Một số miền liên quan đến thế giới vật lý: Miền của chương trình đặt vé máy bay liên quan đến những người thật đang lên những chiếc máy bay thật. Một số miền lại vô hình: Miền của chương trình kế toán là tiền bạc và tài chính. Các miền phần mềm thường ít liên quan đến máy tính, mặc dù có một số ngoại lệ: Miền của hệ thống kiểm soát mã nguồn chính là phát triển phần mềm.

                        Để tạo ra phần mềm có giá trị liên quan đến hoạt động của người dùng, một nhóm phát triển phải áp dụng một khối lượng kiến thức liên quan đến những hoạt động đó. Độ rộng của kiến thức cần thiết có thể rất đáng lo ngại. Khối lượng và độ phức tạp của thông tin có thể choáng ngợp. Mô hình là công cụ để giải quyết tình trạng quá tải này. Một mô hình là một hình thức kiến thức được đơn giản hóa có chọn lọc và cấu trúc một cách có ý thức. Một mô hình phù hợp giúp hiểu rõ thông tin và tập trung vào một vấn đề.

                        Mô hình miền không phải là một sơ đồ cụ thể; nó là ý tưởng mà sơ đồ đó định truyền tải. Nó không chỉ là kiến thức trong đầu của một chuyên gia miền; nó là một sự trừu tượng có tổ chức và chọn lọc một cách nghiêm ngặt của kiến thức đó. Một sơ đồ có thể đại diện và truyền đạt một mô hình, cũng như mã code được viết cẩn thận, cũng như một câu tiếng Anh.

                        Mô hình miền không phải là việc tạo ra một mô hình "thực tế" nhất có thể. Ngay cả trong một miền của những thứ thực tế hữu hình, mô hình của chúng ta là một sản phẩm nhân tạo. Nó cũng không chỉ là việc xây dựng một cơ chế phần mềm cung cấp các kết quả cần thiết. Nó giống như việc làm phim, thể hiện một cách lỏng lẻo thực tại với một mục đích cụ thể. Ngay cả một bộ phim tài liệu cũng không cho thấy cuộc sống thực tế chưa qua biên tập. Cũng giống như một nhà làm phim chọn các khía cạnh của trải nghiệm và trình bày chúng theo cách riêng biệt để kể một câu chuyện hoặc truyền đạt một điểm, một người mô hình miền chọn một mô hình cụ thể vì tính hữu dụng của nó.

                        The Utility of a Model in Domain-Driven Design

                        Trong thiết kế hướng miền, ba cách sử dụng cơ bản xác định sự lựa chọn một mô hình.

                        1. Mô hình và trái tim của thiết kế định hình lẫn nhau. Đó là mối liên hệ mật thiết giữa mô hình và triển khai làm cho mô hình có liên quan và đảm bảo rằng phân tích mà nó chứa đựng áp dụng cho sản phẩm cuối cùng, là một chương trình đang chạy. Sự ràng buộc giữa mô hình và triển khai cũng giúp trong việc bảo trì và phát triển liên tục, vì mã có thể được diễn giải dựa trên việc hiểu mô hình. (Xem Chương 3.)

                        • Mô hình là xương sống của một ngôn ngữ được sử dụng bởi tất cả các thành viên trong nhóm. Nhờ vào sự liên kết giữa mô hình và việc triển khai, các nhà phát triển có thể nói về chương trình bằng ngôn ngữ này. Họ có thể giao tiếp với các chuyên gia trong lĩnh vực mà không cần dịch thuật. Và vì ngôn ngữ dựa trên mô hình, khả năng ngôn ngữ tự nhiên của chúng ta có thể được sử dụng để hoàn thiện chính mô hình đó. (Xem Chương 2.)

                        • Mô hình là kiến thức tinh chế. Mô hình là cách mà nhóm đã thống nhất để cấu trúc kiến thức miền và phân biệt các yếu tố quan trọng nhất. Một mô hình nắm bắt cách mà chúng ta lựa chọn để suy nghĩ về miền khi chúng ta chọn thuật ngữ, phân tách khái niệm và liên kết chúng lại với nhau. Ngôn ngữ chung cho phép các nhà phát triển và chuyên gia miền hợp tác hiệu quả khi họ xử lý thông tin thành dạng này. Sự gắn kết giữa mô hình và triển khai giúp kinh nghiệm với các phiên bản sớm của phần mềm có thể áp dụng làm phản hồi vào quá trình mô hình hóa. (Xem Chương 1.)

                        • Ba chương tiếp theo sẽ xem xét ý nghĩa và giá trị của từng đóng góp này theo thứ tự, cũng như các cách chúng liên kết với nhau. Việc sử dụng một mô hình theo cách này có thể hỗ trợ việc phát triển phần mềm với chức năng phong phú mà nếu không sẽ phải đầu tư một khoản lớn vào phát triển không theo kế hoạch.

                          The Heart of Software

                          Trái tim của phần mềm là khả năng giải quyết các vấn đề liên quan đến lĩnh vực cho người dùng của nó. Tất cả các tính năng khác, dù quan trọng đến đâu, đều hỗ trợ cho mục đích cơ bản này. Khi lĩnh vực trở nên phức tạp, đây là một nhiệm vụ khó khăn, đòi hỏi nỗ lực tập trung của những người tài năng và có kỹ năng. Các nhà phát triển phải chìm đắm trong lĩnh vực đó để tích lũy kiến thức về doanh nghiệp. Họ phải mài giũa kỹ năng mô hình hóa của mình và làm chủ thiết kế lĩnh vực.

                          Tuy nhiên, đây không phải là ưu tiên trong hầu hết các dự án phần mềm. Hầu hết các nhà phát triển tài năng không có nhiều hứng thú trong việc tìm hiểu về lĩnh vực cụ thể mà họ đang làm việc, huống chi là cam kết lớn để mở rộng kỹ năng mô hình miền của họ. Những người làm kỹ thuật thích những vấn đề có thể đo lường được, thử thách kỹ năng kỹ thuật của họ. Công việc miền thì lộn xộn và đòi hỏi nhiều kiến thức mới phức tạp mà dường như không bổ sung gì cho khả năng của một nhà khoa học máy tính.

                          Thay vào đó, tài năng kỹ thuật tập trung vào việc xây dựng các khung công nghệ phức tạp, cố gắng giải quyết các vấn đề trong miền bằng công nghệ. Việc tìm hiểu và mô hình hóa miền được để lại cho những người khác. Sự phức tạp ở cốt lõi của phần mềm phải được đối mặt trực tiếp. Nếu không làm như vậy, sẽ có nguy cơ không còn liên quan.

                          Trong một cuộc phỏng vấn trên chương trình truyền hình, diễn viên hài John Cleese đã kể về một sự kiện trong quá trình quay phim Monty Python và Chén Thánh. Họ đã quay một cảnh nhất định nhiều lần, nhưng không hiểu sao nó lại không hài hước. Cuối cùng, ông đã nghỉ ngơi và tham khảo ý kiến với diễn viên hài đồng nghiệp Michael Palin (diễn viên khác trong cảnh đó), và họ đã nghĩ ra một biến thể nhỏ. Họ quay thêm một lần nữa, và hóa ra nó lại hài hước, vì vậy họ đã kết thúc một ngày làm việc.

                          Sáng hôm sau, Cleese nhìn vào bản dựng thô mà biên tập viên phim đã lắp ghép từ công việc của ngày hôm trước. Đến cảnh mà họ đã vật lộn, Cleese nhận ra rằng nó không hài hước; một trong những cảnh quay trước đó đã được sử dụng.

                          Ông hỏi biên tập viên phim tại sao ông ấy không sử dụng cảnh quay cuối cùng, như đã chỉ đạo. "Không thể sử dụng, có ai đó đã đi vào khung hình," biên tập viên trả lời. Cleese xem lại cảnh đó một lần nữa, rồi lại một lần nữa. Vẫn không thấy có gì sai. Cuối cùng, biên tập viên đã dừng phim và chỉ ra một ống tay áo xuất hiện trong một khoảnh khắc ở mép hình.

                          Người biên tập phim tập trung vào việc thực hiện chính xác chuyên môn của mình. Ông lo lắng rằng các biên tập viên phim khác khi xem bộ phim sẽ đánh giá công việc của ông dựa trên độ hoàn hảo về kỹ thuật. Trong quá trình đó, trái tim của cảnh phim đã bị mất.

                          Rất may, cảnh hài hước đã được khôi phục bởi một đạo diễn hiểu về hài kịch. Tương tự như vậy, các lãnh đạo trong một nhóm có thể hiểu tầm quan trọng của lĩnh vực sẽ đưa dự án phần mềm của họ trở lại đúng hướng khi việc phát triển một mô hình phản ánh sự hiểu biết sâu sắc bị lạc trong công việc.

                          Cuốn sách này sẽ cho thấy rằng phát triển miền mang đến cơ hội để rèn luyện những kỹ năng thiết kế rất tinh vi. Sự lộn xộn của hầu hết các miền phần mềm thực sự là một thách thức kỹ thuật thú vị. Thực tế, trong nhiều lĩnh vực khoa học, "độ phức tạp" là một trong những chủ đề hiện tại hấp dẫn nhất, khi các nhà nghiên cứu cố gắng giải quyết sự lộn xộn của thế giới thực. Một nhà phát triển phần mềm cũng có triển vọng tương tự khi đối mặt với một miền phức tạp chưa bao giờ được hình thức hóa. Việc tạo ra một mô hình rõ ràng giúp cắt ngang qua sự phức tạp đó là điều thú vị.

                          Có những cách tư duy hệ thống mà các nhà phát triển có thể áp dụng để tìm kiếm những hiểu biết và tạo ra các mô hình hiệu quả. Có những kỹ thuật thiết kế có thể mang lại trật tự cho một ứng dụng phần mềm phức tạp. Việc rèn luyện những kỹ năng này khiến một nhà phát triển trở nên có giá trị hơn, ngay cả trong một lĩnh vực ban đầu chưa quen thuộc.


                          Chapter One. Crunching Knowledge

                          Vài năm trước, tôi bắt tay vào thiết kế một công cụ phần mềm chuyên biệt cho thiết kế mạch in (PCB). Một vấn đề: tôi không biết gì về phần cứng điện tử. Tất nhiên, tôi có quyền truy cập vào một số nhà thiết kế PCB, nhưng họ thường khiến tôi chóng mặt chỉ trong ba phút. Làm thế nào tôi có thể hiểu đủ để viết phần mềm này? Chắc chắn là tôi sẽ không trở thành một kỹ sư điện trước thời hạn giao hàng!

                          Chúng tôi đã cố gắng để các nhà thiết kế PCB nói cho tôi biết chính xác phần mềm nên làm gì. Đó là một ý tưởng tồi. Họ là những nhà thiết kế mạch tài năng, nhưng ý tưởng về phần mềm của họ thường liên quan đến việc đọc một tệp ASCII, sắp xếp nó, ghi lại với một số chú thích và tạo ra một báo cáo. Rõ ràng rằng điều này sẽ không dẫn đến sự đột phá về năng suất mà họ đang tìm kiếm.

                          Những cuộc họp đầu tiên thật thất vọng, nhưng có một tia hy vọng trong các báo cáo mà họ yêu cầu. Chúng luôn liên quan đến "mạng" và các chi tiết khác nhau về chúng. Trong lĩnh vực này, một mạng về cơ bản là một dẫn điện bằng dây có thể kết nối bất kỳ số lượng linh kiện nào trên một bảng mạch in và truyền tín hiệu điện đến mọi thứ mà nó kết nối. Chúng tôi đã có yếu tố đầu tiên của mô hình miền.

                          Figure 1.1.

                          graphics/01fig01.gif

                          Tôi bắt đầu vẽ sơ đồ cho họ khi chúng tôi thảo luận về những điều họ muốn phần mềm thực hiện. Tôi đã sử dụng một biến thể không chính thức của sơ đồ tương tác đối tượng để đi qua các kịch bản.

                          Figure 1.2.

                          graphics/01fig02.gif

                          Chuyên gia PCB 1: Các linh kiện không cần phải là chip.

                          Vậy tôi chỉ nên gọi chúng là "thành phần" phải không?

                          Chuyên gia 1: Chúng tôi gọi chúng là "các thể hiện thành phần." Có thể có nhiều thể hiện giống nhau của cùng một thành phần.

                          Chuyên gia 2: Hộp "net" trông giống hệt như một phiên bản thành phần.

                          Chuyên gia 1: Anh ta không sử dụng ký hiệu của chúng ta. Mọi thứ đều là hộp đối với họ, tôi đoán vậy.

                          Nhà phát triển: Rất tiếc phải nói rằng, có. Tôi đoán tôi nên giải thích thêm về ký hiệu này một chút.

                          Họ liên tục chỉnh sửa tôi, và khi họ làm như vậy, tôi bắt đầu học. Chúng tôi đã giải quyết các va chạm và sự mơ hồ trong thuật ngữ của họ cùng với những khác biệt trong quan điểm kỹ thuật của họ, và họ đã học. Họ bắt đầu giải thích mọi thứ một cách chính xác và nhất quán hơn, và chúng tôi bắt đầu phát triển một mô hình cùng nhau.

                          Chuyên gia 1: Không chỉ đơn giản nói rằng một tín hiệu đến tại một ref-des, chúng ta phải biết chân nào.

                          Nhà phát triển: Ref-des?

                          Chuyên gia 2: Cũng giống như một instance thành phần. Ref-des là cách gọi trong một công cụ cụ thể mà chúng tôi sử dụng.

                          Chuyên gia 1: Dù sao đi nữa, một mạng kết nối một chân cụ thể của một ví dụ với một chân cụ thể của ví dụ khác.

                          Nhà phát triển: Bạn đang nói rằng một chân chỉ thuộc về một instance thành phần duy nhất và kết nối với chỉ một mạng?

                          Chuyên gia 1: Vâng, đúng vậy.

                          Chuyên gia 2: Ngoài ra, mỗi mạng đều có một topo, một cách sắp xếp xác định cách các phần tử của mạng kết nối với nhau.

                          Nhà phát triển: Được rồi, thế còn cái này thì sao?

                          Figure 1.3.

                          graphics/01fig03.gif

                          Để tập trung vào việc khám phá, chúng tôi đã giới hạn mình trong một thời gian, chỉ nghiên cứu một tính năng cụ thể. Một "mô phỏng dò" sẽ theo dõi sự lan truyền của tín hiệu để phát hiện các vị trí có khả năng xảy ra một số loại vấn đề trong thiết kế.

                          Nhà phát triển: Tôi hiểu cách mà tín hiệu được truyền qua Mạng đến tất cả các chân gắn kèm, nhưng nó đi xa hơn thế nào? Liệu Đồ thị có liên quan đến điều đó không?

                          Chuyên gia 2: Không. Thành phần đó truyền tín hiệu đi.

                          Nhà phát triển: Chúng tôi chắc chắn không thể mô hình hóa hành vi nội bộ của một chip. Điều đó quá phức tạp.

                          Chuyên gia 2: Chúng ta không cần phải làm vậy. Chúng ta có thể sử dụng một sự đơn giản hóa. Chỉ cần một danh sách các phép đẩy qua thành phần từ một số chân nhất định đến một số chân khác.

                          Nhà phát triển: Có phải như thế này không?

                          [Qua nhiều thử nghiệm và sai sót, chúng tôi đã phác thảo ra một kịch bản.]

                          Figure 1.4.

                          graphics/01fig04.gif

                          Nhà phát triển: Nhưng bạn cần biết chính xác điều gì từ phép tính này?

                          Chuyên gia 2: Chúng tôi sẽ tìm kiếm những độ trễ tín hiệu lâu dài - nói cách khác, bất kỳ đường tín hiệu nào quá hai hoặc ba bước nhảy. Đó là một quy tắc chung. Nếu đường dẫn quá dài, tín hiệu có thể không đến kịp trong chu kỳ đồng hồ.

                          Nhà phát triển: Hơn ba bước nhảy.... Vì vậy, chúng ta cần tính toán độ dài đường đi. Và điều gì được tính là một bước nhảy?

                          Chuyên gia 2: Mỗi lần tín hiệu vượt qua một Mạng, đó là một bước nhảy.

                          Nhà phát triển: Vậy chúng ta có thể truyền số lượng hops đi, và một Net có thể tăng nó lên, như thế này.

                          Figure 1.5.

                          graphics/01fig05.gif

                          Nhà phát triển: Phần duy nhất mà tôi không rõ là "những đợt đẩy" đến từ đâu. Chúng ta có lưu trữ dữ liệu đó cho mỗi Instance Thành phần không?

                          Chuyên gia 2: Các đợt đẩy sẽ giống nhau cho tất cả các phiên bản của một thành phần.

                          Nhà phát triển: Vậy loại thành phần xác định các lần đẩy. Chúng sẽ giống nhau cho mọi trường hợp phải không?

                          Figure 1.6.

                          graphics/01fig06.gif

                          Chuyên gia 2: Tôi không chắc chắn chính xác một số điều này có nghĩa là gì, nhưng tôi tưởng tượng việc lưu trữ push-through cho từng thành phần sẽ trông giống như vậy.

                          Nhà phát triển: Xin lỗi, tôi đã đi vào chi tiết hơi nhiều. Tôi chỉ đang suy nghĩ về nó. . . . Vậy, bây giờ, Topology liên quan ở đâu?

                          Chuyên gia 1: Điều đó không được sử dụng cho mô phỏng đầu dò.

                          Nhà phát triển: Vậy thì tôi sẽ tạm gác lại lúc này, được chứ? Chúng ta có thể đưa nó trở lại khi đến những tính năng đó.

                          Và thế là nó diễn ra (với nhiều sự vấp váp hơn những gì được thể hiện ở đây). Động não và hoàn thiện; đặt câu hỏi và giải thích. Mô hình phát triển cùng với sự hiểu biết của tôi về miền và sự hiểu biết của họ về cách mà mô hình sẽ góp phần vào giải pháp. Một sơ đồ lớp đại diện cho mô hình ban đầu trông giống như thế này.

                          Figure 1.7.

                          graphics/01fig07.gif

                          Sau vài ngày làm việc bán thời gian nữa, tôi cảm thấy mình đã hiểu đủ để thử viết mã. Tôi đã viết một nguyên mẫu rất đơn giản, được điều khiển bởi một khung kiểm tra tự động. Tôi đã tránh xa mọi cơ sở hạ tầng. Không có tính bền vững và không có giao diện người dùng (UI). Điều này cho phép tôi tập trung vào hành vi. Tôi đã có thể chứng minh một mô phỏng đơn giản của cảm biến chỉ trong vài ngày nữa. Mặc dù nó sử dụng dữ liệu giả và ghi lại văn bản thô vào bảng điều khiển, nhưng nó vẫn thực hiện tính toán thực tế của độ dài đường đi bằng các đối tượng Java. Những đối tượng Java đó phản ánh một mô hình được chia sẻ giữa các chuyên gia trong lĩnh vực và tôi.

                          Tính cụ thể của nguyên mẫu này đã làm rõ ràng hơn cho các chuyên gia trong lĩnh vực về ý nghĩa của mô hình và cách nó liên quan đến phần mềm đang hoạt động. Từ thời điểm đó, các cuộc thảo luận về mô hình của chúng tôi trở nên tương tác hơn, vì họ có thể thấy cách tôi kết hợp kiến thức mới đã học vào mô hình và sau đó vào phần mềm. Họ cũng có phản hồi cụ thể từ nguyên mẫu để đánh giá ý tưởng của chính họ.

                          Được nhúng trong mô hình đó, mà tự nhiên trở nên phức tạp hơn nhiều so với mô hình được trình bày ở đây, là kiến thức về lĩnh vực PCB liên quan đến các vấn đề mà chúng tôi đang giải quyết. Nó tập hợp nhiều từ đồng nghĩa và những biến thể nhỏ trong mô tả. Nó loại trừ hàng trăm thông tin mà các kỹ sư hiểu nhưng không liên quan trực tiếp, chẳng hạn như các tính năng số thực tế của các linh kiện. Một chuyên gia phần mềm như tôi có thể nhìn vào các sơ đồ và trong vài phút bắt đầu nắm bắt nội dung của phần mềm. Anh ấy hoặc cô ấy sẽ có một khuôn khổ để tổ chức thông tin mới và học nhanh hơn, để đưa ra những phỏng đoán tốt hơn về những gì quan trọng và những gì không, và để giao tiếp tốt hơn với các kỹ sư PCB.

                          Khi các kỹ sư mô tả những tính năng mới mà họ cần, tôi đã yêu cầu họ hướng dẫn tôi qua các tình huống về cách các đối tượng tương tác. Khi các đối tượng mô hình không thể dẫn chúng tôi qua một tình huống quan trọng, chúng tôi đã brainstorming ra những tình huống mới hoặc thay đổi những tình huống cũ, khai thác kiến thức của họ. Chúng tôi đã tinh chỉnh mô hình; mã nguồn đã đồng tiến hóa. Vài tháng sau, các kỹ sư PCB đã có một công cụ phong phú vượt xa mong đợi của họ.


                            Ingredients of Effective Modeling

                            Một số việc chúng tôi đã làm đã dẫn đến thành công mà tôi vừa mô tả.

                            1. Liên kết mô hình và triển khai. Nguyên mẫu thô đó đã tạo ra liên kết thiết yếu từ sớm, và nó đã được duy trì qua tất cả các lần lặp lại sau này.

                            Nuôi dưỡng một ngôn ngữ dựa trên mô hình. Ban đầu, các kỹ sư phải giải thích cho tôi các vấn đề cơ bản của PCB, và tôi phải giải thích ý nghĩa của một sơ đồ lớp. Nhưng khi dự án tiến triển, bất kỳ ai trong chúng tôi cũng có thể lấy các thuật ngữ trực tiếp từ mô hình, sắp xếp chúng thành các câu nhất quán với cấu trúc của mô hình, và được hiểu một cách rõ ràng mà không cần dịch.

                            Phát triển một mô hình giàu tri thức. Các đối tượng có hành vi và các quy tắc được thực thi. Mô hình không chỉ đơn thuần là một sơ đồ dữ liệu; nó là phần thiết yếu để giải quyết một vấn đề phức tạp. Nó đã nắm bắt tri thức ở nhiều dạng khác nhau.

                            Chưng cất mô hình. Những khái niệm quan trọng đã được thêm vào mô hình khi nó trở nên hoàn thiện hơn, nhưng không kém phần quan trọng, các khái niệm đã được bỏ qua khi chúng không chứng minh được tính hữu ích hoặc trung tâm. Khi một khái niệm không cần thiết gắn liền với một khái niệm cần thiết, một mô hình mới được tìm thấy để phân biệt khái niệm thiết yếu để khái niệm khác có thể được loại bỏ.

                            Lên ý tưởng và thử nghiệm. Ngôn ngữ, kết hợp với các bản phác thảo và tinh thần động não, đã biến các cuộc thảo luận của chúng tôi thành phòng thí nghiệm của mô hình, nơi hàng trăm biến thể thử nghiệm có thể được thực hiện, thử nghiệm và đánh giá. Khi đội ngũ xem xét các kịch bản, chính những biểu đạt bằng lời đã cung cấp một bài kiểm tra tính khả thi nhanh chóng cho mô hình được đề xuất, khi tai có thể nhanh chóng phát hiện ra sự rõ ràng và dễ dàng hoặc sự vụng về trong cách diễn đạt.

                            Đó là sự sáng tạo trong việc động não và thử nghiệm quy mô lớn, được tận dụng thông qua một ngôn ngữ dựa trên mô hình và được quy định bởi quy trình phản hồi qua việc thực hiện, điều này giúp tìm ra một mô hình giàu tri thức và tinh lọc nó. Quá trình xử lý tri thức kiểu này biến kiến thức của đội ngũ thành những mô hình giá trị.


                              Knowledge Crunching

                              Các nhà phân tích tài chính xử lý các con số. Họ lục lọi qua hàng nghìn con số chi tiết, kết hợp và tái kết hợp chúng để tìm ra ý nghĩa cơ bản, tìm kiếm một cách trình bày đơn giản làm nổi bật những gì thực sự quan trọng - một sự hiểu biết có thể là cơ sở cho quyết định tài chính.

                              Những người lập mô hình miền hiệu quả là những người xử lý kiến thức. Họ tiếp nhận một lượng thông tin lớn và tìm kiếm những phần thông tin quan trọng. Họ thử một ý tưởng tổ chức này sang ý tưởng khác, tìm kiếm cái nhìn đơn giản giúp hiểu rõ khối lượng thông tin. Nhiều mô hình được thử nghiệm, từ chối hoặc biến đổi. Thành công đến từ một tập hợp các khái niệm trừu tượng đang dần hình thành, giúp hiểu rõ tất cả chi tiết. Sự tinh lọc này là một diễn đạt nghiêm ngặt của kiến thức cụ thể mà đã được tìm thấy là phù hợp nhất.

                              Việc phân tích kiến thức không phải là hoạt động đơn độc. Một đội ngũ lập trình viên và các chuyên gia trong lĩnh vực cùng hợp tác, thường do các lập trình viên dẫn dắt. Họ cùng nhau thu thập thông tin và biến nó thành dạng hữu ích. Nguyên liệu thô đến từ những suy nghĩ của các chuyên gia trong lĩnh vực, từ người dùng của các hệ thống hiện có, từ kinh nghiệm trước đó của đội ngũ kỹ thuật với một hệ thống kế thừa liên quan hoặc một dự án khác trong cùng lĩnh vực. Nó xuất hiện dưới hình thức tài liệu được viết cho dự án hoặc sử dụng trong kinh doanh, và rất nhiều cuộc trò chuyện. Các phiên bản đầu tiên hoặc nguyên mẫu cung cấp kinh nghiệm trở lại cho đội ngũ và thay đổi cách diễn giải.

                              Trong phương pháp thác nước cũ, các chuyên gia kinh doanh nói chuyện với các nhà phân tích, và các nhà phân tích tiếp nhận, trừu tượng hóa và chuyển kết quả đến các lập trình viên, những người viết mã phần mềm. Phương pháp này thất bại vì hoàn toàn thiếu phản hồi. Các nhà phân tích phải chịu trách nhiệm hoàn toàn trong việc tạo ra mô hình, chỉ dựa vào thông tin từ các chuyên gia kinh doanh. Họ không có cơ hội để học hỏi từ các lập trình viên hoặc có kinh nghiệm với các phiên bản phần mềm ban đầu. Kiến thức chỉ chảy theo một hướng, nhưng không tích lũy lại.

                              Các dự án khác sử dụng quy trình lặp đi lặp lại, nhưng họ không xây dựng được kiến thức vì họ không trừu tượng hóa. Các lập trình viên yêu cầu các chuyên gia mô tả một tính năng mong muốn và sau đó họ xây dựng nó. Họ cho các chuyên gia xem kết quả và hỏi nên làm gì tiếp theo. Nếu các lập trình viên thực hành tái cấu trúc, họ có thể giữ cho phần mềm đủ sạch để tiếp tục mở rộng, nhưng nếu lập trình viên không quan tâm đến miền chuyên môn, họ chỉ học những gì ứng dụng nên làm, chứ không phải những nguyên tắc đứng sau nó. Phần mềm hữu ích có thể được xây dựng theo cách đó, nhưng dự án sẽ không bao giờ đến được điểm mà các tính năng mới mạnh mẽ xuất hiện như là hệ quả của các tính năng cũ.

                              Các lập trình viên giỏi sẽ tự nhiên bắt đầu trừu tượng hóa và phát triển một mô hình có khả năng thực hiện nhiều công việc hơn. Nhưng khi điều này chỉ xảy ra trong một bối cảnh kỹ thuật, không có sự hợp tác với các chuyên gia trong lĩnh vực, các khái niệm sẽ trở nên ngây thơ. Sự nông cạn trong kiến thức đó tạo ra phần mềm chỉ thực hiện được những công việc cơ bản nhưng thiếu mối liên hệ sâu sắc với cách suy nghĩ của các chuyên gia trong lĩnh vực.

                              Sự tương tác giữa các thành viên trong nhóm thay đổi khi tất cả các thành viên cùng làm việc với mô hình. Việc tinh chỉnh liên tục mô hình miền buộc các nhà phát triển phải học các nguyên tắc quan trọng của doanh nghiệp mà họ đang hỗ trợ, thay vì chỉ sản xuất các chức năng theo cách máy móc. Các chuyên gia trong lĩnh vực thường làm sâu sắc hơn sự hiểu biết của chính họ khi bị buộc phải chắt lọc những gì họ biết thành những điều cốt lõi, và họ bắt đầu hiểu được yêu cầu khắt khe về khái niệm mà các dự án phần mềm cần thiết.

                              Tất cả những điều này làm cho các thành viên trong nhóm trở thành những người phân tích thông tin có năng lực hơn. Họ lọc bỏ những thứ không cần thiết. Họ tái cấu trúc mô hình thành một hình thức hữu ích hơn bao giờ hết. Vì các nhà phân tích và lập trình viên tham gia vào, nó được tổ chức và trừu tượng hóa một cách rõ ràng, vì vậy nó có thể cung cấp đòn bẩy cho việc triển khai. Vì các chuyên gia trong lĩnh vực tham gia vào, mô hình phản ánh hiểu biết sâu sắc về doanh nghiệp. Những sự trừu tượng này là những nguyên tắc kinh doanh đúng đắn.

                              Khi mô hình được cải thiện, nó trở thành một công cụ để tổ chức thông tin liên tục chảy qua dự án. Mô hình tập trung vào phân tích yêu cầu. Nó tương tác chặt chẽ với lập trình và thiết kế. Và trong một chu trình thiện chí, nó làm sâu sắc thêm cái nhìn của các thành viên trong nhóm về lĩnh vực, giúp họ thấy rõ hơn và dẫn đến việc tinh chỉnh mô hình thêm nữa. Các mô hình này không bao giờ hoàn hảo; chúng tiến hóa. Chúng phải thực tế và hữu ích trong việc làm rõ lĩnh vực. Chúng phải đủ nghiêm ngặt để làm cho ứng dụng đơn giản để triển khai và hiểu.


                                Continuous Learning

                                Khi chúng ta bắt tay vào viết phần mềm, chúng ta không bao giờ biết đủ. Kiến thức về dự án bị phân mảnh, rải rác giữa nhiều người và tài liệu, và nó bị lẫn với thông tin khác đến nỗi chúng ta không biết những phần kiến thức nào là thực sự cần thiết. Các lĩnh vực có vẻ ít khó khăn về mặt kỹ thuật có thể đánh lừa chúng ta: chúng ta không nhận ra mình không biết nhiều như thế nào. Sự thiếu hiểu biết này dẫn chúng ta đến việc đưa ra những giả định sai lầm.

                                Trong khi đó, tất cả các dự án đều rò rỉ kiến thức. Những người đã học được điều gì đó thường chuyển đi. Sự tái tổ chức phân tán đội ngũ, và kiến thức lại bị phân mảnh. Các miền hệ thống quan trọng được thuê ngoài theo cách mà mã được giao nhưng kiến thức thì không. Và với các phương pháp thiết kế điển hình, mã và tài liệu không diễn đạt được kiến thức đã tích lũy được một cách hữu ích, vì vậy khi truyền thống miệng bị gián đoạn vì bất kỳ lý do nào, kiến thức sẽ bị mất.

                                Các nhóm có năng suất cao phát triển kiến thức của họ một cách có ý thức, thực hành việc học tập liên tục (Kerievsky 2003). Đối với các nhà phát triển, điều này có nghĩa là cải thiện kiến thức kỹ thuật, cùng với các kỹ năng mô hình miền tổng quát (chẳng hạn như những kỹ năng trong cuốn sách này). Nhưng nó cũng bao gồm việc học nghiêm túc về miền cụ thể mà họ đang làm việc.

                                Những thành viên trong nhóm tự học này tạo thành một lõi ổn định của những người tập trung vào các nhiệm vụ phát triển liên quan đến những lĩnh vực quan trọng nhất. (Để biết thêm về vấn đề này, xem Chương 15.) Kiến thức tích lũy trong tâm trí của nhóm lõi này giúp họ trở thành những người xử lý thông tin hiệu quả hơn.

                                Tại thời điểm này, hãy dừng lại và tự hỏi bản thân một câu hỏi. Bạn có học được điều gì về quy trình thiết kế PCB không? Mặc dù ví dụ này chỉ là một cái nhìn tổng quát về lĩnh vực đó, nhưng vẫn nên có một số kiến thức thu được khi thảo luận về mô hình miền. Tôi đã học được rất nhiều. Tôi không học cách trở thành một kỹ sư PCB. Đó không phải là mục tiêu. Tôi học cách giao tiếp với các chuyên gia PCB, hiểu các khái niệm chính liên quan đến ứng dụng, và kiểm tra tính hợp lý của những gì chúng tôi đang xây dựng.

                                Trên thực tế, nhóm của chúng tôi cuối cùng đã phát hiện ra rằng việc mô phỏng probe là một ưu tiên thấp cho việc phát triển, và tính năng này cuối cùng đã bị loại bỏ hoàn toàn. Cùng với nó, các phần của mô hình mà nắm bắt sự hiểu biết về việc truyền tín hiệu qua các thành phần và đếm số bước nhảy cũng đã biến mất. Cốt lõi của ứng dụng hóa ra nằm ở những chỗ khác, và mô hình đã thay đổi để đưa những khía cạnh đó lên trung tâm. Các chuyên gia trong lĩnh vực đã học hỏi nhiều hơn và đã làm rõ mục tiêu của ứng dụng. (Chương 15 thảo luận những vấn đề này một cách sâu sắc.)

                                Dù vậy, công việc ban đầu là rất cần thiết. Các yếu tố chính của mô hình đã được giữ lại, nhưng quan trọng hơn, công việc đó đã khởi động quá trình thu thập kiến thức mà làm cho tất cả các công việc sau này hiệu quả: kiến thức thu được từ các thành viên trong nhóm, các nhà phát triển và các chuyên gia trong lĩnh vực; sự khởi đầu của một ngôn ngữ chung; và việc khép kín một vòng phản hồi thông qua việc thực hiện. Một hành trình khám phá phải bắt đầu từ đâu đó.


                                  Knowledge-Rich Design

                                  Loại kiến thức được ghi lại trong một mô hình như ví dụ PCB vượt ra ngoài việc "tìm các danh từ." Các hoạt động và quy tắc kinh doanh cũng quan trọng đối với một miền như các thực thể liên quan; bất kỳ miền nào cũng sẽ có nhiều loại khái niệm khác nhau. Việc xử lý kiến thức tạo ra các mô hình phản ánh loại hiểu biết này. Song song với những thay đổi mô hình, các nhà phát triển tái cấu trúc việc triển khai để thể hiện mô hình, giúp ứng dụng sử dụng kiến thức đó.

                                  Với sự di chuyển này vượt ra ngoài các thực thể và giá trị, việc xử lý tri thức có thể trở nên căng thẳng, vì có thể có sự không nhất quán thực sự giữa các quy tắc kinh doanh. Các chuyên gia trong lĩnh vực thường không nhận thức được mức độ phức tạp của các quy trình tư duy của họ, vì trong quá trình làm việc, họ điều hướng tất cả những quy tắc này, hòa giải các mâu thuẫn và lấp đầy những khoảng trống bằng lẽ thường. Phần mềm không thể làm điều này. Chính thông qua việc xử lý tri thức trong sự hợp tác chặt chẽ với các chuyên gia phần mềm mà các quy tắc được làm rõ, phát triển, hòa giải hoặc được đưa ra ngoài phạm vi.

                                  Example
                                  Extracting a Hidden Concept

                                  Hãy bắt đầu với một mô hình miền rất đơn giản có thể là cơ sở cho một ứng dụng đặt hàng hóa lên chuyến đi của một con tàu.

                                  Figure 1.8.

                                  graphics/01fig08.gif

                                  Chúng ta có thể nói rằng trách nhiệm của ứng dụng đặt chỗ là liên kết mỗi Cargo với một Voyage, ghi lại và theo dõi mối quan hệ đó. Đến giờ vẫn ổn. Ở đâu đó trong mã ứng dụng có thể có một phương thức như sau:

                                  public int makeBooking(Cargo cargo, Voyage voyage) { int confirmation = orderConfirmationSequence.next(); voyage.addCargo(cargo, confirmation); return confirmation; } 

                                  Vì luôn có những trường hợp hủy chuyến vào phút chót, nên thực tiễn tiêu chuẩn trong ngành vận chuyển là chấp nhận nhiều hàng hóa hơn mức mà một chiếc tàu có thể chở trong một chuyến đi. Điều này được gọi là "đặt chỗ vượt quá." Đôi khi, một tỷ lệ đơn giản của công suất được sử dụng, chẳng hạn như đặt 110% công suất. Trong những trường hợp khác, các quy tắc phức tạp được áp dụng, ưu tiên cho các khách hàng lớn hoặc một số loại hàng hóa nhất định.

                                  Đây là một chiến lược cơ bản trong lĩnh vực vận chuyển mà bất kỳ doanh nhân nào trong ngành vận tải cũng biết, nhưng có thể không phải ai trong đội ngũ kỹ thuật phần mềm cũng hiểu.

                                  Tài liệu yêu cầu chứa dòng này:

                                  Cho phép quá bán 10%.

                                  Biểu đồ lớp và mã bây giờ trông như thế này:

                                  Figure 1.9.

                                  graphics/01fig09.gif

                                  public int makeBooking(Cargo cargo, Voyage voyage) { double maxBooking = voyage.capacity() * 1.1; if ((voyage.bookedCargoSize() + cargo.size()) > maxBooking) return –1; int confirmation = orderConfirmationSequence.next(); voyage.addCargo(cargo, confirmation); return confirmation; } 

                                  Hiện tại, một quy tắc kinh doanh quan trọng bị ẩn dưới dạng một điều khoản bảo vệ trong một phương thức ứng dụng. Sau này, trong Chương 4, chúng ta sẽ xem xét nguyên tắc KIẾN TRÚC TẦNG, điều này sẽ hướng dẫn chúng ta di chuyển quy tắc đặt chỗ quá mức vào một đối tượng miền, nhưng bây giờ hãy tập trung vào cách chúng ta có thể làm cho kiến thức này rõ ràng hơn và dễ tiếp cận hơn với mọi người trong dự án. Điều này sẽ đưa chúng ta đến một giải pháp tương tự.

                                  1. Như đã viết, khó có khả năng bất kỳ chuyên gia kinh doanh nào có thể đọc mã này để xác minh quy tắc, ngay cả với sự hướng dẫn của một nhà phát triển.

                                  Sẽ rất khó khăn cho một người không có chuyên môn kinh doanh nhưng có kiến thức kỹ thuật để kết nối văn bản yêu cầu với mã.

                                  Nếu quy tắc phức tạp hơn, thì sẽ có nhiều thứ hơn nữa bị ảnh hưởng.

                                  Chúng ta có thể thay đổi thiết kế để tốt hơn trong việc nắm bắt kiến thức này. Quy tắc quá đặt chỗ là một chính sách. Chính sách là một tên gọi khác cho mẫu thiết kế được biết đến với tên STRATEGY (Gamma et al. 1995). Nó thường được thúc đẩy bởi nhu cầu thay thế các quy tắc khác nhau, điều này không cần thiết ở đây, như far như chúng tôi biết. Nhưng khái niệm mà chúng tôi đang cố gắng nắm bắt phù hợp với ý nghĩa của một chính sách, đây là một động lực quan trọng không kém trong thiết kế hướng miền. (Xem Chương 12, "Liên quan Đến Các Mẫu Thiết Kế Với Mô Hình.")

                                  Figure 1.10.

                                  graphics/01fig10.gif

                                  Mã hiện tại là:

                                  public int makeBooking(Cargo cargo, Voyage voyage) { if (!overbookingPolicy.isAllowed(cargo, voyage)) return –1; int confirmation = orderConfirmationSequence.next(); voyage.addCargo(cargo, confirmation); return confirmation; } 

                                  Lớp Chính sách Đặt chỗ quá mức mới chứa phương thức này:

                                  public boolean isAllowed(Cargo cargo, Voyage voyage) { return (cargo.size() + voyage.bookedCargoSize()) <= (voyage.capacity() * 1.1); } 

                                  Sẽ rõ ràng với mọi người rằng việc đặt chỗ quá mức là một chính sách khác biệt, và việc thực hiện quy tắc đó là rõ ràng và tách biệt.

                                  Bây giờ, tôi không khuyên bạn nên áp dụng một thiết kế phức tạp như vậy cho mọi chi tiết của lĩnh vực. Chương 15, "Chưng cất," đi sâu vào cách để tập trung vào những điều quan trọng và giảm thiểu hoặc tách biệt mọi thứ khác. Ví dụ này nhằm mục đích cho thấy rằng một mô hình miền và thiết kế tương ứng có thể được sử dụng để bảo vệ và chia sẻ kiến thức. Thiết kế rõ ràng hơn có những lợi ích sau:

                                  1. Để đưa thiết kế đến giai đoạn này, các lập trình viên và tất cả những người liên quan sẽ phải hiểu rõ bản chất của việc đặt chỗ quá mức như một quy tắc kinh doanh riêng biệt và quan trọng, chứ không chỉ là một phép tính mơ hồ.

                                  Các lập trình viên có thể trình bày cho các chuyên gia kinh doanh những sản phẩm kỹ thuật, thậm chí là mã code, mà các chuyên gia trong lĩnh vực có thể hiểu được (với sự hướng dẫn), từ đó khép kín vòng phản hồi.


                                    Deep Models

                                    Các mô hình hữu ích hiếm khi nằm trên bề mặt. Khi chúng ta bắt đầu hiểu miền và nhu cầu của ứng dụng, chúng ta thường loại bỏ những yếu tố mô hình nông nổi mà trước đây có vẻ quan trọng, hoặc thay đổi góc nhìn của chúng. Những trừu tượng tinh tế xuất hiện mà chúng ta không nghĩ đến lúc ban đầu nhưng lại đi sâu vào vấn đề cốt lõi.

                                    Ví dụ trước đó được dựa loosely vào một trong những dự án mà tôi sẽ sử dụng làm ví dụ trong suốt cuốn sách: một hệ thống vận chuyển container. Các ví dụ trong cuốn sách này sẽ được giữ ở mức dễ tiếp cận cho những người không phải là chuyên gia về vận tải. Nhưng trong một dự án thực tế, nơi mà việc học liên tục chuẩn bị cho các thành viên trong nhóm, mô hình hữu ích và rõ ràng thường đòi hỏi sự tinh vi cả trong lĩnh vực và trong kỹ thuật mô hình hóa.

                                    Trong dự án đó, vì việc giao hàng bắt đầu từ hành động đặt chỗ hàng hóa, chúng tôi đã phát triển một mô hình cho phép mô tả hàng hóa, lộ trình của nó và những vấn đề khác. Tất cả những điều này đều cần thiết và hữu ích, nhưng các chuyên gia trong lĩnh vực cảm thấy không hài lòng. Có một cách mà họ nhìn nhận doanh nghiệp của mình mà chúng tôi đã bỏ lỡ.

                                    Cuối cùng, sau nhiều tháng nghiền ngẫm kiến thức, chúng tôi nhận ra rằng việc xử lý hàng hóa, việc xếp dỡ hàng hóa, và các di chuyển từ nơi này đến nơi khác chủ yếu được thực hiện bởi các nhà thầu phụ hoặc những người hoạt động trong công ty. Theo ý kiến của các chuyên gia vận chuyển của chúng tôi, có một loạt các chuyển giao trách nhiệm giữa các bên. Một quy trình quản lý việc chuyển giao trách nhiệm pháp lý và thực tế, từ người gửi hàng đến một nhà vận chuyển địa phương, từ nhà vận chuyển này sang nhà vận chuyển khác, và cuối cùng đến người nhận hàng. Thường thì hàng hóa sẽ nằm trong kho trong khi những bước quan trọng đang được thực hiện. Vào những lúc khác, hàng hóa sẽ di chuyển qua các bước vật lý phức tạp mà không liên quan đến các quyết định kinh doanh của công ty vận chuyển. Thay vì tập trung vào logistics của hành trình, những gì nổi bật lên lại là các tài liệu pháp lý như vận đơn, và các quy trình dẫn đến việc giải phóng thanh toán.

                                    Quan điểm sâu sắc hơn về ngành vận tải biển không dẫn đến việc loại bỏ đối tượng Lịch trình, nhưng mô hình đã thay đổi sâu sắc. Quan điểm của chúng tôi về vận tải biển đã chuyển từ việc di chuyển container từ địa điểm này đến địa điểm khác, sang việc chuyển giao trách nhiệm hàng hóa từ thực thể này sang thực thể khác. Các tính năng để xử lý những chuyển giao trách nhiệm này không còn bị gán một cách vụng về vào các hoạt động dỡ hàng, mà được hỗ trợ bởi một mô hình xuất phát từ sự hiểu biết về mối quan hệ quan trọng giữa những hoạt động đó và những trách nhiệm này.

                                    Khám phá kiến thức là một hành trình, và bạn không thể biết bạn sẽ kết thúc ở đâu.


                                      Chapter Two. Communication and the Use of Language

                                      Một mô hình miền có thể là cốt lõi của một ngôn ngữ chung cho một dự án phần mềm. Mô hình là một tập hợp các khái niệm được hình thành trong đầu của những người tham gia dự án, với các thuật ngữ và mối quan hệ phản ánh hiểu biết về miền. Các thuật ngữ và mối quan hệ này cung cấp ý nghĩa cho một ngôn ngữ được điều chỉnh theo miền nhưng đủ chính xác cho phát triển kỹ thuật. Đây là sợi dây quan trọng gắn kết mô hình với hoạt động phát triển và liên kết nó với mã nguồn.

                                      Giao tiếp dựa trên mô hình này không chỉ giới hạn trong các sơ đồ của Ngôn ngữ Mô hình Hợp nhất (UML). Để sử dụng mô hình một cách hiệu quả nhất, nó cần thấm nhuần trong mọi phương tiện giao tiếp. Nó tăng cường khả năng sử dụng của các tài liệu văn bản viết, cũng như các sơ đồ không chính thức và các cuộc đối thoại thân mật được nhấn mạnh trong các quy trình Agile. Nó cải thiện giao tiếp qua chính mã nguồn và qua các bài kiểm tra cho mã nguồn đó.

                                      Việc sử dụng ngôn ngữ trong một dự án là tinh tế nhưng lại rất quan trọng.


                                        Ubiquitous Language

                                        Trước tiên, bạn viết một câu, Rồi bạn cắt nó thành từng phần nhỏ; Sau đó trộn các mảnh lại và sắp xếp chúng Như chúng rơi xuống: Thứ tự của các cụm từ không Có bất kỳ khác biệt nào.

                                        "Lewis Carroll, 'Nhà thơ được hình thành, không phải được sinh ra'"

                                        Để tạo ra một thiết kế mềm mại, phong phú kiến thức, cần có một ngôn ngữ nhóm linh hoạt và chia sẻ, cùng với một sự thử nghiệm sinh động với ngôn ngữ mà hiếm khi xảy ra trong các dự án phần mềm.

                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                        Các chuyên gia trong lĩnh vực có sự hiểu biết hạn chế về các thuật ngữ kỹ thuật của phát triển phần mềm, nhưng họ sử dụng thuật ngữ trong lĩnh vực của họ - có thể theo nhiều cách khác nhau. Mặt khác, các lập trình viên có thể hiểu và thảo luận về hệ thống bằng các thuật ngữ mô tả, chức năng, nhưng lại thiếu đi ý nghĩa mà ngôn ngữ của các chuyên gia mang lại. Hoặc các lập trình viên có thể tạo ra các trừu tượng hỗ trợ thiết kế của họ nhưng không được các chuyên gia trong lĩnh vực hiểu. Các lập trình viên làm việc trên các phần khác nhau của vấn đề phát triển các khái niệm thiết kế và cách mô tả lĩnh vực riêng của họ.

                                        Trên cái khoảng cách ngôn ngữ này, các chuyên gia trong lĩnh vực mơ hồ mô tả điều họ muốn. Các nhà phát triển, gặp khó khăn trong việc hiểu một lĩnh vực mới, cũng chỉ hiểu một cách mơ hồ. Một vài thành viên trong nhóm cố gắng trở thành người song ngữ, nhưng họ trở thành nút thắt trong dòng chảy thông tin, và những bản dịch của họ không chính xác.

                                        Trong một dự án không có ngôn ngữ chung, các nhà phát triển phải dịch cho các chuyên gia trong lĩnh vực. Các chuyên gia trong lĩnh vực dịch giữa các nhà phát triển và các chuyên gia trong lĩnh vực khác. Các nhà phát triển thậm chí còn dịch cho nhau. Việc dịch thuật làm rối loạn các khái niệm mô hình, dẫn đến việc tái cấu trúc mã phá hoại. Sự gián tiếp trong giao tiếp che giấu việc hình thành các phân rã—các thành viên khác nhau trong nhóm sử dụng các thuật ngữ khác nhau nhưng không nhận ra điều đó. Điều này dẫn đến phần mềm không đáng tin cậy mà không hòa hợp với nhau (xem Chương 14). Nỗ lực dịch thuật ngăn cản việc tương tác giữa kiến thức và ý tưởng, điều này dẫn đến những nhận thức sâu sắc về mô hình.

                                        Một dự án gặp phải các vấn đề nghiêm trọng khi ngôn ngữ của nó bị phân mảnh. Các chuyên gia trong lĩnh vực sử dụng biệt ngữ của họ trong khi các thành viên trong đội kỹ thuật có ngôn ngữ riêng được điều chỉnh để thảo luận về lĩnh vực theo cách thiết kế.

                                        Thuật ngữ trong các cuộc thảo luận hàng ngày không liên quan đến thuật ngữ được nhúng trong mã (sản phẩm quan trọng nhất của một dự án phần mềm). Thậm chí, ngay cả cùng một người cũng sử dụng ngôn ngữ khác nhau trong lời nói và trong văn viết, do đó những biểu thức sắc bén nhất của miền thường xuất hiện dưới hình thức tạm thời mà không bao giờ được ghi lại trong mã hoặc thậm chí trong văn bản.

                                        Dịch thuật làm giảm sự giao tiếp và khiến việc xử lý kiến thức trở nên yếu ớt.

                                        Tuy nhiên, không có phương ngữ nào trong số này có thể trở thành ngôn ngữ chung vì không phương ngữ nào đáp ứng tất cả các nhu cầu.

                                        Chi phí phụ của tất cả các bản dịch, cộng với rủi ro hiểu lầm, là quá cao. Một dự án cần một ngôn ngữ chung vững chắc hơn là mức thấp nhất của người tham gia. Với nỗ lực có ý thức từ đội ngũ, mô hình miền có thể cung cấp nền tảng cho ngôn ngữ chung đó, đồng thời kết nối giao tiếp của đội với việc triển khai phần mềm. Ngôn ngữ đó có thể hiện hữu trong công việc của cả đội.

                                        Vocabularies của NGÔN NGỮ PHỔ BIẾN đó bao gồm tên của các lớp và các phép toán quan trọng. NGÔN NGỮ này bao gồm các thuật ngữ để thảo luận về các quy tắc đã được nêu rõ trong mô hình. Nó được bổ sung bằng các thuật ngữ từ các nguyên tắc tổ chức cấp cao được áp đặt lên mô hình (như BẢN ĐỒ NGỮ CẢNH và các cấu trúc quy mô lớn, sẽ được thảo luận trong Chương 14 và 16). Cuối cùng, ngôn ngữ này được làm phong phú với các tên mẫu mà nhóm thường áp dụng vào mô hình miền.

                                        Các mối quan hệ trong mô hình trở thành quy tắc kết hợp mà tất cả các ngôn ngữ đều có. Ý nghĩa của các từ và cụm từ phản ánh ngữ nghĩa của mô hình.

                                        Ngôn ngữ dựa trên mô hình nên được sử dụng giữa các nhà phát triển để mô tả không chỉ các đối tượng trong hệ thống mà còn cả nhiệm vụ và chức năng. Mô hình này cũng nên cung cấp ngôn ngữ cho các nhà phát triển và các chuyên gia trong lĩnh vực để giao tiếp với nhau, và cho các chuyên gia trong lĩnh vực để giao tiếp với nhau về yêu cầu, kế hoạch phát triển và các tính năng. Ngôn ngữ được sử dụng phổ biến hơn sẽ giúp việc hiểu biết diễn ra suôn sẻ hơn.

                                        Ít nhất, đây là nơi chúng ta cần phải đến. Nhưng ban đầu, mô hình có thể đơn giản là không đủ tốt để đảm nhiệm những vai trò này. Nó có thể thiếu sự phong phú ngữ nghĩa của các thuật ngữ chuyên ngành trong lĩnh vực đó. Nhưng những thuật ngữ đó không thể được sử dụng nguyên vẹn vì chúng chứa đựng những mơ hồ và mâu thuẫn. Nó có thể thiếu những đặc điểm tinh tế và năng động hơn mà các nhà phát triển đã tạo ra trong mã, hoặc vì họ không coi đó là một phần của mô hình, hoặc vì phong cách lập trình là quy trình và chỉ âm thầm mang những khái niệm của lĩnh vực.

                                        Nhưng mặc dù chuỗi này có vẻ giống như một vòng tròn, quá trình xử lý kiến thức có thể tạo ra một loại mô hình hữu ích hơn phụ thuộc vào cam kết của đội ngũ đối với ngôn ngữ dựa trên mô hình. Việc sử dụng liên tục NGÔN NGỮ PHỔ BIẾN sẽ buộc những điểm yếu của mô hình phải được làm sáng tỏ. Đội ngũ sẽ thử nghiệm và tìm ra các cách diễn đạt thay thế cho những thuật ngữ hoặc tổ hợp lúng túng. Khi các khoảng trống được phát hiện trong ngôn ngữ, những từ mới sẽ được đưa vào thảo luận. Những thay đổi trong ngôn ngữ này sẽ được công nhận là những thay đổi trong mô hình miền và sẽ dẫn đội ngũ cập nhật các sơ đồ lớp và đổi tên các lớp và phương thức trong mã, hoặc thậm chí thay đổi hành vi, khi ý nghĩa của một thuật ngữ thay đổi.

                                        Cam kết sử dụng ngôn ngữ này trong bối cảnh triển khai, các nhà phát triển sẽ chỉ ra sự không chính xác hoặc mâu thuẫn, tham gia cùng các chuyên gia trong việc khám phá các lựa chọn khả thi.

                                        Tất nhiên, các chuyên gia trong lĩnh vực sẽ nói ngoài phạm vi của NGÔN NGỮ PHỔ BIẾN, để giải thích và cung cấp bối cảnh rộng hơn. Nhưng trong phạm vi mà mô hình đề cập, họ nên sử dụng NGÔN NGỮ và nêu ra những mối quan ngại khi họ cảm thấy nó khó hiểu hoặc chưa đầy đủ—hoặc sai. Bằng cách sử dụng ngôn ngữ dựa trên mô hình một cách triệt để và không hài lòng cho đến khi nó trở nên trôi chảy, chúng ta tiến đến một mô hình hoàn chỉnh và dễ hiểu, được tạo thành từ những yếu tố đơn giản kết hợp để diễn đạt những ý tưởng phức tạp.

                                        Do đó:

                                        Sử dụng mô hình như xương sống của một ngôn ngữ. Cam kết đội ngũ thực hành ngôn ngữ đó một cách liên tục trong tất cả các giao tiếp trong đội và trong mã. Sử dụng cùng một ngôn ngữ trong các sơ đồ, văn bản và đặc biệt là trong lời nói.

                                        Giải quyết các khó khăn bằng cách thử nghiệm với các biểu thức thay thế, phản ánh các mô hình thay thế. Sau đó, cải tiến mã, đổi tên các lớp, phương thức và mô-đun để phù hợp với mô hình mới. Giải quyết sự nhầm lẫn về các thuật ngữ trong cuộc trò chuyện, giống như cách chúng ta thống nhất về ý nghĩa của những từ thông thường.

                                        Nhận ra rằng một sự thay đổi trong NGÔN NGỮ PHỔ BIẾN là một sự thay đổi trong mô hình.

                                        Các chuyên gia trong lĩnh vực nên phản đối các thuật ngữ hoặc cấu trúc không tự nhiên hoặc không đủ để truyền đạt sự hiểu biết về lĩnh vực; các nhà phát triển nên chú ý đến sự không rõ ràng hoặc không nhất quán có thể gây khó khăn cho thiết kế.

                                        Với một NGÔN NGỮ PHỔ BIẾN, mô hình không chỉ là một sản phẩm thiết kế. Nó trở thành phần không thể thiếu trong mọi hoạt động mà các nhà phát triển và chuyên gia lĩnh vực thực hiện cùng nhau. NGÔN NGỮ mang lại kiến thức dưới dạng động. Cuộc thảo luận bằng NGÔN NGỮ làm sống lại ý nghĩa đằng sau các sơ đồ và mã lệnh.

                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                        Cuộc thảo luận về NGÔN NGỮ PHỔ THÔNG này giả định rằng chỉ có một mô hình duy nhất đang hoạt động. Chương 14, "Bảo trì Tính toàn vẹn của Mô hình," đề cập đến sự đồng tồn tại của các mô hình (và NGÔN NGỮ) khác nhau và cách để giữ cho một mô hình không bị phân mảnh.

                                        NGÔN NGỮ PHỔ BIẾN là yếu tố chính mang những khía cạnh của thiết kế không xuất hiện trong mã - các cấu trúc quy mô lớn tổ chức toàn bộ hệ thống (xem Chương 16), BỐI CẢNH GIỚI HẠN xác định mối quan hệ của các hệ thống và mô hình khác nhau (xem Chương 14), và các mẫu khác được áp dụng vào mô hình và thiết kế.

                                        Example
                                        Working Out a Cargo Router

                                        Hai cuộc đối thoại dưới đây có những khác biệt tinh tế nhưng quan trọng. Trong mỗi tình huống, hãy chú ý đến việc người nói bàn luận nhiều về việc phần mềm có ý nghĩa như thế nào đối với doanh nghiệp so với cách nó hoạt động về mặt kỹ thuật. Liệu người dùng và nhà phát triển có đang nói cùng một ngôn ngữ không? Liệu ngôn ngữ đó có đủ phong phú để truyền tải cuộc thảo luận về những điều ứng dụng phải làm không?

                                        Scenario 1: Minimal Abstraction of the Domain
                                        Figure 2.1.

                                        graphics/02fig01.gif

                                        Người dùng: Vậy khi chúng tôi thay đổi điểm thông quan, chúng tôi cần làm lại toàn bộ kế hoạch định tuyến.

                                        Nhà phát triển: Đúng. Chúng tôi sẽ xóa tất cả các hàng trong bảng lô hàng với mã hàng hóa đó, sau đó chúng tôi sẽ truyền điểm xuất phát, điểm đến và điểm thông quan mới vào Dịch vụ Định tuyến, và nó sẽ tái lập bảng. Chúng tôi sẽ phải có một biến Boolean trong Cargo để biết có dữ liệu trong bảng lô hàng.

                                        Người dùng: Xóa các hàng? Được rồi, mặc kệ. Dù sao, nếu trước đây chúng ta không có điểm thông quan nào, chúng ta sẽ phải làm điều tương tự.

                                        Nhà phát triển: Chắc chắn rồi, bất cứ khi nào bạn thay đổi điểm xuất phát, điểm đến hoặc điểm thông quan (hoặc nhập một trong các điểm này lần đầu tiên), chúng tôi sẽ kiểm tra xem có dữ liệu lô hàng hay không, sau đó chúng tôi sẽ xóa nó và để Dịch vụ Định tuyến tái tạo lại.

                                        Người dùng: Tất nhiên, nếu thủ tục hải quan cũ tình cờ đúng, chúng ta sẽ không muốn làm điều đó.

                                        Nhà phát triển: Ồ, không vấn đề gì. Dễ hơn khi chỉ để Dịch vụ Định tuyến làm lại việc tải và dỡ hàng mỗi lần.

                                        Người dùng: Vâng, nhưng đó là công việc thêm cho chúng tôi để lập tất cả các kế hoạch hỗ trợ cho một lộ trình mới, vì vậy chúng tôi không muốn thay đổi lộ trình trừ khi việc thay đổi đó yêu cầu.

                                        Nhà phát triển: Ugh. Vậy thì, nếu bạn đang vào một điểm thông quan lần đầu tiên, chúng ta sẽ phải truy vấn bảng để tìm điểm thông quan đã được xác định trước đó, và sau đó so sánh nó với điểm mới. Sau đó, chúng ta sẽ biết liệu có cần làm lại hay không.

                                        Người dùng: Bạn sẽ không phải lo lắng về điều này ở điểm khởi hành hoặc điểm đến, vì hành trình luôn thay đổi.

                                        Nhà phát triển: Tốt. Chúng tôi sẽ không.

                                        Scenario 2: Domain Model Enriched to Support Discussion
                                        Figure 2.2.

                                        graphics/02fig02.gif

                                        Người dùng: Vì vậy, khi chúng tôi thay đổi điểm thông quan, chúng tôi cần làm lại toàn bộ kế hoạch định tuyến.

                                        Nhà phát triển: Đúng vậy. Khi bạn thay đổi bất kỳ thuộc tính nào trong Đặc tả Tuyến đường, chúng tôi sẽ xóa Itinerary cũ và yêu cầu Dịch vụ Định tuyến tạo một cái mới dựa trên Đặc tả Tuyến đường mới.

                                        Người dùng: Nếu chúng ta chưa xác định điểm thông quan nào trước đây, chúng ta sẽ phải làm điều đó cùng một lúc.

                                        Nhà phát triển: Chắc chắn rồi, bất cứ khi nào bạn thay đổi bất kỳ điều gì trong Thông số Tuyến đường, chúng tôi sẽ tái tạo Lịch trình. Điều này bao gồm cả việc nhập thông tin lần đầu tiên.

                                        Người dùng: Tất nhiên, nếu thủ tục thông quan cũ tình cờ là cái đúng, chúng tôi sẽ không muốn làm điều đó.

                                        Nhà phát triển: Ồ, không có vấn đề gì. Dễ hơn là chỉ cần làm cho Dịch vụ Định tuyến làm lại Lịch trình mỗi lần.

                                        Người dùng: Vâng, nhưng đó là công việc thêm cho chúng tôi để tạo tất cả các kế hoạch hỗ trợ cho một hành trình mới, vì vậy chúng tôi không muốn thay đổi lộ trình trừ khi sự thay đổi đó yêu cầu điều đó.

                                        Nhà phát triển: Ồ. Vậy chúng ta sẽ phải thêm một số chức năng vào Đặc tả Lộ trình. Sau đó, bất cứ khi nào bạn thay đổi bất kỳ điều gì trong Đặc tả, chúng ta sẽ xem liệu Lịch trình có còn thoả mãn Đặc tả không. Nếu không, chúng ta sẽ để Dịch vụ Định tuyến tái tạo Lịch trình.

                                        Người dùng: Bạn sẽ không phải lo lắng về điều này tại điểm xuất phát hoặc điểm đến, vì Lịch trình sẽ luôn thay đổi vào lúc đó.

                                        Nhà phát triển: Được rồi, nhưng sẽ dễ dàng hơn cho chúng tôi nếu thực hiện so sánh mỗi lần. Lịch trình chỉ được tạo ra khi đặc điểm lộ trình không còn được thỏa mãn.

                                        Đối thoại thứ hai truyền đạt nhiều hơn về ý định của chuyên gia trong lĩnh vực này. Người dùng đã sử dụng từ "hành trình" trong cả hai cuộc đối thoại, nhưng trong lần thứ hai, đó là một đối tượng mà hai người có thể thảo luận một cách chính xác và cụ thể. Họ đã thảo luận về "đặc tả lộ trình" một cách rõ ràng, thay vì mô tả nó mỗi lần dưới dạng các thuộc tính và quy trình.

                                        Hai cuộc đối thoại này được xây dựng có chủ đích để tương đồng với nhau. Thực tế, cuộc đối thoại đầu tiên sẽ dài dòng hơn, tràn ngập các giải thích về các tính năng ứng dụng và những sự hiểu lầm. Thuật ngữ dựa trên mô hình miền trong thiết kế thứ hai khiến cuộc đối thoại thứ hai ngắn gọn hơn.


                                          Modeling Out Loud

                                          Sự tách rời của ngôn ngữ nói khỏi các hình thức giao tiếp khác là một tổn thất đặc biệt lớn, vì chúng ta, con người, có tài năng cho ngôn ngữ nói. Thật không may, khi mọi người nói chuyện, họ thường không sử dụng ngôn ngữ của mô hình miền.

                                          Câu phát biểu đó có thể không đúng với bạn ngay từ đầu, và thực sự có những trường hợp ngoại lệ. Nhưng lần tới khi bạn tham dự một cuộc thảo luận về yêu cầu hoặc thiết kế, hãy lắng nghe thật kỹ. Bạn sẽ nghe những mô tả về các tính năng bằng ngôn ngữ kinh doanh hoặc phiên bản dễ hiểu của ngôn ngữ chuyên ngành. Bạn sẽ nghe nói về các tài liệu kỹ thuật và chức năng cụ thể. Chắc chắn rằng bạn sẽ nghe thấy các thuật ngữ từ mô hình miền; những danh từ rõ ràng trong ngôn ngữ chung từ ngôn ngữ kinh doanh thường được mã hóa dưới dạng đối tượng, và vì vậy các thuật ngữ đó sẽ có xu hướng được nhắc đến. Nhưng bạn có nghe thấy những cụm từ có thể nói đến mối quan hệ và tương tác trong mô hình miền hiện tại của bạn không?

                                          Một trong những cách tốt nhất để cải thiện một mô hình là khám phá bằng cách nói, thử nghiệm thành tiếng các cấu trúc từ các biến thể mô hình có thể. Những điểm chưa hoàn thiện dễ dàng được nghe thấy.

                                          "Nếu chúng ta cung cấp cho Dịch vụ Định Tuyến một điểm khởi đầu, điểm đến và thời gian đến, nó có thể tra cứu các điểm dừng mà hàng hóa sẽ phải dừng lại và, ừm . . . lưu trữ chúng vào cơ sở dữ liệu."

                                          "Nguồn gốc, điểm đến và nhiều thứ khác... tất cả đều được đưa vào Dịch vụ Định tuyến, và chúng tôi nhận lại một Lịch trình có mọi thứ chúng tôi cần trong đó."

                                          "Dịch vụ định tuyến tìm hành trình thỏa mãn yêu cầu lộ trình."

                                          Rất quan trọng là chúng ta phải chơi với từ ngữ và cụm từ, sử dụng khả năng ngôn ngữ của mình cho nỗ lực mô hình hóa, cũng như việc cần thiết phải tham gia vào tư duy trực quan/khoảng không bằng cách phác thảo các sơ đồ. Cũng giống như chúng ta sử dụng khả năng phân tích của mình với phân tích và thiết kế có phương pháp, cùng với "cảm giác" kỳ diệu của mã nguồn. Những cách suy nghĩ này bổ sung cho nhau, và cần tất cả chúng để tìm ra các mô hình và thiết kế hữu ích. Trong số tất cả những điều này, việc thử nghiệm với ngôn ngữ thường bị bỏ qua nhất. (Phần III của cuốn sách này sẽ đi sâu vào quá trình khám phá này và chỉ ra mối tương tác này trong một số cuộc đối thoại.)

                                          Trên thực tế, bộ não của chúng ta dường như được chuyên biệt một phần cho việc xử lý sự phức tạp trong ngôn ngữ nói (một tài liệu tốt cho những người không chuyên, như tôi, là cuốn "Bản Năng Ngôn Ngữ" của Steven Pinker [Pinker 1994]). Ví dụ, khi người thuộc các nền văn hóa ngôn ngữ khác nhau cùng nhau tham gia vào thương mại, nếu họ không có một ngôn ngữ chung, họ sẽ invent một loại ngôn ngữ mới, gọi là pidgin. Pidgin không phong phú như các ngôn ngữ gốc của người nói, nhưng nó phù hợp với nhiệm vụ hiện tại. Khi mọi người nói chuyện, họ tự nhiên phát hiện ra những khác biệt trong cách hiểu và ý nghĩa của từ ngữ của họ, và họ tự nhiên giải quyết những khác biệt đó. Họ tìm ra những chỗ gồ ghề trong ngôn ngữ và làm cho chúng mượt mà hơn.

                                          Một lần tôi đã tham gia một lớp tiếng Tây Ban Nha tăng cường ở trường đại học. Quy tắc trong lớp học là không được nói một lời nào bằng tiếng Anh. Ban đầu, điều đó thật khó chịu. Nó cảm thấy rất không tự nhiên và đòi hỏi nhiều kỷ luật tự giác. Nhưng cuối cùng, tôi và các bạn cùng lớp đã đạt được một mức độ lưu loát mà chúng tôi không bao giờ có thể đạt được chỉ bằng các bài tập trên giấy.

                                          Khi chúng ta sử dụng NGÔN NGỮ PHỔ THÔNG của mô hình miền trong các cuộc thảo luận - đặc biệt là các cuộc thảo luận trong đó các nhà phát triển và chuyên gia miền làm rõ các kịch bản và yêu cầu - chúng ta trở nên thành thạo hơn trong ngôn ngữ này và dạy nhau những sắc thái của nó. Chúng ta tự nhiên chia sẻ ngôn ngữ mà chúng ta nói theo cách mà điều này không bao giờ xảy ra với các sơ đồ và tài liệu.

                                          Việc mang lại một NGÔN NGỮ PHỔ BIẾN trong một dự án phần mềm dễ nói hơn làm, và chúng ta phải hoàn toàn tận dụng tài năng tự nhiên của mình để thực hiện điều đó. Cũng giống như khả năng thị giác và không gian của con người cho phép chúng ta truyền đạt và xử lý thông tin một cách nhanh chóng qua các cái nhìn đồ họa, chúng ta có thể khai thác tài năng bẩm sinh của mình về ngôn ngữ ngữ pháp và có ý nghĩa để thúc đẩy sự phát triển mô hình.

                                          Do đó, như một phụ lục cho mô hình NGÔI NGÀY NGÔI NGÀY:

                                          Chơi với mô hình trong khi bạn nói về hệ thống. Mô tả các kịch bản ra tiếng bằng cách sử dụng các yếu tố và tương tác của mô hình, kết hợp các khái niệm theo cách mà mô hình cho phép. Tìm cách dễ hơn để nói những gì bạn cần nói, sau đó mang những ý tưởng mới đó trở lại với các sơ đồ và mã nguồn.


                                            One Team, One Language

                                            Người kỹ thuật thường cảm thấy cần phải "bảo vệ" các chuyên gia kinh doanh khỏi mô hình miền. Họ nói:

                                            "Quá trừu tượng đối với họ."

                                            "Họ không hiểu các đối tượng."

                                            "Chúng ta phải thu thập các yêu cầu bằng thuật ngữ của họ."

                                            Đây chỉ là một vài lý do tôi đã nghe về việc có hai ngôn ngữ trong đội. Quên chúng đi.

                                            Tất nhiên, có những yếu tố kỹ thuật của thiết kế có thể không liên quan đến các chuyên gia trong lĩnh vực, nhưng cốt lõi của mô hình thì tốt hơn nên thu hút sự quan tâm của họ. Quá trừu tượng? Vậy làm thế nào bạn biết rằng các sự trừu tượng là hợp lý? Bạn có hiểu lĩnh vực đó sâu sắc như họ không? Đôi khi, các yêu cầu cụ thể được thu thập từ người dùng cấp thấp hơn, và một tập hợp các thuật ngữ cụ thể hơn có thể là cần thiết cho họ, nhưng được giả định rằng một chuyên gia trong lĩnh vực có khả năng suy nghĩ một cách sâu sắc về lĩnh vực của mình. Nếu những chuyên gia trong lĩnh vực tinh vi không hiểu mô hình, thì có điều gì đó sai với mô hình đó.

                                            Bây giờ, ở giai đoạn đầu, khi người dùng đang thảo luận về những khả năng tương lai của hệ thống mà chưa được mô hình hóa, thì không có mô hình nào cho họ sử dụng. Nhưng ngay khi họ bắt đầu làm việc với các ý tưởng mới này cùng với các nhà phát triển, quá trình tìm kiếm một mô hình chung bắt đầu. Nó có thể khởi đầu bất tiện và chưa hoàn chỉnh, nhưng sẽ dần dần được tinh chỉnh. Khi ngôn ngữ mới phát triển, các chuyên gia trong lĩnh vực phải nỗ lực thêm để tiếp nhận nó và cập nhật bất kỳ tài liệu cũ nào vẫn còn quan trọng.

                                            Khi các chuyên gia trong lĩnh vực sử dụng NGÔN NGỮ này trong các cuộc thảo luận với các nhà phát triển hoặc giữa họ với nhau, họ nhanh chóng phát hiện ra những lĩnh vực mà mô hình không đáp ứng được nhu cầu của họ hoặc dường như không đúng theo quan điểm của họ. Các chuyên gia trong lĩnh vực (với sự trợ giúp của các nhà phát triển) cũng sẽ tìm ra những lĩnh vực mà độ chính xác của ngôn ngữ dựa trên mô hình phơi bày những mâu thuẫn hoặc sự mơ hồ trong suy nghĩ của họ.

                                            Các nhà phát triển và chuyên gia trong lĩnh vực có thể thử nghiệm mô hình một cách không chính thức bằng cách đi qua các kịch bản, sử dụng các đối tượng mô hình từng bước một. Hầu như mọi cuộc thảo luận đều là cơ hội cho các nhà phát triển và chuyên gia người dùng cùng chơi với mô hình, làm sâu sắc thêm sự hiểu biết của nhau và tinh chỉnh các khái niệm khi họ tiến hành.

                                            Các chuyên gia miền có thể sử dụng ngôn ngữ của mô hình trong việc viết các trường hợp sử dụng, và có thể làm việc trực tiếp hơn với mô hình bằng cách chỉ định các bài kiểm tra chấp nhận.

                                            Đôi khi có những phản đối đối với việc sử dụng ngôn ngữ của mô hình để thu thập yêu cầu. Rốt cuộc, yêu cầu không nên độc lập với thiết kế mà đáp ứng chúng sao? Điều này bỏ qua thực tế rằng tất cả ngôn ngữ đều dựa trên một mô hình nào đó. Ý nghĩa của các từ là những thứ không ổn định. Mô hình miền thường sẽ dựa trên thuật ngữ của các chuyên gia trong lĩnh vực nhưng sẽ được "làm sạch", để có được những định nghĩa sắc nét, hẹp hơn. Tất nhiên, các chuyên gia trong lĩnh vực nên phản đối nếu các định nghĩa này lệch khỏi những ý nghĩa được chấp nhận trong lĩnh vực. Trong một quy trình Agile, yêu cầu phát triển theo thời gian của dự án vì hiếm khi có đủ kiến thức từ trước để xác định một ứng dụng một cách đầy đủ. Một phần của sự phát triển này nên là việc định hình lại các yêu cầu trong NGÔN NGỮ TINH TÚY đã được tinh chỉnh.

                                            Sự đa dạng ngôn ngữ thường là cần thiết, nhưng sự phân chia ngôn ngữ không bao giờ nên nằm giữa các chuyên gia trong miền và các nhà phát triển. (Chương 12, "Duy trì Tính Toàn Vẹn của Mô Hình," đề cập đến sự đồng tồn tại của các mô hình trong cùng một dự án.)

                                            Tất nhiên, các nhà phát triển thường sử dụng thuật ngữ kỹ thuật mà một chuyên gia trong lĩnh vực có thể không hiểu. Các nhà phát triển có một hệ thống từ ngữ phong phú mà họ cần để thảo luận về các khía cạnh kỹ thuật của một hệ thống. Hầu như chắc chắn, người dùng cũng sẽ có những thuật ngữ chuyên ngành vượt xa phạm vi hẹp của ứng dụng và sự hiểu biết của các nhà phát triển. Nhưng đây chỉ là những phần mở rộng của ngôn ngữ. Những phương ngữ này không nên chứa các từ vựng thay thế cho cùng một lĩnh vực mà phản ánh các mô hình khác nhau.

                                            Figure 2.3. UBIQUITOUS LANGUAGE is cultivated in the intersection of jargons.

                                            graphics/02fig03.gif

                                            Với một NGÔN NGỮ PHỔ BIẾN, các cuộc trò chuyện giữa các nhà phát triển, các cuộc thảo luận giữa các chuyên gia trong lĩnh vực và các biểu thức trong chính mã đều dựa trên cùng một ngôn ngữ, được lấy từ một mô hình miền chung.


                                              Documents and Diagrams

                                              Mỗi khi tôi tham gia một cuộc họp thảo luận về thiết kế phần mềm, tôi gần như không thể hoạt động nếu không vẽ trên bảng trắng hoặc giấy vẽ. Phần lớn những gì tôi vẽ là các sơ đồ UML, chủ yếu là sơ đồ lớp hoặc tương tác đối tượng.

                                              Một số người có thiên hướng trực quan tự nhiên, và sơ đồ giúp họ nắm bắt một số loại thông tin. Các sơ đồ UML khá hiệu quả trong việc truyền đạt mối quan hệ giữa các đối tượng, và chúng cũng tương đối ổn trong việc thể hiện sự tương tác. Nhưng chúng không truyền tải được các định nghĩa khái niệm của những đối tượng đó. Trong một cuộc họp, tôi sẽ làm rõ những ý nghĩa đó bằng lời nói trong khi tôi phác thảo sơ đồ, hoặc chúng sẽ xuất hiện trong một cuộc đối thoại với các участник khác.

                                              Các biểu đồ UML đơn giản và không chính thức có thể là điểm tựa cho một cuộc thảo luận. Hãy phác thảo một biểu đồ với từ ba đến năm đối tượng trung tâm liên quan đến vấn đề đang được bàn luận, và mọi người có thể giữ sự tập trung. Mọi người sẽ cùng có một cái nhìn chung về các mối quan hệ giữa các đối tượng và, quan trọng hơn, là tên gọi của các đối tượng. Cuộc thảo luận bằng lời nói có thể hiệu quả hơn với sự trợ giúp này. Một biểu đồ có thể được thay đổi khi mọi người thử nghiệm với những ý tưởng khác nhau, và phác thảo đó sẽ mang tính linh hoạt như những lời nói, trở thành một phần thật sự của cuộc thảo luận. Rốt cuộc, UML là viết tắt của Ngôn ngữ Mô hình Hợp nhất.

                                              Rắc rối xảy ra khi mọi người cảm thấy bị buộc phải truyền đạt toàn bộ mô hình hoặc thiết kế qua UML. Nhiều sơ đồ mô hình đối tượng quá đầy đủ và, đồng thời, bỏ qua quá nhiều thứ. Chúng quá đầy đủ vì mọi người cảm thấy họ phải đưa tất cả các đối tượng mà họ sẽ lập trình vào một công cụ mô hình. Với tất cả chi tiết đó, không ai có thể nhìn thấy rừng vì những cây.

                                              Tuy nhiên, bất chấp tất cả những chi tiết đó, các thuộc tính và mối quan hệ chỉ chiếm một nửa câu chuyện của một mô hình đối tượng. Hành vi của những đối tượng đó và các ràng buộc đối với chúng thì không dễ để minh họa. Các sơ đồ tương tác đối tượng có thể minh họa một số điểm nóng khó khăn trong thiết kế, nhưng phần lớn các tương tác không thể được thể hiện theo cách đó. Thật sự là quá nhiều công việc, cả để tạo ra các sơ đồ lẫn để đọc chúng. Và một sơ đồ tương tác vẫn chỉ có thể ngụ ý mục đích phía sau mô hình. Để bao gồm các ràng buộc và tuyên bố, UML phải dựa vào văn bản, được đặt trong các dấu ngoặc nhỏ, chèn vào sơ đồ.

                                              Nghĩa vụ hành vi của một đối tượng có thể được gợi ý thông qua tên các thao tác, và chúng có thể được thể hiện một cách ngầm định qua các biểu đồ tương tác (hoặc chuỗi), nhưng không thể được nêu rõ. Vì vậy, nhiệm vụ này thuộc về văn bản bổ sung hoặc cuộc trò chuyện. Nói cách khác, một biểu đồ UML không thể truyền đạt hai khía cạnh quan trọng nhất của một mô hình: ý nghĩa của các khái niệm mà nó đại diện, và những gì các đối tượng có nhiệm vụ thực hiện. Tuy nhiên, điều này không cần phải làm phiền chúng ta, vì việc sử dụng cẩn thận tiếng Anh (hoặc tiếng Tây Ban Nha, hoặc ngôn ngữ khác) có thể thực hiện vai trò này một cách khá tốt.

                                              UML cũng không phải là một ngôn ngữ lập trình thỏa đáng. Mọi nỗ lực mà tôi đã thấy để sử dụng khả năng sinh mã của các công cụ mô hình hóa đều mang lại kết quả ngược lại. Nếu bạn bị ràng buộc bởi khả năng của UML, bạn sẽ thường phải bỏ qua phần quan trọng nhất của mô hình vì đó là một quy tắc không phù hợp với sơ đồ các hộp và đường. Và, tất nhiên, một trình tạo mã không thể sử dụng những chú thích bằng văn bản đó. Nếu bạn sử dụng một công nghệ cho phép viết các chương trình thực thi trong một ngôn ngữ lập trình như sơ đồ UML, thì sơ đồ UML chỉ còn là một cách khác để xem chương trình đó, và ý nghĩa thực sự của "mô hình" sẽ bị mất. Nếu bạn sử dụng UML làm ngôn ngữ triển khai của mình, bạn vẫn sẽ cần đến những phương tiện khác để truyền đạt mô hình gọn gàng.

                                              Sơ đồ là một phương tiện giao tiếp và giải thích, và chúng tạo điều kiện cho việc brainstorming. Chúng phục vụ tốt nhất cho những mục đích này nếu chúng là tối giản. Các sơ đồ toàn diện của toàn bộ mô hình đối tượng thường không truyền đạt hay giải thích được; chúng làm cho người đọc choáng ngợp với chi tiết và thiếu ý nghĩa. Điều này dẫn chúng ta ra khỏi sơ đồ mô hình đối tượng toàn diện, hoặc thậm chí kho lưu trữ cơ sở dữ liệu toàn diện của UML. Nó dẫn chúng ta đến các sơ đồ đơn giản hóa của những phần quan trọng về mặt khái niệm của mô hình đối tượng mà là thiết yếu để hiểu thiết kế. Các sơ đồ trong cuốn sách này điển hình cho những gì tôi sử dụng trong các dự án. Chúng đơn giản hóa, chúng giải thích, và thậm chí chúng còn kết hợp một chút ký hiệu không chuẩn khi điều đó làm rõ quan điểm của chúng. Chúng cho thấy các hạn chế thiết kế, nhưng chúng không phải là các thông số thiết kế ở mọi chi tiết. Chúng đại diện cho bộ khung của những ý tưởng.

                                              Chi tiết quan trọng về thiết kế được ghi lại trong mã. Một triển khai được viết tốt nên minh bạch, tiết lộ mô hình cơ bản của nó. (Việc đảm bảo điều này xảy ra là chủ đề của chương tiếp theo và nhiều phần còn lại của cuốn sách này.) Các sơ đồ và tài liệu bổ sung có thể hướng sự chú ý của mọi người đến những điểm trung tâm. Cuộc thảo luận bằng ngôn ngữ tự nhiên có thể làm sáng tỏ những sắc thái của ý nghĩa. Đây là lý do tại sao tôi thích lật ngược mọi thứ so với cách mà một sơ đồ UML điển hình xử lý chúng. Thay vì một sơ đồ có chú thích bằng văn bản, tôi viết một tài liệu văn bản được minh họa bằng các sơ đồ chọn lọc và đơn giản hóa.

                                              Luôn nhớ rằng mô hình không phải là sơ đồ. Mục đích của sơ đồ là giúp truyền đạt và giải thích mô hình. Mã có thể đóng vai trò như một kho lưu trữ các chi tiết của thiết kế. Java được viết tốt có thể diễn đạt tốt như UML theo cách của nó. Những sơ đồ được chọn lọc và xây dựng cẩn thận có thể giúp tập trung sự chú ý và hỗ trợ việc điều hướng nếu chúng không bị che khuất bởi một sự ép buộc phải diễn tả mô hình hoặc thiết kế một cách đầy đủ.

                                              Written Design Documents

                                              Giao tiếp bằng lời nói bổ sung cho sự nghiêm ngặt và chi tiết của mã nguồn bằng ý nghĩa. Nhưng mặc dù việc nói chuyện rất quan trọng để kết nối mọi người với mô hình, một nhóm bất kỳ kích thước nào cũng có thể cần sự ổn định và khả năng chia sẻ của một số tài liệu viết. Tuy nhiên, việc tạo ra các tài liệu viết thực sự giúp nhóm sản xuất phần mềm tốt là một thách thức.

                                              Khi một tài liệu trở nên bền vững, nó thường mất đi sự liên kết với dòng chảy của dự án. Nó bị bỏ lại phía sau bởi sự phát triển của mã nguồn hoặc sự phát triển của ngôn ngữ của dự án.

                                              Nhiều phương pháp có thể hiệu quả. Một vài tài liệu cụ thể sẽ được đề xuất muộn hơn, trong Phần IV của cuốn sách này, nhằm đáp ứng những nhu cầu cụ thể, nhưng tôi không cố gắng quy định một bộ tài liệu mà một dự án nên sử dụng. Thay vào đó, tôi sẽ cung cấp hai hướng dẫn chung để đánh giá một tài liệu.

                                              Documents Should Complement Code and Speech

                                              Mỗi quy trình Agile có triết lý riêng về tài liệu. Extreme Programming ủng hộ việc không sử dụng tài liệu thiết kế phụ nào và để mã nguồn tự nói lên điều đó. Mã nguồn đang chạy không nói dối, như bất kỳ tài liệu nào khác có thể. Hành vi của mã nguồn đang chạy là không mơ hồ.

                                              Lập trình Cực đoan tập trung hoàn toàn vào các yếu tố hoạt động của một chương trình và các bài kiểm tra có thể thực thi. Ngay cả những chú thích thêm vào mã cũng không ảnh hưởng đến hành vi của chương trình, vì vậy chúng luôn bị lạc nhịp với mã hoạt động và mô hình điều khiển của nó. Tài liệu và sơ đồ bên ngoài không ảnh hưởng đến hành vi của chương trình, vì vậy chúng cũng bị lạc nhịp. Mặt khác, giao tiếp bằng lời và sơ đồ tạm thời trên bảng trắng không lưu lại để tạo ra sự nhầm lẫn. Sự phụ thuộc vào mã như là phương tiện giao tiếp khiến các nhà phát triển duy trì mã sạch và minh bạch.

                                              Nhưng mã như một tài liệu thiết kế cũng có giới hạn của nó. Nó có thể làm cho người đọc choáng ngợp với chi tiết. Mặc dù hành vi của nó là không mơ hồ, điều đó không có nghĩa là nó rõ ràng. Và ý nghĩa phía sau một hành vi có thể khó truyền đạt. Nói cách khác, việc tài liệu hóa hoàn toàn thông qua mã có một số vấn đề cơ bản giống như việc sử dụng các sơ đồ UML toàn diện. Tất nhiên, việc giao tiếp nói chuyện mạnh mẽ trong nhóm cung cấp ngữ cảnh và hướng dẫn xung quanh mã, nhưng nó là tạm thời và địa phương. Và các lập trình viên không phải là những người duy nhất cần hiểu mô hình.

                                              Một tài liệu không nên cố gắng làm những gì mã đã thực hiện tốt. Mã đã cung cấp chi tiết. Nó là một thông số kỹ thuật chính xác về hành vi của chương trình.

                                              Các tài liệu khác cần làm sáng tỏ ý nghĩa, cung cấp cái nhìn sâu sắc vào các cấu trúc quy mô lớn, và tập trung sự chú ý vào các yếu tố cốt lõi. Tài liệu có thể làm rõ ý định thiết kế khi ngôn ngữ lập trình không hỗ trợ việc triển khai một khái niệm theo cách đơn giản. Tài liệu viết nên bổ sung cho mã nguồn và các cuộc trao đổi.

                                              Documents Should Work for a Living and Stay Current

                                              Khi tôi tài liệu hóa một mô hình bằng văn bản, tôi vẽ sơ đồ cho những tập hợp nhỏ, được chọn lọc cẩn thận của mô hình và bao quanh chúng bằng văn bản. Tôi định nghĩa các lớp và trách nhiệm của chúng bằng lời và đặt chúng trong một bối cảnh có ý nghĩa mà chỉ ngôn ngữ tự nhiên mới có thể làm được. Nhưng sơ đồ cho thấy một số lựa chọn đã được thực hiện trong việc chính thức hóa và giảm thiểu các khái niệm thành một mô hình đối tượng. Những sơ đồ này có thể khá thoải mái - thậm chí là vẽ tay. Ngoài việc tiết kiệm công sức, sơ đồ vẽ tay có lợi thế là cảm giác thoải mái và tạm thời. Đây là những điều tốt để truyền đạt vì chúng thường đúng với các ý tưởng mô hình của chúng tôi.

                                              Giá trị lớn nhất của một tài liệu thiết kế là giải thích các khái niệm của mô hình, giúp điều hướng chi tiết của mã, và có thể cung cấp một số hiểu biết về phong cách sử dụng mà mô hình hướng tới. Tùy thuộc vào triết lý của đội ngũ, toàn bộ tài liệu thiết kế có thể đơn giản chỉ là một tập hợp các bản phác thảo được treo trên tường, hoặc có thể là một tài liệu đồ sộ.

                                              Một tài liệu phải được tham gia vào các hoạt động dự án. Cách dễ nhất để đánh giá điều này là quan sát sự tương tác của tài liệu với NGÔN NGỮ PHỔ BIẾN. Tài liệu có được viết bằng ngôn ngữ mà mọi người đang sử dụng trong dự án (hiện tại) không? Nó có được viết bằng ngôn ngữ được nhúng trong mã không?

                                              Lắng nghe NGÔN NGỮ PHỔ BIẾN và cách nó đang thay đổi. Nếu các thuật ngữ được giải thích trong một tài liệu thiết kế không bắt đầu xuất hiện trong các cuộc trò chuyện và mã nguồn, tài liệu đó không hoàn thành mục đích của nó. Có thể tài liệu quá dài hoặc phức tạp. Có thể nó không tập trung vào một chủ đề đủ quan trọng. Mọi người có thể không đọc nó hoặc không thấy nó thuyết phục. Nếu nó không có tác động gì lên NGÔN NGỮ PHỔ BIẾN, có điều gì đó không ổn.

                                              Ngược lại, bạn có thể nghe thấy NGÔN NGỮ PHỔ BIẾN thay đổi một cách tự nhiên trong khi một tài liệu bị bỏ lại. Rõ ràng, tài liệu đó dường như không còn quan trọng đối với mọi người hoặc không đủ quan trọng để cập nhật. Nó có thể được lưu trữ an toàn như một phần lịch sử, nhưng vẫn được giữ hoạt động có thể tạo ra sự nhầm lẫn và gây hại cho dự án. Và nếu một tài liệu không đóng vai trò quan trọng, việc giữ cho nó luôn được cập nhật chỉ bằng ý chí và kỷ luật sẽ tốn công sức một cách không cần thiết.

                                              NGÔN NGỮ PHỔ BIẾN cho phép các tài liệu khác, chẳng hạn như tài liệu yêu cầu, trở nên ngắn gọn hơn và ít mơ hồ hơn. Khi mô hình miền phản ánh kiến thức quan trọng nhất của doanh nghiệp, các yêu cầu ứng dụng trở thành các kịch bản trong mô hình đó, và NGÔN NGỮ PHỔ BIẾN có thể được sử dụng để mô tả một kịch bản như vậy bằng những thuật ngữ kết nối trực tiếp với THIẾT KẾ DỰA TRÊN MÔ HÌNH (xem Chương 3). Kết quả là, các thông số kỹ thuật có thể được viết một cách đơn giản hơn, vì chúng không cần phải truyền đạt kiến thức kinh doanh nằm sau mô hình.

                                              Bằng cách giữ cho tài liệu tối thiểu và tập trung vào việc bổ sung cho mã và cuộc trò chuyện, tài liệu có thể được kết nối với dự án. Hãy để NGÔN NGỮ PHỔ BIẾN và sự phát triển của nó hướng dẫn bạn trong việc chọn lựa các tài liệu sống động và được dệt vào hoạt động của dự án.

                                              Executable Bedrock

                                              Bây giờ, hãy xem xét sự lựa chọn của cộng đồng XP và một số người khác, đó là dựa gần như hoàn toàn vào mã thực thi và các bài kiểm tra của nó. Phần lớn cuốn sách này thảo luận về cách làm cho mã truyền đạt ý nghĩa thông qua một THIẾT KẾ DỰA TRÊN MÔ HÌNH (xem Chương 3). Mã được viết tốt có thể rất truyền cảm, nhưng thông điệp mà nó truyền đạt không được đảm bảo là chính xác. Ồ, thực tế về hành vi do một đoạn mã gây ra là điều không thể tránh khỏi. Nhưng tên phương thức có thể mơ hồ, gây hiểu lầm, hoặc đã lỗi thời so với các thành phần bên trong của phương thức. Các tuyên bố trong một bài kiểm tra rất nghiêm ngặt, nhưng câu chuyện được kể bởi các tên biến và cách tổ chức mã thì không. Phong cách lập trình tốt giữ cho sự kết nối này càng trực tiếp càng tốt, nhưng đó vẫn là một bài tập về tính kỷ luật bản thân. Cần có sự tỉ mỉ để viết mã không chỉ thực hiện đúng mà còn truyền đạt đúng.

                                              Việc loại bỏ những bất đồng này là một điểm bán hàng chính của các phương pháp như thiết kế khai báo (được thảo luận trong Chương 10), trong đó một tuyên bố về mục đích của một thành phần chương trình xác định hành vi thực tế của nó trong chương trình. Sự thúc đẩy để tạo ra chương trình từ UML phần nào được thúc đẩy bởi điều này, mặc dù cho đến nay nó thường không được thực hiện tốt.

                                              Tuy nhiên, mặc dù ngay cả mã cũng có thể gây hiểu lầm, nhưng nó gần gũi hơn với thực tế so với các tài liệu khác. Việc đồng bộ hóa hành vi, ý định và thông điệp của mã bằng cách sử dụng công nghệ tiêu chuẩn hiện tại đòi hỏi kỷ luật và một cách tư duy nhất định về thiết kế (sẽ được thảo luận chi tiết trong Phần III). Để giao tiếp hiệu quả, mã phải dựa trên cùng một ngôn ngữ được sử dụng để viết các yêu cầu - cùng một ngôn ngữ mà các nhà phát triển sử dụng để giao tiếp với nhau và với các chuyên gia trong lĩnh vực.


                                                Explanatory Models

                                                Nội dung chính của cuốn sách này là một mô hình nên làm nền tảng cho việc triển khai, thiết kế và giao tiếp trong nhóm. Việc có những mô hình riêng biệt cho các mục đích khác nhau có thể gây rủi ro.

                                                Các mô hình cũng có thể có giá trị như là công cụ giáo dục để dạy về lĩnh vực. Mô hình mà dẫn dắt thiết kế là một cái nhìn về lĩnh vực, nhưng có thể sẽ hữu ích cho việc học nếu có những cái nhìn khác, chỉ được sử dụng như là công cụ giáo dục, để truyền đạt kiến thức chung về lĩnh vực. Để mục đích này, mọi người có thể sử dụng hình ảnh hoặc từ ngữ để truyền đạt những loại mô hình khác không liên quan đến thiết kế phần mềm.

                                                Một lý do cụ thể mà các mô hình khác cần thiết là phạm vi. Mô hình kỹ thuật điều khiển quy trình phát triển phần mềm phải được cắt giảm một cách nghiêm ngặt đến mức tối thiểu cần thiết để thực hiện các chức năng của nó. Mô hình giải thích có thể bao gồm các khía cạnh của miền cung cấp ngữ cảnh làm rõ mô hình có phạm vi hẹp hơn.

                                                Các mô hình giải thích cung cấp sự tự do để tạo ra những phong cách giao tiếp mang tính cá nhân hóa hơn, phù hợp với một chủ đề cụ thể. Những phép ẩn dụ hình ảnh được sử dụng bởi các chuyên gia trong lĩnh vực thường mang lại những giải thích rõ ràng hơn, giáo dục các nhà phát triển và hòa hợp các chuyên gia. Các mô hình giải thích cũng trình bày lĩnh vực theo cách mà đơn giản là khác biệt, và những giải thích đa dạng, phong phú giúp mọi người học hỏi.

                                                Không cần thiết phải có các mô hình giải thích là các mô hình đối tượng, và thường là tốt nhất nếu chúng không phải vậy. Thật sự hữu ích khi tránh sử dụng UML trong những mô hình này, để tránh bất kỳ ấn tượng sai lệch nào về sự tương ứng với thiết kế phần mềm. Mặc dù mô hình giải thích và mô hình điều khiển thiết kế thường tương ứng với nhau, nhưng sự tương đồng sẽ hiếm khi chính xác hoàn toàn. Để tránh nhầm lẫn, mọi người cần phải nhận thức rõ về sự phân biệt này.

                                                Example
                                                Shipping Operations and Routes

                                                Xem xét một ứng dụng theo dõi hàng hóa cho một công ty vận tải. Mô hình bao gồm một cái nhìn chi tiết về cách các hoạt động cảng và hành trình tàu được tập hợp thành một kế hoạch hoạt động cho hàng hóa (một "lộ trình"). Nhưng đối với những người không quen thuộc, một sơ đồ lớp có thể không rõ ràng lắm.

                                                Figure 2.4. A class diagram for a shipping route

                                                graphics/02fig04.gif

                                                Trong trường hợp như vậy, một mô hình giải thích có thể giúp các thành viên trong nhóm hiểu ý nghĩa thực sự của sơ đồ lớp. Dưới đây là một cách khác để nhìn nhận cùng một khái niệm:

                                                Mỗi dòng trong Hình 2.5 đại diện cho một hoạt động cảng (xếp dỡ hàng hóa), hoặc hàng hóa đang lưu kho trên mặt đất, hoặc hàng hóa đang ở trên tàu đang di chuyển. Điều này không hoàn toàn tương ứng với sơ đồ lớp, nhưng nó củng cố những điểm quan trọng từ miền.

                                                Figure 2.5. An explanatory model for a shipping route

                                                graphics/02fig05.gif

                                                Loại sơ đồ này, cùng với các giải thích bằng ngôn ngữ tự nhiên về mô hình mà nó đại diện, có thể giúp các nhà phát triển và chuyên gia trong lĩnh vực hiểu rõ hơn về các sơ đồ mô hình phần mềm nghiêm ngặt hơn. Cùng nhau, chúng dễ hiểu hơn so với từng cách nhìn riêng lẻ.


                                                  Chapter Three. Binding Model and Implementation

                                                  Điều đầu tiên tôi nhìn thấy khi bước qua cửa là một sơ đồ lớp hoàn chỉnh được in trên những tờ giấy lớn che phủ một bức tường lớn. Đó là ngày đầu tiên của tôi trong một dự án mà những người thông minh đã dành nhiều tháng để nghiên cứu và phát triển một mô hình chi tiết về miền. Mỗi đối tượng trong mô hình có những mối liên hệ phức tạp với ba hoặc bốn đối tượng khác, và mạng lưới các mối liên hệ này có rất ít biên giới tự nhiên. Trên phương diện này, các nhà phân tích đã trung thực với bản chất của miền.

                                                  Mặc dù sơ đồ kích thước bức tường rất choáng ngợp, nhưng mô hình đã thu hút được một số kiến thức. Sau một thời gian học vừa phải, tôi đã học được khá nhiều (mặc dù việc học đó khó có thể được điều hướng - giống như lướt web ngẫu nhiên). Tôi cảm thấy phiền lòng hơn khi thấy rằng việc học của tôi không mang lại cái nhìn nào về mã nguồn và thiết kế của ứng dụng.

                                                  Khi các nhà phát triển bắt đầu triển khai ứng dụng, họ nhanh chóng phát hiện ra rằng sự phức tạp của các mối quan hệ, mặc dù có thể điều hướng bởi một nhà phân tích con người, lại không chuyển thành các đơn vị có thể lưu trữ, truy xuất mà có thể được thao tác với tính toàn vẹn giao dịch. Hãy nhớ rằng, dự án này đang sử dụng một cơ sở dữ liệu đối tượng, vì vậy các nhà phát triển thậm chí không phải đối mặt với những thách thức trong việc ánh xạ các đối tượng vào các bảng quan hệ. Ở cấp độ cơ bản, mô hình không cung cấp một hướng dẫn cho việc triển khai.

                                                  Vì mô hình được coi là "đúng," kết quả của sự hợp tác rộng rãi giữa các nhà phân tích kỹ thuật và các chuyên gia kinh doanh, các nhà phát triển đã đi đến kết luận rằng các đối tượng dựa trên khái niệm không thể là nền tảng thiết kế của họ. Do đó, họ tiến hành phát triển một thiết kế theo kiểu ad hoc. Thiết kế của họ có sử dụng một vài tên lớp và thuộc tính giống nhau để lưu trữ dữ liệu, nhưng nó không dựa trên mô hình hiện có, hay bất kỳ mô hình nào khác.

                                                  Dự án có một mô hình miền, nhưng một mô hình chỉ trên giấy tờ thì có ích gì nếu nó không trực tiếp hỗ trợ việc phát triển phần mềm hoạt động?

                                                  Vài năm sau, tôi thấy kết quả cuối cùng tương tự xuất phát từ một quy trình hoàn toàn khác. Dự án này nhằm thay thế một ứng dụng C++ hiện có bằng một thiết kế mới được triển khai bằng Java. Ứng dụng cũ đã được ghép lại mà không có sự xem xét nào về mô hình đối tượng. Thiết kế của ứng dụng cũ, nếu có, đã tích lũy dần qua từng khả năng được thêm vào mã hiện có, mà không có sự tổng quát hoặc trừu tượng nào đáng chú ý.

                                                  Điều kỳ lạ là sản phẩm cuối cùng của hai quy trình này rất giống nhau! Cả hai đều có chức năng, nhưng đều phức tạp, rất khó hiểu và cuối cùng không thể duy trì được. Mặc dù các cách triển khai có, ở một số chỗ, sự trực tiếp nhưng bạn không thể có nhiều hiểu biết về mục đích của hệ thống chỉ bằng cách đọc mã. Cả hai quy trình đều không tận dụng bất kỳ lợi thế nào của mô hình đối tượng có sẵn trong môi trường phát triển của họ, ngoại trừ việc sử dụng như các cấu trúc dữ liệu phức tạp.

                                                  Các mô hình có nhiều loại và phục vụ nhiều vai trò, ngay cả những mô hình bị hạn chế trong bối cảnh của một dự án phát triển phần mềm. Thiết kế hướng miền yêu cầu một mô hình không chỉ hỗ trợ phân tích ban đầu mà còn là nền tảng chính của thiết kế. Cách tiếp cận này có một số tác động quan trọng đối với mã nguồn. Điều ít rõ ràng hơn là thiết kế hướng miền yêu cầu một cách tiếp cận khác đối với việc lập mô hình. . . .


                                                    Model-Driven Design

                                                    Kính thiên văn, được sử dụng để tính toán vị trí của các vì sao, là một ứng dụng cơ khí của mô hình bầu trời.

                                                    graphics/03inf01.gif

                                                    Gắn liên chặt chẽ mã với một mô hình cơ sở sẽ giúp mã có ý nghĩa và làm cho mô hình trở nên phù hợp.


                                                    A Medieval Sky Computer

                                                    Các nhà thiên văn học Hy Lạp cổ đại đã phát minh ra cái dụng cụ thiên văn gọi là astrolabe, được hoàn thiện bởi các nhà khoa học Hồi giáo trung cổ. Một mạng lưới xoay (gọi là rete) đại diện cho vị trí của các ngôi sao cố định trên bầu trời. Các bản kỷ niệm có thể thay thế, được khắc với hệ thống tọa độ hình cầu địa phương, đại diện cho các quan điểm từ các vĩ độ khác nhau. Việc xoay rete chống lại bản kỷ niệm cho phép tính toán các vị trí thiên văn cho bất kỳ thời điểm và ngày nào trong năm. Ngược lại, với một vị trí sao hoặc mặt trời đã cho, thời gian có thể được tính toán. Astrolabe là một ứng dụng cơ học của một mô hình hướng đối tượng của bầu trời.

                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                    Các dự án không có mô hình miền nào cả, mà chỉ đơn giản viết mã để thực hiện từng chức năng một, sẽ chỉ thu được một số lợi ích từ việc phân tích kiến thức và giao tiếp được đề cập trong hai chương trước. Một miền phức tạp sẽ làm họ choáng ngợp.

                                                    Mặt khác, nhiều dự án phức tạp cố gắng xây dựng một loại mô hình miền nào đó, nhưng họ không duy trì mối liên hệ chặt chẽ giữa mô hình và mã nguồn. Mô hình mà họ phát triển, có thể hữu ích như một công cụ khám phá ban đầu, trở nên ngày càng không liên quan và thậm chí gây hiểu lầm. Tất cả sự chăm sóc dành cho mô hình không mang lại nhiều sự yên tâm rằng thiết kế là chính xác, bởi vì hai điều đó là khác nhau.

                                                    Kết nối này có thể bị phá vỡ theo nhiều cách, nhưng sự tách rời thường là một lựa chọn có ý thức. Nhiều phương pháp thiết kế khuyến khích một mô hình phân tích, hoàn toàn khác biệt so với thiết kế và thường được phát triển bởi những người khác nhau. Nó được gọi là mô hình phân tích vì là sản phẩm của việc phân tích miền kinh doanh để tổ chức các khái niệm của nó mà không xem xét vai trò mà nó sẽ đóng trong một hệ thống phần mềm. Mô hình phân tích được coi là một công cụ chỉ để hiểu; việc trộn lẫn các vấn đề thực hiện được cho là làm rối thêm tình hình. Sau đó, một thiết kế được tạo ra có thể chỉ có sự tương ứng lỏng lẻo với mô hình phân tích. Mô hình phân tích không được tạo ra với các vấn đề thiết kế trong tâm trí và do đó có khả năng trở nên khá không thực tế cho những nhu cầu đó.

                                                    Một số kiến thức bị nghiền ngẫm xảy ra trong quá trình phân tích như vậy, nhưng hầu hết chúng bị mất khi bắt đầu lập trình, khi các nhà phát triển buộc phải đưa ra các trừu tượng mới cho thiết kế. Lúc này, không có gì đảm bảo rằng những hiểu biết mà các nhà phân tích thu được và được nhúng trong mô hình sẽ được giữ lại hoặc phát hiện lại. Vào thời điểm này, việc duy trì bất kỳ ánh xạ nào giữa thiết kế và mô hình kết nối lỏng lẻo không còn hiệu quả về chi phí.

                                                    Mô hình phân tích thuần túy thậm chí còn không đạt được mục tiêu chính của nó là hiểu biết về miền, vì những phát hiện quan trọng luôn xuất hiện trong suốt quá trình thiết kế/thực hiện. Những vấn đề rất cụ thể và không mong đợi luôn phát sinh. Một mô hình trước đó sẽ đi sâu vào một số chủ đề không liên quan, trong khi bỏ qua một số chủ đề quan trọng. Các chủ đề khác sẽ được trình bày theo những cách không hữu ích cho ứng dụng. Kết quả là các mô hình phân tích thuần túy bị từ bỏ ngay sau khi bắt đầu mã hóa, và đa số các vấn đề đã thảo luận phải được làm lại. Nhưng lần thứ hai, nếu các nhà phát triển coi phân tích là một quy trình riêng biệt, việc lập mô hình sẽ diễn ra theo cách kém kỷ luật hơn. Nếu các nhà quản lý coi phân tích là một quy trình riêng biệt, đội ngũ phát triển có thể không được tiếp cận đầy đủ với các chuyên gia trong miền.

                                                    Dù nguyên nhân là gì, phần mềm thiếu một khái niệm ở nền tảng thiết kế của nó, thì tốt nhất chỉ là một cơ chế thực hiện những điều hữu ích mà không giải thích được hành động của nó.

                                                    Nếu thiết kế, hoặc một phần trung tâm của nó, không phù hợp với mô hình miền, thì mô hình đó có giá trị rất ít, và độ chính xác của phần mềm bị nghi ngờ. Đồng thời, những ánh xạ phức tạp giữa các mô hình và chức năng thiết kế khó hiểu và trong thực tế, gần như không thể duy trì khi thiết kế thay đổi. Một khoảng cách chết chóc mở ra giữa phân tích và thiết kế, khiến cho những hiểu biết thu được trong mỗi hoạt động đó không được chuyển giao cho hoạt động kia.

                                                    Phân tích phải nắm bắt được các khái niệm cơ bản từ lĩnh vực một cách dễ hiểu và biểu cảm. Thiết kế phải xác định một tập hợp các thành phần có thể được xây dựng bằng các công cụ lập trình đang sử dụng trong dự án, thực hiện hiệu quả trong môi trường triển khai mục tiêu và giải quyết đúng các vấn đề đặt ra cho ứng dụng.

                                                    MÔ HÌNH LÁI THIẾT KẾ loại bỏ sự phân chia giữa mô hình phân tích và thiết kế để tìm kiếm một mô hình duy nhất phục vụ cả hai mục đích. Bỏ qua các vấn đề kỹ thuật thuần túy, mỗi đối tượng trong thiết kế đều đóng vai trò khái niệm được mô tả trong mô hình. Điều này yêu cầu chúng ta phải đặt ra yêu cầu cao hơn đối với mô hình đã chọn, vì nó phải đáp ứng hai mục tiêu hoàn toàn khác nhau.

                                                    Luôn có nhiều cách để trừu tượng hóa một miền và luôn có nhiều thiết kế có thể giải quyết một vấn đề ứng dụng. Đó là điều khiến việc ràng buộc mô hình và thiết kế trở nên thực tiễn. Sự ràng buộc này không được đến từ việc phân tích yếu đi, bị tổn hại nghiêm trọng bởi những cân nhắc kỹ thuật. Chúng ta cũng không thể chấp nhận những thiết kế vụng về, phản ánh ý tưởng miền nhưng bỏ qua các nguyên tắc thiết kế phần mềm. Cách tiếp cận này đòi hỏi một mô hình hoạt động tốt như cả phân tích và thiết kế. Khi một mô hình dường như không thực tiễn cho việc triển khai, chúng ta phải tìm kiếm một mô hình mới. Khi một mô hình không thể hiện trung thực các khái niệm chính của miền, chúng ta phải tìm kiếm một mô hình mới. Quá trình mô hình hóa và thiết kế trở thành một vòng lặp lặp đi lặp lại duy nhất.

                                                    Sự cần thiết phải liên kết mô hình miền chặt chẽ với thiết kế thêm một tiêu chí nữa để chọn ra những mô hình hữu ích hơn trong vô số các mô hình có thể. Nó đòi hỏi suy nghĩ sâu sắc và thường cần nhiều lần lặp lại cũng như rất nhiều việc tái cấu trúc, nhưng điều đó khiến mô hình trở nên liên quan.

                                                    Vì vậy:

                                                    Thiết kế một phần của hệ thống phần mềm để phản ánh mô hình miền một cách rất trực quan, để việc ánh xạ trở nên rõ ràng. Xem xét lại mô hình và chỉnh sửa nó để có thể được triển khai một cách tự nhiên hơn trong phần mềm, ngay cả khi bạn cố gắng làm cho nó phản ánh cái nhìn sâu sắc hơn về miền. Yêu cầu một mô hình duy nhất phục vụ tốt cả hai mục đích, bên cạnh việc hỗ trợ một NGÔN NGỮ PHỔ BIẾN vững chắc.

                                                    Rút ra từ mô hình các thuật ngữ sử dụng trong thiết kế và phân công trách nhiệm cơ bản. Mã trở thành một biểu hiện của mô hình, vì vậy việc thay đổi mã có thể là một sự thay đổi của mô hình. Tác động của nó phải lan tỏa qua các hoạt động khác của dự án tương ứng.

                                                    Để buộc việc triển khai gắn chặt với một mô hình thường yêu cầu các công cụ và ngôn ngữ phát triển phần mềm hỗ trợ một cách tiếp cận mô hình hóa, chẳng hạn như lập trình hướng đối tượng.

                                                    Đôi khi sẽ có các mô hình khác nhau cho các hệ thống con khác nhau (xem Chương 14), nhưng chỉ có một mô hình nên áp dụng cho một phần cụ thể của hệ thống, trong tất cả các khía cạnh của nỗ lực phát triển, từ mã đến phân tích yêu cầu.

                                                    Mô hình đơn lẻ giảm cơ hội xảy ra lỗi, vì thiết kế giờ đây là sự phát triển trực tiếp từ mô hình đã được xem xét kỹ lưỡng. Thiết kế, và ngay cả mã nguồn, đều có tính truyền đạt của một mô hình.

                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                    Phát triển một mô hình duy nhất mà nắm bắt vấn đề và cung cấp một thiết kế thực tiễn dễ nói hơn làm. Bạn không thể chỉ lấy bất kỳ mô hình nào và biến nó thành một thiết kế có thể làm việc. Mô hình phải được chế tác cẩn thận để đảm bảo cho một việc thực hiện thực tiễn. Các kỹ thuật thiết kế và thực hiện phải được sử dụng để cho phép mã biểu thị một mô hình một cách hiệu quả (xem Phần II). Những người khai thác kiến thức khám phá các tùy chọn mô hình và tinh chỉnh chúng thành các yếu tố phần mềm thực tiễn. Phát triển trở thành một quy trình lặp đi lặp lại của việc tinh chỉnh mô hình, thiết kế và mã như một hoạt động đơn nhất (xem Phần III).


                                                      Modeling Paradigms and Tool Support

                                                      Để việc THIẾT KẾ DỰA TRÊN MÔ HÌNH đem lại kết quả, sự tương ứng phải là nguyên bản, chính xác trong giới hạn của lỗi con người. Để tạo ra sự tương ứng gần gũi giữa mô hình và thiết kế, gần như thiết yếu phải làm việc trong một mô hình hóa được hỗ trợ bởi các công cụ phần mềm cho phép bạn tạo ra các tương tự trực tiếp với các khái niệm trong mô hình.

                                                      Figure 3.1.

                                                      graphics/03fig01.gif

                                                      Lập trình hướng đối tượng mạnh mẽ vì nó dựa trên một mô hình lý thuyết, và nó cung cấp các triển khai của các cấu trúc mô hình. Đối với lập trình viên, các đối tượng thực sự tồn tại trong bộ nhớ, chúng có mối liên kết với các đối tượng khác, chúng được tổ chức thành các lớp, và chúng cung cấp hành vi có sẵn qua việc nhắn tin. Mặc dù nhiều nhà phát triển chỉ hưởng lợi từ việc áp dụng các khả năng kỹ thuật của các đối tượng để tổ chức mã chương trình, bước đột phá thực sự của thiết kế đối tượng đến khi mã thể hiện các khái niệm của một mô hình. Java và nhiều công cụ khác cho phép tạo ra các đối tượng và quan hệ tương tự trực tiếp với các mô hình đối tượng khái niệm.

                                                      Mặc dù nó chưa bao giờ đạt được mức sử dụng đại trà như các ngôn ngữ lập trình hướng đối tượng, ngôn ngữ Prolog là sự lựa chọn tự nhiên cho THIẾT KẾ DỰA TRÊN MÔ HÌNH. Trong trường hợp này, mô hình là logic, và mô hình là một tập hợp các quy tắc và sự thật logic mà chúng hoạt động trên đó.

                                                      THIẾT KẾ DỰA TRÊN MÔ HÌNH có tính khả thi hạn chế khi sử dụng các ngôn ngữ như C, vì không có một mô hình nào tương ứng với một ngôn ngữ thuần túy theo quy trình. Các ngôn ngữ đó mang tính quy trình ở chỗ lập trình viên hướng dẫn máy tính thực hiện một loạt các bước. Mặc dù lập trình viên có thể đang suy nghĩ về các khái niệm của miền, nhưng chương trình tự thân nó lại là một loạt các thao tác kỹ thuật trên dữ liệu. Kết quả có thể hữu ích, nhưng chương trình không nắm bắt được nhiều ý nghĩa. Các ngôn ngữ lập trình theo quy trình thường hỗ trợ các kiểu dữ liệu phức tạp mà bắt đầu tương ứng với những nhận thức tự nhiên hơn về miền, nhưng những kiểu phức tạp này chỉ là dữ liệu được tổ chức, và không nắm bắt được các khía cạnh chủ động của miền. Kết quả là phần mềm được viết bằng các ngôn ngữ quy trình có những hàm phức tạp liên kết với nhau dựa trên các đường đi thực thi dự kiến, chứ không phải theo các kết nối khái niệm trong mô hình miền.

                                                      Trước khi tôi nghe nói về lập trình hướng đối tượng, tôi đã viết các chương trình Fortran để giải quyết các mô hình toán học, và đó chính là lĩnh vực mà Fortran tỏa sáng. Các hàm toán học là thành phần khái niệm chính của một mô hình như vậy và có thể được biểu diễn rõ ràng trong Fortran. Tuy nhiên, không có cách nào để nắm bắt ý nghĩa ở cấp độ cao hơn ngoài các hàm. Hầu hết các lĩnh vực không liên quan đến toán học không phù hợp với THIẾT KẾ DỰA TRÊN MÔ HÌNH trong các ngôn ngữ lập trình tuần tự vì các lĩnh vực đó không được khái niệm hóa như các hàm toán học hay như các bước trong một quy trình.

                                                      Thiết kế hướng đối tượng, khuynh hướng hiện đang chiếm ưu thế trong phần lớn các dự án tham vọng, là phương pháp chủ yếu được sử dụng trong cuốn sách này.

                                                      Example
                                                      From Procedural to MODEL-DRIVEN

                                                      Như đã đề cập trong Chương 1, một bảng mạch in (PCB) có thể được coi như một tập hợp các dẫn điện (gọi là nets) kết nối các chân của các linh kiện khác nhau. Thường có hàng chục nghìn nets. Phần mềm chuyên dụng, được gọi là công cụ thiết kế PCB, tìm một cách sắp xếp vật lý cho tất cả các nets sao cho chúng không chéo hoặc can thiệp vào nhau. Nó thực hiện điều này bằng cách tối ưu hóa các đường đi của chúng trong khi đáp ứng một số lượng lớn các ràng buộc do các nhà thiết kế con người đặt ra, hạn chế cách chúng có thể được bố trí. Mặc dù các công cụ thiết kế PCB rất tinh vi, nhưng chúng vẫn có một số hạn chế.

                                                      Một vấn đề là mỗi một trong số hàng ngàn mạng này đều có tập quy tắc bố trí riêng. Kỹ sư PCB thấy rằng nhiều mạng thuộc về các nhóm tự nhiên nên nên chia sẻ cùng một quy tắc. Ví dụ, một số mạng hình thành các bus.

                                                      Figure 3.2. An explanatory diagram of buses and nets

                                                      graphics/03fig02.gif

                                                      Bằng cách gom các mạng vào một bus, có thể là 8, 16 hoặc 256 mạng cùng một lúc, kỹ sư giảm công việc xuống kích thước dễ quản lý hơn, cải thiện năng suất và giảm thiểu lỗi. Vấn đề là, công cụ bố trí không có khái niệm nào như bus. Các quy tắc phải được gán cho hàng chục nghìn mạng, từng mạng một.

                                                      A Mechanistic Design

                                                      Các kỹ sư tuyệt vọng đã tìm cách vượt qua giới hạn này trong công cụ bố trí bằng cách viết các script phân tích các tệp dữ liệu của công cụ bố trí và chèn các quy tắc trực tiếp vào tệp, áp dụng chúng cho toàn bộ bus trong một lần.

                                                      Công cụ bố trí lưu trữ mỗi kết nối mạch trong một tệp danh sách mạng, trông giống như thế này:

                                                      Net Name Component.Pin -------- ------------- Xyz0 A.0, B.0 Xyz1 A.1, B.1 Xyz2 A.2, B.2 . . . 

                                                      Nó lưu trữ các quy tắc bố cục trong định dạng tệp giống như thế này:

                                                      Net Name Rule Type Parameters -------- --------- ---------- Xyz1 min_linewidth 5 Xyz1 max_delay 15 Xyz2 min_linewidth 5 Xyz2 max_delay 15 . . . 

                                                      Các kỹ sư cẩn thận sử dụng một quy tắc đặt tên cho các đường tín hiệu để việc sắp xếp theo thứ tự chữ cái của tệp dữ liệu sẽ đưa các đường tín hiệu của một bus vào cùng một tệp đã được sắp xếp. Sau đó, kịch bản của họ có thể phân tích tệp và chỉnh sửa từng đường tín hiệu dựa trên bus của nó. Mã thực tế để phân tích, thao tác và ghi các tệp là quá dài dòng và không rõ ràng để phục vụ cho ví dụ này, vì vậy tôi chỉ liệt kê các bước trong quy trình.

                                                      1. Sort net list file by net name. 2. Read each line in file, seeking first one that starts with bus name pattern. 3. For each line with matching name, parse line to get net name. 4. Append net name with rule text to rules file. 5. Repeat from 3 until left of line no longer matches bus name. 

                                                      Vì vậy, đầu vào của một quy tắc bus như thế này:

                                                      Bus Name Rule Type Parameters -------- --------- ---------- Xyz max_vias 3 

                                                      sẽ dẫn đến việc thêm các quy tắc net vào tệp như thế này:

                                                      Net Name Rule Type Parameters -------- --------- ---------- . . . Xyz0 max_vias 3 Xyz1 max_vias 3 Xyz2 max_vias 3 . . . 

                                                      Tôi tưởng tượng rằng người đầu tiên viết ra một kịch bản như vậy chỉ có nhu cầu đơn giản này, và nếu đây là yêu cầu duy nhất, một kịch bản như thế này sẽ rất hợp lý. Nhưng trên thực tế, bây giờ có hàng chục kịch bản. Chúng có thể, tất nhiên, được tái cấu trúc để chia sẻ các chức năng sắp xếp và so khớp chuỗi, và nếu ngôn ngữ hỗ trợ các cuộc gọi hàm để bao bọc các chi tiết, các kịch bản có thể bắt đầu đọc gần như như các bước tóm tắt ở trên. Nhưng vẫn, chúng chỉ là thao tác tập tin. Một định dạng tập tin khác (và có nhiều định dạng) sẽ yêu cầu bắt đầu lại từ đầu, mặc dù khái niệm nhóm xe buýt và áp dụng các quy tắc cho chúng là như nhau. Nếu bạn muốn chức năng phong phú hơn hoặc sự tương tác, bạn sẽ phải trả tiền cho từng inch.

                                                      Những gì các biên kịch đang cố gắng thực hiện là bổ sung mô hình miền của công cụ bằng khái niệm "bus." Việc triển khai của họ suy ra sự tồn tại của bus thông qua các loại và phép so khớp chuỗi, nhưng không xử lý rõ ràng khái niệm này.

                                                      A Model-Driven Design

                                                      Cuộc thảo luận trước đó đã mô tả những khái niệm mà các chuyên gia trong lĩnh vực sử dụng để tư duy về vấn đề của họ. Bây giờ, chúng ta cần tổ chức những khái niệm đó một cách rõ ràng thành một mô hình mà chúng ta có thể dựa vào để phát triển phần mềm.

                                                      Figure 3.3. A class diagram oriented toward efficient assignment of layout rules

                                                      graphics/03fig03.gif

                                                      Với những đối tượng này được triển khai trong một ngôn ngữ hướng đối tượng, chức năng cốt lõi trở nên gần như tầm thường.

                                                      Phương thức assignRule() có thể được triển khai trên Abstract Net. Phương thức assignedRules() trên Net lấy các quy tắc của chính nó và các quy tắc của Bus của nó.

                                                      abstract class AbstractNet { private Set rules; void assignRule(LayoutRule rule) { rules.add(rule); } Set assignedRules() { return rules; } } class Net extends AbstractNet { private Bus bus; Set assignedRules() { Set result = new HashSet(); result.addAll(super.assignedRules()); result.addAll(bus.assignedRules()); return result; } } 

                                                      Tất nhiên, sẽ có một lượng lớn mã hỗ trợ, nhưng điều này bao trùm các chức năng cơ bản của kịch bản.

                                                      Ứng dụng yêu cầu logic nhập/xuất, mà chúng tôi sẽ đóng gói vào một số dịch vụ đơn giản.

                                                      Dịch vụ

                                                      Trách nhiệm

                                                      Nhập danh sách mạng

                                                      Đọc tệp danh sách mạng, tạo thể hiện của mạng cho mỗi mục.

                                                      Xuất quy tắc mạng

                                                      Cho một tập hợp các Mạng, ghi tất cả các quy tắc gắn kèm vào Tệp Quy tắc.

                                                      Chúng tôi cũng cần một vài tiện ích:

                                                      Lớp

                                                      Trách nhiệm

                                                      Kho lưu trữ mạng

                                                      Cung cấp quyền truy cập vào Nets theo tên

                                                      Nhà máy xe buýt suy diễn

                                                      Dựa trên một tập hợp các mạng, sử dụng quy tắc đặt tên để suy ra các bus, tạo các ví dụ.

                                                      Kho chứa xe buýt

                                                      Cung cấp quyền truy cập vào các xe buýt theo tên

                                                      Bây giờ, việc khởi động ứng dụng chỉ là vấn đề khởi tạo các kho dữ liệu với dữ liệu được nhập khẩu:

                                                      Collection nets = NetListImportService.read(aFile); NetRepository.addAll(nets); Collection buses = InferredBusFactory.groupIntoBuses(nets); BusRepository.addAll(buses); 

                                                      Mỗi dịch vụ và kho chứa đều có thể được kiểm tra đơn vị. Quan trọng hơn, logic miền cốt lõi có thể được kiểm tra. Dưới đây là một bài kiểm tra đơn vị cho hành vi trung tâm nhất (sử dụng framework kiểm tra JUnit):

                                                      public void testBusRuleAssignment() { Net a0 = new Net("a0"); Net a1 = new Net("a1"); Bus a = new Bus("a"); //Bus is not conceptually dependent a.addNet(a0); //on name-based recognition, and so a.addNet(a1); //its tests should not be either. NetRule minWidth4 = NetRule.create(MIN_WIDTH, 4); a.assignRule(minWidth4); assertTrue(a0.assignedRules().contains(minWidth4)); assertEquals(minWidth4, a0.getRule(MIN_WIDTH)); assertEquals(minWidth4, a1.getRule(MIN_WIDTH)); } 

                                                      Một giao diện người dùng tương tác có thể hiển thị danh sách các xe buýt, cho phép người dùng gán các quy tắc cho từng xe, hoặc nó có thể đọc từ một tệp quy tắc để tương thích ngược. Một façade giúp việc truy cập trở nên đơn giản cho cả hai giao diện. Việc triển khai của nó phản ánh bài kiểm tra.

                                                      public void assignBusRule(String busName, String ruleType, double parameter){ Bus bus = BusRepository.getByName(busName); bus.assignRule(NetRule.create(ruleType, parameter)); } 

                                                      Kết thúc:

                                                      NetRuleExport.write(aFileName, NetRepository.allNets()); 

                                                      (Dịch vụ yêu cầu mỗi Net cho assignedRules(), sau đó viết chúng ra dưới dạng đầy đủ.)

                                                      Tất nhiên, nếu chỉ có một hoạt động (như trong ví dụ), thì cách tiếp cận dựa trên kịch bản có thể cũng thực tiễn không kém. Nhưng trên thực tế, có 20 hoặc nhiều hơn. THIẾT KẾ DỰA TRÊN MÔ HÌNH dễ dàng mở rộng và có thể bao gồm các ràng buộc về quy tắc kết hợp và các cải tiến khác.

                                                      Thiết kế thứ hai cũng hỗ trợ việc kiểm tra. Các thành phần của nó có giao diện được định nghĩa rõ ràng có thể được kiểm tra đơn vị. Cách duy nhất để kiểm tra kịch bản là thực hiện so sánh file vào/file ra từ đầu đến cuối.

                                                      Hãy nhớ rằng một thiết kế như vậy không xuất hiện trong một bước duy nhất. Nó sẽ cần nhiều lần chỉnh sửa và chắt lọc kiến thức để tinh giản các khái niệm quan trọng của miền thành một mô hình đơn giản, sắc bén.


                                                        Letting the Bones Show: Why Models Matter to Users

                                                        Về lý thuyết, có thể bạn có thể hiển thị cho người dùng bất kỳ cái nhìn nào về một hệ thống, bất kể những gì nằm bên dưới. Nhưng trên thực tế, sự không khớp xảy ra gây ra sự nhầm lẫn ở mức tốt nhất - và lỗi ở mức tệ nhất. Hãy xem xét một ví dụ rất đơn giản về cách người dùng bị đánh lừa bởi các mô hình chồng lên nhau của các dấu trang cho các trang web trong các phiên bản hiện tại của Microsoft Internet Explorer.

                                                        Brian Marick đã nhắc đến ví dụ này với tôi.

                                                        Một người sử dụng Internet Explorer coi "Yêu thích" như một danh sách tên các trang web tồn tại từ phiên này sang phiên khác. Nhưng cách triển khai coi một mục Yêu thích như một tệp chứa URL, và tên tệp đó được đưa vào danh sách Yêu thích. Điều đó trở thành vấn đề nếu tiêu đề trang web chứa các ký tự không hợp lệ trong tên tệp của Windows. Giả sử một người dùng cố gắng lưu một mục Yêu thích và gõ tên như sau: "Lười biếng: Bí quyết để Hạnh phúc". Một thông báo lỗi sẽ hiển thị: "Tên tệp không được chứa bất kỳ ký tự nào trong số sau: \/ : * ? " < > |". Tên tệp gì? Mặt khác, nếu tiêu đề trang web đã chứa một ký tự không hợp lệ, Internet Explorer sẽ đơn giản là lặng lẽ loại bỏ nó. Việc mất dữ liệu có thể không đáng kể trong trường hợp này, nhưng không phải là điều mà người dùng mong đợi. Việc lặng lẽ thay đổi dữ liệu là hoàn toàn không thể chấp nhận trong hầu hết các ứng dụng.

                                                        MÔ HÌNH-LÁI THIẾT KẾ yêu cầu làm việc với chỉ một mô hình (trong bất kỳ ngữ cảnh nào, như sẽ được thảo luận trong Chương 14). Hầu hết các lời khuyên và ví dụ nhắm đến các vấn đề phát sinh từ việc có các mô hình phân tích và mô hình thiết kế riêng biệt, nhưng ở đây chúng ta có một vấn đề phát sinh từ một cặp mô hình khác: mô hình người dùng và mô hình thiết kế/thực hiện.

                                                        Tất nhiên, một cái nhìn đơn giản về mô hình miền chắc chắn sẽ không thuận tiện cho người dùng trong hầu hết các trường hợp. Nhưng việc cố gắng tạo ra trong giao diện người dùng một ảo tưởng về một mô hình khác ngoài mô hình miền sẽ gây nhầm lẫn trừ khi ảo tưởng đó hoàn hảo. Nếu Web Favorites thực chất chỉ là một tập hợp các tệp lối tắt, thì hãy công khai sự thật này cho người dùng và loại bỏ mô hình thay thế gây nhầm lẫn. Không chỉ tính năng này sẽ ít gây nhầm lẫn hơn, mà người dùng có thể tận dụng những gì anh ta biết về hệ thống tệp để xử lý Web Favorites. Anh ta có thể sắp xếp lại chúng bằng File Explorer, chẳng hạn, thay vì sử dụng các công cụ khó sử dụng được tích hợp trong trình duyệt Web. Người dùng thông thạo sẽ có khả năng khai thác tính linh hoạt của việc lưu trữ lối tắt Web ở bất kỳ đâu trong hệ thống tệp. Chỉ bằng cách loại bỏ mô hình bổ sung gây hiểu lầm, sức mạnh của ứng dụng sẽ tăng lên và trở nên rõ ràng hơn. Tại sao lại khiến người dùng phải học một mô hình mới khi các lập trình viên cảm thấy mô hình cũ đã đủ tốt?

                                                        Ngoài ra, hãy lưu trữ Danh sách yêu thích theo một cách khác, chẳng hạn như trong một tệp dữ liệu, để chúng có thể tuân theo các quy tắc riêng của chúng. Những quy tắc đó có lẽ sẽ là các quy tắc đặt tên áp dụng cho các trang web. Điều này lại cung cấp một mô hình thống nhất. Mô hình này cho người dùng biết rằng mọi thứ họ biết về việc đặt tên các trang web đều áp dụng cho Danh sách yêu thích.

                                                        Khi một thiết kế dựa trên một mô hình phản ánh những mối quan tâm cơ bản của người dùng và các chuyên gia trong lĩnh vực, cấu trúc của thiết kế có thể được tiết lộ cho người dùng nhiều hơn so với những phương pháp thiết kế khác. Việc tiết lộ mô hình cung cấp cho người dùng quyền truy cập nhiều hơn vào tiềm năng của phần mềm và mang lại hành vi nhất quán, dễ dự đoán.


                                                          Hands-On Modelers

                                                          Sản xuất là một phép ẩn dụ phổ biến cho việc phát triển phần mềm. Một suy diễn từ phép ẩn dụ này: các kỹ sư tay nghề cao thiết kế; những công nhân kém tay nghề hơn lắp ráp sản phẩm. Phép ẩn dụ này đã làm hỏng nhiều dự án vì một lý do đơn giản—phát triển phần mềm hoàn toàn là thiết kế. Tất cả các nhóm đều có vai trò chuyên biệt cho các thành viên, nhưng việc phân chia trách nhiệm quá mức cho phân tích, mô hình hóa, thiết kế và lập trình làm cản trở QUÁN TRỌNG ĐẾN THIẾT KẾ DỰA TRÊN MÔ HÌNH.

                                                          Trong một dự án, công việc của tôi là phối hợp các nhóm ứng dụng khác nhau và giúp phát triển mô hình miền sẽ điều khiển thiết kế. Nhưng ban quản lý nghĩ rằng những người mô hình nên tập trung vào việc mô hình hóa, và việc lập trình là lãng phí những kỹ năng đó, vì vậy tôi đã bị cấm không được lập trình hoặc làm việc chi tiết với các lập trình viên.

                                                          Mọi thứ có vẻ ổn trong một thời gian. Làm việc với các chuyên gia trong lĩnh vực và các nhà phát triển dẫn dắt các đội khác nhau, chúng tôi đã tích lũy kiến thức và tinh chỉnh một mô hình cốt lõi đẹp. Nhưng mô hình đó không bao giờ được áp dụng, vì hai lý do.

                                                          Đầu tiên, một số ý định của mô hình đã bị mất trong quá trình chuyển giao. Ảnh hưởng tổng thể của một mô hình có thể rất nhạy cảm với các chi tiết (như sẽ được thảo luận trong các Phần II và III), và những chi tiết đó không phải lúc nào cũng được truyền đạt qua một sơ đồ UML hoặc một cuộc thảo luận chung. Nếu tôi có thể xắn tay áo và làm việc trực tiếp với các nhà phát triển khác, cung cấp một số mã để làm ví dụ, và cung cấp một số hỗ trợ gần gũi, đội ngũ có thể tiếp nhận các trừu tượng của mô hình và thực hiện chúng.

                                                          Vấn đề khác là sự gián tiếp trong phản hồi từ tương tác của mô hình với quy trình triển khai và công nghệ. Ví dụ, một số khía cạnh của mô hình tỏ ra rất kém hiệu quả trên nền tảng công nghệ của chúng tôi, nhưng những tác động đầy đủ không trở lại với tôi trong nhiều tháng. Những thay đổi tương đối nhỏ có thể đã giải quyết được vấn đề, nhưng đến lúc đó thì đã không còn quan trọng nữa. Các nhà phát triển đã trên đường viết phần mềm hoạt động—không có mô hình, mà đã được giảm xuống chỉ còn là một cấu trúc dữ liệu, bất kể khi nào nó vẫn còn được sử dụng. Các nhà phát triển đã vứt bỏ đứa trẻ cùng với nước tắm, nhưng họ có sự lựa chọn nào khác? Họ không thể mạo hiểm bị ràng buộc bởi những quy định của kiến trúc sư trong tháp ngà nữa.

                                                          Điều kiện ban đầu của dự án này gần như thuận lợi nhất cho một nhà mô hình hóa không can thiệp. Tôi đã có kinh nghiệm thực tế rộng rãi với hầu hết các công nghệ được sử dụng trong dự án. Tôi thậm chí đã từng dẫn dắt một đội phát triển nhỏ cho cùng một dự án trước khi vai trò của tôi thay đổi, vì vậy tôi đã quen thuộc với quy trình phát triển và môi trường lập trình của dự án. Ngay cả những yếu tố đó cũng không đủ để khiến tôi hiệu quả, do sự tách biệt giữa nhà mô hình hóa và triển khai.

                                                          Nếu những người viết mã không cảm thấy có trách nhiệm với mô hình, hoặc không hiểu cách làm cho mô hình hoạt động cho một ứng dụng, thì mô hình sẽ không liên quan gì đến phần mềm. Nếu các nhà phát triển không nhận ra rằng việc thay đổi mã sẽ thay đổi mô hình, thì việc tái cấu trúc của họ sẽ làm yếu đi mô hình thay vì làm mạnh nó lên. Trong khi đó, khi một nhà mô hình bị tách biệt khỏi quá trình triển khai, anh ta hoặc cô ta sẽ không bao giờ có được, hoặc nhanh chóng mất đi, cảm nhận về những hạn chế của việc triển khai. Hạn chế cơ bản của THIẾT KẾ ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH - rằng mô hình hỗ trợ một triển khai hiệu quả và trừu tượng hóa kiến thức quan trọng trong lĩnh vực - đã mất đi một nửa, và các mô hình kết quả sẽ trở nên không thực tiễn. Cuối cùng, kiến thức và kỹ năng của các thiết kế viên có kinh nghiệm sẽ không được truyền đạt cho các nhà phát triển khác nếu sự phân công công việc ngăn cản loại hình hợp tác truyền đạt những tinh tế của việc lập trình một THIẾT KẾ ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH.

                                                          Nhu cầu về những NGƯỜI MÔ HÌNH THỰC HÀNH không có nghĩa là các thành viên trong nhóm không thể có những vai trò chuyên môn. Mỗi quy trình Agile, bao gồm cả Extreme Programming, đều xác định vai trò cho các thành viên trong nhóm, và các chuyên môn không chính thức khác thường xuất hiện một cách tự nhiên. Vấn đề phát sinh từ việc tách rời hai nhiệm vụ có liên quan trong một THIẾT KẾ DỰA TRÊN MÔ HÌNH, đó là mô hình hóa và triển khai.

                                                          Hiệu quả của một thiết kế tổng thể rất nhạy cảm với chất lượng và sự nhất quán của các quyết định thiết kế và triển khai chi tiết. Với một THIẾT KẾ DỰA TRÊN MÔ HÌNH, một phần của mã nguồn là sự biểu đạt của mô hình; việc thay đổi mã đó sẽ thay đổi mô hình. Lập trình viên chính là những nhà mô hình, dù có ai thích hay không. Do đó, tốt hơn là thiết lập dự án sao cho lập trình viên có thể thực hiện tốt công việc mô hình hóa.

                                                          Do đó:

                                                          Bất kỳ người kỹ thuật nào tham gia vào mô hình cũng phải dành thời gian tiếp xúc với mã, bất kể vai trò chính của họ trong dự án là gì. Bất kỳ ai chịu trách nhiệm thay đổi mã phải học cách diễn đạt một mô hình thông qua mã. Mỗi lập trình viên phải tham gia vào một mức độ thảo luận về mô hình và có liên hệ với các chuyên gia trong lĩnh vực. Những người đóng góp theo các cách khác nhau phải chủ động kết nối với những người làm việc với mã trong một cuộc trao đổi động về các ý tưởng mô hình thông qua NGÔN NGU PHỔ BIẾN.

                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                          Sự tách biệt rõ ràng giữa mô hình hóa và lập trình không hoạt động, tuy nhiên các dự án lớn vẫn cần những lãnh đạo kỹ thuật để phối hợp thiết kế và mô hình hóa ở cấp cao, cũng như giúp giải quyết những quyết định khó khăn hoặc quan trọng nhất. Phần IV, "Thiết kế Chiến lược," đề cập đến những quyết định như vậy và nên kích thích những ý tưởng cho cách định nghĩa vai trò và trách nhiệm của những người kỹ thuật cấp cao một cách hiệu quả hơn.

                                                          Thiết kế theo miền (Domain-driven design) sử dụng một mô hình để giải quyết các vấn đề cho một ứng dụng. Thông qua việc xử lý kiến thức, một nhóm tinh chế một lượng thông tin hỗn loạn thành một mô hình thực tiễn. THIẾT KẾ DỰA TRÊN MÔ HÌNH (MODEL-DRIVEN DESIGN) kết nối chặt chẽ mô hình và việc triển khai. NGÔN NGỮ PHỔ QUÁT (UBIQUITOUS LANGUAGE) là kênh để tất cả thông tin được thông suốt giữa các nhà phát triển, chuyên gia miền và phần mềm.

                                                          Kết quả là phần mềm cung cấp chức năng phong phú dựa trên sự hiểu biết cơ bản về lĩnh vực cốt lõi.

                                                          Như đã đề cập, sự thành công với THIẾT KẾ DỰA TRÊN MÔ HÌNH nhạy cảm với các quyết định thiết kế chi tiết, đây là chủ đề của các chương tiếp theo.


                                                            Part II: The Building Blocks of a Model-Driven Design

                                                            Để giữ cho việc triển khai phần mềm rõ ràng và đi cùng với một mô hình, bất chấp thực tế rối ren, bạn phải áp dụng các phương pháp tốt nhất về mô hình hóa và thiết kế. Cuốn sách này không phải là một hướng dẫn giới thiệu về thiết kế hướng đối tượng, cũng như không đề xuất những nguyên tắc thiết kế radical. Thiết kế hướng miền chuyển trọng tâm của một số ý tưởng thông thường nhất định.

                                                            Một số loại quyết định giữ cho mô hình và việc triển khai đồng bộ với nhau, mỗi cái củng cố hiệu quả của cái kia. Sự đồng bộ này đòi hỏi phải chú ý đến các chi tiết của từng yếu tố. Việc tạo ra một cách cẩn thận ở quy mô nhỏ này mang lại cho các nhà phát triển một nền tảng vững chắc để áp dụng các phương pháp mô hình hóa của Phần III và IV.

                                                            Phong cách thiết kế trong cuốn sách này chủ yếu tuân theo nguyên tắc "thiết kế dựa trên trách nhiệm," được đề xuất trong Wirfs-Brock et al. 1990 và được cập nhật trong Wirfs-Brock 2003. Nó cũng dựa nhiều vào (đặc biệt là trong Phần III) những ý tưởng về "thiết kế theo hợp đồng" được mô tả trong Meyer 1988. Nó nhất quán với bối cảnh chung của các thực tiễn tốt nhất khác được nhiều người công nhận trong thiết kế hướng đối tượng, được mô tả trong các cuốn sách như Larman 1998.

                                                            Khi một dự án gặp khó khăn, lớn hay nhỏ, các lập trình viên có thể gặp phải những tình huống khiến các nguyên tắc đó dường như không thể áp dụng. Để quá trình thiết kế hướng theo miền trở nên kiên cường, các lập trình viên cần hiểu cách mà các nguyên tắc cơ bản nổi tiếng hỗ trợ THIẾT KẾ HƯỚNG THEO MÔ HÌNH, để họ có thể thỏa hiệp mà không làm mất phương hướng.

                                                            Nội dung trong ba chương tiếp theo được tổ chức dưới dạng "ngôn ngữ mẫu" (xem Phụ lục A), sẽ cho thấy cách mà những khác biệt mô hình tinh tế và các quyết định thiết kế ảnh hưởng đến quy trình thiết kế hướng miền.

                                                            Biểu đồ ở đầu trang tiếp theo là một bản đồ điều hướng. Nó cho thấy các mô hình sẽ được trình bày trong phần này và một vài cách mà chúng liên quan đến nhau.

                                                            Chia sẻ những mẫu chuẩn này mang lại trật tự cho thiết kế và giúp các thành viên trong nhóm dễ hiểu công việc của nhau hơn. Việc sử dụng các mẫu chuẩn cũng góp phần vào NGÔN NGỮ PHỔ BIẾN, mà tất cả các thành viên trong nhóm có thể sử dụng để thảo luận về các quyết định mô hình và thiết kế.

                                                            Phát triển một mô hình miền tốt là một nghệ thuật. Nhưng thiết kế và triển khai thực tế của các thành phần riêng lẻ của mô hình có thể tương đối có hệ thống. Tách biệt thiết kế miền khỏi vô số các vấn đề khác trong hệ thống phần mềm sẽ làm rõ ràng mối liên hệ của thiết kế với mô hình. Định nghĩa các thành phần của mô hình theo những sự phân biệt nhất định làm sắc nét ý nghĩa của chúng. Việc tuân theo các mẫu đã được chứng minh cho các thành phần riêng lẻ giúp sản xuất một mô hình có thể thực hiện được.

                                                            Bản đồ điều hướng của ngôn ngữ THIẾT KẾ DỰA TRÊN MÔ HÌNH

                                                            graphics/partii.gif

                                                            Các mô hình phức tạp có thể vượt qua sự phức tạp chỉ khi chú ý đến các yếu tố cơ bản, dẫn đến những yếu tố chi tiết mà nhóm có thể tự tin kết hợp.


                                                              Chapter Four. Isolating the Domain

                                                              Phần mềm mà giải quyết các vấn đề cụ thể từ miền thường chỉ chiếm một phần nhỏ trong toàn bộ hệ thống phần mềm, mặc dù tầm quan trọng của nó không tương xứng với kích thước. Để áp dụng tư duy tốt nhất, chúng ta cần có khả năng nhìn nhận các yếu tố trong mô hình của mình và xem chúng như một hệ thống. Chúng ta không nên bị ép buộc phải tách chúng ra khỏi một hỗn hợp lớn hơn của các đối tượng, giống như việc cố gắng xác định các chòm sao trong bầu trời đêm. Chúng ta cần tách rời các đối tượng miền khỏi các chức năng khác của hệ thống, để có thể tránh nhầm lẫn các khái niệm miền với các khái niệm liên quan chỉ đến công nghệ phần mềm hoặc mất tầm nhìn về miền trong khối lượng của hệ thống.

                                                              Công nghệ tinh vi cho việc cô lập này đã xuất hiện. Đây là một lĩnh vực đã được khai thác nhiều, nhưng nó rất quan trọng cho việc áp dụng thành công các nguyên tắc mô hình miền đến nỗi nó cần được xem xét ngắn gọn, từ góc độ hướng miền. . . .


                                                                Layered Architecture

                                                                graphics/04inf02.gif

                                                                Để một ứng dụng vận chuyển hỗ trợ hành động đơn giản của người dùng là chọn điểm đến của hàng hóa từ danh sách các thành phố, cần có mã chương trình thực hiện các tác vụ sau (1) vẽ một widget trên màn hình, (2) truy vấn cơ sở dữ liệu để lấy tất cả các thành phố có thể, (3) hiểu và xác thực đầu vào của người dùng, (4) liên kết thành phố đã chọn với hàng hóa, và (5) lưu thay đổi vào cơ sở dữ liệu. Tất cả mã này nằm trong cùng một chương trình, nhưng chỉ một phần nhỏ trong đó liên quan đến lĩnh vực vận chuyển.

                                                                Các chương trình phần mềm bao gồm thiết kế và mã để thực hiện nhiều loại nhiệm vụ khác nhau. Chúng nhận đầu vào từ người dùng, thực hiện logic kinh doanh, truy cập cơ sở dữ liệu, giao tiếp qua mạng, hiển thị thông tin cho người dùng, và nhiều hơn nữa. Do đó, mã liên quan đến từng chức năng của chương trình có thể là rất lớn.

                                                                Trong một chương trình hướng đối tượng, giao diện người dùng, cơ sở dữ liệu và các mã hỗ trợ khác thường được viết trực tiếp vào các đối tượng kinh doanh. Logic kinh doanh bổ sung được nhúng trong hành vi của các widget giao diện người dùng và các tập lệnh cơ sở dữ liệu. Điều này xảy ra vì đó là cách dễ nhất để mọi thứ hoạt động, trong ngắn hạn.

                                                                Khi mã liên quan đến miền bị phân tán qua một lượng lớn mã khác, nó trở nên cực kỳ khó để nhìn thấy và lý luận. Những thay đổi bề mặt đối với giao diện người dùng thực sự có thể thay đổi logic kinh doanh. Để thay đổi một quy tắc kinh doanh có thể yêu cầu việc theo dõi tỉ mỉ mã giao diện người dùng, mã cơ sở dữ liệu hoặc các yếu tố chương trình khác. Việc triển khai các đối tượng có mô hình nhất quán trở nên không thực tế. Kiểm tra tự động trở nên bất tiện. Với tất cả các công nghệ và logic liên quan đến mỗi hoạt động, một chương trình phải được giữ rất đơn giản hoặc trở nên không thể hiểu được.

                                                                Việc tạo ra các chương trình có thể xử lý các tác vụ rất phức tạp yêu cầu phải tách biệt các mối quan tâm, cho phép tập trung vào các phần khác nhau của thiết kế một cách cô lập. Đồng thời, các tương tác phức tạp trong hệ thống phải được duy trì bất chấp sự tách biệt.

                                                                Có rất nhiều cách để phân chia một hệ thống phần mềm, nhưng qua kinh nghiệm và truyền thống, ngành công nghiệp đã hội tụ vào CÁC KIẾN TRÚC LỚP, và cụ thể là một vài lớp tiêu chuẩn. Ẩn dụ về việc phân lớp được sử dụng rất rộng rãi đến nỗi hầu hết các nhà phát triển đều cảm thấy nó trực quan. Nhiều cuộc thảo luận tốt về việc phân lớp có sẵn trong tài liệu, đôi khi ở dạng một mẫu (như trong Buschmann et al. 1996, tr. 31–51). Nguyên tắc cốt lõi là bất kỳ phần tử nào của một lớp chỉ phụ thuộc vào các phần tử khác trong cùng một lớp hoặc vào các phần tử của các lớp "dưới" nó. Sự giao tiếp theo chiều lên phải đi qua một cơ chế gián tiếp nào đó, điều mà tôi sẽ thảo luận một chút sau đây.

                                                                Giá trị của các lớp là mỗi lớp chuyên về một khía cạnh cụ thể của một chương trình máy tính. Sự chuyên môn hóa này cho phép thiết kế mỗi khía cạnh đồng nhất hơn, và khiến cho việc diễn giải các thiết kế này dễ dàng hơn nhiều. Tất nhiên, việc chọn các lớp để tách biệt những khía cạnh thiết kế đồng nhất quan trọng nhất là điều sống còn. Một lần nữa, kinh nghiệm và quy ước đã dẫn tới một số hội tụ. Mặc dù có nhiều biến thể, hầu hết các kiến trúc thành công sử dụng một phiên bản nào đó của bốn lớp khái niệm này:

                                                                Giao diện người dùng (hoặc lớp trình bày)

                                                                Chịu trách nhiệm hiển thị thông tin cho người dùng và giải thích các lệnh của người dùng. Diễn viên bên ngoài có thể đôi khi là một hệ thống máy tính khác chứ không phải là người dùng con người.

                                                                Lớp ứng dụng

                                                                Xác định các công việc mà phần mềm cần thực hiện và chỉ đạo các đối tượng miền biểu đạt giải quyết các vấn đề. Các nhiệm vụ mà lớp này chịu trách nhiệm có ý nghĩa đối với doanh nghiệp hoặc cần thiết cho việc tương tác với các lớp ứng dụng của các hệ thống khác.

                                                                Lớp này được giữ mỏng. Nó không chứa các quy tắc hoặc tri thức kinh doanh, mà chỉ phối hợp các nhiệm vụ và phân công công việc cho các đối tượng miền trong lớp bên dưới. Nó không có trạng thái phản ánh tình hình kinh doanh, nhưng có thể có trạng thái phản ánh tiến độ của một nhiệm vụ cho người dùng hoặc chương trình.

                                                                Lớp Miền (hoặc Lớp Mô Hình)

                                                                Chịu trách nhiệm đại diện cho các khái niệm của doanh nghiệp, thông tin về tình hình kinh doanh và các quy tắc kinh doanh. Trạng thái phản ánh tình hình kinh doanh được kiểm soát và sử dụng ở đây, mặc dù các chi tiết kỹ thuật về việc lưu trữ nó được ủy thác cho cơ sở hạ tầng. Lớp này là trái tim của phần mềm doanh nghiệp.

                                                                Lớp Hạ tầng

                                                                Cung cấp các khả năng kỹ thuật chung hỗ trợ các lớp cao hơn: gửi tin nhắn cho ứng dụng, lưu trữ cho miền, vẽ giao diện cho UI, và vân vân. Lớp hạ tầng cũng có thể hỗ trợ mẫu tương tác giữa bốn lớp thông qua một khung kiến trúc.

                                                                Một số dự án không phân biệt rõ ràng giữa giao diện người dùng và các lớp ứng dụng. Những dự án khác có nhiều lớp hạ tầng. Nhưng chính sự tách biệt quan trọng của lớp miền đã cho phép DESIGN DỰA TRÊN MÔ HÌNH.

                                                                Vì vậy:

                                                                Phân chia một chương trình phức tạp thành các lớp. Phát triển một thiết kế trong mỗi lớp mà đồng nhất và chỉ phụ thuộc vào các lớp bên dưới. Tuân theo các mẫu kiến trúc tiêu chuẩn để cung cấp sự tách rời lỏng lẻo cho các lớp ở trên. Tập trung tất cả mã liên quan đến mô hình miền trong một lớp và tách biệt nó khỏi giao diện người dùng, ứng dụng và mã hạ tầng. Các đối tượng miền, không phải chịu trách nhiệm hiển thị, lưu trữ, quản lý các tác vụ của ứng dụng, và các công việc khác, có thể tập trung vào việc diễn đạt mô hình miền. Điều này cho phép một mô hình phát triển đủ phong phú và rõ ràng để nắm bắt kiến thức kinh doanh thiết yếu và đưa chúng vào hoạt động.

                                                                Việc tách biệt lớp miền khỏi các lớp hạ tầng và giao diện người dùng cho phép thiết kế của mỗi lớp trở nên sạch sẽ hơn. Các lớp tách biệt ít tốn kém để duy trì hơn, vì chúng có xu hướng phát triển với tốc độ khác nhau và đáp ứng những nhu cầu khác nhau. Sự tách biệt cũng giúp việc triển khai trong hệ thống phân tán, bằng cách cho phép các lớp khác nhau được đặt một cách linh hoạt trên các máy chủ hoặc máy khách khác nhau, nhằm giảm thiểu độ trễ giao tiếp và cải thiện hiệu suất (Fowler 1996).

                                                                Example
                                                                Partitioning Online Banking Functionality into Layers

                                                                Một ứng dụng cung cấp nhiều chức năng để quản lý tài khoản ngân hàng. Một tính năng là chuyển khoản, trong đó người dùng nhập hoặc chọn hai số tài khoản và một số tiền, sau đó khởi động quá trình chuyển khoản.

                                                                Để làm cho ví dụ này dễ quản lý, tôi đã bỏ qua các tính năng kỹ thuật chính, đặc biệt là bảo mật. Thiết kế miền cũng được đơn giản hóa quá mức. (Sự phức tạp thực tế chỉ làm tăng nhu cầu về kiến trúc phân lớp.) Hơn nữa, hạ tầng cụ thể được ngụ ý ở đây được cho là đơn giản và rõ ràng để làm cho ví dụ trở nên dễ hiểu—nó không phải là một thiết kế được gợi ý. Các trách nhiệm của chức năng còn lại sẽ được phân lớp như được thể hiện trong Hình 4.1.

                                                                Figure 4.1. Objects carry out responsibilities consistent with their layer and are more coupled to other objects in their layer.

                                                                graphics/04fig01.gif

                                                                Lưu ý rằng lớp miền, chứ không phải lớp ứng dụng, chịu trách nhiệm về các quy tắc kinh doanh cơ bản - trong trường hợp này, quy tắc là "Mỗi khoản tín dụng đều có một khoản ghi nợ tương ứng."

                                                                Ứng dụng cũng không đưa ra giả định nào về nguồn gốc của yêu cầu chuyển tiền. Chương trình có lẽ bao gồm một giao diện người dùng với các trường nhập cho số tài khoản và số tiền, cùng với các nút cho các lệnh. Nhưng giao diện người dùng đó có thể được thay thế bằng một yêu cầu wire ở định dạng XML mà không ảnh hưởng đến lớp ứng dụng hoặc bất kỳ lớp nào bên dưới. Sự tách biệt này rất quan trọng không phải vì các dự án thường xuyên cần thay thế giao diện người dùng bằng các yêu cầu wire, mà vì sự phân tách rõ ràng các mối quan tâm giúp cho thiết kế của mỗi lớp dễ hiểu và duy trì.

                                                                Thực tế, Hình 4.1 tự nó nhẹ nhàng minh họa vấn đề không tách rời miền. Bởi vì mọi thứ từ yêu cầu đến kiểm soát giao dịch đều phải được bao gồm, lớp miền đã phải đơn giản hóa để giữ cho tương tác tổng thể đủ đơn giản để theo dõi. Nếu chúng ta tập trung vào thiết kế của lớp miền tách rời, chúng ta sẽ có không gian trên trang và trong đầu cho một mô hình tốt hơn đại diện cho các quy tắc của miền, có lẽ bao gồm sổ cái, các đối tượng tín dụng và nợ, hoặc các đối tượng giao dịch tiền tệ.

                                                                Relating the Layers

                                                                Cho đến nay, cuộc thảo luận đã tập trung vào việc tách biệt các lớp và cách mà việc phân chia đó cải thiện thiết kế của từng khía cạnh của chương trình, đặc biệt là lớp miền. Nhưng tất nhiên, các lớp cần phải được liên kết. Việc làm này mà không làm mất đi lợi ích của sự tách biệt chính là động lực phía sau một số mẫu thiết kế.

                                                                Các lớp được thiết kế để có sự liên kết lỏng lẻo, với các phụ thuộc thiết kế chỉ theo một hướng. Các lớp cao hơn có thể sử dụng hoặc thao tác với các thành phần của các lớp thấp hơn một cách dễ dàng bằng cách gọi các giao diện công khai của chúng, giữ tham chiếu đến chúng (ít nhất là tạm thời), và thường sử dụng các phương tiện tương tác thông thường. Nhưng khi một đối tượng ở cấp thấp cần giao tiếp lên trên (ngoài việc trả lời một truy vấn trực tiếp), chúng ta cần một cơ chế khác, dựa vào các mẫu kiến trúc để liên kết các lớp như các callback hoặc OBSERVERS (Gamma et al. 1995).

                                                                Ông tổ của các mẫu kết nối giao diện người dùng với các lớp ứng dụng và miền là MÔ HÌNH-THỐNG KÊ-KIỂM SOÁT (MVC). Nó được khởi xướng trong thế giới Smalltalk vào những năm 1970 và đã truyền cảm hứng cho nhiều kiến trúc giao diện người dùng theo sau. Fowler (2002) đã thảo luận về mẫu này và một số biến thể hữu ích. Larman (1998) khám phá những vấn đề này trong MẪU PHÂN TÁCH MÔ HÌNH-THỐNG KÊ, và COORDINATOR ỨNG DỤNG của ông là một phương pháp để kết nối lớp ứng dụng.

                                                                Có những cách khác để kết nối giao diện người dùng và ứng dụng. Đối với mục đích của chúng tôi, tất cả các phương pháp đều ổn miễn là chúng duy trì sự tách biệt của lớp miền, cho phép các đối tượng miền được thiết kế mà không cần suy nghĩ đồng thời về giao diện người dùng có thể tương tác với chúng.

                                                                Lớp hạ tầng thường không khởi xướng hành động trong lớp miền. Vốn "ở dưới" lớp miền, nó không nên có kiến thức cụ thể về miền mà nó phục vụ. Thực tế, những khả năng kỹ thuật như vậy thường được cung cấp dưới dạng DỊCH VỤ. Ví dụ, nếu một ứng dụng cần gửi một email, một giao diện gửi tin nhắn có thể được đặt trong lớp hạ tầng và các thành phần của lớp ứng dụng có thể yêu cầu truyền tải tin nhắn. Việc tách rời này mang lại một số tính linh hoạt bổ sung. Giao diện gửi tin nhắn có thể được kết nối với một người gửi email, một người gửi fax, hoặc bất kỳ gì khác có sẵn. Nhưng lợi ích chính là đơn giản hóa lớp ứng dụng, giữ nó tập trung hẹp vào công việc của mình: biết khi nào gửi một tin nhắn, nhưng không phải gánh nặng với cách gửi.

                                                                Các lớp ứng dụng và miền gọi đến các DỊCH VỤ được cung cấp bởi lớp hạ tầng. Khi phạm vi của một DỊCH VỤ được chọn lựa hợp lý và giao diện của nó được thiết kế tốt, người gọi có thể duy trì sự kết nối lỏng lẻo và không bị phức tạp bởi hành vi tinh vi mà giao diện DỊCH VỤ bao gồm.

                                                                Nhưng không phải tất cả hạ tầng đều dưới dạng DỊCH VỤ có thể gọi từ các lớp cao hơn. Một số thành phần kỹ thuật được thiết kế để hỗ trợ trực tiếp các chức năng cơ bản của các lớp khác (chẳng hạn như cung cấp một lớp cơ sở trừu tượng cho tất cả các đối tượng miền) và cung cấp các cơ chế để chúng liên kết với nhau (như các triển khai của MVC và tương tự). Một "khung kiến trúc" như vậy có tác động lớn hơn nhiều đến thiết kế của các phần khác trong chương trình.

                                                                Architectural Frameworks

                                                                Khi hạ tầng được cung cấp dưới dạng DỊCH VỤ được gọi thông qua các giao diện, việc hiểu cách các lớp hoạt động và cách giữ cho các lớp lỏng lẻo liên kết với nhau là khá trực quan. Nhưng một số vấn đề kỹ thuật yêu cầu các hình thức hạ tầng can thiệp nhiều hơn. Các khung công tác tích hợp nhiều nhu cầu hạ tầng thường yêu cầu các lớp khác được triển khai theo những cách rất cụ thể, chẳng hạn như là một lớp con của một lớp khung hoặc với các chữ ký phương thức có cấu trúc. (Có thể có vẻ nghịch lý khi một lớp con nằm ở một lớp cao hơn lớp cha, nhưng hãy nhớ rằng lớp nào phản ánh nhiều kiến thức hơn về lớp khác.) Các khung kiến trúc tốt nhất giải quyết các vấn đề kỹ thuật phức tạp trong khi cho phép nhà phát triển miền tập trung vào việc diễn đạt một mô hình. Nhưng các khung công tác có thể dễ dàng cản trở, hoặc bằng cách tạo ra quá nhiều giả định hạn chế lựa chọn thiết kế miền, hoặc bằng cách làm cho việc triển khai quá nặng nề khiến quá trình phát triển chậm lại.

                                                                Một dạng khung kiến trúc nào đó thường là cần thiết (mặc dù đôi khi các nhóm chọn những khung mà không phục vụ tốt cho họ). Khi áp dụng một khung, nhóm cần tập trung vào mục tiêu của mình: xây dựng một triển khai thể hiện mô hình miền và sử dụng nó để giải quyết những vấn đề quan trọng. Nhóm phải tìm kiếm cách sử dụng khung để đạt được mục tiêu đó, ngay cả khi điều đó có nghĩa là không sử dụng tất cả các tính năng của khung. Ví dụ, các ứng dụng J2EE đầu tiên thường triển khai tất cả các đối tượng miền dưới dạng "entity beans." Cách tiếp cận này đã làm giảm hiệu suất và tốc độ phát triển. Thay vào đó, thực tiễn tốt nhất hiện nay là sử dụng khung J2EE cho các đối tượng có kích thước lớn hơn, triển khai hầu hết logic kinh doanh bằng các đối tượng Java chung. Nhiều bất lợi của các khung có thể được tránh bằng cách áp dụng chúng một cách chọn lọc để giải quyết các vấn đề khó mà không tìm kiếm một giải pháp đều cho mọi tình huống. Áp dụng một cách hợp lý chỉ những tính năng có giá trị nhất của khung sẽ giảm sự ràng buộc giữa triển khai và khung, cho phép linh hoạt hơn trong các quyết định thiết kế sau này. Quan trọng hơn, vì nhiều khung hiện tại rất phức tạp để sử dụng, sự tối giản này giúp giữ cho các đối tượng kinh doanh có thể đọc được và có tính diễn đạt cao.

                                                                Các khung kiến trúc và các công cụ khác sẽ tiếp tục phát triển. Các khung mới hơn sẽ tự động hóa hoặc chế tạo trước nhiều khía cạnh kỹ thuật của một ứng dụng hơn. Nếu điều này được thực hiện đúng, các nhà phát triển ứng dụng sẽ ngày càng tập trung thời gian của họ vào việc mô hình hóa các vấn đề kinh doanh cốt lõi, cải thiện đáng kể năng suất và chất lượng. Nhưng khi chúng ta tiến về hướng này, chúng ta phải cảnh giác với sự nhiệt tình của mình đối với các giải pháp kỹ thuật; các khung phức tạp cũng có thể khiến các nhà phát triển ứng dụng bị ràng buộc.


                                                                  The Domain Layer Is Where the Model Lives

                                                                  KIẾN TRÚC LỚP được sử dụng trong hầu hết các hệ thống ngày nay, dưới các sơ đồ lớp khác nhau. Nhiều phong cách phát triển cũng có thể hưởng lợi từ việc phân lớp. Tuy nhiên, thiết kế hướng miền chỉ yêu cầu một lớp cụ thể tồn tại.

                                                                  Mô hình miền là một tập hợp các khái niệm. "Lớp miền" là sự thể hiện của mô hình đó và tất cả các yếu tố thiết kế liên quan trực tiếp. Thiết kế và triển khai logic kinh doanh cấu thành lớp miền. Trong MÔ HÌNH-ĐƯA RA THIẾT KẾ, các cấu trúc phần mềm của lớp miền phản ánh các khái niệm trong mô hình.

                                                                  Thật không thực tế để đạt được sự tương ứng đó khi logic miền bị trộn lẫn với các mối quan tâm khác của chương trình. Việc tách biệt việc triển khai miền là một điều kiện tiên quyết cho thiết kế hướng miền.


                                                                    The Smart UI "Anti-Pattern"

                                                                    . . . Điều đó tóm tắt mô hình KIẾN TRÚC LỚP chấp nhận rộng rãi cho các ứng dụng đối tượng. Nhưng sự tách biệt này giữa giao diện người dùng, ứng dụng và miền thường được cố gắng thực hiện mà hiếm khi thành công, đến mức sự phủ định của nó xứng đáng được thảo luận riêng.

                                                                    Nhiều dự án phần mềm thực sự áp dụng và nên tiếp tục áp dụng một cách tiếp cận thiết kế ít phức tạp hơn mà tôi gọi là SMART UI. Tuy nhiên, SMART UI là một nhánh thay thế, loại trừ lẫn nhau, không tương thích với cách tiếp cận thiết kế hướng miền. Nếu con đường đó được chọn, hầu hết những gì có trong cuốn sách này sẽ không áp dụng. Sự quan tâm của tôi nằm ở những tình huống mà SMART UI không áp dụng, vì vậy tôi gọi nó, với một chút châm biếm, là một "kiểu mẫu ngược." Việc thảo luận về nó ở đây cung cấp một sự tương phản hữu ích và sẽ giúp làm rõ những hoàn cảnh biện minh cho con đường khó khăn hơn được chọn trong phần còn lại của cuốn sách.

                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                    Một dự án cần cung cấp chức năng đơn giản, chủ yếu là nhập liệu và hiển thị, với ít quy tắc kinh doanh. Nhân viên không phải là những người mô hình hóa đối tượng nâng cao.

                                                                    Nếu một đội ngũ không tinh vi với một dự án đơn giản quyết định thử nghiệm THIẾT KẾ DỰA TRÊN MÔ HÌNH với KIẾN TRÚC TẦNG, họ sẽ gặp phải một đường cong học tập khó khăn. Các thành viên trong đội sẽ phải thành thạo những công nghệ phức tạp mới và vật lộn qua quá trình học mô hình hóa đối tượng (điều này rất thách thức, ngay cả khi có sự trợ giúp của cuốn sách này!). Chi phí quản lý cơ sở hạ tầng và các lớp làm cho những nhiệm vụ rất đơn giản mất nhiều thời gian hơn. Các dự án đơn giản thường có thời gian ngắn và kỳ vọng khiêm tốn. Trước khi đội hoàn thành nhiệm vụ được giao, chưa nói đến việc thể hiện những khả năng thú vị của cách tiếp cận này, dự án sẽ bị hủy bỏ.

                                                                    Ngay cả khi nhóm được cho thêm thời gian, các thành viên trong nhóm có khả năng sẽ không thành thạo các kỹ thuật mà không có sự giúp đỡ của chuyên gia. Và cuối cùng, nếu họ vượt qua những thử thách này, họ sẽ chỉ tạo ra một hệ thống đơn giản. Các khả năng phong phú chưa bao giờ được yêu cầu.

                                                                    Một đội ngũ có kinh nghiệm hơn sẽ không gặp phải những sự đánh đổi tương tự. Các nhà phát triển dày dạn có thể làm phẳng đường cong học tập và rút ngắn thời gian cần thiết để quản lý các lớp. Thiết kế hướng miền mang lại lợi ích tốt nhất cho những dự án đầy tham vọng, và nó thực sự đòi hỏi những kỹ năng vững mạnh. Không phải mọi dự án đều đầy tham vọng. Không phải tất cả các nhóm dự án đều có thể tập hợp những kỹ năng đó.

                                                                    Do đó, khi hoàn cảnh cho phép:

                                                                    Đưa toàn bộ logic kinh doanh vào giao diện người dùng. Chia ứng dụng thành các chức năng nhỏ và triển khai chúng dưới dạng các giao diện người dùng riêng biệt, nhúng các quy tắc kinh doanh vào các giao diện đó. Sử dụng cơ sở dữ liệu quan hệ như một kho dữ liệu chung. Sử dụng các công cụ xây dựng giao diện người dùng và lập trình trực quan tự động hóa tốt nhất có sẵn.

                                                                    Heresy! Tin mừng (như được ủng hộ ở khắp nơi, bao gồm cả những nơi khác trong cuốn sách này) là miền và giao diện người dùng nên tách biệt. Trên thực tế, thật khó để áp dụng bất kỳ phương pháp nào được thảo luận sau này trong cuốn sách này mà không có sự tách biệt đó, vì vậy UI SMART này có thể được coi là một "mô hình phản" trong bối cảnh thiết kế hướng miền. Tuy nhiên, đây là một mô hình hợp lệ trong một số bối cảnh khác. Thực tế, có những lợi ích của UI SMART, và có những tình huống mà nó hoạt động tốt nhất—điều này phần nào giải thích tại sao nó rất phổ biến. Xem xét nó ở đây giúp chúng ta hiểu tại sao chúng ta cần tách biệt ứng dụng khỏi miền và, quan trọng hơn, khi nào chúng ta có thể không muốn làm điều đó.

                                                                    Advantages

                                                                    • Năng suất cao và ngay lập tức cho các ứng dụng đơn giản.

                                                                    • Các nhà phát triển kém năng lực có thể làm việc theo cách này với ít đào tạo.

                                                                    • Ngay cả những thiếu sót trong phân tích yêu cầu cũng có thể được khắc phục bằng cách phát hành một nguyên mẫu cho người dùng và sau đó nhanh chóng điều chỉnh sản phẩm để phù hợp với yêu cầu của họ.

                                                                    • Các ứng dụng được tách rời khỏi nhau, để lịch trình giao hàng của các mô-đun nhỏ có thể được lập kế hoạch khá chính xác. Việc mở rộng hệ thống với các hành vi đơn giản bổ sung có thể dễ dàng.

                                                                    • Cơ sở dữ liệu quan hệ hoạt động tốt và cung cấp tích hợp ở cấp độ dữ liệu.

                                                                    • Công cụ 4GL hoạt động tốt.

                                                                    • Khi các ứng dụng được chuyển giao, lập trình viên bảo trì sẽ có thể nhanh chóng làm lại những phần mà họ không thể hiểu, vì tác động của những thay đổi sẽ được giới hạn trong từng giao diện người dùng cụ thể.

                                                                    Disadvantages

                                                                    • Việc tích hợp các ứng dụng là khó khăn trừ khi thông qua cơ sở dữ liệu.

                                                                    • Không có việc tái sử dụng hành vi và không có sự trừu tượng hóa vấn đề kinh doanh. Các quy tắc kinh doanh phải được sao chép trong mỗi hoạt động mà chúng áp dụng.

                                                                    • Sự tạo mẫu nhanh và lặp lại đạt đến một giới hạn tự nhiên vì thiếu sự trừu tượng hạn chế các tùy chọn tái cấu trúc.

                                                                    • Sự phức tạp nhanh chóng chôn vùi bạn, vì vậy con đường phát triển chỉ hướng tới những ứng dụng đơn giản hơn. Không có con đường nào dễ dàng để đạt được hành vi phong phú hơn.

                                                                    Nếu mô hình này được áp dụng một cách có ý thức, một nhóm có thể tránh được việc phải gánh chịu nhiều chi phí quản lý cần thiết cho các phương pháp khác. Một sai lầm phổ biến là thực hiện một phương pháp thiết kế phức tạp mà nhóm không có cam kết thực hiện đến cùng. Một sai lầm tốn kém khác là xây dựng một hạ tầng phức tạp và sử dụng các công cụ công nghiệp mạnh mẽ cho một dự án không cần thiết.

                                                                    Các ngôn ngữ linh hoạt nhất (như Java) là thừa thãi cho những ứng dụng này và sẽ tốn kém. Một công cụ kiểu 4GL là sự lựa chọn tốt nhất.

                                                                    Hãy nhớ rằng, một trong những hệ quả của mô hình này là bạn không thể chuyển sang một cách tiếp cận thiết kế khác trừ khi thay thế toàn bộ ứng dụng. Chỉ sử dụng một ngôn ngữ đa mục đích như Java sẽ không thực sự đưa bạn vào vị trí có thể từ bỏ SMART UI sau này, vì vậy nếu bạn đã chọn con đường đó, bạn nên chọn các công cụ phát triển phù hợp với nó. Đừng mất công phòng ngừa. Chỉ sử dụng một ngôn ngữ linh hoạt không tạo ra một hệ thống linh hoạt, nhưng có thể tạo ra một hệ thống đắt đỏ.

                                                                    Theo cách thức tương tự, một đội ngũ cam kết thiết kế Dựa trên Mô Hình cần phải thiết kế theo cách đó ngay từ đầu. Tất nhiên, ngay cả những đội ngũ dự án dày dạn kinh nghiệm với những tham vọng lớn cũng phải bắt đầu với các chức năng đơn giản và phát triển dần qua các phiên bản liên tiếp. Nhưng những bước đi đầu tiên này sẽ được Dựa trên Mô Hình với một lớp miền riêng biệt, nếu không, dự án rất có thể sẽ bị mắc kẹt với một Giao Diện Thông Minh. Giao Diện Thông Minh được thảo luận chỉ để làm rõ lý do và thời điểm nào một mẫu như Kiến Trúc Lớp là cần thiết để tách biệt một lớp miền.

                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                    Có những giải pháp khác giữa GIA DIỆN THÔNG MINH (SMART UI) và KIẾN TRÚC LỚP (LAYERED ARCHITECTURE). Ví dụ, Fowler (2002) mô tả KỊCH BẢN GIAO DỊCH (TRANSACTION SCRIPT), tách biệt giao diện người dùng khỏi ứng dụng nhưng không cung cấp mô hình đối tượng. Điểm mấu chốt là như thế này: Nếu kiến trúc cô lập mã liên quan đến miền theo cách cho phép một thiết kế miền hợp nhất liên kết lỏng lẻo với phần còn lại của hệ thống, thì kiến trúc đó có thể hỗ trợ thiết kế driven by domain.

                                                                    Các phong cách phát triển khác có chỗ đứng của chúng, nhưng bạn phải chấp nhận những giới hạn khác nhau về độ phức tạp và tính linh hoạt. Việc không tách rời thiết kế miền có thể gây ra hậu quả nghiêm trọng trong một số tình huống nhất định. Nếu bạn có một ứng dụng phức tạp và cam kết với THIẾT KẾ DỰA TRÊN MÔ HÌNH, hãy kiên quyết, tìm kiếm các chuyên gia cần thiết và tránh giao diện SMART.


                                                                      Other Kinds of Isolation

                                                                      Rất tiếc, có những yếu tố khác ngoài cơ sở hạ tầng và giao diện người dùng có thể làm hỏng mô hình miền tinh tế của bạn. Bạn phải xử lý các thành phần miền khác không hoàn toàn được tích hợp vào mô hình của bạn. Bạn phải đối phó với các nhóm phát triển khác sử dụng các mô hình khác nhau cho cùng một miền. Những yếu tố này và các yếu tố khác có thể làm mờ mô hình của bạn và tước bỏ tính hữu ích của nó. Chương 14, "Bảo trì tính toàn vẹn của mô hình," đề cập đến chủ đề này, giới thiệu các mẫu như BOUND CONTEXT và ANTICORRUPTION LAYER. Một mô hình miền thực sự phức tạp có thể trở nên khó quản lý ngay cả khi tự nó. Chương 15, "Chưng cất," thảo luận về cách phân biệt trong lớp miền có thể giải phóng các khái niệm thiết yếu của miền khỏi các chi tiết bên lề.

                                                                      Nhưng tất cả điều đó sẽ đến sau. Tiếp theo, chúng ta sẽ xem xét những chi tiết cơ bản của việc cùng phát triển một mô hình miền hiệu quả và một triển khai thể hiện rõ ràng. Vì sau cùng, phần tốt nhất của việc tách biệt miền là loại bỏ tất cả những thứ khác để chúng ta có thể thật sự tập trung vào thiết kế miền.


                                                                        Chapter Five. A Model Expressed in Software

                                                                        Để thỏa hiệp trong việc triển khai mà không làm mất đi sức mạnh của MÔ HÌNH KHOA HỌC, cần phải cơ cấu lại các nguyên tắc cơ bản. Việc kết nối mô hình và triển khai phải được thực hiện ở cấp độ chi tiết. Chương này tập trung vào các thành phần mô hình riêng lẻ, điều chỉnh chúng để hỗ trợ các hoạt động trong các chương sau.

                                                                        Cuộc thảo luận này sẽ bắt đầu với các vấn đề về thiết kế và hợp lý hóa các hiệp hội. Các hiệp hội giữa các đối tượng thì đơn giản để tưởng tượng và đồ họa, nhưng việc triển khai chúng có thể là một bãi lầy tiềm ẩn. Các hiệp hội minh họa tầm quan trọng của những quyết định triển khai chi tiết đối với tính khả thi của MÔ HÌNH-LÁI THIẾT KẾ.

                                                                        Chuyển sang các đối tượng tự thân, nhưng vẫn tiếp tục xem xét mối quan hệ giữa các lựa chọn mô hình chi tiết và các vấn đề thực hiện, chúng ta sẽ tập trung vào việc phân biệt giữa ba loại mô hình mà biểu thị mô hình: CÁC ĐỐI TƯỢNG, ĐỐI TƯỢNG GIÁ TRỊ, và DỊCH VỤ.

                                                                        Việc xác định các đối tượng nắm bắt khái niệm của miền dường như rất trực quan trên bề mặt, nhưng những thách thức nghiêm trọng đang ẩn mình trong các sắc thái của ý nghĩa. Một số sự phân biệt đã xuất hiện để làm rõ ý nghĩa của các phần tử mô hình và gắn kết với một tập hợp các phương pháp thiết kế nhằm tạo ra các loại đối tượng cụ thể.

                                                                        Một đối tượng có đại diện cho một cái gì đó với sự liên tục và bản sắc—một cái gì đó được theo dõi qua các trạng thái khác nhau hoặc thậm chí qua các triển khai khác nhau không? Hay đó là một thuộc tính mô tả trạng thái của một cái gì khác? Đây là sự phân biệt cơ bản giữa MỘT THỰC THỂ và MỘT ĐỐI TƯỢNG GIÁ TRỊ. Việc xác định các đối tượng một cách rõ ràng tuân theo một kiểu mẫu này hay kiểu mẫu khác làm cho các đối tượng ít mơ hồ hơn và tạo ra con đường đến các lựa chọn cụ thể cho một thiết kế vững chắc.

                                                                        Sau đó, có những khía cạnh của miền mà được thể hiện rõ hơn dưới dạng hành động hoặc thao tác, thay vì dưới dạng đối tượng. Mặc dù đây là một sự lệch nhẹ so với truyền thống mô hình hướng đối tượng, nhưng thường thì tốt nhất là thể hiện những điều này dưới dạng DỊCH VỤ, thay vì bắt buộc một THỰC THỂ hoặc ĐỐI TƯỢNG GIÁ TRỊ phải chịu trách nhiệm cho một thao tác. DỊCH VỤ là điều gì đó được thực hiện cho một khách hàng theo yêu cầu. Trong các lớp kỹ thuật của phần mềm, có nhiều DỊCH VỤ. Chúng cũng xuất hiện trong miền, khi một hoạt động được mô hình hóa tương ứng với điều gì đó mà phần mềm phải làm, nhưng không tương ứng với trạng thái.

                                                                        Có những tình huống không thể tránh khỏi trong đó độ tinh khiết của mô hình đối tượng phải được thoả hiệp, chẳng hạn như khi lưu trữ trong cơ sở dữ liệu quan hệ. Chương này sẽ đưa ra một số hướng dẫn để giữ vững con đường khi bạn buộc phải đối mặt với những thực tế phức tạp này.

                                                                        Cuối cùng, một cuộc thảo luận về CÁC MODULE sẽ nhấn mạnh rằng mỗi quyết định thiết kế nên được động lực bởi một cái nhìn vào miền ứng dụng. Những ý tưởng về độ kết dính cao và độ kết nối thấp, thường được coi là các chỉ số kỹ thuật, có thể được áp dụng cho chính các khái niệm. Trong THIẾT KẾ DỰA TRÊN MÔ HÌNH, CÁC MODULE là một phần của mô hình, và chúng nên phản ánh các khái niệm trong miền ứng dụng.

                                                                        Chương này tập hợp tất cả các khối xây dựng này, mà thể hiện mô hình trong phần mềm. Những ý tưởng này là thông thường, và các thiên kiến về mô hình và thiết kế phát sinh từ chúng đã được viết về trước đây. Nhưng việc đặt chúng trong bối cảnh này sẽ giúp các nhà phát triển tạo ra các thành phần chi tiết phục vụ cho các ưu tiên của thiết kế hướng miền khi giải quyết các vấn đề lớn hơn về mô hình và thiết kế. Ngoài ra, một cảm nhận về các nguyên tắc cơ bản sẽ giúp các nhà phát triển giữ vững định hướng trong bối cảnh các thỏa hiệp không thể tránh khỏi.


                                                                          Associations

                                                                          Sự tương tác giữa mô hình hóa và triển khai đặc biệt phức tạp với các mối liên hệ giữa các đối tượng.

                                                                          Đối với mỗi mối liên kết có thể đi qua trong mô hình, có một cơ chế trong phần mềm với cùng các thuộc tính.

                                                                          Một mô hình thể hiện mối liên hệ giữa một khách hàng và một đại diện bán hàng tương ứng với hai điều. Một mặt, nó trừu tượng hóa một mối quan hệ mà các nhà phát triển coi là quan trọng giữa hai người thật. Mặt khác, nó tương ứng với một con trỏ đối tượng giữa hai đối tượng Java, hoặc một sự đóng gói của một truy vấn cơ sở dữ liệu, hoặc một triển khai tương tự.

                                                                          Ví dụ, một mối quan hệ một-nhiều có thể được triển khai dưới dạng một tập hợp trong một biến thể hiện. Nhưng thiết kế không nhất thiết phải đơn giản như vậy. Có thể không có tập hợp; một phương thức truy cập có thể truy vấn cơ sở dữ liệu để tìm các bản ghi phù hợp và khởi tạo đối tượng dựa trên chúng. Cả hai thiết kế này đều phản ánh cùng một mô hình. Thiết kế phải xác định một cơ chế duyệt cụ thể có hành vi nhất quán với mối quan hệ trong mô hình.

                                                                          Trong thực tế, có rất nhiều mối quan hệ nhiều-nhiều, và một số lượng lớn trong số đó là hai chiều một cách tự nhiên. Điều tương tự cũng xảy ra đối với các hình thức đầu tiên của một mô hình khi chúng ta động não và khám phá lĩnh vực. Nhưng những mối quan hệ chung này làm phức tạp việc triển khai và bảo trì. Hơn nữa, chúng truyền đạt rất ít về bản chất của mối quan hệ.

                                                                          Có ít nhất ba cách để làm cho các liên kết dễ quản lý hơn.

                                                                          1. Áp đặt một chiều di chuyển

                                                                          Thêm một định nghĩa, hiệu quả là giảm bội số.

                                                                          Loại bỏ các mối liên hệ không cần thiết

                                                                          Quan trọng là hạn chế các mối quan hệ càng nhiều càng tốt. Một mối liên kết hai chiều có nghĩa là cả hai đối tượng chỉ có thể được hiểu khi kết hợp với nhau. Khi yêu cầu của ứng dụng không cần phải truy cập theo cả hai hướng, việc thêm một hướng truy cập sẽ giảm sự phụ thuộc lẫn nhau và đơn giản hóa thiết kế. Hiểu biết về miền có thể tiết lộ một xu hướng hướng đi tự nhiên.

                                                                          Hoa Kỳ đã có nhiều tổng thống, giống như nhiều quốc gia khác. Đây là một mối quan hệ song phương, một-nhiều. Tuy nhiên, chúng ta hiếm khi bắt đầu với cái tên "George Washington" và hỏi: "Ông ấy đã là tổng thống của quốc gia nào?" Một cách thực tiễn, chúng ta có thể giảm mối quan hệ này thành một mối quan hệ đơn chiều, có thể truy cập từ quốc gia đến tổng thống. Sự tinh chỉnh này thực sự phản ánh hiểu biết về miền, cũng như tạo ra một thiết kế thực tiễn hơn. Nó ghi lại sự hiểu biết rằng một chiều của mối quan hệ này có ý nghĩa và tầm quan trọng hơn nhiều so với chiều kia. Nó giữ cho lớp "Người" độc lập với khái niệm "Tổng thống" kém cơ bản hơn nhiều.

                                                                          Figure 5.1. Some traversal directions reflect a natural bias in the domain.

                                                                          graphics/05fig01.gif

                                                                          Rất thường xuyên, sự hiểu biết sâu sắc dẫn đến một mối quan hệ "được xác định". Khi nhìn sâu vào các tổng thống, chúng ta nhận ra rằng (trừ trong một cuộc nội chiến, có thể) một đất nước chỉ có một tổng thống tại một thời điểm. Điều này giảm thiểu sự đa dạng xuống còn một-một và rõ ràng đã nhúng một quy tắc quan trọng vào mô hình. Ai là tổng thống của Hoa Kỳ vào năm 1790? George Washington.

                                                                          Figure 5.2. Constrained associations communicate more knowledge and are more practical designs.

                                                                          graphics/05fig02.gif

                                                                          Việc ràng buộc hướng duyệt của một mối quan hệ nhiều-nhiều thực sự làm giảm việc triển khai của nó thành một-một nhiều - một thiết kế dễ dàng hơn nhiều.

                                                                          Cách thức liên tục ràng buộc các mối liên hệ theo những cách phản ánh thành kiến của miền không chỉ khiến những mối liên hệ đó trở nên giao tiếp hơn và dễ thực hiện hơn, mà còn mang lại ý nghĩa cho các mối liên hệ hai chiều còn lại. Khi tính hai chiều của một mối quan hệ là một đặc điểm ngữ nghĩa của miền, khi nó cần thiết cho chức năng ứng dụng, việc giữ lại cả hai hướng truy cập cho thấy điều đó.

                                                                          Tất nhiên, sự đơn giản hóa tối ưu là loại bỏ một mối liên hệ hoàn toàn, nếu nó không thiết yếu cho công việc hiện tại hoặc ý nghĩa cơ bản của các đối tượng mô hình.

                                                                          Example
                                                                          Associations in a Brokerage Account

                                                                          Figure 5.3.

                                                                          graphics/05fig03.gif

                                                                          Một triển khai Java của Tài khoản Môi giới trong mô hình này sẽ là

                                                                          public class BrokerageAccount { String accountNumber; Customer customer; Set investments; // Constructors, etc. omitted public Customer getCustomer() { return customer; } public Set getInvestments() { return investments; } } 

                                                                          Nhưng nếu chúng ta cần lấy dữ liệu từ cơ sở dữ liệu quan hệ, một triển khai khác, cũng nhất quán với mô hình, sẽ là như sau:

                                                                          BẢNG: TÀI KHOẢN MÔ GIỚI

                                                                          SỐ_TÀI_KHOẢN

                                                                          SỐ_BẰNG_LÁI_KHÁCH_HÀNG

                                                                          Bảng: KHÁCH HÀNG

                                                                          Số an sinh xã hội

                                                                          TÊN

                                                                          Bảng: ĐẦU TƯ

                                                                          SỐ_TÍNH_KHOẢN

                                                                          MÃ CỔ PHIẾU

                                                                          SỐ TIỀN

                                                                          public class BrokerageAccount { String accountNumber; String customerSocialSecurityNumber; // Omit constructors, etc. public Customer getCustomer() { String sqlQuery = "SELECT * FROM CUSTOMER WHERE" + "SS_NUMBER='"+customerSocialSecurityNumber+"'"; return QueryService.findSingleCustomerFor(sqlQuery); } public Set getInvestments() { String sqlQuery = "SELECT * FROM INVESTMENT WHERE" + "BROKERAGE_ACCOUNT='"+accountNumber+"'"; return QueryService.findInvestmentsFor(sqlQuery); } } 

                                                                          (Lưu ý: QueryService, một công cụ để lấy các hàng từ cơ sở dữ liệu và tạo đối tượng, rất đơn giản cho việc giải thích các ví dụ, nhưng không nhất thiết là một thiết kế tốt cho một dự án thực sự.)

                                                                          Hãy tinh chỉnh mô hình bằng cách xác định mối quan hệ giữa Tài khoản Môi giới và Đầu tư, giảm bớt sự đa trị của nó. Điều này có nghĩa là chỉ có một khoản đầu tư cho mỗi cổ phiếu.

                                                                          Figure 5.4.

                                                                          graphics/05fig04.gif

                                                                          Điều này sẽ không đúng cho tất cả các tình huống kinh doanh (ví dụ, nếu các lô hàng cần được theo dõi), nhưng bất kể các quy tắc cụ thể nào, khi các hạn chế về các mối quan hệ được phát hiện, chúng nên được đưa vào mô hình và triển khai. Chúng làm cho mô hình chính xác hơn và việc triển khai dễ dàng bảo trì hơn.

                                                                          Cài đặt Java có thể trở thành:

                                                                          public class BrokerageAccount { String accountNumber; Customer customer; Map investments; // Omitting constructors, etc. public Customer getCustomer() { return customer; } public Investment getInvestment(String stockSymbol) { return (Investment)investments.get(stockSymbol); } } 

                                                                          Và một triển khai dựa trên SQL sẽ là:

                                                                          public class BrokerageAccount { String accountNumber; String customerSocialSecurityNumber; //Omitting constructors, etc. public Customer getCustomer() { String sqlQuery = "SELECT * FROM CUSTOMER WHERE SS_NUMBER='" + customerSocialSecurityNumber + "'"; return QueryService.findSingleCustomerFor(sqlQuery); } public Investment getInvestment(String stockSymbol) { String sqlQuery = "SELECT * FROM INVESTMENT " + "WHERE BROKERAGE_ACCOUNT='" + accountNumber + "'" + "AND STOCK_SYMBOL='" + stockSymbol +"'"; return QueryService.findInvestmentFor(sqlQuery); } } 

                                                                          Cẩn thận chắt lọc và giới hạn những mối liên hệ của mô hình sẽ giúp bạn tiến xa trong việc thiết kế theo mô hình. Bây giờ hãy quay sang các đối tượng tự chúng. Một số sự phân biệt sẽ làm rõ hơn mô hình trong khi vẫn tạo điều kiện cho một việc triển khai thực tiễn hơn.


                                                                            Entities (a.k.a. Reference Objects)

                                                                            graphics/05inf01.gif

                                                                            Nhiều đối tượng không được định nghĩa một cách cơ bản bởi những đặc tính của chúng, mà thay vào đó bởi một sợi chỉ liên tục và danh tính.

                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                            Một bà chủ nhà đã kiện tôi, cáo buộc tôi gây thiệt hại lớn cho tài sản của bà. Các giấy tờ mà tôi nhận được mô tả một căn hộ với những lỗ hổng trên tường, vết bẩn trên thảm, và một chất lỏng độc hại trong bồn rửa bát gây ra hơi caustic khiến giấy dán tường trong bếp bị bong tróc. Các tài liệu của tòa án đã chỉ định tôi là người thuê nhà chịu trách nhiệm cho những thiệt hại, xác định tôi bằng tên và địa chỉ hiện tại của tôi vào thời điểm đó. Điều này khiến tôi bối rối, vì tôi thậm chí chưa bao giờ đặt chân đến nơi hư hại đó.

                                                                            Sau một lúc, tôi nhận ra rằng đây chắc hẳn là một trường hợp nhầm danh tính. Tôi đã gọi cho nguyên đơn và nói với cô ấy điều này, nhưng cô ấy không tin tôi. Người thuê cũ đã trốn tránh cô ấy suốt vài tháng. Làm thế nào tôi có thể chứng minh rằng tôi không phải là người đã khiến cô ấy mất quá nhiều tiền? Tôi là Eric Evans duy nhất trong danh bạ điện thoại.

                                                                            Chà, cuốn sách điện thoại đã trở thành cứu cánh của tôi. Bởi vì tôi đã sống trong cùng một căn hộ suốt hai năm, tôi đã hỏi cô ấy liệu cô ấy có còn cuốn sách của năm trước không. Sau khi cô ấy tìm thấy và xác minh rằng thông tin của tôi vẫn giống như trước (ngay bên cạnh thông tin của người cùng tên với tôi), cô ấy nhận ra rằng tôi không phải là người mà cô ấy muốn kiện, đã xin lỗi và hứa sẽ bỏ vụ kiện.

                                                                            Máy tính không phải là nguồn tài nguyên phong phú. Một trường hợp nhận diện sai trong một hệ thống phần mềm dẫn đến sự hỏng dữ liệu và lỗi chương trình.

                                                                            Có những thách thức kỹ thuật đặc biệt ở đây, mà tôi sẽ thảo luận sau, nhưng trước tiên hãy xem xét vấn đề cơ bản: Nhiều thứ được xác định bởi danh tính của chúng, chứ không phải bởi bất kỳ thuộc tính nào. Trong quan niệm điển hình của chúng ta, một người (để tiếp tục với ví dụ không kỹ thuật) có một danh tính kéo dài từ khi sinh ra cho đến khi chết và thậm chí còn hơn thế. Những thuộc tính vật lý của người đó biến đổi và cuối cùng biến mất. Tên có thể thay đổi. Các mối quan hệ tài chính đến và đi. Không có bất kỳ thuộc tính nào của một người không thể thay đổi; thế nhưng danh tính vẫn tồn tại. Tôi có phải là cùng một người như khi tôi năm tuổi hay không? Câu hỏi siêu hình dạng này quan trọng trong việc tìm kiếm các mô hình miền hiệu quả. Nói cách khác: Người sử dụng ứng dụng có quan tâm nếu tôi là cùng một người như khi tôi năm tuổi không?

                                                                            Trong một hệ thống phần mềm theo dõi các tài khoản đến hạn, đối tượng "khách hàng" khiêm tốn đó có thể có một khía cạnh sinh động hơn. Nó tích lũy trạng thái bằng cách thanh toán kịp thời hoặc được chuyển cho một cơ quan thu hồi nợ vì không thanh toán. Nó có thể sống một cuộc sống kép trong một hệ thống hoàn toàn khác khi đội ngũ bán hàng trích xuất dữ liệu khách hàng vào phần mềm quản lý liên hệ của mình. Trong mọi trường hợp, nó bị nén xuống một cách không trang trọng để được lưu trữ trong một bảng cơ sở dữ liệu. Khi nguồn kinh doanh mới ngừng chảy ra từ nguồn đó, đối tượng khách hàng sẽ được chuyển vào kho lưu trữ, trở thành cái bóng của chính nó trong quá khứ.

                                                                            Mỗi hình thức của khách hàng này là một triển khai khác nhau dựa trên một ngôn ngữ lập trình và công nghệ khác nhau. Nhưng khi có một cuộc gọi đến với đơn đặt hàng, điều quan trọng là biết: Đây có phải là khách hàng đang có tài khoản quá hạn không? Đây có phải là khách hàng mà Jack (một đại diện bán hàng cụ thể) đã làm việc trong nhiều tuần không? Đây có phải là một khách hàng hoàn toàn mới không?

                                                                            Một danh tính khái niệm phải được ghép nối giữa nhiều phiên bản của các đối tượng, các hình thức được lưu trữ của chúng, và các tác nhân trong thực tế như người gọi điện thoại. Các thuộc tính có thể không khớp. Một đại diện bán hàng có thể đã nhập một cập nhật địa chỉ vào phần mềm liên lạc, mà hiện đang được truyền đi cho các tài khoản đến hạn. Hai liên hệ khách hàng có thể có cùng tên. Trong phần mềm phân tán, nhiều người dùng có thể đang nhập dữ liệu từ các nguồn khác nhau, dẫn đến các giao dịch cập nhật được truyền qua hệ thống để được đối chiếu trong các cơ sở dữ liệu khác nhau một cách không đồng bộ.

                                                                            Mô hình đối tượng thường khiến chúng ta tập trung vào các thuộc tính của một đối tượng, nhưng khái niệm cơ bản về MỘT THỰC THỂ là một sự liên tục trừu tượng xuyên suốt một vòng đời và thậm chí trải qua nhiều hình thức khác nhau.

                                                                            Một số đối tượng không được định nghĩa chủ yếu bởi các thuộc tính của chúng. Chúng đại diện cho một chỉ dẫn về bản sắc kéo dài qua thời gian và thường xuyên qua các đại diện khác nhau. Đôi khi, một đối tượng như vậy phải được ghép nối với một đối tượng khác mặc dù các thuộc tính khác nhau. Một đối tượng phải được phân biệt với các đối tượng khác mặc dù chúng có thể có cùng thuộc tính. Nhận diện sai có thể dẫn đến việc làm hỏng dữ liệu.

                                                                            Một đối tượng được xác định chủ yếu bởi danh tính của nó được gọi là THỰC THỂ. CÁC THỰC THỂ có những cân nhắc đặc biệt về mô hình hóa và thiết kế. Chúng có chu kỳ sống có thể thay đổi hình thức và nội dung của chúng một cách đáng kể, nhưng một sợi chỉ liên tục phải được duy trì. Danh tính của chúng phải được xác định để có thể theo dõi hiệu quả. Các định nghĩa lớp, trách nhiệm, thuộc tính và mối quan hệ của chúng nên xoay quanh ai mà chúng là, thay vì thuộc tính cụ thể mà chúng mang theo. Ngay cả đối với CÁC THỰC THỂ không biến đổi quá đáng kể hoặc có chu kỳ sống phức tạp như vậy, việc đặt chúng vào danh mục ngữ nghĩa dẫn đến các mô hình rõ ràng hơn và các triển khai mạnh mẽ hơn.

                                                                            Một mô hình ENTITY không giống như "entity bean" trong Java. Entity bean được tạo ra như một khuôn khổ để triển khai các ENTITY, hơn hoặc kém, nhưng thực tế thì không diễn ra như vậy. Hầu hết các ENTITY được triển khai như những đối tượng bình thường. Bất kể chúng được triển khai như thế nào, ENTITY là một sự phân biệt cơ bản trong mô hình miền.

                                                                            Tất nhiên, hầu hết các "THỰC THỂ" trong một hệ thống phần mềm không phải là người hoặc thực thể theo nghĩa thông thường của từ này. Một THỰC THỂ là bất cứ điều gì có sự liên tục qua một vòng đời và các đặc điểm độc lập với các thuộc tính quan trọng đối với người sử dụng ứng dụng. Nó có thể là một người, một thành phố, một chiếc xe, một tờ vé số, hoặc một giao dịch ngân hàng.

                                                                            Mặt khác, không phải tất cả các đối tượng trong mô hình đều là CÁC THỰC THỂ với bản sắc có ý nghĩa. Vấn đề này trở nên phức tạp bởi thực tế rằng các ngôn ngữ lập trình hướng đối tượng xây dựng các thao tác "bản sắc" vào từng đối tượng (ví dụ, toán tử "==" trong Java). Những thao tác này xác định xem hai tham chiếu có trỏ đến cùng một đối tượng hay không bằng cách so sánh vị trí của chúng trong bộ nhớ hoặc bằng một cơ chế khác. Theo nghĩa này, mỗi thể hiện đối tượng đều có bản sắc. Trong miền, hãy nói, tạo ra một môi trường chạy Java hoặc một khuôn khổ kỹ thuật để lưu trữ các đối tượng từ xa tại chỗ, mỗi thể hiện đối tượng thực sự có thể là một THỰC THỂ. Nhưng cơ chế bản sắc này có nghĩa rất ít trong các miền ứng dụng khác. Bản sắc là một thuộc tính tinh vi và có ý nghĩa của CÁC THỰC THỂ, không thể chuyển giao cho các tính năng tự động của ngôn ngữ.

                                                                            Xem xét các giao dịch trong một ứng dụng ngân hàng. Hai khoản tiền gửi cùng một số tiền vào cùng một tài khoản trong cùng một ngày vẫn là những giao dịch riêng biệt, vì vậy chúng có danh tính và là CÁC THỰC THỂ. Mặt khác, thuộc tính số tiền của hai giao dịch đó có thể là các thực thể của một đối tượng tiền. Các giá trị này không có danh tính, vì không có ích lợi gì trong việc phân biệt chúng. Thực tế, hai đối tượng có thể có cùng một danh tính mà không cần có cùng thuộc tính hoặc thậm chí, không nhất thiết phải thuộc cùng một lớp. Khi khách hàng ngân hàng đối chiếu các giao dịch trong sao kê ngân hàng với các giao dịch trong sổ check, nhiệm vụ là, cụ thể, để khớp các giao dịch có cùng danh tính, mặc dù chúng được ghi lại bởi những người khác nhau vào những ngày khác nhau (ngày thanh toán của ngân hàng muộn hơn ngày ghi trên check). Mục đích của số check là để phục vụ như một định danh duy nhất cho mục đích này, cho dù vấn đề đang được xử lý bởi một chương trình máy tính hay bằng tay. Các khoản tiền gửi và rút tiền mặt, không có số định danh, có thể phức tạp hơn, nhưng nguyên tắc tương tự vẫn áp dụng: mỗi giao dịch là một THỰC THỂ, xuất hiện dưới ít nhất hai hình thức.

                                                                            Thường thì danh tính có ý nghĩa quan trọng ngoài một hệ thống phần mềm cụ thể, như trường hợp của các giao dịch ngân hàng và người thuê căn hộ. Nhưng đôi khi, danh tính chỉ quan trọng trong bối cảnh của hệ thống, chẳng hạn như danh tính của một quá trình máy tính.

                                                                            Do đó:

                                                                            Khi một đối tượng được phân biệt bởi danh tính của nó, thay vì thuộc tính của nó, hãy làm điều này trở thành yếu tố chính trong định nghĩa của nó trong mô hình. Giữ cho định nghĩa lớp đơn giản và tập trung vào sự liên tục trong vòng đời và danh tính. Định nghĩa một phương tiện để phân biệt mỗi đối tượng bất kể hình thức hoặc lịch sử của nó. Hãy chú ý đến các yêu cầu mà yêu cầu khớp các đối tượng bằng thuộc tính. Định nghĩa một phép toán được đảm bảo sẽ sản xuất một kết quả duy nhất cho mỗi đối tượng, có thể bằng cách đính kèm một ký hiệu được đảm bảo là duy nhất. Phương tiện xác định này có thể đến từ bên ngoài, hoặc có thể là một định danh tùy ý được tạo ra bởi và cho hệ thống, nhưng nó phải tương ứng với các phân biệt danh tính trong mô hình. Mô hình phải định nghĩa ý nghĩa của việc là cùng một thứ.

                                                                            Danh tính không phải là bản chất vốn có của một thứ trong thế giới; nó là một ý nghĩa được chồng lên vì nó hữu ích. Thực tế, cùng một sự vật trong thế giới thực có thể hoặc không thể được biểu diễn dưới dạng MỘT THỰC THỂ trong mô hình miền.

                                                                            Một ứng dụng để đặt chỗ ngồi trong một sân vận động có thể coi chỗ ngồi và người tham dự là CÁC THỰC THỂ. Trong trường hợp có chỗ ngồi được chỉ định, trong đó mỗi vé có số chỗ ngồi trên đó, chỗ ngồi là một THỰC THỂ. Định danh của nó là số chỗ ngồi, điều này là duy nhất trong sân vận động. Chỗ ngồi có thể có nhiều thuộc tính khác, chẳng hạn như vị trí của nó, liệu tầm nhìn có bị cản trở hay không, và giá cả, nhưng chỉ số chỗ ngồi, hoặc một hàng và vị trí duy nhất, được sử dụng để xác định và phân biệt các chỗ ngồi.

                                                                            Mặt khác, nếu sự kiện là "vào cửa tự do", có nghĩa là những người giữ vé ngồi ở bất kỳ chỗ nào họ tìm thấy ghế trống, thì không cần phân biệt các chỗ ngồi riêng lẻ. Chỉ có tổng số ghế là quan trọng. Mặc dù số ghế vẫn được khắc trên các ghế vật lý, nhưng phần mềm không cần phải theo dõi chúng. Trên thực tế, sẽ là sai lầm nếu mô hình liên kết các số ghế cụ thể với vé, vì không có ràng buộc nào như vậy tại sự kiện vào cửa tự do. Trong trường hợp này, các chỗ ngồi không phải là THỰC THỂ, và không cần định danh nào.

                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                            Modeling ENTITIES

                                                                            Thật tự nhiên để suy nghĩ về các thuộc tính khi mô hình hóa một đối tượng, và cũng rất quan trọng để suy nghĩ về hành vi của nó. Nhưng trách nhiệm cơ bản nhất của CÁC THỰC THỂ là thiết lập sự liên tục để hành vi có thể rõ ràng và dự đoán được. Chúng thực hiện điều này tốt nhất nếu được giữ đơn giản. Thay vì tập trung vào các thuộc tính hoặc thậm chí hành vi, hãy làm giảm định nghĩa của đối tượng CÁC THỰC THỂ xuống những đặc điểm nội tại nhất, đặc biệt là những đặc điểm xác định nó hoặc thường được sử dụng để tìm kiếm hoặc khớp với nó. Chỉ thêm hành vi cần thiết cho khái niệm và các thuộc tính cần thiết cho hành vi đó. Ngoài ra, hãy tìm cách loại bỏ hành vi và thuộc tính sang các đối tượng khác liên quan đến CÁC THỰC THỂ cốt lõi. Một số trong số này sẽ là các CÁC THỰC THỂ khác. Một số sẽ là CÁC ĐỐI TƯỢNG GIÁ TRỊ, đây là mẫu tiếp theo trong chương này. Ngoài các vấn đề về danh tính, CÁC THỰC THỂ thường hoàn thành trách nhiệm của chúng bằng cách phối hợp các hoạt động của các đối tượng mà chúng sở hữu.

                                                                            Mã khách hàng là một và chỉ một định danh của THỰC THỂ Khách Hàng trong Hình 5.5, nhưng số điện thoại và địa chỉ thường được sử dụng để tìm hoặc khớp một Khách Hàng. Tên không xác định danh tính của một người, nhưng thường được sử dụng như một phần trong việc xác định danh tính đó. Trong ví dụ này, các thuộc tính số điện thoại và địa chỉ đã được chuyển vào Khách Hàng, nhưng trong một dự án thực tế, lựa chọn đó sẽ phụ thuộc vào cách mà khách hàng trong miền thường được khớp hoặc phân biệt. Ví dụ, nếu một Khách Hàng có nhiều số điện thoại liên hệ cho các mục đích khác nhau, thì số điện thoại đó không liên quan đến danh tính và nên được giữ lại với Liên Hệ Bán Hàng.

                                                                            Figure 5.5. Attributes associated with identity stay with the ENTITY.

                                                                            graphics/05fig05.gif

                                                                            Designing the Identity Operation

                                                                            Mỗi ENTITY phải có một phương thức hoạt động để xác định danh tính của nó với một đối tượng khác—phân biệt ngay cả với một đối tượng khác có các thuộc tính mô tả giống nhau. Một thuộc tính nhận dạng phải được đảm bảo là duy nhất trong hệ thống, bất kể cách mà hệ thống đó được định nghĩa—kể cả khi phân tán, kể cả khi các đối tượng được lưu trữ.

                                                                            Như đã đề cập trước đó, các ngôn ngữ lập trình hướng đối tượng có các phép toán "định danh" để xác định xem hai tham chiếu có trỏ đến cùng một đối tượng hay không bằng cách so sánh vị trí của các đối tượng trong bộ nhớ. Loại theo dõi định danh này quá mong manh cho mục đích của chúng tôi. Trong hầu hết các công nghệ lưu trữ bền vững cho các đối tượng, mỗi khi một đối tượng được truy xuất từ cơ sở dữ liệu, một phiên bản mới được tạo ra, do đó, định danh ban đầu bị mất. Mỗi khi một đối tượng được truyền qua mạng, một phiên bản mới được tạo ra ở điểm đến, và một lần nữa định danh bị mất. Vấn đề có thể càng tồi tệ hơn khi có nhiều phiên bản của cùng một đối tượng tồn tại trong hệ thống, chẳng hạn như khi các cập nhật lan truyền qua một cơ sở dữ liệu phân tán.

                                                                            Ngay cả với các khung công tác đơn giản hóa những vấn đề kỹ thuật này, vấn đề cơ bản vẫn tồn tại: Làm thế nào bạn biết rằng hai đối tượng đại diện cho cùng một THỰC THỂ khái niệm? Định nghĩa về danh tính phát sinh từ mô hình. Việc định nghĩa danh tính đòi hỏi phải hiểu biết về miền.

                                                                            Đôi khi, một số thuộc tính dữ liệu hoặc sự kết hợp của các thuộc tính có thể được đảm bảo hoặc chỉ đơn giản là bị giới hạn để trở nên duy nhất trong hệ thống. Cách tiếp cận này cung cấp một khóa duy nhất cho THỰC THỂ. Ví dụ, các tờ báo hàng ngày có thể được xác định bằng tên của tờ báo, thành phố và ngày xuất bản. (Nhưng hãy cẩn thận với các ấn phẩm đặc biệt và sự thay đổi tên!)

                                                                            Khi không có khóa duy nhất thực sự được tạo thành từ các thuộc tính của một đối tượng, một giải pháp phổ biến khác là gán cho mỗi phiên bản một ký hiệu (chẳng hạn như một số hoặc một chuỗi) duy nhất trong lớp. Khi ký hiệu ID này được tạo ra và lưu trữ như một thuộc tính của ENTITY, nó được chỉ định là bất biến. Nó không bao giờ được thay đổi, ngay cả khi hệ thống phát triển không thể trực tiếp thực thi quy tắc này. Ví dụ, thuộc tính ID được bảo tồn khi đối tượng được làm phẳng vào cơ sở dữ liệu và được tái tạo. Đôi khi, một khung kỹ thuật giúp với quy trình này, nhưng nếu không, nó chỉ đòi hỏi kỷ luật kỹ thuật.

                                                                            Thường thì ID được tạo ra tự động bởi hệ thống. Thuật toán tạo ID phải đảm bảo tính duy nhất trong hệ thống, điều này có thể là một thách thức với việc xử lý đồng thời và trong các hệ thống phân tán. Việc tạo ra một ID như vậy có thể yêu cầu các kỹ thuật vượt quá phạm vi của cuốn sách này. Mục tiêu ở đây là nêu bật khi nào những xem xét này phát sinh, để các nhà phát triển nhận thức rằng họ có một vấn đề cần giải quyết và biết cách thu hẹp mối quan tâm của họ vào những lĩnh vực quan trọng. Chìa khóa là nhận ra rằng các mối quan tâm về danh tính phụ thuộc vào những khía cạnh cụ thể của mô hình. Thường thì, các phương tiện nhận diện đòi hỏi một nghiên cứu cẩn thận về miền công việc.

                                                                            Khi ID được tự động tạo ra, người dùng có thể không bao giờ cần nhìn thấy nó. ID có thể chỉ cần thiết cho các mục đích nội bộ, chẳng hạn như trong một ứng dụng quản lý liên hệ cho phép người dùng tìm kiếm các bản ghi theo tên của một người. Chương trình cần phải có khả năng phân biệt hai liên hệ có cùng tên một cách đơn giản và không mập mờ. Các ID duy nhất và nội bộ cho phép hệ thống làm điều đó. Sau khi lấy hai mục khác nhau, hệ thống sẽ hiển thị hai liên hệ riêng biệt cho người dùng, nhưng các ID có thể không được hiển thị. Người dùng sẽ phân biệt chúng dựa trên công ty của họ, địa điểm của họ, và những thông tin tương tự khác.

                                                                            Cuối cùng, có những trường hợp mà một ID được tạo ra là điều mà người dùng quan tâm. Khi tôi gửi một gói hàng qua dịch vụ giao hàng, tôi được cung cấp một số theo dõi, được tạo ra bởi phần mềm của công ty vận chuyển, mà tôi có thể sử dụng để xác định và theo dõi gói hàng của mình. Khi tôi đặt vé máy bay hoặc đặt phòng khách sạn, tôi nhận được các số xác nhận là những định danh duy nhất cho giao dịch.

                                                                            Trong một số trường hợp, tính duy nhất của mã ID phải áp dụng vượt ra ngoài ranh giới của hệ thống máy tính. Ví dụ, nếu hồ sơ y tế được trao đổi giữa hai bệnh viện có hệ thống máy tính riêng biệt, lý tưởng là mỗi hệ thống sẽ sử dụng cùng một ID bệnh nhân, nhưng điều này rất khó khăn nếu họ tự tạo ra mã riêng. Các hệ thống như vậy thường sử dụng một mã định danh do một tổ chức khác phát hành, thường là một cơ quan chính phủ. Tại Hoa Kỳ, số An sinh xã hội thường được các bệnh viện sử dụng làm mã định danh cho một người. Tuy nhiên, những phương pháp này không hoàn hảo. Không phải ai cũng có số An sinh xã hội (trẻ em và người không cư trú tại Hoa Kỳ, đặc biệt), và nhiều người phản đối việc sử dụng nó vì lý do riêng tư.

                                                                            Trong các tình huống kém formal hơn (chẳng hạn như rental video), số điện thoại được sử dụng như là các định danh. Nhưng một chiếc điện thoại có thể được chia sẻ. Số có thể thay đổi. Một số cũ thậm chí có thể được chuyển giao cho một người khác.

                                                                            Vì những lý do này, các mã nhận dạng được gán riêng thường được sử dụng (chẳng hạn như số thẻ bay thường xuyên), và các thuộc tính khác, như số điện thoại và số an sinh xã hội, được sử dụng để đối chiếu và xác minh. Trong bất kỳ trường hợp nào, khi ứng dụng yêu cầu một ID bên ngoài, người dùng của hệ thống trở nên có trách nhiệm cung cấp các ID duy nhất, và hệ thống phải cung cấp cho họ đủ công cụ để xử lý các trường hợp ngoại lệ phát sinh.

                                                                            Xét tất cả những vấn đề kỹ thuật này, thật dễ để mất đi cái nhìn về vấn đề khái niệm cơ bản: Điều gì có nghĩa rằng hai đối tượng là cùng một thứ? Thật dễ dàng để gán mỗi đối tượng với một ID, hoặc để viết một phép so sánh hai thể hiện, nhưng nếu những ID hoặc phép so sánh này không tương ứng với một sự phân biệt có ý nghĩa trong lĩnh vực, chúng chỉ làm rối thêm vấn đề. Đó là lý do tại sao các phép gán danh tính thường liên quan đến đầu vào của con người. Phần mềm đối chiếu sổ ngân hàng, chẳng hạn, có thể đưa ra những kết quả tương tự nhưng người dùng được mong đợi sẽ đưa ra quyết định cuối cùng.


                                                                              Value Objects

                                                                              graphics/05inf02.jpg

                                                                              Nhiều đối tượng không có bản sắc khái niệm. Những đối tượng này mô tả một số đặc điểm của một thứ.

                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                              Khi một đứa trẻ đang vẽ, nó quan tâm đến màu sắc của bút đánh dấu mà nó chọn, và có thể nó cũng quan tâm đến độ sắc nét của đầu bút. Nhưng nếu có hai bút đánh dấu cùng màu và hình dạng, có lẽ nó sẽ không quan tâm đến việc sử dụng bút nào. Nếu một bút bị mất và được thay thế bằng một bút khác cùng màu từ một gói mới, nó có thể tiếp tục công việc của mình mà không lo lắng về sự thay đổi.

                                                                              Hãy hỏi đứa trẻ về những bức tranh khác nhau trên tủ lạnh, và nó sẽ nhanh chóng phân biệt những cái mà nó vẽ với những cái mà chị gái nó vẽ. Nó và chị gái có những bản sắc hữu ích, cũng như những bức tranh hoàn thành của họ. Nhưng hãy tưởng tượng sẽ phức tạp như thế nào nếu nó phải theo dõi những đường nét nào trong bức tranh được tạo ra bởi mỗi cây bút. Việc vẽ sẽ không còn là trò chơi trẻ con nữa.

                                                                              Bởi vì những đối tượng nổi bật nhất trong một mô hình thường là CÁC THỰC THỂ, và vì việc theo dõi danh tính của từng THỰC THỂ là rất quan trọng, nên việc xem xét việc gán một danh tính cho tất cả các đối tượng trong miền là điều tự nhiên. Thực tế, một số framework gán một ID duy nhất cho mỗi đối tượng.

                                                                              Hệ thống phải đối phó với tất cả việc theo dõi, và nhiều tối ưu hóa hiệu suất khả thi bị loại trừ. Nỗ lực phân tích là cần thiết để xác định các danh tính có ý nghĩa và tìm ra những cách đáng tin cậy để theo dõi các đối tượng qua các hệ thống phân tán hoặc trong lưu trữ cơ sở dữ liệu. Quan trọng không kém, việc tiếp nhận các danh tính giả tạo là sai lầm. Điều này làm rối loạn mô hình, ép tất cả các đối tượng vào cùng một khuôn mẫu.

                                                                              Theo dõi danh tính của CÁ THỂ là rất quan trọng, nhưng gán danh tính cho các đối tượng khác có thể làm giảm hiệu suất của hệ thống, tăng khối lượng công việc phân tích và làm rối mô hình bằng cách khiến tất cả các đối tượng trông giống nhau.

                                                                              Thiết kế phần mềm là một cuộc chiến liên tục với độ phức tạp. Chúng ta phải tạo ra sự phân biệt để việc xử lý đặc biệt chỉ được áp dụng ở những nơi cần thiết.

                                                                              Tuy nhiên, nếu chúng ta nghĩ về danh mục đối tượng này chỉ là sự thiếu vắng danh tính, chúng ta không bổ sung được nhiều cho bộ công cụ hoặc từ vựng của mình. Thực tế, những đối tượng này có những đặc điểm riêng và ý nghĩa riêng trong mô hình. Đây là những đối tượng mô tả các sự vật.

                                                                              Một đối tượng đại diện cho khía cạnh mô tả của miền mà không có bản sắc khái niệm được gọi là ĐỐI TƯỢNG GIÁ TRỊ. ĐỐI TƯỢNG GIÁ TRỊ được khởi tạo để đại diện cho các yếu tố trong thiết kế mà chúng ta chỉ quan tâm đến chúng là gì, chứ không phải là ai hoặc cái nào.


                                                                              Is "Address" a VALUE OBJECT? Who's Asking?

                                                                              Trong phần mềm cho một công ty đặt hàng qua bưu điện, cần có một địa chỉ để xác nhận thẻ tín dụng và để ghi nhãn cho bưu phẩm. Nhưng nếu một bạn cùng phòng cũng đặt hàng từ công ty đó, thì không quan trọng việc nhận ra họ ở cùng một vị trí. Địa chỉ là một ĐỐI TƯỢNG GIÁ TRỊ.

                                                                              Trong phần mềm cho dịch vụ bưu chính, nhằm tổ chức các tuyến giao hàng, quốc gia có thể được hình thành thành một hệ thống phân cấp gồm các vùng, thành phố, khu vực bưu chính và các khối, kết thúc bằng các địa chỉ cá nhân. Các đối tượng địa chỉ này sẽ lấy mã bưu chính từ cấp cha trong hệ thống phân cấp, và nếu dịch vụ bưu chính quyết định điều chỉnh lại các khu vực bưu chính, tất cả các địa chỉ bên trong sẽ theo cùng. Ở đây, Địa chỉ là một THỰC THỂ.

                                                                              Trong phần mềm cho một công ty điện lực, một địa chỉ tương ứng với một điểm đến cho các đường dây và dịch vụ của công ty. Nếu từng bạn cùng phòng gọi điện để đặt dịch vụ điện, công ty sẽ cần nhận ra điều đó. Địa chỉ là một THỰC THỂ. Ngoài ra, mô hình có thể liên kết dịch vụ tiện ích với một "nơi ở," một THỰC THỂ có thuộc tính là địa chỉ. Khi đó, Địa chỉ sẽ là một ĐỐI TƯỢNG GIÁ TRỊ.

                                                                              Màu sắc là một ví dụ về ĐỐI TƯỢNG GIÁ TRỊ được cung cấp trong các thư viện cơ bản của nhiều hệ thống phát triển hiện đại; chuỗi và số cũng vậy. (Bạn không quan tâm bạn có "4" nào hay "Q" nào.) Những ví dụ cơ bản này thì đơn giản, nhưng ĐỐI TƯỢNG GIÁ TRỊ không nhất thiết phải đơn giản. Ví dụ, một chương trình pha trộn màu sắc có thể có một mô hình phong phú trong đó các đối tượng màu sắc nâng cao có thể được kết hợp để tạo ra các màu khác. Những màu sắc này có thể có các thuật toán phức tạp để hợp tác nhằm tạo ra ĐỐI TƯỢNG GIÁ TRỊ mới.

                                                                              MỘT ĐỐI TƯỢNG GIÁ TRỊ có thể là một tập hợp của các đối tượng khác. Trong phần mềm thiết kế kế hoạch nhà, một đối tượng có thể được tạo ra cho mỗi kiểu cửa sổ. "Kiểu cửa sổ" này có thể được đưa vào một đối tượng "cửa sổ", cùng với chiều cao và chiều rộng, cũng như các quy tắc điều chỉnh cách những thuộc tính này có thể được thay đổi và kết hợp. Những cửa sổ này là những ĐỐI TƯỢNG GIÁ TRỊ phức tạp được tạo thành từ các ĐỐI TƯỢNG GIÁ TRỊ khác. Chúng lại được đưa vào các yếu tố lớn hơn của một kế hoạch, chẳng hạn như các đối tượng "tường".

                                                                              CÁC ĐỐI TƯỢNG GIÁ TRỊ thậm chí có thể tham chiếu đến CÁC THỰC THỂ. Ví dụ, nếu tôi yêu cầu một dịch vụ bản đồ trực tuyến về một lộ trình chạy xe phong cảnh từ San Francisco đến Los Angeles, nó có thể tạo ra một đối tượng Lộ trình liên kết L.A. và San Francisco qua Đường bờ biển Thái Bình Dương. Đối tượng Lộ trình đó sẽ là một GIÁ TRỊ, mặc dù ba đối tượng mà nó tham chiếu (hai thành phố và một con đường) đều là CÁC THỰC THỂ.

                                                                              CÁC ĐỐI TƯỢNG GIÁ TRỊ thường được truyền dưới dạng tham số trong các thông điệp giữa các đối tượng. Chúng thường là tạm thời, được tạo ra cho một thao tác và sau đó bị bỏ đi. CÁC ĐỐI TƯỢNG GIÁ TRỊ được sử dụng làm thuộc tính của CÁC THỰC THỂ (và các GIÁ TRỊ khác). Một người có thể được mô hình hóa như một THỰC THỂ với một bản sắc, nhưng tên của người đó là một GIÁ TRỊ.

                                                                              Khi bạn chỉ quan tâm đến các thuộc tính của một phần tử trong mô hình, hãy phân loại nó là ĐỐI TƯỢNG GIÁ TRỊ. Hãy làm cho nó thể hiện ý nghĩa của các thuộc tính mà nó truyền đạt và cung cấp chức năng liên quan. Hãy xem ĐỐI TƯỢNG GIÁ TRỊ như là không thể thay đổi. Đừng gán cho nó bất kỳ danh tính nào và tránh những phức tạp trong thiết kế cần thiết để duy trì CÁC THỰC THỂ.

                                                                              Các thuộc tính cấu thành một ĐỐI TƯỢNG GIÁ TRỊ nên tạo thành một tổng thể khái niệm. Ví dụ, đường, thành phố và mã bưu điện không nên là các thuộc tính riêng biệt của một đối tượng Người. Chúng là một phần của một địa chỉ duy nhất, điều này làm cho đối tượng Người đơn giản hơn và ĐỐI TƯỢNG GIÁ TRỊ trở nên mạch lạc hơn.

                                                                              Mô hình GIÁ TRỊ TOÀN DIỆN, bởi Ward Cunningham.

                                                                              Figure 5.6. A VALUE OBJECT can give information about an ENTITY. It should be conceptually whole.

                                                                              graphics/05fig06.gif

                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                              Designing VALUE OBJECTS

                                                                              Chúng tôi không quan tâm đến việc chúng tôi có thể có thể hiện nào của một ĐỐI TƯỢNG GIÁ TRỊ. Sự thiếu ràng buộc này mang lại cho chúng tôi tự do thiết kế mà chúng tôi có thể sử dụng để đơn giản hóa thiết kế hoặc tối ưu hóa hiệu suất. Điều này liên quan đến việc đưa ra những lựa chọn về sao chép, chia sẻ và bất biến.

                                                                              Nếu hai người có cùng một tên, điều đó không có nghĩa là họ là cùng một người, hay có thể thay thế cho nhau. Nhưng đối tượng đại diện cho tên có thể thay thế, vì chỉ có cách viết của tên là quan trọng. Một đối tượng Tên có thể được sao chép từ đối tượng Người đầu tiên sang đối tượng Người thứ hai.

                                                                              Trên thực tế, hai đối tượng Person có thể không cần các phiên bản tên riêng của chúng. Cùng một đối tượng Name có thể được chia sẻ giữa hai đối tượng Person (mỗi đối tượng đều có một con trỏ đến cùng một phiên bản tên) mà không làm thay đổi hành vi hay danh tính của chúng. Điều đó có nghĩa là hành vi của chúng sẽ đúng cho đến khi có sự thay đổi nào đó đối với tên của một người. Khi đó, tên của người còn lại cũng sẽ thay đổi! Để bảo vệ chống lại điều này, để một đối tượng có thể được chia sẻ một cách an toàn, nó phải là bất biến: nó không thể bị thay đổi trừ khi được thay thế hoàn toàn.

                                                                              Các vấn đề tương tự xuất hiện khi một đối tượng truyền một trong những thuộc tính của nó cho một đối tượng khác dưới dạng tham số hoặc giá trị trả về. Bất cứ điều gì có thể xảy ra với đối tượng lang thang trong khi nó ngoài kiểm soát của chủ sở hữu. GIÁ TRỊ có thể bị thay đổi theo cách làm hỏng chủ sở hữu, bằng cách vi phạm các bất biến của chủ sở hữu. Vấn đề này được tránh bằng cách làm cho đối tượng được truyền là không thay đổi, hoặc bằng cách truyền một bản sao.

                                                                              Việc tạo ra các tùy chọn bổ sung để tối ưu hiệu suất có thể rất quan trọng vì CÁC ĐỐI TƯỢNG GIÁ TRỊ thường rất nhiều. Ví dụ về phần mềm thiết kế nhà gợi ý điều này. Nếu mỗi ổ cắm điện là một ĐỐI TƯỢNG GIÁ TRỊ riêng biệt, có thể có tới hàng trăm ổ cắm trong một phiên bản của một kế hoạch nhà duy nhất. Nhưng nếu tất cả các ổ cắm được coi là có thể thay thế cho nhau, chúng ta có thể chia sẻ chỉ một thể hiện của một ổ cắm và trỏ đến nó hàng trăm lần (một ví dụ về FLYWEIGHT [Gamma et al. 1995]). Trong các hệ thống lớn, hiệu ứng kiểu này có thể được nhân lên gấp hàng ngàn lần, và việc tối ưu hóa như vậy có thể tạo ra sự khác biệt giữa một hệ thống khả dụng và một hệ thống chậm lại, bị nghẹt bởi hàng triệu đối tượng dư thừa. Đây chỉ là một ví dụ về một mẹo tối ưu hóa không có sẵn cho CÁC THỰC THỂ.

                                                                              Nền kinh tế của việc sao chép so với việc chia sẻ phụ thuộc vào môi trường triển khai. Mặc dù sao chép có thể làm tắc nghẽn hệ thống với một số lượng lớn đối tượng, việc chia sẻ có thể làm chậm một hệ thống phân tán. Khi một bản sao được chuyển giữa hai máy tính, một thông điệp duy nhất được gửi và bản sao tồn tại độc lập trên máy nhận. Nhưng nếu một thể hiện duy nhất đang được chia sẻ, chỉ một tham chiếu được truyền, yêu cầu một thông điệp quay lại đối tượng cho mỗi lần tương tác.

                                                                              Chia sẻ chỉ nên giới hạn ở những trường hợp mà nó có giá trị cao nhất và ít gây phiền phức nhất.

                                                                              • Khi việc lưu trữ không gian hoặc số lượng đối tượng trong cơ sở dữ liệu là rất quan trọng.

                                                                              • Khi chi phí truyền thông thấp (chẳng hạn như trong một máy chủ tập trung)

                                                                              • Khi đối tượng chia sẻ hoàn toàn không thay đổi

                                                                              Tính bất biến của một thuộc tính hoặc một đối tượng có thể được tuyên bố trong một số ngôn ngữ và môi trường nhưng không phải trong những ngôn ngữ khác. Những tính năng như vậy giúp truyền đạt quyết định thiết kế, nhưng chúng không phải là thiết yếu. Nhiều phân biệt mà chúng ta đang thực hiện trong mô hình không thể được tuyên bố rõ ràng trong việc triển khai với hầu hết các công cụ và ngôn ngữ lập trình hiện tại. Ví dụ, bạn không thể tuyên bố CÁC THỰC THỂ và sau đó có một thao tác nhận diện được tự động thi hành. Nhưng việc thiếu hỗ trợ ngôn ngữ trực tiếp cho một sự phân biệt khái niệm không có nghĩa là sự phân biệt đó không hữu ích. Nó chỉ có nghĩa là cần có nhiều kỷ luật hơn để duy trì các quy tắc sẽ chỉ được ngụ ý trong việc triển khai. Điều này có thể được củng cố bằng cách đặt tên quy ước, tài liệu chọn lọc và nhiều cuộc thảo luận.

                                                                              Miễn là một ĐỐI TƯỢNG GIÁ TRỊ là bất biến, việc quản lý thay đổi rất đơn giản—không có thay đổi nào ngoại trừ việc thay thế toàn bộ. Các đối tượng bất biến có thể được chia sẻ tự do, như trong ví dụ về ổ cắm điện. Nếu việc thu gom rác là đáng tin cậy, việc xóa bỏ chỉ đơn giản là đánh rơi tất cả các tham chiếu đến đối tượng. Khi một ĐỐI TƯỢNG GIÁ TRỊ được chỉ định là bất biến trong thiết kế, các lập trình viên có thể tự do đưa ra quyết định về các vấn đề như sao chép và chia sẻ chỉ dựa trên cơ sở kỹ thuật, với sự tự tin rằng ứng dụng không phụ thuộc vào các bản sao cụ thể của các đối tượng.


                                                                              Special Cases: When to Allow Mutability

                                                                              Tính không thay đổi là một yếu tố làm cho việc triển khai đơn giản hơn, giúp việc chia sẻ và truyền tham chiếu trở nên an toàn. Nó cũng phù hợp với ý nghĩa của một giá trị. Nếu giá trị của một thuộc tính thay đổi, bạn sẽ sử dụng một ĐỐI TƯỢNG GIÁ TRỊ khác, thay vì sửa đổi đối tượng hiện tại. Dù vậy, vẫn có những trường hợp mà các yếu tố về hiệu suất sẽ ủng hộ việc cho phép một ĐỐI TƯỢNG GIÁ TRỊ trở nên biến đổi. Những yếu tố này sẽ thiên về hướng một triển khai biến đổi:

                                                                              • Nếu GIÁ TRỊ thay đổi thường xuyên

                                                                              • Nếu việc tạo hoặc xóa đối tượng tốn kém

                                                                              • "Nếu việc thay thế (thay vì sửa đổi) sẽ làm gián đoạn việc phân cụm (như đã thảo luận trong ví dụ trước)"

                                                                              • "Nếu không có nhiều sự chia sẻ về GIÁ TRỊ, hoặc nếu việc chia sẻ đó bị bỏ qua để cải thiện việc phân cụm hoặc vì lý do kỹ thuật nào đó."

                                                                              Chỉ để nhắc lại: Nếu việc triển khai một GIÁ TRỊ là có thể thay đổi, thì nó không được chia sẻ. Bất kể bạn có chia sẻ hay không, hãy thiết kế CÁC ĐỐI TƯỢNG GIÁ TRỊ là bất biến khi bạn có thể.

                                                                              Định nghĩa CÁC ĐỐI TƯỢNG GIÁ TRỊ và chỉ định chúng là bất biến là một trường hợp tuân theo một quy tắc chung: Tránh các ràng buộc không cần thiết trong một mô hình để cho phép các nhà phát triển tự do thực hiện việc tối ưu hóa hiệu suất kỹ thuật. Việc xác định rõ ràng các ràng buộc thiết yếu cho phép các nhà phát triển điều chỉnh thiết kế trong khi vẫn an toàn khỏi việc thay đổi hành vi có ý nghĩa. Những điều chỉnh thiết kế như vậy thường rất đặc thù đối với công nghệ đang được sử dụng trong một dự án cụ thể.

                                                                              Example
                                                                              Tuning a Database with VALUE OBJECTS

                                                                              Cơ sở dữ liệu, ở cấp độ thấp nhất, phải đặt dữ liệu tại một vị trí vật lý trên đĩa, và việc di chuyển các phần vật lý để đọc dữ liệu đó mất thời gian. Các cơ sở dữ liệu tinh vi cố gắng nhóm các địa chỉ vật lý này lại với nhau để dữ liệu liên quan có thể được lấy từ đĩa trong một thao tác vật lý duy nhất.

                                                                              Nếu một đối tượng được tham chiếu bởi nhiều đối tượng khác, một số đối tượng đó sẽ không nằm gần nhau (trên cùng một trang), đòi hỏi một thao tác vật lý bổ sung để truy xuất dữ liệu. Bằng cách tạo một bản sao, thay vì chia sẻ một tham chiếu đến cùng một thể hiện, một ĐỐI TƯỢNG GIÁ TRỊ đang hoạt động như một thuộc tính của nhiều THỰC THỂ có thể được lưu trữ trên cùng một trang với mỗi THỰC THỂ mà nó sử dụng. Kỹ thuật lưu trữ nhiều bản sao của cùng một dữ liệu được gọi là phi chuẩn hóa và thường được sử dụng khi thời gian truy cập quan trọng hơn không gian lưu trữ hoặc sự đơn giản trong việc bảo trì.

                                                                              Trong một cơ sở dữ liệu quan hệ, bạn có thể muốn đưa một GIÁ TRỊ nhất định vào bảng của THỰC THỂ sở hữu nó, thay vì tạo một mối liên hệ đến một bảng riêng biệt. Trong một hệ thống phân tán, việc giữ một tham chiếu đến một ĐỐI TƯỢNG GIÁ TRỊ trên máy chủ khác có thể dẫn đến phản hồi chậm đối với các tin nhắn; thay vào đó, một bản sao của toàn bộ đối tượng nên được chuyển đến máy chủ khác. Chúng ta có thể thoải mái sao chép những bản sao này vì chúng ta đang xử lý với ĐỐI TƯỢNG GIÁ TRỊ.

                                                                              Designing Associations That Involve VALUE OBJECTS

                                                                              Hầu hết các cuộc thảo luận trước đây về các mối quan hệ đều áp dụng cho THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ giống nhau. Số lượng và độ phức tạp của các mối quan hệ trong mô hình càng ít và đơn giản thì càng tốt.

                                                                              Tuy nhiên, trong khi các liên kết hai chiều giữa CÁC THỰC THỂ có thể khó duy trì, thì các liên kết hai chiều giữa hai ĐỐI TƯỢNG GIÁ TRỊ lại hoàn toàn không có nghĩa. Khi không có danh tính, không có ý nghĩa gì khi nói rằng một đối tượng quay trở lại cùng một ĐỐI TƯỢNG GIÁ TRỊ mà nó chỉ tới. Điều duy nhất bạn có thể nói là nó chỉ tới một đối tượng mà bằng với đối tượng đang chỉ tới nó, nhưng bạn sẽ phải duy trì định đề đó ở đâu đó. Và mặc dù bạn có thể làm điều đó và thiết lập các con trỏ theo cả hai hướng, nhưng rất khó để nghĩ ra ví dụ nào mà cách sắp xếp như vậy sẽ hữu ích. Hãy cố gắng loại bỏ hoàn toàn các liên kết hai chiều giữa các ĐỐI TƯỢNG GIÁ TRỊ. Nếu cuối cùng các liên kết như vậy dường như cần thiết trong mô hình của bạn, hãy xem xét lại quyết định công nhận đối tượng là một ĐỐI TƯỢNG GIÁ TRỊ ngay từ đầu. Có thể nó có một danh tính mà chưa được công nhận rõ ràng.

                                                                              CÁC THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ là những yếu tố chính của các mô hình đối tượng truyền thống, nhưng những nhà thiết kế thực dụng đã bắt đầu sử dụng một yếu tố, DỊCH VỤ.


                                                                                Services

                                                                                graphics/05inf03.gif

                                                                                Đôi khi, nó chỉ không phải là một điều gì đó.

                                                                                Trong một số trường hợp, thiết kế rõ ràng và thực dụng nhất bao gồm các thao tác mà về mặt khái niệm không thuộc về bất kỳ đối tượng nào. Thay vì ép buộc vấn đề, chúng ta có thể theo sát những đường nét tự nhiên của không gian vấn đề và bao gồm các DỊCH VỤ một cách rõ ràng trong mô hình.

                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                Có những hoạt động quan trọng trong miền mà không thể tìm thấy một nơi tự nhiên trong ĐỐI TƯỢNG hoặc ĐỐI TƯỢNG GIÁ TRỊ. Một số trong số này thực chất là các hoạt động hoặc hành động, chứ không phải là sự vật, nhưng vì mô hình hóa của chúng ta sử dụng đối tượng, chúng ta cố gắng gắn chúng vào các đối tượng dù sao đi nữa.

                                                                                Bây giờ, sai lầm phổ biến hơn là từ bỏ quá dễ dàng việc gán hành vi vào một đối tượng phù hợp, dần dần trượt về phía lập trình quy trình. Nhưng khi chúng ta ép một hoạt động vào một đối tượng không phù hợp với định nghĩa của đối tượng đó, đối tượng sẽ mất đi sự rõ ràng về khái niệm và trở nên khó hiểu hoặc tái cấu trúc. Các hoạt động phức tạp có thể dễ dàng làm ngợp một đối tượng đơn giản, che mờ vai trò của nó. Và vì những hoạt động này thường kéo theo nhiều đối tượng miền, việc phối hợp chúng và đưa chúng vào hành động sẽ tạo ra trách nhiệm thêm, tạo ra sự phụ thuộc vào tất cả những đối tượng đó, làm rối rắm các khái niệm có thể được hiểu độc lập.

                                                                                Đôi khi, các dịch vụ ngụy trang thành các đối tượng mô hình, xuất hiện như những đối tượng không có ý nghĩa gì ngoài việc thực hiện một số thao tác. Những "người thực hiện" này thường có tên kết thúc bằng "Quản lý" và các từ tương tự. Chúng không có trạng thái riêng hay bất kỳ ý nghĩa nào trong miền ngoài thao tác mà chúng chứa đựng. Tuy nhiên, ít nhất giải pháp này cũng tạo cho những hành vi khác biệt này một chốn ở mà không làm rối loạn một đối tượng mô hình thực sự.

                                                                                Một số khái niệm trong lĩnh vực này không tự nhiên để mô hình hóa dưới dạng đối tượng. Việc ép buộc chức năng cần thiết của miền trở thành trách nhiệm của một THỰC THỂ hoặc GIÁ TRỊ sẽ làm méo mó định nghĩa của một đối tượng dựa trên mô hình hoặc thêm những đối tượng nhân tạo không có ý nghĩa.

                                                                                MỘT DỊCH VỤ là một hoạt động được cung cấp dưới dạng giao diện mà đứng độc lập trong mô hình, không bao gói trạng thái, như CÁC THỰC THỂ và CÁC ĐỐI TƯỢNG GIÁ TRỊ. DỊCH VỤ là một mẫu phổ biến trong các khuôn khổ kỹ thuật, nhưng chúng cũng có thể áp dụng trong tầng miền.

                                                                                Dịch vụ tên nhấn mạnh mối quan hệ với các đối tượng khác. Khác với CÁC THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ, nó được định nghĩa hoàn toàn dựa trên những gì nó có thể làm cho một khách hàng. Một DỊCH VỤ thường được đặt tên cho một hoạt động, thay vì một thực thể - một động từ thay vì một danh từ. Một DỊCH VỤ vẫn có thể có định nghĩa trừu tượng và có ý định; nó chỉ có một hương vị khác với định nghĩa của một đối tượng. Một DỊCH VỤ vẫn nên có trách nhiệm được xác định, và trách nhiệm đó cũng như giao diện thực hiện nó nên được định nghĩa như một phần của mô hình miền. Tên các hoạt động nên đến từ NGÔN NGỮ PHỔ BIẾN hoặc được giới thiệu vào nó. Các tham số và kết quả nên là các đối tượng miền.

                                                                                DỊCH VỤ nên được sử dụng một cách thận trọng và không được phép tước bỏ hành vi của các THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ. Nhưng khi một thao tác thực sự là một khái niệm quan trọng trong miền, một DỊCH VỤ hình thành một phần tự nhiên trong thiết kế DỮ LIỆU MÔ HÌNH. Được công nhận trong mô hình như một DỊCH VỤ, thay vì như một đối tượng giả mạo mà không thực sự đại diện cho bất cứ điều gì, thao tác độc lập sẽ không gây nhầm lẫn cho bất kỳ ai.

                                                                                Một dịch vụ tốt có ba đặc điểm.

                                                                                1. Hoạt động này liên quan đến một khái niệm miền không phải là một phần tự nhiên của ENTITY hoặc VALUE OBJECT.

                                                                                Giao diện được định nghĩa dựa trên các yếu tố khác của mô hình miền.

                                                                                Hoạt động này là không trạng thái.

                                                                                Tình trạng không trạng thái ở đây có nghĩa là bất kỳ khách hàng nào cũng có thể sử dụng bất kỳ phiên bản nào của một DỊCH VỤ nhất định mà không cần quan tâm đến lịch sử riêng biệt của phiên bản đó. Việc thực thi một DỊCH VỤ sẽ sử dụng thông tin có sẵn toàn cầu và có thể thậm chí thay đổi thông tin toàn cầu đó (tức là, nó có thể có tác động phụ). Nhưng DỊCH VỤ không giữ trạng thái riêng của nó ảnh hưởng đến hành vi của chính nó, như hầu hết các đối tượng miền.

                                                                                Khi một quy trình hoặc sự biến đổi đáng kể trong miền không phải là trách nhiệm tự nhiên của một ENTITY hoặc VALUE OBJECT, hãy thêm một phép toán vào mô hình dưới dạng giao diện độc lập được tuyên bố là SERVICE. Định nghĩa giao diện theo ngôn ngữ của mô hình và đảm bảo rằng tên phép toán là một phần của NGÔN NGỮ PHỔ BIẾN. Làm cho SERVICE không trạng thái.

                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                SERVICES and the Isolated Domain Layer

                                                                                Mô hình này tập trung vào những DỊCH VỤ có ý nghĩa quan trọng trong miền của chính nó, nhưng tất nhiên DỊCH VỤ không chỉ được sử dụng trong lớp miền. Nó chú ý đến việc phân biệt DỊCH VỤ thuộc lớp miền với những DỊCH VỤ của các lớp khác, và phân chia trách nhiệm để giữ cho sự phân biệt đó rõ ràng.

                                                                                Hầu hết các DỊCH VỤ được đề cập trong tài liệu hoàn toàn mang tính kỹ thuật và thuộc về lớp hạ tầng. Các DỊCH VỤ miền và ứng dụng hợp tác với các DỊCH VỤ hạ tầng này. Ví dụ, một ngân hàng có thể có một ứng dụng gửi email cho khách hàng khi số dư tài khoản giảm xuống dưới một ngưỡng cụ thể. Giao diện bao quanh hệ thống email, và có thể là các phương thức thông báo thay thế, là một DỊCH VỤ trong lớp hạ tầng.

                                                                                Nó có thể khó hơn để phân biệt các DỊCH VỤ ứng dụng với các DỊCH VỤ miền. Lớp ứng dụng chịu trách nhiệm cho việc đặt hàng thông báo. Lớp miền chịu trách nhiệm xác định xem một ngưỡng đã đạt được hay không - mặc dù nhiệm vụ này có thể không cần thiết phải có một DỊCH VỤ, vì nó phù hợp với trách nhiệm của một đối tượng "tài khoản". Ứng dụng ngân hàng đó có thể chịu trách nhiệm cho việc chuyển tiền. Nếu một DỊCH VỤ được thiết kế để thực hiện các ghi nợ và ghi có thích hợp cho một khoản chuyển tiền, khả năng đó sẽ thuộc về lớp miền. Việc chuyển tiền có ý nghĩa trong ngôn ngữ miền ngân hàng và liên quan đến logic kinh doanh cơ bản. Các DỊCH VỤ kỹ thuật nên thiếu bất kỳ ý nghĩa kinh doanh nào.

                                                                                Nhiều DỊCH VỤ miền hoặc ứng dụng được xây dựng dựa trên các tập hợp của THỰC THỂ và GIÁ TRỊ, hoạt động như những kịch bản giúp tổ chức tiềm năng của miền để thực sự hoàn thành một cái gì đó. THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ thường quá chi tiết để cung cấp một cách tiếp cận thuận tiện đến khả năng của lớp miền. Ở đây, chúng ta gặp một ranh giới rất mảnh giữa lớp miền và lớp ứng dụng. Ví dụ, nếu ứng dụng ngân hàng có thể chuyển đổi và xuất các giao dịch của chúng ta thành một tệp bảng tính để chúng ta phân tích, thì việc xuất này là một DỊCH VỤ ứng dụng. Không có ý nghĩa của "định dạng tệp" trong miền ngân hàng, và không có quy tắc kinh doanh nào liên quan.

                                                                                Mặt khác, một tính năng có thể chuyển tiền từ tài khoản này sang tài khoản khác là một DỊCH VỤ vì nó bao gồm các quy tắc kinh doanh quan trọng (ví dụ như ghi có và ghi nợ các tài khoản thích hợp) và vì thuật ngữ "chuyển tiền" có ý nghĩa trong ngân hàng. Trong trường hợp này, DỊCH VỤ không làm nhiều một mình; nó sẽ yêu cầu hai đối tượng Tài khoản thực hiện phần lớn công việc. Nhưng việc đặt thao tác "chuyển" trên đối tượng Tài khoản sẽ bất tiện, vì thao tác này liên quan đến hai tài khoản và một số quy tắc toàn cầu.

                                                                                Chúng tôi có thể muốn tạo ra một đối tượng Chuyển tiền để đại diện cho hai mục nhập cùng với các quy tắc và lịch sử xung quanh việc chuyển khoản. Nhưng chúng tôi vẫn phải thực hiện các cuộc gọi đến CÁC DỊCH VỤ trong các mạng liên ngân hàng. Hơn nữa, trong hầu hết các hệ thống phát triển, việc tạo giao diện trực tiếp giữa một đối tượng miền và các tài nguyên bên ngoài là không thuận tiện. Chúng tôi có thể trang bị cho các DỊCH VỤ bên ngoài như vậy một BÌNH PHONG mà nhận đầu vào theo mô hình, có thể trả về một đối tượng Chuyển tiền như kết quả. Nhưng dù có bao nhiêu trung gian mà chúng tôi có, và mặc dù chúng không thuộc về chúng tôi, những DỊCH VỤ đó đang thực hiện trách nhiệm miền của việc chuyển tiền.

                                                                                Chia dịch vụ thành các lớp

                                                                                Ứng dụng

                                                                                Dịch vụ Chuyển Tiền Ứng Dụng

                                                                                • Tiêu hóa đầu vào (chẳng hạn như một yêu cầu XML).

                                                                                • Gửi tin nhắn đến dịch vụ miền để thực hiện.

                                                                                • Lắng nghe để xác nhận.

                                                                                • Quyết định gửi thông báo bằng dịch vụ hạ tầng.

                                                                                Miền

                                                                                Dịch vụ chuyển tiền trong lĩnh vực tài chính

                                                                                • Tương tác với các đối tượng Tài khoản và Sổ cái cần thiết, thực hiện các khoản ghi nợ và ghi có thích hợp.

                                                                                • Xác nhận kết quả cung cấp (cho phép chuyển nhượng hay không, và những điều khác).

                                                                                Cơ sở hạ tầng

                                                                                Dịch vụ Gửi Thông Báo

                                                                                • Gửi email, thư và các thông tin liên lạc khác theo chỉ dẫn của ứng dụng.

                                                                                Granularity

                                                                                Mặc dù cuộc thảo luận về mẫu này đã nhấn mạnh tính biểu đạt của việc mô hình hóa một khái niệm như một DỊCH VỤ, nhưng mẫu này cũng có giá trị như một phương tiện kiểm soát độ tinh vi trong các giao diện của lớp miền, cũng như tách rời các khách hàng khỏi CÁC THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ.

                                                                                DỊCH VỤ có độ phân giải trung bình và không trạng thái có thể dễ dàng tái sử dụng trong các hệ thống lớn hơn vì chúng bao bọc chức năng đáng kể sau một giao diện đơn giản. Ngoài ra, các đối tượng có độ phân giải mịn có thể dẫn đến việc truyền tin không hiệu quả trong một hệ thống phân tán.

                                                                                Như đã thảo luận trước đó, các đối tượng miền chi tiết có thể dẫn đến việc rò rỉ kiến thức từ miền vào lớp ứng dụng, nơi mà hành vi của đối tượng miền được phối hợp. Độ phức tạp của một tương tác chi tiết cao cuối cùng được xử lý trong lớp ứng dụng, cho phép kiến thức miền len lỏi vào mã ứng dụng hoặc giao diện người dùng, nơi mà nó bị mất khỏi lớp miền. Việc giới thiệu một cách thận trọng các dịch vụ miền có thể giúp duy trì ranh giới rõ ràng giữa các lớp.

                                                                                Mô hình này ủng hộ sự đơn giản của giao diện hơn là sự kiểm soát và đa năng của khách hàng. Nó cung cấp một mức độ chức năng trung bình rất hữu ích trong việc đóng gói các thành phần của các hệ thống lớn hoặc phân tán. Và đôi khi, một DỊCH VỤ là cách tự nhiên nhất để thể hiện một khái niệm miền.

                                                                                Access to SERVICES

                                                                                Kiến trúc hệ thống phân tán, chẳng hạn như J2EE và CORBA, cung cấp các cơ chế xuất bản đặc biệt cho DỊCH VỤ, với các quy ước cho việc sử dụng của chúng, và chúng thêm khả năng phân phối và truy cập. Nhưng những khung làm việc như vậy không phải lúc nào cũng được sử dụng trong một dự án, và ngay cả khi chúng được sử dụng, chúng có thể là quá mức cần thiết khi động lực chỉ là một sự tách biệt hợp lý về các mối quan tâm.

                                                                                Cách thức cung cấp quyền truy cập vào DỊCH VỤ không quan trọng bằng quyết định thiết kế để phân chia các trách nhiệm cụ thể. Một đối tượng "thực hiện" có thể là một cách làm hài lòng cho việc triển khai giao diện của DỊCH VỤ. Một SINGLETON đơn giản (Gamma et al. 1995) có thể được viết dễ dàng để cung cấp quyền truy cập. Các quy ước lập trình có thể làm rõ rằng những đối tượng này chỉ là các cơ chế truyền tải cho giao diện DỊCH VỤ, chứ không phải là các đối tượng miền có ý nghĩa. Các kiến trúc phức tạp chỉ nên được sử dụng khi thật sự cần thiết để phân phối hệ thống hoặc sử dụng các khả năng của khung.


                                                                                  Modules (a.k.a. Packages)

                                                                                  CÁC MÔ-ĐUN là một yếu tố thiết kế cũ, đã được thiết lập. Có những vấn đề kỹ thuật, nhưng quá tải nhận thức là động cơ chính cho sự phân mảnh. CÁC MÔ-ĐUN cho phép mọi người có hai cách nhìn về mô hình: Họ có thể xem chi tiết bên trong một MÔ-ĐUN mà không bị choáng ngợp bởi toàn bộ, hoặc họ có thể nhìn thấy các mối quan hệ giữa các MÔ-ĐUN trong các cái nhìn không bao gồm chi tiết bên trong.

                                                                                  "CÁC MODULE trong lớp miền nên hiện ra như một phần có ý nghĩa của mô hình, kể câu chuyện về miền theo quy mô lớn hơn."

                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                  Mọi người đều sử dụng MODULES, nhưng ít người xem chúng như một phần toàn diện của mô hình. Mã được phân chia thành đủ loại danh mục, từ các khía cạnh của kiến trúc kỹ thuật đến phân công công việc của các nhà phát triển. Ngay cả những nhà phát triển thường xuyên tái cấu trúc cũng thường hài lòng với các MODULES được hình thành từ sớm trong dự án.

                                                                                  Điều hiển nhiên là nên có sự kết nối thấp giữa các MODULE và sự gắn kết cao trong chúng. Giải thích về sự kết nối và gắn kết thường khiến chúng có vẻ như là các chỉ số kỹ thuật, được đánh giá một cách máy móc dựa trên sự phân phối của các mối liên hệ và tương tác. Tuy nhiên, không chỉ có mã được chia thành các MODULE, mà còn là các khái niệm. Có một giới hạn về số lượng điều mà một người có thể nghĩ đến cùng một lúc (do đó là sự kết nối thấp). Những mảnh vụn ý tưởng không liên kết lại khó hiểu như một món súp ý tưởng không phân biệt (do đó là sự gắn kết cao).

                                                                                  Tính liên kết thấp và tính cohesion cao là các nguyên tắc thiết kế chung áp dụng cho cả các đối tượng cá nhân và các MODULE, nhưng chúng đặc biệt quan trọng ở cấp độ mô hình và thiết kế lớn hơn này. Những thuật ngữ này đã tồn tại từ lâu; một lời giải thích theo phong cách mẫu có thể được tìm thấy trong Larman 1998.

                                                                                  Mỗi khi hai phần tử mô hình được tách ra thành các mô-đun khác nhau, các mối quan hệ giữa chúng trở nên ít trực tiếp hơn so với trước, điều này làm tăng chi phí hiểu biết về vị trí của chúng trong thiết kế. Sự tách biệt thấp giữa các MODULE tối thiểu hóa chi phí này và cho phép phân tích nội dung của một MODULE với ít tham chiếu đến những MODULE khác tương tác.

                                                                                  Đồng thời, các yếu tố của một mô hình tốt có sự đồng bộ, và các MODULE được chọn lựa cẩn thận kết hợp các yếu tố của mô hình với những mối quan hệ khái niệm đặc biệt phong phú. Sự gắn kết cao này giữa các đối tượng có trách nhiệm liên quan cho phép công việc mô hình hóa và thiết kế tập trung trong một MODULE duy nhất, một quy mô phức tạp mà trí óc con người có thể dễ dàng xử lý.

                                                                                  CÁC PHÂN MODUL và các yếu tố nhỏ hơn nên tiến hóa đồng thời, nhưng thường thì chúng không như vậy. CÁC PHÂN MODUL được chọn để tổ chức một hình thức sớm của các đối tượng. Sau đó, các đối tượng có xu hướng thay đổi theo những cách giữ chúng trong giới hạn của định nghĩa CÁC PHÂN MODUL hiện có. Việc tổ chức lại CÁC PHÂN MODUL tốn nhiều công sức và gây rối hơn so với việc tổ chức lại các lớp, và có lẽ không thể diễn ra thường xuyên. Nhưng cũng giống như các đối tượng mô hình thường bắt đầu với sự naiv và cụ thể và sau đó dần dần chuyển hóa để tiết lộ cái nhìn sâu sắc hơn, CÁC PHÂN MODUL có thể trở nên tinh vi và tr-abstractive. Để CÁC PHÂN MODUL phản ánh sự hiểu biết đang thay đổi về miền sẽ cho phép nhiều tự do hơn cho các đối tượng bên trong chúng phát triển.

                                                                                  Như mọi thứ khác trong thiết kế dựa trên miền, CÁC MODULE là một cơ chế giao tiếp. Ý nghĩa của các đối tượng được phân vùng cần phải dẫn dắt sự lựa chọn CÁC MODULE. Khi bạn đặt một số lớp lại với nhau trong một MODULE, bạn đang nói với nhà phát triển tiếp theo xem xét thiết kế của bạn rằng hãy nghĩ về chúng cùng nhau. Nếu mô hình của bạn đang kể một câu chuyện, các MODULE là các chương. Tên của MODULE truyền tải ý nghĩa của nó. Những tên này sẽ tham gia vào NGÔN NGỮ PHỔ BIẾN. "Bây giờ hãy nói về module 'khách hàng'," bạn có thể nói với một chuyên gia kinh doanh, và bối cảnh đã được thiết lập cho cuộc trò chuyện của bạn.

                                                                                  Do đó:

                                                                                  Chọn CÁC MODULE kể câu chuyện của hệ thống và chứa một tập hợp các khái niệm nhất quán. Điều này thường mang lại độ coupl thấp giữa CÁC MODULE, nhưng nếu không, hãy tìm cách thay đổi mô hình để tách rời các khái niệm, hoặc tìm kiếm một khái niệm bị bỏ qua có thể là cơ sở cho một MODULE có thể kết hợp các phần tử lại với nhau theo cách có ý nghĩa. Tìm kiếm độ coupling thấp theo nghĩa của các khái niệm có thể được hiểu và suy luận độc lập với nhau. Tinh chỉnh mô hình cho đến khi nó phân chia theo các khái niệm miền cấp cao và mã tương ứng cũng được tách rời.

                                                                                  Hãy cung cấp tên các MODULE mà trở thành một phần của NGÔN NGỮ PHỔ THÔNG. Các MODULE và tên của chúng nên phản ánh cái nhìn sâu sắc vào miền.

                                                                                  Xem xét các mối quan hệ khái niệm không phải là một lựa chọn thay thế cho các biện pháp kỹ thuật. Chúng là các cấp độ khác nhau của cùng một vấn đề, và cả hai đều cần phải được thực hiện. Nhưng tư duy tập trung vào mô hình sản sinh ra một giải pháp sâu sắc hơn, thay vì một giải pháp ngẫu nhiên. Và khi phải có sự đánh đổi, tốt nhất là nên chọn sự rõ ràng khái niệm, ngay cả khi điều đó có nghĩa là nhiều mối liên hệ hơn giữa các MODULE hoặc có những hiệu ứng lan tỏa khi thay đổi một MODULE. Các nhà phát triển có thể xử lý những vấn đề này nếu họ hiểu câu chuyện mà mô hình đang kể cho họ.

                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                  Agile MODULES

                                                                                  CÁC MODULE cần đồng tiến hóa với phần còn lại của mô hình. Điều này có nghĩa là phải tái cấu trúc CÁC MODULE cùng với mô hình và mã nguồn. Nhưng việc tái cấu trúc này thường không xảy ra. Việc thay đổi CÁC MODULE thường yêu cầu cập nhật rộng rãi mã nguồn. Những thay đổi như vậy có thể gây ra sự gián đoạn trong giao tiếp giữa các thành viên trong nhóm và thậm chí có thể làm rối loạn các công cụ phát triển, chẳng hạn như hệ thống kiểm soát mã nguồn. Kết quả là, cấu trúc và tên của CÁC MODULE thường phản ánh các hình thức của mô hình từ rất sớm hơn so với các lớp.

                                                                                  Những sai lầm đầu tiên không thể tránh khỏi trong việc chọn MODULE dẫn đến sự phụ thuộc cao, điều này làm cho việc tái cấu trúc trở nên khó khăn. Việc thiếu tái cấu trúc chỉ làm tăng độ quán tính. Nó chỉ có thể được khắc phục bằng cách chấp nhận sự thật và tổ chức lại các MODULE dựa trên kinh nghiệm về những điểm vấn đề.

                                                                                  Một số công cụ phát triển và hệ thống lập trình làm trầm trọng thêm vấn đề. Bất kể công nghệ phát triển nào mà việc triển khai sẽ dựa vào, chúng ta cần tìm cách giảm thiểu công việc tái cấu trúc CÁC MODULE và giảm thiểu sự lộn xộn trong việc giao tiếp với các nhà phát triển khác.

                                                                                  Example
                                                                                  Package Coding Conventions in Java

                                                                                  Trong Java, các phần phụ thuộc (dependencies) phải được khai báo trong một lớp riêng lẻ. Một người lập mô hình có lẽ nghĩ rằng các gói phụ thuộc vào các gói khác, nhưng điều này không thể được nêu rõ trong Java. Các quy ước lập trình chung khuyến khích việc nhập các lớp cụ thể, dẫn đến mã như sau:

                                                                                  ClassA1 import packageB.ClassB1; import packageB.ClassB2; import packageB.ClassB3; import packageC.ClassC1; import packageC.ClassC2; import packageC.ClassC3; . . . 

                                                                                  Trong Java, thật không may, không có cách nào để tránh việc nhập vào từng lớp riêng lẻ, nhưng ít nhất bạn có thể nhập toàn bộ gói cùng một lúc, phản ánh ý định rằng các gói là những đơn vị có tính kết hợp cao trong khi đồng thời giảm bớt nỗ lực trong việc thay đổi tên gói.

                                                                                  ClassA1 import packageB.*; import packageC.*; . . . 

                                                                                  Đúng vậy, kỹ thuật này có nghĩa là trộn lẫn hai quy mô (các lớp phụ thuộc vào gói), nhưng nó truyền đạt nhiều hơn so với danh sách lớp quá dài trước đây - nó truyền đạt ý định tạo ra sự phụ thuộc vào các MODULE cụ thể.

                                                                                  Nếu một lớp cá nhân thực sự phụ thuộc vào một lớp cụ thể trong một gói khác, và MODULE địa phương dường như không có sự phụ thuộc khái niệm vào MODULE khác, thì có lẽ một lớp nên được di chuyển, hoặc các MODULE nên được xem xét lại.

                                                                                  The Pitfalls of Infrastructure-Driven Packaging

                                                                                  Sự ảnh hưởng mạnh mẽ đến quyết định đóng gói của chúng tôi đến từ các khung kỹ thuật. Một số khung này có ích, trong khi những khung khác cần phải được chống lại.

                                                                                  Một ví dụ về một tiêu chuẩn khung rất hữu ích là việc thực thi KIẾN TRÚC TẦNG lớp bằng cách phân chia mã cơ sở hạ tầng và giao diện người dùng thành các nhóm gói riêng biệt, để lại lớp miền tách biệt về mặt vật lý trong một tập hợp gói riêng của nó.

                                                                                  Mặt khác, kiến trúc phân tầng có thể làm phân mảnh việc triển khai các đối tượng mô hình. Một số khung công tác tạo tầng bằng cách phân chia các trách nhiệm của một đối tượng miền duy nhất thành nhiều đối tượng khác nhau và sau đó đặt những đối tượng đó vào các gói riêng biệt. Ví dụ, với J2EE, một thực tiễn phổ biến là đặt dữ liệu và quyền truy cập dữ liệu vào một "entity bean" trong khi đặt logic kinh doanh liên quan vào một "session bean." Ngoài sự phức tạp trong việc triển khai mỗi thành phần, sự tách biệt ngay lập tức làm mất đi độ kết cấu của mô hình đối tượng. Một trong những khái niệm cơ bản nhất của đối tượng là đóng gói dữ liệu với logic hoạt động trên dữ liệu đó. Loại triển khai phân tầng này không phải là chết người, vì cả hai thành phần có thể được xem như cùng cấu thành một phần tử mô hình duy nhất, nhưng để làm trầm trọng thêm tình huống, các entity bean và session bean thường được tách ra thành các gói khác nhau. Vào thời điểm đó, việc xem xét các đối tượng khác nhau và hình dung chúng kết hợp lại như một THỰC THỂ khái niệm duy nhất trở nên quá khó khăn. Chúng ta mất đi kết nối giữa mô hình và thiết kế. Thực hành tốt nhất là sử dụng EJB ở một quy mô lớn hơn so với các đối tượng ENTITY, giảm thiểu nhược điểm của việc tách biệt các tầng. Nhưng các đối tượng tinh tế thường cũng bị tách thành các tầng.

                                                                                  Ví dụ, tôi đã gặp những vấn đề này trong một dự án được quản lý một cách thông minh, nơi mỗi đối tượng khái niệm thực sự được chia thành bốn tầng. Mỗi phân khúc có lý do tốt. Tầng đầu tiên là một lớp lưu trữ dữ liệu, xử lý ánh xạ và truy cập vào cơ sở dữ liệu quan hệ. Tiếp theo là một lớp xử lý hành vi nội tại của đối tượng trong tất cả các tình huống. Lớp tiếp theo là lớp chồng lên chức năng cụ thể của ứng dụng. Tầng thứ tư được thiết kế như một giao diện công khai, tách rời khỏi tất cả các triển khai phía dưới. Sơ đồ này có phần quá phức tạp, nhưng các lớp thì được xác định rõ ràng và có một sự gọn gàng trong việc phân tách các mối quan tâm. Chúng tôi có thể đã sống chung với việc kết nối về mặt tinh thần tất cả các đối tượng vật lý tạo thành một đối tượng khái niệm. Sự phân tách các khía cạnh thậm chí đã giúp ích vào những lúc nhất định. Cụ thể, việc mã giữ liệu được di chuyển ra ngoài đã loại bỏ rất nhiều sự lộn xộn.

                                                                                  Nhưng trên tất cả những điều này, khung yêu cầu mỗi tầng phải nằm trong một bộ gói riêng biệt, được đặt tên theo một quy ước xác định tầng. Điều này đã chiếm hết không gian tư duy cho việc phân chia. Kết quả là, các nhà phát triển miền có xu hướng tránh tạo ra quá nhiều MODULE (mỗi MODULE lại được nhân lên bốn lần) và hầu như không bao giờ thay đổi một MODULE nào, vì nỗ lực tái cấu trúc một MODULE là quá lớn. Tệ hơn, việc tìm kiếm tất cả dữ liệu và hành vi xác định một lớp khái niệm duy nhất rất khó khăn (kết hợp với tính gián tiếp của các lớp) đến mức các nhà phát triển không còn nhiều không gian tư duy để suy nghĩ về các mô hình. Ứng dụng đã được giao, nhưng với một mô hình miền yếu ớt chủ yếu đáp ứng các yêu cầu truy cập cơ sở dữ liệu của ứng dụng, với hành vi được cung cấp bởi một vài DỊCH VỤ. Sự tận dụng lẽ ra phải phát sinh từ THIẾT KẾ HƯỚNG MÔ HÌNH bị giới hạn vì mã không minh bạch tiết lộ mô hình và cho phép một nhà phát triển làm việc với nó.

                                                                                  Loại thiết kế khung này đang cố gắng giải quyết hai vấn đề hợp lý. Một là sự phân chia hợp lý các trách nhiệm: Một đối tượng chịu trách nhiệm cho việc truy cập cơ sở dữ liệu, một đối tượng khác cho logic kinh doanh, và cứ như vậy. Những sự phân chia như vậy giúp dễ dàng hiểu chức năng của từng tầng (ở mức độ kỹ thuật) và làm cho việc thay thế các lớp trở nên dễ dàng hơn. Vấn đề là chi phí cho việc phát triển ứng dụng không được công nhận. Đây không phải là một cuốn sách về thiết kế khung, vì vậy tôi sẽ không đi vào các giải pháp thay thế cho vấn đề đó, nhưng chúng vẫn tồn tại. Và ngay cả khi không có các tùy chọn, thì việc đánh đổi những lợi ích này để đổi lấy một lớp miền gắn kết hơn sẽ tốt hơn.

                                                                                  Động lực khác cho những kế hoạch đóng gói này là sự phân phối các cấp độ. Đây có thể là một lập luận mạnh mẽ nếu mã thực sự được triển khai trên các máy chủ khác nhau. Thông thường điều này không xảy ra. Sự linh hoạt được tìm kiếm chỉ trong trường hợp nó cần thiết. Trong một dự án hy vọng tận dụng từ THIẾT KẾ DỰA TRÊN MẪU, sự hy sinh này là quá lớn trừ khi nó giải quyết một vấn đề ngay lập tức và cấp bách.

                                                                                  Các phương án đóng gói được thúc đẩy bằng kỹ thuật phức tạp sẽ chịu hai loại chi phí.

                                                                                  • Nếu các quy tắc phân chia của khung làm tách rời các phần tử thực hiện các đối tượng khái niệm, thì mã nguồn sẽ không còn biểu hiện mô hình nữa.

                                                                                  • Chỉ có một giới hạn về việc phân chia mà một tâm trí có thể khôi phục lại, và nếu khung sử dụng hết tất cả, các nhà phát triển miền sẽ mất khả năng chia mô hình thành các phần có ý nghĩa.

                                                                                  Tốt nhất là giữ mọi thứ đơn giản. Chọn một số quy tắc phân vùng kỹ thuật tối thiểu cần thiết cho môi trường kỹ thuật hoặc thực sự giúp ích cho sự phát triển. Ví dụ, tách biệt mã lưu trữ dữ liệu phức tạp khỏi các khía cạnh hành vi của các đối tượng có thể giúp việc tái cấu trúc dễ dàng hơn.

                                                                                  Trừ khi có ý định thực sự phân phối mã trên các máy chủ khác nhau, hãy giữ tất cả mã thực hiện một đối tượng khái niệm duy nhất trong cùng một MODULE, nếu không phải là cùng một đối tượng.

                                                                                  Chúng tôi có thể đã đi đến cùng một kết luận bằng cách dựa vào tiêu chuẩn cũ, "tính gắn kết cao/tính tách rời thấp." Mối liên hệ giữa một "đối tượng" thực hiện logic kinh doanh và đối tượng chịu trách nhiệm truy cập cơ sở dữ liệu là rất rộng rãi, do đó tính tách rời rất thấp.

                                                                                  Có những cạm bẫy khác mà việc thiết kế khung hoặc chỉ các quy ước của một công ty hoặc dự án có thể làm suy yếu THIẾT KẾ DỰA TRÊN MÔ HÌNH bằng cách làm mờ đi sự gắn kết tự nhiên của các đối tượng miền, nhưng bản chất vấn đề vẫn giống nhau. Những sự hạn chế, hoặc chỉ là số lượng lớn các gói yêu cầu, đã loại trừ việc sử dụng các sơ đồ đóng gói khác được điều chỉnh theo nhu cầu của mô hình miền.

                                                                                  Sử dụng đóng gói để tách lớp miền khỏi các mã khác. Ngoài ra, hãy để các nhà phát triển miền có nhiều sự tự do nhất có thể để đóng gói các đối tượng miền theo cách hỗ trợ mô hình và lựa chọn thiết kế của họ.

                                                                                  Một ngoại lệ xảy ra khi mã được tạo ra dựa trên một thiết kế tuyên bố (được thảo luận trong Chương 10). Trong trường hợp đó, các nhà phát triển không cần phải đọc mã, và tốt hơn là đưa nó vào một gói riêng biệt để nó không cản trở, không làm rối các yếu tố thiết kế mà các nhà phát triển thực sự phải làm việc với.

                                                                                  Tính mô đun trở nên quan trọng hơn khi thiết kế trở nên lớn hơn và phức tạp hơn. Phần này trình bày các yếu tố cơ bản. Phần lớn của Phần IV, "Thiết kế chiến lược," cung cấp các phương pháp để đóng gói và phân tách các mô hình và thiết kế lớn, cũng như cách để cung cấp cho mọi người những điểm chú ý nhằm hướng dẫn sự hiểu biết.

                                                                                  Mỗi khái niệm từ mô hình miền nên được phản ánh trong một yếu tố của việc triển khai. CÁC THỰC THỂ, ĐỐI TƯỢNG GIÁ TRỊ và các mối quan hệ của chúng, cùng với một số DỊCH VỤ miền và các MODULE tổ chức, là những điểm tương ứng trực tiếp giữa việc triển khai và mô hình. Các đối tượng, con trỏ và cơ chế truy xuất trong việc triển khai phải ánh xạ đến các yếu tố mô hình một cách rõ ràng và hiển nhiên. Nếu không, hãy dọn dẹp mã, quay lại và thay đổi mô hình, hoặc cả hai.

                                                                                  Chống lại cám dỗ để thêm bất cứ điều gì vào các đối tượng miền mà không có liên quan chặt chẽ đến những khái niệm mà chúng đại diện. Những yếu tố thiết kế này có nhiệm vụ của chúng: chúng biểu thị mô hình. Có những trách nhiệm liên quan đến miền khác mà phải được thực hiện và các dữ liệu khác cần được quản lý để làm cho hệ thống hoạt động, nhưng chúng không thuộc về những đối tượng này. Trong Chương 6, tôi sẽ thảo luận về một số đối tượng hỗ trợ thực hiện các trách nhiệm kỹ thuật của lớp miền, chẳng hạn như định nghĩa các tìm kiếm cơ sở dữ liệu và bao bọc quá trình tạo đối tượng phức tạp.

                                                                                  Bốn mẫu trong chương này cung cấp các khối xây dựng cho một mô hình đối tượng. Nhưng THIẾT KẾ DỰA TRÊN MÔ HÌNH không nhất thiết nghĩa là ép mọi thứ vào một khuôn đối tượng. Cũng có những mô hình khác được các công cụ hỗ trợ, như động cơ quy tắc. Các dự án phải thực hiện các thương lượng thiết thực giữa chúng. Những công cụ và kỹ thuật khác này là phương tiện để đạt được THIẾT KẾ DỰA TRÊN MÔ HÌNH, không phải là lựa chọn thay thế cho nó.


                                                                                    Modeling Paradigms

                                                                                    THIẾT KẾ DỰA TRÊN MÔ HÌNH yêu cầu một công nghệ triển khai phù hợp với mô hình cụ thể đang được áp dụng. Nhiều mô hình như vậy đã được thử nghiệm, nhưng chỉ một số ít được sử dụng rộng rãi trong thực tế. Hiện tại, mô hình chiếm ưu thế là thiết kế hướng đối tượng, và hầu hết các dự án phức tạp ngày nay đều bắt đầu bằng cách sử dụng đối tượng. Sự thống trị này đã xảy ra vì nhiều lý do: một số yếu tố thuộc về bản chất của đối tượng, một số là hoàn cảnh, và những yếu tố khác xuất phát từ những lợi thế đi kèm với việc sử dụng rộng rãi.

                                                                                    Why the Object Paradigm Predominates

                                                                                    Nhiều lý do mà các đội chọn mô hình đối tượng không phải là kỹ thuật, thậm chí không phải là bản chất của các đối tượng. Nhưng ngay từ đầu, mô hình đối tượng tạo ra một sự cân bằng đẹp giữa sự đơn giản và sự tinh vi.

                                                                                    Nếu một mô hình lý thuyết quá khó hiểu, không đủ lập trình viên sẽ làm chủ nó, và họ sẽ sử dụng nó không đúng cách. Nếu các thành viên không kỹ thuật trong nhóm không thể nắm bắt ít nhất những điều cơ bản của mô hình, họ sẽ không hiểu được mô hình, và NGÔN NGỮ PHỔ BIẾN sẽ bị mất. Các nguyên tắc cơ bản của thiết kế hướng đối tượng dường như đến với hầu hết mọi người một cách tự nhiên. Mặc dù một số lập trình viên không phát hiện ra những điểm tinh tế của mô hình, thậm chí những người không làm trong lĩnh vực công nghệ cũng có thể theo dõi một sơ đồ của mô hình đối tượng.

                                                                                    Tuy nhiên, mặc dù khái niệm mô hình đối tượng là đơn giản, nhưng nó đã chứng tỏ đủ phong phú để nắm bắt kiến thức miền quan trọng. Và nó đã được hỗ trợ ngay từ đầu bởi các công cụ phát triển cho phép một mô hình được biểu diễn trong phần mềm.

                                                                                    Hôm nay, mô hình đối tượng cũng có một số lợi thế đáng kể từ sự trưởng thành và phổ biến rộng rãi. Nếu không có cơ sở hạ tầng và hỗ trợ công cụ trưởng thành, một dự án có thể bị chệch hướng vào nghiên cứu và phát triển công nghệ, làm chậm tiến độ và phân bổ lại tài nguyên khỏi phát triển ứng dụng cũng như giới thiệu rủi ro kỹ thuật. Một số công nghệ không tương thích tốt với các công nghệ khác, và có thể không thể tích hợp chúng với các giải pháp tiêu chuẩn ngành, buộc nhóm phải tái phát minh các tiện ích phổ biến. Nhưng qua nhiều năm, nhiều vấn đề này đã được giải quyết cho các đối tượng, hoặc trở nên không còn liên quan do sự áp dụng rộng rãi. (Bây giờ, trách nhiệm thuộc về các phương pháp khác để tích hợp với công nghệ đối tượng chính thống.) Hầu hết các công nghệ mới đều cung cấp phương tiện để tích hợp với các nền tảng hướng đối tượng phổ biến. Điều này làm cho việc tích hợp dễ dàng hơn và thậm chí còn mở ra khả năng kết hợp các hệ thống con dựa trên các mô hình khác (chúng tôi sẽ thảo luận sau trong chương này).

                                                                                    Cũng quan trọng không kém là sự trưởng thành của cộng đồng lập trình viên và văn hóa thiết kế chính nó. Một dự án áp dụng một mô hình mới có thể không tìm được lập trình viên có chuyên môn về công nghệ đó, hoặc có kinh nghiệm để tạo ra các mô hình hiệu quả trong mô hình đã chọn. Có thể không khả thi để đào tạo lập trình viên trong một khoảng thời gian hợp lý vì các hình mẫu để tận dụng tối đa mô hình và công nghệ chưa được hình thành rõ ràng. Có lẽ những người tiên phong trong lĩnh vực này rất hiệu quả nhưng chưa công bố những hiểu biết của họ theo một hình thức dễ tiếp cận.

                                                                                    Các đối tượng đã được hiểu bởi một cộng đồng gồm hàng ngàn nhà phát triển, quản lý dự án và tất cả những chuyên gia khác tham gia vào công việc dự án.

                                                                                    Một câu chuyện từ một dự án hướng đối tượng chỉ cách đây một thập kỷ minh họa cho những rủi ro khi làm việc trong một mô hình còn non trẻ. Vào đầu những năm 1990, dự án này cam kết áp dụng một số công nghệ tiên tiến, bao gồm việc sử dụng cơ sở dữ liệu hướng đối tượng quy mô lớn. Thật thú vị. Những người trong nhóm tự hào nói với khách tham quan rằng chúng tôi đang triển khai cơ sở dữ liệu lớn nhất mà công nghệ này từng hỗ trợ. Khi tôi gia nhập dự án, các nhóm khác nhau đang phát triển các thiết kế hướng đối tượng và lưu trữ các đối tượng của họ trong cơ sở dữ liệu một cách dễ dàng. Nhưng dần dần, nhận thức rằng chúng tôi đã bắt đầu tiêu tốn một phần đáng kể dung lượng của cơ sở dữ liệu—với dữ liệu thử nghiệm! Cơ sở dữ liệu thực tế sẽ lớn gấp hàng chục lần. Khối lượng giao dịch thực tế sẽ cao gấp hàng chục lần. Liệu có phải là không thể sử dụng công nghệ này cho ứng dụng này không? Chúng tôi đã sử dụng nó sai cách? Chúng tôi không thể theo kịp.

                                                                                    Rất may mắn, chúng tôi đã có thể đưa vào đội ngũ một trong số ít người trên thế giới có kỹ năng để giải quyết vấn đề của chúng tôi. Ông đưa ra mức giá của mình và chúng tôi đã chấp nhận. Có ba nguồn gốc của vấn đề. Thứ nhất, cơ sở hạ tầng có sẵn đi kèm với cơ sở dữ liệu đơn giản không đủ khả năng mở rộng theo nhu cầu của chúng tôi. Thứ hai, việc lưu trữ các đối tượng chi tiết hóa hóa ra lại tốn kém hơn chúng tôi đã nhận ra. Thứ ba, một số phần của mô hình đối tượng có quá nhiều mối phụ thuộc lẫn nhau đến mức tình trạng tranh chấp trở thành vấn đề với một số lượng giao dịch đồng thời tương đối nhỏ.

                                                                                    Với sự trợ giúp của chuyên gia thuê ngoài này, chúng tôi đã nâng cao cơ sở hạ tầng. Đội ngũ, giờ đây nhận thức được tác động của các đối tượng tinh vi, bắt đầu tìm kiếm các mô hình hoạt động tốt hơn với công nghệ này. Tất cả chúng tôi đã làm sâu sắc thêm suy nghĩ về tầm quan trọng của việc giới hạn mạng lưới mối quan hệ trong một mô hình, và chúng tôi bắt đầu áp dụng hiểu biết mới này để tạo ra những mô hình tốt hơn với sự tách rời nhiều hơn giữa các tập hợp liên quan chặt chẽ.

                                                                                    Nhiều tháng đã bị lãng phí trong quá trình phục hồi này, cộng thêm những tháng trước đó đã dành cho việc đi vào một con đường không thành công. Và đây không phải là lần đầu tiên đội ngũ gặp phải khó khăn do sự chưa trưởng thành của các công nghệ được chọn và sự thiếu kinh nghiệm của chúng tôi với quá trình học tập liên quan. Buồn thay, dự án này đã bị thu hẹp lại và trở nên khá bảo thủ. Đến ngày hôm nay, họ vẫn sử dụng các công nghệ độc đáo, nhưng chỉ cho những ứng dụng có phạm vi thận trọng mà có lẽ không thực sự được hưởng lợi từ chúng.

                                                                                    Một thập kỷ sau, công nghệ hướng đối tượng đã tương đối trưởng thành. Hầu hết các nhu cầu cơ sở hạ tầng phổ biến có thể được đáp ứng bằng các giải pháp có sẵn trên thị trường đã được sử dụng trong thực tế. Các công cụ quan trọng cho nhiệm vụ đến từ các nhà cung cấp lớn, thường là nhiều nhà cung cấp, hoặc từ các dự án mã nguồn mở ổn định. Nhiều phần của cơ sở hạ tầng này được sử dụng rộng rãi đến mức có một cơ sở người dùng đã hiểu rõ về chúng, cũng như có sách giải thích về chúng và những thứ tương tự. Các giới hạn của những công nghệ đã được thiết lập này khá rõ ràng, vì vậy đội ngũ có kinh nghiệm ít có khả năng vượt quá khả năng của mình.

                                                                                    Các mô hình lý thuyết thú vị khác chỉ đơn giản là không có độ chín muồi này. Một số quá khó để làm chủ và sẽ không bao giờ được sử dụng ngoài các lĩnh vực nhỏ. Những cái khác có tiềm năng, nhưng hạ tầng kỹ thuật vẫn còn không đồng đều hoặc yếu kém, và rất ít người hiểu được những tinh tế trong việc tạo ra các mô hình tốt cho chúng. Những mô hình này có thể trưởng thành, nhưng chúng chưa sẵn sàng cho hầu hết các dự án.

                                                                                    Đó là lý do tại sao, trong thời điểm hiện tại, hầu hết các dự án cố gắng THIẾT KẾ DỰA TRÊN MÔ HÌNH khôn ngoan sử dụng công nghệ hướng đối tượng làm cốt lõi của hệ thống của họ. Họ sẽ không bị mắc kẹt trong một hệ thống chỉ có đối tượng - vì các đối tượng đã trở thành dòng chính của ngành công nghiệp, các công cụ tích hợp có sẵn để kết nối với hầu như bất kỳ công nghệ nào khác đang được sử dụng hiện nay.

                                                                                    Tuy nhiên, điều này không có nghĩa là mọi người nên tự hạn chế mình chỉ với các đối tượng mãi mãi. Du lịch cùng đám đông mang lại một số mức độ an toàn, nhưng không phải lúc nào cũng là cách tốt nhất. Các mô hình đối tượng giải quyết một số lượng lớn các vấn đề phần mềm thực tiễn, nhưng có những lĩnh vực không tự nhiên để mô hình hóa dưới dạng các gói hành vi được bao bọc riêng biệt. Ví dụ, những lĩnh vực có tính toán cao hoặc bị chi phối bởi lý luận logic toàn cầu không phù hợp với phương pháp tiếp cận hướng đối tượng.

                                                                                    Nonobjects in an Object World

                                                                                    Một mô hình miền không nhất thiết phải là một mô hình đối tượng. Có những THIẾT KẾ DỰA TRÊN MÔ HÌNH được triển khai bằng Prolog, ví dụ, với một mô hình được cấu thành từ các quy tắc và sự kiện logic. Các mô hình đã được phát triển để giải quyết những cách mà con người thích suy nghĩ về các miền nhất định. Sau đó, các mô hình của những miền đó được định hình bởi khuôn khổ. Kết quả là một mô hình phù hợp với khuôn khổ để có thể được triển khai hiệu quả trong các công cụ hỗ trợ phong cách mô hình hóa đó.

                                                                                    Dù mô hình chính nào có thể là mô hình chi phối trong một dự án, luôn có những phần của miền mà sẽ dễ dàng hơn rất nhiều để biểu diễn bằng một mô hình khác. Khi chỉ có một vài yếu tố bất thường trong một miền mà về mặt khác hoạt động tốt trong một mô hình, các nhà phát triển có thể chấp nhận một số đối tượng không thuận tiện trong một mô hình nhất quán. (Hoặc, ở đầu cực đối diện, nếu phần lớn miền vấn đề được biểu diễn tự nhiên hơn trong một mô hình khác, có thể hợp lý khi chuyển đổi hoàn toàn giữa các mô hình và chọn một nền tảng triển khai khác.) Nhưng khi các phần lớn của miền dường như thuộc về các mô hình khác nhau, thì việc mô hình hóa từng phần trong một mô hình phù hợp trở nên hấp dẫn về mặt trí tuệ, sử dụng một hỗn hợp các bộ công cụ để hỗ trợ triển khai. Khi sự phụ thuộc là nhỏ, một tiểu hệ thống trong mô hình khác có thể được đóng gói, chẳng hạn như một tính toán toán học phức tạp chỉ cần được gọi bởi một đối tượng. Đôi khi, các khía cạnh khác nhau lại liên kết chặt chẽ hơn, chẳng hạn như khi sự tương tác của các đối tượng phụ thuộc vào một số mối quan hệ toán học.

                                                                                    Điều này thúc đẩy việc tích hợp vào hệ thống đối tượng các thành phần không phải đối tượng như động cơ quy tắc kinh doanh và động cơ quy trình làm việc. Việc kết hợp các mô hình cho phép các nhà phát triển mô hình hóa các khái niệm cụ thể theo phong cách phù hợp nhất. Hơn nữa, hầu hết các hệ thống phải sử dụng một số cơ sở hạ tầng kỹ thuật không phải đối tượng, thường gặp nhất là cơ sở dữ liệu quan hệ. Nhưng việc tạo ra một mô hình nhất quán trải dài qua các mô hình là khó khăn, và việc làm cho các công cụ hỗ trợ đồng tồn tại là phức tạp. Khi các nhà phát triển không thể nhìn thấy một mô hình nhất quán hiện thân trong phần mềm, THIẾT KẾ DỰA TRÊN MÔ HÌNH có thể bị bỏ qua, ngay cả khi sự pha trộn này làm tăng nhu cầu về nó.

                                                                                    Sticking with MODEL-DRIVEN DESIGN When Mixing Paradigms

                                                                                    Công cụ quy tắc sẽ là một ví dụ về công nghệ đôi khi được kết hợp vào một dự án phát triển ứng dụng hướng đối tượng. Một mô hình miền giàu tri thức có lẽ chứa các quy tắc rõ ràng, nhưng mô hình đối tượng thiếu ngữ nghĩa cụ thể để nêu ra các quy tắc và sự tương tác của chúng. Mặc dù các quy tắc có thể được mô hình hóa như các đối tượng, và thường thành công, nhưng việc bao bọc đối tượng khiến việc áp dụng các quy tắc toàn cục trải dài trên toàn hệ thống trở nên khó khăn. Công nghệ công cụ quy tắc có sức hấp dẫn bởi vì nó hứa hẹn cung cấp một cách tự nhiên và tuyên bố hơn để định nghĩa các quy tắc, cho phép pha trộn một cách hiệu quả giữa quy tắc và mô hình đối tượng. Mô hình logic là một lĩnh vực phát triển tốt và mạnh mẽ, và dường như là một sự bổ sung tốt cho những điểm mạnh và điểm yếu của đối tượng.

                                                                                    Nhưng không phải lúc nào mọi người cũng nhận được những gì họ mong đợi từ các công cụ luật. Một số sản phẩm đơn giản là không hoạt động tốt. Một số thiếu một cái nhìn liền mạch có thể cho thấy sự liên quan của các khái niệm mô hình chạy giữa hai môi trường triển khai. Một kết quả phổ biến là một ứng dụng bị chia cắt thành hai phần: một hệ thống lưu trữ dữ liệu tĩnh sử dụng đối tượng, và một ứng dụng xử lý quy tắc tự phát đã mất gần như tất cả mối liên hệ với mô hình đối tượng.

                                                                                    Điều quan trọng là tiếp tục suy nghĩ theo mô hình trong khi làm việc với các quy tắc. Đội ngũ phải tìm một mô hình duy nhất có thể hoạt động với cả hai kiểu triển khai. Điều này không dễ, nhưng có thể thực hiện được nếu bộ điều khiển quy tắc cho phép triển khai mang tính biểu cảm. Nếu không, dữ liệu và các quy tắc sẽ trở nên không liên kết. Các quy tắc trong bộ điều khiển cuối cùng sẽ giống như những chương trình nhỏ hơn là các quy tắc khái niệm trong mô hình miền. Với mối quan hệ chặt chẽ, rõ ràng giữa các quy tắc và các đối tượng, ý nghĩa của cả hai phần được giữ lại.

                                                                                    "Nếu không có một môi trường liền mạch, trách nhiệm thuộc về các nhà phát triển để tinh lọc một mô hình được cấu thành từ những khái niệm rõ ràng và cơ bản nhằm gắn kết toàn bộ thiết kế."

                                                                                    Công cụ hiệu quả nhất để gắn kết các phần lại với nhau là một NGÔN NGỮ PHỔ BIẾN mạnh mẽ, nền tảng cho toàn bộ mô hình đa dạng. Việc áp dụng nhất quán các tên trong hai môi trường và sử dụng các tên đó trong NGÔN NGỮ PHỔ BIẾN có thể giúp thu hẹp khoảng cách.

                                                                                    Đây là một chủ đề xứng đáng có một cuốn sách riêng. Mục tiêu của phần này chỉ là để chỉ ra rằng không cần phải từ bỏ THIẾT KẾ DỰA TRÊN MÔ HÌNH, và rằng nỗ lực để duy trì nó là điều đáng giá.

                                                                                    Mặc dù một THIẾT KẾ ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH không nhất thiết phải theo hướng đối tượng, nhưng nó phụ thuộc vào việc có một cách triển khai diễn đạt những cấu trúc mô hình, cho dù đó là đối tượng, quy tắc hay quy trình làm việc. Nếu công cụ có sẵn không hỗ trợ được tính diễn đạt đó, hãy xem xét lại sự lựa chọn công cụ. Một triển khai không diễn đạt sẽ làm mất đi lợi thế của khái niệm bổ sung.

                                                                                    Dưới đây là bốn quy tắc chung để kết hợp các yếu tố phi đối tượng vào một hệ thống chủ yếu dựa trên đối tượng:

                                                                                    • Đừng chống lại mô hình triển khai. Luôn luôn có cách khác để suy nghĩ về một lĩnh vực. Tìm kiếm các khái niệm mô hình phù hợp với mô hình triển khai.

                                                                                    • Dựa vào ngôn ngữ phổ quát. Ngay cả khi không có mối liên hệ chặt chẽ giữa các công cụ, việc sử dụng ngôn ngữ nhất quán có thể giữ cho các phần của thiết kế không bị phân tán.

                                                                                    • Đừng quá sa lầy vào UML. Đôi khi sự gắn bó với một công cụ, chẳng hạn như sơ đồ UML, khiến mọi người bóp méo mô hình để nó phù hợp với những gì có thể dễ dàng vẽ ra. Ví dụ, UML có một số tính năng để biểu diễn các ràng buộc, nhưng chúng không luôn đủ. Một phong cách vẽ khác (có thể là phong cách thông thường cho một triết lý khác), hoặc các mô tả bằng tiếng Anh đơn giản, thường tốt hơn là việc điều chỉnh gian nan một phong cách vẽ được thiết kế cho một cái nhìn nhất định về các đối tượng.

                                                                                    • Hãy hoài nghi. Công cụ này có thực sự đáng giá không? Chỉ vì bạn có một số quy tắc, không có nghĩa là bạn cần sự phức tạp của một công cụ quản lý quy tắc. Các quy tắc có thể được diễn đạt dưới dạng đối tượng, có thể hơi kém gọn gàng hơn; nhiều phương thức lập trình làm tình huống trở nên phức tạp hơn rất nhiều.

                                                                                    Trước khi đảm nhận gánh nặng của các khung mẫu hỗn hợp, các tùy chọn trong khung mẫu chiếm ưu thế nên được khai thác hết mức. Mặc dù một số khái niệm trong miền không biểu hiện như những đối tượng rõ ràng, chúng thường có thể được mô hình hóa trong khung mẫu. Chương 9 sẽ thảo luận về việc mô hình hóa các loại khái niệm không theo quy ước bằng cách sử dụng công nghệ đối tượng.

                                                                                    Mô hình quan hệ là một trường hợp đặc biệt của sự pha trộn các mô hình. Công nghệ không phải đối tượng phổ biến nhất, cơ sở dữ liệu quan hệ cũng có mối quan hệ gần gũi hơn với mô hình đối tượng so với các thành phần khác, vì nó hoạt động như nơi lưu trữ lâu dài của dữ liệu tạo nên chính các đối tượng. Việc lưu trữ dữ liệu đối tượng trong các cơ sở dữ liệu quan hệ sẽ được thảo luận trong Chương 6, cùng với nhiều thách thức khác của chu trình sống của đối tượng.


                                                                                      Chapter Six. The Life Cycle of a Domain Object

                                                                                      Mỗi đối tượng đều có một vòng đời. Một đối tượng được sinh ra, có khả năng trải qua nhiều trạng thái khác nhau, và cuối cùng nó sẽ chết—hoặc được lưu trữ hoặc bị xóa. Tất nhiên, nhiều đối tượng này chỉ đơn giản, tạm thời, được tạo ra với một lời gọi đơn giản tới hàm khởi tạo của chúng, được sử dụng trong một phép toán nào đó, và sau đó bị bỏ rơi cho bộ thu gom rác. Không cần phải làm phức tạp hóa những đối tượng như vậy. Nhưng những đối tượng khác có tuổi thọ dài hơn, không phải lúc nào cũng được dành cho bộ nhớ hoạt động. Chúng có các mối quan hệ phụ thuộc phức tạp với những đối tượng khác. Chúng trải qua những thay đổi trạng thái mà các bất biến áp dụng. Quản lý những đối tượng này đặt ra những thách thức có thể dễ dàng làm trật bánh một nỗ lực theo KIẾN TRÚC ĐIỀU KHIỂN MÔ HÌNH.

                                                                                      Figure 6.1. The life cycle of a domain object

                                                                                      graphics/06fig01.gif

                                                                                      Các thách thức rơi vào hai loại.

                                                                                      1. Duy trì tính toàn vẹn xuyên suốt vòng đời

                                                                                      Ngăn chặn mô hình bị choáng ngợp bởi sự phức tạp trong việc quản lý vòng đời.

                                                                                      Chương này sẽ giải quyết những vấn đề này thông qua ba mô hình. Đầu tiên, AGGREGATES làm chặt chẽ mô hình bằng cách xác định quyền sở hữu và ranh giới rõ ràng, tránh một mạng lưới đối tượng lộn xộn, rối ren. Mô hình này là rất quan trọng để duy trì tính toàn vẹn trong tất cả các giai đoạn của vòng đời.

                                                                                      Tiếp theo, trọng tâm chuyển sang giai đoạn đầu của vòng đời, sử dụng CÁC NHÀ MÁY để tạo ra và tái tạo các đối tượng phức tạp và CỤM, giữ cho cấu trúc bên trong của chúng được bao bọc. Cuối cùng, CÁC KHO cung cấp các phương tiện để tìm kiếm và truy suất các đối tượng bền vững, đồng thời bao bọc hạ tầng khổng lồ liên quan.

                                                                                      Mặc dù REPOSITORIES và FACTORIES không phải xuất phát từ miền, nhưng chúng có vai trò có ý nghĩa trong thiết kế miền. Các cấu trúc này hoàn thiện THIẾT KẾ DỰA TRÊN MÔ HÌNH bằng cách cung cấp cho chúng ta những tay cầm dễ tiếp cận với các đối tượng mô hình.

                                                                                      Mô hình hóa CỤM và thêm NHÀ MÁY và KHO TÀI NGUYÊN vào thiết kế cho phép chúng ta thao tác với các đối tượng mô hình một cách có hệ thống và trong các đơn vị có ý nghĩa suốt vòng đời của chúng. CÁC CỤM đánh dấu phạm vi bên trong đó các bất biến phải được duy trì ở mọi giai đoạn của vòng đời. CÁC NHÀ MÁY và KHO TÀI NGUYÊN hoạt động trên CỤM, bao gói sự phức tạp của các chuyển giao vòng đời cụ thể.


                                                                                        Aggregates

                                                                                        graphics/06inf01.gif

                                                                                        Thiết kế tối giản của các liên kết giúp đơn giản hóa quá trình duyệt và hạn chế sự bùng nổ của mối quan hệ phần nào, nhưng hầu hết các lĩnh vực kinh doanh đều có sự kết nối chặt chẽ đến nỗi chúng ta vẫn phải theo dõi những con đường dài và sâu qua các tham chiếu đối tượng. Theo một cách nào đó, sự rối ren này phản ánh thực tế của thế giới, nơi hiếm khi cho chúng ta những ranh giới rõ ràng. Đây là một vấn đề trong thiết kế phần mềm.

                                                                                        Giả sử bạn đang xóa một đối tượng Người từ cơ sở dữ liệu. Cùng với người đó có một tên, ngày sinh và mô tả công việc. Nhưng còn địa chỉ thì sao? Có thể có những người khác cùng địa chỉ. Nếu bạn xóa địa chỉ, những đối tượng Người đó sẽ có tham chiếu đến một đối tượng đã bị xóa. Nếu bạn để lại, bạn sẽ tích lũy những địa chỉ rác trong cơ sở dữ liệu. Bộ thu gom rác tự động có thể loại bỏ những địa chỉ rác, nhưng giải pháp kỹ thuật đó, ngay cả khi có sẵn trong hệ thống cơ sở dữ liệu của bạn, cũng phớt lờ một vấn đề cơ bản trong mô hình.

                                                                                        Ngay cả khi xem xét một giao dịch đơn lẻ, mạng lưới các mối quan hệ trong một mô hình đối tượng điển hình không đưa ra giới hạn rõ ràng cho hiệu ứng tiềm tàng của một thay đổi. Không thực tế khi phải làm mới mọi đối tượng trong hệ thống, chỉ để phòng khi có một số phụ thuộc.

                                                                                        Vấn đề trở nên cấp bách trong một hệ thống có nhiều người dùng truy cập đồng thời vào cùng một đối tượng. Với nhiều người dùng tham khảo và cập nhật các đối tượng khác nhau trong hệ thống, chúng ta phải ngăn chặn các thay đổi đồng thời đối với các đối tượng liên quan đến nhau. Việc hiểu sai phạm vi có thể dẫn đến những hậu quả nghiêm trọng.

                                                                                        Thật khó để đảm bảo tính nhất quán của các thay đổi đối với các đối tượng trong một mô hình có các liên kết phức tạp. Cần phải duy trì các bất biến áp dụng cho các nhóm đối tượng liên quan chặt chẽ, không chỉ đối với các đối tượng rời rạc. Tuy nhiên, các hệ thống khóa thận trọng khiến nhiều người dùng can thiệp lẫn nhau một cách không cần thiết và làm cho hệ thống trở nên không thể sử dụng được.

                                                                                        Nói cách khác, làm thế nào chúng ta biết một đối tượng được tạo thành từ những đối tượng khác bắt đầu và kết thúc ở đâu? Trong bất kỳ hệ thống nào có lưu trữ dữ liệu cố định, phải có một phạm vi cho một giao dịch thay đổi dữ liệu và một cách để duy trì tính nhất quán của dữ liệu (tức là, duy trì các bất biến của nó). Cơ sở dữ liệu cho phép các loại hệ thống khóa khác nhau, và các bài kiểm tra có thể được lập trình. Nhưng những giải pháp ad hoc này làm phân tâm sự chú ý khỏi mô hình, và sớm thôi bạn lại quay trở lại việc hack và hy vọng.

                                                                                        Trên thực tế, việc tìm ra giải pháp cân bằng cho những loại vấn đề này đòi hỏi sự hiểu biết sâu sắc về lĩnh vực, lần này mở rộng đến các yếu tố như tần suất thay đổi giữa các trường hợp của một số lớp nhất định. Chúng ta cần tìm một mô hình mà trong đó các điểm mâu thuẫn cao được giữ lỏng hơn và các bất biến nghiêm ngặt được giữ chặt hơn.

                                                                                        Mặc dù vấn đề này xuất hiện như những khó khăn kỹ thuật trong các giao dịch cơ sở dữ liệu, nhưng nó có nguồn gốc từ mô hình - từ việc thiếu các ranh giới được xác định. Một giải pháp dựa trên mô hình sẽ giúp mô hình dễ hiểu hơn và làm cho thiết kế dễ giao tiếp hơn. Khi mô hình được xem xét lại, nó sẽ hướng dẫn chúng ta thực hiện các thay đổi trong việc triển khai.

                                                                                        Các sơ đồ đã được phát triển để xác định các mối quan hệ quyền sở hữu trong mô hình. Hệ thống đơn giản nhưng chặt chẽ sau đây, được chắt lọc từ những khái niệm đó, bao gồm một tập hợp các quy tắc để thực hiện các giao dịch thay đổi các đối tượng và chủ sở hữu của chúng.

                                                                                        David Siegel đã thiết kế và sử dụng hệ thống này trong các dự án vào những năm 1990 nhưng chưa công bố.

                                                                                        Trước tiên, chúng ta cần một sự trừu tượng để đóng gói các tham chiếu trong mô hình. Một AGGREGATE là một cụm các đối tượng liên quan mà chúng ta coi như một đơn vị cho mục đích thay đổi dữ liệu. Mỗi AGGREGATE có một gốc và một ranh giới. Ranh giới xác định những gì nằm bên trong AGGREGATE. Gốc là một THỰC THỂ cụ thể duy nhất nằm trong AGGREGATE. Gốc là thành viên duy nhất của AGGREGATE mà các đối tượng bên ngoài được phép giữ tham chiếu tới, mặc dù các đối tượng trong ranh giới có thể giữ tham chiếu đến nhau. Các THỰC THỂ khác ngoài gốc có danh tính cục bộ, nhưng danh tính đó cần phải có thể phân biệt chỉ trong AGGREGATE, vì không có đối tượng bên ngoài nào có thể nhìn thấy nó ngoài bối cảnh của THỰC THỂ gốc.

                                                                                        Mô hình của một chiếc ô tô có thể được sử dụng trong phần mềm cho một cửa hàng sửa chữa ô tô. Chiếc ô tô là một THỰC THỂ với danh tính toàn cầu: chúng ta muốn phân biệt chiếc ô tô đó với tất cả các xe khác trên thế giới, ngay cả những chiếc tương tự. Chúng ta có thể sử dụng số định danh phương tiện cho việc này, một định danh duy nhất được gán cho mỗi chiếc ô tô mới. Chúng ta có thể muốn theo dõi lịch sử quay của các bánh xe qua bốn vị trí bánh xe. Chúng ta có thể muốn biết số dặm đi và độ mòn gai của mỗi lốp. Để biết chiếc lốp nào là cái nào, các lốp cần phải được xác định là THỰC THỂ. Nhưng rất khó để chúng ta quan tâm đến danh tính của những chiếc lốp đó ngoài bối cảnh của chiếc ô tô cụ thể đó. Nếu chúng ta thay thế lốp và gửi những lốp cũ đến nhà máy tái chế, phần mềm của chúng ta sẽ không còn theo dõi chúng nữa, hoặc chúng sẽ trở thành những thành viên vô danh trong một đống lốp. Không ai sẽ quan tâm đến lịch sử quay của chúng. Để rõ ràng hơn, ngay cả khi chúng còn gắn trên xe, không ai sẽ cố gắng truy vấn hệ thống để tìm một chiếc lốp cụ thể và sau đó xem nó đang ở xe nào. Họ sẽ truy vấn cơ sở dữ liệu để tìm một chiếc ô tô và sau đó yêu cầu một tham chiếu tạm thời đến các lốp. Do đó, chiếc ô tô là THỰC THỂ gốc của TỔ HỢP mà ranh giới bao gồm cả các lốp. Mặt khác, các khối động cơ có số sê-ri được khắc lên chúng và đôi khi được theo dõi độc lập với chiếc ô tô. Trong một số ứng dụng, động cơ có thể là gốc của TỔ HỢP của riêng nó.

                                                                                        Figure 6.2. Local versus global identity and object references

                                                                                        graphics/06fig02.gif

                                                                                        Các hằng số, là các quy tắc tính nhất quán cần được duy trì mỗi khi dữ liệu thay đổi, sẽ liên quan đến mối quan hệ giữa các thành viên của AGGREGATE. Bất kỳ quy tắc nào trải dài qua các AGGREGATE sẽ không được kỳ vọng luôn luôn được cập nhật. Thông qua xử lý sự kiện, xử lý theo lô, hoặc các cơ chế cập nhật khác, các phụ thuộc khác có thể được giải quyết trong một khoảng thời gian xác định. Nhưng các hằng số áp dụng trong một AGGREGATE sẽ được thi hành với sự hoàn thành của mỗi giao dịch.

                                                                                        Figure 6.3. AGGREGATE invariants

                                                                                        graphics/06fig03.gif

                                                                                        Bây giờ, để chuyển đổi khái niệm TỔNG HỢP đó thành hiện thực, chúng ta cần một bộ quy tắc áp dụng cho tất cả các giao dịch.

                                                                                        • Thực thể gốc có danh tính toàn cầu và cuối cùng chịu trách nhiệm kiểm tra các bất biến.

                                                                                        • CÁC THỰC THỂ GỐC có danh tính toàn cầu. CÁC THỰC THỂ bên trong ranh giới có danh tính cục bộ, chỉ duy nhất trong PHÂN TÍCH.

                                                                                        • Không có gì bên ngoài ranh giới AGGREGATE có thể giữ tham chiếu đến bất kỳ điều gì bên trong, ngoại trừ thực thể gốc. Thực thể gốc có thể trao tham chiếu đến các thực thể nội bộ cho các đối tượng khác, nhưng những đối tượng đó chỉ có thể sử dụng chúng một cách tạm thời và không được giữ tham chiếu. Thực thể gốc có thể trao một bản sao của đối tượng giá trị cho một đối tượng khác, và điều đó không quan trọng điều gì xảy ra với nó, vì nó chỉ là một GIÁ TRỊ và không còn liên kết với AGGREGATE nữa.

                                                                                        • Như một hệ quả của quy tắc trước, chỉ có các gốc AGGREGATE mới có thể được lấy trực tiếp bằng các truy vấn cơ sở dữ liệu. Tất cả các đối tượng khác phải được tìm thấy bằng việc duyệt qua các mối quan hệ.

                                                                                        • Các đối tượng trong AGGREGATE có thể giữ tham chiếu đến các gốc AGGREGATE khác.

                                                                                        • Một thao tác xóa phải loại bỏ mọi thứ bên trong ranh giới AGGREGATE cùng một lúc. (Với việc thu gom rác, điều này rất dễ. Bởi vì không có bất kỳ tham chiếu nào bên ngoài ngoài gốc, hãy xóa gốc và mọi thứ khác sẽ được thu gom.)

                                                                                        • Khi một thay đổi đối với bất kỳ đối tượng nào trong ranh giới AGGREGATE được cam kết, tất cả các bất biến của toàn bộ AGGREGATE phải được thỏa mãn.

                                                                                        Nhóm các THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ thành các TẬP HỢP và xác định ranh giới xung quanh từng tập hợp. Chọn một THỰC THỂ làm gốc cho mỗi TẬP HỢP, và kiểm soát toàn bộ quyền truy cập vào các đối tượng bên trong ranh giới thông qua gốc. Cho phép các đối tượng bên ngoài giữ tham chiếu chỉ đến gốc. Các tham chiếu tạm thời đến các thành viên nội bộ có thể được truyền ra để sử dụng trong một thao tác duy nhất. Bởi vì gốc kiểm soát quyền truy cập, nó không thể bị bất ngờ bởi những thay đổi trong nội bộ. Cách sắp xếp này giúp thực thi tất cả các bất biến cho các đối tượng trong TẬP HỢP và cho TẬP HỢP nói chung trong bất kỳ thay đổi trạng thái nào.

                                                                                        Việc có một khung kỹ thuật cho phép bạn khai báo các TỔNG HỢP và sau đó tự động thực hiện cơ chế khóa và các công việc khác có thể rất hữu ích. Nếu không có sự hỗ trợ đó, nhóm phải có kỷ luật tự giác để đồng ý về các TỔNG HỢP và lập trình nhất quán với chúng.

                                                                                        Example
                                                                                        Purchase Order Integrity

                                                                                        Xem xét các phức tạp có thể xảy ra trong một hệ thống đơn đặt hàng đơn giản.

                                                                                        Figure 6.4. A model for a purchase order system

                                                                                        graphics/06fig04.gif

                                                                                        Sơ đồ này trình bày một cái nhìn khá thông thường về đơn đặt hàng (PO), được chia thành các mục dòng, với một quy tắc không thay đổi rằng tổng của các mục dòng không được vượt quá hạn mức cho toàn bộ đơn đặt hàng. Việc thực hiện hiện tại gặp ba vấn đề liên quan đến nhau.

                                                                                        1. Thực thi tính bất biến. Khi một mục mới được thêm vào, đơn đặt hàng (PO) kiểm tra tổng số và tự đánh dấu là không hợp lệ nếu một mục nào đó khiến nó vượt quá giới hạn. Như chúng ta sẽ thấy, đây không phải là biện pháp bảo vệ đầy đủ.

                                                                                        Quản lý thay đổi. Khi PO bị xóa hoặc lưu trữ, các mặt hàng kèm theo cũng bị xóa, nhưng mô hình không cung cấp hướng dẫn về việc dừng theo dõi các mối quan hệ. Cũng có sự nhầm lẫn về tác động của việc thay đổi giá phần vào những thời điểm khác nhau.

                                                                                        Chia sẻ cơ sở dữ liệu. Nhiều người dùng đang tạo ra các vấn đề cạnh tranh trong cơ sở dữ liệu.

                                                                                        Nhiều người dùng sẽ cùng lúc vào và cập nhật các đơn đặt hàng khác nhau, và chúng ta phải ngăn chặn họ làm rối công việc của nhau. Hãy bắt đầu với một chiến lược rất đơn giản, trong đó chúng ta khóa bất kỳ đối tượng nào mà người dùng bắt đầu chỉnh sửa cho đến khi người đó hoàn tất giao dịch. Vì vậy, khi George đang chỉnh sửa mục dòng 001, Amanda không thể truy cập vào đó. Cô ấy có thể chỉnh sửa bất kỳ mục dòng nào khác trên bất kỳ đơn đặt hàng nào khác (bao gồm các mục khác trong đơn đặt hàng mà George đang làm việc).

                                                                                        Figure 6.5. The initial condition of the PO stored in the database

                                                                                        graphics/06fig05.gif

                                                                                        Các đối tượng sẽ được đọc từ cơ sở dữ liệu và được khởi tạo trong không gian bộ nhớ của từng người dùng. Tại đó, chúng có thể được xem và chỉnh sửa. Các khóa cơ sở dữ liệu sẽ chỉ được yêu cầu khi bắt đầu chỉnh sửa. Vì vậy, cả George và Amanda có thể làm việc song song, miễn là họ tránh xa các mục của nhau. Mọi thứ đều tốt đẹp . . . cho đến khi cả George và Amanda bắt đầu làm việc trên các mục riêng biệt trong cùng một đơn đặt hàng.

                                                                                        Figure 6.6. Simultaneous edits in distinct transactions

                                                                                        graphics/06fig06.gif

                                                                                        Mọi thứ trông ổn đối với cả hai người dùng và phần mềm của họ vì họ bỏ qua những thay đổi đối với các phần khác của cơ sở dữ liệu xảy ra trong suốt giao dịch, và không có mục nào bị khóa liên quan đến thay đổi của người dùng kia.

                                                                                        Figure 6.7. The resulting PO violates the approval limit (broken invariant).

                                                                                        graphics/06fig07.gif

                                                                                        Sau khi cả hai người dùng đã lưu các thay đổi của họ, một PO bị lưu trữ trong cơ sở dữ liệu vi phạm bất biến của mô hình miền. Một quy tắc kinh doanh quan trọng đã bị vi phạm. Và không ai biết cả.

                                                                                        Rõ ràng, việc khoá một mục đơn lẻ không phải là một biện pháp bảo vệ đủ. Nếu thay vào đó chúng ta đã khoá toàn bộ đơn hàng cùng một lúc, vấn đề này đã được ngăn chặn.

                                                                                        Figure 6.8. Locking the entire PO allows the invariant to be enforced.

                                                                                        graphics/06fig08.gif

                                                                                        Chương trình sẽ không cho phép giao dịch này được lưu lại cho đến khi Amanda giải quyết vấn đề, có thể bằng cách tăng giới hạn hoặc bằng cách loại bỏ một cây guitar. Cơ chế này ngăn chặn vấn đề, và có thể là một giải pháp tốt nếu công việc chủ yếu được phân bổ rộng rãi trên nhiều PO. Nhưng nếu nhiều người thường xuyên làm việc cùng lúc trên các mục khác nhau của một PO lớn, thì việc khóa này sẽ trở nên bất tiện.

                                                                                        Ngay cả khi giả định có nhiều đơn đặt hàng nhỏ, vẫn có những cách khác để vi phạm phát biểu. Hãy xem xét "phần." Nếu ai đó thay đổi giá của một chiếc trombone trong khi Amanda đang thêm vào đơn hàng của cô ấy, điều đó có phải là vi phạm tính bất biến hay không?

                                                                                        Hãy thử khóa phần riêng lẻ bên cạnh toàn bộ đơn hàng. Đây là những gì xảy ra khi George, Amanda và Sam đang làm việc trên các đơn hàng khác nhau:

                                                                                        Figure 6.9. Over-cautious locking is interfering with people's work.

                                                                                        graphics/06fig09.gif

                                                                                        Sự bất tiện đang gia tăng, vì có rất nhiều sự cạnh tranh cho các công cụ (các "phần"). Và sau đó:

                                                                                        Figure 6.10. Deadlock

                                                                                        graphics/06fig10.gif

                                                                                        Ba người đó sẽ phải chờ một lúc.

                                                                                        Tại thời điểm này, chúng ta có thể bắt đầu cải thiện mô hình bằng cách kết hợp những kiến thức sau về doanh nghiệp:

                                                                                        1. Các linh kiện được sử dụng trong nhiều đơn đặt hàng (cạnh tranh cao).

                                                                                        Có ít thay đổi ở các bộ phận hơn là ở các đơn đặt hàng.

                                                                                        Sự thay đổi giá của linh kiện không nhất thiết phải áp dụng cho các đơn hàng hiện có. Nó phụ thuộc vào thời điểm thay đổi giá so với trạng thái của đơn hàng.

                                                                                        Điểm 3 đặc biệt rõ ràng khi chúng ta xem xét các đơn hàng đã lưu trữ mà đã được giao. Chúng tất nhiên nên hiển thị giá vào thời điểm chúng được thực hiện, chứ không phải giá hiện tại.

                                                                                        Figure 6.11. Price is copied into Line Item. AGGREGATE invariant can now be enforced.

                                                                                        graphics/06fig11.gif

                                                                                        Một triển khai phù hợp với mô hình này sẽ đảm bảo tính bất biến liên quan đến PO và các mặt hàng của nó, trong khi những thay đổi về giá của một linh kiện sẽ không cần phải ảnh hưởng ngay lập tức đến các mặt hàng tham chiếu đến nó. Các quy tắc nhất quán rộng hơn có thể được giải quyết theo những cách khác. Ví dụ, hệ thống có thể trình bày một hàng đợi các mặt hàng có giá lỗi thời cho người dùng mỗi ngày, để họ có thể cập nhật hoặc miễn trừ mỗi mặt hàng. Nhưng đây không phải là một bất biến cần được thực thi mọi lúc. Bằng cách làm cho sự phụ thuộc của các mặt hàng dòng vào các linh kiện lỏng lẻo hơn, chúng ta tránh được sự tranh chấp và phản ánh tốt hơn thực tế của doanh nghiệp. Đồng thời, việc thắt chặt mối quan hệ giữa PO và các mặt hàng dòng đảm bảo rằng một quy tắc kinh doanh quan trọng sẽ được tuân thủ.

                                                                                        AGGREGATE áp đặt quyền sở hữu đối với PO và các mặt hàng của nó theo cách nhất quán với thực tiễn kinh doanh. Việc tạo ra và xóa PO cũng như các mặt hàng tự nhiên có mối liên hệ chặt chẽ với nhau, trong khi việc tạo ra và xóa các bộ phận là độc lập.

                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                        CÁC TỔNG HỢP đánh dấu phạm vi trong đó các đặc tính không thay đổi phải được duy trì ở mỗi giai đoạn của vòng đời. Các mẫu sau đây, NHÀ MÁY và KHO, hoạt động trên CÁC TỔNG HỢP, bao bọc sự phức tạp của các chuyển tiếp vòng đời cụ thể.


                                                                                          Factories

                                                                                          graphics/06inf02.gif

                                                                                          Khi việc tạo ra một đối tượng hoặc một TỔNG HỢP hoàn chỉnh trở nên phức tạp hoặc tiết lộ quá nhiều về cấu trúc bên trong, CÁC NHÀ MÁY cung cấp sự đóng gói.

                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                          Nhiều sức mạnh của các đối tượng nằm ở cấu hình phức tạp của phần bên trong và các mối quan hệ của chúng. Một đối tượng nên được tinh chế cho đến khi không còn gì tồn tại mà không liên quan đến ý nghĩa của nó hoặc hỗ trợ vai trò của nó trong các tương tác. Trách nhiệm trong giai đoạn giữa của vòng đời này là rất nhiều. Vấn đề nảy sinh từ việc nạp quá nhiều trách nhiệm cho một đối tượng phức tạp về việc tự tạo ra chính nó.

                                                                                          Một động cơ ô tô là một bộ máy phức tạp, với hàng chục bộ phận phối hợp để thực hiện trách nhiệm của động cơ: quay một trục. Ai đó có thể tưởng tượng việc thiết kế một khối động cơ có thể nắm bắt một bộ pít-tông và lắp chúng vào các xi lanh, những bugi sẽ tìm đến ổ cắm của chúng và tự vặn vào. Nhưng có vẻ không thể tin rằng một cỗ máy phức tạp như vậy sẽ đáng tin cậy hoặc hiệu quả như những động cơ mà chúng ta thường thấy. Thay vào đó, chúng ta chấp nhận rằng có một yếu tố khác sẽ lắp ráp các bộ phận này. Có thể đó sẽ là một thợ cơ khí con người hoặc có thể đó sẽ là một robot công nghiệp. Cả robot và con người thực sự phức tạp hơn động cơ mà họ lắp ráp. Công việc lắp ráp các bộ phận hoàn toàn không liên quan đến công việc quay một trục. Những người lắp ráp chỉ hoạt động trong quá trình tạo ra xe ô tô — bạn không cần một robot hoặc một thợ cơ khí bên cạnh khi bạn lái xe. Bởi vì xe ô tô không bao giờ được lắp ráp và lái cùng một lúc, không có giá trị nào trong việc kết hợp cả hai chức năng này vào cùng một cơ chế. Tương tự, việc lắp ráp một đối tượng phức tạp là công việc tốt nhất nên tách biệt khỏi bất kỳ công việc nào mà đối tượng đó sẽ phải làm khi nó hoàn tất.

                                                                                          Nhưng việc chuyển giao trách nhiệm cho bên liên quan khác, đối tượng khách hàng trong ứng dụng, dẫn đến những vấn đề tồi tệ hơn. Khách hàng biết công việc gì cần phải được thực hiện và dựa vào các đối tượng miền để thực hiện các tính toán cần thiết. Nếu khách hàng được kỳ vọng sẽ lắp ráp các đối tượng miền mà nó cần, nó phải biết một điều gì đó về cấu trúc nội bộ của đối tượng. Để đảm bảo tất cả các bất biến áp dụng cho mối quan hệ của các phần trong đối tượng miền, khách hàng phải biết một số quy tắc của đối tượng. Ngay cả việc gọi các hàm tạo cũng khiến khách hàng gắn bó với các lớp cụ thể của các đối tượng mà nó đang xây dựng. Không thể thực hiện bất kỳ thay đổi nào cho việc triển khai của các đối tượng miền mà không làm thay đổi khách hàng, điều này làm cho việc tái cấu trúc trở nên khó khăn hơn.

                                                                                          Một khách hàng thực hiện việc tạo đối tượng sẽ trở nên phức tạp một cách không cần thiết và làm mờ trách nhiệm của nó. Điều này vi phạm tính đóng gói của các đối tượng miền và các TỔNG HỢP đang được tạo ra. Tệ hơn nữa, nếu khách hàng là một phần của lớp ứng dụng, thì trách nhiệm đã bị rò rỉ ra khỏi lớp miền hoàn toàn. Việc liên kết chặt chẽ ứng dụng với các chi tiết cụ thể của việc triển khai sẽ loại bỏ hầu hết các lợi ích của sự trừu tượng trong lớp miền và làm cho việc thay đổi tiếp theo trở nên tốn kém hơn.

                                                                                          Việc tạo ra một đối tượng có thể là một thao tác lớn tự nó, nhưng các thao tác lắp ráp phức tạp không phù hợp với trách nhiệm của các đối tượng được tạo ra. Kết hợp những trách nhiệm như vậy có thể tạo ra những thiết kế lôi thôi khó hiểu. Việc để khách hàng trực tiếp xây dựng làm cho thiết kế của khách hàng trở nên mơ hồ, vi phạm tính đóng gói của đối tượng được lắp ráp hoặc TỔNG HỢP, và làm tăng quá mức sự phụ thuộc của khách hàng vào việc triển khai của đối tượng được tạo ra.

                                                                                          Việc tạo ra các đối tượng phức tạp là trách nhiệm của lớp miền, tuy nhiên nhiệm vụ đó không thuộc về các đối tượng thể hiện mô hình. Có một số trường hợp mà việc tạo ra và lắp ráp đối tượng tương ứng với một cột mốc quan trọng trong miền, chẳng hạn như "mở một tài khoản ngân hàng." Nhưng việc tạo ra và lắp ráp đối tượng thường không có ý nghĩa gì trong miền; chúng là một nhu cầu của việc triển khai. Để giải quyết vấn đề này, chúng ta cần thêm các cấu trúc vào thiết kế miền mà không phải là THỰC THỂ, ĐỐI TƯỢNG GIÁ TRỊ hoặc DỊCH VỤ. Đây là một sự khác biệt so với chương trước, và điều quan trọng là phải làm rõ điều này: Chúng ta đang thêm các yếu tố vào thiết kế mà không tương ứng với bất kỳ điều gì trong mô hình, nhưng chúng vẫn nằm trong trách nhiệm của lớp miền.

                                                                                          Mỗi ngôn ngữ lập trình hướng đối tượng đều cung cấp một cơ chế để tạo ra các đối tượng (các hàm khởi tạo trong Java và C++, các phương thức tạo thể trong Smalltalk, chẳng hạn), nhưng có nhu cầu về các cơ chế xây dựng trừu tượng hơn, tách rời khỏi các đối tượng khác. Một phần tử của chương trình có trách nhiệm là tạo ra các đối tượng khác được gọi là NHÀ MÁY.

                                                                                          Figure 6.12. Basic interactions with a FACTORY

                                                                                          graphics/06fig12.gif

                                                                                          Cũng giống như giao diện của một đối tượng nên bao bọc việc thực thi của nó, cho phép một khách hàng sử dụng hành vi của đối tượng mà không cần biết nó hoạt động như thế nào, một NHÀ MÁY bao bọc kiến thức cần thiết để tạo ra một đối tượng phức tạp hoặc TỔ HỢP. Nó cung cấp một giao diện phản ánh mục tiêu của khách hàng và một cái nhìn trừu tượng về đối tượng được tạo ra.

                                                                                          Vì vậy:

                                                                                          Chuyển giao trách nhiệm tạo ra các thể hiện của các đối tượng phức tạp và AGGREGATES cho một đối tượng riêng biệt, mà có thể bản thân nó không có trách nhiệm trong mô hình miền nhưng vẫn là một phần của thiết kế miền. Cung cấp một giao diện mà bao gồm tất cả các lắp ráp phức tạp và không yêu cầu khách hàng tham chiếu đến các lớp cụ thể của các đối tượng đang được khởi tạo. Tạo ra toàn bộ AGGREGATES như một phần, thi hành các bất biến của chúng.

                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                          Có nhiều cách để thiết kế CÁC NHÀ MÁY. Một số mẫu tạo ra có mục đích đặc biệt - PHƯƠNG PHÁP NHÀ MÁY, NHÀ MÁY TRỪU TƯỢNG, và NGƯỜI XÂY DỰNG - đã được trình bày kỹ lưỡng trong cuốn sách của Gamma và cộng sự năm 1995. Cuốn sách đó chủ yếu khám phá các mẫu cho những vấn đề xây dựng đối tượng khó khăn nhất. Điểm quan trọng ở đây không phải là đi sâu vào việc thiết kế CÁC NHÀ MÁY, mà thay vào đó là để chỉ ra vị trí của CÁC NHÀ MÁY như những thành phần quan trọng của một thiết kế miền. Việc sử dụng đúng CÁC NHÀ MÁY có thể giúp duy trì thiết kế DỰ ĐOÁN MÔ HÌNH.

                                                                                          Hai yêu cầu cơ bản cho bất kỳ nhà máy tốt nào là

                                                                                          1. Mỗi phương thức tạo ra là nguyên tử và đảm bảo tất cả các bất biến của đối tượng hoặc TỔ HỢP được tạo ra. Một NHÀ MÁY chỉ nên có khả năng tạo ra một đối tượng ở trạng thái nhất quán. Đối với một THỰC THỂ, điều này có nghĩa là việc tạo ra toàn bộ TỔ HỢP, với tất cả các bất biến được thỏa mãn, nhưng có thể vẫn còn các phần tử tùy chọn cần được thêm vào. Đối với một ĐỐI TƯỢNG GIÁ TRỊ bất biến, điều này có nghĩa là tất cả các thuộc tính được khởi tạo về trạng thái cuối cùng đúng của chúng. Nếu giao diện cho phép yêu cầu một đối tượng mà không thể được tạo ra đúng cách, thì một ngoại lệ nên được ném ra hoặc một cơ chế khác nên được gọi ra để đảm bảo rằng không có giá trị trả về không hợp lệ nào có thể xảy ra.

                                                                                          Nhà MÁY nên được trừu tượng hóa theo loại mong muốn, thay vì các lớp cụ thể được tạo ra. Các mẫu NHÀ MÁY tinh vi trong tài liệu của Gamma và các cộng sự năm 1995 giúp điều này.

                                                                                          Choosing FACTORIES and Their Sites

                                                                                          Nói chung, bạn tạo một nhà máy để xây dựng một cái gì đó mà bạn muốn ẩn chi tiết, và bạn đặt NHÀ MÁY ở nơi bạn muốn có quyền kiểm soát. Những quyết định này thường xoay quanh CÁC TỔNG HỢP.

                                                                                          Ví dụ, nếu bạn cần thêm các phần tử vào bên trong một AGGREGATE đã tồn tại, bạn có thể tạo một PHƯƠNG THỨC CHẾ TẠO trên nút gốc của AGGREGATE. Điều này ẩn đi việc triển khai nội bộ của AGGREGATE từ bất kỳ khách hàng bên ngoài nào, đồng thời giao cho nút gốc trách nhiệm đảm bảo tính toàn vẹn của AGGREGATE khi các phần tử được thêm vào, như được trình bày trong Hình 6.13 ở trang tiếp theo.

                                                                                          Figure 6.13. A FACTORY METHOD encapsulates expansion of an AGGREGATE.

                                                                                          graphics/06fig13.gif

                                                                                          Một ví dụ khác là đặt một PHƯƠNG THỨC NHÀ MÁY trên một đối tượng có liên quan mật thiết trong việc sinh ra một đối tượng khác, mặc dù nó không sở hữu sản phẩm sau khi được tạo ra. Khi dữ liệu và có thể là các quy tắc của một đối tượng rất mạnh mẽ trong việc tạo ra một đối tượng, điều này giúp tiết kiệm việc kéo thông tin ra khỏi đối tượng tạo ra để sử dụng ở nơi khác để tạo đối tượng. Nó cũng truyền đạt mối quan hệ đặc biệt giữa đối tượng tạo ra và sản phẩm.

                                                                                          Trong Hình 6.14, Đơn Đặt Hàng không thuộc cùng một TỔNG HỢP với Tài Khoản Môi Giới vì, trước hết, nó sẽ tương tác với ứng dụng thực hiện giao dịch, nơi mà Tài Khoản Môi Giới chỉ gây cản trở. Tuy nhiên, có vẻ tự nhiên khi giao quyền kiểm soát việc tạo Đơn Đặt Hàng cho Tài Khoản Môi Giới. Tài Khoản Môi Giới chứa thông tin sẽ được nhúng vào Đơn Đặt Hàng (bắt đầu với chính danh tính của nó), và nó chứa các quy tắc điều chỉnh những giao dịch nào được phép. Chúng ta cũng có thể hưởng lợi từ việc ẩn đi việc cài đặt của Đơn Đặt Hàng. Ví dụ, nó có thể được tái cấu trúc thành một phân cấp, với các lớp con riêng biệt cho Đơn Mua và Đơn Bán. NHÀ MÁY giữ cho khách hàng không bị ràng buộc với các lớp cụ thể.

                                                                                          Figure 6.14. A FACTORY METHOD spawns an ENTITY that is not part of the same AGGREGATE.

                                                                                          graphics/06fig14.gif

                                                                                          MỘT NHÀ MÁY rất chặt chẽ liên kết với sản phẩm của nó, vì vậy MỘT NHÀ MÁY nên chỉ được gắn liền với một đối tượng có mối quan hệ tự nhiên gần gũi với sản phẩm. Khi có điều gì đó mà chúng ta muốn che giấu—hoặc là việc triển khai cụ thể, hoặc là sự phức tạp trong việc xây dựng—nhưng dường như không có một chủ thể tự nhiên, chúng ta phải tạo ra một đối tượng NHÀ MÁY hoặc DỊCH VỤ chuyên dụng. Một NHÀ MÁY độc lập thường sản xuất toàn bộ TỔ HỢP, cung cấp một tham chiếu đến gốc, và đảm bảo rằng các bất biến của sản phẩm TỔ HỢP được duy trì. Nếu một đối tượng bên trong TỔ HỢP cần một NHÀ MÁY, và gốc TỔ HỢP không phải là nơi hợp lý cho nó, thì hãy tiến hành tạo một NHÀ MÁY độc lập. Nhưng hãy tôn trọng các quy tắc giới hạn quyền truy cập trong TỔ HỢP, và đảm bảo chỉ có các tham chiếu tạm thời đến sản phẩm từ bên ngoài TỔ HỢP.

                                                                                          Figure 6.15. A standalone FACTORY builds AGGREGATE.

                                                                                          graphics/06fig15.gif

                                                                                          When a Constructor Is All You Need

                                                                                          Tôi đã thấy quá nhiều mã trong đó tất cả các thể hiện được tạo ra bằng cách gọi trực tiếp các hàm tạo lớp, hoặc bất cứ cấp độ nguyên thủy nào của việc tạo thể hiện cho ngôn ngữ lập trình. Việc giới thiệu CÁC NHÀ MÁY có nhiều lợi thế to lớn, và thường thì không được sử dụng nhiều. Tuy nhiên, có những lúc độ trực tiếp của một hàm tạo khiến nó trở thành sự lựa chọn tốt nhất. CÁC NHÀ MÁY thực sự có thể làm mờ đi các đối tượng đơn giản không sử dụng đa hình.

                                                                                          Các trọng số ưu tiên một hàm khởi tạo công khai tối giản trong các trường hợp sau.

                                                                                          • Lớp là kiểu. Nó không phải là một phần của bất kỳ hệ thống phân cấp thú vị nào, và nó không được sử dụng đa hình bằng cách triển khai một giao diện.

                                                                                          • Khách hàng quan tâm đến việc thực hiện, có thể như một cách để lựa chọn một CHIẾN LƯỢC.

                                                                                          • Tất cả các thuộc tính của đối tượng đều có sẵn cho khách hàng, vì vậy không có việc tạo đối tượng nào bị lồng ghép bên trong hàm tạo mà được công khai cho khách hàng.

                                                                                          • Công việc xây dựng không phức tạp.

                                                                                          • Một constructor công khai phải tuân theo các quy tắc giống như một FACTORY: Nó phải là một thao tác nguyên tử mà thoả mãn tất cả các bất biến của đối tượng được tạo ra.

                                                                                          Tránh gọi các hàm khởi tạo (constructor) trong các hàm khởi tạo của các lớp khác. Các hàm khởi tạo nên đơn giản hết mức có thể. Những cấu trúc phức tạp, đặc biệt là của CÁC TỔ HỢP, nên được xử lý bằng CÁC NHÀ MÁY (FACTORIES). Ngưỡng để quyết định sử dụng một ít PHƯƠNG THỨC NHÀ MÁY (FACTORY METHOD) không quá cao.

                                                                                          Thư viện lớp Java cung cấp những ví dụ thú vị. Tất cả các collections đều triển khai các giao diện giúp tách biệt khách hàng khỏi việc thực hiện cụ thể. Tuy nhiên, tất cả đều được tạo ra bằng cách gọi trực tiếp các bộ khởi tạo. Một NHÀ MÁY có thể đã bao encapsulated hệ thống phân cấp collection. Các phương thức của NHÀ MÁY có thể cho phép một khách hàng yêu cầu những tính năng mà họ cần, với NHÀ MÁY chọn lớp phù hợp để khởi tạo. Mã mà tạo ra các collections sẽ trở nên diễn đạt hơn, và các lớp collection mới có thể được cài đặt mà không làm hỏng mọi chương trình Java.

                                                                                          Nhưng có một trường hợp ủng hộ các bộ xây dựng cụ thể. Đầu tiên, việc lựa chọn triển khai có thể nhạy cảm về hiệu suất đối với nhiều ứng dụng, vì vậy một ứng dụng có thể muốn kiểm soát. (Dù vậy, một FACTORY thực sự thông minh có thể thích ứng với những yếu tố như vậy.) Dù sao đi nữa, không có nhiều lớp bộ sưu tập, vì vậy việc chọn lựa không quá phức tạp.

                                                                                          Các loại tập hợp trừu tượng bảo tồn một số giá trị mặc dù thiếu một NHÀ MÁY do các mẫu sử dụng của chúng. Các tập hợp thường được tạo ra ở một nơi và được sử dụng ở nơi khác. Điều này có nghĩa là client cuối cùng sử dụng tập hợp—thêm, xóa và truy xuất nội dung của nó—vẫn có thể giao tiếp với giao diện và tách biệt khỏi triển khai. Việc chọn một lớp tập hợp thường thuộc về đối tượng sở hữu tập hợp, hoặc đến NHÀ MÁY của đối tượng sở hữu.

                                                                                          Designing the Interface

                                                                                          Khi thiết kế chữ ký phương thức của một NHÀ MÁY, cho dù là độc lập hay PHƯƠNG THỨC NHÀ MÁY, hãy ghi nhớ hai điểm sau đây.

                                                                                          • Mỗi thao tác phải là nguyên tử. Bạn phải truyền vào tất cả mọi thứ cần thiết để tạo ra một sản phẩm hoàn chỉnh trong một tương tác duy nhất với NHÀ MÁY. Bạn cũng phải quyết định điều gì sẽ xảy ra nếu việc tạo ra thất bại, trong trường hợp một số bất biến không được thỏa mãn. Bạn có thể ném một ngoại lệ hoặc chỉ trả về null. Để nhất quán, hãy xem xét việc áp dụng một tiêu chuẩn lập trình cho các trường hợp thất bại trong NHÀ MÁY.

                                                                                          • NHÀ MÁY sẽ được kết nối với các tham số của nó. Nếu bạn không cẩn thận trong việc chọn các tham số đầu vào, bạn có thể tạo ra một mớ hỗn độn của các phụ thuộc. Mức độ kết nối sẽ phụ thuộc vào cách bạn xử lý tham số. Nếu nó chỉ được cắm vào sản phẩm, bạn đã tạo ra một phụ thuộc khiêm tốn. Nếu bạn đang chọn các phần từ tham số để sử dụng trong quá trình xây dựng, sự kết nối sẽ chặt chẽ hơn.

                                                                                          Các tham số an toàn nhất là những tham số từ một lớp thiết kế thấp hơn. Ngay cả trong một lớp, thường có những lớp tự nhiên với các đối tượng cơ bản hơn được sử dụng bởi các đối tượng cấp cao hơn. (Việc phân lớp như vậy sẽ được thảo luận theo nhiều cách khác nhau trong Chương 10, "Thiết kế Linh hoạt," và một lần nữa trong Chương 16, "Cấu trúc Quy mô Lớn.")

                                                                                          Một lựa chọn tốt khác cho tham số là một đối tượng có liên quan chặt chẽ đến sản phẩm trong mô hình, để không thêm phụ thuộc mới. Trong ví dụ trước về Mục Đơn Đặt Hàng, PHƯƠNG THỨC NHÀ MÁY nhận một Phần Danh Mục làm tham số, đây là một mối liên hệ thiết yếu cho Mục. Điều này tạo ra một phụ thuộc trực tiếp giữa lớp Đơn Đặt Hàng và Phần. Nhưng ba đối tượng này hình thành một nhóm khái niệm chặt chẽ. AGGREGATE của Đơn Đặt Hàng đã tham chiếu đến Phần rồi, dù sao đi nữa. Vì vậy, việc giao quyền kiểm soát cho gốc AGGREGATE và bao bọc cấu trúc nội bộ của AGGREGATE là một sự đánh đổi hợp lý.

                                                                                          Sử dụng kiểu trừu tượng của các tham số, không phải là các lớp cụ thể của chúng. FACTORY được liên kết với lớp cụ thể của các sản phẩm; nó không cần thiết phải liên kết với các tham số cụ thể.

                                                                                          Where Does Invariant Logic Go?

                                                                                          MỘT NHÀ MÁY có trách nhiệm đảm bảo rằng tất cả các invariant được đáp ứng đối với đối tượng hoặc TẬP HỢP mà nó tạo ra; tuy nhiên, bạn nên luôn suy nghĩ kỹ trước khi loại bỏ các quy tắc áp dụng cho một đối tượng bên ngoài đối tượng đó. NHÀ MÁY có thể ủy quyền việc kiểm tra invariant cho sản phẩm, và điều này thường là tốt nhất.

                                                                                          Nhưng CÁC NHÀ MÁY có mối quan hệ đặc biệt với sản phẩm của họ. Họ đã biết cấu trúc bên trong của sản phẩm và lý do tồn tại của họ bao gồm việc thực hiện sản phẩm của họ. Dưới một số hoàn cảnh, có lợi ích khi đặt logic không thay đổi trong NHÀ MÁY và giảm sự lộn xộn trong sản phẩm. Điều này đặc biệt hấp dẫn với các quy tắc TỔ HỢP (bao trùm nhiều đối tượng). Nó đặc biệt không hấp dẫn với CÁC PHƯƠNG THỨC NHÀ MÁY gắn liền với các đối tượng miền khác.

                                                                                          Dù về nguyên tắc, các bất biến áp dụng vào cuối mỗi thao tác, nhưng thường thì các biến đổi cho phép đối với đối tượng không bao giờ có thể đưa chúng vào áp dụng. Có thể có một quy tắc áp dụng cho việc gán các thuộc tính định danh của một ENTITY. Nhưng sau khi được tạo ra, danh tính đó là bất biến. VALUE OBJECT hoàn toàn là bất biến. Một đối tượng không cần phải mang theo logic mà sẽ không bao giờ được áp dụng trong vòng đời hoạt động của nó. Trong những trường hợp như vậy, FACTORY là một nơi hợp lý để đặt các bất biến, giữ cho sản phẩm đơn giản hơn.

                                                                                          ENTITY FACTORIES Versus VALUE OBJECT FACTORIES

                                                                                          CÁC NHÀ MÁY THỰC THỂ khác với CÁC NHÀ MÁY ĐỐI TƯỢNG GIÁ TRỊ ở hai điểm. CÁC ĐỐI TƯỢNG GIÁ TRỊ là Không thay đổi; sản phẩm được ra mắt hoàn chỉnh trong hình thức cuối cùng của nó. Vì vậy, các thao tác NHÀ MÁY phải cho phép một mô tả đầy đủ về sản phẩm. CÁC NHÀ MÁY THỰC THỂ thường chỉ lấy những thuộc tính thiết yếu cần thiết để tạo ra một TỔ HỢP hợp lệ. Các chi tiết có thể được thêm vào sau này nếu chúng không cần thiết theo một bất biến.

                                                                                          Sau đó, có những vấn đề liên quan đến việc gán danh tính cho một THỰC THỂ - không liên quan đến MỤC GIÁ TRỊ. Như đã chỉ ra trong Chương 5, một định danh có thể được gán tự động bởi chương trình hoặc được cung cấp từ bên ngoài, thường là bởi người dùng. Nếu cần theo dõi danh tính của một khách hàng qua số điện thoại, thì số điện thoại đó rõ ràng phải được truyền vào như một đối số cho NHÀ MÁY. Khi chương trình gán một định danh, NHÀ MÁY là một nơi tốt để kiểm soát điều đó. Mặc dù việc tạo ra một ID theo dõi duy nhất thường được thực hiện bởi "chuỗi" của cơ sở dữ liệu hoặc các cơ chế hạ tầng khác, NHÀ MÁY biết cần yêu cầu điều gì và đặt vào đâu.

                                                                                          Reconstituting Stored Objects

                                                                                          Đến thời điểm này, NHÀ MÁY đã thực hiện vai trò của mình trong những giai đoạn đầu của vòng đời một đối tượng. Vào một thời điểm nào đó, hầu hết các đối tượng sẽ được lưu trữ trong cơ sở dữ liệu hoặc truyền qua mạng, và rất ít công nghệ cơ sở dữ liệu hiện tại duy trì tính chất đối tượng của nội dung của chúng. Hầu hết các phương pháp truyền tải làm phẳng một đối tượng thành một hình thức trình bày hạn chế hơn. Do đó, việc truy xuất đòi hỏi một quy trình có thể phức tạp để tái lắp ráp các phần thành một đối tượng sống.

                                                                                          Một nhà máy được sử dụng để tái cấu trúc rất giống với một nhà máy được sử dụng để tạo ra, với hai sự khác biệt chính.

                                                                                          1. Một NHÀ MÁY THỰC THỂ được sử dụng để tái cấu trúc không gán một ID theo dõi mới. Nếu làm như vậy sẽ mất sự liên tục với hiện thân trước đó của đối tượng. Do đó, các thuộc tính xác định phải là một phần của các tham số đầu vào trong một NHÀ MÁY tái cấu trúc một đối tượng đã được lưu trữ.

                                                                                          Một NHÀ MÁY tái cấu trúc một đối tượng sẽ xử lý vi phạm của một bất biến theo cách khác nhau. Trong quá trình tạo ra một đối tượng mới, một NHÀ MÁY nên chỉ đơn giản là từ chối khi một bất biến không được đáp ứng, nhưng một phản ứng linh hoạt hơn có thể cần thiết trong quá trình tái cấu trúc. Nếu một đối tượng đã tồn tại ở đâu đó trong hệ thống (như trong cơ sở dữ liệu), điều này không thể bị phớt lờ. Tuy nhiên, chúng ta cũng không thể phớt lờ vi phạm quy tắc. Phải có một chiến lược nào đó để sửa chữa những bất đồng như vậy, điều này có thể làm cho việc tái cấu trúc trở nên khó khăn hơn so với việc tạo ra các đối tượng mới.

                                                                                          Hình 6.16 và 6.17 (trang tiếp theo) cho thấy hai loại tái cấu trúc. Các công nghệ lập bản đồ đối tượng có thể cung cấp một phần hoặc toàn bộ các dịch vụ này trong trường hợp tái cấu trúc cơ sở dữ liệu, điều này rất tiện lợi. Bất cứ khi nào có sự phức tạp lộ ra trong việc tái cấu trúc một đối tượng từ một phương tiện khác, FACTORY là một lựa chọn tốt.

                                                                                          Figure 6.16. Reconstituting an ENTITY retrieved from a relational database

                                                                                          graphics/06fig16.gif

                                                                                          Figure 6.17. Reconstituting an ENTITY transmitted as XML

                                                                                          graphics/06fig17.gif

                                                                                          Tóm lại, các điểm truy cập để tạo ra các thể hiện cần phải được xác định, và phạm vi của chúng phải được định nghĩa rõ ràng. Chúng có thể đơn giản chỉ là các hàm khởi tạo, nhưng thường có nhu cầu sử dụng một cơ chế tạo thể hiện trừu tượng hoặc phức tạp hơn. Nhu cầu này giới thiệu các cấu trúc mới vào thiết kế: CÁC NHÀ MÁY. CÁC NHÀ MÁY thường không diễn đạt bất kỳ phần nào của mô hình, nhưng chúng là một phần của thiết kế miền giúp giữ cho các đối tượng diễn đạt mô hình được sắc nét.

                                                                                          MỘT NHÀ MÁY bao gồm các giai đoạn chuyển đổi của việc tạo ra và tái cấu trúc. Một giai đoạn chuyển đổi khác làm lộ ra sự phức tạp kỹ thuật có thể làm cho thiết kế miền bị ngợp là giai đoạn chuyển đổi đến và từ kho lưu trữ. Giai đoạn chuyển đổi này là trách nhiệm của một cấu trúc thiết kế miền khác, đó là KHO.


                                                                                            Repositories

                                                                                            graphics/06inf03.gif

                                                                                            Các mối quan hệ cho phép chúng ta tìm một đối tượng dựa trên mối quan hệ của nó với một đối tượng khác. Nhưng chúng ta phải có một điểm khởi đầu để bắt đầu hành trình đến một THỰC THỂ hoặc GIÁ TRỊ ở giữa vòng đời của nó.

                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                            Để làm bất kỳ điều gì với một đối tượng, bạn phải giữ một tham chiếu đến nó. Làm thế nào để bạn có được tham chiếu đó? Một cách là tạo ra đối tượng, vì thao tác tạo ra sẽ trả về một tham chiếu đến đối tượng mới. Một cách thứ hai là duyệt qua một sự liên kết. Bạn bắt đầu với một đối tượng mà bạn đã biết và hỏi nó về một đối tượng liên kết. Bất kỳ chương trình hướng đối tượng nào cũng sẽ thực hiện rất nhiều điều này, và những liên kết này mang lại cho các mô hình đối tượng phần lớn sức mạnh biểu đạt của chúng. Nhưng bạn phải có được đối tượng đầu tiên đó.

                                                                                            Tôi thực sự đã gặp một dự án một lần trong đó đội ngũ đang cố gắng, với sự nhiệt tình đón nhận THIẾT KẾ DỰA TRÊN MÔ HÌNH, để thực hiện tất cả việc truy cập đối tượng thông qua việc tạo ra hoặc duyệt! Các đối tượng của họ cư trú trong một cơ sở dữ liệu đối tượng, và họ lập luận rằng các mối quan hệ khái niệm hiện có sẽ cung cấp tất cả các liên kết cần thiết. Họ chỉ cần phân tích chúng đủ sâu, để làm cho toàn bộ mô hình miền của họ trở nên nhất quán. Giới hạn do họ tự đặt ra buộc họ phải tạo ra đúng loại mớ bùng nhùng vô tận mà chúng tôi đã cố gắng tránh trong vài chương trước, với việc thực hiện cẩn thận các THỰC THỂ và ứng dụng của CỤM. Các thành viên trong đội không kiên trì với chiến lược này lâu, nhưng họ cũng không thay thế nó bằng một phương pháp nhất quán nào khác. Họ đã ghép nối các giải pháp ad hoc và trở nên ít tham vọng hơn.

                                                                                            Ít người thậm chí còn nghĩ đến cách tiếp cận này, huống chi là bị cám dỗ bởi nó, vì họ lưu trữ hầu hết các đối tượng của mình trong các cơ sở dữ liệu quan hệ. Công nghệ lưu trữ này khiến việc sử dụng cách thứ ba để lấy tham chiếu trở nên tự nhiên: Thực hiện một truy vấn để tìm đối tượng trong cơ sở dữ liệu dựa trên các thuộc tính của nó, hoặc tìm các thành phần của một đối tượng và sau đó tái tạo lại nó.

                                                                                            Tìm kiếm cơ sở dữ liệu có thể truy cập toàn cầu và cho phép đi trực tiếp đến bất kỳ đối tượng nào. Không cần thiết phải kết nối tất cả các đối tượng với nhau, điều này giúp chúng ta giữ cho mạng lưới các đối tượng dễ quản lý. Việc cung cấp một quá trình duyệt hay dựa vào tìm kiếm trở thành một quyết định thiết kế, cân nhắc giữa việc tách biệt tìm kiếm và tính kết nối của mối quan hệ. Liệu đối tượng Khách hàng có nên giữ một tập hợp tất cả các Đơn hàng đã đặt không? Hay các Đơn hàng nên được tìm thấy trong cơ sở dữ liệu, thông qua tìm kiếm trên trường ID Khách hàng? Sự kết hợp đúng đắn giữa tìm kiếm và mối quan hệ khiến cho thiết kế dễ hiểu hơn.

                                                                                            Rất tiếc, các nhà phát triển thường không có cơ hội suy nghĩ nhiều về những tinh tế trong thiết kế như vậy, vì họ đang phải đối mặt với rất nhiều cơ chế cần thiết để thực hiện việc lưu trữ một đối tượng và đưa nó trở lại - và cuối cùng là loại bỏ nó khỏi kho lưu trữ.

                                                                                            Bây giờ, từ góc độ kỹ thuật, việc truy xuất một đối tượng đã lưu thực sự là một phần của việc tạo ra, vì dữ liệu từ cơ sở dữ liệu được sử dụng để lắp ráp các đối tượng mới. Thật vậy, mã mà thường phải được viết làm cho khó quên thực tế này. Nhưng xét về khái niệm, đây là giữa vòng đời của một THỰC THỂ. Một đối tượng Khách hàng không đại diện cho một khách hàng mới chỉ vì chúng ta đã lưu nó trong cơ sở dữ liệu và truy xuất nó. Để giữ sự phân biệt này trong tâm trí, tôi gọi việc tạo ra một phiên bản từ dữ liệu đã lưu là sự tái cấu trúc.

                                                                                            Mục tiêu của thiết kế dựa trên miền là tạo ra phần mềm tốt hơn bằng cách tập trung vào mô hình của miền thay vì công nghệ. Khi một lập trình viên đã xây dựng một truy vấn SQL, truyền nó đến một dịch vụ truy vấn trong lớp hạ tầng, nhận được một tập kết quả là các hàng bảng, lấy thông tin cần thiết ra, và chuyển nó đến một trình xây dựng hoặc NHÀ MÁY, sự tập trung vào mô hình đã biến mất. Thật tự nhiên khi nghĩ về các đối tượng như những container cho dữ liệu mà các truy vấn cung cấp, và toàn bộ thiết kế chuyển sang phong cách xử lý dữ liệu. Các chi tiết của công nghệ khác nhau, nhưng vấn đề vẫn là khách hàng đang làm việc với công nghệ, thay vì các khái niệm của mô hình. Cơ sở hạ tầng như CÁC LỚP ÁNH XẠ METADATA (Fowler 2002) giúp rất nhiều, bằng cách thực hiện việc chuyển đổi kết quả truy vấn thành các đối tượng dễ dàng hơn, nhưng lập trình viên vẫn đang nghĩ về các cơ chế kỹ thuật, không phải là miền. Tệ hơn, khi mã của khách hàng sử dụng cơ sở dữ liệu trực tiếp, các lập trình viên bị cám dỗ để bỏ qua các tính năng của mô hình như TẬP HỢP, hoặc thậm chí việc bao gói đối tượng, thay vào đó trực tiếp lấy và thao tác với dữ liệu mà họ cần. Ngày càng có nhiều quy tắc miền được nhúng trong mã truy vấn hoặc đơn giản là bị mất. Cơ sở dữ liệu đối tượng không loại bỏ vấn đề chuyển đổi, nhưng các cơ chế tìm kiếm thường vẫn mang tính cơ khí, và các lập trình viên vẫn bị cám dỗ để lấy bất kỳ đối tượng nào họ muốn.

                                                                                            Một khách hàng cần một phương tiện thực tiễn để thu được tham chiếu đến các đối tượng miền đã tồn tại. Nếu hạ tầng làm cho điều này trở nên dễ dàng, các nhà phát triển của khách hàng có thể thêm nhiều mối quan hệ có thể duyệt, làm rối mô hình. Mặt khác, họ có thể sử dụng truy vấn để lấy đúng dữ liệu họ cần từ cơ sở dữ liệu, hoặc để lấy một vài đối tượng cụ thể thay vì di chuyển từ các nút GỘP. Logic miền di chuyển vào các truy vấn và mã khách hàng, và CÁC ĐỐI TƯỢNG và ĐỐI TƯỢNG GIÁ TRỊ trở thành những thùng chứa dữ liệu đơn thuần. Độ phức tạp kỹ thuật thuần túy khi áp dụng hầu hết hạ tầng truy cập cơ sở dữ liệu nhanh chóng làm cho mã khách hàng bị ngập lụt, điều này dẫn đến việc các nhà phát triển phải đơn giản hóa lớp miền, khiến mô hình trở nên không còn liên quan.

                                                                                            Dựa trên các nguyên tắc thiết kế đã được thảo luận cho đến nay, chúng ta có thể thu hẹp vấn đề truy cập đối tượng một chút, với điều kiện chúng ta tìm ra một phương pháp truy cập giữ cho trọng tâm mô hình đủ sắc nét để áp dụng những nguyên tắc đó. Đầu tiên, chúng ta không cần phải lo lắng về các đối tượng tạm thời. Các đối tượng tạm thời (thường là CÁC ĐỐI TƯỢNG GIÁ TRỊ) có cuộc sống ngắn ngủi, được sử dụng trong hoạt động của khách hàng mà tạo ra chúng và sau đó bị bỏ đi. Chúng ta cũng không cần truy cập truy vấn cho các đối tượng bền vững mà thuận tiện hơn để tìm kiếm bằng cách duyệt. Ví dụ, địa chỉ của một người có thể được yêu cầu từ đối tượng Person. Và điều quan trọng nhất, bất kỳ đối tượng nào bên trong một TỔ HỢP đều bị cấm truy cập ngoại trừ việc duyệt từ gốc.

                                                                                            Các ĐỐI TƯỢNG GIÁ TRỊ BỀN VỮNG thường được tìm thấy bằng cách duyệt từ một THỰC THỂ nào đó đóng vai trò là gốc của TỔ HỢP mà bao encapsulate chúng. Thực tế, việc truy cập tìm kiếm toàn cầu vào một GIÁ TRỊ thường vô nghĩa, vì việc tìm kiếm một GIÁ TRỊ theo các thuộc tính của nó sẽ tương đương với việc tạo ra một thể hiện mới với những thuộc tính đó. Tuy nhiên, vẫn có những trường hợp ngoại lệ. Ví dụ, khi tôi lập kế hoạch du lịch trực tuyến, đôi khi tôi lưu lại một vài hành trình tiềm năng và trở lại sau để chọn một trong số đó để đặt vé. Những hành trình đó là GIÁ TRỊ (nếu có hai hành trình bao gồm cùng một chuyến bay, tôi sẽ không quan tâm đến cái nào là cái nào), nhưng chúng đã được liên kết với tên người dùng của tôi và được truy xuất nguyên vẹn cho tôi. Một trường hợp khác là "liệt kê," khi một kiểu có một tập hợp giá trị có thể đã được xác định một cách hạn chế và cố định. Truy cập toàn cầu vào CÁC ĐỐI TƯỢNG GIÁ TRỊ ít phổ biến hơn nhiều so với CÁC THỰC THỂ, mặc dù, và nếu bạn thấy mình cần tìm kiếm cơ sở dữ liệu cho một GIÁ TRỊ đã tồn tại, thì đáng xem xét khả năng rằng bạn thực sự có một THỰC THỂ mà danh tính của nó bạn chưa nhận ra.

                                                                                            Từ cuộc thảo luận này, rõ ràng là hầu hết các đối tượng không nên được truy cập thông qua tìm kiếm toàn cầu. Thật tốt nếu thiết kế có thể truyền đạt những đối tượng mà có thể.

                                                                                            Bây giờ vấn đề có thể được diễn đạt một cách chính xác hơn.

                                                                                            Một tập con của các đối tượng kéo dài phải được truy cập toàn cầu thông qua tìm kiếm dựa trên thuộc tính của đối tượng. Sự truy cập như vậy là cần thiết cho các gốc của CÁC TẬP HỢP mà không thuận tiện để tiếp cận bằng cách duyệt. Chúng thường là CÁC THỰC THỂ, đôi khi là CÁC ĐỐI TƯỢNG GIÁ TRỊ với cấu trúc nội bộ phức tạp, và đôi khi là CÁC GIÁ TRỊ được liệt kê. Việc cung cấp quyền truy cập vào các đối tượng khác làm mờ đi những sự phân biệt quan trọng. Các truy vấn cơ sở dữ liệu tự do thực sự có thể vi phạm sự bao bọc của các đối tượng miền và CÁC TẬP HỢP. Việc lộ ra hạ tầng kỹ thuật và các cơ chế truy cập cơ sở dữ liệu làm phức tạp khách hàng và làm mờ ý tưởng THIẾT KẾ LÁI MÔ HÌNH.

                                                                                            Có rất nhiều kỹ thuật để giải quyết những thách thức kỹ thuật trong việc truy cập cơ sở dữ liệu. Ví dụ bao gồm việc bao bọc SQL vào các ĐỐI TƯỢNG TRUY VẤN hoặc dịch chuyển giữa các đối tượng và bảng thông qua các LỚP ÁNH XẠ THÔNG TIN (Fowler 2002). CÁC XƯỞNG có thể giúp tái cấu trúc các đối tượng đã lưu (như sẽ được thảo luận sau trong chương này). Những kỹ thuật này và nhiều kỹ thuật khác giúp giảm thiểu độ phức tạp.

                                                                                            Nhưng ngay cả như vậy, hãy lưu ý về những gì đã bị mất. Chúng ta không còn suy nghĩ về các khái niệm trong mô hình miền của mình. Mã của chúng ta sẽ không giao tiếp về doanh nghiệp; nó sẽ thao tác công nghệ truy xuất dữ liệu. Mô hình REPOSITORY là một khung khái niệm đơn giản để bao gồm những giải pháp đó và đưa trở lại sự tập trung vào mô hình của chúng ta.

                                                                                            Một KHO lưu trữ đại diện cho tất cả các đối tượng của một loại nhất định như một tập hợp khái niệm (thường được mô phỏng). Nó hoạt động giống như một bộ sưu tập, ngoại trừ khả năng truy vấn phức tạp hơn. Các đối tượng của loại phù hợp được thêm vào và xóa đi, và cơ chế đứng sau KHO lưu trữ sẽ chèn hoặc xóa chúng khỏi cơ sở dữ liệu. Định nghĩa này tập hợp một bộ trách nhiệm chặt chẽ để cung cấp quyền truy cập vào các gốc của CỤM từ giai đoạn đầu của vòng đời đến cuối.

                                                                                            Khách hàng yêu cầu các đối tượng từ KHO bằng các phương thức truy vấn chọn đối tượng dựa trên các tiêu chí được chỉ định bởi khách hàng, thường là giá trị của một số thuộc tính nhất định. KHO truy xuất đối tượng yêu cầu, đóng gói cơ chế của các truy vấn cơ sở dữ liệu và ánh xạ siêu dữ liệu. KHO có thể thực hiện nhiều loại truy vấn khác nhau để chọn đối tượng dựa trên bất kỳ tiêu chí nào mà khách hàng yêu cầu. Chúng cũng có thể trả về thông tin tóm tắt, chẳng hạn như số lượng bao nhiêu trường hợp đáp ứng một số tiêu chí. Chúng thậm chí có thể trả về các phép tính tóm tắt, chẳng hạn như tổng của tất cả các đối tượng phù hợp của một thuộc tính số nào đó.

                                                                                            Figure 6.18. A REPOSITORY doing a search for a client

                                                                                            graphics/06fig18.gif

                                                                                            Một REPOSITORY gánh vác một khối lượng lớn công việc từ phía client, cho phép client giao tiếp với một giao diện đơn giản, rõ ràng về ý định, và yêu cầu những gì cần thiết liên quan đến mô hình. Để hỗ trợ tất cả điều này cần rất nhiều hạ tầng kỹ thuật phức tạp, nhưng giao diện thì đơn giản và liên kết về mặt khái niệm với mô hình miền.

                                                                                            Do đó:

                                                                                            Đối với mỗi loại đối tượng cần truy cập toàn cầu, tạo ra một đối tượng có thể cung cấp ảo giác về một tập hợp tất cả các đối tượng của loại đó trong bộ nhớ. Thiết lập quyền truy cập thông qua một giao diện toàn cầu mà mọi người đều biết. Cung cấp các phương thức để thêm và xóa đối tượng, điều này sẽ bao gồm việc chèn hoặc loại bỏ dữ liệu thực sự trong kho dữ liệu. Cung cấp các phương thức chọn đối tượng dựa trên một số tiêu chí và trả về các đối tượng đã được khởi tạo hoàn toàn hoặc các tập hợp đối tượng có giá trị thuộc tính đáp ứng tiêu chí, do đó bao gói công nghệ lưu trữ và truy vấn thực tế. Cung cấp REPOSITORIES chỉ cho các gốc AGGREGATE thực sự cần truy cập trực tiếp. Giữ cho khách hàng tập trung vào mô hình, ủy quyền tất cả việc lưu trữ và truy cập đối tượng cho các REPOSITORIES.

                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                            CÁC KHO lưu trữ có nhiều lợi ích, bao gồm những điều sau đây:

                                                                                            • Họ cung cấp cho khách hàng một mô hình đơn giản để obtaining objects bền vững và quản lý vòng đời của chúng.

                                                                                            • Họ tách rời thiết kế ứng dụng và miền khỏi công nghệ lưu trữ, các chiến lược cơ sở dữ liệu đa dạng, hoặc thậm chí là nhiều nguồn dữ liệu khác nhau.

                                                                                            • Họ truyền đạt các quyết định thiết kế về việc truy cập đối tượng.

                                                                                            • Chúng cho phép thay thế dễ dàng một triển khai giả, để sử dụng trong việc kiểm tra (thường bằng cách sử dụng một bộ sưu tập trong bộ nhớ).

                                                                                            Querying a REPOSITORY

                                                                                            Tất cả các kho lưu trữ đều cung cấp các phương thức cho phép một khách hàng yêu cầu các đối tượng phù hợp với một số tiêu chí, nhưng có nhiều tùy chọn để thiết kế giao diện này.

                                                                                            Kho lưu trữ dễ nhất để xây dựng là những truy vấn đã được mã hóa cứng với các tham số cụ thể. Những truy vấn này có thể rất đa dạng: lấy một thực thể theo danh tính của nó (được cung cấp bởi hầu hết các kho lưu trữ); yêu cầu một tập hợp các đối tượng với một giá trị thuộc tính cụ thể hoặc một tổ hợp phức tạp của các tham số; chọn các đối tượng dựa trên khoảng giá trị (chẳng hạn như khoảng thời gian); và thậm chí thực hiện một số tính toán mà thuộc trách nhiệm chung của một kho lưu trữ (đặc biệt là dựa vào các thao tác được hỗ trợ bởi cơ sở dữ liệu cơ sở).

                                                                                            Mặc dù hầu hết các truy vấn trả về một đối tượng hoặc một tập hợp các đối tượng, nhưng nó cũng phù hợp với khái niệm trả về một số loại tính toán tóm tắt, chẳng hạn như số lượng đối tượng hoặc tổng cộng một thuộc tính số mà mô hình dự định được tính.

                                                                                            Figure 6.19. Hard-coded queries in a simple REPOSITORY

                                                                                            graphics/06fig19.gif

                                                                                            Các truy vấn được định sẵn có thể được xây dựng trên bất kỳ cơ sở hạ tầng nào và không cần nhiều vốn đầu tư, vì chúng chỉ thực hiện những gì mà một khách hàng nào đó cũng sẽ phải làm.

                                                                                            Trên những dự án có nhiều truy vấn, một framework REPOSITORY có thể được xây dựng cho phép thực hiện các truy vấn linh hoạt hơn. Điều này đòi hỏi đội ngũ nhân viên quen thuộc với công nghệ cần thiết và được hỗ trợ rất nhiều bởi một hạ tầng đồng bộ.

                                                                                            Một phương pháp đặc biệt phù hợp để tổng quát hóa CÁC KHO LƯU TRỮ thông qua một khung là sử dụng các truy vấn DỰ THẢO. Một DỰ THẢO cho phép một khách hàng mô tả (tức là, chỉ rõ) những gì họ muốn mà không quan tâm đến cách thức nó sẽ được đạt được. Trong quá trình này, một đối tượng có thể thực hiện việc lựa chọn thực sự được tạo ra. Mô hình này sẽ được thảo luận chi tiết trong Chương 9.

                                                                                            Figure 6.20. A flexible, declarative SPECIFICATION of search criteria in a sophisticated REPOSITORY

                                                                                            graphics/06fig20.gif

                                                                                            Câu truy vấn dựa trên ĐẶC TÍNH là thanh lịch và linh hoạt. Tùy thuộc vào cơ sở hạ tầng hiện có, nó có thể là một khuôn khổ khiêm tốn hoặc có thể rất khó khăn. Rob Mee và Edward Hieatt thảo luận về nhiều vấn đề kỹ thuật liên quan đến việc thiết kế các NGUỒN LƯU TRỮ như vậy trong Fowler 2002.

                                                                                            Ngay cả một thiết kế NHÀ LƯU TRỮ với các truy vấn linh hoạt cũng nên cho phép việc bổ sung các truy vấn cứng chuyên biệt. Chúng có thể là các phương thức tiện lợi đóng gói một truy vấn thường được sử dụng hoặc một truy vấn không trả về chính các đối tượng, chẳng hạn như một tổng hợp toán học của các đối tượng được chọn. Các khuôn khổ không cho phép những tình huống như vậy thường có xu hướng làm biến dạng thiết kế miền hoặc bị các nhà phát triển bỏ qua.

                                                                                            Client Code Ignores REPOSITORY Implementation; Developers Do Not

                                                                                            Việc đóng gói công nghệ lưu trữ cho phép khách hàng trở nên rất đơn giản, hoàn toàn tách biệt khỏi việc triển khai REPOSITORY. Nhưng như thường lệ với việc đóng gói, lập trình viên phải hiểu những gì đang diễn ra bên trong. Những tác động đến hiệu suất có thể rất lớn khi các REPOSITORY được sử dụng theo những cách khác nhau hoặc hoạt động theo những cách khác nhau.

                                                                                            Kyle Brown đã kể cho tôi câu chuyện về việc được gọi vào một ứng dụng sản xuất dựa trên WebSphere đang được triển khai. Hệ thống bí ẩn bị hết bộ nhớ sau vài giờ sử dụng. Kyle đã duyệt qua mã và tìm ra lý do: Ở một thời điểm nào đó, họ đã tổng hợp một số thông tin về từng mục trong nhà máy. Các nhà phát triển đã thực hiện điều này bằng cách sử dụng một truy vấn gọi là "tất cả đối tượng", điều này đã khởi tạo từng đối tượng và sau đó chọn những phần họ cần. Mã này có tác dụng đưa toàn bộ cơ sở dữ liệu vào bộ nhớ một lần! Vấn đề này đã không xuất hiện trong quá trình kiểm tra vì lượng dữ liệu kiểm tra rất nhỏ.

                                                                                            Điều này rõ ràng là không nên làm, nhưng những sai sót tinh tế hơn có thể tạo ra những vấn đề nghiêm trọng tương đương. Các nhà phát triển cần hiểu những tác động của việc sử dụng hành vi được đóng gói. Điều đó không nhất thiết phải có hiểu biết chi tiết về triển khai. Các thành phần được thiết kế tốt có thể được đặc trưng. (Đây là một trong những điểm chính của Chương 10, "Thiết Kế Linh Hoạt.")

                                                                                            Như đã thảo luận trong Chương 5, công nghệ cơ bản có thể hạn chế các lựa chọn mô hình của bạn. Ví dụ, một cơ sở dữ liệu quan hệ có thể đặt ra giới hạn thực tế đối với các cấu trúc đối tượng tổ hợp sâu. Cũng theo cách tương tự, phải có sự phản hồi cho các nhà phát triển theo cả hai chiều giữa việc sử dụng REPOSITORY và việc thực hiện các truy vấn của nó.

                                                                                            Implementing a REPOSITORY

                                                                                            Việc triển khai sẽ khác nhau rất nhiều, tùy thuộc vào công nghệ được sử dụng cho việc lưu trữ và hạ tầng mà bạn có. Lý tưởng nhất là ẩn tất cả các hoạt động bên trong khỏi khách hàng (mặc dù không phải khỏi nhà phát triển của khách hàng), để mã khách hàng sẽ giống nhau cho dù dữ liệu được lưu trữ trong cơ sở dữ liệu đối tượng, lưu trữ trong cơ sở dữ liệu quan hệ, hoặc đơn giản chỉ được giữ trong bộ nhớ. REPOSITORY sẽ ủy quyền cho các dịch vụ hạ tầng phù hợp để hoàn thành công việc. Việc đóng gói các cơ chế lưu trữ, truy xuất và truy vấn là tính năng cơ bản nhất của một triển khai REPOSITORY.

                                                                                            Figure 6.21. The REPOSITORY encapsulates the underlying data store.

                                                                                            graphics/06fig21.gif

                                                                                            Khái niệm KHO có thể thích ứng với nhiều tình huống. Các khả năng triển khai rất đa dạng đến nỗi tôi chỉ có thể liệt kê một số mối quan tâm cần lưu ý.

                                                                                            • Trừu tượng loại. Một REPOSITORY "chứa" tất cả các thể hiện của một loại cụ thể, nhưng điều này không có nghĩa là bạn cần một REPOSITORY cho mỗi lớp. Loại này có thể là một siêu lớp trừu tượng trong một phân cấp (ví dụ, một TradeOrder có thể là một BuyOrder hoặc một SellOrder). Loại này có thể là một giao diện mà các thực hiện của nó thậm chí không liên quan đến nhau theo phân cấp. Hoặc nó có thể là một lớp cụ thể. Hãy nhớ rằng bạn có thể phải đối mặt với các hạn chế do sự thiếu hụt của kiểu đa hình trong công nghệ cơ sở dữ liệu của bạn.

                                                                                            • Tận dụng sự tách biệt khỏi client. Bạn có nhiều tự do hơn để thay đổi cách triển khai của một REPOSITORY so với khi client gọi trực tiếp các cơ chế. Bạn có thể tận dụng điều này để tối ưu hiệu suất, bằng cách thay đổi kỹ thuật truy vấn hoặc bằng cách lưu trữ các đối tượng trong bộ nhớ, tự do chuyển đổi các chiến lược lưu trữ vào bất kỳ lúc nào. Bạn cũng có thể dễ dàng hỗ trợ kiểm tra mã client và các đối tượng domain bằng cách cung cấp một chiến lược mô phỏng dễ dàng thao tác, lưu trữ trong bộ nhớ.

                                                                                            • Hãy để quản lý giao dịch cho khách hàng. Mặc dù REPOSITORY sẽ chèn và xóa từ cơ sở dữ liệu, nhưng nó thường sẽ không cam kết bất cứ điều gì. Thật hấp dẫn để cam kết sau khi lưu, chẳng hạn như, nhưng khách hàng có lẽ có ngữ cảnh để khởi động và cam kết đúng các đơn vị công việc. Quản lý giao dịch sẽ đơn giản hơn nếu REPOSITORY không can thiệp.

                                                                                            Thông thường, các nhóm thêm một framework vào lớp hạ tầng để hỗ trợ việc triển khai CÁC KHO. Ngoài việc hợp tác với các thành phần hạ tầng cấp thấp hơn, lớp cha CỦA KHO có thể triển khai một số truy vấn cơ bản, đặc biệt khi một truy vấn linh hoạt đang được thực hiện. Thật không may, với một hệ thống kiểu như của Java, tiếp cận này buộc bạn phải kiểu hóa các đối tượng trả về là "Object", để lại cho khách hàng việc ép kiểu chúng về loại chứa của CÁC KHO. Nhưng dĩ nhiên, điều này sẽ phải được thực hiện với các truy vấn mà trả về các bộ sưu tập trong Java.

                                                                                            Một số hướng dẫn bổ sung về việc triển khai REPOSITORIES và một số mẫu kỹ thuật hỗ trợ của chúng như QUERY OBJECT có thể được tìm thấy trong Fowler (2002).

                                                                                            Working Within Your Frameworks

                                                                                            Trước khi triển khai một cái gì đó như REPOSITORY, bạn cần suy nghĩ kỹ về cơ sở hạ tầng mà bạn cam kết, đặc biệt là bất kỳ khung kiến trúc nào. Bạn có thể thấy rằng khung này cung cấp các dịch vụ mà bạn có thể sử dụng để dễ dàng tạo một REPOSITORY, hoặc bạn có thể thấy rằng khung này cản trở bạn trong suốt quá trình. Bạn có thể phát hiện ra rằng khung kiến trúc đã định nghĩa một mẫu tương đương để lấy các đối tượng bền. Hoặc bạn có thể phát hiện ra rằng nó đã định nghĩa một mẫu không giống như REPOSITORY chút nào.

                                                                                            Ví dụ, dự án của bạn có thể cam kết với J2EE. Tìm kiếm sự đồng cảm khái niệm giữa framework và các mẫu của THIẾT KẾ ĐIỀU KHIỂN MÔ HÌNH (và nhớ rằng một entity bean không giống như một ENTITY), bạn có thể đã chọn sử dụng entity beans để tương ứng với các gốc AGGREGATE. Cấu trúc trong khung kiến trúc của J2EE có trách nhiệm cung cấp quyền truy cập vào các đối tượng này là "EJB Home." Cố gắng cải trang EJB Home để trông như một REPOSITORY có thể dẫn đến những vấn đề khác.

                                                                                            Nói chung, đừng chống lại các khung công tác của bạn. Hãy tìm cách giữ lại các nguyên tắc cơ bản của thiết kế hướng miền và buông bỏ những chi tiết khi khung công tác không phù hợp. Tìm kiếm sự tương đồng giữa các khái niệm của thiết kế hướng miền và các khái niệm trong khung công tác. Điều này giả định rằng bạn không có sự lựa chọn nào khác ngoài việc sử dụng khung công tác. Nhiều dự án J2EE hoàn toàn không sử dụng entity beans. Nếu bạn có tự do, hãy chọn các khung công tác, hoặc các phần của khung công tác, mà phù hợp với phong cách thiết kế mà bạn muốn sử dụng.

                                                                                            The Relationship with FACTORIES

                                                                                            Một NHÀ MÁY xử lý giai đoạn đầu của cuộc sống của một đối tượng; một KHO giúp quản lý giữa và cuối. Khi các đối tượng đang được giữ trong bộ nhớ hoặc được lưu trữ trong một cơ sở dữ liệu đối tượng, điều này là rõ ràng. Nhưng thường thì có ít nhất một số lưu trữ đối tượng trong các cơ sở dữ liệu quan hệ, tệp hoặc các hệ thống không hướng đối tượng khác. Trong những trường hợp như vậy, dữ liệu được truy xuất phải được tạo lại thành dạng đối tượng.

                                                                                            Bởi vì REPOSITORY trong trường hợp này đang tạo ra các đối tượng dựa trên dữ liệu, nhiều người coi REPOSITORY như một FACTORY - thực sự là như vậy từ góc độ kỹ thuật. Nhưng sẽ hữu ích hơn nếu giữ mô hình ở vị trí trung tâm, và như đã đề cập trước đó, việc tái tạo một đối tượng đã được lưu trữ không phải là việc tạo ra một đối tượng khái niệm mới. Trong quan điểm thiết kế có định hướng miền này, FACTORIES và REPOSITORIES có trách nhiệm khác nhau. FACTORY tạo ra các đối tượng mới; REPOSITORY tìm kiếm các đối tượng cũ. Khách hàng của một REPOSITORY nên được tạo ấn tượng rằng các đối tượng đang có trong bộ nhớ. Đối tượng có thể cần phải được tái tạo (vâng, một phiên bản mới có thể được tạo ra), nhưng đó vẫn là cùng một đối tượng khái niệm, vẫn ở giữa chu kỳ sống của nó.

                                                                                            Hai quan điểm này có thể được hòa hợp bằng cách để đối tượng REPOSITORY ủy thác việc tạo đối tượng cho một FACTORY, mà (trên lý thuyết, mặc dù hiếm khi trong thực tế) cũng có thể được sử dụng để tạo ra các đối tượng từ đầu.

                                                                                            Figure 6.22. A REPOSITORY uses a FACTORY to reconstitute a preexisting object.

                                                                                            graphics/06fig22.gif

                                                                                            Sự tách biệt rõ ràng này cũng giúp gỡ bỏ tất cả trách nhiệm về sự tồn tại từ các NHÀ MÁY. Nhiệm vụ của một NHÀ MÁY là khởi tạo một đối tượng có thể phức tạp từ dữ liệu. Nếu sản phẩm là một đối tượng mới, khách hàng sẽ biết điều này và có thể thêm nó vào KHO, nơi sẽ bao trùm việc lưu trữ đối tượng trong cơ sở dữ liệu.

                                                                                            Figure 6.23. A client uses a REPOSITORY to store a new object.

                                                                                            graphics/06fig23.gif

                                                                                            Một trường hợp khác khiến mọi người kết hợp NHÀ MÁY và KHO là mong muốn có chức năng "tìm hoặc tạo", trong đó một khách hàng có thể mô tả một đối tượng mà họ muốn và, nếu không tìm thấy đối tượng đó, sẽ được cung cấp một đối tượng mới được tạo ra. Chức năng này nên được tránh. Đây chỉ là một tiện ích nhỏ nếu có. Nhiều trường hợp mà nó có vẻ hữu ích sẽ biến mất khi phân biệt giữa THỰC THỂ và ĐỐI TƯỢNG GIÁ TRỊ. Một khách hàng muốn một ĐỐI TƯỢNG GIÁ TRỊ có thể trực tiếp đến NHÀ MÁY và yêu cầu một cái mới. Thông thường, sự phân biệt giữa một đối tượng mới và một đối tượng tồn tại là quan trọng trong miền, và một khung làm cho sự kết hợp này trở nên mơ hồ thực sự sẽ làm rối tình hình.


                                                                                              Designing Objects for Relational Databases

                                                                                              Phần không đối tượng phổ biến nhất trong các hệ thống phần mềm chủ yếu hướng đối tượng là cơ sở dữ liệu quan hệ. Thực tế này đưa ra những vấn đề thường gặp của sự pha trộn các mô hình (xem Chương 5). Tuy nhiên, cơ sở dữ liệu có mối liên hệ chặt chẽ hơn với mô hình đối tượng so với hầu hết các thành phần khác. Cơ sở dữ liệu không chỉ tương tác với các đối tượng; nó còn lưu trữ hình thức bền vững của dữ liệu tạo nên chính các đối tượng đó. Có rất nhiều tài liệu đã được viết về những thách thức kỹ thuật trong việc ánh xạ các đối tượng vào các bảng quan hệ và việc lưu trữ cũng như truy xuất chúng một cách hiệu quả. Một cuộc thảo luận gần đây có thể tìm thấy trong tác phẩm của Fowler năm 2002. Có những công cụ được tinh chỉnh hợp lý để tạo ra và quản lý các ánh xạ giữa hai bên. Ngoài những mối quan tâm kỹ thuật, sự không khớp này có thể có ảnh hưởng đáng kể đến mô hình đối tượng.

                                                                                              Có ba trường hợp phổ biến:

                                                                                              1. Cơ sở dữ liệu chủ yếu là một kho lưu trữ cho các đối tượng.

                                                                                              Cơ sở dữ liệu được thiết kế cho một hệ thống khác.

                                                                                              Cơ sở dữ liệu được thiết kế cho hệ thống này nhưng phục vụ trong các vai trò khác ngoài lưu trữ đối tượng.

                                                                                              Khi sơ đồ cơ sở dữ liệu được tạo ra đặc biệt như một kho cho các đối tượng, thật đáng để chấp nhận một số giới hạn của mô hình nhằm giữ cho việc ánh xạ rất đơn giản. Nếu không có yêu cầu khác về thiết kế sơ đồ, cơ sở dữ liệu có thể được cấu trúc để đảm bảo tính toàn vẹn của tập hợp an toàn và hiệu quả hơn khi có cập nhật. Về mặt kỹ thuật, thiết kế bảng quan hệ không nhất thiết phải phản ánh mô hình miền. Các công cụ ánh xạ đủ tinh vi để cầu nối những khác biệt đáng kể. Vấn đề là, nhiều mô hình chồng chéo lại với nhau thì quá phức tạp. Nhiều lập luận tương tự được trình bày cho THIẾT KẾ DỰA TRÊN MÔ HÌNH - tránh các mô hình phân tích và thiết kế riêng biệt - cũng áp dụng cho sự không tương thích này. Điều này đòi hỏi một số hy sinh trong sự phong phú của mô hình đối tượng, và đôi khi cần phải thỏa hiệp trong thiết kế cơ sở dữ liệu (chẳng hạn như tách bỏ chọn lọc), nhưng làm theo cách khác sẽ có nguy cơ mất đi mối liên hệ chặt chẽ giữa mô hình và triển khai. Phương pháp này không yêu cầu một ánh xạ đơn giản một đối tượng/một bảng. Tùy thuộc vào sức mạnh của công cụ ánh xạ, một số sự tập hợp hoặc cấu thành của các đối tượng có thể khả thi. Nhưng điều quan trọng là các ánh xạ phải minh bạch, dễ hiểu khi kiểm tra mã hoặc đọc các mục trong công cụ ánh xạ.

                                                                                              • Khi cơ sở dữ liệu được xem như một kho đối tượng, đừng để mô hình dữ liệu và mô hình đối tượng trở nên khác biệt quá xa, bất kể khả năng của các công cụ ánh xạ. Hy sinh một số độ phong phú của các mối quan hệ đối tượng để giữ cho gần gũi với mô hình quan hệ. Thỏa hiệp một số tiêu chuẩn quan hệ chính thức, chẳng hạn như chuẩn hóa, nếu điều đó giúp đơn giản hóa việc ánh xạ đối tượng.

                                                                                              • Các quy trình bên ngoài hệ thống đối tượng không nên truy cập vào kho đối tượng như vậy. Chúng có thể vi phạm các bất biến được các đối tượng thực thi. Ngoài ra, việc truy cập của chúng sẽ khóa mô hình dữ liệu khiến việc thay đổi trở nên khó khăn khi các đối tượng được tái cấu trúc.

                                                                                              Mặt khác, có nhiều trường hợp dữ liệu đến từ một hệ thống kế thừa hoặc bên ngoài chưa bao giờ được thiết kế như một kho lưu trữ đối tượng. Trong tình huống này, thực tế có hai mô hình miền cùng tồn tại trong cùng một hệ thống. Chương 14, "Duy trì Tính toàn vẹn của Mô hình," sẽ giải quyết vấn đề này một cách kỹ lưỡng. Có thể hợp lý để tuân thủ theo mô hình ngầm định trong hệ thống khác, hoặc có thể tốt hơn nếu làm cho mô hình hoàn toàn khác biệt.

                                                                                              Một lý do khác cho việc ngoại lệ là hiệu suất. Những thay đổi thiết kế lập dị có thể phải được giới thiệu để giải quyết các vấn đề về tốc độ thực thi.

                                                                                              Nhưng đối với trường hợp quan trọng phổ biến của một cơ sở dữ liệu quan hệ hoạt động như là hình thức bền vững của một miền hướng đối tượng, sự đơn giản trực tiếp là tốt nhất. Một dòng bảng nên chứa một đối tượng, có thể kèm theo các thành phần phụ trong một AGGREGATE. Khóa ngoại trong bảng nên được dịch thành một tham chiếu đến một đối tượng ENTITY khác. Sự cần thiết đôi khi phải lệch khỏi sự đơn giản trực tiếp này không nên dẫn đến việc từ bỏ hoàn toàn nguyên tắc về các ánh xạ đơn giản.

                                                                                              NGÔN NGỮ PHỔ BIẾN có thể giúp kết nối các thành phần đối tượng và quan hệ lại với nhau thành một mô hình đơn. Tên và mối quan hệ của các phần tử trong các đối tượng phải tương ứng tỉ mỉ với các bảng quan hệ. Mặc dù sức mạnh của một số công cụ ánh xạ có thể khiến điều này có vẻ không cần thiết, nhưng những khác biệt tinh tế trong các mối quan hệ sẽ gây ra rất nhiều nhầm lẫn.

                                                                                              Truyền thống refactoring mà ngày càng trở nên phổ biến trong thế giới đối tượng không thực sự ảnh hưởng nhiều đến thiết kế cơ sở dữ liệu quan hệ. Hơn nữa, các vấn đề di chuyển dữ liệu nghiêm trọng khiến việc thay đổi thường xuyên trở nên khó khăn. Điều này có thể tạo ra một gánh nặng cho việc refactoring mô hình đối tượng, nhưng nếu mô hình đối tượng và mô hình cơ sở dữ liệu bắt đầu khác biệt, tính minh bạch có thể bị mất nhanh chóng.

                                                                                              Cuối cùng, có một số lý do để chọn một lược đồ khác biệt với mô hình đối tượng, ngay cả khi cơ sở dữ liệu được tạo ra cụ thể cho hệ thống của bạn. Cơ sở dữ liệu cũng có thể được sử dụng bởi phần mềm khác mà không khởi tạo đối tượng. Cơ sở dữ liệu có thể yêu cầu ít thay đổi, ngay cả khi hành vi của các đối tượng thay đổi hoặc tiến triển nhanh chóng. Việc tách biệt cả hai khỏi nhau là một con đường hấp dẫn. Nó thường xảy ra một cách không cố ý, khi nhóm không duy trì cơ sở dữ liệu theo kịp với mô hình. Nếu sự tách biệt được lựa chọn một cách có chủ ý, nó có thể dẫn đến một lược đồ cơ sở dữ liệu rõ ràng - không phải là một lược đồ khó xử đầy những thỏa hiệp phù hợp với mô hình đối tượng của năm trước.


                                                                                                Chapter Seven. Using the Language: An Extended Example

                                                                                                Ba chương trước đã giới thiệu một ngôn ngữ mẫu để tinh chỉnh các chi tiết nhỏ của một mô hình và duy trì một thiết kế DỰA TRÊN MÔ HÌNH chặt chẽ. Trong các ví dụ trước, các mẫu chủ yếu được áp dụng từng cái một, nhưng trong một dự án thực tế, bạn phải kết hợp chúng lại với nhau. Chương này trình bày một ví dụ phức tạp (vẫn đơn giản hơn nhiều so với một dự án thực tế, tất nhiên). Ví dụ sẽ tuần tự bước qua một loạt các tinh chỉnh mô hình và thiết kế khi một nhóm giả định xử lý các yêu cầu và vấn đề triển khai, phát triển một THIẾT KẾ DỰA TRÊN MÔ HÌNH, cho thấy các lực tác động và cách các mẫu của Phần II có thể giải quyết chúng.


                                                                                                  Introducing the Cargo Shipping System

                                                                                                  Chúng tôi đang phát triển phần mềm mới cho một công ty vận chuyển hàng hóa. Các yêu cầu ban đầu là ba chức năng cơ bản.

                                                                                                  1. Theo dõi việc xử lý hàng hóa của khách hàng

                                                                                                  Đặt hàng trước

                                                                                                  Gửi hóa đơn cho khách hàng tự động khi hàng hóa đến một điểm nào đó trong quá trình xử lý.

                                                                                                  Trong một dự án thực tế, sẽ cần một khoảng thời gian và nhiều lần thử nghiệm để đạt được sự rõ ràng của mô hình này. Phần III của cuốn sách này sẽ đi sâu vào quá trình khám phá. Nhưng ở đây, chúng ta sẽ bắt đầu với một mô hình có những khái niệm cần thiết dưới dạng hợp lý, và chúng ta sẽ tập trung vào việc điều chỉnh các chi tiết để hỗ trợ thiết kế.

                                                                                                  Figure 7.1. A class diagram representing a model of the shipping domain

                                                                                                  graphics/07fig01.gif

                                                                                                  Mô hình này tổ chức kiến thức miền và cung cấp một ngôn ngữ cho nhóm. Chúng ta có thể đưa ra những tuyên bố như thế này:

                                                                                                  "Nhiều khách hàng tham gia vào một lô hàng, mỗi người đảm nhận một vai trò khác nhau."

                                                                                                  "Mục tiêu giao hàng hàng hóa được xác định."

                                                                                                  Một loạt các Di chuyển Carrier đáp ứng các yêu cầu sẽ hoàn thành mục tiêu giao hàng.

                                                                                                  Mỗi đối tượng trong mô hình đều có một ý nghĩa rõ ràng:

                                                                                                  Một Sự Kiện Xử Lý là một hành động riêng biệt được thực hiện với hàng hóa, chẳng hạn như xếp hàng lên tàu hoặc thông quan. Lớp này có thể được phát triển thành một hệ thống phân cấp các loại sự cố khác nhau, chẳng hạn như xếp hàng, dỡ hàng hoặc được nhận bởi người nhận.

                                                                                                  Thông số giao hàng xác định mục tiêu giao hàng, mà ít nhất sẽ bao gồm một điểm đến và một ngày đến, nhưng có thể phức tạp hơn. Lớp này tuân theo mẫu SPECIFICATION (xem Chương 9).

                                                                                                  Trách nhiệm này có thể đã được Cargo đảm nhận, nhưng việc trừu tượng hóa Thông số Giao hàng mang lại ít nhất ba lợi thế.

                                                                                                  1. "Nếu không có Đặc tả Giao hàng, đối tượng Cargo sẽ phải chịu trách nhiệm về ý nghĩa chi tiết của tất cả các thuộc tính và mối liên hệ để xác định mục tiêu giao hàng. Điều này sẽ làm Cargo trở nên rối rắm và khó hiểu hoặc thay đổi."

                                                                                                  Sự trừu tượng này giúp dễ dàng và an toàn để ẩn đi chi tiết khi giải thích mô hình tổng thể. Ví dụ, có thể có những tiêu chí khác được bao gồm trong Đặc tả Giao hàng, nhưng một sơ đồ ở mức độ chi tiết này sẽ không cần phải tiết lộ điều đó. Sơ đồ đang nói với người đọc rằng có một ĐẶC TẢ về giao hàng, và các chi tiết của nó không quan trọng để suy nghĩ (và thực tế, có thể dễ dàng thay đổi sau này).

                                                                                                  Mô hình này rõ ràng hơn. Việc thêm Thông số Giao hàng nói rõ rằng phương thức giao hàng chính xác của Hàng hóa chưa được xác định, nhưng nó phải đạt được mục tiêu được nêu trong Thông số Giao hàng.

                                                                                                  Một vai trò phân biệt các phần khác nhau mà Khách hàng đóng trong một lô hàng. Một là "người gửi", một là "người nhận", một là "người thanh toán", và cứ như vậy. Bởi vì chỉ một Khách hàng có thể đóng vai trò nhất định cho một hàng hóa cụ thể, mối liên hệ trở thành nhiều-đến-một có điều kiện thay vì nhiều-đến-nhiều. Vai trò có thể được thực hiện đơn giản chỉ là một chuỗi, hoặc có thể là một lớp nếu cần thiết thêm hành vi khác.

                                                                                                  Di chuyển của phương tiện đại diện cho một chuyến đi cụ thể của một phương tiện cụ thể (chẳng hạn như xe tải hoặc tàu) từ một vị trí này đến một vị trí khác. Hàng hóa có thể di chuyển từ nơi này đến nơi khác bằng cách được xếp lên các phương tiện trong khoảng thời gian của một hoặc nhiều lần di chuyển của phương tiện.

                                                                                                  Lịch sử giao hàng phản ánh những gì đã xảy ra thực tế với Cargo, trái ngược với Đặc điểm Giao hàng, mô tả các mục tiêu. Một đối tượng Lịch sử Giao hàng có thể tính toán Vị trí hiện tại của Cargo bằng cách phân tích lần tải hoặc dỡ hàng cuối cùng và điểm đến của Chuyển động Vận chuyển tương ứng. Một giao hàng thành công sẽ kết thúc với một Lịch sử Giao hàng thỏa mãn các mục tiêu của Đặc điểm Giao hàng.

                                                                                                  Tất cả các khái niệm cần thiết để xử lý các yêu cầu vừa được mô tả đều có trong mô hình này, giả sử có các cơ chế phù hợp để lưu trữ các đối tượng, tìm các đối tượng liên quan, và v.v. Các vấn đề triển khai như vậy không được đề cập trong mô hình, nhưng chúng phải có trong thiết kế.

                                                                                                  Để thực hiện một cách vững chắc, mô hình này vẫn cần một số sự làm rõ và siết chặt.

                                                                                                  Nhớ rằng, thông thường, việc tinh chỉnh mô hình, thiết kế và thực hiện nên đi đôi với nhau trong một quy trình phát triển lặp đi lặp lại. Nhưng trong chương này, để làm rõ trong phần giải thích, chúng ta bắt đầu với một mô hình tương đối trưởng thành, và các thay đổi sẽ được động lực hóa một cách nghiêm ngặt bởi nhu cầu kết nối mô hình đó với một triển khai thực tiễn, sử dụng các mẫu khối xây dựng.

                                                                                                  Thông thường, khi mô hình được tinh chỉnh để hỗ trợ thiết kế tốt hơn, nó cũng nên được tinh chỉnh để phản ánh những hiểu biết mới về lĩnh vực. Tuy nhiên, trong chương này, vì lý do rõ ràng trong giải thích, các thay đổi sẽ hoàn toàn được thúc đẩy bởi nhu cầu kết nối với một triển khai thực tiễn, sử dụng các mẫu khối xây dựng.


                                                                                                    Isolating the Domain: Introducing the Applications

                                                                                                    Để ngăn chặn các trách nhiệm miền bị trộn lẫn với các phần khác của hệ thống, hãy áp dụng KIẾN TRÚC TẦNG để đánh dấu một lớp miền.

                                                                                                    Không đi sâu vào phân tích, chúng ta có thể xác định ba chức năng ứng dụng cấp người dùng, mà chúng ta có thể gán cho ba lớp ứng dụng.

                                                                                                    1. Một truy vấn theo dõi có thể truy cập xử lý hàng hóa cụ thể trong quá khứ và hiện tại.

                                                                                                    Một ứng dụng đặt chỗ cho phép đăng ký hàng hóa mới và chuẩn bị hệ thống cho nó.

                                                                                                    Một ứng dụng ghi chép sự cố có thể ghi lại từng thao tác xử lý hàng hóa (cung cấp thông tin được tìm thấy qua truy vấn theo dõi).

                                                                                                    Các lớp ứng dụng này là các phối hợp viên. Chúng không nên tìm ra câu trả lời cho các câu hỏi mà chúng đặt ra. Đó là nhiệm vụ của lớp miền.


                                                                                                      Distinguishing ENTITIES and VALUE Objects

                                                                                                      Xem xét từng đối tượng một, chúng ta sẽ tìm kiếm danh tính cần được theo dõi hoặc một giá trị cơ bản được thể hiện. Đầu tiên, chúng ta sẽ đi qua những trường hợp rõ ràng và sau đó xem xét những trường hợp mơ hồ hơn.

                                                                                                      Customer

                                                                                                      Hãy bắt đầu với một điều dễ dàng. Đối tượng Khách hàng đại diện cho một người hoặc một công ty, một thực thể theo nghĩa thông thường của từ này. Đối tượng Khách hàng rõ ràng có danh tính quan trọng đối với người sử dụng, vì vậy nó là một THỰC THỂ trong mô hình. Làm thế nào để theo dõi nó? Mã số thuế có thể phù hợp trong một số trường hợp, nhưng một công ty quốc tế có thể không thể sử dụng điều đó. Câu hỏi này cần tham khảo ý kiến của một chuyên gia trong lĩnh vực. Chúng tôi thảo luận về vấn đề với một người làm kinh doanh trong công ty vận chuyển, và chúng tôi phát hiện rằng công ty đã có một cơ sở dữ liệu khách hàng mà trong đó mỗi Khách hàng được gán một số ID tại lần liên hệ bán hàng đầu tiên. Số ID này đã được sử dụng trong toàn công ty; việc sử dụng số này trong phần mềm của chúng tôi sẽ thiết lập sự liên tục của danh tính giữa các hệ thống đó. Ban đầu, nó sẽ là một mục nhập thủ công.

                                                                                                      Cargo

                                                                                                      Hai thùng hàng giống hệt nhau phải có thể phân biệt, vì vậy, các đối tượng hàng hóa là CÁC THỰC THỂ. Trên thực tế, tất cả các công ty vận chuyển đều gán mã theo dõi cho từng kiện hàng. Mã này sẽ được tạo tự động, hiển thị cho người dùng và trong trường hợp này, có thể được thông báo cho khách hàng vào thời điểm đặt chỗ.

                                                                                                      Handling Event and Carrier Movement

                                                                                                      Chúng tôi quan tâm đến những sự kiện cá nhân như vậy vì chúng cho phép chúng tôi theo dõi những gì đang diễn ra. Chúng phản ánh các sự kiện trong thế giới thực, thường không thể thay thế cho nhau, vì vậy chúng là CÁI THỂ. Mỗi Di chuyển của Hãng vận chuyển sẽ được xác định bằng một mã lấy từ lịch trình vận chuyển.

                                                                                                      Một cuộc thảo luận khác với một chuyên gia trong lĩnh vực cho thấy rằng việc Xử lý Sự kiện có thể được xác định một cách độc nhất bằng sự kết hợp của ID Hàng hóa, thời gian hoàn thành và loại. Ví dụ, cùng một Hàng hóa không thể vừa được chất lên và dỡ xuống cùng một lúc.

                                                                                                      Location

                                                                                                      Hai địa điểm có cùng tên không phải là một. Vĩ độ và kinh độ có thể cung cấp một khóa duy nhất, nhưng có lẽ không phải là một khóa thực tế do những đo lường đó không được quan tâm cho hầu hết các mục đích của hệ thống này, và chúng sẽ khá phức tạp. Hơn khả năng, Vị trí sẽ là một phần của một mô hình địa lý nào đó liên quan đến các địa điểm theo các tuyến vận chuyển và các mối quan tâm cụ thể khác. Vì vậy, một định danh tùy ý, nội bộ, tự động được tạo ra sẽ đủ.

                                                                                                      Delivery History

                                                                                                      Đây là một vấn đề phức tạp. Lịch sử giao hàng không thể hoán đổi cho nhau, vì vậy chúng là CÁI THỂ. Nhưng một Lịch sử giao hàng có quan hệ một-một với hàng hóa của nó, vì vậy nó không thực sự có danh tính riêng. Danh tính của nó được mượn từ hàng hóa mà nó thuộc về. Điều này sẽ trở nên rõ ràng hơn khi chúng ta mô hình hóa các TỔNG HỢP.

                                                                                                      Delivery Specification

                                                                                                      Mặc dù nó đại diện cho mục tiêu của một Cargo, nhưng sự trừu tượng này không phụ thuộc vào Cargo. Nó thực sự thể hiện một trạng thái giả thuyết của một Lịch sử Giao hàng nào đó. Chúng tôi hy vọng rằng Lịch sử Giao hàng gắn liền với Cargo của chúng tôi cuối cùng sẽ đáp ứng theo Đặc tả Giao hàng gắn liền với Cargo của chúng tôi. Nếu chúng tôi có hai Cargo đi đến cùng một địa điểm, chúng có thể chia sẻ cùng một Đặc tả Giao hàng, nhưng chúng không thể chia sẻ cùng một Lịch sử Giao hàng, mặc dù những lịch sử bắt đầu giống nhau (trống). Đặc tả Giao hàng là CÁC ĐỐI TƯỢNG GIÁ TRỊ.

                                                                                                      Role and Other Attributes

                                                                                                      Vai trò nói về một cái gì đó liên quan đến hiệp hội mà nó đủ điều kiện, nhưng nó không có lịch sử hoặc sự liên tục. Nó là một ĐỐI TƯỢNG GIÁ TRỊ, và nó có thể được chia sẻ giữa các hiệp hội Hàng hóa/Khách hàng khác nhau.

                                                                                                      Các thuộc tính khác như dấu thời gian hoặc tên là CÁC ĐỐI TƯỢNG GIÁ TRỊ.


                                                                                                        Designing Associations in the Shipping Domain

                                                                                                        Không có bất kỳ mối quan hệ nào trong sơ đồ gốc chỉ định hướng đi của hành trình, nhưng các mối quan hệ hai chiều là vấn đề trong thiết kế. Hơn nữa, hướng đi của hành trình thường thể hiện cái nhìn sâu sắc vào miền, làm sâu sắc thêm mô hình.

                                                                                                        Nếu Khách hàng có một tham chiếu trực tiếp đến từng Hàng hóa mà họ đã gửi, điều này sẽ trở nên rắc rối đối với những Khách hàng lâu dài và thường xuyên. Ngoài ra, khái niệm Khách hàng không chỉ cụ thể cho Hàng hóa. Trong một hệ thống lớn, Khách hàng có thể có nhiều vai trò với nhiều đối tượng khác nhau. Tốt nhất là nên giữ cho nó không có những trách nhiệm cụ thể như vậy. Nếu chúng ta cần khả năng tìm Hàng hóa theo Khách hàng, điều này có thể được thực hiện thông qua một truy vấn cơ sở dữ liệu. Chúng ta sẽ trở lại vấn đề này sau trong chương này, trong phần về CÁC KHO.

                                                                                                        Nếu ứng dụng của chúng tôi theo dõi hàng tồn kho của tàu, việc di chuyển từ Carrier Movement đến Handling Event sẽ rất quan trọng. Nhưng nhu cầu kinh doanh của chúng tôi chỉ cần theo dõi hàng hóa. Việc làm cho mối liên kết có thể truy cập chỉ từ Handling Event đến Carrier Movement thể hiện được sự hiểu biết về doanh nghiệp của chúng tôi. Điều này cũng giảm thiểu việc triển khai thành một tham chiếu đối tượng đơn giản, vì hướng đi với số lượng đã bị cấm.

                                                                                                        Lý do phía sau các quyết định còn lại được giải thích trong Hình 7.2, ở trang tiếp theo.

                                                                                                        Figure 7.2. Traversal direction has been constrained on some associations.

                                                                                                        graphics/07fig02.gif

                                                                                                        Có một vòng tham chiếu trong mô hình của chúng tôi: Cargo biết Lịch sử Giao hàng của nó, mà chứa một loạt các Sự kiện Xử lý, mà lại trỏ ngược về Cargo. Các vòng tham chiếu tồn tại hợp lý trong nhiều lĩnh vực và đôi khi cũng cần thiết trong thiết kế, nhưng chúng rất khó bảo trì. Các lựa chọn triển khai có thể giúp bằng cách tránh việc giữ thông tin giống nhau ở hai nơi mà cần phải được đồng bộ hóa. Trong trường hợp này, chúng tôi có thể thực hiện một cách đơn giản nhưng dễ bị tổn thương (trong Java) trong một nguyên mẫu ban đầu, bằng cách cho Lịch sử Giao hàng một đối tượng Danh sách chứa các Sự kiện Xử lý. Nhưng vào một thời điểm nào đó, chúng tôi có thể sẽ muốn bỏ bộ sưu tập này để chuyển sang tìm kiếm cơ sở dữ liệu với Cargo là khóa. Cuộc thảo luận này sẽ được đề cập lại khi lựa chọn CÁC KHO. Nếu truy vấn để xem lịch sử là tương đối ít xảy ra, điều này nên mang lại hiệu suất tốt, đơn giản hóa việc bảo trì và giảm bớt chi phí khi thêm các Sự kiện Xử lý. Nếu truy vấn này xảy ra rất thường xuyên, thì tốt hơn là duy trì con trỏ trực tiếp. Những đánh đổi trong thiết kế này cân bằng giữa sự đơn giản trong việc triển khai và hiệu suất. Mô hình vẫn giống nhau; nó chứa vòng lặp và mối quan hệ hai chiều.


                                                                                                          AGGREGATE Boundaries

                                                                                                          Khách hàng, Địa điểm và Di chuyển của Nhà vận chuyển có danh tính riêng và được chia sẻ bởi nhiều Hàng hóa, do đó chúng phải là gốc của các TỔ HỢP riêng của chúng, chứa các thuộc tính của chúng và có thể là các đối tượng khác dưới mức độ chi tiết của cuộc thảo luận này. Hàng hóa cũng là một gốc TỔ HỢP rõ ràng, nhưng việc xác định ranh giới cần một chút suy nghĩ.

                                                                                                          AGGREGATE Hàng Hóa có thể bao trùm mọi thứ sẽ không tồn tại nếu không có Cargo cụ thể, bao gồm Lịch sử Giao hàng, Đặc điểm Giao hàng và Sự kiện Xử lý. Điều này phù hợp với Lịch sử Giao hàng. Không ai tìm kiếm Lịch sử Giao hàng một cách trực tiếp nếu không muốn có Cargo chính nó. Với việc không cần truy cập toàn cầu trực tiếp, và với một danh tính thực sự chỉ được thể hiện từ Cargo, Lịch sử Giao hàng phù hợp đẹp đẽ trong ranh giới của Cargo, và nó không cần phải là một gốc. Đặc điểm Giao hàng là một ĐỐI TƯỢNG GIÁ TRỊ, vì vậy không có phức tạp nào khi đưa nó vào AGGREGATE Hàng Hóa.

                                                                                                          Sự kiện xử lý là một vấn đề khác. Trước đây, chúng ta đã xem xét hai truy vấn cơ sở dữ liệu có thể tìm kiếm các sự kiện xử lý này: một truy vấn để tìm các sự kiện xử lý cho một lịch sử giao hàng như một lựa chọn có thể thay thế cho việc thu thập, sẽ ở mức địa phương trong AGGREGATE Cargo; truy vấn còn lại sẽ được sử dụng để tìm tất cả các hoạt động để tải và chuẩn bị cho một chuyển động của nhà vận chuyển cụ thể. Trong trường hợp thứ hai, dường như hoạt động xử lý hàng hóa có một ý nghĩa nhất định ngay cả khi được xem xét tách biệt khỏi chính hàng hóa. Vì vậy, sự kiện xử lý nên là gốc của AGGREGATE riêng của nó.

                                                                                                          Figure 7.3. AGGREGATE boundaries imposed on the model. (Note: An ENTITY outside a drawn boundary is implied to be the root of its own AGGREGATE.)

                                                                                                          graphics/07fig03.gif


                                                                                                            Selecting REPOSITORIES

                                                                                                            Có năm THỰC THỂ trong thiết kế là gốc của các TỔ HỢP, vì vậy chúng ta có thể giới hạn xem xét của mình đối với những thực thể này, vì không có đối tượng nào khác được phép có CÁC KHO.

                                                                                                            Để quyết định ai trong số các ứng cử viên này nên thực sự có một REPOSITORY, chúng ta phải quay trở lại với các yêu cầu của ứng dụng. Để thực hiện một đặt chỗ thông qua Ứng dụng Đặt chỗ, người dùng cần chọn Khách hàng (những người chơi các vai trò khác nhau như người gửi hàng, người nhận hàng, v.v.). Vì vậy, chúng ta cần một Repository Khách hàng. Chúng ta cũng cần tìm một Địa điểm để chỉ định làm điểm đến cho Hàng hóa, vì vậy chúng ta tạo một Repository Địa điểm.

                                                                                                            Ứng dụng Ghi Nhận Hoạt Động cần phải cho phép người dùng tra cứu Di chuyển Vận Chuyển mà hàng hóa đang được chất lên, vì vậy chúng ta cần một Kho Lưu Trữ Di chuyển Vận Chuyển. Người dùng này cũng phải cho hệ thống biết hàng hóa nào đã được chất lên, vì vậy chúng ta cần một Kho Lưu Trữ Hàng Hóa.

                                                                                                            Figure 7.4. REPOSITORIES give access to selected AGGREGATE roots.

                                                                                                            graphics/07fig04.gif

                                                                                                            Hiện tại không có Kho sự kiện xử lý, vì chúng tôi đã quyết định triển khai mối quan hệ với Lịch sử giao hàng dưới dạng một tập hợp trong vòng lặp đầu tiên, và chúng tôi không có yêu cầu ứng dụng nào để tìm hiểu những gì đã được tải lên một Chuyển động Vận chuyển. Một trong hai lý do này có thể thay đổi; nếu có, chúng tôi sẽ thêm một KHO.


                                                                                                              Walking Through Scenarios

                                                                                                              Để kiểm tra lại tất cả những quyết định này, chúng ta phải liên tục xem xét các kịch bản để xác nhận rằng chúng ta có thể giải quyết các vấn đề ứng dụng một cách hiệu quả.

                                                                                                              Sample Application Feature: Changing the Destination of a Cargo

                                                                                                              Thỉnh thoảng, một khách hàng gọi tới và nói: "Ôi không! Chúng tôi đã yêu cầu gửi hàng hóa của mình đến Hackensack, nhưng thực sự chúng tôi cần nó ở Hoboken." Chúng tôi luôn sẵn sàng phục vụ, vì vậy hệ thống cần phải hỗ trợ cho sự thay đổi này.

                                                                                                              Đặc tả giao hàng là một ĐỐI TƯỢNG GIÁ TRỊ, vì vậy đơn giản nhất là bỏ nó đi và tạo một cái mới, sau đó sử dụng phương thức setter trên Cargo để thay thế cái cũ bằng cái mới.

                                                                                                              Sample Application Feature: Repeat Business

                                                                                                              Người dùng cho biết rằng các đơn đặt chỗ lặp lại từ cùng một khách hàng thường giống nhau, vì vậy họ muốn sử dụng các hàng hóa cũ làm mẫu cho các hàng hóa mới. Ứng dụng sẽ cho phép họ tìm một hàng hóa trong KHO và sau đó chọn một lệnh để tạo một hàng hóa mới dựa trên hàng hóa đã chọn. Chúng tôi sẽ thiết kế điều này sử dụng mẫu PROTOTYPE (Gamma và các cộng sự 1995).

                                                                                                              Cargo là một THỰC THỂ và là gốc rễ của một TỔNG HỢP. Do đó, nó cần được sao chép cẩn thận; chúng ta cần xem xét những gì nên xảy ra với từng đối tượng hoặc thuộc tính nằm trong ranh giới TỔNG HỢP của nó. Hãy cùng xem qua từng cái một:

                                                                                                              • Lịch sử giao hàng: Chúng ta nên tạo một cái mới, rỗng, vì lịch sử của cái cũ không áp dụng. Đây là trường hợp thông thường với CÁC THỰC THỂ bên trong ranh giới TỔ HỢP.

                                                                                                              • Vai trò của Khách hàng: Chúng ta nên sao chép bản đồ (hoặc bộ sưu tập khác) giữ các tham chiếu được khóa đến Khách hàng, bao gồm cả các khóa, vì chúng có khả năng đóng vai trò tương tự trong lô hàng mới. Nhưng chúng ta phải cẩn thận không sao chép chính các đối tượng Khách hàng. Chúng ta phải kết thúc với các tham chiếu đến cùng các đối tượng Khách hàng mà đối tượng Cargo cũ đã tham chiếu, vì chúng là CÁC THỰC THỂ bên ngoài ranh giới TỔNG HỢP.

                                                                                                              • Mã theo dõi: Chúng ta phải cung cấp một Mã theo dõi mới từ cùng một nguồn như khi chúng ta tạo một lô hàng mới từ đầu.

                                                                                                              Xin lưu ý rằng chúng tôi đã sao chép mọi thứ bên trong ranh giới AGGREGATE của Cargo, chúng tôi đã thực hiện một số sửa đổi đối với bản sao, nhưng chúng tôi không ảnh hưởng gì đến bên ngoài ranh giới AGGREGATE.


                                                                                                                Object Creation

                                                                                                                FACTORIES and Constructors for Cargo

                                                                                                                Ngay cả khi chúng ta có một NHÀ MÁY cao cấp cho Cargo, hoặc sử dụng một Cargo khác làm NHÀ MÁY, như trong kịch bản "Kinh doanh lặp lại", chúng ta vẫn phải có một hàm khởi tạo nguyên thủy. Chúng tôi muốn hàm khởi tạo tạo ra một đối tượng đáp ứng các bất biến của nó hoặc ít nhất, trong trường hợp của một THỰC THỂ, có danh tính của nó được giữ nguyên.

                                                                                                                Dựa trên những quyết định này, chúng ta có thể tạo một phương thức FACTORY trên Cargo như sau:

                                                                                                                public Cargo copyPrototype(String newTrackingID) 

                                                                                                                Hoặc chúng ta có thể tạo một phương thức trên một NHÀ MÁY độc lập như thế này:

                                                                                                                public Cargo newCargo(Cargo prototype, String newTrackingID) 

                                                                                                                Một NHÀ MÁY độc lập cũng có thể bao gồm quy trình lấy một ID mới (được tạo tự động) cho một Cargo mới, trong trường hợp đó nó chỉ cần một đối số duy nhất:

                                                                                                                public Cargo newCargo(Cargo prototype) 

                                                                                                                Kết quả trả về từ bất kỳ nhà máy nào trong số này sẽ giống nhau: một Cargo với Lịch sử Giao hàng trống và Đặc điểm Giao hàng null.

                                                                                                                Mối liên kết hai chiều giữa Cargo và Lịch sử giao hàng có nghĩa là không có Cargo hay Lịch sử giao hàng nào hoàn chỉnh nếu không chỉ ra đối tác của nó, vì vậy chúng phải được tạo ra cùng nhau. Hãy nhớ rằng Cargo là gốc của AGGREGATE bao gồm Lịch sử giao hàng. Do đó, chúng ta có thể cho phép constructor hoặc FACTORY của Cargo tạo ra một Lịch sử giao hàng. Constructor của Lịch sử giao hàng sẽ nhận một Cargo như một tham số. Kết quả sẽ tương tự như sau:

                                                                                                                public Cargo(String id) { trackingID = id; deliveryHistory = new DeliveryHistory(this); customerRoles = new HashMap(); } 

                                                                                                                Kết quả là một Cargo mới với một Lịch sử Giao hàng mới liên kết trở lại với Cargo. Trình tạo Lịch sử Giao hàng chỉ được sử dụng bởi gốc AGGREGATE của nó, tức là Cargo, vì vậy việc cấu thành Cargo được bao bọc.

                                                                                                                Adding a Handling Event

                                                                                                                Mỗi khi hàng hóa được xử lý trong thế giới thực, một người dùng sẽ nhập một Sự kiện Xử lý bằng Ứng dụng Ghi nhật ký Sự cố.

                                                                                                                Mỗi lớp phải có các trình khởi tạo nguyên thủy. Bởi vì Sự kiện Xử lý là một THỰC THỂ, tất cả các thuộc tính xác định danh tính của nó phải được chuyển đến trình khởi tạo. Như đã thảo luận trước đó, Sự kiện Xử lý được xác định duy nhất bởi sự kết hợp của ID của Hàng hóa, thời gian hoàn thành và loại sự kiện. Thuộc tính duy nhất khác của Sự kiện Xử lý là sự liên kết với Chuyển động Vận chuyển, mà một số loại Sự kiện Xử lý thậm chí không có. Một trình khởi tạo cơ bản tạo ra một Sự kiện Xử lý hợp lệ sẽ là:

                                                                                                                public HandlingEvent(Cargo c, String eventType, Date timeStamp) { handled = c; type = eventType; completionTime = timeStamp; } 

                                                                                                                Các thuộc tính không xác định của một THỰC THỂ thường có thể được thêm vào sau. Trong trường hợp này, tất cả các thuộc tính của Sự kiện Xử lý sẽ được thiết lập trong giao dịch ban đầu và không bao giờ bị thay đổi (trừ trường hợp có thể để sửa lỗi nhập dữ liệu), vì vậy có thể thuận tiện và làm cho mã khách hàng trở nên rõ ràng hơn khi thêm một PHƯƠNG THỨC CHẾ TẠO đơn giản cho Sự kiện Xử lý cho mỗi loại sự kiện, nhận tất cả các đối số cần thiết. Ví dụ, một "sự kiện xếp hàng" liên quan đến một Chuyển động Vận tải:

                                                                                                                public static HandlingEvent newLoading( Cargo c, CarrierMovement loadedOnto, Date timeStamp) { HandlingEvent result = new HandlingEvent(c, LOADING_EVENT, timeStamp); result.setCarrierMovement(loadedOnto); return result; } 

                                                                                                                Sự kiện Xử lý trong mô hình là một sự trừu tượng có thể bao gồm nhiều lớp Sự kiện Xử lý chuyên biệt, từ việc loading và unloading đến sealing, lưu trữ và các hoạt động khác không liên quan đến Vận chuyển. Chúng có thể được triển khai dưới dạng nhiều lớp con hoặc có quá trình khởi tạo phức tạp—hoặc cả hai. Bằng cách thêm CÁC PHƯƠNG THỨC NHÀ SẢN XUẤT vào lớp cơ sở (Sự kiện Xử lý) cho mỗi loại, việc tạo đối tượng được trừu tượng hóa, giúp khách hàng không cần phải biết về cách triển khai. NHÀ SẢN XUẤT có trách nhiệm biết lớp nào sẽ được khởi tạo và nó nên được khởi tạo như thế nào.

                                                                                                                Rất tiếc, câu chuyện không đơn giản như vậy. Chu trình tham chiếu, từ Cargo đến Lịch sử Giao hàng, đến Sự kiện Lịch sử và quay trở lại Cargo, làm phức tạp việc tạo các thể hiện. Lịch sử Giao hàng giữ một tập hợp các Sự kiện Xử lý liên quan đến Cargo của nó, và đối tượng mới phải được thêm vào tập hợp này như một phần của giao dịch. Nếu con trỏ quay ngược này không được tạo ra, các đối tượng sẽ không nhất quán.

                                                                                                                Figure 7.5. Adding a Handling Event requires inserting it into a Delivery History.

                                                                                                                graphics/07fig05.gif

                                                                                                                Việc tạo ra con trỏ ngược có thể được bao bọc trong FACTORY (và giữ ở tầng miền nơi nó thuộc về), nhưng bây giờ chúng ta sẽ xem xét một thiết kế thay thế loại bỏ hoàn toàn sự tương tác ngượng ngùng này.


                                                                                                                  Pause for Refactoring: An Alternative Design of the Cargo AGGREGATE

                                                                                                                  Mô hình hóa và thiết kế không phải là một quá trình tiến về phía trước liên tục. Nó sẽ dừng lại nếu không có sự tái cấu trúc thường xuyên để tận dụng những hiểu biết mới nhằm cải thiện mô hình và thiết kế.

                                                                                                                  Bây giờ, có một vài khía cạnh rắc rối trong thiết kế này, mặc dù nó hoạt động và phản ánh mô hình. Những vấn đề tưởng chừng không quan trọng khi bắt đầu thiết kế giờ đây bắt đầu trở nên khó chịu. Hãy quay lại một trong những vấn đề đó và, với lợi thế của sự sáng suốt, sắp xếp thiết kế theo hướng có lợi cho chúng ta.

                                                                                                                  Cần cập nhật Lịch sử Giao hàng khi thêm Sự kiện Xử lý làm cho Cargo AGGREGATE tham gia vào giao dịch. Nếu một người dùng khác đang sửa đổi Cargo cùng lúc, giao dịch Sự kiện Xử lý có thể bị thất bại hoặc bị trì hoãn. Việc nhập Sự kiện Xử lý là một hoạt động vận hành cần phải nhanh chóng và đơn giản, vì vậy một yêu cầu quan trọng của ứng dụng là khả năng nhập Sự kiện Xử lý mà không bị cạnh tranh. Điều này khiến chúng ta phải xem xét một thiết kế khác.

                                                                                                                  Thay thế bộ sưu tập Sự kiện Xử lý trong Lịch sử Giao hàng bằng một truy vấn sẽ cho phép thêm các Sự kiện Xử lý mà không gây ra bất kỳ vấn đề toàn vẹn nào bên ngoài AGGREGATE của nó. Thay đổi này sẽ cho phép các giao dịch như vậy hoàn thành mà không bị can thiệp. Nếu có nhiều Sự kiện Xử lý được nhập vào và tương đối ít truy vấn, thiết kế này sẽ hiệu quả hơn. Thực tế, nếu một cơ sở dữ liệu quan hệ là công nghệ cơ sở, thì có thể một truy vấn đã được sử dụng bên trong để mô phỏng bộ sưu tập. Sử dụng một truy vấn thay vì một bộ sưu tập cũng sẽ giảm bớt khó khăn trong việc duy trì tính nhất quán trong tham chiếu vòng giữa Cargo và Sự kiện Xử lý.

                                                                                                                  Để chịu trách nhiệm cho các truy vấn, chúng tôi sẽ thêm một REPOSITORY để Xử lý Sự kiện. Repository Xử lý Sự kiện sẽ hỗ trợ một truy vấn cho các Sự kiện liên quan đến một Cargo nhất định. Thêm vào đó, REPOSITORY có thể cung cấp các truy vấn được tối ưu hóa để trả lời những câu hỏi cụ thể một cách hiệu quả. Ví dụ, nếu một đường truy cập thường xuyên là Lịch sử Giao hàng tìm kiếm tải hoặc dỡ hàng gần nhất đã được báo cáo, để suy luận trạng thái hiện tại của Cargo, một truy vấn có thể được thiết kế để trả về chỉ Sự kiện Xử lý liên quan đó. Và nếu chúng tôi muốn một truy vấn để tìm tất cả Cargo đã được tải lên một Di chuyển Carrier cụ thể, chúng tôi có thể dễ dàng thêm vào.

                                                                                                                  Figure 7.6. Implementing Delivery History's collection of Handling Events as a query makes insertion of Handling Events simple and free of contention with the Cargo AGGREGATE.

                                                                                                                  graphics/07fig06.gif

                                                                                                                  Điều này khiến Lịch sử Giao hàng không có trạng thái bền vững. Vào lúc này, không có lý do thực sự nào để giữ nó lại. Chúng ta có thể suy diễn Lịch sử Giao hàng mỗi khi cần thiết để trả lời một câu hỏi nào đó. Chúng ta có thể suy diễn đối tượng này vì, mặc dù ENTITY sẽ được tái tạo nhiều lần, mối liên kết với cùng một đối tượng Cargo giữ cho sợi chỉ liên tục giữa các phiên bản.

                                                                                                                  Tham chiếu vòng tròn không còn khó khăn để tạo ra và duy trì. Cargo Factory sẽ được đơn giản hóa để không còn gán một Lịch sử Giao hàng trống cho các thể hiện mới. Không gian database có thể được giảm nhẹ, và số lượng đối tượng tồn tại thực tế có thể giảm đáng kể, điều này là một nguồn tài nguyên hạn chế trong một số cơ sở dữ liệu đối tượng. Nếu mẫu sử dụng phổ biến là người dùng hiếm khi truy vấn trạng thái của Cargo cho đến khi nó đến, thì nhiều công việc không cần thiết sẽ hoàn toàn được tránh khỏi.

                                                                                                                  Mặt khác, nếu chúng ta đang sử dụng một cơ sở dữ liệu đối tượng, việc duyệt qua một mối quan hệ hoặc một tập hợp rõ ràng có thể nhanh hơn nhiều so với một truy vấn REPOSITORY. Nếu mẫu truy cập bao gồm việc thường xuyên liệt kê toàn bộ lịch sử, thay vì thỉnh thoảng truy vấn có mục tiêu về vị trí cuối cùng, thì việc đánh đổi về hiệu suất có thể nghiêng về tập hợp rõ ràng. Và hãy nhớ rằng tính năng thêm này ("Cái gì trên Di chuyển Vận chuyển này?") vẫn chưa được yêu cầu, và có thể sẽ không bao giờ được yêu cầu, vì vậy chúng ta không muốn trả nhiều cho tùy chọn đó.

                                                                                                                  Những loại hình thức thay thế và sự đánh đổi thiết kế này hiện hữu khắp nơi, và tôi có thể đưa ra nhiều ví dụ chỉ trong hệ thống đơn giản này. Tuy nhiên, điểm quan trọng là đây là những mức độ tự do trong cùng một mô hình. Bằng cách mô hình hóa CÁC GIÁ TRỊ, THỰC THỂ và các TỔ HỢP của chúng như chúng tôi đã làm, chúng tôi đã giảm thiểu tác động của những thay đổi thiết kế như vậy. Ví dụ, trong trường hợp này, tất cả các thay đổi đều được bao gói trong ranh giới TỔ HỢP của Cargo. Nó cũng yêu cầu việc bổ sung Kho sự kiện xử lý, nhưng không cần thiết phải thiết kế lại chính sự kiện xử lý (mặc dù một số thay đổi trong triển khai có thể liên quan, tùy thuộc vào chi tiết của khuôn khổ KHO).


                                                                                                                    MODULES in the Shipping Model

                                                                                                                    Cho đến nay, chúng ta đã xem xét quá ít đối tượng đến mức tính mô-đun chưa trở thành vấn đề. Bây giờ, hãy cùng nhìn vào một phần lớn hơn của mô hình vận chuyển (dù vẫn được đơn giản hóa, tất nhiên) để xem cách tổ chức của nó thành CÁC MÔ-ĐUN sẽ ảnh hưởng đến mô hình.

                                                                                                                    Hình 7.7 cho thấy một mô hình được phân chia gọn gàng bởi một độc giả nhiệt tình giả định của cuốn sách này. Sơ đồ này là một biến thể của vấn đề đóng gói dựa trên cơ sở hạ tầng được đề cập trong Chương 5. Trong trường hợp này, các đối tượng đã được nhóm lại theo mẫu mà mỗi cái theo. Kết quả là, các đối tượng mà về mặt khái niệm có mối quan hệ ít (tính kết hợp thấp) lại bị nhồi nhét lại với nhau, và các liên kết chạy lung tung giữa tất cả các MODULE (tính kết hợp cao). Các gói này kể một câu chuyện, nhưng đó không phải là câu chuyện về việc vận chuyển; đó là câu chuyện về những gì nhà phát triển đang đọc vào thời điểm đó.

                                                                                                                    Figure 7.7. These MODULES do not convey domain knowledge.

                                                                                                                    graphics/07fig07.gif

                                                                                                                    Việc phân vùng theo mẫu có vẻ như là một lỗi hiển nhiên, nhưng nó thực sự không kém phần hợp lý so với việc tách biệt các đối tượng bền vững ra khỏi các đối tượng tạm thời hoặc bất kỳ phương pháp có hệ thống nào khác không dựa trên ý nghĩa của các đối tượng.

                                                                                                                    Thay vào đó, chúng ta nên tìm kiếm các khái niệm gắn kết và tập trung vào những gì chúng ta muốn truyền đạt cho người khác trong dự án. Giống như các quyết định mô hình quy mô nhỏ hơn, có nhiều cách để thực hiện điều đó. Hình 7.8 cho thấy một cách tiếp cận đơn giản.

                                                                                                                    Figure 7.8. MODULES based on broad domain concepts

                                                                                                                    graphics/07fig08.gif

                                                                                                                    Các tên MODULE trong Hình 7.8 góp phần vào ngôn ngữ của nhóm. Công ty chúng tôi thực hiện việc giao hàng cho khách hàng để có thể lập hóa đơn cho họ. Đội ngũ bán hàng và tiếp thị của chúng tôi làm việc với khách hàng và thiết lập các thỏa thuận với họ. Nhân viên vận hành thực hiện việc giao hàng, đưa hàng hóa đến địa điểm đã chỉ định. Bộ phận văn phòng phía sau chăm sóc việc lập hóa đơn, gửi các hóa đơn theo đúng giá cả trong thỏa thuận của khách hàng. Đó là một câu chuyện mà tôi có thể kể với bộ MODULE này.

                                                                                                                    Sự phân tích trực quan này có thể được tinh chỉnh, chắc chắn, trong các lần lặp tiếp theo, hoặc thậm chí bị thay thế hoàn toàn, nhưng hiện tại nó đang hỗ trợ THIẾT KẾ DỰA TRÊN MÔ HÌNH và đóng góp cho NGÔN NGỮ PHỔ BIẾN.


                                                                                                                      Introducing a New Feature: Allocation Checking

                                                                                                                      Đến thời điểm này, chúng ta đã làm việc dựa trên các yêu cầu và mô hình ban đầu. Bây giờ, các chức năng mới quan trọng đầu tiên sẽ được thêm vào.

                                                                                                                      Phòng kinh doanh của công ty vận chuyển ảo sử dụng phần mềm khác để quản lý mối quan hệ khách hàng, dự báo doanh số và nhiều thứ khác. Một tính năng hỗ trợ quản lý sản lượng bằng cách cho phép công ty phân bổ bao nhiêu hàng hóa của các loại cụ thể mà họ sẽ cố gắng đặt chỗ dựa trên loại hàng hóa, điểm xuất phát và điểm đến, hoặc bất kỳ yếu tố nào khác mà họ có thể chọn mà có thể nhập dưới dạng tên danh mục. Điều này tạo thành các mục tiêu về số lượng sẽ được bán cho mỗi loại, để các loại kinh doanh có lợi nhuận cao hơn không bị chen lấn bởi các loại hàng hóa kém lợi nhuận, trong khi vẫn tránh tình trạng đặt chỗ thiếu (không sử dụng hết công suất vận chuyển) hoặc đặt chỗ quá mức (khiến việc hủy chỗ hàng hóa diễn ra quá thường xuyên, gây tổn hại đến mối quan hệ với khách hàng).

                                                                                                                      Bây giờ họ muốn tính năng này được tích hợp với hệ thống đặt chỗ. Khi một đơn đặt chỗ đến, họ muốn kiểm tra nó với các phân bổ này để xem nó có nên được chấp nhận hay không.

                                                                                                                      Thông tin cần thiết nằm ở hai nơi, mà Ứng dụng Đặt chỗ sẽ phải truy vấn để có thể chấp nhận hoặc từ chối yêu cầu đặt chỗ. Một phác thảo về các luồng thông tin chung trông giống như sau.

                                                                                                                      Figure 7.9. Our Booking Application must use information from the Sales Management System and from our own domain REPOSITORIES.

                                                                                                                      graphics/07fig09.gif

                                                                                                                      Connecting the Two Systems

                                                                                                                      Hệ thống Quản lý Bán hàng không được viết với cùng một mô hình mà chúng ta đang làm việc ở đây. Nếu Ứng dụng Đặt chỗ tương tác trực tiếp với nó, ứng dụng của chúng ta sẽ phải điều chỉnh theo thiết kế của hệ thống khác, điều này sẽ khiến việc duy trì một THIẾT KẾ DỰA TRÊN MÔ HÌNH trở nên khó khăn hơn và sẽ gây nhầm lẫn cho NGÔN NGỮ TINH TẾ. Thay vào đó, hãy tạo một lớp khác có nhiệm vụ dịch giữa mô hình của chúng ta và ngôn ngữ của Hệ thống Quản lý Bán hàng. Nó sẽ không phải là một cơ chế dịch thuật chung. Nó sẽ chỉ cung cấp những tính năng mà ứng dụng của chúng ta cần, và nó sẽ tái trừu tượng hóa chúng theo mô hình miền của chúng ta. Lớp này sẽ đóng vai trò như một LỚP CHỐNG THAM NHŨNG (được thảo luận trong Chương 14).

                                                                                                                      Đây là một giao diện cho Hệ thống Quản lý Bán hàng, vì vậy chúng ta có thể nghĩ đến việc gọi nó là "Giao diện Quản lý Bán hàng." Nhưng chúng ta sẽ bỏ lỡ cơ hội sử dụng ngôn ngữ để định hình lại vấn đề theo những cách có ích hơn cho chúng ta. Thay vào đó, hãy định nghĩa một DỊCH VỤ cho từng chức năng phân bổ mà chúng ta cần từ hệ thống khác. Chúng ta sẽ triển khai CÁC DỊCH VỤ này bằng một lớp có tên phản ánh trách nhiệm của nó trong hệ thống của chúng ta: "Kiểm tra Phân bổ."

                                                                                                                      Nếu cần tích hợp khác (ví dụ, sử dụng cơ sở dữ liệu khách hàng của Hệ thống Quản lý Bán hàng thay vì kho khách hàng của chúng tôi), một trình dịch khác có thể được tạo ra với DỊCH VỤ đáp ứng trách nhiệm đó. Có thể vẫn hữu ích khi có một lớp cấp thấp như Giao diện Hệ thống Quản lý Bán hàng để xử lý công việc giao tiếp với chương trình khác, nhưng nó sẽ không chịu trách nhiệm về việc dịch. Ngoài ra, nó sẽ được ẩn sau Kiểm tra Phân bổ, vì vậy nó sẽ không xuất hiện trong thiết kế miền.

                                                                                                                      Enhancing the Model: Segmenting the Business

                                                                                                                      Bây giờ chúng ta đã phác thảo sự tương tác của hai hệ thống, chúng ta sẽ cung cấp giao diện nào để có thể trả lời câu hỏi "Có bao nhiêu loại hàng hóa này có thể được đặt chỗ?" Vấn đề khó khăn là xác định "loại" của hàng hóa là gì, vì mô hình miền của chúng ta chưa phân loại hàng hóa. Trong Hệ thống Quản lý Bán hàng, các loại hàng hóa chỉ là một tập hợp các từ khóa phân loại, và chúng ta có thể điều chỉnh các loại của mình theo danh sách đó. Chúng ta có thể truyền vào một tập hợp các chuỗi như một đối số. Nhưng chúng ta sẽ bỏ lỡ một cơ hội khác: lần này, để tái trù suy mô hình của hệ thống khác. Chúng ta cần làm phong phú mô hình miền của mình để chứa đựng kiến thức rằng có các loại hàng hóa. Chúng ta nên tổ chức một buổi brainstorming với một chuyên gia trong lĩnh vực để phát triển khái niệm mới.

                                                                                                                      Đôi khi (như sẽ được thảo luận trong Chương 11), một mẫu phân tích có thể cung cấp cho chúng ta một ý tưởng về một giải pháp mô hình. Cuốn sách "Mẫu Phân Tích" (Fowler 1996) mô tả một mẫu giải quyết loại vấn đề này: PHÂN KHÚC DOANH NGHIỆP. PHÂN KHÚC DOANH NGHIỆP là một tập hợp các chiều không gian định nghĩa một cách để phân chia một doanh nghiệp. Các chiều này có thể bao gồm tất cả những chiều đã được đề cập cho doanh nghiệp vận chuyển, cũng như các chiều thời gian, chẳng hạn như tháng đến thời điểm hiện tại. Sử dụng khái niệm này trong mô hình phân bổ của chúng ta làm cho mô hình trở nên diễn đạt hơn và đơn giản hóa các giao diện. Một lớp gọi là "Phân Khúc Doanh Nghiệp" sẽ xuất hiện trong mô hình miền và thiết kế của chúng ta như một ĐỐI TƯỢNG GIÁ TRỊ bổ sung, sẽ phải được suy ra cho mỗi Cargo.

                                                                                                                      Figure 7.10. The Allocation Checker acts as an ANTICORRUPTION LAYER presenting a selective interface to the Sales Management System in terms of our domain model.

                                                                                                                      graphics/07fig10.gif

                                                                                                                      Trình kiểm tra phân bổ sẽ dịch giữa các phân khúc doanh nghiệp và tên danh mục của hệ thống bên ngoài. Kho hàng hóa cũng phải cung cấp một truy vấn dựa trên phân khúc doanh nghiệp. Trong cả hai trường hợp, việc hợp tác với đối tượng phân khúc doanh nghiệp có thể được sử dụng để thực hiện các thao tác mà không vi phạm tính đóng gói của phân khúc và làm phức tạp các triển khai của chính họ. (Lưu ý rằng kho hàng hóa đang trả lời một truy vấn với một số lượng, thay vì một tập hợp các thể hiện.)

                                                                                                                      Vẫn còn một vài vấn đề với thiết kế này.

                                                                                                                      1. Chúng tôi đã giao cho Ứng dụng Đặt chỗ nhiệm vụ áp dụng quy tắc này: "Một lô hàng được chấp nhận nếu không gian được phân bổ cho Phân đoạn Doanh nghiệp của nó lớn hơn số lượng đã đặt cộng với kích thước của lô hàng mới." Việc thực thi quy tắc kinh doanh là trách nhiệm của miền và không nên được thực hiện ở tầng ứng dụng.

                                                                                                                      Không rõ Ứng dụng Đặt chỗ lấy phần Khách hàng Doanh nghiệp từ đâu.

                                                                                                                      Cả hai trách nhiệm này có vẻ thuộc về Trình Kiểm Tra Phân Bổ. Việc thay đổi giao diện của nó có thể tách biệt hai DỊCH VỤ này và làm cho sự tương tác trở nên rõ ràng và rõ ràng hơn.

                                                                                                                      Figure 7.11. Domain responsibilities shifted from Booking Application to Allocation Checker

                                                                                                                      graphics/07fig11.gif

                                                                                                                      Ràng buộc nghiêm trọng duy nhất mà việc tích hợp này áp đặt là Hệ thống Quản lý Bán hàng không được sử dụng các chiều mà Bộ kiểm tra Phân bổ không thể biến thành Các phân khúc Doanh nghiệp. (Nếu không áp dụng mô hình PHÂN KHÚC DOANH NGHIỆP, cùng một ràng buộc sẽ buộc hệ thống bán hàng phải chỉ sử dụng các chiều có thể được sử dụng trong truy vấn đến Kho hàng. Cách tiếp cận này là khả thi, nhưng hệ thống bán hàng sẽ lan ra các phần khác của miền. Trong thiết kế này, Kho hàng chỉ cần được thiết kế để xử lý Các phân khúc Doanh nghiệp, và những thay đổi trong hệ thống bán hàng chỉ ảnh hưởng đến Bộ kiểm tra Phân bổ, vốn đã được hình thành như một BẢNG TRƯỚC ngay từ đầu.)

                                                                                                                      Performance Tuning

                                                                                                                      Mặc dù giao diện của Trình kiểm tra Phân bổ là phần duy nhất liên quan đến thiết kế miền còn lại, việc thực hiện nội bộ của nó có thể mang lại cơ hội để giải quyết các vấn đề về hiệu suất, nếu có phát sinh. Ví dụ, nếu Hệ thống Quản lý Bán hàng đang chạy trên một máy chủ khác, có thể ở một địa điểm khác, chi phí giao tiếp có thể rất lớn, và có hai lần trao đổi tin nhắn cho mỗi kiểm tra phân bổ. Không có sự thay thế nào cho tin nhắn thứ hai, mà yêu cầu Hệ thống Quản lý Bán hàng trả lời câu hỏi cơ bản là liệu một cargo nhất định có được chấp nhận hay không. Nhưng tin nhắn đầu tiên, mà xác định Phân khúc Doanh nghiệp cho một cargo, dựa trên dữ liệu và hành vi tương đối tĩnh so với các quyết định phân bổ tự thân. Một tùy chọn thiết kế có thể là lưu trữ thông tin này để nó có thể được chuyển sang máy chủ với Trình kiểm tra Phân bổ, giảm chi phí tin nhắn xuống còn một nửa. Có một cái giá cho sự linh hoạt này. Thiết kế trở nên phức tạp hơn và dữ liệu bị trùng lặp giờ đây phải được cập nhật theo một cách nào đó. Nhưng khi hiệu suất là yếu tố quan trọng trong một hệ thống phân tán, việc triển khai linh hoạt có thể là một mục tiêu thiết kế quan trọng.


                                                                                                                        A Final Look

                                                                                                                        Đó là tất cả. Sự tích hợp này có thể đã biến thiết kế đơn giản, nhất quán về mặt khái niệm của chúng tôi thành một mớ hỗn độn, nhưng giờ đây, bằng cách sử dụng LỚP CHỐNG THAM NHŨNG, một DỊCH VỤ và một số PHÂN KHÚC DOANH NGHIỆP, chúng tôi đã tích hợp chức năng của Hệ thống Quản lý Bán hàng vào hệ thống đặt chỗ của mình một cách sạch sẽ, làm phong phú thêm miền.

                                                                                                                        Một câu hỏi thiết kế cuối cùng: Tại sao không giao cho Cargo trách nhiệm trong việc suy diễn Segment Doanh Nghiệp? Nhìn thoáng qua, nó có vẻ thanh lịch, nếu tất cả dữ liệu mà việc suy diễn dựa trên đều nằm trong Cargo, thì việc biến nó thành một thuộc tính suy diễn của Cargo là hợp lý. Tuy nhiên, thực tế không đơn giản như vậy. Các Segment Doanh Nghiệp được định nghĩa một cách tùy ý để phân chia theo các tiêu chí có ích cho chiến lược kinh doanh. Cùng một ĐỐI TƯỢNG có thể được phân đoạn theo nhiều cách khác nhau cho các mục đích khác nhau. Chúng tôi đang suy diễn segment cho một Cargo cụ thể nhằm mục đích phân bổ đặt chỗ, nhưng nó có thể có một Segment Doanh Nghiệp hoàn toàn khác cho mục đích kế toán thuế. Ngay cả Segment Doanh Nghiệp phân bổ cũng có thể thay đổi nếu Hệ Thống Quản Lý Bán Hàng được cấu hình lại vì một chiến lược bán hàng mới. Vì vậy, Cargo sẽ phải biết về Trình Kiểm Tra Phân Bổ, điều này hoàn toàn nằm ngoài trách nhiệm khái niệm của nó, và nó sẽ bị quá tải với các phương thức để suy diễn các loại Segment Doanh Nghiệp cụ thể. Do đó, trách nhiệm trong việc suy diễn giá trị này thuộc về đối tượng biết các quy tắc phân đoạn, thay vì đối tượng có dữ liệu mà các quy tắc đó áp dụng. Những quy tắc này có thể được tách ra thành một đối tượng "Chiến lược" riêng biệt, có thể được truyền cho Cargo để cho phép nó suy diễn một Segment Doanh Nghiệp. Giải pháp đó có vẻ đi xa hơn các yêu cầu mà chúng tôi có ở đây, nhưng đó sẽ là một tùy chọn cho thiết kế sau này và không nên là một thay đổi gây rối loạn lớn.


                                                                                                                          Part III: Refactoring Toward Deeper Insight

                                                                                                                          Phần II của cuốn sách này đã thiết lập một nền tảng cho việc duy trì sự tương ứng giữa mô hình và triển khai. Việc sử dụng một bộ các khối xây dựng cơ bản đã được chứng minh cùng với ngôn ngữ nhất quán mang lại một chút lý trí cho nỗ lực phát triển.

                                                                                                                          Tất nhiên, thách thức thật sự là tìm ra một mô hình sắc bén, một mô hình phản ánh những mối quan tâm tinh tế của các chuyên gia trong lĩnh vực và có thể dẫn dắt một thiết kế thực tiễn. Cuối cùng, chúng tôi hy vọng sẽ phát triển một mô hình nắm bắt được sự hiểu biết sâu sắc về lĩnh vực. Điều này sẽ làm cho phần mềm phù hợp hơn với cách mà các chuyên gia trong lĩnh vực suy nghĩ và nhạy bén hơn với nhu cầu của người dùng. Phần này của cuốn sách sẽ làm rõ mục tiêu đó, mô tả quy trình mà qua đó có thể tiếp cận, và giải thích một số nguyên tắc và mẫu thiết kế để áp dụng nhằm giúp thiết kế phù hợp với nhu cầu của ứng dụng cũng như các nhà phát triển.

                                                                                                                          Thành công trong việc phát triển các mô hình hữu ích phụ thuộc vào ba điểm.

                                                                                                                          1. Các mô hình miền tinh vi có thể đạt được và xứng đáng với công sức bỏ ra.

                                                                                                                          • Chúng thường hiếm khi được phát triển ngoại trừ thông qua một quá trình lặp đi lặp lại của việc tái cấu trúc, bao gồm sự tham gia gần gũi của các chuyên gia trong lĩnh vực với các nhà phát triển quan tâm đến việc tìm hiểu về lĩnh vực đó.

                                                                                                                          • Chúng có thể yêu cầu kỹ năng thiết kế tinh vi để triển khai và sử dụng hiệu quả.

                                                                                                                          • Levels of Refactoring

                                                                                                                            Refactoring là việc tái thiết kế phần mềm theo cách không thay đổi chức năng của nó. Thay vì đưa ra các quyết định thiết kế phức tạp ngay từ đầu, các lập trình viên thực hiện một loạt các thay đổi thiết kế nhỏ và riêng biệt, mỗi thay đổi đều không làm thay đổi chức năng hiện tại trong khi làm cho thiết kế linh hoạt hơn hoặc dễ hiểu hơn. Một bộ kiểm tra đơn vị tự động cho phép thử nghiệm với mã một cách tương đối an toàn. Quy trình này giúp các lập trình viên không cần phải nhìn xa về phía trước.

                                                                                                                            Nhưng hầu hết mọi tài liệu về cách tái cấu trúc đều tập trung vào những thay đổi máy móc đối với mã nguồn làm cho nó dễ đọc hơn hoặc cải thiện ở mức độ rất chi tiết. Cách tiếp cận "tái cấu trúc theo mẫu" có thể cung cấp một mục tiêu ở cấp độ cao hơn cho quá trình tái cấu trúc khi một nhà phát triển nhận ra cơ hội áp dụng một mẫu thiết kế đã được thiết lập. Tuy nhiên, đây chủ yếu là một cái nhìn kỹ thuật về chất lượng thiết kế.

                                                                                                                            Các mẫu như là mục tiêu cho việc tái cấu trúc đã được đề cập ngắn gọn trong Gamma và cộng sự (1995). Joshua Kerievsky đã phát triển quy trình tái cấu trúc thành các mẫu thành một hình thức trưởng thành và hữu ích hơn (Kerievsky 2003).

                                                                                                                            Những cải tiến có tác động lớn nhất đến tính khả thi của hệ thống là những cải tiến được thúc đẩy bởi những hiểu biết mới về miền hoặc những cải tiến làm rõ biểu hiện của mô hình thông qua mã nguồn. Loại cải tiến này không thay thế bất kỳ cải tiến nào liên quan đến các mẫu thiết kế hoặc cải tiến vi mô, mà những điều đó nên được thực hiện liên tục. Nó chồng lên một cấp độ khác: cải tiến đến một mô hình sâu hơn. Thực hiện một cải tiến dựa trên hiểu biết miền thường liên quan đến một loạt các cải tiến vi mô, nhưng động lực không chỉ là trạng thái của mã. Thay vào đó, các cải tiến vi mô cung cấp các đơn vị thay đổi thuận tiện hướng tới một mô hình sâu sắc hơn. Mục tiêu là không chỉ lập trình viên có thể hiểu những gì mã đang thực hiện; mà họ còn có thể hiểu tại sao nó lại thực hiện như vậy và có thể liên hệ điều đó với việc giao tiếp liên tục với các chuyên gia trong miền.

                                                                                                                            Danh mục trong Refactoring (Fowler 1999) bao gồm hầu hết các micro-refactorings thường xuất hiện. Mỗi loại được thúc đẩy chủ yếu bởi một số vấn đề có thể quan sát thấy trong chính mã nguồn. Ngược lại, các mô hình miền được biến đổi theo nhiều cách khác nhau khi những hiểu biết mới xuất hiện, vì vậy việc biên soạn một danh mục toàn diện là điều không thể.

                                                                                                                            Mô hình hóa tự nhiên không có cấu trúc như bất kỳ khám phá nào. Việc tái cấu trúc để có cái nhìn sâu sắc hơn nên theo sau những gì mà việc học hỏi và tư duy sâu sắc dẫn dắt. Các bộ sưu tập mô hình thành công đã được công bố có thể hữu ích, như đã thảo luận trong Chương 11, nhưng chúng ta không nên bị phân tâm khi cố gắng giảm mô hình miền xuống thành một cuốn sách công thức hay một bộ công cụ. Mô hình hóa và thiết kế đòi hỏi sự sáng tạo. Sáu chương tiếp theo sẽ đề xuất một số cách tiếp cận cụ thể để suy nghĩ về việc cải tiến một mô hình miền, cùng với thiết kế làm cho nó sống động.

                                                                                                                            Deep Models

                                                                                                                            Cách giải thích truyền thống về phân tích đối tượng liên quan đến việc xác định danh từ và động từ trong tài liệu yêu cầu và sử dụng chúng làm các đối tượng và phương thức ban đầu. Cách giải thích này được coi là một sự giản lược quá mức, có thể hữu ích cho việc dạy mô hình đối tượng cho những người mới bắt đầu. Tuy nhiên, sự thật là, các mô hình ban đầu thường naiv và nông cạn, dựa trên kiến thức hời hợt.

                                                                                                                            Ví dụ, tôi đã từng làm việc trên một ứng dụng vận chuyển, trong đó ý tưởng ban đầu của tôi về một mô hình đối tượng bao gồm tàu và container. Tàu di chuyển từ nơi này đến nơi khác. Các container được liên kết và hủy liên kết thông qua các thao tác tải và dỡ. Đó là một mô tả chính xác về một số hoạt động vận chuyển thực tế. Tuy nhiên, đó không phải là một mô hình hữu ích cho phần mềm kinh doanh vận chuyển.

                                                                                                                            Cuối cùng, sau nhiều tháng làm việc với các chuyên gia vận chuyển qua nhiều lần chỉnh sửa, chúng tôi đã phát triển một mô hình khá khác biệt. Nó ít rõ ràng đối với người không chuyên, nhưng có ý nghĩa hơn đối với các chuyên gia. Nó đã được tái định hướng vào lĩnh vực giao hàng hàng hóa.

                                                                                                                            Các con tàu vẫn còn đó, nhưng đã được trừu tượng hóa dưới hình thức của một "cuộc hành trình của tàu," một chuyến đi cụ thể được lên lịch cho một tàu, xe lửa, hoặc phương tiện vận chuyển khác. Con tàu thực tế trở thành thứ yếu, và có thể bị thay thế vào phút chót vì bảo trì hoặc lịch trình bị trễ, trong khi cuộc hành trình của tàu vẫn diễn ra theo kế hoạch. Container vận chuyển gần như biến mất khỏi mô hình. Nó đã xuất hiện trong một ứng dụng xử lý hàng hóa dưới một hình thức rất phức tạp khác, nhưng trong bối cảnh của ứng dụng ban đầu, container chỉ là một chi tiết hoạt động. Sự di chuyển vật lý của hàng hóa trở nên không quan trọng bằng việc chuyển giao trách nhiệm pháp lý cho hàng hóa đó. Những đối tượng ít rõ ràng hơn, như "vận đơn," đã trở nên nổi bật.

                                                                                                                            Mỗi khi những người mô hình hóa đối tượng mới xuất hiện trong dự án, gợi ý đầu tiên của họ là gì? Các lớp còn thiếu: tàu và container. Họ là những người thông minh. Họ chỉ chưa trải qua các quá trình khám phá.

                                                                                                                            Một mô hình sâu cung cấp một biểu hiện rõ ràng về những mối quan tâm chính của các chuyên gia trong lĩnh vực và kiến thức liên quan nhất của họ, trong khi loại bỏ những khía cạnh bề mặt của lĩnh vực. Định nghĩa này không đề cập đến trừu tượng. Một mô hình sâu thường có các yếu tố trừu tượng, nhưng nó cũng có thể có các yếu tố cụ thể, nơi mà những yếu tố đó đi đến cốt lõi của vấn đề.

                                                                                                                            Sự linh hoạt, đơn giản và sức thuyết phục đến từ một mô hình thực sự phù hợp với lĩnh vực. Một đặc điểm mà các mô hình như vậy gần như luôn có là một ngôn ngữ đơn giản, mặc dù có thể trừu tượng, mà các chuyên gia kinh doanh thích sử dụng.

                                                                                                                            Deep Model/Supple Design

                                                                                                                            Trong quá trình tái cấu trúc liên tục, thiết kế bản thân nó cần phải hỗ trợ cho sự thay đổi. Chương 10 xem xét các cách để làm cho một thiết kế dễ làm việc, cả cho những người thay đổi nó và cho những người tích hợp nó với các phần khác của hệ thống.

                                                                                                                            Một số đặc điểm của một thiết kế làm cho nó dễ thay đổi và sử dụng hơn. Chúng không phức tạp, nhưng chúng có thể đầy thách thức. "Thiết kế linh hoạt" và những cách tiếp cận nó là chủ đề của Chương 10.

                                                                                                                            Một chút may mắn là chính việc biến đổi mô hình và mã đi mãi đi mãi—nếu mỗi thay đổi phản ánh sự hiểu biết mới—có thể mang lại sự linh hoạt tại những điểm mà sự thay đổi là cần thiết nhất, cùng với những cách dễ dàng để thực hiện những điều thông thường. Một chiếc găng tay đã được sử dụng nhiều trở nên mềm mại tại những điểm mà các ngón tay uốn cong, trong khi những phần khác vẫn cứng cáp và bảo vệ. Vì vậy, mặc dù có nhiều thử nghiệm và sai sót liên quan đến cách tiếp cận này trong mô hình hóa và thiết kế, những thay đổi thực sự có thể trở nên dễ dàng hơn để thực hiện, và những thay đổi lặp đi lặp lại thực sự đưa chúng ta hướng tới một thiết kế mềm mại.

                                                                                                                            Ngoài việc tạo điều kiện cho sự thay đổi, một thiết kế linh hoạt còn góp phần vào việc tinh chỉnh chính mô hình. MỘT THIẾT KẾ DỰA TRÊN MÔ HÌNH đứng trên hai chân. Một mô hình sâu sắc cho phép một thiết kế đầy biểu cảm. Đồng thời, một thiết kế thực sự có thể cung cấp những hiểu biết vào quá trình khám phá mô hình khi nó có đủ linh hoạt để cho phép nhà phát triển thử nghiệm và độ rõ ràng để cho nhà phát triển thấy những gì đang diễn ra. Phần này của vòng phản hồi là rất quan trọng, vì mô hình mà chúng ta đang tìm kiếm không chỉ là một tập hợp ý tưởng đẹp mà nó còn là nền tảng của hệ thống.

                                                                                                                            The Discovery Process

                                                                                                                            Để tạo ra một thiết kế thực sự phù hợp với vấn đề đang gặp phải, trước tiên bạn phải có một mô hình nắm bắt các khái niệm trung tâm liên quan đến lĩnh vực đó. Việc tích cực tìm kiếm những khái niệm này và đưa chúng vào thiết kế là nội dung của Chương 9, "Biến các Khái niệm Ngầm thành Rõ ràng."

                                                                                                                            Vì mối quan hệ chặt chẽ giữa mô hình và thiết kế, quá trình mô hình hóa sẽ dừng lại khi mã khó để tái cấu trúc. Chương 10, "Thiết Kế Linh Hoạt," thảo luận về cách viết phần mềm cho các lập trình viên, không chỉ cho bản thân bạn, để việc mở rộng và thay đổi trở nên hiệu quả. Nỗ lực này đi đôi với việc tinh chỉnh thêm mô hình. Nó thường liên quan đến các kỹ thuật thiết kế tiên tiến hơn và sự nghiêm ngặt hơn trong các định nghĩa mô hình.

                                                                                                                            Bạn thường sẽ phụ thuộc vào sự sáng tạo và thử nghiệm để tìm ra những cách hay để mô hình hóa các khái niệm mà bạn khám phá, nhưng đôi khi có người đã thiết lập một quy tắc mà bạn có thể theo. Các chương 11 và 12 thảo luận về ứng dụng của "mô hình phân tích" và "mô hình thiết kế." Những mô hình như vậy không phải là giải pháp có sẵn, nhưng chúng hỗ trợ quá trình xử lý kiến thức của bạn và thu hẹp tìm kiếm của bạn.

                                                                                                                            Nhưng tôi sẽ bắt đầu Phần III với sự kiện thú vị nhất trong thiết kế có định hướng miền. Đôi khi, khi bối cảnh đã được thiết lập với một THIẾT KẾ HƯỚNG MÔ HÌNH và những khái niệm rõ ràng, bạn sẽ có một bước đột phá. Một cơ hội mở ra để biến phần mềm của bạn thành thứ gì đó biểu đạt và linh hoạt hơn những gì bạn mong đợi. Điều này có thể mang lại những tính năng mới hoặc chỉ đơn giản là thay thế một phần lớn mã cứng nhắc bằng một biểu thức đơn giản, linh hoạt của một mô hình sâu hơn. Mặc dù những bước đột phá như vậy không xảy ra mỗi ngày, nhưng chúng có giá trị đến nỗi khi chúng xảy ra, cơ hội cần phải được công nhận và nắm bắt.

                                                                                                                            Chương 8 kể về câu chuyện có thật của một dự án mà quá trình tái cấu trúc để có cái nhìn sâu sắc hơn đã dẫn đến một bước đột phá. Trải nghiệm này là điều bạn không thể lên kế hoạch trước. Tuy nhiên, nó cung cấp một bối cảnh tốt để suy nghĩ về việc tái cấu trúc miền.


                                                                                                                            Chapter Eight. Breakthrough

                                                                                                                            graphics/08inf01.gif

                                                                                                                            Lợi ích từ việc tái cấu trúc không phải là tuyến tính. Thường thì có một lợi ích biên cho một nỗ lực nhỏ, và những cải tiến nhỏ sẽ tích lũy lại. Chúng chống lại sự thoái hóa, và chúng là hàng phòng thủ tuyến đầu chống lại di sản hóa đá. Nhưng một số nhận thức quan trọng nhất đến một cách đột ngột và gây sốc cho dự án.

                                                                                                                            Chậm nhưng chắc chắn, đội ngũ tiếp thu kiến thức và biến nó thành một mô hình. Các mô hình sâu có thể xuất hiện dần dần thông qua một chuỗi các cải tiến nhỏ, từng đối tượng một: một mối liên hệ điều chỉnh ở đây, một trách nhiệm được chuyển giao ở đó.

                                                                                                                            Thường thì, việc tái cấu trúc liên tục tạo điều kiện cho những điều kém trật tự hơn. Mỗi sự tinh chỉnh của mã và mô hình giúp các lập trình viên có cái nhìn rõ ràng hơn. Sự rõ ràng này tạo ra tiềm năng cho những phát hiện đột phá. Một làn sóng thay đổi dẫn đến một mô hình phù hợp hơn ở cấp độ sâu hơn với thực tế và ưu tiên của người dùng. Tính linh hoạt và sức mạnh giải thích bất ngờ tăng lên ngay cả khi độ phức tạp biến mất.

                                                                                                                            Sự đột phá kiểu này không phải là một kỹ thuật; nó là một sự kiện. Thách thức nằm ở việc nhận ra những gì đang xảy ra và quyết định cách xử lý nó. Để truyền đạt cảm giác của trải nghiệm này, tôi sẽ kể một câu chuyện có thật về một dự án mà tôi đã làm cách đây vài năm, và cách mà chúng tôi đã đến được một mô hình sâu rất giá trị.


                                                                                                                              Story of a Breakthrough

                                                                                                                              Sau một mùa đông dài ở New York dành cho việc tái cấu trúc, chúng tôi đã đạt được một mô hình nắm bắt một số kiến thức chính của miền và một thiết kế thực hiện một số công việc thực sự cho ứng dụng. Chúng tôi đang phát triển một phần cốt lõi của một ứng dụng lớn để quản lý các khoản vay đồng sinh trong một ngân hàng đầu tư.

                                                                                                                              Khi Intel muốn xây dựng một nhà máy trị giá hàng tỷ đô la, họ cần một khoản vay quá lớn để bất kỳ công ty cho vay đơn lẻ nào có thể đảm nhận, vì vậy các nhà cho vay thành lập một liên minh để tập hợp nguồn lực hỗ trợ cho một cơ sở (xem phần bên). Một ngân hàng đầu tư thường đóng vai trò là lãnh đạo liên minh, điều phối các giao dịch và dịch vụ khác. Dự án của chúng tôi là xây dựng phần mềm để theo dõi và hỗ trợ toàn bộ quá trình này.

                                                                                                                              A Decent Model, and Yet . . .

                                                                                                                              Chúng tôi cảm thấy khá tốt. Bốn tháng trước, chúng tôi đã gặp rất nhiều rắc rối với một mã nguồn kế thừa hoàn toàn không thể hoạt động, mà chúng tôi đã đấu tranh để chuyển thành một THIẾT KẾ DỰA TRÊN MÔ HÌNH hợp lý.

                                                                                                                              Mô hình được phản ánh trong Hình 8.1 làm cho trường hợp phổ biến trở nên rất đơn giản. Khoản Đầu Tư Vay là một đối tượng được phát sinh đại diện cho đóng góp của một nhà đầu tư cụ thể vào Khoản Vay, tỉ lệ với phần của họ trong Cơ Sở.

                                                                                                                              Figure 8.1. A model that assumes lender shares are fixed

                                                                                                                              graphics/08fig01.gif


                                                                                                                              What Is a "Facility"?

                                                                                                                              Một "cơ sở" trong bối cảnh này không phải là một tòa nhà. Như trong hầu hết các dự án, thuật ngữ chuyên ngành từ các chuyên gia đã gia nhập vào từ vựng của chúng ta và trở thành một phần của NGÔN NGỮ PHỔ BIẾN. Trong lĩnh vực ngân hàng thương mại, một cơ sở là một cam kết của một công ty để cho vay. Thẻ tín dụng của bạn là một cơ sở cho phép bạn vay theo yêu cầu lên đến một giới hạn đã được thỏa thuận trước với một lãi suất xác định. Khi bạn sử dụng thẻ, bạn tạo ra một khoản vay chưa thanh toán, và mỗi khoản chi thêm là một sự rút tiền khỏi cơ sở của bạn, làm tăng khoản vay. Cuối cùng, bạn trả lại gốc khoản vay. Bạn cũng có thể phải trả một khoản phí hàng năm. Đây là một khoản phí cho đặc quyền sở hữu thẻ (cơ sở) và độc lập với khoản vay của bạn.

                                                                                                                              Nhưng có một số dấu hiệu khiến chúng tôi lo lắng. Chúng tôi liên tục gặp phải những yêu cầu không mong đợi làm phức tạp thiết kế. Một ví dụ lớn là nhận thức dần dần rằng các cổ phần trong một Cơ sở chỉ là một hướng dẫn cho việc tham gia vào bất kỳ khoản vay nào. Khi người vay yêu cầu tiền, người đứng đầu liên minh gọi tất cả các thành viên theo cổ phần của họ.

                                                                                                                              Khi được gọi, các nhà đầu tư thường đáp ứng phần của mình, nhưng thường thì họ thương lượng với các thành viên khác trong liên doanh và đầu tư ít hơn (hoặc nhiều hơn). Chúng tôi đã điều chỉnh điều này bằng cách thêm các Điều chỉnh Khoản vay vào mô hình.

                                                                                                                              Figure 8.2. A model incrementally changed to solve problems. Loan Adjustments track departures from the share a lender originally agreed to in the Facility.

                                                                                                                              graphics/08fig02.gif

                                                                                                                              Sự tinh chỉnh như vậy đã cho phép chúng tôi theo kịp khi các quy tắc của nhiều giao dịch trở nên rõ ràng hơn. Nhưng độ phức tạp đang gia tăng, và có vẻ như chúng tôi không nhanh chóng tiến tới một chức năng thật sự vững chắc.

                                                                                                                              Càng đáng lo ngại hơn là những sự không nhất quán trong việc làm tròn số tinh vi mà chúng tôi không thể khắc phục bằng những thuật toán ngày càng phức tạp. Đúng là trong một thỏa thuận trị giá 100 triệu đô la, không ai quan tâm đến việc những đồng xu lẻ đi đâu, nhưng các ngân hàng không tin tưởng phần mềm không thể tính toán một cách tỉ mỉ cho những đồng xu đó. Chúng tôi bắt đầu nghi ngờ rằng những khó khăn của chúng tôi là triệu chứng của một vấn đề thiết kế cơ bản.

                                                                                                                              The Breakthrough

                                                                                                                              Đột nhiên, một tuần nọ, chúng tôi nhận ra điều gì sai. Mô hình của chúng tôi đã kết nối các cổ phần của Cơ sở và Khoản vay theo cách không phù hợp với doanh nghiệp. Sự phát hiện này đã có những hậu quả lớn. Với các chuyên gia kinh doanh gật đầu, nhiệt tình hỗ trợ - và, tôi dám nói, tự hỏi sao chúng tôi lại mất thời gian lâu như vậy - chúng tôi đã phác thảo một mô hình mới trên bảng trắng. Mặc dù các chi tiết vẫn chưa rõ ràng, nhưng chúng tôi biết đặc điểm quan trọng của mô hình mới: các cổ phần của Khoản vay và của Cơ sở có thể thay đổi độc lập với nhau. Với hiểu biết đó, chúng tôi đã xem xét nhiều kịch bản khác nhau bằng cách sử dụng một hình ảnh trực quan của mô hình mới trông giống như thế này:

                                                                                                                              Figure 8.3. A drawdown distributed based on Facility shares

                                                                                                                              graphics/08fig03.gif

                                                                                                                              Sơ đồ này cho biết rằng người vay đã chọn rút $50 triệu từ số tiền $100 triệu đã cam kết theo Hợp đồng. Ba nhà cho vay đóng góp theo tỷ lệ tương ứng với phần chia của Hợp đồng, dẫn đến một khoản Vay $50 triệu được chia đều giữa các nhà cho vay.

                                                                                                                              Sau đó, trong Hình 8.4, người vay rút thêm 30 triệu đô la, nâng tổng số tiền vay của anh ta lên 80 triệu đô la, vẫn dưới hạn mức 100 triệu đô la của Cơ sở. Lần này, Công ty B chọn không tham gia, để Công ty A nhận một phần lớn hơn. Các tỷ lệ của khoản rút tiền phản ánh những lựa chọn đầu tư này. Khi các khoản rút tiền được cộng vào khoản vay, các tỷ lệ của khoản vay không còn tương xứng với các tỷ lệ của Cơ sở nữa. Điều này là phổ biến.

                                                                                                                              Figure 8.4. Lender B opts out of a second drawdown.

                                                                                                                              graphics/08fig04.gif

                                                                                                                              Figure 8.5. Principal payments are always distributed proportional to shares in the outstanding Loan.

                                                                                                                              graphics/08fig05.gif

                                                                                                                              Khi người vay thanh toán khoản vay, số tiền sẽ được chia cho các bên cho vay theo tỷ lệ của khoản vay, không phải theo Tín dụng. Tương tự, các khoản thanh toán lãi sẽ được chia theo tỷ lệ khoản vay.

                                                                                                                              Figure 8.6. Fee payments are always distributed proportionally to shares in the Facility.

                                                                                                                              graphics/08fig06.gif

                                                                                                                              Mặt khác, khi người vay trả một khoản phí để có quyền sử dụng Tín dụng, số tiền này được phân chia theo tỷ lệ cổ phần của Tín dụng, bất kể ai thực sự đã cho vay tiền. Khoản vay không thay đổi do các khoản thanh toán phí. Thậm chí có những trường hợp mà các nhà cho vay giao dịch cổ phần phí riêng biệt với cổ phần lãi suất của họ, và v.v.

                                                                                                                              A Deeper Model

                                                                                                                              Chúng tôi đã có hai nhận định sâu sắc. Đầu tiên là nhận ra rằng "Đầu tư" và "Đầu tư Vay" chỉ là hai trường hợp đặc biệt của một khái niệm tổng quát và cơ bản: cổ phần. Cổ phần của một cơ sở, cổ phần của một khoản vay, cổ phần của một phân phối thanh toán. Cổ phần, cổ phần ở khắp mọi nơi. Cổ phần của bất kỳ giá trị nào có thể chia được.

                                                                                                                              Vài ngày hỗn loạn sau đó, tôi đã phác thảo một mô hình cổ phần, dựa trên ngôn ngữ được sử dụng trong các cuộc thảo luận với các chuyên gia và các kịch bản mà chúng tôi đã cùng khám phá.

                                                                                                                              Figure 8.7. An abstract model of shares

                                                                                                                              graphics/08fig07.gif

                                                                                                                              Tôi cũng đã phác thảo một mô hình cho vay mới để đi kèm với nó.

                                                                                                                              Figure 8.8. The Loan model using Share Pie

                                                                                                                              graphics/08fig08.gif

                                                                                                                              Không còn những đối tượng chuyên biệt cho cổ phần của một Cơ sở hoặc một Khoản vay nữa. Cả hai đều được phân tích thành "Bánh cổ phần" dễ hiểu hơn. Sự tổng quát này đã cho phép việc giới thiệu "toán học cổ phần," đơn giản hóa đáng kể việc tính toán cổ phần trong bất kỳ giao dịch nào, và làm cho những tính toán đó trở nên biểu cảm, ngắn gọn và dễ dàng kết hợp hơn.

                                                                                                                              Nhưng quan trọng nhất, các vấn đề đã biến mất vì mô hình mới đã loại bỏ một ràng buộc không phù hợp. Nó đã tự do cho Cổ phần của Khoản vay tách rời khỏi tỷ lệ của Cổ phần của Cơ sở, trong khi vẫn giữ nguyên các ràng buộc hợp lệ về tổng số, phân phối phí, và những thứ khác. Bánh Cổ phần của Khoản vay có thể được điều chỉnh trực tiếp, vì vậy việc Điều chỉnh Khoản vay không còn cần thiết nữa, và một lượng lớn logic trường hợp đặc biệt đã bị loại bỏ.

                                                                                                                              Khoản đầu tư vay đã biến mất, và vào thời điểm này chúng tôi nhận ra rằng "khoản đầu tư vay" không phải là một thuật ngữ ngân hàng. Thực tế, các chuyên gia kinh doanh đã nói với chúng tôi nhiều lần rằng họ không hiểu điều đó. Họ đã nhượng bộ cho kiến thức phần mềm của chúng tôi và cho rằng nó hữu ích cho thiết kế kỹ thuật. Thực ra, chúng tôi đã tạo ra nó dựa trên sự hiểu biết chưa đầy đủ về lĩnh vực.

                                                                                                                              Đột nhiên, dựa trên cách nhìn mới về lĩnh vực này, chúng tôi có thể dễ dàng xem xét mọi kịch bản mà chúng tôi từng gặp phải, đơn giản hơn bao giờ hết. Và các sơ đồ mô hình của chúng tôi hoàn toàn hợp lý với các chuyên gia kinh doanh, những người đã thường xuyên cho rằng các sơ đồ đó "quá kỹ thuật" đối với họ. Chỉ cần phác thảo trên bảng trắng, chúng tôi có thể thấy rằng những vấn đề làm tròn dai dẳng nhất của chúng tôi sẽ được loại bỏ triệt để, cho phép chúng tôi bỏ đi một số mã làm tròn phức tạp.

                                                                                                                              Mẫu mới của chúng tôi hoạt động rất tốt. Thực sự, rất rất tốt.

                                                                                                                              Và chúng tôi đều cảm thấy đau bụng!

                                                                                                                              A Sobering Decision

                                                                                                                              Bạn có thể hợp lý cho rằng chúng tôi sẽ rất phấn khích ở thời điểm này. Chúng tôi không như vậy. Chúng tôi đang đối mặt với thời hạn nghiêm trọng; dự án đã chậm tiến độ một cách nguy hiểm. Cảm xúc chi phối của chúng tôi là nỗi sợ hãi.

                                                                                                                              Tin mừng của việc tái cấu trúc là bạn luôn tiến hành từng bước nhỏ, luôn giữ cho mọi thứ hoạt động. Nhưng để tái cấu trúc mã của chúng tôi theo mô hình mới này sẽ yêu cầu thay đổi rất nhiều mã hỗ trợ, và sẽ có rất ít, nếu không muốn nói là không có, điểm dừng ổn định nào ở giữa. Chúng tôi có thể thấy một số cải tiến nhỏ mà chúng tôi có thể thực hiện, nhưng không có cải tiến nào giúp chúng tôi tiến gần hơn đến khái niệm mới. Chúng tôi có thể thấy một chuỗi các bước nhỏ để đến đó, nhưng một số phần của ứng dụng sẽ bị vô hiệu hóa trong quá trình đó. Và điều này xảy ra trước thời kỳ mà kiểm thử tự động được sử dụng rộng rãi trong các dự án như vậy. Chúng tôi không có bất kỳ kiểm thử nào, vì vậy chắc chắn sẽ có những sự cố không thể lường trước.

                                                                                                                              Và điều đó sẽ đòi hỏi nỗ lực. Chúng tôi đã mệt mỏi sau nhiều tháng nỗ lực.

                                                                                                                              Vào thời điểm này, chúng tôi đã có một cuộc họp với quản lý dự án của chúng tôi mà tôi sẽ không bao giờ quên. Quản lý của chúng tôi là một người thông minh và dũng cảm. Ông đã đặt ra một loạt câu hỏi:

                                                                                                                              Q1:

                                                                                                                              Mất bao lâu để trở lại chức năng hiện tại với thiết kế mới?

                                                                                                                              A1:

                                                                                                                              Khoảng ba tuần.

                                                                                                                              Q2:

                                                                                                                              Chúng ta có thể giải quyết các vấn đề mà không cần nó không?

                                                                                                                              A2:

                                                                                                                              Có lẽ. Nhưng không cách nào để chắc chắn.

                                                                                                                              Q3:

                                                                                                                              Chúng ta có thể tiến tới trong bản phát hành tiếp theo nếu bây giờ chúng ta không làm điều đó không?

                                                                                                                              A3:

                                                                                                                              Việc tiến lên sẽ chậm chạp nếu không có sự thay đổi. Và sự thay đổi sẽ trở nên khó khăn hơn nhiều khi chúng ta đã có một cơ sở đã được cài đặt.

                                                                                                                              Q4:

                                                                                                                              Chúng ta có nghĩ rằng đó là điều đúng đắn để làm không?

                                                                                                                              A4:

                                                                                                                              Chúng tôi biết tình hình chính trị không ổn định, vì vậy chúng tôi sẽ ứng phó nếu cần. Và chúng tôi đã mệt mỏi. Nhưng, đúng vậy, đó là một giải pháp đơn giản hơn phù hợp hơn với doanh nghiệp. Về lâu dài, nó ít rủi ro hơn.

                                                                                                                              Ông đã cho chúng tôi sự đồng ý và nói rằng ông sẽ xử lý áp lực. Tôi luôn ngưỡng mộ sự dũng cảm và niềm tin mà ông đã có để đưa ra quyết định đó.

                                                                                                                              Chúng tôi đã nỗ lực rất nhiều và hoàn thành công việc trong ba tuần. Đó là một công việc lớn, nhưng mọi thứ diễn ra khá suôn sẻ.

                                                                                                                              The Payoff

                                                                                                                              Những thay đổi yêu cầu bí ẩn và bất ngờ đã ngừng lại. Logic làm tròn, mặc dù chưa bao giờ hoàn toàn đơn giản, đã ổn định và trở nên hợp lý. Chúng tôi đã hoàn thành phiên bản một và con đường đã rõ ràng cho phiên bản hai. Cơn khủng hoảng thần kinh của tôi đã được tránh một cách sát sao.

                                                                                                                              Khi phiên bản thứ hai phát triển, Share Pie trở thành chủ đề thống nhất của toàn bộ ứng dụng. Những người có chuyên môn kỹ thuật và các chuyên gia kinh doanh đã sử dụng nó để thảo luận về hệ thống. Những người làm marketing đã sử dụng nó để giải thích các tính năng cho khách hàng tiềm năng. Các khách hàng tiềm năng và khách hàng ngay lập tức nắm bắt được nó và sử dụng nó để thảo luận về các tính năng. Nó thực sự đã trở thành một phần của NGÔN NGỮ PHỔ BIẾN vì nó chạm đến cốt lõi của vấn đề phát hành cho vay tập thể.


                                                                                                                                Opportunities

                                                                                                                                Khi triển vọng đạt được một mô hình sâu hơn xuất hiện, nó thường khiến người ta lo sợ. Sự thay đổi như vậy có cơ hội cao hơn và rủi ro cao hơn so với hầu hết các cuộc tái cấu trúc khác. Và thời điểm có thể không thuận lợi.

                                                                                                                                Mặc dù chúng ta rất muốn điều đó diễn ra khác đi, nhưng sự tiến bộ không phải là một hành trình suôn sẻ. Việc chuyển sang một mô hình thật sự sâu sắc là một sự thay đổi sâu sắc trong cách suy nghĩ của bạn và đòi hỏi một sự thay đổi lớn trong thiết kế. Trong nhiều dự án, sự tiến bộ quan trọng nhất trong mô hình và thiết kế thường đến từ những bước đột phá này.


                                                                                                                                  Focus on Basics

                                                                                                                                  Đừng trở nên tê liệt khi cố gắng tạo ra một bước đột phá. Khả năng thường đến sau nhiều sự tái cấu trúc khiêm tốn. Phần lớn thời gian được chi cho việc cải tiến từng phần, với những hiểu biết về mô hình xuất hiện dần dần qua mỗi lần tinh chỉnh liên tiếp.

                                                                                                                                  Để tạo điều kiện cho một bước đột phá, hãy tập trung vào việc xử lý tri thức và phát triển một NGÔN NGỮ PHỔ BIẾN vững chắc. Khám phá các khái niệm quan trọng trong miền và làm cho chúng rõ ràng trong mô hình (như đã thảo luận trong Chương 9). Tinh chỉnh thiết kế để linh hoạt hơn (xem Chương 10). Chưng cất mô hình (xem Chương 15). Tập trung vào những yếu tố có thể dự đoán hơn, điều này tăng cường sự rõ ràng - thường là dấu hiệu trước của những bước đột phá.

                                                                                                                                  Đừng kiềm chế những cải tiến nhỏ, mà dần dần làm sâu sắc mô hình, ngay cả khi bị giới hạn trong cùng một khung khái niệm tổng quát. Đừng bị tê liệt khi nhìn quá xa về phía trước. Hãy luôn chú ý đến cơ hội.


                                                                                                                                    Epilogue: A Cascade of New Insights

                                                                                                                                    Cú đột phá đó đã giúp chúng tôi vượt qua khó khăn, nhưng đó không phải là điểm kết thúc của câu chuyện. Mô hình sâu hơn đã mở ra những cơ hội bất ngờ để làm cho ứng dụng phong phú hơn và thiết kế rõ ràng hơn.

                                                                                                                                    Chỉ vài tuần sau khi phát hành phiên bản Share Pie của phần mềm, chúng tôi nhận thấy một khía cạnh khác khó xử của mô hình đang làm phức tạp thiết kế. Một THỰC THỂ quan trọng đã bị thiếu, sự vắng mặt của nó khiến những trách nhiệm bổ sung phải được đảm nhận bởi các đối tượng khác. Cụ thể, có những quy tắc quan trọng liên quan đến việc rút vốn vay, thanh toán phí, và v.v., và tất cả logic này đã bị nhét chặt vào các phương thức khác nhau trên Facility và Loan. Những vấn đề thiết kế này, trước đây chỉ khó nhận thấy sau bước đột phá Share Pie, giờ đây trở nên rõ ràng hơn với tầm nhìn rõ ràng của chúng tôi. Giờ đây, chúng tôi nhận thấy các thuật ngữ xuất hiện trong các cuộc thảo luận của mình mà không ở đâu trong mô hình - các thuật ngữ như "giao dịch" (nghĩa là một giao dịch tài chính) - mà chúng tôi bắt đầu nhận ra đang được ngầm hiểu bởi tất cả những phương thức phức tạp đó.

                                                                                                                                    Theo một quy trình tương tự như đã được mô tả trước đó (mặc dù, thật may mắn, dưới áp lực thời gian ít hơn nhiều), chúng tôi đã có thêm một đợt khám phá mới và một mô hình sâu sắc hơn. Mô hình mới này đã làm cho những khái niệm ngầm trở nên rõ ràng, như các loại Giao dịch, và đồng thời đơn giản hóa các Vị trí (một sự trừu tượng bao gồm Cơ sở và Khoản vay). Việc định nghĩa các giao dịch đa dạng mà chúng tôi có, cùng với các quy tắc, quy trình đàm phán và quy trình phê duyệt của chúng, trở nên dễ dàng, và tất cả được thể hiện bằng mã khá dễ hiểu.

                                                                                                                                    Figure 8.9. Another model break-through that followed several weeks later. Constraints on Transactions could be expressed with easy precision.

                                                                                                                                    graphics/08fig09.gif

                                                                                                                                    Như thường thấy sau một bước đột phá thực sự vào một mô hình sâu, sự rõ ràng và đơn giản của thiết kế mới, kết hợp với việc giao tiếp được nâng cao dựa trên ngôn ngữ phổ quát mới, đã dẫn đến một bước đột phá mô hình khác.

                                                                                                                                    Tốc độ phát triển của chúng tôi đang tăng nhanh ở giai đoạn mà hầu hết các dự án bắt đầu bị chững lại do khối lượng và sự phức tạp của những gì đã được xây dựng.


                                                                                                                                      Chapter Nine. Making Implicit Concepts Explicit

                                                                                                                                      Mô hình sâu nghe có vẻ tuyệt vời, nhưng bạn thực sự làm điều đó như thế nào? Một mô hình sâu có sức mạnh vì nó chứa đựng các khái niệm và trừu tượng trung tâm có thể diễn đạt một cách ngắn gọn và linh hoạt kiến thức thiết yếu về các hoạt động của người dùng, các vấn đề của họ và các giải pháp. Bước đầu tiên là làm thế nào đó để đại diện cho các khái niệm thiết yếu của miền trong mô hình. Sự tinh chỉnh sẽ đến sau, sau nhiều vòng lặp của việc xử lý kiến thức và tái cấu trúc. Nhưng quá trình này thực sự bắt đầu khi một khái niệm quan trọng được nhận ra và được làm rõ trong mô hình và thiết kế.

                                                                                                                                      Nhiều chuyển đổi của các mô hình miền và mã tương ứng xảy ra khi các nhà phát triển nhận ra một khái niệm đã được gợi ý trong cuộc thảo luận hoặc hiện diện ngầm trong thiết kế, và sau đó họ biểu diễn nó một cách rõ ràng trong mô hình với một hoặc nhiều đối tượng hoặc mối quan hệ.

                                                                                                                                      Đôi khi, việc chuyển đổi một khái niệm trước đây ẩn dụ thành một khái niệm rõ ràng là một bước đột phá dẫn đến một mô hình sâu sắc. Tuy nhiên, thường thì bước đột phá sẽ đến sau, khi một số khái niệm quan trọng đã trở nên rõ ràng trong mô hình; sau nhiều lần tái cấu trúc đã điều chỉnh lại trách nhiệm của chúng nhiều lần, thay đổi mối quan hệ với các đối tượng khác, và thậm chí thay đổi tên gọi của chúng vài lần. Mọi thứ cuối cùng sẽ trở nên rõ ràng. Nhưng quá trình bắt đầu bằng việc nhận ra các khái niệm ẩn ý dưới một hình thức nào đó, dù còn thô sơ.


                                                                                                                                        Digging Out Concepts

                                                                                                                                        Các nhà phát triển cần phải nhạy cảm với những manh mối tiết lộ những khái niệm ngầm đang ẩn chứa, và đôi khi họ phải chủ động tìm kiếm chúng. Hầu hết các phát hiện như vậy đến từ việc lắng nghe ngôn ngữ của nhóm, scrutinizing sự khó khăn trong thiết kế và những mâu thuẫn có vẻ trong các tuyên bố của các chuyên gia, khai thác tài liệu trong lĩnh vực, và thực hiện rất nhiều thí nghiệm.

                                                                                                                                        Listen to Language

                                                                                                                                        Bạn có thể nhớ lại một trải nghiệm như thế này: Người dùng luôn nói về một mục nào đó trên báo cáo. Mục đó được tổng hợp từ các thuộc tính của nhiều đối tượng khác nhau và có thể thậm chí là một truy vấn trực tiếp từ cơ sở dữ liệu. Bộ dữ liệu giống hệt được lắp ráp ở một phần khác của ứng dụng để trình bày, báo cáo hoặc suy ra điều gì đó. Nhưng bạn chưa bao giờ thấy cần thiết về một đối tượng. Có lẽ, bạn chưa bao giờ thực sự hiểu những gì người dùng đề cập đến bằng một thuật ngữ cụ thể và không nhận ra rằng điều đó quan trọng.

                                                                                                                                        Rồi bỗng nhiên một ánh sáng lóe lên trong đầu bạn. Tên của mục trong báo cáo đó chỉ định một khái niệm quan trọng trong miền. Bạn nói chuyện sôi nổi với các chuyên gia của mình về cái nhìn mới này. Có thể họ thể hiện sự nhẹ nhõm vì cuối cùng bạn đã hiểu. Có thể họ ngáp vì họ đã xem điều đó là hiển nhiên từ lâu. Dù sao đi nữa, bạn bắt đầu vẽ các sơ đồ mô hình trên bảng để thay thế cho một số cử chỉ trừu tượng mà bạn đã làm trước đó. Người dùng sửa cho bạn những chi tiết về cách mà mô hình mới kết nối, nhưng bạn có thể nhận thấy rằng có sự thay đổi trong chất lượng của cuộc thảo luận. Bạn và người dùng hiểu nhau chính xác hơn, và việc trình diễn các tương tác của mô hình để giải quyết các kịch bản cụ thể đã trở nên tự nhiên hơn. Ngôn ngữ của mô hình miền đã trở nên mạnh mẽ hơn. Bạn tái cấu trúc mã để phản ánh mô hình mới và nhận ra rằng bạn có một thiết kế sạch hơn.

                                                                                                                                        Lắng nghe ngôn ngữ mà các chuyên gia trong lĩnh vực sử dụng. Có phải có những thuật ngữ diễn đạt một cách súc tích điều gì đó phức tạp không? Họ có đang sửa đổi lựa chọn từ của bạn (có thể một cách khéo léo) không? Có phải những cái nhìn bối rối trên khuôn mặt họ biến mất khi bạn sử dụng một cụm từ nhất định không? Đây là những gợi ý về một khái niệm có thể mang lại lợi ích cho mô hình.

                                                                                                                                        Đây không phải là quan niệm cũ "danh từ là đối tượng". Việc nghe một từ mới tạo ra một dấu hiệu, và bạn theo dõi nó bằng cách trò chuyện và nghiền ngẫm kiến thức, với mục tiêu xác định một khái niệm rõ ràng và hữu ích. Khi người dùng hoặc các chuyên gia trong lĩnh vực sử dụng từ vựng mà không có trong thiết kế, đó là một dấu hiệu cảnh báo. Đó là một cảnh báo mạnh mẽ gấp đôi khi cả các nhà phát triển lẫn các chuyên gia trong lĩnh vực đều sử dụng các thuật ngữ không có trong thiết kế.

                                                                                                                                        Hoặc có thể tốt hơn nếu coi đó như một cơ hội. NGÔN NGỮ PHỔ BIẾN được tạo thành từ từ vựng tràn ngập trong lời nói, tài liệu, sơ đồ mô hình và thậm chí cả mã. Nếu một thuật ngữ nào đó không có trong thiết kế, đó là cơ hội để cải thiện mô hình và thiết kế bằng cách đưa nó vào.

                                                                                                                                        Example
                                                                                                                                        Hearing a Missing Concept in the Shipping Model

                                                                                                                                        Nhóm đã phát triển một ứng dụng hoạt động có thể đặt chỗ cargo. Họ đang bắt đầu xây dựng một ứng dụng "hỗ trợ hoạt động" sẽ giúp quản lý các đơn hàng công việc cho việc xếp dỡ hàng hóa tại cảng đi và cảng đến cũng như tại các điểm chuyển giao giữa các tàu.

                                                                                                                                        Ứng dụng đặt chỗ đã sử dụng một công cụ định tuyến để lên kế hoạch cho chuyến đi của hàng hóa. Mỗi chặng của hành trình được lưu trữ trong một hàng của bảng cơ sở dữ liệu, ghi lại ID của chuyến đi của tàu (một chuyến đi cụ thể của một con tàu cụ thể) dự kiến sẽ chở hàng hóa, vị trí nơi hàng sẽ được chất lên, và vị trí nơi hàng sẽ được dỡ xuống.

                                                                                                                                        Figure 9.1.

                                                                                                                                        graphics/09fig01.gif

                                                                                                                                        Hãy lén nghe một cuộc trò chuyện (rút gọn rất nhiều) giữa nhà phát triển và chuyên gia giao hàng.

                                                                                                                                        Nhà phát triển: Tôi muốn đảm bảo rằng bảng "đặt chỗ hàng hóa" có tất cả dữ liệu mà ứng dụng vận hành sẽ cần.

                                                                                                                                        Chuyên gia: Họ sẽ cần toàn bộ lịch trình cho hàng hóa. Hiện tại nó có thông tin gì?

                                                                                                                                        Nhà phát triển: Mã hàng hóa, hành trình tàu, cảng xếp hàng và cảng dỡ hàng cho mỗi chặng.

                                                                                                                                        Chuyên gia: Thế còn thời gian? Bộ phận vận hành sẽ cần xử lý công việc theo hợp đồng dựa trên thời gian dự kiến.

                                                                                                                                        Nhà phát triển: Vâng, điều đó có thể được rút ra từ lịch trình chuyến đi của tàu. Dữ liệu trong bảng đã được chuẩn hóa.

                                                                                                                                        Chuyên gia: Vâng, việc cần có ngày là điều bình thường. Những người làm trong bộ phận vận hành sử dụng những loại hành trình này để lên kế hoạch cho công việc xử lý sắp tới.

                                                                                                                                        Nhà phát triển: Ừm... Đúng vậy, họ chắc chắn sẽ có quyền truy cập vào các ngày tháng. Ứng dụng quản lý hoạt động sẽ có thể cung cấp toàn bộ chuỗi xếp dỡ, với ngày tháng của từng thao tác xử lý. "Lịch trình," tôi nghĩ bạn có thể gọi như vậy.

                                                                                                                                        Chuyên gia: Tốt. Hành trình là điều chính mà họ cần. Thực ra, bạn biết đấy, ứng dụng đặt chỗ có một mục trong menu để in hành trình hoặc gửi qua e-mail cho khách hàng. Bạn có thể sử dụng điều đó như thế nào không?

                                                                                                                                        Nhà phát triển: Đó chỉ là một báo cáo, tôi nghĩ vậy. Chúng ta sẽ không thể dựa vào đó để xây dựng ứng dụng vận hành.

                                                                                                                                        [Nhà phát triển trông có vẻ suy tư, sau đó hào hứng.]

                                                                                                                                        Nhà phát triển: Vậy thì, hành trình này thật sự là liên kết giữa đặt chỗ và hoạt động.

                                                                                                                                        Chuyên gia: Vâng, và một số mối quan hệ với khách hàng nữa.

                                                                                                                                        Nhà phát triển: [Phác thảo một sơ đồ trên bảng trắng.] Vậy bạn có thể nói rằng nó giống như thế này không?

                                                                                                                                        Figure 9.2.

                                                                                                                                        graphics/09fig02.gif

                                                                                                                                        Chuyên gia: Vâng, đó về cơ bản là đúng. Đối với mỗi chặng, bạn muốn xem hành trình của tàu, địa điểm xếp dỡ hàng hóa và thời gian.

                                                                                                                                        Nhà phát triển: Vì vậy, một khi chúng ta tạo ra đối tượng Leg, nó có thể trích xuất thời gian từ lịch trình chuyến đi của tàu. Chúng ta có thể làm cho đối tượng Itinerary trở thành điểm liên lạc chính với ứng dụng vận hành. Và chúng ta có thể viết lại báo cáo hành trình để sử dụng điều này, vì vậy chúng ta sẽ đưa logic miền quay trở lại lớp miền.

                                                                                                                                        Chuyên gia: Tôi không theo kịp tất cả những điều đó, nhưng bạn đúng là hai công dụng chính của lịch trình nằm trong báo cáo đặt chỗ và trong ứng dụng điều hành.

                                                                                                                                        Nhà phát triển: Chào! Chúng ta có thể làm cho giao diện dịch vụ định tuyến trả về một đối tượng hành trình thay vì đưa dữ liệu vào bảng cơ sở dữ liệu. Bằng cách đó, động cơ định tuyến không cần phải biết về các bảng của chúng ta.

                                                                                                                                        Chuyên gia: Hả?

                                                                                                                                        Nhà phát triển: Ý tôi là, tôi sẽ làm cho công cụ định tuyến chỉ trả về một Lịch trình. Sau đó, nó có thể được lưu trữ trong cơ sở dữ liệu bởi ứng dụng đặt chỗ khi phần còn lại của việc đặt chỗ được lưu.

                                                                                                                                        Chuyên gia: Ý bạn là bây giờ không phải như vậy sao?!

                                                                                                                                        Nhà phát triển sau đó đã đi nói chuyện với các nhà phát triển khác liên quan đến quá trình định tuyến. Họ đã thảo luận về những thay đổi đối với mô hình và các tác động đến thiết kế, gọi đến các chuyên gia vận chuyển khi cần. Họ đã đưa ra sơ đồ trong Hình 9.3.

                                                                                                                                        Figure 9.3.

                                                                                                                                        graphics/09fig03.gif

                                                                                                                                        Tiếp theo, các nhà phát triển đã tái cấu trúc mã để phản ánh mô hình mới. Họ thực hiện điều này trong một loạt hai hoặc ba lần tái cấu trúc, nhưng trong thời gian ngắn, trong vòng một tuần, ngoại trừ việc đơn giản hóa báo cáo lịch trình trong ứng dụng đặt chỗ, điều mà họ đã thực hiện sớm vào tuần sau.

                                                                                                                                        Nhà phát triển đã lắng nghe đủ sát sao ý kiến của chuyên gia vận chuyển để nhận ra khái niệm "lịch trình" quan trọng như thế nào đối với ông. Đúng là tất cả dữ liệu đã được thu thập, và hành vi đã ngấm ngầm thể hiện trong báo cáo lịch trình, nhưng lịch trình rõ ràng như một phần của mô hình đã mở ra những cơ hội mới.

                                                                                                                                        Lợi ích của việc tái cấu trúc thành đối tượng Itinerary rõ ràng:

                                                                                                                                        1. Định nghĩa giao diện của Dịch vụ Định tuyến một cách rõ ràng hơn.

                                                                                                                                        Tách dịch vụ định tuyến khỏi các bảng cơ sở dữ liệu đặt chỗ.

                                                                                                                                        Làm rõ mối quan hệ giữa ứng dụng đặt chỗ và ứng dụng hỗ trợ hoạt động (việc chia sẻ đối tượng Itinerary)

                                                                                                                                        Giảm thiểu sự trùng lặp, vì hành trình lấy thời gian xếp dỡ cho cả báo cáo đặt chỗ và ứng dụng hỗ trợ hoạt động.

                                                                                                                                        Gỡ bỏ logic miền khỏi báo cáo đặt chỗ và đặt nó vào lớp miền tách biệt.

                                                                                                                                        Mở rộng NGÔN NGỮ PHỔ BIẾN, cho phép thảo luận chính xác hơn về mô hình và thiết kế giữa các nhà phát triển và chuyên gia trong lĩnh vực, cũng như trong số các nhà phát triển với nhau.

                                                                                                                                        Scrutinize Awkwardness

                                                                                                                                        Khái niệm bạn cần không phải lúc nào cũng nổi bật trên bề mặt, xuất hiện trong cuộc trò chuyện hoặc tài liệu. Bạn có thể phải đào sâu và sáng tạo. Nơi cần đào sâu là phần khó xử nhất trong thiết kế của bạn. Nơi mà các quy trình thực hiện những điều phức tạp khó có thể giải thích. Nơi mà mỗi yêu cầu mới dường như lại làm tăng thêm độ phức tạp.

                                                                                                                                        Đôi khi thật khó để nhận ra rằng có một khái niệm bị thiếu. Bạn có thể có các đối tượng làm tất cả công việc nhưng lại thấy một số trách nhiệm không thoải mái. Hoặc, nếu bạn nhận ra có điều gì đó bị thiếu, một giải pháp mô hình có thể sẽ lẩn tránh bạn.

                                                                                                                                        Bây giờ bạn cần tích cực tham gia các chuyên gia trong lĩnh vực vào quá trình tìm kiếm. Nếu bạn may mắn, họ có thể thích thú trong việc chơi với những ý tưởng và thử nghiệm với mô hình. Nếu bạn không may mắn như vậy, bạn và các nhà phát triển đồng nghiệp sẽ phải đưa ra những ý tưởng, sử dụng chuyên gia trong lĩnh vực như một người xác thực, theo dõi sự khó chịu hoặc sự công nhận trên gương mặt của họ.

                                                                                                                                        Example
                                                                                                                                        Earning Interest the Hard Way

                                                                                                                                        Câu chuyện tiếp theo diễn ra trong một công ty tài chính giả định chuyên đầu tư vào các khoản vay thương mại và các tài sản sinh lãi khác. Một ứng dụng theo dõi các khoản đầu tư đó và thu nhập từ chúng đã phát triển dần dần, theo từng tính năng. Mỗi đêm, một thành phần sẽ chạy dưới dạng tập lệnh batch, tính toán tất cả lãi suất và phí trong ngày và sau đó ghi chép chúng một cách thích hợp trong phần mềm kế toán của công ty.

                                                                                                                                        Figure 9.4. An awkward model

                                                                                                                                        graphics/09fig04.gif

                                                                                                                                        Kịch bản lô ban đêm đã lặp lại qua từng Tài sản, yêu cầu mỗi tài sản tính toán lãi suất cho ngày hôm đó. Kịch bản đã lấy giá trị trả về (số tiền kiếm được) và chuyển số tiền này, cùng với tên của một sổ cái cụ thể, đến một DỊCH VỤ cung cấp giao diện công cộng của chương trình kế toán. Phần mềm đó đã đăng số tiền vào sổ cái đã nêu. Kịch bản đã thực hiện một quy trình tương tự để lấy phí trong ngày từ mỗi Tài sản, đăng chúng vào một sổ cái khác.

                                                                                                                                        Một nhà phát triển đã gặp khó khăn với sự phức tạp ngày càng tăng trong việc tính toán lãi suất. Cô ấy bắt đầu nghi ngờ rằng có cơ hội cho một mô hình phù hợp hơn với nhiệm vụ này. Nhà phát triển này đã nhờ người chuyên gia trong lĩnh vực yêu thích của mình giúp cô ấy đào sâu vào vấn đề này.

                                                                                                                                        Nhà phát triển: Máy tính lãi suất của chúng tôi đang trở nên quá tải.

                                                                                                                                        Chuyên gia: Đó là một phần phức tạp. Chúng tôi vẫn còn nhiều trường hợp đang bị giữ lại.

                                                                                                                                        Nhà phát triển: Tôi biết. Chúng ta có thể thêm các loại lãi suất mới bằng cách thay thế một Máy tính lãi suất khác. Nhưng điều mà chúng tôi gặp rắc rối nhiều nhất hiện nay là tất cả những trường hợp đặc biệt khi họ không trả lãi đúng lịch.

                                                                                                                                        Chuyên gia: Thực sự những trường hợp đó không đặc biệt. Có rất nhiều sự linh hoạt về thời gian thanh toán của mọi người.

                                                                                                                                        Nhà phát triển: Hồi đó khi chúng tôi tách Máy tính lãi suất ra khỏi Tài sản, điều đó đã giúp ích rất nhiều. Chúng tôi có thể cần phải tách nó ra nhiều hơn nữa.

                                                                                                                                        Chuyên gia: Được rồi.

                                                                                                                                        Nhà phát triển: Tôi đang nghĩ rằng bạn có thể có cách nào đó để nói về việc tính lãi suất này.

                                                                                                                                        Chuyên gia: Bạn có ý nghĩa gì?

                                                                                                                                        Nhà phát triển: Vâng, ví dụ, chúng tôi đang theo dõi lãi suất phải trả nhưng chưa thanh toán trong một kỳ kế toán. Bạn có tên cho điều đó không?

                                                                                                                                        Chuyên gia: Chà, chúng tôi không thực sự làm như vậy. Lợi nhuận kiếm được và khoản thanh toán là hai bút toán tách biệt.

                                                                                                                                        Nhà phát triển: Vậy bạn không cần số đó sao?

                                                                                                                                        Chuyên gia: Thỉnh thoảng chúng tôi có thể xem xét nó, nhưng đó không phải là cách chúng tôi làm kinh doanh.

                                                                                                                                        Nhà phát triển: Được rồi, nếu khoản thanh toán và lãi suất là tách biệt, có lẽ chúng ta nên mô hình hóa chúng theo cách đó. Điều này trông như thế nào? [Phác thảo trên bảng trắng]

                                                                                                                                        Figure 9.5.

                                                                                                                                        graphics/09fig05.gif

                                                                                                                                        Chuyên gia: Có lẽ điều đó có lý. Nhưng bạn chỉ chuyển nó từ nơi này sang nơi khác.

                                                                                                                                        Nhà phát triển: Ngoại trừ việc bây giờ Máy tính lãi suất chỉ theo dõi lãi suất đã kiếm được, và Thanh toán giữ con số đó riêng biệt. Nó không đơn giản hóa nhiều, nhưng có phản ánh tốt hơn thực tiễn kinh doanh của bạn không?

                                                                                                                                        Chuyên gia: À. Tôi hiểu. Chúng ta có thể có lịch sử lãi suất không? Giống như Lịch sử Thanh toán.

                                                                                                                                        Nhà phát triển: Vâng, điều đó đã được yêu cầu như một tính năng mới. Nhưng điều đó có thể đã được thêm vào thiết kế ban đầu.

                                                                                                                                        Chuyên gia: Ôi. Chà, khi tôi thấy lãi suất và Lịch sử Thanh toán được tách biệt như vậy, tôi đã nghĩ rằng bạn đang phân tách lãi suất để tổ chức nó giống như Lịch sử Thanh toán hơn. Bạn có biết gì về kế toán trên cơ sở dồn tích không?

                                                                                                                                        Nhà phát triển: Xin vui lòng giải thích.

                                                                                                                                        Chuyên gia: Mỗi ngày, hoặc khi có lịch trình, chúng tôi có một khoản lãi phát sinh được ghi vào sổ cái. Các khoản thanh toán được ghi theo cách khác. Tổng hợp bạn có ở đây hơi khó hiểu một chút.

                                                                                                                                        Nhà phát triển: Bạn đang nói rằng nếu chúng tôi giữ một danh sách "khoản phải thu", chúng có thể được tổng hợp hoặc... "đăng" khi cần.

                                                                                                                                        Chuyên gia: Có thể đã được đăng vào ngày ghi nhận, nhưng đúng, có thể tổng hợp bất kỳ lúc nào. Phí hoạt động theo cách tương tự, được đăng vào sổ cái khác, tất nhiên.

                                                                                                                                        Nhà phát triển: Thực ra, việc tính lãi sẽ đơn giản hơn nếu chỉ thực hiện trong một ngày hoặc một khoảng thời gian. Và sau đó chúng ta chỉ cần giữ chúng lại. Thế nào?

                                                                                                                                        Figure 9.6.

                                                                                                                                        graphics/09fig06.gif

                                                                                                                                        Chuyên gia: Chắc chắn rồi. Nó trông tốt. Tôi không chắc tại sao điều này lại dễ dàng hơn cho bạn. Nhưng về cơ bản, điều làm cho bất kỳ tài sản nào có giá trị là những gì nó có thể tích lũy từ lãi suất, phí và những thứ khác.

                                                                                                                                        Nhà phát triển: Bạn đã nói rằng phí hoạt động theo cách tương tự? Chúng . . . cái gì nhỉ . . . sẽ được ghi vào các sổ cái khác nhau?

                                                                                                                                        Figure 9.7.

                                                                                                                                        graphics/09fig07.gif

                                                                                                                                        Nhà phát triển: Với mô hình này, chúng ta tách logic tính toán lãi suất, hay đúng hơn là tính toán sự tích lũy, ra khỏi việc theo dõi. Và tôi chưa nhận ra cho đến bây giờ có bao nhiêu sự trùng lặp trong Máy tính phí. Ngoài ra, bây giờ các loại phí khác nhau có thể dễ dàng được thêm vào.

                                                                                                                                        Chuyên gia: Vâng, phép tính trước đây là chính xác, nhưng bây giờ tôi có thể thấy mọi thứ.

                                                                                                                                        Bởi vì các lớp Máy tính không bị ràng buộc trực tiếp với các phần khác trong thiết kế, nên việc làm lại này khá dễ dàng. Nhà phát triển đã có thể viết lại các bài kiểm tra đơn vị để sử dụng ngôn ngữ mới trong vài giờ và đã có thiết kế mới hoạt động vào tối ngày hôm sau. Cô ấy đã kết thúc với điều này.

                                                                                                                                        Figure 9.8. A deeper model after refactoring

                                                                                                                                        graphics/09fig08.gif

                                                                                                                                        Trong ứng dụng đã được cải tiến, script xử lý theo lô vào ban đêm yêu cầu mỗi Tài sản tính toán Đối chiếu đến ngày. Giá trị trả về là một tập hợp các Khoản phải thu, mà mỗi khoản trong số đó được ghi vào sổ cái đã chỉ định.

                                                                                                                                        Mô hình mới có nhiều ưu điểm. Sự thay đổi

                                                                                                                                        1. Làm phong phú ngôn ngữ PHỔ THÔNG với thuật ngữ "dồn tích".

                                                                                                                                        Tách riêng tích lũy khỏi thanh toán

                                                                                                                                        Chuyển giao kiến thức miền (như là sổ cái nào để ghi) từ kịch bản vào lớp miền.

                                                                                                                                        Kết hợp phí và lãi theo cách phù hợp với doanh nghiệp và loại bỏ sự trùng lặp trong mã.

                                                                                                                                        Cung cấp một con đường đơn giản để thêm các biến thể mới của phí và lãi suất như Các lịch trình tích lũy.

                                                                                                                                        Lần này, nhà phát triển phải đào bới để tìm kiếm những khái niệm mới mà cô cần. Cô có thể thấy sự lúng túng trong các phép tính lãi suất và đã nỗ lực nghiêm túc để tìm kiếm một câu trả lời sâu sắc hơn.

                                                                                                                                        Cô ấy thật may mắn khi có một đối tác thông minh và có động lực là chuyên gia ngân hàng. Nếu có một nguồn chuyên môn thụ động hơn, cô ấy sẽ có nhiều khởi đầu sai hơn và phụ thuộc nhiều hơn vào các nhà phát triển khác như những đối tác tư duy. Tiến độ sẽ chậm hơn, nhưng vẫn có thể.

                                                                                                                                        Contemplate Contradictions

                                                                                                                                        Các chuyên gia trong các lĩnh vực khác nhau nhìn nhận sự việc theo những cách khác nhau dựa trên kinh nghiệm và nhu cầu của họ. Ngay cả cùng một người cũng có thể cung cấp thông tin không nhất quán về mặt logic sau khi phân tích cẩn thận. Những mâu thuẫn phiền phức như vậy, mà chúng ta thường gặp khi đào sâu vào yêu cầu của chương trình, có thể là những manh mối tuyệt vời cho những mô hình sâu hơn. Một số chỉ là các biến thể trong thuật ngữ hoặc do sự hiểu lầm. Nhưng vẫn có những trường hợp mà hai phát biểu thực tế của các chuyên gia dường như mâu thuẫn với nhau.

                                                                                                                                        Nhà thiên văn học Galileo từng nêu ra một nghịch lý. Bằng chứng từ các giác quan rõ ràng chỉ ra rằng Trái Đất là tĩnh: con người không bị thổi bay hay rơi xuống. Tuy nhiên, Copernicus đã đưa ra một lập luận thuyết phục rằng Trái Đất đang chuyển động quanh Mặt Trời với tốc độ khá nhanh. Việc hòa giải điều này có thể tiết lộ điều gì đó sâu sắc về cách thức hoạt động của tự nhiên.

                                                                                                                                        Galileo đã nghĩ ra một thí nghiệm tư duy. Nếu một người cưỡi ngựa thả một quả bóng từ một con ngựa đang chạy, quả bóng sẽ rơi ở đâu? Tất nhiên, quả bóng sẽ di chuyển cùng với con ngựa cho đến khi nó chạm đất ở chân ngựa, giống như khi con ngựa đứng im. Từ đó, ông suy ra một hình thức sơ khai của ý tưởng về hệ quy chiếu quán tính, giải quyết nghịch lý và dẫn đến một mô hình hữu ích hơn về vật lý chuyển động.

                                                                                                                                        Được rồi. Những mâu thuẫn của chúng ta thường không quá thú vị, cũng như những tác động không sâu sắc đến vậy. Dù vậy, chính mẫu tư duy này thường giúp xuyên thủng các lớp bề ngoài của một miền vấn đề để khám phá ra những hiểu biết sâu sắc hơn.

                                                                                                                                        Việc hòa giải tất cả các mâu thuẫn là không thực tế, và có thể còn không mong muốn. (Chương 14 đi sâu vào cách quyết định và cách quản lý kết quả.) Tuy nhiên, ngay cả khi một mâu thuẫn được giữ lại, việc suy ngẫm về cách hai phát biểu có thể đều áp dụng cho cùng một thực tế bên ngoài có thể mang lại những điều thú vị.

                                                                                                                                        Read the Book

                                                                                                                                        Đừng bỏ qua những điều hiển nhiên khi tìm kiếm các khái niệm mô hình. Trong nhiều lĩnh vực, bạn có thể tìm thấy sách giải thích những khái niệm cơ bản và tri thức thông thường. Bạn vẫn phải làm việc với các chuyên gia trong lĩnh vực của bạn để chắt lọc phần liên quan đến vấn đề của bạn và biến nó thành một thứ phù hợp với phần mềm hướng đối tượng. Nhưng bạn có thể bắt đầu với một cái nhìn mạch lạc, được xem xét kỹ lưỡng.

                                                                                                                                        Example
                                                                                                                                        Earning Interest by the Book

                                                                                                                                        Hãy tưởng tượng một kịch bản khác cho ứng dụng theo dõi đầu tư được thảo luận trong ví dụ trước. Giống như trước đây, câu chuyện bắt đầu khi nhà phát triển nhận ra rằng thiết kế đang trở nên cồng kềnh, đặc biệt là Bộ Tính Lãi. Nhưng trong kịch bản này, trách nhiệm chính của chuyên gia lĩnh vực nằm ở nơi khác, và anh ta không mấy hứng thú trong việc hỗ trợ dự án phát triển phần mềm. Trong kịch bản này, nhà phát triển không thể tìm đến chuyên gia để tổ chức một buổi brainstorming nhằm khai thác những khái niệm còn thiếu mà cô nghi ngờ đang ẩn dưới bề mặt.

                                                                                                                                        Thay vào đó, cô ấy đã đến hiệu sách. Sau một chút xem qua, cô đã tìm thấy một cuốn sách kế toán nhập môn mà cô thích, và cô đã lướt qua nó. Cô đã phát hiện ra một hệ thống toàn bộ các khái niệm được định nghĩa rõ ràng. Một đoạn trích đặc biệt kích thích suy nghĩ của cô:

                                                                                                                                        Kế toán dồn tích. Phương pháp này công nhận thu nhập khi nó được kiếm, ngay cả khi nó chưa được thanh toán. Tất cả các chi phí cũng sẽ được ghi nhận khi chúng phát sinh, cho dù đã được thanh toán hay chỉ được lập hóa đơn để thanh toán sau. Mọi nghĩa vụ phải trả, bao gồm thuế, sẽ được ghi nhận là chi phí.

                                                                                                                                        Tài chính và Kế toán: Cách Giữ Sổ Sách và Quản Lý Tài Chính Của Bạn Không Cần MBA, CPA Hay Tiến Sĩ, của Suzanne Caplan (Adams Media, 2000)

                                                                                                                                        Nhà phát triển không còn cần phải tái phát minh kế toán nữa. Sau một vài buổi động não với một nhà phát triển khác, cô đã đưa ra một mô hình.

                                                                                                                                        Figure 9.9. A somewhat deeper model based on book learning

                                                                                                                                        graphics/09fig09.gif

                                                                                                                                        Cô ấy không nhận thức được rằng Tài sản là nguồn sinh ra thu nhập, vì vậy các Máy tính vẫn còn đó. Kiến thức về sổ cái vẫn nằm trong ứng dụng, thay vì ở tầng miền nơi mà nó có lẽ thuộc về. Nhưng cô ấy đã tách biệt vấn đề thanh toán khỏi việc tích lũy thu nhập, đó là lĩnh vực gây khó khăn nhất, và cô ấy đã giới thiệu từ "tích lũy" vào mô hình và vào NGÔN NGỮ PHỔ BIẾN. Việc tinh chỉnh thêm có thể đến từ các phiên bản sau.

                                                                                                                                        Khi cô ấy cuối cùng có cơ hội để nói chuyện với chuyên gia trong lĩnh vực, ông ấy đã khá ngạc nhiên. Đây là lần đầu tiên một lập trình viên thể hiện một chút quan tâm đến những gì ông làm. Do cách mà trách nhiệm của ông được phân công, chuyên gia không bao giờ tương tác với cô, ngồi xuống để xem xét mô hình, như đã xảy ra trong tình huống trước đó. Tuy nhiên, vì kiến thức của nhà phát triển này đã giúp cô đặt ra những câu hỏi tốt hơn, từ đó trở đi, chuyên gia đã lắng nghe cô một cách cẩn thận, và ông đã nỗ lực đặc biệt để trả lời các câu hỏi của cô kịp thời.

                                                                                                                                        Tất nhiên, đây không phải là một vấn đề chỉ chọn một trong hai. Ngay cả khi có sự hỗ trợ đầy đủ từ các chuyên gia trong lĩnh vực, việc tham khảo tài liệu để hiểu rõ lý thuyết của lĩnh vực là điều cần thiết. Hầu hết các doanh nghiệp không có các mô hình được tinh chỉnh đến mức độ của kế toán hoặc tài chính, nhưng trong nhiều doanh nghiệp, đã có những nhà tư tưởng trong lĩnh vực này tổ chức và trừu tượng hóa các thực tiễn chung của doanh nghiệp.

                                                                                                                                        Một tùy chọn khác mà nhà phát triển có thể lựa chọn là đọc một tài liệu được viết bởi một chuyên gia phần mềm khác có kinh nghiệm phát triển trong lĩnh vực này. Ví dụ, Chương 6 của cuốn sách "Analysis Patterns: Reusable Object Models" (Fowler 1997) có thể đã dẫn cô ấy theo một hướng hoàn toàn khác, không nhất thiết là tốt hơn hay tệ hơn. Đọc sách như vậy sẽ không cung cấp một giải pháp có sẵn. Nó sẽ mang lại nhiều điểm khởi đầu mới cho các thí nghiệm của cô ấy, cùng với kinh nghiệm chắt lọc của những người đã khám phá lãnh thổ này. Cô ấy sẽ được miễn khỏi việc phát minh lại bánh xe. Chương 11, "Áp dụng các Mô hình Phân tích," sẽ đi sâu hơn vào tùy chọn này.

                                                                                                                                        Try, Try Again

                                                                                                                                        Những ví dụ mà tôi đã đưa ra không thể hiện được mức độ thử và sai mà tôi đã trải qua. Tôi có thể theo dõi nửa tá manh mối trong cuộc trò chuyện trước khi tìm ra một manh mối có vẻ rõ ràng và hữu ích đủ để thử nghiệm trong mô hình. Cuối cùng, tôi sẽ thay thế manh mối đó ít nhất một lần sau này, khi kinh nghiệm và kiến thức bổ sung cung cấp ra những ý tưởng tốt hơn. Một nhà mô hình/nhà thiết kế không thể nào gắn bó với những ý tưởng của chính mình.

                                                                                                                                        Tất cả những thay đổi hướng đi này không chỉ là sự lộn xộn. Mỗi sự thay đổi đều chạm sâu vào hiểu biết về mô hình. Mỗi lần tái cấu trúc khiến thiết kế trở nên linh hoạt hơn, dễ thay đổi hơn lần tiếp theo, sẵn sàng uốn cong ở những chỗ cần phải uốn cong.

                                                                                                                                        Thực sự không có sự lựa chọn nào khác. Thí nghiệm là cách để học những gì hiệu quả và không hiệu quả. Cố gắng tránh những bước đi sai lầm trong thiết kế sẽ dẫn đến kết quả kém chất lượng hơn vì nó dựa trên kinh nghiệm ít hơn. Và nó có thể dễ dàng mất nhiều thời gian hơn so với một loạt các thí nghiệm nhanh.


                                                                                                                                          How to Model Less Obvious Kinds of Concepts

                                                                                                                                          Quan điểm lập trình hướng đối tượng dẫn chúng ta tới việc tìm kiếm và phát minh ra một số loại khái niệm nhất định. Những đối tượng, ngay cả những đối tượng rất trừu tượng như "dồn tích," là phần cốt lõi của hầu hết các mô hình đối tượng, cùng với các hành động mà những đối tượng đó thực hiện. Đây là những "danh từ và động từ" mà các cuốn sách thiết kế hướng đối tượng nhập môn thường đề cập đến. Tuy nhiên, những danh mục khái niệm quan trọng khác cũng có thể được làm rõ ràng trong một mô hình.

                                                                                                                                          Tôi sẽ thảo luận về ba loại như vậy mà ban đầu tôi không nhận ra khi bắt đầu với các đối tượng. Thiết kế của tôi trở nên sắc nét hơn với mỗi loại mà tôi học được.

                                                                                                                                          Explicit Constraints

                                                                                                                                          Các ràng buộc tạo thành một loại khái niệm mô hình đặc biệt quan trọng. Chúng thường xuất hiện một cách ngầm định, và việc diễn đạt chúng một cách rõ ràng có thể cải thiện đáng kể thiết kế.

                                                                                                                                          Đôi khi, các ràng buộc tìm thấy một chỗ ở tự nhiên trong một đối tượng hoặc phương thức. Một đối tượng "Bucket" phải đảm bảo được bất biến rằng nó không chứa nhiều hơn dung tích của nó.

                                                                                                                                          Figure 9.10.

                                                                                                                                          graphics/09fig10.gif

                                                                                                                                          Một bất biến đơn giản như thế này có thể được thực thi bằng cách sử dụng logic case trong mỗi thao tác có khả năng thay đổi nội dung.

                                                                                                                                          class Bucket { private float capacity; private float contents; public void pourIn(float addedVolume) { if (contents + addedVolume > capacity) { contents = capacity; } else { contents = contents + addedVolume; } } } 

                                                                                                                                          Logic này đơn giản đến nỗi quy tắc là rõ ràng. Nhưng bạn có thể dễ dàng tưởng tượng rằng ràng buộc này có thể bị lãng quên trong một lớp phức tạp hơn. Hãy tách nó thành một phương thức riêng, với một tên rõ ràng và rõ ràng thể hiện tầm quan trọng của ràng buộc.

                                                                                                                                          class Bucket { private float capacity; private float contents; public void pourIn(float addedVolume) { float volumePresent = contents + addedVolume; contents = constrainedToCapacity(volumePresent); } private float constrainedToCapacity(float volumePlacedIn) { if (volumePlacedIn > capacity) return capacity; return volumePlacedIn; } } 

                                                                                                                                          Cả hai phiên bản của mã này đều thực thi ràng buộc, nhưng phiên bản thứ hai có mối quan hệ rõ ràng hơn với mô hình (yêu cầu cơ bản của THIẾT KẾ DỰA TRÊN MÔ HÌNH). Quy tắc rất đơn giản này dễ hiểu trong hình thức ban đầu của nó, nhưng khi các quy tắc được thực thi trở nên phức tạp hơn, chúng bắt đầu áp đảo đối tượng hoặc hoạt động mà chúng áp dụng, như bất kỳ khái niệm ngầm nào. Việc tách ràng buộc vào một phương thức riêng cho phép chúng ta đặt tên cho nó một cách rõ ràng, điều này làm cho ràng buộc trở nên rõ ràng trong thiết kế của chúng ta. Nó bây giờ là một cái tên mà chúng ta có thể thảo luận. Cách tiếp cận này cũng tạo ra không gian cho ràng buộc. Một quy tắc phức tạp hơn có thể dễ dàng sản xuất một phương thức dài hơn cả phương thức gọi nó (phương thức pourIn() trong trường hợp này). Bằng cách này, phương thức gọi vẫn đơn giản và tập trung vào nhiệm vụ của nó trong khi ràng buộc có thể phát triển về độ phức tạp nếu cần thiết.

                                                                                                                                          Phương pháp tách biệt này cho phép ràng buộc có không gian để phát triển, nhưng có nhiều trường hợp khi một ràng buộc không thể vừa vặn một cách thoải mái trong một phương pháp đơn lẻ. Hoặc ngay cả khi phương pháp vẫn đơn giản, nó có thể dựa vào thông tin mà đối tượng không cần cho trách nhiệm chính của mình. Quy tắc có thể không có chỗ ở tốt trong một đối tượng hiện có.

                                                                                                                                          Dưới đây là một số dấu hiệu cảnh báo cho thấy một ràng buộc đang làm biến đổi thiết kế của đối tượng chủ.

                                                                                                                                          1. Đánh giá một ràng buộc đòi hỏi dữ liệu không phù hợp với định nghĩa của đối tượng.

                                                                                                                                          Các quy tắc liên quan xuất hiện trong nhiều đối tượng, buộc phải sao chép hoặc kế thừa giữa các đối tượng vốn không thuộc cùng một gia đình.

                                                                                                                                          Nhiều cuộc trò chuyện về thiết kế và yêu cầu xoay quanh các ràng buộc, nhưng trong quá trình triển khai, chúng bị ẩn giấu trong mã quy trình.

                                                                                                                                          Khi các ràng buộc làm mờ đi trách nhiệm cơ bản của đối tượng, hoặc khi ràng buộc này nổi bật trong miền nhưng lại không nổi bật trong mô hình, bạn có thể tách nó ra thành một đối tượng rõ ràng hoặc thậm chí mô hình hóa nó như một tập hợp các đối tượng và mối quan hệ. (Một cách tiếp cận bán chính thức sâu sắc về chủ đề này có thể được tìm thấy trong cuốn "Ngôn ngữ Ràng buộc Đối tượng: Mô hình hóa Chính xác với UML" [Warmer và Kleppe 1999].)

                                                                                                                                          Example
                                                                                                                                          Review: Overbooking Policy

                                                                                                                                          Trong Chương 1, chúng tôi đã làm việc với một thực tiễn kinh doanh vận chuyển phổ biến: đặt hàng hóa nhiều hơn 10% so với khả năng vận chuyển. (Kinh nghiệm đã dạy các công ty vận tải rằng việc đặt trước này bù đắp cho những đơn hủy vào phút chót, vì vậy tàu của họ sẽ chạy gần đầy.)

                                                                                                                                          Ràng buộc này về mối liên hệ giữa Voyage và Cargo đã được làm rõ, cả trong các sơ đồ và trong mã, bằng cách thêm một lớp mới đại diện cho ràng buộc đó.

                                                                                                                                          Figure 9.11. The model refactored to make policy explicit

                                                                                                                                          graphics/09fig11.gif

                                                                                                                                          Để xem xét mã và lý do trong ví dụ đầy đủ, xem trang 17.

                                                                                                                                          Processes as Domain Objects

                                                                                                                                          Ngay từ đầu, hãy đồng ý rằng chúng ta không muốn làm cho các quy trình trở thành một khía cạnh nổi bật trong mô hình của chúng ta. Các đối tượng được thiết kế để bao bọc các quy trình và cho phép chúng ta suy nghĩ về mục tiêu hoặc ý định của chúng thay vào đó.

                                                                                                                                          Những gì tôi đang nói ở đây là các quy trình tồn tại trong miền, mà chúng ta phải thể hiện trong mô hình. Khi những điều này xuất hiện, chúng thường dẫn đến những thiết kế đối tượng khó khăn.

                                                                                                                                          Ví dụ đầu tiên trong chương này đã mô tả một hệ thống vận chuyển hàng hóa để định tuyến hàng hóa. Quy trình định tuyến này có ý nghĩa kinh doanh. MỘT DỊCH VỤ là một cách để diễn đạt một quy trình như vậy một cách rõ ràng, đồng thời vẫn bao gồm các thuật toán vô cùng phức tạp.

                                                                                                                                          Khi có nhiều hơn một cách để thực hiện một quy trình, một cách tiếp cận khác là biến chính thuật toán hoặc một phần quan trọng của nó thành một đối tượng riêng biệt. Sự lựa chọn giữa các quy trình trở thành một sự lựa chọn giữa những đối tượng này, mỗi đối tượng đại diện cho một CHIẾN LƯỢC khác nhau. (Chương 12 sẽ xem xét chi tiết hơn về việc sử dụng CÁC CHIẾN LƯỢC trong lĩnh vực này.)

                                                                                                                                          Chìa khóa để phân biệt một quy trình nên được làm rõ từ một quy trình nên được giấu kín rất đơn giản: Đây có phải là điều mà các chuyên gia trong lĩnh vực thảo luận hay chỉ là một phần của cơ chế trong chương trình máy tính?

                                                                                                                                          Các ràng buộc và quy trình là hai thể loại khái niệm mô hình rộng lớn mà không tự nhiên xuất hiện khi lập trình trong một ngôn ngữ hướng đối tượng, nhưng chúng có thể thực sự làm sắc bén thiết kế một khi chúng ta bắt đầu suy nghĩ về chúng như là các yếu tố của mô hình.

                                                                                                                                          Một số loại khái niệm hữu ích thì hẹp hơn nhiều. Tôi sẽ kết thúc chương này với một khái niệm cụ thể hơn nhiều, nhưng cũng khá phổ biến. ĐẶC TÍNH cung cấp một cách ngắn gọn để diễn đạt một số loại quy tắc nhất định, tách chúng ra khỏi logic điều kiện và làm cho chúng rõ ràng trong mô hình.

                                                                                                                                          Tôi đã phát triển CÁC ĐỊNH NGHĨA trong sự hợp tác với Martin Fowler (Evans và Fowler 1997). Sự đơn giản của khái niệm này che giấu những sắc thái trong việc áp dụng và thực hiện, do đó có nhiều chi tiết trong phần này. Sẽ có nhiều thảo luận hơn nữa trong Chương 10, nơi mẫu được mở rộng. Sau khi đọc giải thích ban đầu về mẫu mà theo sau, bạn có thể muốn xem nhanh phần "Áp dụng và Thực hiện CÁC ĐỊNH NGHĨA", cho đến khi bạn thực sự cố gắng áp dụng mẫu.

                                                                                                                                          Specification

                                                                                                                                          graphics/09inf01.gif

                                                                                                                                          Trong tất cả các loại ứng dụng, các phương pháp kiểm tra Boolean xuất hiện thực sự là những phần của những quy tắc nhỏ. Miễn là chúng đơn giản, chúng ta xử lý chúng bằng các phương pháp kiểm tra, chẳng hạn như anIterator.hasNext() hoặc anInvoice.isOverdue(). Trong lớp Hóa đơn, mã trong isOverdue() là một thuật toán đánh giá một quy tắc. Ví dụ,

                                                                                                                                          public boolean isOverdue() { Date currentDate = new Date(); return currentDate.after(dueDate); } 

                                                                                                                                          Nhưng không phải tất cả các quy tắc đều đơn giản như vậy. Trên cùng một lớp Hóa đơn, một quy tắc khác, anInvoice.isDelinquent() có lẽ sẽ bắt đầu bằng việc kiểm tra xem Hóa đơn có bị quá hạn hay không, nhưng đó chỉ là sự khởi đầu. Một chính sách về thời gian ân hạn có thể phụ thuộc vào trạng thái tài khoản của khách hàng. Một số hóa đơn quá hạn sẽ sẵn sàng để gửi thông báo thứ hai, trong khi những hóa đơn khác sẽ sẵn sàng để gửi cho một cơ quan thu nợ. Lịch sử thanh toán của khách hàng, chính sách công ty về các dòng sản phẩm khác nhau... sự rõ ràng của Hóa đơn như một yêu cầu thanh toán sẽ nhanh chóng bị mất đi trong khối lượng mã đánh giá quy tắc khổng lồ. Hóa đơn cũng sẽ phát triển đủ loại phụ thuộc vào các lớp miền và các hệ thống con không hỗ trợ nghĩa cơ bản đó.

                                                                                                                                          Tại thời điểm này, để cứu vãn lớp Hóa đơn, một nhà phát triển thường sẽ tái cấu trúc mã đánh giá quy tắc vào lớp ứng dụng (trong trường hợp này là một ứng dụng thu tiền). Bây giờ các quy tắc đã được tách ra khỏi lớp miền hoàn toàn, để lại một đối tượng dữ liệu chết mà không biểu đạt các quy tắc vốn có trong mô hình kinh doanh. Các quy tắc này cần phải được giữ lại trong lớp miền, nhưng chúng không phù hợp với đối tượng đang được đánh giá (trong trường hợp này là Hóa đơn). Không chỉ vậy, mà các phương thức đánh giá cũng tràn ngập mã điều kiện, khiến cho quy tắc trở nên khó đọc.

                                                                                                                                          Các nhà phát triển làm việc trong mô hình lập trình logic sẽ xử lý tình huống này theo cách khác. Những quy tắc như vậy sẽ được biểu diễn dưới dạng các predicate. Predicate là các hàm đánh giá thành "đúng" hoặc "sai" và có thể được kết hợp với nhau bằng các toán tử như "VÀ" và "HOẶC" để biểu thị các quy tắc phức tạp hơn. Với predicate, chúng ta có thể tuyên bố các quy tắc một cách rõ ràng và sử dụng chúng với Hóa đơn. Giá như chúng ta đang ở trong mô hình logic.

                                                                                                                                          Nhìn thấy điều này, mọi người đã cố gắng áp dụng các quy tắc logic theo cách mô hình hóa các đối tượng. Một số nỗ lực như vậy rất tinh vi, trong khi những nỗ lực khác thì ngây thơ. Một số thì tham vọng, trong khi một số thì khiêm tốn. Một số đã chứng tỏ giá trị, trong khi những cái khác bị loại bỏ như những thí nghiệm thất bại. Một vài nỗ lực đã làm chệch hướng các dự án của họ. Một điều rõ ràng: Mặc dù ý tưởng này hấp dẫn, nhưng việc triển khai hoàn toàn logic trong các đối tượng là một nhiệm vụ lớn lao. (Sau tất cả, lập trình logic là một toàn bộ mô hình hóa và thiết kế theo đúng nghĩa của nó.)

                                                                                                                                          Các quy tắc kinh doanh thường không phù hợp với trách nhiệm của bất kỳ THỰC THỂ hay ĐỐI TƯỢNG GIÁ TRỊ rõ ràng nào, và sự đa dạng cũng như sự kết hợp của chúng có thể áp đảo ý nghĩa cơ bản của đối tượng miền. Tuy nhiên, việc di chuyển các quy tắc ra khỏi lớp miền thậm chí còn tồi tệ hơn, vì mã miền không còn thể hiện được mô hình nữa.

                                                                                                                                          Lập trình logic cung cấp khái niệm về các đối tượng quy tắc tách biệt, có thể kết hợp gọi là "đối số," nhưng việc triển khai đầy đủ khái niệm này với các đối tượng thì rườm rà. Nó cũng quá chung chung đến nỗi không truyền đạt ý định nhiều như các thiết kế chuyên biệt hơn.

                                                                                                                                          May mắn thay, chúng ta không thực sự cần phải triển khai đầy đủ lập trình logic để thu được lợi ích lớn. Hầu hết các quy tắc của chúng ta đều rơi vào một vài trường hợp đặc biệt. Chúng ta có thể mượn khái niệm về các giao thức và tạo ra các đối tượng chuyên biệt để đánh giá một giá trị Boolean. Những phương thức kiểm tra mà trở nên phức tạp sẽ được mở rộng một cách gọn gàng thành các đối tượng riêng biệt. Chúng là những bài kiểm tra đúng sai nhỏ có thể được tách ra thành một ĐỐI TƯỢNG GIÁ TRỊ riêng. Đối tượng mới này có thể đánh giá một đối tượng khác để xem liệu giao thức có đúng cho đối tượng đó không.

                                                                                                                                          Figure 9.12.

                                                                                                                                          graphics/09fig12.gif

                                                                                                                                          Nói cách khác, đối tượng mới là một đặc tả. Một ĐẶC TẢ xác định một ràng buộc về trạng thái của một đối tượng khác, mà có thể có hoặc không có. Nó có nhiều công dụng, nhưng một công dụng truyền đạt khái niệm cơ bản nhất là một ĐẶC TẢ có thể kiểm tra bất kỳ đối tượng nào để xem nó có thỏa mãn các tiêu chí đã được chỉ định hay không.

                                                                                                                                          Do đó:

                                                                                                                                          Tạo các ĐỐI TƯỢNG GIÁ TRỊ giống như predicate rõ ràng cho các mục đích chuyên biệt. MỘT ĐẶC TÍNH là một predicate xác định xem một đối tượng có thỏa mãn hoặc không thỏa mãn một số tiêu chí nào đó.

                                                                                                                                          Nhiều ĐẶC TÍNH là các kiểm tra đơn giản, chuyên dụng, như trong ví dụ về hóa đơn quá hạn. Trong các trường hợp mà các quy tắc phức tạp, khái niệm có thể được mở rộng để cho phép các đặc tính đơn giản được kết hợp, giống như các tiền đề được kết hợp với các toán tử logic. (Kỹ thuật này sẽ được thảo luận trong chương tiếp theo.) Mô hình cơ bản vẫn giữ nguyên và cung cấp một con đường từ các mô hình đơn giản hơn đến các mô hình phức tạp hơn.

                                                                                                                                          Trường hợp của hóa đơn quá hạn có thể được mô hình hóa bằng một ĐẶC TẢ xác định nghĩa là quá hạn và có thể đánh giá bất kỳ hóa đơn nào và đưa ra quyết định.

                                                                                                                                          Figure 9.13. A more elaborate delinquency rule factored out as a SPECIFICATION

                                                                                                                                          graphics/09fig13.gif

                                                                                                                                          Đặc tả giữ quy tắc trong lớp miền. Bởi vì quy tắc là một đối tượng hoàn chỉnh, thiết kế có thể phản ánh rõ ràng hơn mô hình. Một nhà máy có thể cấu hình một đặc tả bằng cách sử dụng thông tin từ các nguồn khác, chẳng hạn như tài khoản của khách hàng hoặc cơ sở dữ liệu chính sách của công ty. Việc cung cấp quyền truy cập trực tiếp vào những nguồn này từ Hóa đơn sẽ kết nối các đối tượng theo một cách không liên quan đến yêu cầu thanh toán (trách nhiệm cơ bản của Hóa đơn). Trong trường hợp này, Đặc tả Hóa đơn quá hạn được tạo ra, được sử dụng để đánh giá một số Hóa đơn, và sau đó bị loại bỏ, vì vậy một ngày đánh giá cụ thể đã được xây dựng ngay bên trong - một sự đơn giản hóa tuyệt vời. Một đặc tả có thể được cung cấp thông tin cần thiết để thực hiện công việc của nó một cách đơn giản và trực tiếp.

                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                          Khái niệm cơ bản của ĐẶC TÍNH rất đơn giản và giúp chúng ta suy nghĩ về một vấn đề mô hình miền. Nhưng một THIẾT KẾ ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH cần một triển khai hiệu quả mà cũng thể hiện khái niệm. Để thực hiện điều đó cần phải đào sâu vào cách mà mẫu sẽ được áp dụng. Một mẫu miền không chỉ là một ý tưởng thú vị cho một sơ đồ UML; nó là một giải pháp cho một vấn đề lập trình mà vẫn giữ được THIẾT KẾ ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH.

                                                                                                                                          Khi bạn áp dụng một mẫu một cách thích hợp, bạn có thể khai thác một kho tàng tư tưởng về cách tiếp cận một loại vấn đề mô hình miền, và bạn có thể hưởng lợi từ nhiều năm kinh nghiệm trong việc tìm kiếm các triển khai hiệu quả. Có rất nhiều chi tiết trong phần thảo luận về ĐẶC TẢ phía dưới: nhiều tùy chọn cho các tính năng và cách tiếp cận để triển khai. Một mẫu không phải là một cuốn sách nấu ăn. Nó cho phép bạn bắt đầu từ một cơ sở kinh nghiệm để phát triển giải pháp của mình, và nó cung cấp cho bạn một số ngôn ngữ để nói về những gì bạn đang làm.

                                                                                                                                          Bạn có thể muốn đọc lướt qua các khái niệm chính khi lần đầu đọc. Sau đó, khi bạn gặp phải tình huống, bạn có thể quay lại và rút ra từ kinh nghiệm được ghi lại trong phần thảo luận chi tiết. Sau đó, bạn có thể đi tìm và xác định một giải pháp cho vấn đề của bạn.

                                                                                                                                          Applying and Implementing SPECIFICATION

                                                                                                                                          Giá trị lớn của ĐẶC TÍNH là nó thống nhất chức năng của ứng dụng mà có thể trông có vẻ rất khác nhau. Chúng ta có thể cần chỉ định trạng thái của một đối tượng cho một hoặc nhiều trong ba mục đích này.

                                                                                                                                          1. Để xác thực một đối tượng xem nó có đáp ứng nhu cầu nào đó hoặc đã sẵn sàng cho một mục đích nào đó không.

                                                                                                                                          Để chọn một đối tượng từ một tập hợp (như trong trường hợp truy vấn các hóa đơn quá hạn)

                                                                                                                                          Để chỉ định việc tạo ra một đối tượng mới để phù hợp với một nhu cầu nào đó.

                                                                                                                                          Ba cách sử dụng này—xác minh, lựa chọn và xây dựng theo đơn đặt hàng—là giống nhau ở cấp độ khái niệm. Nếu không có một mẫu như ĐẶC TẢ, cùng một quy tắc có thể xuất hiện dưới nhiều hình thức khác nhau, và có thể là các hình thức mâu thuẫn. Sự thống nhất khái niệm có thể bị mất. Việc áp dụng mẫu ĐẶC TẢ cho phép sử dụng một mô hình nhất quán, ngay cả khi việc triển khai có thể phải khác biệt.

                                                                                                                                          Validation

                                                                                                                                          Cách sử dụng đơn giản nhất của một ĐỊNH NGHĨA là xác thực, và đây là cách sử dụng thể hiện khái niệm một cách rõ ràng nhất.

                                                                                                                                          Figure 9.14. A model applying a SPECIFICATION for validation

                                                                                                                                          graphics/09fig14.gif

                                                                                                                                          class DelinquentInvoiceSpecification extends InvoiceSpecification { private Date currentDate; // An instance is used and discarded on a single date public DelinquentInvoiceSpecification(Date currentDate) { this.currentDate = currentDate; } public boolean isSatisfiedBy(Invoice candidate) { int gracePeriod = candidate.customer().getPaymentGracePeriod(); Date firmDeadline = DateUtility.addDaysToDate(candidate.dueDate(), gracePeriod); return currentDate.after(firmDeadline); } } 

                                                                                                                                          Bây giờ, giả sử chúng ta cần hiển thị một lá cờ đỏ mỗi khi một nhân viên bán hàng đề cập đến một khách hàng có hóa đơn trễ hạn. Chúng ta chỉ cần viết một phương thức trong một lớp khách hàng, đại loại như vậy.

                                                                                                                                          public boolean accountIsDelinquent(Customer customer) { Date today = new Date(); Specification delinquentSpec = new DelinquentInvoiceSpecification(today); Iterator it = customer.getInvoices().iterator(); while (it.hasNext()) { Invoice candidate = (Invoice) it.next(); if (delinquentSpec.isSatisfiedBy(candidate)) return true; } return false; } 
                                                                                                                                          Selection (or Querying)

                                                                                                                                          Kiểm tra xác thực một đối tượng cá nhân để xem nó có đáp ứng một số tiêu chí hay không, có lẽ để khách hàng có thể hành động dựa trên kết luận đó. Một nhu cầu phổ biến khác là chọn một tập con của một bộ sưu tập các đối tượng dựa trên một số tiêu chí. Cùng một khái niệm về ĐẶC TÍNH có thể được áp dụng ở đây, nhưng các vấn đề thực hiện thì khác nhau.

                                                                                                                                          Giả sử có một yêu cầu ứng dụng để liệt kê tất cả khách hàng có Hóa đơn trễ hạn. Về lý thuyết, Đặc tả Hóa đơn trễ hạn mà chúng tôi đã định nghĩa trước đó vẫn có thể áp dụng, nhưng trên thực tế, việc triển khai của nó có thể phải thay đổi. Để chứng minh rằng khái niệm là giống nhau, hãy giả định trước rằng số lượng Hóa đơn là nhỏ, có thể đã có trong bộ nhớ. Trong trường hợp này, việc triển khai đơn giản đã được phát triển cho việc xác thực vẫn có tác dụng. Kho Hóa đơn có thể có một phương thức tổng quát để chọn Hóa đơn dựa trên một ĐẶC TẢ:

                                                                                                                                          public Set selectSatisfying(InvoiceSpecification spec) { Set results = new HashSet(); Iterator it = invoices.iterator(); while (it.hasNext()) { Invoice candidate = (Invoice) it.next(); if (spec.isSatisfiedBy(candidate)) results.add(candidate); } return results; } 

                                                                                                                                          Vì vậy, một khách hàng có thể lấy một bộ sưu tập tất cả các hóa đơn quá hạn bằng một câu lệnh mã duy nhất.

                                                                                                                                          Set delinquentInvoices = invoiceRepository.selectSatisfying( new DelinquentInvoiceSpecification(currentDate)); 

                                                                                                                                          Dòng mã đó thiết lập khái niệm phía sau hoạt động. Tất nhiên, các đối tượng Hóa đơn có thể không có trong bộ nhớ. Có thể có hàng nghìn đối tượng như vậy. Trong một hệ thống doanh nghiệp điển hình, dữ liệu có thể đang ở trong một cơ sở dữ liệu quan hệ. Và, như đã chỉ ra ở các chương trước, trọng tâm của mô hình thường bị mất khi gặp các giao điểm với các công nghệ khác.

                                                                                                                                          Cơ sở dữ liệu quan hệ có khả năng tìm kiếm mạnh mẽ. Chúng ta có thể tận dụng sức mạnh đó để giải quyết vấn đề này một cách hiệu quả trong khi vẫn giữ được mô hình của một ĐẶC TẢ. THIẾT KẾ HƯỚNG MÔ HÌNH yêu cầu mô hình phải đồng bộ với việc triển khai, nhưng cho phép tự do chọn bất kỳ phương thức triển khai nào trung thực với ý nghĩa của mô hình. May mắn thay, SQL là một cách rất tự nhiên để viết ĐẶC TẢ.

                                                                                                                                          Dưới đây là một ví dụ đơn giản, trong đó truy vấn được bao bọc trong cùng một lớp với quy tắc xác thực. Một phương thức duy nhất được thêm vào Đặc tả Hóa đơn và được thực hiện trong lớp con Đặc tả Hóa đơn Quá hạn.

                                                                                                                                          public String asSQL() { return "SELECT * FROM INVOICE, CUSTOMER" + " WHERE INVOICE.CUST_ID = CUSTOMER.ID" + " AND INVOICE.DUE_DATE + CUSTOMER.GRACE_PERIOD" + " < " + SQLUtility.dateAsSQL(currentDate); } 

                                                                                                                                          CÁC ĐẶC TÍNH hòa hợp một cách mượt mà với CÁC KHO LƯU TRỮ, là những cơ chế nền tảng để cung cấp quyền truy cập truy vấn đến các đối tượng miền và bao bọc giao diện với cơ sở dữ liệu (xem Hình 9.15).

                                                                                                                                          Figure 9.15. The interaction between REPOSITORY and SPECIFICATION

                                                                                                                                          graphics/09fig15.gif

                                                                                                                                          Bây giờ, thiết kế này có một số vấn đề. Quan trọng nhất, các chi tiết của cấu trúc bảng đã rò rỉ vào LỚP MIỀN; chúng nên được tách biệt trong một lớp ánh xạ liên kết các đối tượng miền với các bảng quan hệ. Việc sao chép ngầm thông tin đó ở đây có thể gây hại cho khả năng sửa đổi và bảo trì của các đối tượng Hóa đơn và Khách hàng, vì bất kỳ sự thay đổi nào đối với các ánh xạ của chúng hiện phải được theo dõi ở hơn một nơi. Nhưng ví dụ này chỉ là một minh họa đơn giản về cách giữ quy tắc ở chỉ một nơi. Một số khung ánh xạ đối tượng-đa quan hệ cung cấp các phương tiện để diễn đạt một truy vấn như vậy theo các đối tượng mô hình và thuộc tính, tạo ra SQL thực tế ở lớp hạ tầng. Điều này sẽ cho phép chúng ta có bánh và ăn nó cùng một lúc.

                                                                                                                                          Khi hạ tầng không cứu trợ, chúng ta có thể tái cấu trúc SQL ra khỏi các đối tượng miền biểu cảm bằng cách thêm một phương thức truy vấn chuyên biệt vào Kho lưu trữ Hóa đơn. Để tránh nhúng quy tắc vào KHO LƯU TRỮ, chúng ta phải diễn đạt truy vấn một cách tổng quát hơn, không nắm bắt quy tắc nhưng có thể kết hợp hoặc đặt trong ngữ cảnh để làm rõ quy tắc (trong ví dụ này, bằng cách sử dụng cơ chế gọi hàm hai lần).

                                                                                                                                          public class InvoiceRepository { public Set selectWhereGracePeriodPast(Date aDate){ //This is not a rule, just a specialized query String sql = whereGracePeriodPast_SQL(aDate); ResultSet queryResultSet = SQLDatabaseInterface.instance().executeQuery(sql); return buildInvoicesFromResultSet(queryResultSet); } public String whereGracePeriodPast_SQL(Date aDate) { return "SELECT * FROM INVOICE, CUSTOMER" + " WHERE INVOICE.CUST_ID = CUSTOMER.ID" + " AND INVOICE.DUE_DATE + CUSTOMER.GRACE_PERIOD" + " < " + SQLUtility.dateAsSQL(aDate); } public Set selectSatisfying(InvoiceSpecification spec) { return spec.satisfyingElementsFrom(this); } } 

                                                                                                                                          Phương thức asSql() trên Đặc tả Hóa đơn được thay thế bằng satisfyingElementsFrom(InvoiceRepository), mà Đặc tả Hóa đơn Chậm thực hiện như sau:

                                                                                                                                          public class DelinquentInvoiceSpecification { // Basic DelinquentInvoiceSpecification code here public Set satisfyingElementsFrom( InvoiceRepository repository) { //Delinquency rule is defined as: // "grace period past as of current date" return repository.selectWhereGracePeriodPast(currentDate); } } 

                                                                                                                                          Điều này đưa SQL vào trong REPOSITORY, trong khi SPECIFICATION xác định câu truy vấn nào nên được sử dụng. Các quy tắc không được tập hợp gọn gàng trong SPECIFICATION, nhưng tuyên bố cần thiết về điều gì tạo thành tình trạng vi phạm (tức là, quá thời gian ân hạn) thì vẫn có đó.

                                                                                                                                          REPOSITORY hiện đang có một truy vấn rất chuyên biệt mà có khả năng sẽ chỉ được sử dụng trong trường hợp này. Điều đó là chấp nhận được, nhưng tùy thuộc vào tỷ lệ số hóa đơn quá hạn so với những hóa đơn chậm trả, một giải pháp trung gian cho phép các phương thức của REPOSITORY vẫn mang tính tổng quát hơn có thể vẫn mang lại hiệu suất tốt, trong khi giữ cho SPECIFICATION dễ hiểu hơn.

                                                                                                                                          public class InvoiceRepository { public Set selectWhereDueDateIsBefore(Date aDate) { String sql = whereDueDateIsBefore_SQL(aDate); ResultSet queryResultSet = SQLDatabaseInterface.instance().executeQuery(sql); return buildInvoicesFromResultSet(queryResultSet); } public String whereDueDateIsBefore_SQL(Date aDate) { return "SELECT * FROM INVOICE" + " WHERE INVOICE.DUE_DATE" + " < " + SQLUtility.dateAsSQL(aDate); } public Set selectSatisfying(InvoiceSpecification spec) { return spec.satisfyingElementsFrom(this); } } public class DelinquentInvoiceSpecification { //Basic DelinquentInvoiceSpecification code here public Set satisfyingElementsFrom( InvoiceRepository repository) { Collection pastDueInvoices = repository.selectWhereDueDateIsBefore(currentDate); Set delinquentInvoices = new HashSet(); Iterator it = pastDueInvoices.iterator(); while (it.hasNext()) { Invoice anInvoice = (Invoice) it.next(); if (this.isSatisfiedBy(anInvoice)) delinquentInvoices.add(anInvoice); } return delinquentInvoices; } } 

                                                                                                                                          Chúng ta sẽ gặp phải một chút giảm hiệu suất với đoạn mã này, vì chúng ta lấy ra nhiều Hoá đơn hơn và sau đó phải chọn từ chúng trong bộ nhớ. Liệu đây có phải là chi phí chấp nhận được cho việc phân chia trách nhiệm tốt hơn hay không hoàn toàn phụ thuộc vào hoàn cảnh. Có nhiều cách để triển khai các tương tác giữa CÁC THÔNG SỐ và CÁC KHO, nhằm tận dụng nền tảng phát triển, trong khi vẫn giữ nguyên các trách nhiệm cơ bản.

                                                                                                                                          Đôi khi, để cải thiện hiệu suất, hoặc có lẽ là để tăng cường bảo mật, các truy vấn có thể được thực hiện trên máy chủ dưới dạng các thủ tục lưu trữ. Trong trường hợp đó, CÁC THAM SỐ chỉ có thể chứa các tham số được phép bởi thủ tục lưu trữ. Tuy nhiên, giữa các triển khai khác nhau này không có sự khác biệt nào trong mô hình. Sự lựa chọn về triển khai là tự do, ngoại trừ trong những trường hợp cụ thể bị ràng buộc bởi mô hình. Tuy nhiên, điều này đem lại cách viết và duy trì truy vấn phức tạp hơn.

                                                                                                                                          Cuộc thảo luận này chỉ mới chạm đến bề mặt của những thách thức khi kết hợp CÁC ĐẶC TÍNH với cơ sở dữ liệu, và tôi sẽ không cố gắng đề cập đến tất cả các yếu tố có thể phát sinh. Tôi chỉ muốn cung cấp một cái nhìn tổng quan về loại lựa chọn phải được đưa ra. Mee và Hieatt thảo luận về một số vấn đề kỹ thuật liên quan đến việc thiết kế CƠ SỞ DỮ LIỆU với CÁC ĐẶC TÍNH trong bài viết của Fowler năm 2002.

                                                                                                                                          Building to Order (Generating)

                                                                                                                                          Khi Lầu Năm Góc muốn có một máy bay chiến đấu mới, các quan chức viết một bản đặc tả. Bản đặc tả này có thể yêu cầu rằng máy bay đạt tốc độ Mach 2, có tầm bay 1800 dặm, có chi phí không quá 50 triệu đô la, và những yêu cầu tương tự. Nhưng dù bản đặc tả có chi tiết đến đâu, nó không phải là một thiết kế cho máy bay, càng không phải là một chiếc máy bay. Một công ty kỹ thuật hàng không vũ trụ sẽ tiếp nhận bản đặc tả và tạo ra một hoặc nhiều thiết kế dựa trên đó. Các công ty cạnh tranh có thể sản xuất những thiết kế khác nhau, tất cả đều có thể đáp ứng yêu cầu ban đầu.

                                                                                                                                          Nhiều chương trình máy tính tạo ra các đối tượng, và các đối tượng đó cần phải được chỉ định. Khi bạn đặt một bức tranh vào tài liệu xử lý văn bản, văn bản sẽ chảy xung quanh nó. Bạn đã chỉ định vị trí của bức tranh, và có thể cả kiểu chảy của văn bản. Việc đặt chính xác các từ trên trang sau đó được xử lý bởi trình soạn thảo văn bản theo cách mà nó đáp ứng yêu cầu của bạn.

                                                                                                                                          Mặc dù có thể không rõ ràng ngay từ đầu, nhưng đây là cùng một khái niệm về ĐẶC TẢ đã được áp dụng cho việc xác nhận và lựa chọn. Chúng ta đang chỉ định tiêu chí cho các đối tượng chưa có mặt. Tuy nhiên, việc triển khai sẽ hoàn toàn khác. ĐẶC TẢ này không phải là một bộ lọc cho các đối tượng đã tồn tại, như với truy vấn. Nó không phải là một bài kiểm tra cho một đối tượng hiện có, như với việc xác nhận. Lần này, một đối tượng mới hoàn toàn hoặc một tập hợp các đối tượng sẽ được tạo ra hoặc cấu hình lại để thỏa mãn ĐẶC TẢ.

                                                                                                                                          Không sử dụng SPECIFICATION, có thể viết một trình tạo (generator) có các thủ tục hoặc một tập hợp các hướng dẫn tạo ra các đối tượng cần thiết. Mã này ngầm định định nghĩa hành vi của trình tạo.

                                                                                                                                          Thay vào đó, một giao diện của bộ tạo được định nghĩa theo một ĐẶC TẢ mô tả rõ ràng ràng buộc các sản phẩm của bộ tạo. Cách tiếp cận này có một số lợi thế.

                                                                                                                                          • Việc triển khai của bộ phát điện được tách biệt khỏi giao diện của nó. ĐẶC TẢ xác định các yêu cầu cho đầu ra nhưng không định nghĩa cách thức mà kết quả đó đạt được.

                                                                                                                                          • Giao diện giao tiếp các quy tắc của nó một cách rõ ràng, để các nhà phát triển có thể biết điều gì sẽ xảy ra với bộ phát sinh mà không cần phải hiểu tất cả các chi tiết của hoạt động của nó. Cách duy nhất để dự đoán hành vi của một bộ phát sinh được định nghĩa theo quy trình là chạy các trường hợp hoặc hiểu mỗi dòng mã.

                                                                                                                                          • Giao diện trở nên linh hoạt hơn, hoặc có thể được nâng cao với nhiều tính linh hoạt hơn, vì việc đưa ra yêu cầu nằm trong tay của khách hàng, trong khi bộ tạo chỉ có trách nhiệm thực hiện đúng theo nội dung của ĐẶC TẢ.

                                                                                                                                          • Cuối cùng, nhưng không kém phần quan trọng, loại giao diện này dễ dàng kiểm tra hơn, vì mô hình chứa một cách rõ ràng để xác định đầu vào cho bộ sinh mà cũng là một cách xác nhận đầu ra. Cụ thể, cùng một ĐẶC TẢ được truyền vào giao diện của bộ sinh để ràng buộc quá trình tạo ra cũng có thể được sử dụng, trong vai trò xác thực của nó (nếu việc triển khai hỗ trợ), để xác nhận rằng đối tượng đã tạo ra là chính xác. (Đây là một ví dụ về một PHÁT BIỂU, được thảo luận trong Chương 10.)

                                                                                                                                          Xây dựng theo yêu cầu có thể có nghĩa là tạo ra một đối tượng từ đầu, nhưng nó cũng có thể là một cấu hình của những đối tượng có sẵn để đáp ứng các yêu cầu.

                                                                                                                                          Example
                                                                                                                                          Chemical Warehouse Packer

                                                                                                                                          Có một kho chứa trong đó nhiều loại hóa chất được lưu trữ trong các chồng thùng lớn, giống như các toa xe hàng. Một số hóa chất là trơ và có thể được lưu trữ ở hầu hết mọi nơi. Một số hóa chất thì dễ bay hơi và phải được lưu trữ trong các thùng chứa được thông gió đặc biệt. Một số hóa chất là chất nổ và phải được lưu trữ trong các thùng chứa được bọc thép đặc biệt. Cũng có các quy định về các sự kết hợp cho phép trong một thùng chứa.

                                                                                                                                          Mục tiêu là viết phần mềm để tìm ra cách hiệu quả và an toàn để đưa các hóa chất vào các container.

                                                                                                                                          Figure 9.16. A model for warehouse storage

                                                                                                                                          graphics/09fig16.gif

                                                                                                                                          Chúng ta có thể bắt đầu bằng cách viết một quy trình để lấy một hóa chất và đặt nó vào một container, nhưng thay vào đó, hãy bắt đầu với vấn đề xác thực. Điều này sẽ buộc chúng ta phải làm rõ các quy tắc, và nó sẽ cung cấp cho chúng ta một cách để thử nghiệm triển khai cuối cùng.

                                                                                                                                          Mỗi hóa chất sẽ có một thông số kỹ thuật cho bình chứa:

                                                                                                                                          Hóa học

                                                                                                                                          Thông số kỹ thuật container

                                                                                                                                          TNT in Vietnamese is "TNT".

                                                                                                                                          Thùng container bọc thép

                                                                                                                                          Cát

                                                                                                                                          Mẫu sinh học

                                                                                                                                          Không được chia sẻ container với chất nổ.

                                                                                                                                          Amoniac

                                                                                                                                          Container thông gió

                                                                                                                                          Bây giờ, nếu chúng ta viết những điều này dưới dạng Thông số Container, chúng ta nên có thể lấy một cấu hình các container đã được đóng gói và kiểm tra xem nó có đáp ứng các ràng buộc này hay không.

                                                                                                                                          Tính năng của container

                                                                                                                                          Nội dung

                                                                                                                                          Đặc tả đã được đáp ứng chưa?

                                                                                                                                          Bọc thép

                                                                                                                                          20 pound thuốc nổ TNT

                                                                                                                                          500 lbs cát

                                                                                                                                          50 pound mẫu sinh học

                                                                                                                                          Amoniac

                                                                                                                                          Một phương pháp trong Đặc tả Container, isSatisfied(), sẽ phải được triển khai để kiểm tra các Tính năng Container cần thiết. Ví dụ, ĐẶC TẢ đính kèm với một hóa chất nổ sẽ tìm kiếm tính năng "bọc thép":

                                                                                                                                          public class ContainerSpecification { private ContainerFeature requiredFeature; public ContainerSpecification(ContainerFeature required) { requiredFeature = required; } boolean isSatisfiedBy(Container aContainer){ return aContainer.getFeatures().contains(requiredFeature); } } 

                                                                                                                                          Dưới đây là mã mẫu của khách hàng để thiết lập một hóa chất nổ:

                                                                                                                                          tnt.setContainerSpecification( new ContainerSpecification(ARMORED)); 

                                                                                                                                          Một phương pháp trên đối tượng Container, isSafelyPacked(), sẽ xác nhận rằng Container có tất cả các tính năng được chỉ định bởi các Hóa chất mà nó chứa.

                                                                                                                                          boolean isSafelyPacked(){ Iterator it = contents.iterator(); while (it.hasNext()) { Drum drum = (Drum) it.next(); if (!drum.containerSpecification().isSatisfiedBy(this)) return false; } return true; } 

                                                                                                                                          Vào lúc này, chúng ta có thể viết một ứng dụng giám sát sẽ sử dụng cơ sở dữ liệu hàng tồn kho và báo cáo bất kỳ tình huống không an toàn nào.

                                                                                                                                          Iterator it = containers.iterator(); while (it.hasNext()) { Container container = (Container) it.next(); if (!container.isSafelyPacked()) unsafeContainers.add(container); } 

                                                                                                                                          Đây không phải là phần mềm mà chúng tôi được yêu cầu viết. Sẽ tốt nếu thông báo cho những người trong doanh nghiệp về cơ hội này, nhưng chúng tôi đã được giao nhiệm vụ thiết kế một bộ đóng gói. Những gì chúng tôi có là một bài kiểm tra cho một bộ đóng gói. Hiểu biết về lĩnh vực và mô hình dựa trên ĐẶC TẢ của chúng tôi đã đặt chúng tôi vào vị trí để định nghĩa một giao diện rõ ràng và đơn giản cho một DỊCH VỤ sẽ nhận các bộ Drum và Container và đóng gói chúng theo đúng quy tắc.

                                                                                                                                          public interface WarehousePacker { public void pack(Collection containersToFill, Collection drumsToPack) throws NoAnswerFoundException; /* ASSERTION: At end of pack(), the ContainerSpecification of each Drum shall be satisfied by its Container. If no complete solution can be found, an exception shall be thrown. */ } 

                                                                                                                                          Hiện tại, nhiệm vụ thiết kế một bộ giải ràng buộc tối ưu để thực hiện các trách nhiệm của dịch vụ Packer đã được tách ra khỏi phần còn lại của ứng dụng, và những cơ chế đó sẽ không làm rối rắm phần thiết kế thể hiện mô hình. (Xem "Phong cách thiết kế khai báo," Chương 10, và CƠ CHẾ GẮN KẾT, Chương 15.) Tuy nhiên, các quy tắc governing packing vẫn chưa được tách ra khỏi các đối tượng miền.

                                                                                                                                          Example
                                                                                                                                          A Working Prototype of the Warehouse Packer

                                                                                                                                          Việc viết logic tối ưu để làm cho phần mềm đóng gói kho hoạt động là một công việc lớn. Một nhóm nhỏ các nhà phát triển và chuyên gia kinh doanh đã tách ra và bắt tay vào công việc này, nhưng họ thậm chí chưa bắt đầu viết mã. Trong khi đó, một nhóm nhỏ khác đang phát triển ứng dụng cho phép người dùng truy xuất hàng tồn kho từ cơ sở dữ liệu, cung cấp cho Packer và diễn giải kết quả. Họ đang cố gắng thiết kế cho Packer mà họ dự đoán. Nhưng tất cả những gì họ có thể làm là tạo ra một giao diện người dùng mẫu và làm việc trên một số mã tích hợp cơ sở dữ liệu. Họ không thể cho người dùng thấy một giao diện với hành vi có ý nghĩa để nhận phản hồi tốt. Vì lý do tương tự, nhóm Packer cũng đang làm việc trong một môi trường khép kín.

                                                                                                                                          Với các đối tượng miền và giao diện DỊCH VỤ được tạo ra trong ví dụ warehouse packer, nhóm ứng dụng nhận ra họ có thể xây dựng một triển khai rất đơn giản của Packer giúp quá trình phát triển diễn ra thuận lợi, cho phép công việc tiến triển song song và đóng vòng phản hồi, điều này chỉ đạt hiệu quả đầy đủ khi có một hệ thống end-to-end hoạt động.

                                                                                                                                          public class Container { private double capacity; private Set contents; //Drums public boolean hasSpaceFor(Drum aDrum) { return remainingSpace() >= aDrum.getSize(); } public double remainingSpace() { double totalContentSize = 0.0; Iterator it = contents.iterator(); while (it.hasNext()) { Drum aDrum = (Drum) it.next(); totalContentSize = totalContentSize + aDrum.getSize(); } return capacity – totalContentSize; } public boolean canAccommodate(Drum aDrum) { return hasSpaceFor(aDrum) && aDrum.getContainerSpecification().isSatisfiedBy(this); } } public class PrototypePacker implements WarehousePacker { public void pack(Collection containers, Collection drums) throws NoAnswerFoundException { /* This method fulfills the ASSERTION as written. However, when an exception is thrown, Containers' contents may have changed. Rollback must be handled at a higher level. */ Iterator it = drums.iterator(); while (it.hasNext()) { Drum drum = (Drum) it.next(); Container container = findContainerFor(containers, drum); container.add(drum); } } public Container findContainerFor( Collection containers, Drum drum) throws NoAnswerFoundException { Iterator it = containers.iterator(); while (it.hasNext()) { Container container = (Container) it.next(); if (container.canAccommodate(drum)) return container; } throw new NoAnswerFoundException(); } } 

                                                                                                                                          Thừa nhận rằng đoạn mã này còn nhiều điều chưa hoàn hảo. Nó có thể đóng cát vào các thùng chứa đặc biệt và sau đó hết chỗ trước khi đóng các hóa chất nguy hại. Chắc chắn rằng nó không tối ưu hóa doanh thu. Nhưng nhiều vấn đề tối ưu hóa chẳng bao giờ được giải quyết hoàn hảo. Cách triển khai này tuân thủ các quy tắc đã được nêu cho đến nay.


                                                                                                                                          Clearing Development Logjams with Working Prototypes

                                                                                                                                          Một đội phải chờ mã nguồn làm việc từ đội khác để có thể tiến lên. Cả hai đội đều phải chờ tích hợp hoàn chỉnh để thực hiện các thành phần của họ hoặc nhận phản hồi từ người dùng. Loại tắc nghẽn này thường có thể được giảm nhẹ bằng một nguyên mẫu ĐƯỢC ĐIỀU KHIỂN BỞI MÔ HÌNH của một thành phần chính, ngay cả khi nó không thỏa mãn tất cả các yêu cầu. Khi việc triển khai được tách rời khỏi giao diện, thì việc có bất kỳ triển khai nào cũng cho phép linh hoạt cho công việc dự án diễn ra song song. Khi thời điểm thích hợp đến, nguyên mẫu có thể được thay thế bằng một triển khai hiệu quả hơn. Trong thời gian đó, tất cả các phần khác của hệ thống đều có thứ gì đó để tương tác trong quá trình phát triển.

                                                                                                                                          Sở hữu nguyên mẫu này cho phép các nhà phát triển ứng dụng hoạt động với tốc độ tối đa, bao gồm cả các tích hợp với các hệ thống bên ngoài. Nhóm phát triển Packer cũng nhận được phản hồi khi các chuyên gia trong lĩnh vực tương tác với nguyên mẫu và củng cố ý tưởng của họ, giúp làm rõ yêu cầu và ưu tiên. Nhóm Packer quyết định tiếp quản nguyên mẫu và điều chỉnh nó để thử nghiệm các ý tưởng.

                                                                                                                                          Họ cũng giữ cho giao diện luôn được cập nhật với thiết kế mới nhất của mình, buộc phải tái cấu trúc ứng dụng và một số đối tượng miền, qua đó giải quyết các vấn đề tích hợp ngay từ đầu.

                                                                                                                                          Ngay khi Packer tinh vi sẵn sàng, việc tích hợp trở nên dễ dàng vì nó đã được viết theo một giao diện được xác định rõ ràng—cùng một giao diện và CÁC KHẲNG ĐỊNH mà ứng dụng đã được viết cho khi tương tác với nguyên mẫu.

                                                                                                                                          Cần những chuyên gia về thuật toán tối ưu hóa hàng tháng trời để làm cho nó đúng. Họ đã được hưởng lợi từ phản hồi mà họ nhận được từ người dùng tương tác với nguyên mẫu. Trong lúc đó, tất cả các phần khác của hệ thống đều có thứ để tương tác trong quá trình phát triển.

                                                                                                                                          Ở đây chúng ta có một ví dụ về "điều đơn giản nhất có thể hoạt động" mà thực sự trở nên khả thi nhờ vào một mô hình tinh vi hơn. Chúng ta có thể có một nguyên mẫu hoạt động của một thành phần rất phức tạp trong chỉ vài chục dòng mã dễ hiểu. Một phương pháp ít dựa vào mô hình hơn sẽ khó hiểu hơn, khó nâng cấp hơn (bởi vì Packer sẽ có sự liên kết chặt chẽ hơn với phần còn lại của thiết kế), và trong trường hợp này, có thể sẽ mất nhiều thời gian hơn để tạo mẫu.


                                                                                                                                            Chapter Ten. Supple Design

                                                                                                                                            graphics/10inf01.gif

                                                                                                                                            Mục đích cuối cùng của phần mềm là phục vụ người dùng. Nhưng trước tiên, phần mềm đó phải phục vụ các nhà phát triển. Điều này đặc biệt đúng trong một quy trình nhấn mạnh vào việc tái cấu trúc mã. Khi một chương trình phát triển, các nhà phát triển sẽ sắp xếp và viết lại từng phần. Họ sẽ tích hợp các đối tượng miền vào ứng dụng và với các đối tượng miền mới. Ngay cả nhiều năm sau, các lập trình viên bảo trì sẽ thay đổi và mở rộng mã. Mọi người phải làm việc với những thứ này. Nhưng liệu họ có muốn làm vậy không?

                                                                                                                                            Khi phần mềm với hành vi phức tạp thiếu thiết kế tốt, việc tái cấu trúc hoặc kết hợp các yếu tố trở nên khó khăn. Sự trùng lặp bắt đầu xuất hiện ngay khi một lập trình viên không tự tin dự đoán đầy đủ các tác động của một phép toán. Sự trùng lặp bị ép buộc khi các yếu tố thiết kế là đơn khối, khiến các phần không thể được tái kết hợp. Các lớp và phương thức có thể được chia nhỏ để dễ tái sử dụng hơn, nhưng rất khó để theo dõi tất cả các phần nhỏ đó làm gì. Khi phần mềm không có thiết kế rõ ràng, các lập trình viên ngại ngần khi nhìn vào mớ hỗn độn hiện có, chưa nói đến việc thực hiện một thay đổi có thể làm trầm trọng thêm tình trạng rối rắm hoặc làm hỏng một thứ gì đó do sự phụ thuộc không lường trước. Trong bất kỳ hệ thống nào ngoài những hệ thống nhỏ nhất, sự mong manh này đặt ra một giới hạn cho độ phong phú của hành vi mà có thể xây dựng một cách khả thi. Nó ngăn chặn việc tái cấu trúc và tinh chỉnh lặp đi lặp lại.

                                                                                                                                            Để một dự án tăng tốc khi tiến triển phát triển - thay vì bị nặng nề bởi di sản của chính nó - đòi hỏi một thiết kế mà dễ chịu khi làm việc, khuyến khích sự thay đổi. Một thiết kế linh hoạt.

                                                                                                                                            Thiết kế mềm mại là sự bổ sung cho mô hình sâu. Khi bạn đã khai thác các khái niệm ngầm và làm cho chúng trở nên rõ ràng, bạn có nguyên liệu thô. Thông qua chu kỳ lặp đi lặp lại, bạn sẽ mài giũa nguyên liệu đó thành một hình dạng hữu ích, xây dựng một mô hình mà đơn giản và rõ ràng nắm bắt các mối quan tâm chính, và định hình thiết kế cho phép nhà phát triển thực sự ứng dụng mô hình đó. Việc phát triển thiết kế và mã dẫn đến những hiểu biết làm tinh chỉnh các khái niệm mô hình. Quá trình cứ tiếp diễn – chúng ta trở lại với chu kỳ lặp và tái cấu trúc hướng tới cái nhìn sâu sắc hơn. Nhưng bạn đang cố gắng đạt được loại thiết kế nào? Bạn nên thử những thí nghiệm nào trên hành trình này? Đó là chủ đề của chương này.

                                                                                                                                            Rất nhiều sự thiết kế quá mức đã được biện minh bằng tên gọi linh hoạt. Nhưng thường thì, những lớp trừu tượng và gián tiếp quá mức gây cản trở. Hãy nhìn vào thiết kế phần mềm thực sự trao quyền cho những người sử dụng nó; bạn sẽ thường thấy điều gì đó đơn giản. Đơn giản không có nghĩa là dễ. Để tạo ra các yếu tố có thể được lắp ráp thành các hệ thống phức tạp và vẫn có thể hiểu được, một sự cống hiến cho THIẾT KẾ DỰA TRÊN MÔ HÌNH phải được kết hợp với một phong cách thiết kế có phần chặt chẽ. Điều này có thể yêu cầu kỹ năng thiết kế tương đối tinh vi để tạo ra hoặc sử dụng.

                                                                                                                                            Các nhà phát triển đóng hai vai trò, mỗi vai trò phải được phục vụ bởi thiết kế. Cùng một người có thể đảm nhận cả hai vai trò - thậm chí chuyển đổi qua lại trong vài phút - nhưng mối quan hệ với mã vẫn khác nhau. Một vai trò là nhà phát triển của một ứng dụng khách, người hòa trộn các đối tượng miền vào mã ứng dụng hoặc mã lớp miền khác, sử dụng các khả năng của thiết kế. Một thiết kế linh hoạt tiết lộ một mô hình nền tảng sâu sắc làm rõ tiềm năng của nó. Nhà phát triển ứng dụng khách có thể linh hoạt sử dụng một bộ khái niệm lỏng lẻo tối thiểu để diễn đạt một loạt các kịch bản trong miền. Các yếu tố thiết kế kết hợp với nhau một cách tự nhiên với kết quả có thể dự đoán, được phân loại rõ ràng và mạnh mẽ.

                                                                                                                                            Quan trọng không kém, thiết kế phải phục vụ cho nhà phát triển đang làm việc để thay đổi nó. Để mở ra khả năng thay đổi, một thiết kế phải dễ hiểu, tiết lộ mô hình cơ bản mà nhà phát triển của khách hàng đang dựa vào. Nó phải theo những đường nét của một mô hình sâu sắc trong lĩnh vực đó, để hầu hết các thay đổi có thể uốn cong thiết kế tại những điểm linh hoạt. Ảnh hưởng của mã của nó phải rõ ràng một cách minh bạch, để những hậu quả của một sự thay đổi sẽ dễ dàng dự đoán.

                                                                                                                                            Phiên bản sớm của một thiết kế thường cứng nhắc. Nhiều thiết kế không bao giờ đạt được sự linh hoạt trong khung thời gian hoặc ngân sách của dự án. Tôi chưa bao giờ thấy một chương trình lớn nào có chất lượng này suốt cả quá trình. Nhưng khi sự phức tạp kìm hãm sự tiến bộ, việc mài giũa những phần quan trọng và phức tạp nhất để đạt được một thiết kế linh hoạt sẽ tạo ra sự khác biệt giữa việc bị cuốn vào việc bảo trì di sản và vượt qua trần phức tạp.

                                                                                                                                            Không có công thức nào để thiết kế phần mềm như thế này, nhưng tôi đã tuyển chọn một bộ mẫu mà, theo kinh nghiệm của tôi, thường mang lại sự linh hoạt cho một thiết kế khi chúng phù hợp. Những mẫu này và ví dụ sẽ giúp bạn cảm nhận về một thiết kế linh hoạt và loại tư duy cần có để đạt được điều đó.

                                                                                                                                            Figure 10.1. Some patterns that contribute to supple design

                                                                                                                                            graphics/10fig01.gif


                                                                                                                                              Intention-Revealing Interfaces

                                                                                                                                              Trong thiết kế hướng miền, chúng ta muốn suy nghĩ về logic miền có ý nghĩa. Mã code tạo ra hiệu ứng của một quy tắc mà không nêu rõ quy tắc đó buộc chúng ta phải suy nghĩ về các quy trình phần mềm từng bước một. Điều này cũng áp dụng cho một phép tính chỉ là kết quả của việc chạy một số mã, nhưng không rõ ràng. Nếu không có mối liên hệ rõ ràng với mô hình, sẽ khó hiểu hiệu ứng của đoạn mã hoặc dự đoán hiệu ứng của một thay đổi. Chương trước đã đi sâu vào việc mô hình hóa các quy tắc và phép tính một cách rõ ràng. Việc triển khai những đối tượng như vậy yêu cầu rất nhiều sự hiểu biết về các chi tiết nhỏ nhặt của phép tính hoặc những điểm nhỏ trong quy tắc. Vẻ đẹp của các đối tượng là khả năng bao encapsulate tất cả những điều đó, để mã khách hàng trở nên đơn giản và có thể được diễn giải theo các khái niệm cấp cao hơn.

                                                                                                                                              Nhưng nếu giao diện không cung cấp cho nhà phát triển khách hàng những thông tin cần thiết để sử dụng đối tượng một cách hiệu quả, thì anh ta sẽ phải tìm hiểu sâu vào các chi tiết bên trong để hiểu biết. Một người đọc mã của khách hàng cũng sẽ phải làm điều tương tự. Khi đó, hầu hết giá trị của việc đóng gói đã bị mất. Chúng ta luôn phải đấu tranh với việc quá tải nhận thức: Nếu tâm trí của nhà phát triển khách hàng bị tràn ngập bởi chi tiết về cách một thành phần thực hiện nhiệm vụ của nó, thì tâm trí của anh ta sẽ không rõ ràng để xử lý những phức tạp của thiết kế khách hàng. Điều này đúng ngay cả khi cùng một người đảm nhận cả hai vai trò, phát triển và sử dụng mã của chính mình, vì ngay cả khi anh ta không cần phải học những chi tiết đó, thì vẫn có một giới hạn về số lượng yếu tố mà anh ta có thể xem xét cùng một lúc.

                                                                                                                                              Nếu một nhà phát triển phải xem xét việc triển khai một thành phần để sử dụng nó, giá trị của việc đóng gói sẽ bị mất. Nếu ai đó ngoài nhà phát triển gốc phải suy diễn mục đích của một đối tượng hoặc hoạt động dựa trên triển khai của nó, nhà phát triển mới có thể suy diễn một mục đích mà hoạt động hoặc lớp đó thực hiện chỉ hoàn toàn ngẫu nhiên. Nếu đó không phải là ý định, mã có thể hoạt động trong chốc lát, nhưng cơ sở khái niệm của thiết kế sẽ bị hỏng, và hai nhà phát triển sẽ làm việc với những mục đích đối lập.

                                                                                                                                              Để có được giá trị của việc mô hình hóa một khái niệm một cách rõ ràng dưới dạng lớp hoặc phương thức, chúng ta phải đặt tên cho các phần tử chương trình này sao cho phản ánh những khái niệm đó. Tên của các lớp và phương thức là cơ hội tuyệt vời để nâng cao sự giao tiếp giữa các lập trình viên và cải thiện sự trừu tượng của hệ thống.

                                                                                                                                              Kent Beck đã viết về việc đặt tên phương thức để truyền đạt mục đích của chúng bằng một CHỌN LỰA TIẾT LỘ Ý ĐỊNH (Beck 1997). Tất cả các phần tử công khai của một thiết kế cùng nhau tạo thành giao diện của nó, và tên của mỗi phần tử trong số đó mang đến một cơ hội để tiết lộ ý định của thiết kế. Tên kiểu, tên phương thức và tên tham số đều kết hợp để tạo thành một GIAO DIỆN TIẾT LỘ Ý ĐỊNH.

                                                                                                                                              Vì vậy:

                                                                                                                                              Đặt tên cho các lớp và thao tác để mô tả hiệu ứng và mục đích của chúng, mà không tham chiếu đến phương tiện mà chúng thực hiện những gì chúng hứa hẹn. Điều này giúp giảm bớt sự cần thiết cho nhà phát triển khách hàng trong việc hiểu các chi tiết bên trong. Những cái tên này nên tuân theo NGÔN NGỮ PHỔ BIẾN để các thành viên trong nhóm có thể nhanh chóng suy luận ý nghĩa của chúng. Viết một bài kiểm tra cho một hành vi trước khi tạo ra nó, để buộc tư duy của bạn sang chế độ nhà phát triển khách hàng.

                                                                                                                                              Tất cả các cơ chế phức tạp nên được bao bọc phía sau các giao diện trừu tượng nói về ý định, chứ không phải phương tiện.

                                                                                                                                              Trong các giao diện công khai của miền, hãy nêu rõ các mối quan hệ và quy tắc, nhưng không phải cách chúng được thực thi; mô tả các sự kiện và hành động, nhưng không phải cách chúng được thực hiện; xây dựng phương trình nhưng không phải phương pháp số để giải nó. Đặt câu hỏi, nhưng đừng trình bày cách mà câu trả lời sẽ được tìm thấy.

                                                                                                                                              Example
                                                                                                                                              Refactoring: A Paint-Mixing Application

                                                                                                                                              Chương trình dành cho các cửa hàng sơn có thể cho khách hàng thấy kết quả của việc pha trộn các loại sơn tiêu chuẩn. Dưới đây là thiết kế ban đầu, có một lớp miền duy nhất.

                                                                                                                                              Figure 10.2.

                                                                                                                                              graphics/10fig02.gif

                                                                                                                                              Cách duy nhất để thậm chí đoán xem phương thức paint(Paint) làm gì là đọc mã nguồn.

                                                                                                                                              public void paint(Paint paint) { v = v + paint.getV(); //After mixing, volume is summed // Omitted many lines of complicated color mixing logic // ending with the assignment of new r, b, and y values. } 

                                                                                                                                              Được rồi, có vẻ như phương pháp này kết hợp hai loại sơn lại với nhau, kết quả có thể tích lớn hơn và màu sắc pha trộn.

                                                                                                                                              Để thay đổi góc nhìn của chúng ta, hãy viết một bài kiểm tra cho phương thức này. (Mã này dựa trên khung thử nghiệm JUnit.)

                                                                                                                                              public void testPaint() { // Create a pure yellow paint with volume=100 Paint yellow = new Paint(100.0, 0, 50, 0); // Create a pure blue paint with volume=100 Paint blue = new Paint(100.0, 0, 0, 50); // Mix the blue into the yellow yellow.paint(blue); // Result should be volume of 200.0 of green paint assertEquals(200.0, yellow.getV(), 0.01); assertEquals(25, yellow.getB()); assertEquals(25, yellow.getY()); assertEquals(0, yellow.getR()); } 

                                                                                                                                              Bài kiểm tra đã qua là điểm khởi đầu. Tại thời điểm này, nó không thỏa mãn vì mã trong bài kiểm tra không cho chúng ta biết nó đang làm gì. Hãy viết lại bài kiểm tra để phản ánh cách mà chúng ta muốn sử dụng các đối tượng Paint nếu chúng ta đang viết một ứng dụng khách. Ban đầu, bài kiểm tra này sẽ thất bại. Thực tế, nó thậm chí sẽ không biên dịch. Chúng ta đang viết nó để khám phá thiết kế giao diện của đối tượng Paint từ góc nhìn của nhà phát triển khách hàng.

                                                                                                                                              public void testPaint() { // Start with a pure yellow paint with volume=100 Paint ourPaint = new Paint(100.0, 0, 50, 0); // Take a pure blue paint with volume=100 Paint blue = new Paint(100.0, 0, 0, 50); // Mix the blue into the yellow ourPaint.mixIn(blue); // Result should be volume of 200.0 of green paint assertEquals(200.0, ourPaint.getVolume(), 0.01); assertEquals(25, ourPaint.getBlue()); assertEquals(25, ourPaint.getYellow()); assertEquals(0, ourPaint.getRed()); } 

                                                                                                                                              Chúng ta nên dành thời gian để viết một bài kiểm tra phản ánh cách mà chúng ta muốn giao tiếp với các đối tượng này. Sau đó, chúng ta sẽ tái cấu trúc lớp Paint để làm cho bài kiểm tra thành công.

                                                                                                                                              Figure 10.3.

                                                                                                                                              graphics/10fig03.gif

                                                                                                                                              Tên phương thức mới có thể không cho người đọc biết mọi thứ về tác động của việc "trộn" một Paint khác (để làm được điều đó, chúng ta sẽ cần các KHẲNG ĐỊNH, sẽ có trong vài trang tới). Nhưng nó sẽ cung cấp cho người đọc đủ thông tin để bắt đầu sử dụng lớp, đặc biệt là với ví dụ mà bài kiểm tra cung cấp. Và nó sẽ cho phép người đọc mã khách hàng hiểu được ý định của khách hàng. Trong vài ví dụ tiếp theo trong chương này, chúng ta sẽ tái cấu trúc lớp này một lần nữa để làm cho nó rõ ràng hơn.

                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                              Toàn bộ các tiểu miền có thể được tách ra thành các mô-đun riêng biệt và được bao bọc bởi CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH. Việc sử dụng cách tách biệt như vậy để tập trung một dự án và quản lý sự phức tạp của một hệ thống lớn sẽ được thảo luận chi tiết hơn trong Chương 15, "Tinh chế," với CÁC CƠ CHẾ GẮN KẾT và CÁC TIỂU MIỀN CHUNG.

                                                                                                                                              Nhưng trong hai mẫu tiếp theo, chúng ta sẽ nỗ lực để làm cho các hậu quả của việc sử dụng một phương pháp trở nên rất dễ đoán. Logic phức tạp có thể được thực hiện một cách an toàn trong CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ. Các phương pháp thay đổi trạng thái hệ thống có thể được đặc trưng bằng CÁC KHẲNG ĐỊNH.


                                                                                                                                                Side -Effect-Free Functions

                                                                                                                                                Các hoạt động có thể được chia thành hai loại chính, lệnh và truy vấn. Truy vấn lấy thông tin từ hệ thống, có thể là bằng cách đơn giản là truy cập dữ liệu trong một biến, hoặc thực hiện một phép tính dựa trên dữ liệu đó. Lệnh (còn được gọi là các bộ sửa đổi) là các hoạt động tác động đến một sự thay đổi nào đó trong hệ thống (ví dụ đơn giản là bằng cách thiết lập một biến). Trong tiếng Anh tiêu chuẩn, thuật ngữ "hiệu ứng phụ" ngụ ý một hậu quả không mong muốn, nhưng trong khoa học máy tính, nó có nghĩa là bất kỳ ảnh hưởng nào đến trạng thái của hệ thống. Đối với mục đích của chúng ta, hãy thu hẹp nghĩa đó xuống bất kỳ sự thay đổi nào trong trạng thái của hệ thống sẽ ảnh hưởng đến các hoạt động trong tương lai.

                                                                                                                                                Tại sao thuật ngữ "hiệu ứng phụ" lại được áp dụng cho những thay đổi có chủ đích do các thao tác gây ra? Tôi cho rằng điều này dựa trên kinh nghiệm với các hệ thống phức tạp. Hầu hết các thao tác đều gọi đến các thao tác khác, và những thao tác đó lại gọi đến những thao tác khác nữa. Ngay khi có sự lồng ghép sâu như vậy, trở nên rất khó để dự đoán tất cả các hậu quả của việc gọi một thao tác. Nhà phát triển của phần mềm khách có thể không có ý định đến những tác động của các thao tác ở tầng thứ hai và thứ ba - chúng đã trở thành hiệu ứng phụ theo đúng nghĩa của từ ngữ. Các yếu tố trong một thiết kế phức tạp tương tác theo những cách khác, có khả năng dẫn đến sự không thể đoán trước tương tự. Việc sử dụng thuật ngữ "hiệu ứng phụ" nhấn mạnh sự không thể tránh khỏi của sự tương tác đó.

                                                                                                                                                Sự tương tác của nhiều quy tắc hoặc sự kết hợp của các phép tính trở nên cực kỳ khó đoán. Nhà phát triển gọi một phép toán phải hiểu cách triển khai của nó và cách triển khai của tất cả các ủy quyền của nó để có thể dự đoán kết quả. Tính hữu ích của bất kỳ sự trừu tượng nào của các giao diện bị giới hạn nếu các nhà phát triển buộc phải xuyên thấu lớp vỏ. Nếu không có các trừu tượng có thể dự đoán an toàn, các nhà phát triển phải giới hạn sự bùng nổ tổ hợp, đặt ra một trần thấp về độ phong phú của hành vi mà có thể xây dựng.

                                                                                                                                                Các phép toán trả về kết quả mà không tạo ra các tác động phụ được gọi là hàm. Một hàm có thể được gọi nhiều lần và trả về cùng một giá trị mỗi lần. Một hàm có thể gọi các hàm khác mà không cần lo lắng về độ sâu của việc lồng nhau. Các hàm dễ dàng được kiểm tra hơn so với các phép toán có tác động phụ. Vì những lý do này, hàm làm giảm rủi ro.

                                                                                                                                                Rõ ràng, bạn không thể tránh khỏi các lệnh trong hầu hết các hệ thống phần mềm, nhưng vấn đề này có thể được giảm thiểu theo hai cách. Đầu tiên, bạn có thể giữ cho các lệnh và truy vấn được phân loại rõ ràng trong các thao tác khác nhau. Đảm bảo rằng các phương thức gây ra thay đổi không trả về dữ liệu miền và được giữ càng đơn giản càng tốt. Thực hiện tất cả các truy vấn và tính toán trong các phương thức không gây ra tác động phụ quan sát được (Meyer 1988).

                                                                                                                                                Thứ hai, thường có các mô hình và thiết kế thay thế không yêu cầu một đối tượng hiện có nào phải được sửa đổi. Thay vào đó, một ĐỐI TƯỢNG GIÁ TRỊ mới, đại diện cho kết quả của phép toán, được tạo ra và trả về. Đây là một kỹ thuật phổ biến, sẽ được minh họa trong ví dụ tiếp theo. Một ĐỐI TƯỢNG GIÁ TRỊ có thể được tạo ra để trả lời một truy vấn, được chuyển giao và bị quên - khác với một THỰC THỂ, vòng đời của nó được quản lý cẩn thận.

                                                                                                                                                CÁC ĐỐI TƯỢNG GIÁ TRỊ (VALUE OBJECTS) là bất biến, điều này có nghĩa là, ngoài các bộ khởi tạo chỉ được gọi trong quá trình tạo, tất cả các phép toán của chúng đều là các hàm. CÁC ĐỐI TƯỢNG GIÁ TRỊ, giống như các hàm, an toàn hơn khi sử dụng và dễ kiểm tra hơn. Một phép toán kết hợp logic hoặc tính toán với thay đổi trạng thái nên được tổ chức lại thành hai phép toán riêng biệt (Fowler 1999, p. 279). Nhưng theo định nghĩa, sự phân tách này của các tác dụng phụ vào các phương thức lệnh đơn giản chỉ áp dụng cho CÁC THỰC THỂ (ENTITIES). Sau khi hoàn tất việc tổ chức lại để tách sửa đổi khỏi truy vấn, hãy xem xét một sự tổ chức lại thứ hai để chuyển trách nhiệm cho các tính toán phức tạp vào một CÁC ĐỐI TƯỢNG GIÁ TRỊ. Các tác dụng phụ thường có thể được loại bỏ hoàn toàn bằng cách tạo ra một CÁC ĐỐI TƯỢNG GIÁ TRỊ thay vì thay đổi trạng thái hiện có, hoặc bằng cách chuyển toàn bộ trách nhiệm vào một CÁC ĐỐI TƯỢNG GIÁ TRỊ.

                                                                                                                                                Do đó:

                                                                                                                                                Đặt càng nhiều logic của chương trình vào các hàm càng tốt, các thao tác trả về kết quả mà không có tác động bên ngoài quan sát được. Phân chia rõ ràng các lệnh (các phương thức dẫn đến việc thay đổi trạng thái quan sát được) thành các thao tác rất đơn giản không trả về thông tin miền. Kiểm soát tác động bên ngoài thêm bằng cách chuyển logic phức tạp vào CÁC ĐỐI TƯỢNG GIÁ TRỊ khi có khái niệm phù hợp với trách nhiệm xuất hiện.

                                                                                                                                                CÁC HÀM KHÔNG CÓ TÁC DỤNG PHỤ, đặc biệt là trong CÁC ĐỐI TƯỢNG GIÁ TRỊ BẤT BIẾN, cho phép kết hợp các hoạt động một cách an toàn. Khi MỘT HÀM được trình bày qua MỘT GIAO DIỆN TIẾT LỘ Ý ĐỊNH, một lập trình viên có thể sử dụng nó mà không cần hiểu chi tiết về cách triển khai của nó.

                                                                                                                                                Example
                                                                                                                                                Refactoring the Paint-Mixing Application Again

                                                                                                                                                Một chương trình cho các cửa hàng cung cấp sơn có thể cho khách hàng thấy kết quả của việc trộn các loại sơn tiêu chuẩn. Bắt đầu từ nơi chúng ta đã dừng lại trong ví dụ trước, đây là lớp miền đơn.

                                                                                                                                                Figure 10.4.

                                                                                                                                                graphics/10fig04.gif

                                                                                                                                                public void mixIn(Paint other) { volume = volume.plus(other.getVolume()); // Many lines of complicated color-mixing logic // ending with the assignment of new red, blue, // and yellow values. } 
                                                                                                                                                Figure 10.5. The side effects of the mixIn() method

                                                                                                                                                graphics/10fig05.gif

                                                                                                                                                Nhiều điều đang diễn ra trong phương thức mixIn(), nhưng thiết kế này vẫn tuân theo quy tắc tách biệt việc sửa đổi với việc truy vấn. Một mối quan tâm, mà chúng ta sẽ đề cập sau, là khối lượng của đối tượng paint 2, đối số của phương thức mixIn(), đã được để lại trong tình trạng không rõ ràng. Khối lượng của paint 2 không bị thay đổi bởi thao tác, điều này có vẻ không hợp lý trong bối cảnh của mô hình khái niệm này. Đây không phải là vấn đề đối với các nhà phát triển ban đầu vì, theo như chúng tôi có thể nói, họ không quan tâm đến đối tượng paint 2 sau thao tác, nhưng thật khó để dự đoán hậu quả của các tác động phụ hoặc sự vắng mặt của chúng. Chúng ta sẽ trở lại câu hỏi này sớm trong cuộc thảo luận về CÁC KHẲNG ĐỊNH. Trước mắt, hãy cùng xem xét màu sắc.

                                                                                                                                                Màu sắc là một khái niệm quan trọng trong lĩnh vực này. Hãy thử thực hiện thí nghiệm làm cho nó trở thành một đối tượng rõ ràng. Nó nên được gọi là gì? "Màu sắc" là từ đầu tiên xuất hiện trong đầu, nhưng việc phân tích kiến thức trước đó đã mang lại cái nhìn quan trọng rằng việc pha màu khác nhau giữa sơn và màn hình ánh sáng RGB quen thuộc hơn. Tên gọi cần phản ánh điều này.

                                                                                                                                                Figure 10.6.

                                                                                                                                                graphics/10fig06.gif

                                                                                                                                                Việc tách ra màu sắc Pigment thực sự truyền đạt nhiều hơn so với phiên bản trước, nhưng phép toán vẫn giống nhau, vẫn trong phương thức mixIn(). Khi chúng ta tách dữ liệu màu ra, chúng ta nên mang theo hành vi liên quan. Trước khi làm điều đó, hãy lưu ý rằng Pigment Color là một ĐỐI TƯỢNG GIÁ TRỊ. Do đó, nó nên được coi là bất biến. Khi chúng ta pha sơn, chính đối tượng Paint đã bị thay đổi. Nó là một THỰC THỂ với một câu chuyện sống động. Ngược lại, một Pigment Color đại diện cho một sắc thái cụ thể của màu vàng luôn luôn giống hệt như vậy. Thay vào đó, việc pha trộn sẽ dẫn đến một đối tượng Pigment Color mới đại diện cho màu mới.

                                                                                                                                                Figure 10.7.

                                                                                                                                                graphics/10fig07.gif

                                                                                                                                                public class PigmentColor { public PigmentColor mixedWith(PigmentColor other, double ratio) { // Many lines of complicated color-mixing logic // ending with the creation of a new PigmentColor object // with appropriate new red, blue, and yellow values. } } public class Paint { public void mixIn(Paint other) { volume = volume + other.getVolume(); double ratio = other.getVolume() / volume; pigmentColor = pigmentColor.mixedWith(other.pigmentColor(), ratio); } } 
                                                                                                                                                Figure 10.8.

                                                                                                                                                graphics/10fig08.gif

                                                                                                                                                Bây giờ mã sửa đổi trong Paint đơn giản nhất có thể. Lớp Màu Sắc Pigment mới nắm bắt kiến thức và truyền đạt nó một cách rõ ràng, và nó cung cấp một HÀM KHÔNG TÁC ĐỘNG LÀM SAI có kết quả dễ hiểu, dễ kiểm tra và an toàn để sử dụng hoặc kết hợp với các thao tác khác. Bởi vì nó rất an toàn, logic phức tạp của việc trộn màu thực sự được đóng gói. Các nhà phát triển sử dụng lớp này không cần phải hiểu cách triển khai.

                                                                                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif


                                                                                                                                                  Assertions

                                                                                                                                                  Tách biệt các phép toán phức tạp thành các hàm KHÔNG CÓ TÁC DỤNG PHỤ giúp thu hẹp vấn đề, nhưng vẫn còn lại một số lệnh trên CÁC THỰC THỂ gây ra tác dụng phụ, và bất kỳ ai sử dụng chúng đều phải hiểu được hậu quả của chúng. CÁC ĐIỀU KIỆN làm cho các tác dụng phụ trở nên rõ ràng và dễ xử lý hơn.

                                                                                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                  Đúng vậy, một lệnh không chứa các phép toán phức tạp có thể dễ dàng được hiểu bằng cách kiểm tra. Nhưng trong một thiết kế nơi các phần lớn được xây dựng từ các phần nhỏ, một lệnh có thể gọi các lệnh khác. Nhà phát triển sử dụng lệnh cấp cao phải hiểu được hậu quả của mỗi lệnh cơ sở. Vậy thì còn gì cho việc đóng gói. Và vì các giao diện đối tượng không hạn chế tác động phụ, hai lớp con triển khai cùng một giao diện có thể có các tác động phụ khác nhau. Nhà phát triển sử dụng chúng sẽ muốn biết cái nào là cái nào để dự đoán các hậu quả. Vậy thì còn gì cho việc trừu tượng và đa hình.

                                                                                                                                                  Khi các tác dụng phụ của các phép toán chỉ được xác định ẩn dụ bởi việc triển khai của chúng, các thiết kế với nhiều sự ủy quyền trở thành một mớ bùng nhùng của nguyên nhân và hệ quả. Cách duy nhất để hiểu một chương trình là theo dõi quá trình thực thi qua các nhánh khác nhau. Giá trị của việc đóng gói bị mất đi. Sự cần thiết của việc theo dõi quá trình thực thi cụ thể đánh bại sự trừu tượng.

                                                                                                                                                  Chúng ta cần một cách để hiểu ý nghĩa của một yếu tố thiết kế và những hậu quả của việc thực hiện một thao tác mà không cần đi sâu vào nội bộ của nó. CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH giúp chúng ta đi được một phần trong việc này, nhưng những gợi ý không chính thức về ý định không phải lúc nào cũng đủ. Trường phái "thiết kế theo hợp đồng" bước thêm một bước nữa, đưa ra "các tuyên bố" về các lớp và phương thức mà lập trình viên đảm bảo sẽ đúng. Phong cách này được thảo luận chi tiết trong Meyer 1988. Ngắn gọn, "điều kiện sau" mô tả các tác động phụ của một thao tác, kết quả được đảm bảo khi gọi một phương thức. "Điều kiện trước" giống như các điều khoản nhỏ trong hợp đồng, những điều kiện cần được thỏa mãn để đảm bảo rằng điều kiện sau sẽ giữ vững. Các bất biến lớp đưa ra các tuyên bố về trạng thái của một đối tượng tại thời điểm kết thúc bất kỳ thao tác nào. Các bất biến cũng có thể được tuyên bố cho toàn bộ CÁC TỔ HỢP, định nghĩa một cách nghiêm ngặt các quy tắc về tính toàn vẹn.

                                                                                                                                                  Tất cả các khẳng định này mô tả trạng thái, không phải quy trình, vì vậy chúng dễ phân tích hơn. Các bất biến lớp giúp đặc trưng hóa ý nghĩa của một lớp và đơn giản hóa công việc của nhà phát triển khách hàng bằng cách làm cho các đối tượng trở nên dự đoán được hơn. Nếu bạn tin tưởng vào đảm bảo của một điều kiện sau, bạn không cần phải lo lắng về cách mà một phương thức hoạt động. Các tác động của các sự ủy thác nên đã được đưa vào các khẳng định.

                                                                                                                                                  Vì vậy:

                                                                                                                                                  Nêu rõ điều kiện sau khi thực hiện các thao tác và các bất biến của các lớp và TỔ HỢP. Nếu CÁC KHẲNG ĐỊNH không thể được mã hóa trực tiếp trong ngôn ngữ lập trình của bạn, hãy viết các bài kiểm tra đơn vị tự động cho chúng. Ghi chúng vào tài liệu hoặc các sơ đồ nơi phù hợp với phong cách của quy trình phát triển dự án.

                                                                                                                                                  Tìm kiếm mô hình với các tập hợp khái niệm nhất quán, giúp nhà phát triển suy luận các KHẲNG ĐỊNH dự kiến, tăng tốc độ học tập và giảm thiểu rủi ro của mã mâu thuẫn.

                                                                                                                                                  Mặc dù nhiều ngôn ngữ lập trình hướng đối tượng hiện tại không hỗ trợ trực tiếp các KHẲNG ĐỊNH, nhưng KHẲNG ĐỊNH vẫn là một cách mạnh mẽ để suy nghĩ về thiết kế. Các bài kiểm tra đơn vị tự động có thể phần nào bù đắp cho sự thiếu hỗ trợ từ ngôn ngữ. Vì KHẲNG ĐỊNH đều liên quan đến trạng thái, chứ không phải quy trình, nên chúng membuat các bài kiểm tra dễ viết. Cài đặt bài kiểm tra đặt các tiền đề vào vị trí; sau đó, sau khi thực thi, bài kiểm tra sẽ kiểm tra xem các hậu điều kiện có được giữ hay không.

                                                                                                                                                  Các bất biến và điều kiện trước và sau được nêu rõ cho phép một lập trình viên hiểu những hậu quả của việc sử dụng một phép toán hoặc đối tượng. Về lý thuyết, bất kỳ tập hợp khẳng định nào không mâu thuẫn cũng đều có thể hoạt động. Nhưng con người không chỉ tổng hợp các tiền đề trong đầu. Họ sẽ suy diễn và nội suy các khái niệm của mô hình, vì vậy điều quan trọng là tìm ra các mô hình hợp lý cho con người cũng như đáp ứng nhu cầu của ứng dụng.

                                                                                                                                                  Example
                                                                                                                                                  Back to Paint Mixing

                                                                                                                                                  Hãy nhớ rằng trong ví dụ trước, tôi đã lo lắng về sự mơ hồ của những gì xảy ra với đối số của phép toán mixIn(Paint) trên lớp Paint.

                                                                                                                                                  Figure 10.9.

                                                                                                                                                  graphics/10fig09.gif

                                                                                                                                                  Âm lượng của ống nghe được tăng lên bằng lượng âm lượng của đối số. Dựa trên hiểu biết chung của chúng ta về sơn vật lý, quá trình pha trộn này nên làm giảm đi sơn khác cùng một lượng, dẫn đến việc giảm nó xuống âm lượng bằng 0, hoặc loại bỏ hoàn toàn. Việc triển khai hiện tại không thay đổi đối số, và việc thay đổi các đối số là một loại tác dụng phụ khá rủi ro.

                                                                                                                                                  Để bắt đầu vững chắc, hãy nêu rõ điều kiện sau của phương thức mixIn() như sau:

                                                                                                                                                  Sau p1.mixIn(p2):

                                                                                                                                                  p1.thể tích được tăng lên bằng số lượng của p2.thể tích.

                                                                                                                                                  `Khối lượng p2 không thay đổi.`

                                                                                                                                                  Vấn đề là, các nhà phát triển sẽ mắc sai lầm, vì những thuộc tính này không phù hợp với các khái niệm mà chúng tôi đã mời họ suy nghĩ về. Giải pháp đơn giản sẽ là thay đổi khối lượng của loại sơn khác thành zero. Thay đổi một đối số là một thực hành không tốt, nhưng điều đó sẽ dễ dàng và trực quan. Chúng tôi có thể phát biểu một bất biến:

                                                                                                                                                  Tổng thể tích sơn không thay đổi khi trộn.

                                                                                                                                                  Nhưng đợi đã! Trong khi các nhà phát triển đang suy nghĩ về tùy chọn này, họ đã có một phát hiện. Hóa ra có một lý do thuyết phục mà các nhà thiết kế ban đầu đã thực hiện như vậy. Cuối cùng, chương trình báo cáo danh sách các loại sơn chưa trộn lẫn được thêm vào. Sau cùng, mục đích cuối cùng của ứng dụng này là giúp người dùng xác định các loại sơn nào nên được đưa vào hỗn hợp.

                                                                                                                                                  Vì vậy, việc làm cho mô hình thể tích nhất quán về logic sẽ khiến nó không phù hợp với các yêu cầu ứng dụng. Dường như có một tình huống khó xử. Liệu chúng ta có bị kẹt trong việc ghi chép lại điều kiện kỳ quái và cố gắng bù đắp bằng việc giao tiếp tốt? Không phải mọi thứ trên thế giới này đều dễ hiểu, và đôi khi đó là câu trả lời tốt nhất. Nhưng trong trường hợp này, sự vụng về dường như chỉ ra rằng có những khái niệm còn thiếu. Hãy tìm kiếm một mô hình mới.

                                                                                                                                                  We Can See Clearly Now

                                                                                                                                                  Khi chúng tôi tìm kiếm một mô hình tốt hơn, chúng tôi có những lợi thế đáng kể so với các nhà thiết kế ban đầu, nhờ vào việc phân tích dữ liệu và tái cấu trúc để có được sự hiểu biết sâu sắc hơn đã diễn ra trong thời gian qua. Ví dụ, chúng tôi tính toán màu sắc bằng một HÀM KHÔNG CÓ TÁC DỤNG PHỤ trên một ĐỐI TƯỢNG GIÁ TRỊ. Điều này có nghĩa là chúng tôi có thể lặp lại phép tính bất cứ khi nào chúng tôi cần. Chúng tôi nên tận dụng điều đó.

                                                                                                                                                  Chúng ta dường như đang giao cho Paint hai trách nhiệm cơ bản khác nhau. Hãy thử chia chúng ra.

                                                                                                                                                  Bây giờ chỉ có một lệnh, mixIn(). Nó chỉ thêm một đối tượng vào một tập hợp, một hiệu ứng rõ ràng từ sự hiểu biết trực quan về mô hình. Tất cả các thao tác khác là CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ.

                                                                                                                                                  Một phương pháp kiểm tra xác nhận một trong những KHẲNG ĐỊNH được liệt kê trong Hình 10.10 có thể trông giống như sau (sử dụng hệ thống kiểm thử JUnit):

                                                                                                                                                  public void testMixingVolume { PigmentColor yellow = new PigmentColor(0, 50, 0); PigmentColor blue = new PigmentColor(0, 0, 50); StockPaint paint1 = new StockPaint(1.0, yellow); StockPaint paint2 = new StockPaint(1.5, blue); MixedPaint mix = new MixedPaint(); mix.mixIn(paint1); mix.mixIn(paint2); assertEquals(2.5, mix.getVolume(), 0.01); } 
                                                                                                                                                  Figure 10.10.

                                                                                                                                                  graphics/10fig10.gif

                                                                                                                                                  Mô hình này nắm bắt và truyền đạt nhiều hơn về miền. Các bất biến và điều kiện hậu có ý nghĩa hợp lý, điều này sẽ giúp chúng dễ bảo trì và sử dụng hơn.

                                                                                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                  Tính giao tiếp của CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH, kết hợp với tính dự đoán được nhờ CÁC HÀM KHÔNG CÓ TÁC DỤNG PHỤ và CÁC KHẲNG ĐỊNH, nên giúp việc đóng gói và trừu tượng hóa trở nên an toàn.

                                                                                                                                                  Nguyên liệu tiếp theo trong các yếu tố có thể tái kết hợp là phân hủy hiệu quả.


                                                                                                                                                    Conceptual Contours

                                                                                                                                                    Đôi khi mọi người chia nhỏ chức năng để cho phép sự kết hợp linh hoạt. Đôi khi họ gộp nó lại thành một phần lớn để thu gọn độ phức tạp. Đôi khi họ tìm kiếm một độ chi tiết nhất quán, làm cho tất cả các lớp và thao tác ở cùng một quy mô tương tự. Đây là những đơn giản hóa quá mức không hoạt động tốt như những quy tắc chung. Nhưng chúng được thúc đẩy bởi một tập hợp các vấn đề cơ bản.

                                                                                                                                                    Khi các yếu tố của một mô hình hoặc thiết kế được nhúng trong một cấu trúc đơn khối, chức năng của chúng bị trùng lặp. Giao diện bên ngoài không nói lên tất cả những gì mà một khách hàng có thể quan tâm. Ý nghĩa của chúng khó hiểu, vì các khái niệm khác nhau được trộn lẫn với nhau.

                                                                                                                                                    Mặt khác, việc phân chia các lớp và phương thức có thể khiến khách hàng trở nên phức tạp một cách không cần thiết, buộc các đối tượng khách hàng phải hiểu cách những mảnh nhỏ ghép lại với nhau. Thậm chí, một khái niệm có thể bị mất hoàn toàn. Nửa của một nguyên tử urani không phải là urani. Và đương nhiên, không chỉ kích thước hạt mới quan trọng, mà còn là vị trí của hạt đó chạy như thế nào.

                                                                                                                                                    Các quy tắc trong sách dạy nấu ăn không hiệu quả. Nhưng có một sự nhất quán logic sâu sắc trong hầu hết các lĩnh vực, nếu không thì chúng sẽ không khả thi trong lĩnh vực của chính mình. Điều này không có nghĩa là các lĩnh vực hoàn toàn nhất quán, và chắc chắn rằng cách mọi người nói về chúng không nhất quán. Nhưng có lý do và sự hòa hợp ở đâu đó, nếu không thì việc mô hình hóa sẽ trở nên vô nghĩa. Bởi vì sự nhất quán cơ bản này, khi chúng ta tìm thấy một mô hình phù hợp với một phần nào đó của lĩnh vực, nó có khả năng cao sẽ nhất quán với các phần khác mà chúng ta phát hiện sau này. Đôi khi những phát hiện mới không dễ dàng để mô hình thích ứng, trong trường hợp đó chúng ta sẽ tái cấu trúc để có được cái nhìn sâu sắc hơn, và hy vọng có thể phù hợp với phát hiện tiếp theo.

                                                                                                                                                    Đây là một lý do tại sao việc tái cấu trúc lặp đi lặp lại cuối cùng dẫn đến sự linh hoạt. CÁC ĐƯỜNG CONCEPTUAL xuất hiện khi mã được điều chỉnh theo các khái niệm hoặc yêu cầu mới được hiểu.

                                                                                                                                                    Hai nguyên tắc cơ bản của sự kết hợp cao và sự tách rời thấp đóng vai trò trong thiết kế ở tất cả các quy mô, từ các phương thức cá nhân cho đến các lớp và MODULES, cho đến các cấu trúc quy mô lớn (xem Chương 16). Hai nguyên tắc này áp dụng cho các khái niệm cũng như cho mã. Để tránh rơi vào quan điểm máy móc về chúng, hãy làm dịu suy nghĩ kỹ thuật của bạn bằng cách thường xuyên kết nối với trực giác của bạn về miền. Với mỗi quyết định, hãy tự hỏi, "Đây có phải là một giải pháp tạm thời dựa trên một tập hợp mối quan hệ cụ thể trong mô hình và mã hiện tại, hay nó phản ánh một đường nét nào đó của miền cơ bản?"

                                                                                                                                                    Tìm kiếm đơn vị chức năng có ý nghĩa khái niệm, và thiết kế kết quả sẽ linh hoạt và dễ hiểu. Ví dụ, nếu "phép cộng" của hai đối tượng có ý nghĩa nhất quán trong miền, thì hãy triển khai các phương thức ở cấp độ đó. Đừng chia nhỏ hàm add() thành hai bước. Đừng tiến hành bước tiếp theo trong cùng một thao tác. Ở quy mô lớn hơn một chút, mỗi đối tượng nên là một khái niệm hoàn chỉnh duy nhất, một "GIÁ TRỊ TOÀN VẸN."

                                                                                                                                                    Mô hình GIÁ TRỊ TOÀN DIỆN, bởi Ward Cunningham.

                                                                                                                                                    Theo cùng cách đó, có những lĩnh vực trong bất kỳ lĩnh vực nào mà sự chi tiết không hấp dẫn đối với loại người mà phần mềm phục vụ. Người dùng của ứng dụng pha trộn sơn giả thuyết của chúng ta không thêm màu đỏ hay màu xanh; họ kết hợp các loại sơn hoàn chỉnh, chứa tất cả ba sắc tố. Việc nhóm những thứ không cần phải phân tích hay sắp xếp lại giúp tránh sự lộn xộn và làm cho việc nhìn thấy các yếu tố thực sự được dự định để tái kết hợp trở nên dễ dàng hơn. Nếu thiết bị vật lý của người dùng cho phép thêm các màu sắc riêng lẻ, lĩnh vực này sẽ bị thay đổi, và các sắc tố cá nhân có thể được điều chỉnh. Một nhà hóa học sơn sẽ cần điều khiển tỉ mỉ hơn nữa, điều này sẽ liên quan đến một phân tích hoàn toàn khác, có thể tạo ra một mô hình chi tiết hơn nhiều về thành phần của sơn so với màu sắc sắc tố trừu tượng của chúng ta phục vụ cho việc pha trộn sơn. Nhưng điều đó thật sự không liên quan đến bất kỳ ai tham gia vào dự án ứng dụng pha trộn sơn.

                                                                                                                                                    Vì vậy:

                                                                                                                                                    Phân tích các yếu tố thiết kế (các hoạt động, giao diện, lớp và TỔNG HỢP) thành các đơn vị gắn kết, xem xét trực giác của bạn về những phân chia quan trọng trong miền. Quan sát các trục thay đổi và ổn định thông qua các lần tái cấu trúc liên tiếp và tìm kiếm các ĐƯỜNG CONCEPTUAL CƠ BẢN giải thích những mẫu cắt xén này. Căn chỉnh mô hình với các khía cạnh nhất quán của miền làm cho nó trở thành một lĩnh vực kiến thức có giá trị ngay từ đầu.

                                                                                                                                                    Mục tiêu là một tập hợp giao diện đơn giản kết hợp hợp lý để tạo ra những tuyên bố hợp lý trong NGÔN NGỮ PHỔ BIẾN, mà không bị phân tâm bởi gánh nặng bảo trì của các lựa chọn không liên quan. Điều này thường là kết quả của việc tái cấu trúc: rất khó để tạo ra ngay từ đầu. Nhưng nó có thể không bao giờ xuất hiện từ việc tái cấu trúc theo định hướng kỹ thuật; nó xuất hiện từ việc tái cấu trúc để đạt được sự hiểu biết sâu sắc hơn.

                                                                                                                                                    Ngay cả khi thiết kế tuân theo CÁC ĐƯỜNG CONCEPTUAL, sẽ cần có các sửa đổi và tái cấu trúc. Khi việc tái cấu trúc liên tiếp có xu hướng được địa phương hóa, không làm lay chuyển nhiều khái niệm rộng lớn của mô hình, đó là một chỉ số cho thấy mô hình phù hợp. Gặp phải yêu cầu buộc phải thay đổi rộng rãi trong việc phân chia các đối tượng và phương thức là một thông điệp: Hiểu biết của chúng ta về lĩnh vực cần được tinh chỉnh. Đây là cơ hội để làm sâu sắc thêm mô hình và làm cho thiết kế linh hoạt hơn.

                                                                                                                                                    Example
                                                                                                                                                    The CONTOURS of Accruals

                                                                                                                                                    Trong Chương 9, một hệ thống theo dõi khoản vay đã được tái cấu trúc dựa trên hiểu biết sâu sắc hơn về các khái niệm kế toán:

                                                                                                                                                    Figure 10.11.

                                                                                                                                                    graphics/10fig11.gif

                                                                                                                                                    Mô hình mới chỉ chứa thêm một đối tượng nữa so với mô hình cũ, nhưng việc phân chia trách nhiệm đã thay đổi đáng kể.

                                                                                                                                                    Các lịch trình, vốn đã được xây dựng thông qua logic trường hợp trong các lớp Calculator, đã được tách ra thành các lớp riêng biệt cho các loại phí và lãi suất khác nhau. Mặt khác, các khoản thanh toán phí và lãi suất, trước đây được giữ riêng biệt, đã được hợp nhất lại với nhau.

                                                                                                                                                    Vì sự cộng hưởng của các khái niệm mới được rõ ràng và tính thống nhất của hệ thống Nhu cầu Đến hạn, nhà phát triển tin rằng mô hình này phù hợp hơn với một số ĐƯỜNG DẠNG KHÁI NIỆM của miền này.

                                                                                                                                                    Figure 10.12. This model accommodates adding new kinds of Accrual Schedules.

                                                                                                                                                    graphics/10fig12.gif

                                                                                                                                                    Sự thay đổi duy nhất mà nhà phát triển có thể dự đoán một cách tự tin là việc bổ sung các Lịch Tích lũy mới. Những yêu cầu đó đã chờ đợi sẵn sàng. Vì vậy, bên cạnh việc làm cho chức năng hiện có trở nên rõ ràng và đơn giản hơn, cô đã chọn một mô hình sẽ dễ dàng cho việc giới thiệu các lịch mới. Nhưng liệu cô có tìm thấy một HÌNH THỂ KHÁI NIỆM nào sẽ giúp thiết kế miền thay đổi và phát triển khi ứng dụng và doanh nghiệp tiến triển? Không thể đảm bảo rằng một thiết kế sẽ xử lý được những thay đổi không lường trước, nhưng cô nghĩ rằng điều đó đã cải thiện xác suất.

                                                                                                                                                    An Unanticipated Change

                                                                                                                                                    Khi dự án tiến triển, một yêu cầu đã xuất hiện về các quy tắc chi tiết để xử lý các khoản thanh toán sớm và muộn. Khi nghiên cứu vấn đề, nhà phát triển rất vui khi thấy rằng gần như cùng một quy tắc áp dụng cho các khoản thanh toán lãi suất và các khoản thanh toán phí. Điều này có nghĩa là các yếu tố mô hình mới sẽ kết nối một cách tự nhiên với lớp Thanh toán duy nhất.

                                                                                                                                                    Figure 10.13.

                                                                                                                                                    graphics/10fig13.gif

                                                                                                                                                    Thiết kế cũ sẽ buộc phải có sự trùng lặp giữa hai lớp Lịch sử Thanh toán. (Khó khăn này có thể đã gợi ra một nhận thức rằng lớp Thanh toán nên được chia sẻ, dẫn đến một mô hình tương tự qua một con đường khác.) Sự dễ dàng trong việc mở rộng này không đến từ việc cô ấy dự đoán trước sự thay đổi. Cũng không phải vì cô ấy tạo ra một thiết kế quá linh hoạt mà có thể đáp ứng bất kỳ sự thay đổi nào có thể xảy ra. Nó xảy ra vì trong lần tái cấu trúc trước đó, thiết kế đã được căn chỉnh với các khái niệm cơ bản của miền.

                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                    CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH cho phép khách hàng trình bày các đối tượng như là đơn vị ý nghĩa chứ không chỉ là cơ chế. CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ và CÁC KHÁM PHÁ làm cho việc sử dụng những đơn vị đó trở nên an toàn và kết hợp phức tạp. Sự xuất hiện của CÁC ĐƯỜNG CONCEPTUAL củng cố các phần của mô hình và cũng làm cho các đơn vị dễ hiểu hơn để sử dụng và kết hợp.

                                                                                                                                                    Chúng ta vẫn có thể gặp phải tình trạng quá tải khái niệm khi các mối liên hệ buộc chúng ta phải suy nghĩ về quá nhiều điều cùng một lúc.


                                                                                                                                                      Standalone Classes

                                                                                                                                                      Sự phụ thuộc lẫn nhau làm cho các mô hình và thiết kế trở nên khó hiểu. Chúng cũng làm cho việc kiểm tra và bảo trì trở nên khó khăn. Và sự phụ thuộc lẫn nhau dễ dàng tích tụ.

                                                                                                                                                      Mỗi mối quan hệ, tất nhiên, là một sự phụ thuộc, và để hiểu một lớp thì cần phải hiểu nó gắn liền với những gì. Những thứ gắn liền đó sẽ còn gắn liền với những thứ khác nữa, và chúng cũng phải được hiểu. Loại của mỗi tham số trong mỗi phương thức cũng là một sự phụ thuộc. Mỗi giá trị trả về cũng vậy.

                                                                                                                                                      Với một độ phụ thuộc, bạn phải suy nghĩ về hai lớp cùng một lúc và tính chất của mối quan hệ của chúng. Với hai độ phụ thuộc, bạn phải xem xét từng lớp trong ba lớp, tính chất mối quan hệ của mỗi lớp với từng lớp, và bất kỳ mối quan hệ nào mà chúng có thể có với nhau. Nếu chúng lại có các độ phụ thuộc, bạn cũng phải cẩn thận với những điều đó. Với ba độ phụ thuộc... nó sẽ trở nên phức tạp.

                                                                                                                                                      Cả MODULES và AGGREGATES đều nhằm mục đích hạn chế mạng lưới phụ thuộc lẫn nhau. Khi một miền con có tính gắn kết cao được tách ra thành một MODULE, một tập hợp các đối tượng được tách rời khỏi phần còn lại của hệ thống, vì vậy có một số lượng hữu hạn các khái niệm liên quan. Nhưng ngay cả một MODULE cũng có thể là một điều lớn cần suy nghĩ nếu không có một cam kết gần như cuồng nhiệt trong việc kiểm soát các phụ thuộc bên trong nó.

                                                                                                                                                      Ngay cả trong một MODULE, độ khó của việc diễn giải một thiết kế tăng lên đáng kể khi các phụ thuộc được thêm vào. Điều này làm tăng tải trọng tâm lý, giới hạn độ phức tạp của thiết kế mà một nhà phát triển có thể xử lý. Các khái niệm ngầm góp phần vào gánh nặng này nhiều hơn so với các tham chiếu rõ ràng.

                                                                                                                                                      Các mô hình tinh chế được chưng cất cho đến khi mọi kết nối còn lại giữa các khái niệm đại diện cho điều gì đó cơ bản cho ý nghĩa của những khái niệm đó. Trong một tập con quan trọng, số lượng các phụ thuộc có thể được giảm xuống còn bằng không, dẫn đến một lớp có thể được hiểu hoàn toàn tự nó, cùng với một vài phần tử nguyên thủy và khái niệm thư viện cơ bản.

                                                                                                                                                      Trong mọi môi trường lập trình, một vài điều cơ bản rất phổ biến đến mức chúng luôn có trong tâm trí. Chẳng hạn, trong phát triển Java, các kiểu nguyên thủy và một vài thư viện chuẩn cung cấp các cơ bản như số, chuỗi và tập hợp. Nói một cách thực tế, "số nguyên" không làm tăng gánh nặng trí tuệ. Ngoài ra, mỗi khái niệm bổ sung phải được giữ trong tâm trí để hiểu một đối tượng đều góp phần vào quá tải tâm lý.

                                                                                                                                                      Các khái niệm ngầm, được nhận diện hoặc không được nhận diện, cũng quan trọng như những tham chiếu rõ ràng. Mặc dù chúng ta có thể bỏ qua các phụ thuộc vào các giá trị nguyên thủy như số nguyên và chuỗi, nhưng chúng ta không thể bỏ qua những gì chúng đại diện. Ví dụ, trong các ví dụ pha trộn màu sơn đầu tiên, đối tượng Paint đã giữ ba số nguyên công khai đại diện cho các giá trị màu đỏ, vàng và xanh lam. Việc tạo ra đối tượng Màu Sắc Pigment không làm tăng số lượng khái niệm liên quan hay các phụ thuộc. Thay vào đó, nó đã làm cho những khái niệm đã có trở nên rõ ràng hơn và dễ hiểu hơn. Mặt khác, thao tác kích thước của Collection (size()) trả về một số nguyên đơn giản chỉ là một phép đếm, nghĩa cơ bản của một số nguyên, vì vậy không có khái niệm mới nào được ngụ ý.

                                                                                                                                                      Mỗi phụ thuộc đều đáng ngờ cho đến khi được chứng minh là cơ bản đối với khái niệm đằng sau đối tượng. Sự xem xét này bắt đầu với việc phân tách các khái niệm mô hình. Sau đó, điều này yêu cầu sự chú ý đến từng mối liên hệ và hoạt động riêng lẻ. Các lựa chọn về mô hình và thiết kế có thể giảm thiểu các phụ thuộc - thường là về không.

                                                                                                                                                      Sự kết nối lỏng lẻo là điều cốt yếu trong thiết kế đối tượng. Khi có thể, hãy làm đến nơi đến chốn. Loại bỏ tất cả các khái niệm khác ra khỏi bức tranh. Lúc đó, lớp sẽ hoàn toàn độc lập và có thể được nghiên cứu và hiểu một cách độc lập. Mỗi lớp độc lập như vậy đều giúp giảm bớt đáng kể gánh nặng của việc hiểu một MODULE.

                                                                                                                                                      Sự phụ thuộc vào các lớp khác trong cùng một mô-đun ít gây hại hơn so với những lớp bên ngoài. Tương tự, khi hai đối tượng tự nhiên liên kết chặt chẽ, nhiều thao tác liên quan đến cùng một cặp có thể làm rõ bản chất của mối quan hệ. Mục tiêu không phải là loại bỏ tất cả các phụ thuộc, mà là loại bỏ tất cả các phụ thuộc không thiết yếu. Nếu không thể loại bỏ mọi phụ thuộc, mỗi phụ thuộc được loại bỏ sẽ giúp nhà phát triển tập trung vào các phụ thuộc khái niệm còn lại.

                                                                                                                                                      Cố gắng phân tách các phép toán phức tạp nhất thành CÁC LỚP ĐỨNG ĐỘC LẬP, có lẽ bằng cách mô hình hóa CÁC ĐỐI TƯỢNG GIÁ TRỊ được giữ bởi các lớp có liên kết chặt chẽ hơn.

                                                                                                                                                      Khái niệm về sơn có liên quan cơ bản đến khái niệm về màu sắc. Nhưng màu sắc, ngay cả của phẩm màu, có thể được xem xét mà không cần đến sơn. Bằng cách làm rõ hai khái niệm này và chắt lọc mối quan hệ, sự liên kết một chiều còn lại nói lên điều gì đó quan trọng, và lớp Màu Phẩm, nơi phần lớn sự phức tạp về tính toán nằm, có thể được nghiên cứu và kiểm tra một cách độc lập.

                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                      Sự tách biệt thấp là một cách cơ bản để giảm tải về khái niệm. MỘT LỚP ĐỘC LẬP là một ví dụ điển hình của sự tách biệt thấp.

                                                                                                                                                      Việc loại bỏ các phụ thuộc không nên đồng nghĩa với việc làm giảm giá trị của mô hình bằng cách tùy tiện thu gọn mọi thứ thành các thành phần cơ bản. Mẫu cuối cùng trong chương này, ĐÓNG KÍ KHI HOẠT ĐỘNG, là một ví dụ về kỹ thuật giảm phụ thuộc trong khi vẫn giữ một giao diện phong phú.


                                                                                                                                                        Closure of Operations

                                                                                                                                                        Nếu chúng ta lấy hai số thực và nhân chúng với nhau, chúng ta sẽ nhận được một số thực khác. [Các số thực bao gồm tất cả các số hữu tỉ và tất cả các số vô tỉ.] Bởi vì điều này luôn đúng, chúng ta nói rằng các số thực "đóng trong phép nhân": không có cách nào để thoát khỏi tập hợp. Khi bạn kết hợp bất kỳ hai phần tử nào của tập hợp, kết quả cũng được bao gồm trong tập hợp.

                                                                                                                                                        Diễn đàn Toán học, Đại học Drexel

                                                                                                                                                        Tất nhiên, sẽ có những phụ thuộc, và đó không phải là điều xấu khi phụ thuộc đó là nền tảng cho khái niệm. Việc đơn giản hóa giao diện chỉ để xử lý những nguyên thủy có thể làm cho chúng trở nên nghèo nàn. Nhưng có rất nhiều phụ thuộc không cần thiết, thậm chí là những khái niệm toàn bộ, được giới thiệu tại các giao diện.

                                                                                                                                                        Hầu hết các đối tượng thú vị cuối cùng làm những việc không thể được đặc trưng chỉ bằng các phần tử nguyên thủy.

                                                                                                                                                        Một thực hành phổ biến khác trong thiết kế tinh tế là điều tôi gọi là "ĐÓNG KÍNH CÁC HOẠT ĐỘNG." Tên gọi này xuất phát từ hệ thống khái niệm tinh tế nhất, toán học. 1 + 1 = 2. Phép cộng được đóng dưới tập hợp các số thực. Các nhà toán học rất nhiệt tình trong việc không đưa vào các khái niệm không cần thiết, và tính chất của sự đóng kín cung cấp cho họ một cách để định nghĩa một phép toán mà không liên quan đến bất kỳ khái niệm nào khác. Chúng ta đã quen với sự tinh tế của toán học đến nỗi có thể rất khó để hiểu sức mạnh của những mẹo nhỏ của nó. Nhưng điều này cũng được sử dụng rộng rãi trong thiết kế phần mềm. Cách sử dụng cơ bản của XSLT là biến đổi một tài liệu XML thành một tài liệu XML khác. Loại phép toán XSLT này được đóng kín dưới tập hợp các tài liệu XML. Tính chất của sự đóng kín đơn giản hóa cực kỳ việc diễn giải một phép toán, và thật dễ dàng để nghĩ về việc kết nối hoặc kết hợp các phép toán đóng kín với nhau.

                                                                                                                                                        Vì vậy:

                                                                                                                                                        Nơi có thể, hãy định nghĩa một thao tác mà kiểu trả về của nó giống với kiểu của đối số (các đối số) của nó. Nếu người thực hiện có trạng thái được sử dụng trong phép toán, thì người thực hiện đó về cơ bản là một đối số của thao tác, do đó, đối số (các đối số) và giá trị trả về nên có cùng kiểu với người thực hiện. Một thao tác như vậy được đóng kín dưới tập hợp các thể hiện của kiểu đó. Một thao tác đóng kín cung cấp một giao diện cấp cao mà không làm phát sinh bất kỳ sự phụ thuộc nào vào các khái niệm khác.

                                                                                                                                                        Mẫu này thường được áp dụng cho các hoạt động của một ĐỐI TƯỢNG GIÁ TRỊ. Bởi vì chu kỳ sống của một THỰC THỂ có ý nghĩa trong miền, bạn không thể chỉ tạo ra một cái mới để trả lời một câu hỏi. Có những hoạt động mà trong đó loại THỰC THỂ được đóng. Bạn có thể hỏi một đối tượng Nhân viên về người giám sát của nó và nhận lại một Nhân viên khác. Nhưng nhìn chung, THỰC THỂ không phải là những khái niệm có khả năng là kết quả của một phép tính. Vì vậy, hầu hết, đây là một cơ hội để tìm kiếm trong các ĐỐI TƯỢNG GIÁ TRỊ.

                                                                                                                                                        Một phép toán có thể được đóng lại dưới một kiểu trừu tượng, trong trường hợp đó, các đối số cụ thể có thể thuộc các lớp cụ thể khác nhau. Rốt cuộc, phép cộng được đóng lại dưới các số thực, mà có thể là hữu tỉ hoặc vô tỉ.

                                                                                                                                                        Khi bạn đang thử nghiệm, tìm kiếm các cách để giảm sự phụ thuộc lẫn nhau và tăng cường sự kết nối, đôi khi bạn tiến gần đến mẫu này. Đối số phù hợp với phần thực hiện, nhưng kiểu trả về thì khác, hoặc kiểu trả về phù hợp với người nhận và đối số thì khác. Những thao tác này không được đóng lại, nhưng chúng mang lại một số lợi ích của CLOSURE. Khi kiểu bổ sung là một kiểu nguyên thủy hoặc lớp thư viện cơ bản, nó giải phóng tâm trí gần như giống như CLOSURE.

                                                                                                                                                        Trong ví dụ trước, phép toán mixedWith() của màu sắc Pigment được đóng lại dưới các màu sắc Pigment, và có một số ví dụ khác rải rác trong cuốn sách. Đây là một ví dụ cho thấy ý tưởng này có thể hữu ích như thế nào, ngay cả khi không đạt được sự ĐÓNG KÍ KÍN thực sự.

                                                                                                                                                        Example
                                                                                                                                                        Selecting from Collections

                                                                                                                                                        Trong Java, nếu bạn muốn chọn một tập con các phần tử từ một Collection, bạn yêu cầu một Iterator. Sau đó, bạn sẽ lặp qua các phần tử, kiểm tra từng phần, có lẽ tích lũy các phần tử phù hợp vào một Collection mới.

                                                                                                                                                        Set employees = (some Set of Employee objects); Set lowPaidEmployees = new HashSet(); Iterator it = employees.iterator(); while (it.hasNext()) { Employee anEmployee = it.next(); if (anEmployee.salary() < 40000) lowPaidEmployees.add(anEmployee); } 

                                                                                                                                                        Về mặt khái niệm, tôi đã chọn một tập con của một tập hợp. Tôi cần gì với khái niệm bổ sung này, Iterator, và tất cả những phức tạp cơ học của nó? Trong Smalltalk, tôi sẽ gọi hoạt động "chọn" trên Collection, truyền vào phép thử như một tham số. Kết quả sẽ là một Collection mới chứa chỉ những phần tử đã vượt qua phép thử.

                                                                                                                                                        employees := (some Set of Employee objects). lowPaidEmployees := employees select: [:anEmployee | anEmployee salary < 40000]. 

                                                                                                                                                        Các Collection trong Smalltalk cung cấp nhiều CHỨC NĂNG khác tương tự trả về các Collection được phát sinh, có thể thuộc nhiều lớp cụ thể khác nhau. Các phép toán không được đóng kín, vì chúng nhận một "khối" (block) làm đối số. Nhưng khối là một kiểu thư viện cơ bản trong Smalltalk, vì vậy chúng không làm tăng thêm gánh nặng tư duy cho nhà phát triển. Bởi vì giá trị trả về phù hợp với người thực hiện, chúng có thể được kết nối với nhau, giống như một chuỗi bộ lọc. Chúng dễ viết và dễ đọc. Chúng không đưa ra các khái niệm thừa thãi không liên quan đến vấn đề chọn lựa các tập con.

                                                                                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                        Các mẫu được trình bày trong chương này minh họa một phong cách thiết kế chung và một cách tư duy về thiết kế. Làm cho phần mềm trở nên rõ ràng, có thể dự đoán và giao tiếp sẽ làm cho việc trừu tượng và đóng gói trở nên hiệu quả. Các mô hình có thể được phân tích để các đối tượng trở nên đơn giản trong việc sử dụng và hiểu nhưng vẫn có giao diện phong phú, cấp cao.

                                                                                                                                                        Những kỹ thuật này đòi hỏi kỹ năng thiết kế khá nâng cao để áp dụng và đôi khi ngay cả để viết một khách hàng. Tính hữu ích của THIẾT KẾ DỰA TRÊN MÔ HÌNH nhạy cảm với chất lượng của các quyết định thiết kế chi tiết và triển khai, và chỉ cần một vài lập trình viên bối rối là có thể làm chệch hướng dự án khỏi mục tiêu.

                                                                                                                                                        Điều đó nói lên rằng, đối với những đội ngũ sẵn sàng phát triển kỹ năng mô hình hóa và thiết kế của mình, những mẫu hình này và cách suy nghĩ mà chúng phản ánh tạo ra phần mềm mà các lập trình viên có thể làm việc và chỉnh sửa để tạo ra phần mềm phức tạp.


                                                                                                                                                          Declarative Design

                                                                                                                                                          CÁC KHẲNG ĐỊNH có thể dẫn đến những thiết kế tốt hơn rất nhiều, ngay cả với cách thử nghiệm khá không chính thức của chúng ta. Nhưng không thể có bất kỳ đảm bảo nào thực sự trong phần mềm viết tay. Chỉ để nêu ra một cách để lách qua CÁC KHẲNG ĐỊNH, mã có thể có những tác dụng phụ bổ sung không được loại trừ một cách cụ thể. Dù thiết kế của chúng ta có PHƯƠNG PHÁP-MÔ HÌNH như thế nào, chúng ta vẫn kết thúc việc viết quy trình để tạo ra hiệu ứng của các tương tác khái niệm. Và chúng ta dành rất nhiều thời gian để viết mã mẫu không thực sự mang lại ý nghĩa hoặc hành vi nào. Điều này gây mệt mỏi và dễ xảy ra lỗi, và phần lớn trong số đó làm mờ ý nghĩa của mô hình của chúng ta. (Một số ngôn ngữ thì tốt hơn những ngôn ngữ khác, nhưng tất cả đều yêu cầu chúng ta phải làm rất nhiều công việc nhọc nhằn.) CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH và các mẫu khác trong chương này giúp ích, nhưng chúng không bao giờ có thể mang lại cho các chương trình hướng đối tượng thông thường tính nghiêm ngặt chính thức.

                                                                                                                                                          Đây là một số động lực đằng sau thiết kế tuyên bố. Thuật ngữ này có nhiều ý nghĩa đối với nhiều người, nhưng thường nó chỉ đến một cách viết chương trình, hoặc một phần của chương trình, như một loại đặc tả có thể thực thi. Một mô tả rất chính xác về các thuộc tính thực sự điều khiển phần mềm. Trong các hình thức khác nhau, điều này có thể được thực hiện thông qua một cơ chế phản chiếu hoặc trong thời gian biên dịch thông qua việc tạo mã (tự động sản xuất mã thông thường, dựa trên khai báo). Cách tiếp cận này cho phép một nhà phát triển khác tiếp nhận khai báo một cách nghiêm túc. Đây là một cam kết tuyệt đối.

                                                                                                                                                          Tạo ra một chương trình chạy từ một tuyên bố về các thuộc tính mô hình là một loại "Chén Thánh" của THIẾT KẾ HƯỚNG MÔ HÌNH, nhưng trong thực tế nó cũng có những cạm bẫy. Ví dụ, đây chỉ là hai vấn đề cụ thể mà tôi đã gặp phải nhiều lần.

                                                                                                                                                          • Một ngôn ngữ khai báo không đủ diễn đạt để làm mọi thứ cần thiết, nhưng là một khuôn khổ khiến việc mở rộng phần mềm vượt ra ngoài phần tự động trở nên rất khó khăn.

                                                                                                                                                          • Kỹ thuật sinh mã làm hỏng chu trình lặp bằng cách kết hợp mã được tạo ra vào mã viết tay theo cách khiến việc tạo lại rất phá hủy.

                                                                                                                                                          Hệ quả không lường trước được của nhiều nỗ lực thiết kế khai báo là sự đơn giản hóa quá mức của mô hình và ứng dụng, khi các nhà phát triển, bị mắc kẹt trong những giới hạn của khuôn khổ, thực hiện việc sàng lọc thiết kế nhằm đưa ra một sản phẩm.

                                                                                                                                                          Lập trình dựa trên quy tắc với một động cơ suy diễn và một cơ sở quy tắc là một phương pháp tiềm năng khác cho thiết kế tuyên bố. Thật không may, những vấn đề tinh tế có thể làm suy yếu ý định này.

                                                                                                                                                          Mặc dù chương trình dựa trên quy tắc về nguyên tắc là tuyên bố, hầu hết các hệ thống đều có "các điều kiện kiểm soát" được thêm vào để cho phép tinh chỉnh hiệu suất. Mã kiểm soát này gây ra các tác động phụ, do đó hành vi không còn bị quy định hoàn toàn bởi các quy tắc đã khai báo. Việc thêm, xóa hoặc sắp xếp lại các quy tắc có thể gây ra những kết quả không mong đợi và không chính xác. Vì vậy, một lập trình viên logic phải cẩn thận để giữ cho tác động của mã được rõ ràng, giống như một lập trình viên đối tượng.

                                                                                                                                                          Nhiều phương pháp khai báo có thể bị sai lệch nếu các nhà phát triển bỏ qua chúng một cách cố ý hoặc vô tình. Điều này thường xảy ra khi hệ thống khó sử dụng hoặc quá cứng nhắc. Mọi người đều phải tuân theo các quy tắc của khung để nhận được lợi ích từ một chương trình khai báo.

                                                                                                                                                          Giá trị lớn nhất mà tôi đã thấy được mang lại là khi một framework có phạm vi hẹp tự động hóa một khía cạnh đặc biệt tẻ nhạt và dễ xảy ra lỗi trong thiết kế, chẳng hạn như sự bền vững và ánh xạ đối tượng-quan hệ. Những framework tốt nhất trong số này giải phóng các lập trình viên khỏi công việc nhàm chán trong khi vẫn để họ tự do hoàn toàn trong việc thiết kế.

                                                                                                                                                          Domain-Specific Languages

                                                                                                                                                          Một cách tiếp cận thú vị đôi khi mang tính khai báo là ngôn ngữ đặc thù theo miền. Trong phong cách này, mã lệnh của khách hàng được viết bằng một ngôn ngữ lập trình được thiết kế cho một mô hình cụ thể của một miền cụ thể. Ví dụ, một ngôn ngữ cho hệ thống vận chuyển có thể bao gồm các thuật ngữ như hàng hóa và lộ trình, cùng với cú pháp để liên kết chúng. Chương trình sau đó được biên dịch, thường thành một ngôn ngữ hướng đối tượng thông thường, nơi có một thư viện các lớp cung cấp các triển khai cho các thuật ngữ trong ngôn ngữ đó.

                                                                                                                                                          Trong một ngôn ngữ như vậy, các chương trình có thể rất biểu cảm và tạo ra sự kết nối mạnh mẽ với NGÔN NGỮ PHỔ BIẾN. Đây là một khái niệm thú vị, nhưng các ngôn ngữ chuyên biệt cho miền cũng có những hạn chế của chúng trong các cách tiếp cận mà tôi đã thấy dựa trên công nghệ hướng đối tượng.

                                                                                                                                                          Để tinh chỉnh mô hình, một nhà phát triển cần có khả năng sửa đổi ngôn ngữ. Điều này có thể liên quan đến việc sửa đổi các tuyên bố ngữ pháp và các tính năng diễn giải ngôn ngữ khác, cũng như sửa đổi các thư viện lớp nền. Tôi hoàn toàn ủng hộ việc học hỏi công nghệ tiên tiến và các khái niệm thiết kế, nhưng chúng ta phải đánh giá một cách tỉnh táo về kỹ năng của một đội ngũ cụ thể, cũng như kỹ năng có thể có của các đội ngũ bảo trì trong tương lai. Ngoài ra, có giá trị trong sự liền mạch của một ứng dụng và một mô hình được triển khai trong cùng một ngôn ngữ. Một nhược điểm khác là có thể rất khó khăn để tái cấu trúc mã khách hàng cho phù hợp với mô hình đã sửa đổi và ngôn ngữ cụ thể cho miền của nó. Tất nhiên, ai đó có thể nghĩ ra một giải pháp kỹ thuật cho các vấn đề tái cấu trúc.


                                                                                                                                                          From the Ground Up

                                                                                                                                                          Một hình thái khác có thể xử lý các ngôn ngữ miền cụ thể tốt hơn các đối tượng. Trong ngôn ngữ lập trình Scheme, một đại diện của "gia đình lập trình hàm", một cái gì đó rất tương tự là một phần của phong cách lập trình tiêu chuẩn, để tính biểu cảm của một ngôn ngữ miền cụ thể có thể được tạo ra mà không cần chia tách hệ thống.

                                                                                                                                                          Kỹ thuật này có thể hữu ích nhất cho những mô hình đã phát triển đến mức rất trưởng thành, có thể trong trường hợp mã client được viết bởi một nhóm khác. Thông thường, những thiết lập như vậy dẫn đến sự phân chia độc hại giữa những người xây dựng khung công nghệ cao và những người xây dựng ứng dụng không có kỹ năng kỹ thuật, nhưng không nhất thiết phải như vậy.

                                                                                                                                                          Trong ngôn ngữ lập trình Scheme, một điều rất tương tự là một phần của phong cách lập trình tiêu chuẩn, để sự biểu cảm của một ngôn ngữ lập trình chuyên dụng có thể được tạo ra mà không phân chia hệ thống.


                                                                                                                                                            A Declarative Style of Design

                                                                                                                                                            Khi thiết kế của bạn có CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH, CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ và CÁC KHẼO ĐỊNH, bạn đang tiến vào lãnh thổ khai báo. Nhiều lợi ích của thiết kế khai báo được đạt được khi bạn có các yếu tố có thể kết hợp với nhau, giao tiếp ý nghĩa của chúng, và có tác động đã được xác định hoặc rõ ràng, hoặc hoàn toàn không có tác động quan sát nào.

                                                                                                                                                            Một thiết kế linh hoạt có thể giúp mã khách hàng sử dụng phong cách thiết kế khai báo. Để minh họa, phần tiếp theo sẽ kết hợp một số mẫu trong chương này để làm cho SPECIFICATION trở nên linh hoạt và khai báo hơn.

                                                                                                                                                            Extending SPECIFICATIONS in a Declarative Style

                                                                                                                                                            Chương 9 đã đề cập đến khái niệm cơ bản về ĐẶC TẢ, vai trò mà nó có thể đảm nhận trong một chương trình, và một số hiểu biết về những gì liên quan đến việc triển khai. Bây giờ, hãy cùng xem qua một vài tính năng bổ sung có thể rất hữu ích trong một số tình huống với các quy tắc phức tạp.

                                                                                                                                                            "ĐẶC TÍNH là một sự thích nghi của một hình thức đã thiết lập, đó là mệnh đề. Các mệnh đề có những đặc tính hữu ích khác mà chúng ta có thể khai thác, một cách chọn lọc."

                                                                                                                                                            Combining SPECIFICATIONS Using Logical Operators

                                                                                                                                                            Khi sử dụng ĐẶC TÍNH, bạn nhanh chóng gặp phải những tình huống mà bạn muốn kết hợp chúng. Như đã đề cập trước đó, một ĐẶC TÍNH là một ví dụ về một tiêu đề, và các tiêu đề có thể được kết hợp và điều chỉnh bằng các phép toán "VÀ," "HOẶC," và "KHÔNG." Những phép toán logic này được đóng trong các tiêu đề, vì vậy sự kết hợp của các ĐẶC TÍNH sẽ thể hiện SỰ ĐÓNG CỬA CỦA CÁC PHÉP TOÁN.

                                                                                                                                                            Khi khả năng tổng quát quan trọng được xây dựng vào CÁC ĐẶC TÍNH, thì thật hữu ích để tạo ra một lớp trừu tượng hoặc giao diện có thể được sử dụng cho CÁC ĐẶC TÍNH của mọi loại. Điều này có nghĩa là nhập các tham số dưới dạng một lớp trừu tượng cấp cao nào đó.

                                                                                                                                                            public interface Specification { boolean isSatisfiedBy(Object candidate); } 

                                                                                                                                                            Sự trừu tượng này yêu cầu một điều khoản bảo vệ ở đầu phương thức, nhưng ngoài ra nó không ảnh hưởng đến chức năng. Ví dụ, Đặc tả Container (từ ví dụ trong Chương 9, trang 236) sẽ được sửa đổi theo cách này:

                                                                                                                                                            public class ContainerSpecification implements Specification { private ContainerFeature requiredFeature; public ContainerSpecification(ContainerFeature required) { requiredFeature = required; } boolean isSatisfiedBy(Object candidate){ if (!candidate instanceof Container) return false; return (Container)aContainer.getFeatures().contains(requiredFeature); } } 

                                                                                                                                                            Bây giờ, hãy mở rộng giao diện Specification bằng cách thêm ba hoạt động mới:

                                                                                                                                                            public interface Specification { boolean isSatisfiedBy(Object candidate); Specification and(Specification other); Specification or(Specification other); Specification not(); } 

                                                                                                                                                            Nhớ rằng một số yêu cầu về Container đã được cấu hình để yêu cầu Container có thông gió và một số khác yêu cầu Container được bọc thép. Một hóa chất vừa dễ bay hơi vừa dễ nổ sẽ, có lẽ, cần cả hai yêu cầu này. Dễ dàng thực hiện, bằng cách sử dụng các phương pháp mới.

                                                                                                                                                            Specification ventilated = new ContainerSpecification(VENTILATED); Specification armored = new ContainerSpecification(ARMORED); Specification both = ventilated.and(armored); 

                                                                                                                                                            Khai báo này định nghĩa một đối tượng Specification mới với các thuộc tính mong đợi. Sự kết hợp này sẽ đòi hỏi một Đặc tả Container phức tạp hơn, và vẫn sẽ chỉ có mục đích đặc biệt.

                                                                                                                                                            Giả sử chúng ta có nhiều loại Container thông gió khác nhau. Đối với một số mặt hàng, loại container mà chúng được đóng gói có thể không quan trọng. Chúng có thể được đặt vào cả hai loại.

                                                                                                                                                            Specification ventilatedType1 = new ContainerSpecification(VENTILATED_TYPE_1); Specification ventilatedType2 = new ContainerSpecification(VENTILATED_TYPE_2); Specification either = ventilatedType1.or(ventilatedType2); 

                                                                                                                                                            Nếu việc lưu trữ cát trong các container chuyên dụng được coi là lãng phí, chúng ta có thể cấm việc đó bằng cách XÁC ĐỊNH một container "rẻ tiền" không có tính năng đặc biệt nào.

                                                                                                                                                            Specification cheap = (ventilated.not()).and(armored.not()); 

                                                                                                                                                            Ràng buộc này sẽ ngăn chặn một số hành vi không tối ưu của bộ đóng gói kho prototype được thảo luận trong Chương 9.

                                                                                                                                                            Khả năng xây dựng các đặc tả phức tạp từ những yếu tố đơn giản làm tăng tính biểu đạt của mã. Các sự kết hợp được viết theo phong cách khai báo.

                                                                                                                                                            Tùy thuộc vào cách IMPLEMENTATIONS được thực hiện, các toán tử này có thể dễ dàng hoặc khó khăn để cung cấp. Dưới đây là một ví dụ rất đơn giản, có thể không hiệu quả trong một số tình huống và khá thực tiễn trong những trường hợp khác. Nó được đưa ra như một ví dụ giải thích. Giống như bất kỳ mẫu nào, có nhiều cách để triển khai nó.

                                                                                                                                                            public abstract class AbstractSpecification implements Specification { public Specification and(Specification other) { return new AndSpecification(this, other); } public Specification or(Specification other) { return new OrSpecification(this, other); } public Specification not() { return new NotSpecification(this); } } public class AndSpecification extends AbstractSpecification { Specification one; Specification other; public AndSpecification(Specification x, Specification y) { one = x; other = y; } public boolean isSatisfiedBy(Object candidate) { return one.isSatisfiedBy(candidate) && other.isSatisfiedBy(candidate); } } public class OrSpecification extends AbstractSpecification { Specification one; Specification other; public OrSpecification(Specification x, Specification y) { one = x; other = y; } public boolean isSatisfiedBy(Object candidate) { return one.isSatisfiedBy(candidate) || other.isSatisfiedBy(candidate); } } public class NotSpecification extends AbstractSpecification { Specification wrapped; public NotSpecification(Specification x) { wrapped = x; } public boolean isSatisfiedBy(Object candidate) { return !wrapped.isSatisfiedBy(candidate); } } 
                                                                                                                                                            Figure 10.14. COMPOSITE design of SPECIFICATION

                                                                                                                                                            graphics/10fig14.gif

                                                                                                                                                            Mã này được viết để dễ đọc nhất có thể trong sách. Như tôi đã nói, có thể có những tình huống mà điều này không hiệu quả. Tuy nhiên, có các tùy chọn triển khai khác có thể giảm thiểu số lượng đối tượng hoặc tăng tốc độ, hoặc có thể tương thích với các công nghệ đặc thù có trong một số dự án. Điều quan trọng là một mô hình nắm bắt các khái niệm chính của miền, cùng với một triển khai trung thành với mô hình đó. Điều này để lại nhiều không gian để giải quyết các vấn đề về hiệu suất.

                                                                                                                                                            Ngoài ra, sự tổng quát đầy đủ này không cần thiết trong nhiều trường hợp. Cụ thể, AND thường được sử dụng nhiều hơn các phép toán khác, và nó cũng thường tạo ra ít độ phức tạp trong việc triển khai hơn. Đừng ngần ngại thực hiện chỉ AND, nếu đó là tất cả những gì bạn cần.

                                                                                                                                                            Ngay từ chương 2, trong đoạn hội thoại mẫu ở trang 30, các nhà phát triển rõ ràng đã không triển khai hành vi "được thỏa mãn bởi" trong ĐẶC TÍNH của họ. Đến thời điểm đó, ĐẶC TÍNH chỉ được sử dụng để xây dựng theo yêu cầu. Tuy nhiên, sự trừu tượng vẫn được giữ nguyên, và việc thêm chức năng là tương đối dễ dàng. Sử dụng một mẫu không có nghĩa là xây dựng các tính năng bạn không cần. Chúng có thể được thêm vào sau, miễn là các khái niệm không bị rối loạn.

                                                                                                                                                            Example
                                                                                                                                                            One Alternative Implementation of COMPOSITE SPECIFICATION

                                                                                                                                                            Một số môi trường thực thi không tiếp nhận tốt các đối tượng rất chi tiết. Tôi đã từng làm việc trong một dự án với một cơ sở dữ liệu đối tượng, nơi nhất định phải gán một ID cho mỗi đối tượng và sau đó theo dõi nó. Mỗi đối tượng đều có nhiều chi phí phụ về không gian bộ nhớ và hiệu suất, và tổng không gian địa chỉ là một yếu tố hạn chế. Tôi đã sử dụng CÁC ĐẶC TÍNH tại một số điểm quan trọng trong thiết kế miền, điều này tôi nghĩ là một quyết định đúng đắn. Nhưng tôi đã sử dụng một phiên bản hơi phức tạp hơn của triển khai được mô tả trong chương này, điều đó chắc chắn là một sai lầm. Nó đã dẫn đến hàng triệu đối tượng rất chi tiết, góp phần làm hệ thống bị chậm lại.

                                                                                                                                                            Dưới đây là một ví dụ về một triển khai thay thế mã hóa SPECIFICATION kết hợp dưới dạng chuỗi hoặc mảng mã hóa biểu thức logic, được diễn giải tại thời gian chạy.

                                                                                                                                                            (Đừng lo lắng nếu bạn không thấy cách nào để triển khai điều này. Điều quan trọng là nhận ra rằng có nhiều cách để triển khai một ĐẶC TẢ với các phép toán logic, và nếu cách đơn giản này không thực tế trong tình huống của bạn, bạn có các tùy chọn.)

                                                                                                                                                            Nội dung thông số cho "Container Rẻ"

                                                                                                                                                            Top in Vietnamese is "Đỉnh".

                                                                                                                                                            AndSpecificationOperator (FLY WEIGHT) - Toán tử đặc tả "And" (Cân nặng nhẹ)

                                                                                                                                                            KhôngThỏaThuậnToánTử (CÂN NẶNG BAY)

                                                                                                                                                            Bọc thép

                                                                                                                                                            KhôngPhépToánKhôngĐặcTrưng

                                                                                                                                                            Thông gió

                                                                                                                                                            Khi bạn muốn kiểm tra một ứng viên, bạn phải giải thích cấu trúc này, điều này có thể được thực hiện bằng cách loại bỏ từng phần tử, sau đó đánh giá nó hoặc loại bỏ phần tử tiếp theo theo yêu cầu của toán tử. Bạn sẽ kết thúc với điều này:

                                                                                                                                                            and(not(armored), not(ventilated)) 

                                                                                                                                                            Thiết kế này có ưu điểm (+) và nhược điểm (–):

                                                                                                                                                            + Số lượng đối tượng thấp

                                                                                                                                                            + Sử dụng bộ nhớ hiệu quả

                                                                                                                                                            Cần những nhà phát triển tinh vi hơn.

                                                                                                                                                            Bạn cần tìm một cách triển khai với các sự đánh đổi phù hợp với hoàn cảnh của bạn. Cùng một mẫu và mô hình có thể nằm dưới nhiều triển khai rất khác nhau.

                                                                                                                                                            Subsumption

                                                                                                                                                            Tính năng cuối cùng này thường không cần thiết và có thể khó triển khai, nhưng thỉnh thoảng nó giải quyết được một vấn đề thực sự khó khăn. Nó cũng làm sáng tỏ nghĩa của một ĐẶC TẢ.

                                                                                                                                                            Xem xét lại nhân viên đóng gói kho hóa chất từ ví dụ trên trang 235. Nhớ rằng mỗi Hóa chất đều có Thông số Container, và Dịch vụ Đóng gói đảm bảo rằng tất cả những điều này sẽ được đáp ứng khi các Thùng được gán cho các Container. Mọi thứ đều ổn... cho đến khi ai đó thay đổi quy định.

                                                                                                                                                            Mỗi vài tháng, một bộ quy tắc mới được ban hành, và người dùng của chúng tôi muốn có khả năng tạo ra một danh sách các loại hóa chất hiện có yêu cầu nghiêm ngặt hơn.

                                                                                                                                                            Tất nhiên, chúng tôi có thể đưa ra một câu trả lời một phần (và một câu trả lời mà người dùng có lẽ cũng muốn) bằng cách chạy một bài kiểm tra xác nhận cho mỗi thùng trong kho, với các ĐẶC TÍNH mới, và tìm ra tất cả những thùng không còn đáp ứng tiêu chuẩn nữa. Điều này sẽ cho người dùng biết những thùng nào trong kho hiện có mà họ cần phải di chuyển.

                                                                                                                                                            Nhưng điều họ yêu cầu là một danh sách các hóa chất có quy định xử lý trở nên nghiêm ngặt hơn. Có thể hiện tại không có chất nào trong nhà, hoặc có thể chúng chỉ tình cờ được đóng gói trong một container nghiêm ngặt hơn. Trong cả hai trường hợp, báo cáo được mô tả chỉ ra sẽ không liệt kê chúng.

                                                                                                                                                            Hãy giới thiệu một phép toán mới để so sánh trực tiếp hai THÔNG SỐ.

                                                                                                                                                            boolean subsumes(Specification other); 

                                                                                                                                                            Một SPEC nghiêm ngặt hơn bao gồm một SPEC ít nghiêm ngặt hơn. Nó có thể thay thế nó mà không cần bỏ qua bất kỳ yêu cầu nào trước đó.

                                                                                                                                                            Figure 10.15. The SPECIFICATION for a gasoline container has been tightened.

                                                                                                                                                            graphics/10fig15.gif

                                                                                                                                                            Trong ngôn ngữ của ĐẶC TÍNH, chúng ta có thể nói rằng đặc tính mới bao hàm đặc tính cũ, vì bất kỳ ứng viên nào thỏa mãn đặc tính mới cũng sẽ thỏa mãn đặc tính cũ.

                                                                                                                                                            Nếu mỗi THÔNG SỐ này được xem như một tiên đề, thì sự phủ định tương đương với hàm ý logic. Sử dụng ký hiệu thông thường, AB có nghĩa là lời tuyên bố A hàm ý lời tuyên bố B, vì vậy nếu A đúng, B cũng đúng.

                                                                                                                                                            Hãy áp dụng logic này cho nhu cầu khớp thùng chứa của chúng ta. Khi một Đặc tả (SPECIFICATION) đang được thay đổi, chúng tôi muốn biết liệu Đặc tả mới đề xuất (SPEC) có đáp ứng tất cả các điều kiện của Đặc tả cũ hay không.

                                                                                                                                                            Thông số mới Thông số cũ

                                                                                                                                                            Có nghĩa là, nếu thông số mới là đúng, thì thông số cũ cũng đúng. Chứng minh một suy luận logic theo cách tổng quát là rất khó, nhưng các trường hợp đặc biệt có thể dễ hơn. Ví dụ, các THÔNG SỐ tham số hóa cụ thể có thể xác định quy tắc bao hàm riêng của chúng.

                                                                                                                                                            public class MinimumAgeSpecification { int threshold; public boolean isSatisfiedBy(Person candidate) { return candidate.getAge() >= threshold; } public boolean subsumes(MinimumAgeSpecification other) { return threshold >= other.getThreshold(); } } 

                                                                                                                                                            Một bài kiểm tra JUnit có thể chứa điều này:

                                                                                                                                                            drivingAge = new MinimumAgeSpecification(16); votingAge = new MinimumAgeSpecification(18); assertTrue(votingAge.subsumes(drivingAge)); 

                                                                                                                                                            Một trường hợp đặc biệt thực tiễn khác, phù hợp để giải quyết vấn đề Đặc tả Container, là một giao diện ĐẶC TẢ kết hợp sự kế thừa với toán tử logic duy nhất AND.

                                                                                                                                                            public interface Specification { boolean isSatisfiedBy(Object candidate); Specification and(Specification other); boolean subsumes(Specification other); } 

                                                                                                                                                            Chứng minh mối suy diễn bằng cách chỉ sử dụng phép AND là đơn giản.

                                                                                                                                                            A VÀ B A

                                                                                                                                                            hoặc, trong một trường hợp phức tạp hơn:

                                                                                                                                                            A VÀ B VÀ C A VÀ B

                                                                                                                                                            Vậy nếu Đặc tả Tổ hợp có khả năng thu thập tất cả các Đặc tả lá được "AND" lại với nhau, thì tất cả những gì chúng ta cần làm là kiểm tra rằng Đặc tả bao hàm có tất cả các lá mà Đặc tả bị bao hàm có, và có thể là một số lá bổ sung nữa - các lá của nó là một tập hợp bao hàm của tập hợp các lá của Đặc tả khác.

                                                                                                                                                            public boolean subsumes(Specification other) { if (other instanceof CompositeSpecification) { Collection otherLeaves = (CompositeSpecification) other.leafSpecifications(); Iterator it = otherLeaves.iterator(); while (it.hasNext()) { if (!leafSpecifications().contains(it.next())) return false; } } else { if (!leafSpecifications().contains(other)) return false; } return true; } 

                                                                                                                                                            Tương tác này có thể được cải thiện để so sánh các THÔNG SỐ lá được tham số hóa được lựa chọn cẩn thận và một số phức tạp khác. Đáng tiếc, khi bao gồm OR và NOT, những chứng minh này trở nên phức tạp hơn nhiều. Trong hầu hết các tình huống, tốt nhất là nên tránh sự phức tạp như vậy bằng cách đưa ra sự lựa chọn, hoặc từ bỏ một số toán tử hoặc từ bỏ sự bao hàm. Nếu cả hai đều cần thiết, hãy xem xét cẩn thận xem lợi ích có đủ lớn để biện minh cho khó khăn hay không.

                                                                                                                                                            Socrates về CÁC ĐẶC TÍNH KỸ THUẬT

                                                                                                                                                            Tất cả đàn ông đều phải chết.

                                                                                                                                                            Specification manSpec = new ManSpecification(); Specification mortalSpec = new MortalSpecification(); assert manSpec.subsumes(mortalSpec); 

                                                                                                                                                            Socrates là một người.

                                                                                                                                                            Man socrates = new Man(); assert manSpec.isSatisfiedBy(socrates); 

                                                                                                                                                            Vì vậy, Socrates là phàm nhân.

                                                                                                                                                            assert mortalSpec.isSatisfiedBy(socrates); 


                                                                                                                                                              Angles of Attack

                                                                                                                                                              Chương này đã trình bày nhiều kỹ thuật để làm rõ mục đích của mã, làm cho hậu quả của việc sử dụng nó trở nên rõ ràng, và tách rời các yếu tố trong mô hình. Tuy nhiên, kiểu thiết kế này rất khó khăn. Bạn không thể chỉ nhìn vào một hệ thống khổng lồ và nói, "Hãy làm cho nó linh hoạt." Bạn phải chọn những mục tiêu cụ thể. Dưới đây là một vài cách tiếp cận tổng quát, tiếp theo là một ví dụ mở rộng cho thấy cách các mẫu được kết hợp và sử dụng để giải quyết một thiết kế lớn hơn.

                                                                                                                                                              Carve Off Subdomains

                                                                                                                                                              Bạn không thể giải quyết toàn bộ thiết kế cùng một lúc. Hãy từ từ giải quyết nó. Một số khía cạnh của hệ thống sẽ gợi ý cho bạn các phương pháp, và chúng có thể được tách ra và làm việc riêng biệt. Bạn có thể thấy một phần của mô hình mà có thể được xem như toán học chuyên ngành; hãy tách nó ra. Ứng dụng của bạn thực thi các quy tắc phức tạp hạn chế việc thay đổi trạng thái; hãy tách điều này ra thành một mô hình riêng biệt hoặc một khung đơn giản cho phép bạn tuyên bố các quy tắc. Với mỗi bước như vậy, không chỉ là mô-đun mới sạch sẽ mà phần còn lại cũng nhỏ hơn và rõ ràng hơn. Phần còn lại được viết theo phong cách khai báo, một tuyên bố theo kiểu toán học chuyên ngành hoặc khung xác thực, hoặc bất kỳ hình thức nào mà miền con chiếm giữ.

                                                                                                                                                              Thật hơn là tạo ra một tác động lớn ở một lĩnh vực, làm cho một phần của thiết kế thực sự linh hoạt, hơn là phân tán nỗ lực của bạn. Chương 15 thảo luận sâu hơn về cách lựa chọn và quản lý các miền con.

                                                                                                                                                              Draw on Established Formalisms, When You Can

                                                                                                                                                              Việc xây dựng một khung khái niệm chặt chẽ từ con số không là điều không thể thực hiện hàng ngày. Đôi khi, bạn khám phá và hoàn thiện một trong số này trong quá trình diễn ra dự án. Nhưng bạn thường có thể sử dụng và điều chỉnh các hệ thống khái niệm đã được thiết lập lâu đời trong lĩnh vực của bạn hoặc các lĩnh vực khác, một số trong số đó đã được tinh luyện và chắt lọc qua nhiều thế kỷ. Nhiều ứng dụng kinh doanh liên quan đến kế toán, chẳng hạn. Kế toán xác định một tập hợp CÁC THỰC THỂ và quy tắc phát triển tốt, cho phép dễ dàng điều chỉnh theo một mô hình sâu và thiết kế linh hoạt.

                                                                                                                                                              Có nhiều khung khái niệm được chính thức hóa như vậy, nhưng sở thích cá nhân của tôi là toán học. Thật ngạc nhiên là nó có thể hữu ích như thế nào khi rút ra một chút biến tấu từ phép cộng cơ bản. Nhiều lĩnh vực đều có ít nhiều liên quan đến toán học. Hãy tìm kiếm nó. Khám phá nó. Toán học chuyên ngành thì rõ ràng, có thể kết hợp theo các quy tắc rõ ràng, và mọi người thấy dễ hiểu. Một ví dụ từ quá khứ của tôi là "Toán Chia sẻ," sẽ kết thúc chương này.

                                                                                                                                                              Example
                                                                                                                                                              Integrating the Patterns: Shares Math

                                                                                                                                                              Chương 8 đã kể về câu chuyện của một bước đột phá mô hình trong một dự án xây dựng hệ thống cho vay đồng syndicate. Bây giờ, ví dụ này sẽ đi vào chi tiết, tập trung vào chỉ một tính năng của một thiết kế tương tự như trong dự án đó.

                                                                                                                                                              Một yêu cầu của ứng dụng đó là khi người vay thực hiện một khoản thanh toán gốc, tiền sẽ được phân chia theo tỷ lệ mặc định dựa trên phần của các nhà cho vay trong khoản vay.

                                                                                                                                                              Initial Design for Payment Distribution

                                                                                                                                                              Khi chúng ta cải tiến mã này, nó sẽ dễ hiểu hơn, vì vậy đừng bận tâm về phiên bản này.

                                                                                                                                                              Figure 10.16.

                                                                                                                                                              graphics/10fig16.gif

                                                                                                                                                              public class Loan { private Map shares; //Accessors, constructors, and very simple methods are excluded public Map distributePrincipalPayment(double paymentAmount) { Map paymentShares = new HashMap(); Map loanShares = getShares(); double total = getAmount(); Iterator it = loanShares.keySet().iterator(); while(it.hasNext()) { Object owner = it.next(); double initialLoanShareAmount = getShareAmount(owner); double paymentShareAmount = initialLoanShareAmount / total * paymentAmount; Share paymentShare = new Share(owner, paymentShareAmount); paymentShares.put(owner, paymentShare); double newLoanShareAmount = initialLoanShareAmount - paymentShareAmount; Share newLoanShare = new Share(owner, newLoanShareAmount); loanShares.put(owner, newLoanShare); } return paymentShares; } public double getAmount() { Map loanShares = getShares(); double total = 0.0; Iterator it = loanShares.keySet().iterator(); while(it.hasNext()) { Share loanShare = (Share) loanShares.get(it.next()); total = total + loanShare.getAmount(); } return total; } } 
                                                                                                                                                              Separating Commands and SIDE-EFFECT-FREE FUNCTIONS

                                                                                                                                                              Thiết kế này đã có các GIAO DIỆN TIẾT LỘ Ý ĐỊNH. Nhưng phương thức distributePaymentPrincipal() thực hiện một điều nguy hiểm: Nó tính toán các phần để phân phối và cũng sửa đổi Khoản vay. Hãy cải tiến để tách biệt truy vấn khỏi sửa đổi.

                                                                                                                                                              Figure 10.17.

                                                                                                                                                              graphics/10fig17.gif

                                                                                                                                                              public void applyPrincipalPaymentShares(Map paymentShares) { Map loanShares = getShares(); Iterator it = paymentShares.keySet().iterator(); while(it.hasNext()) { Object lender = it.next(); Share paymentShare = (Share) paymentShares.get(lender); Share loanShare = (Share) loanShares.get(lender); double newLoanShareAmount = loanShare.getAmount() - paymentShare.getAmount(); Share newLoanShare = new Share(lender, newLoanShareAmount); loanShares.put(lender, newLoanShare); } } public Map calculatePrincipalPaymentShares(double paymentAmount) { Map paymentShares = new HashMap(); Map loanShares = getShares(); double total = getAmount(); Iterator it = loanShares.keySet().iterator(); while(it.hasNext()) { Object lender = it.next(); Share loanShare = (Share) loanShares.get(lender); double paymentShareAmount = loanShare.getAmount() / total * paymentAmount; Share paymentShare = new Share(lender, paymentShareAmount); paymentShares.put(lender, paymentShare); } return paymentShares; } 

                                                                                                                                                              Mã khách hàng bây giờ trông như thế này:

                                                                                                                                                              Map distribution = aLoan.calculatePrincipalPaymentShares(paymentAmount); aLoan.applyPrincipalPaymentShares(distribution); 

                                                                                                                                                              Không tệ lắm. Các HÀM đã đóng gói nhiều phức tạp ẩn sau CÁC GIAO DIỆN TIẾT LỘ Ý ĐỊNH. Nhưng mã bắt đầu trở nên nhiều hơn khi chúng ta thêm applyDrawdown(), calculateFeePaymentShares(), và những cái khác. Mỗi lần mở rộng làm phức tạp mã và nặng nề hơn. Đây có thể là một điểm mà độ phân granularity quá thô. Cách tiếp cận thông thường sẽ là phân chia các phương pháp tính toán thành các tiểu trình. Điều đó có thể là một bước tốt trên con đường đi, nhưng cuối cùng chúng ta muốn thấy các ranh giới khái niệm cơ bản và làm sâu sắc thêm mô hình. Các yếu tố của một thiết kế với độ phân granularity như vậy có thể được kết hợp để tạo ra các biến thể cần thiết.

                                                                                                                                                              Making an Implicit Concept Explicit

                                                                                                                                                              Hiện tại đã có đủ điểm để bắt đầu khám phá mô hình mới đó. Các đối tượng Share trong triển khai này là thụ động và chúng đang được xử lý theo những cách phức tạp, cấp thấp. Điều này xảy ra vì hầu hết các quy tắc và phép tính về cổ phiếu không áp dụng cho cổ phiếu đơn lẻ, mà cho các nhóm cổ phiếu. Có một khái niệm bị thiếu: cổ phiếu có mối liên hệ với nhau như những phần cấu thành một tổng thể. Việc làm rõ khái niệm này sẽ cho phép chúng ta diễn đạt các quy tắc và phép tính đó ngắn gọn hơn.

                                                                                                                                                              Figure 10.18.

                                                                                                                                                              graphics/10fig18.gif

                                                                                                                                                              Bánh chia đại diện cho tổng phân phối của một khoản vay cụ thể. Nó là một THỰC THỂ có danh tính địa phương trong TỔNG HỢP của khoản vay. Các tính toán phân phối thực tế có thể được ủy thác cho Bánh chia.

                                                                                                                                                              Figure 10.19.

                                                                                                                                                              graphics/10fig19.gif

                                                                                                                                                              public class Loan { private SharePie shares; //Accessors, constructors, and straightforward methods //are omitted public Map calculatePrincipalPaymentDistribution( double paymentAmount) { return getShares().prorated(paymentAmount); } public void applyPrincipalPayment(Map paymentShares) { shares.decrease(paymentShares); } } 

                                                                                                                                                              Khoản vay được đơn giản hóa, và các phép tính về cổ phần được tập trung trong một ĐỐI TƯỢNG GIÁ TRỊ tập trung vào trách nhiệm đó. Tuy nhiên, các phép tính vẫn chưa thực sự trở nên đa năng hơn hoặc dễ sử dụng hơn.

                                                                                                                                                              Share Pie Becomes a VALUE OBJECT: Cascade of Insights

                                                                                                                                                              Thường thì kinh nghiệm thực tiễn trong việc triển khai một thiết kế mới sẽ kích thích một cái nhìn mới về chính mô hình đó. Trong trường hợp này, sự kết nối chặt chẽ giữa Loan và Share Pie dường như đang làm mờ đi mối quan hệ giữa Share Pie và Shares. Sẽ ra sao nếu chúng ta biến Share Pie thành một ĐỐI TƯỢNG GIÁ TRỊ?

                                                                                                                                                              Điều này có nghĩa là việc tăng (Tăng) và giảm (Giảm) sẽ không được phép, vì Bánh Cổ phần phải là bất biến. Để thay đổi giá trị của Bánh Cổ phần, toàn bộ Bánh phải được thay thế. Vì vậy, bạn có thể có các thao tác như thêmCổ phần (Map) mà sẽ trả về một Bánh Cổ phần mới, lớn hơn.

                                                                                                                                                              Hãy đi đến việc KẾT THÚC HOẠT ĐỘNG. Thay vì "tăng" một Miếng Chia Cổ Phiếu hoặc thêm Cổ Phiếu vào đó, chỉ cần cộng hai Miếng Chia Cổ Phiếu lại với nhau: kết quả là Miếng Chia Cổ Phiếu lớn hơn mới.

                                                                                                                                                              Chúng ta có thể đóng một phần hoạt động prorate() trên Share Pie chỉ bằng cách thay đổi kiểu trả về. Đổi tên nó thành prorated() nhấn mạnh sự thiếu tác dụng phụ của nó. "Toán học Chia" bắt đầu hình thành, ban đầu với bốn phép toán.

                                                                                                                                                              Figure 10.20.

                                                                                                                                                              graphics/10fig20.gif

                                                                                                                                                              Chúng ta có thể đưa ra một số KHAI BÁO được định nghĩa rõ ràng về các ĐỐI TƯỢNG GIÁ TRỊ mới của chúng ta, các chiếc Bánh Chia Sẻ. Mỗi phương thức đều có ý nghĩa nhất định.

                                                                                                                                                              [View full width]
                                                                                                                                                              public class SharePie { private Map shares = new HashMap(); //Accessors and other straightforward methods are omitted public double getAmount() { double total = 0.0; Iterator it = shares.keySet().iterator(); while(it.hasNext()) { The whole is equal to the sum of its parts. Share loanShare = getShare(it.next()); total = total + loanShare.getAmount(); } return total; } public SharePie minus(SharePie otherShares) { SharePie result = new SharePie(); Set owners = new HashSet(); owners.addAll(getOwners()); owners.addAll(otherShares.getOwners()); The difference between two Pies is the graphics/ccc.gif difference between each owner's share. Iterator it = owners.iterator(); while(it.hasNext()) { Object owner = it.next(); double resultShareAmount = getShareAmount(owner) – otherShares.getShareAmount(owner); result.add(owner, resultShareAmount); } return result; } public SharePie plus(SharePie otherShares) { The combination of two Pies is the graphics/ccc.gif combination of each owner's share. //Similar to implementation of minus() } public SharePie prorated(double amountToProrate) { SharePie proration = new SharePie(); double basis = getAmount(); An amount can be divided proportionately among all graphics/ccc.gif shareholders. Iterator it = shares.keySet().iterator(); while(it.hasNext()) { Object owner = it.next(); Share share = getShare(owner); double proratedShareAmount = share.getAmount() / basis * amountToProrate; proration.add(owner, proratedShareAmount); } return proration; } } 
                                                                                                                                                              The Suppleness of the New Design

                                                                                                                                                              Tại thời điểm này, các phương pháp trong lớp Loan quan trọng có thể đơn giản như thế này:

                                                                                                                                                              public class Loan { private SharePie shares; //Accessors, constructors, and straightforward methods //are omitted public SharePie calculatePrincipalPaymentDistribution( double paymentAmount) { return shares.prorated(paymentAmount); } public void applyPrincipalPayment(SharePie paymentShares) { setShares(shares.minus(paymentShares)); } 

                                                                                                                                                              Mỗi phương pháp ngắn gọn trong số này đều nêu rõ ý nghĩa của nó. Việc áp dụng một khoản thanh toán gốc có nghĩa là bạn trừ khoản thanh toán khỏi khoản vay, theo từng phần. Việc phân bổ một khoản thanh toán gốc được thực hiện bằng cách chia số tiền theo tỷ lệ giữa các cổ đông. Thiết kế của Bánh Cổ Phiếu đã cho phép chúng tôi sử dụng một phong cách tuyên bố trong mã Khoản Vay, tạo ra mã bắt đầu đọc như một định nghĩa khái niệm về giao dịch kinh doanh, thay vì chỉ là một phép tính.

                                                                                                                                                              Các loại giao dịch khác (quá phức tạp để liệt kê trước) giờ đây có thể được khai báo một cách dễ dàng. Ví dụ, các khoản vay được phân chia giữa các nhà cho vay dựa trên tỷ lệ sở hữu của họ đối với Tài sản. Khoản vay mới được thêm vào số dư của khoản vay hiện tại. Trong ngôn ngữ miền mới của chúng tôi:

                                                                                                                                                              public class Facility { private SharePie shares; . . . public SharePie calculateDrawdownDefaultDistribution( double drawdownAmount) { return shares.prorated(drawdownAmount); } } public class Loan { . . . public void applyDrawdown(SharePie drawdownShares) { setShares(shares.plus(drawdownShares)); } } 

                                                                                                                                                              Để xem sự lệch lạc của mỗi nhà cho vay so với đóng góp đã thoả thuận, hãy lấy phân phối lý thuyết của số tiền vay còn lại và trừ nó đi từ các phần thực tế của khoản vay.

                                                                                                                                                              SharePie originalAgreement = aFacility.getShares().prorated(aLoan.getAmount()); SharePie actual = aLoan.getShares(); SharePie deviation = actual.minus(originalAgreement); 

                                                                                                                                                              Một số đặc điểm của thiết kế Share Pie giúp cho việc tái kết hợp và giao tiếp trong mã trở nên dễ dàng.

                                                                                                                                                              • Logic phức tạp được bao gồm trong các ĐỐI TƯỢNG GIÁ TRỊ chuyên biệt với các hàm KHÔNG CÓ TÁC ĐỘNG PHỤ. Hầu hết logic phức tạp đã được bao gồm trong những đối tượng bất biến này. Bởi vì Bánh Chia là ĐỐI TƯỢNG GIÁ TRỊ, các phép toán toán học có thể tạo ra các thể hiện mới, mà chúng tôi có thể sử dụng tự do để thay thế các thể hiện lỗi thời.

                                                                                                                                                                Không có phương pháp nào của Share Pie gây ra bất kỳ thay đổi nào cho bất kỳ đối tượng nào hiện có. Điều này cho phép chúng ta sử dụng plus(), minus(), và pro-rated() một cách tự do trong các phép tính trung gian, kết hợp chúng lại với nhau, mong đợi chúng thực hiện những gì mà tên của chúng gợi ý, và không gì hơn. Nó cũng cho phép chúng ta xây dựng các tính năng phân tích dựa trên cùng các phương pháp này. (Trước đây, chúng chỉ có thể được gọi khi có một phân phối thực tế xảy ra, vì dữ liệu sẽ thay đổi sau mỗi lần gọi.)

                                                                                                                                                              • Các hoạt động sửa đổi trạng thái là đơn giản và được đặc trưng bằng các KHẲNG ĐỊNH. Các trừu tượng cấp cao của Toán Chia cho phép các bất biến của giao dịch được viết một cách ngắn gọn theo phong cách tuyên bố. Ví dụ, độ lệch là số bánh thực tế trừ đi số tiền Vay được phân bổ dựa trên Bánh Chia của Cơ sở.

                                                                                                                                                              • Các khái niệm mô hình được tách biệt; các hoạt động liên kết với tối thiểu các loại khác. Một số phương thức trên Share Pie thể hiện ĐÓNG CÁC HOẠT ĐỘNG (các phương thức để thêm hoặc trừ nằm trong Share Pies). Những phương thức khác nhận các giá trị đơn giản làm tham số hoặc trả về; chúng không đóng, nhưng chúng thêm rất ít vào khối lượng khái niệm. Share Pie tương tác chặt chẽ chỉ với một lớp khác, Share. Do đó, Share Pie là tự chứa, dễ hiểu, dễ kiểm tra và dễ kết hợp để tạo thành các giao dịch tuyên bố. Những đặc tính này được kế thừa từ hình thức toán học.

                                                                                                                                                              • Ngữ pháp quen thuộc làm cho giao thức dễ hiểu. Một giao thức hoàn toàn độc đáo để thao tác với cổ phiếu có thể đã được chế tạo dựa trên thuật ngữ tài chính. Về nguyên tắc, nó có thể đã được làm linh hoạt. Nhưng nó sẽ có hai nhược điểm. Thứ nhất, nó sẽ phải được phát minh ra, một nhiệm vụ khó khăn và không chắc chắn. Thứ hai, mỗi người liên quan đến nó sẽ phải học hỏi. Những người thấy Cổ phiếu Toán học nhận ra một hệ thống mà họ đã biết, và vì thiết kế đã được giữ nhất quán với các quy tắc của số học, những người đó không bị hiểu lầm.

                                                                                                                                                              Rút ra phần của vấn đề tương ứng với hình thức toán học, chúng tôi đã đạt được một thiết kế linh hoạt cho Cổ phiếu mà tinh chế hơn nữa các phương pháp Vay và Cơ sở. (Xem Chương 15 để thảo luận về LĨNH VỰC CỐT LÕI.)

                                                                                                                                                              Thiết kế linh hoạt có ảnh hưởng sâu sắc đến khả năng của phần mềm trong việc xử lý sự thay đổi và phức tạp. Như những ví dụ trong chương này đã cho thấy, nó thường phụ thuộc vào các quyết định mô hình hóa và thiết kế rất chi tiết. Ảnh hưởng có thể vượt ra ngoài một vấn đề mô hình hóa và thiết kế cụ thể. Chương 15 sẽ thảo luận về giá trị chiến lược của thiết kế linh hoạt như là một trong những công cụ để tinh giản mô hình miền nhằm làm cho các dự án lớn và phức tạp dễ quản lý hơn.


                                                                                                                                                                Chapter Eleven. Applying Analysis Patterns

                                                                                                                                                                Các mô hình sâu và thiết kế linh hoạt không dễ dàng có được. Tiến bộ đến từ việc học hỏi nhiều về lĩnh vực, nói chuyện nhiều và thử nghiệm nhiều. Tuy nhiên, đôi khi, chúng ta có thể có lợi thế.

                                                                                                                                                                Khi một nhà phát triển có kinh nghiệm nhìn vào một vấn đề trong miền thấy một loại trách nhiệm quen thuộc hoặc một mạng lưới quan hệ quen thuộc, họ có thể rút ra từ ký ức về cách mà vấn đề đã được giải quyết trước đây. Những mô hình nào đã được thử nghiệm và mô hình nào đã thành công? Những khó khăn nào đã phát sinh trong việc triển khai và chúng đã được giải quyết như thế nào? Kinh nghiệm thử và sai từ trước đó bỗng dưng trở nên có liên quan đến tình huống mới. Một số trong những mô hình này đã được ghi chép và chia sẻ, cho phép phần còn lại của chúng ta rút ra từ kinh nghiệm tích lũy.

                                                                                                                                                                Ngược lại với các mẫu khối xây dựng cơ bản được trình bày trong Phần II và các nguyên tắc thiết kế linh hoạt của Chương 10, những mẫu này ở cấp độ cao hơn và chuyên biệt hơn, liên quan đến việc sử dụng một vài đối tượng để đại diện cho một khái niệm nào đó. Chúng cho phép chúng ta vượt qua những thử nghiệm tốn kém để bắt đầu với một mô hình đã có tính biểu cảm và khả thi, đồng thời giải quyết những sắc thái mà có thể tốn kém để học hỏi. Từ điểm khởi đầu đó, chúng ta sẽ tái cấu trúc và thử nghiệm. Đây không phải là những giải pháp có sẵn.

                                                                                                                                                                Trong sách "Các Mẫu Phân Tích: Mô Hình Đối Tượng Tái Sử Dụng", Martin Fowler đã định nghĩa các mẫu của mình như sau:

                                                                                                                                                                Mẫu phân tích là nhóm các khái niệm đại diện cho một cấu trúc chung trong mô hình kinh doanh. Nó có thể liên quan đến chỉ một lĩnh vực hoặc có thể trải rộng qua nhiều lĩnh vực.

                                                                                                                                                                Các mẫu phân tích mà Fowler trình bày xuất phát từ kinh nghiệm thực tiễn, vì vậy chúng thực tiễn trong những tình huống phù hợp. Những mẫu này cung cấp cho người đang đối mặt với một lĩnh vực thách thức những điểm khởi đầu rất giá trị cho quá trình phát triển lặp đi lặp lại của họ. Tên gọi nhấn mạnh tính chất khái niệm của chúng. Các mẫu phân tích không phải là giải pháp công nghệ; chúng là những hướng dẫn để giúp bạn xây dựng một mô hình trong một lĩnh vực cụ thể.

                                                                                                                                                                Điều mà tên gọi đáng tiếc không truyền đạt được là có sự thảo luận đáng kể về việc triển khai trong các mẫu này, bao gồm một số mã. Fowler hiểu được những cạm bẫy của việc phân tích mà không suy nghĩ đến thiết kế thực tế. Dưới đây là một ví dụ thú vị khi ông nhìn xa hơn cả việc triển khai, đến những tác động của các lựa chọn mô hình cụ thể đối với việc bảo trì lâu dài của hệ thống trong thực tế:

                                                                                                                                                                Khi chúng ta xây dựng một [thực hành] kế toán mới, chúng ta tạo ra một mạng lưới các thể loại quy tắc ghi nhận mới. Chúng ta có thể làm điều này mà không cần phải biên dịch lại hoặc xây dựng lại hệ thống, trong khi nó vẫn hoạt động. Sẽ có những trường hợp không thể tránh khỏi khi chúng ta cần một loại quy tắc ghi nhận mới, nhưng những trường hợp này sẽ hiếm.

                                                                                                                                                                Trong một dự án trưởng thành, các lựa chọn mô hình thường dựa trên kinh nghiệm với ứng dụng. Nhiều triển khai của các thành phần khác nhau sẽ đã được thử nghiệm. Một số trong số đó sẽ đã được đưa vào sản xuất và thậm chí đã trải qua giai đoạn bảo trì. Nhiều vấn đề có thể được tránh khi có những kinh nghiệm như vậy. Các mẫu phân tích ở trạng thái tốt nhất có thể mang theo loại kinh nghiệm đó từ các dự án khác, kết hợp những hiểu biết về mô hình với các cuộc thảo luận sâu rộng về các hướng thiết kế và hậu quả của việc triển khai. Việc thảo luận các ý tưởng mô hình ngoài bối cảnh đó sẽ làm cho chúng khó áp dụng hơn và có nguy cơ mở ra rãnh sâu giữa phân tích và thiết kế, điều này đi ngược lại với THIẾT KẾ DỰA TRÊN MÔ HÌNH.

                                                                                                                                                                Nguyên tắc và ứng dụng của các mẫu phân tích có thể được giải thích tốt hơn bằng ví dụ so với mô tả trừu tượng. Trong chương này, tôi sẽ đưa ra hai ví dụ về các nhà phát triển sử dụng một mẫu nhỏ, đại diện cho các mô hình từ chương "Quản lý hàng tồn kho và Kế toán" trong Fowler 1997. Các mẫu phân tích sẽ được tóm tắt đủ để hỗ trợ cho các ví dụ. Đây rõ ràng không phải là một nỗ lực để lập danh sách các mẫu loại này hoặc thậm chí để giải thích đầy đủ các mẫu đã cho. Mục đích là để minh hoạ sự tích hợp của chúng vào quy trình thiết kế theo miền.


                                                                                                                                                                  Example
                                                                                                                                                                  Earning Interest with Accounts

                                                                                                                                                                  Chương 10 đã cho thấy nhiều cách khác nhau mà một nhà phát triển có thể tìm kiếm một mô hình sâu hơn cho một ứng dụng kế toán chuyên biệt. Dưới đây là một kịch bản khác. Lần này, các nhà phát triển sẽ khai thác cuốn sách Các mẫu phân tích của Fowler để tìm kiếm những ý tưởng hữu ích.

                                                                                                                                                                  Để xem lại, một ứng dụng theo dõi các khoản vay và tài sản sinh lãi khác tính toán lãi suất và các khoản phí phát sinh và theo dõi các khoản thanh toán từ người vay. Một quy trình theo lô hàng đêm lấy những số liệu đó và truyền chúng đến hệ thống kế toán kế thừa, chỉ định sổ cái cụ thể mà mỗi số tiền nên được ghi vào. Thiết kế hoạt động, nhưng khó sử dụng, khó thay đổi và không giao tiếp tốt.

                                                                                                                                                                  Figure 11.1. The initial class diagram

                                                                                                                                                                  graphics/11fig01.gif

                                                                                                                                                                  Nhà phát triển quyết định đọc Chương 6 trong sách Mô Hình Phân Tích, "Tồn Kho và Kế Toán." Dưới đây là tóm tắt phần mà cô ấy thấy quan trọng nhất.

                                                                                                                                                                  Mô hình Kế toán trong Các mẫu Phân tích

                                                                                                                                                                  Các ứng dụng kinh doanh dưới đủ loại hình thức theo dõi các tài khoản, mà trong đó chứa đựng những thứ có giá trị, thường là tiền bạc. Trong nhiều ứng dụng, việc chỉ theo dõi số tiền trong tài khoản là không đủ. Điều quan trọng là phải ghi nhận và kiểm soát mỗi sự thay đổi đối với số tiền đó. Đó là động lực cho mô hình kế toán cơ bản nhất.

                                                                                                                                                                  Figure 11.2. A basic accounting model

                                                                                                                                                                  graphics/11fig02.gif

                                                                                                                                                                  Giá trị có thể được thêm vào bằng cách chèn một mục. Giá trị có thể được loại bỏ bằng cách chèn một mục âm. Các mục không bao giờ bị xóa, vì vậy toàn bộ lịch sử được giữ lại. Số dư là hiệu ứng kết hợp của tất cả các mục. Số dư này có thể được tính toán theo yêu cầu hoặc được lưu trữ, đây là một quyết định triển khai được bao bọc bởi giao diện Tài khoản.

                                                                                                                                                                  Một nguyên tắc cơ bản của kế toán là sự bảo tồn. Tiền không xuất hiện từ đâu cả, cũng không biến mất mà không có dấu vết. Nó chỉ được chuyển từ tài khoản này sang tài khoản khác.

                                                                                                                                                                  Figure 11.3. A transaction model

                                                                                                                                                                  graphics/11fig03.gif

                                                                                                                                                                  Đây là khái niệm đã được thiết lập vững chắc về kế toán hai lớp: Mỗi khoản tín dụng đều có một khoản ghi nợ tương ứng. Tất nhiên, giống như các nguyên tắc bảo toàn khác, nó chỉ áp dụng cho một hệ thống khép kín, một hệ thống bao gồm tất cả các nguồn và hố chứa. Nhiều ứng dụng đơn giản không yêu cầu độ chính xác này.

                                                                                                                                                                  Trong cuốn sách của mình, Fowler bao gồm các hình thức phức tạp hơn của những mô hình này và thảo luận nhiều về các sự cân bằng.

                                                                                                                                                                  Đoạn văn này cung cấp cho nhà phát triển (Nhà phát triển 1) một số ý tưởng mới. Cô ấy cho một đồng nghiệp (Nhà phát triển 2) xem chương này, người đã làm việc cùng cô về một số logic tính toán lãi suất và người đã viết chương trình xử lý theo lô hàng đêm. Cùng nhau, họ phác thảo một thay đổi cho mô hình của mình, tích hợp một số yếu tố mà họ đã đọc về.

                                                                                                                                                                  Figure 11.4. The new model proposal

                                                                                                                                                                  graphics/11fig04.gif

                                                                                                                                                                  Sau đó, họ mời chuyên gia trong lĩnh vực của họ (Chuyên gia) tham gia thảo luận về những ý tưởng mô hình mới của họ.

                                                                                                                                                                  Nhà phát triển 1: Với mô hình mới này, chúng tôi tạo một mục vào Tài khoản Lãi suất cho lãi suất đã kiếm được, thay vì chỉ điều chỉnh số tiền lãi phải trả. Sau đó, một mục khác cho khoản thanh toán sẽ cân bằng lại.

                                                                                                                                                                  Chuyên gia: Vậy bây giờ chúng ta có thể thấy lịch sử của tất cả các khoản lãi tích lũy cũng như lịch sử thanh toán? Đó là điều mà chúng tôi đã mong muốn.

                                                                                                                                                                  Nhà phát triển 2: Tôi không chắc chúng ta đã sử dụng "Giao dịch" đúng cách. Định nghĩa nói về việc chuyển tiền từ tài khoản này sang tài khoản khác, chứ không phải hai mục cân đối với nhau trong cùng một tài khoản.

                                                                                                                                                                  Nhà phát triển 1: Đó là một điểm hay. Tôi cũng lo lắng rằng cuốn sách dường như nhấn mạnh rằng giao dịch được tạo ra tất cả cùng một lúc. Các khoản thanh toán lãi suất có thể trễ vài ngày.

                                                                                                                                                                  Chuyên gia: Những khoản thanh toán đó không nhất thiết phải muộn. Có nhiều tính linh hoạt trong thời gian thanh toán.

                                                                                                                                                                  Nhà phát triển 1: Vậy đây có thể là một ngõ cụt. Tôi đang nghĩ rằng chúng ta có thể đã xác định được một số khái niệm ẩn. Việc để Công cụ Tính lãi suất tạo ra các đối tượng Entry thực sự có vẻ giao tiếp tốt hơn. Và giao dịch dường như gắn kết một cách gọn gàng lãi suất đã được tính toán với khoản thanh toán.

                                                                                                                                                                  Chuyên gia: Tại sao chúng ta cần liên kết khoản tích lũy với khoản thanh toán? Chúng là hai bút toán riêng trong hệ thống kế toán. Số dư trên tài khoản là điều quan trọng nhất. Cùng với các mục riêng lẻ, chúng ta thực sự đã có những gì cần thiết.

                                                                                                                                                                  Nhà phát triển 2: Ý bạn là bạn không theo dõi xem họ đã thực hiện thanh toán lãi suất chưa?

                                                                                                                                                                  Chuyên gia: Chúng tôi tất nhiên là có. Nhưng nó không đơn giản như mô hình thu một lần/chi một lần của bạn.

                                                                                                                                                                  Nhà phát triển 2: Thật ra điều đó có thể đơn giản hóa nhiều thứ nếu không phải lo lắng về kết nối đó.

                                                                                                                                                                  Nhà phát triển 1: Được rồi, thế thì thế này nhé? [Lấy bản sao của sơ đồ lớp cũ và bắt đầu phác thảo các sửa đổi] Nhân tiện, bạn đã sử dụng từ "tích lũy" vài lần. Bạn có thể làm rõ ý nghĩa của nó không?

                                                                                                                                                                  Chuyên gia: Chắc chắn rồi. Một khoản tích lũy chỉ đơn giản là khi bạn ghi nhận một khoản chi phí hoặc thu nhập vào thời điểm phát sinh, không cần quan tâm đến thời điểm tiền thực sự được chuyển nhượng. Vì vậy, chúng ta tích lũy lãi suất hàng ngày, nhưng vào cuối tháng (ví dụ) chúng ta nhận được một khoản thanh toán cho nó.

                                                                                                                                                                  Nhà phát triển 1: Vâng, chúng ta thực sự cần một từ như vậy. Được rồi, cái này trông thế nào?

                                                                                                                                                                  Figure 11.5. Original class diagram, accruals separated from payment

                                                                                                                                                                  graphics/11fig05.gif

                                                                                                                                                                  Nhà phát triển 1: Bây giờ chúng ta có thể loại bỏ tất cả những phức tạp liên quan đến các khoản thanh toán trong máy tính, và chúng tôi đã giới thiệu thuật ngữ "cộng dồn", điều này thể hiện rõ hơn ý định.

                                                                                                                                                                  Chuyên gia: Vậy là chúng ta sẽ không có đối tượng Tài khoản? Tôi đã rất mong muốn được nhìn thấy mọi thứ cùng nhau ở đó, với các khoản tích lũy và thanh toán cũng như một bảng cân đối.

                                                                                                                                                                  Nhà phát triển 1: Thật à?! Vậy trong trường hợp đó, có lẽ cái này sẽ hoạt động. [Lấy một sơ đồ khác và phác thảo]

                                                                                                                                                                  Figure 11.6. The account-based diagram, without Transaction

                                                                                                                                                                  graphics/11fig06.gif

                                                                                                                                                                  Chuyên gia: Thực ra cái đó trông khá tốt!

                                                                                                                                                                  Nhà phát triển 2: Kịch bản lô sẽ dễ dàng để thay đổi để sử dụng các đối tượng mới này.

                                                                                                                                                                  Nhà phát triển 1: Sẽ mất vài ngày để làm cho Công cụ Tính Lãi mới hoạt động. Có khá nhiều bài kiểm tra cần thay đổi. Nhưng bài kiểm tra sẽ rõ ràng hơn sau đó.

                                                                                                                                                                  Hai lập trình viên đã rời đi và bắt đầu làm lại mã dựa trên mô hình mới. Khi họ bắt tay vào mã, siết chặt thiết kế, họ đã có những hiểu biết giúp cải tiến mô hình.

                                                                                                                                                                  Các mục đã được chia thành hai loại là Thanh toán và Tích lũy vì sự kiểm tra kỹ lưỡng hơn đã cho thấy những trách nhiệm hơi khác nhau trong ứng dụng cho chúng, và vì cả hai đều là những khái niệm quan trọng trong lĩnh vực này. Mặt khác, không có sự khác biệt về khái niệm hoặc hành vi giữa các Mục dựa trên việc chúng có xuất phát từ phí hay lãi suất hay không. Chúng chỉ xuất hiện trong Tài khoản thích hợp.

                                                                                                                                                                  Tuy nhiên, đáng tiếc là các nhà phát triển nhận ra rằng họ phải từ bỏ sự trừu tượng cuối cùng này cho việc triển khai. Dữ liệu được lưu trữ trong các bảng quan hệ, và tiêu chuẩn của dự án là làm cho các bảng này có thể hiểu được mà không cần chạy chương trình. Điều này có nghĩa là giữ các mục phí và mục lãi trong các bảng riêng biệt. Cách duy nhất để các nhà phát triển thực hiện điều này, sử dụng khung ánh xạ đối tượng-quan hệ cụ thể của họ, là tạo ra các lớp con cụ thể (Thanh toán phí, Thanh toán lãi, và v.v.). Với một hạ tầng khác, họ có thể đã tránh được sự mở rộng vụng về này.

                                                                                                                                                                  Tôi đã thêm yếu tố bất ngờ này vào câu chuyện phần lớn là hư cấu để thể hiện sự va chạm với thực tế mà chúng ta thường gặp. Chúng ta phải thực hiện những thỏa hiệp có tính toán và sau đó tiến bước mà không để nó làm lệch hướng thiết kế dựa trên mô hình của chúng ta.

                                                                                                                                                                  Figure 11.7. The class diagram after the implementation

                                                                                                                                                                  graphics/11fig07.gif

                                                                                                                                                                  Thiết kế mới dễ phân tích và kiểm tra hơn rất nhiều vì chức năng phức tạp nhất nằm trong CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ. Lệnh còn lại có mã đơn giản (vì nó gọi nhiều HÀM khác nhau) và được đặc trưng bởi CÁC KHẲNG ĐỊNH.

                                                                                                                                                                  Đôi khi, có những phần trong các chương trình của chúng ta mà chúng ta thậm chí không nghi ngờ rằng có tiềm năng để hưởng lợi từ một mô hình miền. Chúng có thể bắt đầu rất đơn giản và tiến triển một cách cơ học. Chúng có vẻ như là mã ứng dụng phức tạp, chứ không phải là logic miền. Các mẫu phân tích có thể đặc biệt hữu ích trong việc cho chúng ta thấy những điểm mù này.

                                                                                                                                                                  Trong ví dụ dưới đây, một nhà phát triển đã có cái nhìn mới vào hộp đen của quá trình xử lý hàng đêm, mà trước đây chưa được xem xét theo hướng miền đã định.


                                                                                                                                                                    Example
                                                                                                                                                                    Insight into the Nightly Batch

                                                                                                                                                                    Sau vài tuần, mô hình dựa trên tài khoản được cải thiện đã bắt đầu ổn định. Như thường xảy ra, sự rõ ràng của thiết kế mới đã làm lộ rõ những vấn đề khác. Nhà phát triển (Nhà phát triển 2) đang điều chỉnh lô dữ liệu hàng đêm để tương tác với thiết kế mới bắt đầu nhận thấy mối liên hệ giữa hành vi của lô và một số khái niệm trong Mô hình Phân tích. Dưới đây là tóm tắt một số khái niệm mà anh ấy thấy có liên quan nhất.

                                                                                                                                                                    Quy định đăng bài

                                                                                                                                                                    Hệ thống kế toán thường cung cấp nhiều cách nhìn khác nhau về cùng một thông tin tài chính cơ bản. Một tài khoản có thể theo dõi thu nhập trong khi một tài khoản khác có thể theo dõi thuế ước tính trên thu nhập đó. Nếu hệ thống được kỳ vọng tự động cập nhật tài khoản thuế ước tính, việc triển khai hai tài khoản này sẽ trở nên rất chồng chéo. Có những hệ thống mà phần lớn các mục tài khoản là kết quả từ các quy tắc như vậy; trong một hệ thống như vậy, logic phụ thuộc trở nên rối rắm. Ngay cả trong các hệ thống khiêm tốn hơn, việc đăng chéo như vậy có thể gặp khó khăn. Bước đầu tiên để thuần hóa sự rối loạn phụ thuộc là làm cho những quy tắc này trở nên rõ ràng bằng cách giới thiệu một đối tượng mới.

                                                                                                                                                                    Figure 11.8. The class diagram of the basic posting rule

                                                                                                                                                                    graphics/11fig08.gif

                                                                                                                                                                    Một quy tắc hạch toán được kích hoạt bởi một mục mới trong tài khoản "đầu vào" của nó. Sau đó, nó sẽ tạo ra một mục mới (dựa trên phương pháp tính toán của riêng nó) và chèn mục mới vào tài khoản "đầu ra" của nó. Trong một hệ thống tiền lương, một mục trong tài khoản lương có thể kích hoạt một quy tắc hạch toán sẽ tính toán thuế thu nhập ước tính 30 phần trăm và chèn nó như một mục trong tài khoản khấu trừ thuế.

                                                                                                                                                                    Thực hiện quy tắc đăng tải

                                                                                                                                                                    Quy tắc đăng đã thiết lập sự phụ thuộc khái niệm giữa các Tài khoản, nhưng nếu mô hình chỉ dừng lại ở đó, thì có thể sẽ khó theo dõi. Một trong những phần khó nhất của các thiết kế phụ thuộc là thời gian và kiểm soát các cập nhật. Fowler thảo luận về ba tùy chọn.

                                                                                                                                                                    1. "Firing khao khát" là điều hiển nhiên nhất, nhưng thường ít thực tiễn nhất. Bất cứ khi nào một Mục được thêm vào Tài khoản, nó ngay lập tức kích hoạt các Quy tắc Đăng và tất cả các cập nhật được thực hiện ngay lập tức.

                                                                                                                                                                    • "Firing dựa trên tài khoản" cho phép việc xử lý được hoãn lại. Tại một thời điểm nào đó, một tin nhắn được gửi đến một Tài khoản và nó kích hoạt các Quy tắc Đăng bài của nó để xử lý tất cả các Mục đã được thêm vào kể từ lần kích hoạt cuối cùng.

                                                                                                                                                                    • Cuối cùng, "kích hoạt dựa trên quy tắc đăng" được khởi xướng bởi một tác nhân bên ngoài, người điều khiến quy tắc đăng thực hiện. Quy tắc đăng có trách nhiệm tra cứu tất cả các mục đã được thực hiện vào tài khoản đầu vào của nó kể từ lần cuối nó được kích hoạt.

                                                                                                                                                                      Mặc dù các chế độ kích hoạt có thể được kết hợp trong một hệ thống, mỗi tập hợp quy tắc cụ thể cần có một điểm khởi đầu và trách nhiệm xác định các Bản Ghi Tài Khoản đầu vào rõ ràng. Việc bổ sung ba chế độ kích hoạt vào NGÔN NGỮ PHỔ THÔNG là quan trọng đối với sự thành công của mô hình cũng như định nghĩa đối tượng của mô hình. Điều này loại bỏ sự mơ hồ và hướng quyết định đến một tập hợp lựa chọn được xác định rõ ràng. Các chế độ này xác định một thách thức dễ bị bỏ qua và cung cấp từ vựng để hỗ trợ cuộc thảo luận rõ ràng.

                                                                                                                                                                    Lập trình viên 2 cần một người để trao đổi về những ý tưởng mới của mình. Anh đã gặp gỡ đồng nghiệp của mình (Lập trình viên 1), người đã chủ yếu chịu trách nhiệm mô hình hóa các khoản tích lũy.

                                                                                                                                                                    Nhà phát triển 2: Ở một thời điểm nào đó, lô hàng ban đêm bắt đầu trở thành nơi chúng tôi giấu giếm mọi thứ. Có logic miền ngầm trong những gì kịch bản thực hiện, và nó ngày càng trở nên phức tạp hơn. Trong một thời gian dài, tôi đã muốn thực hiện một thiết kế dựa trên mô hình cho lô hàng, tách biệt một lớp miền, và biến kịch bản thành một lớp đơn giản đứng phía trên miền đó. Nhưng tôi chưa bao giờ tìm ra mô hình miền đó sẽ như thế nào. Có vẻ như đó chỉ là một số quy trình không thực sự có ý nghĩa như là các đối tượng. Khi tôi đọc phần trong các Mô hình Phân tích về Quy tắc Đăng bài, tôi đã có một số ý tưởng. Đây là những gì tôi đã suy nghĩ. [Đưa một bản phác thảo]

                                                                                                                                                                    Figure 11.9. A shot at using Posting Rules in the batch

                                                                                                                                                                    graphics/11fig09.gif

                                                                                                                                                                    Người phát triển 1: Dịch vụ "Đăng bài" là gì?

                                                                                                                                                                    Nhà phát triển 2: Đó là một FACADA mà phơi bày API của ứng dụng kế toán và trình bày nó như một DỊCH VỤ. Trên thực tế, tôi đã tạo ra điều đó một thời gian trước để đơn giản hóa mã theo lô, và nó cũng mang lại cho tôi một GIA DIỆN TIẾT LỘ Ý ĐỊNH để đăng bài lên hệ thống cũ.

                                                                                                                                                                    Nhà phát triển 1: Thú vị. Vậy, bạn dự định sử dụng kiểu bắn nào cho các Quy tắc Đăng?

                                                                                                                                                                    Nhà phát triển 2: Tôi chưa thực sự đi xa đến vậy.

                                                                                                                                                                    Nhà phát triển 1: Việc Kích hoạt Nhanh sẽ hoạt động cho các Khoản ghi nhận, vì lô công việc thực sự yêu cầu Tài khoản chèn chúng, nhưng nó sẽ không hoạt động cho các Khoản thanh toán, những khoản này được nhập trong suốt cả ngày.

                                                                                                                                                                    Nhà phát triển 2: Tôi không nghĩ chúng ta nên kết hợp phương pháp tính toán chặt chẽ với lô hàng như vậy. Nếu chúng ta từng quyết định kích hoạt việc tính toán lãi suất vào một thời điểm khác, điều đó sẽ gây rối loạn mọi thứ. Và về mặt khái niệm, điều đó dường như không đúng.

                                                                                                                                                                    Nhà phát triển 1: Nghe có vẻ giống như việc kích hoạt dựa trên quy tắc đăng. Lô sẽ thông báo cho mỗi quy tắc đăng thực thi, và quy tắc sẽ đi tìm các mục mới phù hợp và sau đó thực hiện công việc của nó. Đó khá giống với cách bạn đã phác thảo.

                                                                                                                                                                    Nhà phát triển 2: Vậy thì chúng ta tránh tạo ra nhiều phụ thuộc vào thiết kế lô, và lô giữ quyền kiểm soát. Nghe có vẻ đúng.

                                                                                                                                                                    Nhà phát triển 1: Tôi vẫn còn hơi mơ hồ về sự tương tác của những đối tượng này với Tài khoản và Ghi chú.

                                                                                                                                                                    Nhà phát triển 2: Cùng một suy nghĩ với bạn. Những ví dụ trong sách tạo ra một liên kết trực tiếp giữa Tài khoản và Quy tắc Đăng ký. Điều đó có vẻ hợp lý, nhưng tôi không nghĩ nó sẽ hoạt động tốt với chúng ta. Chúng ta phải khởi tạo những đối tượng này từ dữ liệu mỗi lần, vì vậy chúng ta sẽ phải tìm ra quy tắc nào áp dụng để liên kết với nó. Trong khi đó, đối tượng Tài sản là cái biết nội dung của từng Tài khoản, và do đó biết quy tắc nào để áp dụng. Dù sao, còn phần còn lại thì sao?

                                                                                                                                                                    Nhà phát triển 1: Tôi không muốn soi mói, nhưng tôi không nghĩ rằng chúng ta đang sử dụng "Phương thức" đúng. Tôi nghĩ rằng khái niệm là Phương thức tính toán số tiền cần được ghi sổ - như, giả dụ, việc khấu trừ thuế 20 phần trăm trên thu nhập. Nhưng trong trường hợp của chúng ta, điều đó đơn giản: đó luôn là toàn bộ số tiền được ghi sổ. Tôi nghĩ rằng Quy tắc Ghi sổ tự nó nên biết tài khoản nào để ghi sổ, tương ứng với "tên sổ cái" của chúng ta.

                                                                                                                                                                    Nhà phát triển 2: Ồ. Nếu Quy tắc Đăng bài chịu trách nhiệm biết tên sổ cái chính xác, chúng ta có thể không cần Phương thức nữa.

                                                                                                                                                                    Thực sự, toàn bộ vấn đề chọn tên sổ cái phù hợp đang ngày càng trở nên phức tạp. Nó đã là sự kết hợp giữa loại thu nhập (phí hoặc lãi) với "nhóm tài sản" (một danh mục mà doanh nghiệp áp dụng cho từng Tài sản). Đó là một nơi mà tôi hy vọng mô hình mới này sẽ giúp ích.

                                                                                                                                                                    Nhà phát triển 1: Được rồi, hãy tập trung vào đó. Quy tắc Ghi nhận chịu trách nhiệm chọn Sổ cái dựa trên các thuộc tính của Tài khoản. Hiện tại, chúng ta có thể làm cho nó đơn giản để xử lý loại tài sản và sự phân biệt giữa lãi suất và phí. Trong tương lai, bạn sẽ có một MÔ HÌNH ĐỐI TƯỢNG mà bạn có thể mở rộng để xử lý các trường hợp phức tạp hơn.

                                                                                                                                                                    Nhà phát triển 2: Tôi cần suy nghĩ thêm về điều này. Hãy để tôi xem xét kỹ lại, và đọc lại các mẫu, sau đó tôi sẽ thử lại. Tôi có thể nói chuyện với bạn về điều này một lần nữa vào chiều mai không?

                                                                                                                                                                    Trong vài ngày tới, hai lập trình viên đã làm việc để xây dựng một mô hình và tái cấu trúc mã nguồn sao cho lô hàng chỉ đơn giản lặp qua các Tài sản, gửi một vài thông điệp giải thích cho mỗi cái và sau đó cam kết các giao dịch cơ sở dữ liệu. Sự phức tạp đã được chuyển vào lớp miền, nơi mà một mô hình đối tượng làm cho nó vừa rõ ràng hơn vừa trừu tượng hơn.

                                                                                                                                                                    Figure 11.10. The class diagram with Posting Rules

                                                                                                                                                                    graphics/11fig10.gif

                                                                                                                                                                    Figure 11.11. Sequence diagram showing rule firing

                                                                                                                                                                    graphics/11fig11.gif

                                                                                                                                                                    Các nhà phát triển đã rời xa khá nhiều so với các chi tiết của các mô hình được trình bày trong Patterns Phân tích, tuy nhiên họ cảm thấy họ đã giữ được bản chất của các khái niệm. Họ cảm thấy hơi không thoải mái khi phải liên quan đến Tài sản trong việc chọn Quy tắc Đăng. Họ đã chọn cách đó vì Tài sản có kiến thức về bản chất của từng Tài khoản (phí hoặc lãi suất) và cũng là điểm truy cập tự nhiên cho kịch bản. Nếu liên kết trực tiếp đối tượng quy tắc với Tài khoản, sẽ yêu cầu một sự cộng tác với đối tượng Tài sản ở mỗi lần khởi tạo các đối tượng (mỗi lần chạy lô). Thay vào đó, họ để đối tượng Tài sản tìm kiếm hai quy tắc liên quan thông qua quyền truy cập SINGLETON của chúng và chuyển cho chúng Tài khoản thích hợp. Nó dường như giúp mã nguồn trở nên trực tiếp hơn, vì vậy họ đã đưa ra một quyết định thực dụng.

                                                                                                                                                                    Họ đều cảm thấy rằng về mặt khái niệm, sẽ tốt hơn nếu chỉ liên kết Quy tắc Đăng bài với Tài khoản, trong khi giữ cho Tài sản tập trung vào công việc tạo ra Các khoản phải thu. Họ hy vọng rằng những lần tái cấu trúc sau này và cái nhìn sâu sắc hơn sẽ đưa họ quay trở lại vấn đề này và cho họ một cách để thực hiện sự phân chia rõ ràng mà không làm mất đi sự hiển nhiên của mã.


                                                                                                                                                                      Analysis Patterns Are Knowledge to Draw On

                                                                                                                                                                      Khi bạn may mắn có một mẫu phân tích, nó hầu như không bao giờ là câu trả lời cho nhu cầu cụ thể của bạn. Tuy nhiên, nó cung cấp những manh mối quý giá trong cuộc điều tra của bạn và cung cấp từ vựng được trừu tượng hóa một cách sạch sẽ. Nó cũng nên hướng dẫn bạn về những hậu quả của việc triển khai sẽ giúp bạn tránh được nỗi đau trong tương lai.

                                                                                                                                                                      Tất cả những điều này dẫn vào động lực của việc xử lý và tái cấu trúc kiến thức nhằm hướng tới sự hiểu biết sâu sắc hơn và thúc đẩy phát triển. Kết quả thường giống với hình thức được tài liệu hóa trong mẫu phân tích, nhưng đã được điều chỉnh cho phù hợp với hoàn cảnh. Đôi khi kết quả thậm chí còn không liên quan rõ ràng đến chính mẫu phân tích, nhưng lại được kích thích bởi những hiểu biết từ mẫu đó.

                                                                                                                                                                      Có một loại thay đổi mà bạn nên tránh. Khi bạn sử dụng một thuật ngữ từ một mẫu phân tích nổi tiếng, hãy cẩn thận giữ nguyên khái niệm cơ bản mà nó chỉ định, cho dù hình thức bề ngoài có thay đổi nhiều đến đâu. Có hai lý do cho điều này. Thứ nhất, mẫu đó có thể chứa đựng sự hiểu biết giúp bạn tránh được các vấn đề. Thứ hai, và quan trọng hơn, NGÔN NGỮ PHỔ BIẾN của bạn sẽ được nâng cao khi nó bao gồm các thuật ngữ được hiểu rộng rãi hoặc ít nhất là được giải thích rõ ràng. Nếu định nghĩa mô hình của bạn thay đổi thông qua sự tiến hóa tự nhiên của mô hình, hãy cố gắng thay đổi cả tên gọi.

                                                                                                                                                                      Có khá nhiều mô hình đối tượng đã được viết ra, một số chuyên biệt cho một loại ứng dụng trong một ngành công nghiệp và một số thì khá tổng quát. Hầu hết trong số đó cung cấp hạt giống của một ý tưởng, nhưng chỉ một vài mô hình đã nắm bắt được lý do đứng sau các lựa chọn và những hậu quả theo sau, điều này là phần hữu ích nhất của một mẫu phân tích. Nhiều mẫu phân tích tinh chỉnh hơn sẽ có giá trị, giúp chúng ta tránh việc phát minh lại bánh xe một lần nữa và một lần nữa. Tôi sẽ ngạc nhiên nếu thấy một danh mục toàn diện, nhưng có thể sẽ xuất hiện các danh mục theo ngành công nghiệp cụ thể. Và các mẫu cho một số lĩnh vực mà trải dài nhiều ứng dụng có thể được chia sẻ rộng rãi.

                                                                                                                                                                      Việc tái sử dụng kiến thức có tổ chức theo cách này hoàn toàn khác với những nỗ lực tái sử dụng mã thông qua các khuôn khổ hoặc thành phần, ngoại trừ việc cả hai đều có thể cung cấp hạt giống của một ý tưởng không rõ ràng. Một mô hình, ngay cả một khuôn khổ tổng quát, là một tổng thể hoàn chỉnh, trong khi một phân tích là một bộ các mảnh mô hình. Các mẫu phân tích tập trung vào những quyết định quan trọng và khó khăn nhất, đồng thời làm sáng tỏ các lựa chọn và phương án thay thế. Chúng dự đoán những hậu quả sau này sẽ tốn kém nếu bạn phải tự mình khám phá ra chúng.


                                                                                                                                                                        Chapter Twelve. Relating Design Patterns to the Model

                                                                                                                                                                        Các mẫu được khám phá trong cuốn sách này tính đến cho việc giải quyết các vấn đề trong mô hình miền trong bối cảnh thiết kế hướng mô hình. Thực tế, hầu hết các mẫu được công bố đến nay đều tập trung nhiều hơn vào khía cạnh kỹ thuật. Sự khác biệt giữa mẫu thiết kế và mẫu miền là gì? Để bắt đầu, các tác giả của cuốn sách kinh điển, Mẫu Thiết Kế, đã có điều này để nói:

                                                                                                                                                                        Quan điểm ảnh hưởng đến cách diễn giải của một người về những gì là và không phải là một mẫu. Một mẫu của người này có thể là đá xây dựng nguyên thủy của người khác. Trong cuốn sách này, chúng tôi tập trung vào các mẫu ở một mức độ trừu tượng nhất định. Các mẫu thiết kế không phải là các thiết kế như danh sách liên kết và bảng băm có thể được mã hóa trong các lớp và tái sử dụng như chúng là. Cũng không phải là các thiết kế phức tạp, chuyên biệt cho miền cho toàn bộ ứng dụng hoặc phân hệ. Các mẫu thiết kế trong cuốn sách này là mô tả về các đối tượng và lớp giao tiếp được tùy chỉnh để giải quyết một vấn đề thiết kế chung trong một ngữ cảnh cụ thể.

                                                                                                                                                                        Một số, không phải tất cả, các mẫu trong Mẫu Thiết Kế có thể được sử dụng như các mẫu miền. Làm như vậy yêu cầu một sự chuyển đổi trong trọng tâm. Mẫu Thiết Kế trình bày một danh mục các yếu tố thiết kế đã giải quyết các vấn đề thường gặp trong nhiều ngữ cảnh khác nhau. Động lực của các mẫu này và chính các mẫu đó được trình bày bằng thuật ngữ kỹ thuật thuần túy. Nhưng một tập hợp con của các yếu tố này có thể được áp dụng trong ngữ cảnh rộng hơn của mô hình hóa và thiết kế miền, vì chúng tương ứng với các khái niệm tổng quát xuất hiện trong nhiều miền.

                                                                                                                                                                        Ngoài những mẫu thiết kế trong Design Patterns, còn nhiều mẫu thiết kế kỹ thuật khác đã được trình bày trong suốt những năm qua. Một số trong số đó tương ứng với các khái niệm sâu sắc xuất hiện trong các lĩnh vực. Sẽ rất tốt nếu chúng ta có thể dựa vào những công trình này. Để tận dụng những mẫu này trong thiết kế hướng miền, chúng ta phải xem xét các mẫu ở hai cấp độ đồng thời. Ở một cấp độ, chúng là các mẫu thiết kế kỹ thuật trong mã. Ở cấp độ khác, chúng là các mẫu khái niệm trong mô hình.

                                                                                                                                                                        Một mẫu các mẫu cụ thể từ Các Mẫu Thiết Kế sẽ cho thấy cách một mẫu được nghĩ ra như một mẫu thiết kế có thể được áp dụng trong mô hình miền, và nó sẽ làm sáng tỏ sự khác biệt giữa một mẫu thiết kế kỹ thuật và một mẫu miền. COMPOSITE và STRATEGY minh họa cách một số mẫu thiết kế cổ điển có thể được áp dụng cho các vấn đề miền bằng cách suy nghĩ về chúng theo một cách khác. . . .


                                                                                                                                                                          Strategy (A.K.A.Policy)

                                                                                                                                                                          graphics/12inf01.gif

                                                                                                                                                                          Định nghĩa một tập hợp các thuật toán, đóng gói từng thuật toán và làm cho chúng có thể hoán đổi cho nhau. STRATEGY cho phép thuật toán thay đổi độc lập với các đối tượng sử dụng nó.

                                                                                                                                                                          Mô hình miền chứa các quy trình không được động viên bởi kỹ thuật nhưng thực sự có ý nghĩa trong miền vấn đề. Khi phải cung cấp các quy trình thay thế, độ phức tạp trong việc chọn quy trình phù hợp kết hợp với độ phức tạp của nhiều quy trình tự thân, và mọi thứ trở nên mất kiểm soát.

                                                                                                                                                                          Khi chúng ta mô hình hóa các quá trình, chúng ta thường nhận ra rằng có nhiều cách hợp lệ để thực hiện chúng. Khi chúng ta bắt đầu mô tả những lựa chọn này, định nghĩa của chúng ta về quá trình trở nên cồng kềnh và phức tạp. Các lựa chọn hành vi thực sự mà chúng ta đang cân nhắc bị che khuất khi chúng bị trộn lẫn với phần còn lại của hành vi.

                                                                                                                                                                          Chúng tôi muốn tách biệt biến thể này khỏi khái niệm chính của quá trình. Sau đó, chúng tôi sẽ có thể thấy rõ hơn cả quá trình chính và các tùy chọn. Mẫu STRATEGY, đã được thiết lập tốt trong cộng đồng thiết kế phần mềm, giải quyết chính vấn đề này, mặc dù trọng tâm là kỹ thuật. Ở đây, nó được áp dụng như một khái niệm trong một mô hình và phản ánh trong việc cài đặt mã của mô hình đó. Có nhu cầu tương tự để tách phần có nhiều biến đổi cao của quá trình ra khỏi phần ổn định hơn.

                                                                                                                                                                          Do đó:

                                                                                                                                                                          Phân tách phần biến đổi của một quy trình thành một "đối tượng chiến lược" riêng trong mô hình. Phân tách một quy tắc và hành vi mà nó điều chỉnh. Thực hiện quy tắc hoặc quy trình thay thế theo mẫu thiết kế STRATEGY. Nhiều phiên bản của đối tượng chiến lược đại diện cho những cách khác nhau mà quy trình có thể được thực hiện.

                                                                                                                                                                          Trong khi cách nhìn truyền thống về CHIẾN LƯỢC như một mẫu thiết kế tập trung vào khả năng thay thế các thuật toán khác nhau, việc sử dụng nó như một mẫu miền tập trung vào khả năng thể hiện một khái niệm, thường là một quy trình hoặc một quy tắc chính sách.

                                                                                                                                                                          Example
                                                                                                                                                                          Route-Finding Policies

                                                                                                                                                                          Một Đặc tả Lộ trình đang được chuyển đến một Dịch vụ Định tuyến, có nhiệm vụ xây dựng một Lịch trình chi tiết đáp ứng ĐẶC TẢ. DỊCH VỤ này là một động cơ tối ưu hóa có thể được điều chỉnh để tìm kiếm lộ trình nhanh nhất hoặc rẻ nhất.

                                                                                                                                                                          Figure 12.1. A SERVICE interface with options will need conditional logic.

                                                                                                                                                                          graphics/12fig01.gif

                                                                                                                                                                          Cài đặt này có vẻ ổn, nhưng một cái nhìn chi tiết vào mã định tuyến sẽ tiết lộ các điều kiện trong mỗi phép tính, khiến cho việc quyết định giữa nhanh nhất hoặc rẻ nhất xuất hiện ở khắp mọi nơi. Nhiều rắc rối sẽ xảy ra khi các tiêu chí mới được thêm vào để đưa ra những lựa chọn tinh vi hơn giữa các tuyến đường.

                                                                                                                                                                          Một cách tiếp cận là phân tách những tham số điều chỉnh đó thành CÁC CHIẾN LƯỢC. Sau đó, chúng có thể được biểu diễn rõ ràng và được truyền vào Dịch vụ Định tuyến như một tham số.

                                                                                                                                                                          Dịch vụ Định tuyến hiện xử lý tất cả các yêu cầu theo cách không điều kiện giống nhau, tìm kiếm một chuỗi các Chân với độ lớn thấp, như được tính toán bởi Chính sách Độ lớn Chân.

                                                                                                                                                                          Thiết kế này có những lợi thế thúc đẩy mẫu STRATEGY trong các mẫu thiết kế. Ở mức độ đa dụng và linh hoạt của ứng dụng, hành vi của Dịch vụ Định tuyến giờ đây có thể được kiểm soát và mở rộng bằng cách cài đặt một Chính sách Độ lớn Chân phù hợp. Các CHIẾN LƯỢC được minh họa trong Hình 12.2 (nhanh nhất hoặc rẻ nhất) chỉ là những cái rõ ràng nhất. Có thể có những tổ hợp cân bằng giữa tốc độ và chi phí. Cũng có thể có các yếu tố khác nhau, chẳng hạn như thiệt lệch về việc đặt hàng cargo trên các phương tiện vận chuyển của công ty thay vì thuê ngoài để vận chuyển trên các phương tiện của các công ty vận tải khác. Những thay đổi này có thể đã được thực hiện mà không cần resort đến các CHIẾN LƯỢC, nhưng logic sẽ đi qua nội bộ của Dịch vụ Định tuyến và làm phình to giao diện của nó. Việc tách rời làm cho việc này trở nên rõ ràng và dễ kiểm tra hơn.

                                                                                                                                                                          Figure 12.2. Options determined by choice of STRATEGY (POLICY) passed as argument

                                                                                                                                                                          graphics/12fig02.gif

                                                                                                                                                                          Một quy tắc quan trọng căn bản trong lĩnh vực này, cơ sở để chọn một Chặng này hơn Chặng khác khi xây dựng một Lịch trình, giờ đây đã rõ ràng và khác biệt. Nó truyền đạt kiến thức rằng một thuộc tính cụ thể (có thể được suy ra) của một chặng cá nhân, được tinh gọn thành một con số duy nhất, là cơ sở cho việc định tuyến. Điều này cho phép một phát biểu đơn giản trong ngôn ngữ của lĩnh vực xác định hành vi của Dịch vụ Định tuyến: Dịch vụ Định tuyến chọn một Lịch trình với tổng độ lớn tối thiểu của các Chặng dựa trên CHIẾN LƯỢC đã chọn.

                                                                                                                                                                          Lưu ý: Cuộc thảo luận này ngụ ý rằng Dịch vụ Định tuyến thực sự đang đánh giá các Chặng đường khi nó tìm kiếm một Lịch trình. Cách tiếp cận này về mặt khái niệm thì đơn giản và có thể tạo ra một mẫu triển khai hợp lý, nhưng có lẽ sẽ không hiệu quả chấp nhận được. Ứng dụng này sẽ được đề cập lại trong Chương 14, "Duy trì Tính toàn vẹn của Mô hình," nơi cùng một giao diện sẽ được sử dụng với một triển khai hoàn toàn khác của Dịch vụ Định tuyến.

                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                          Khi chúng ta sử dụng mẫu thiết kế kỹ thuật trong lớp miền, chúng ta phải thêm một động lực bổ sung, một lớp ý nghĩa khác. Khi CHIẾN LƯỢC tương ứng với một chiến lược hoặc chính sách kinh doanh thực tế, mẫu này trở thành nhiều hơn một kỹ thuật triển khai hữu ích (mặc dù điều đó cũng có giá trị ở mức độ nhất định).

                                                                                                                                                                          Hệ quả của mẫu thiết kế hoàn toàn áp dụng. Ví dụ, trong cuốn "Design Patterns", Gamma et al. chỉ ra rằng các khách hàng phải nhận thức được những CHIẾN LƯỢC khác nhau, điều này cũng là một mối quan tâm về mô hình. Một mối quan tâm thuần túy về triển khai là các CHIẾN LƯỢC có thể làm tăng số lượng đối tượng trong ứng dụng. Nếu đó là một vấn đề, chi phí có thể được giảm bớt bằng cách triển khai các CHIẾN LƯỢC dưới dạng các đối tượng không trạng thái mà các ngữ cảnh có thể chia sẻ. Cuộc thảo luận sâu rộng về các phương pháp triển khai trong "Design Patterns" đều áp dụng ở đây. Điều này là vì chúng ta vẫn đang sử dụng một CHIẾN LƯỢC. Động lực của chúng ta phần nào khác nhau, điều này sẽ ảnh hưởng đến một số lựa chọn, nhưng những kinh nghiệm được nhúng trong mẫu thiết kế là có sẵn cho chúng ta.


                                                                                                                                                                            Composite

                                                                                                                                                                            graphics/12inf02.gif

                                                                                                                                                                            Biên soạn các đối tượng thành cấu trúc cây để biểu diễn các hệ thống phân phần. COMPOSITE cho phép khách hàng xử lý các đối tượng riêng lẻ và các sự kết hợp của các đối tượng một cách đồng nhất. [Gamma et al. 1995]

                                                                                                                                                                            Chúng tôi thường gặp phải, trong quá trình mô hình hóa các miền phức tạp, một đối tượng quan trọng được cấu thành từ các phần, mà chính các phần đó cũng lại được tạo thành từ các phần, và cứ thế, đôi khi còn lồng vào nhau đến độ sâu tùy ý. Trong một số miền, mỗi cấp độ này là khác biệt về mặt khái niệm, nhưng trong những trường hợp khác, có một cảm giác rằng các phần đều là cùng một loại thứ như toàn bộ, chỉ là nhỏ hơn.

                                                                                                                                                                            Khi mối quan hệ của các đối tượng lồng nhau không được phản ánh trong mô hình, hành vi chung phải được sao chép ở mỗi cấp độ của cấu trúc, và việc lồng nhau là cứng nhắc (ví dụ, các đối tượng thường không thể chứa các đối tượng khác ở cùng cấp độ, và số lượng cấp độ là cố định). Các khách hàng phải xử lý với các cấp độ khác nhau của cấu trúc thông qua các giao diện khác nhau, mặc dù có thể không có sự khác biệt nào về mặt khái niệm mà họ quan tâm. Việc đệ quy qua cấu trúc để tạo ra thông tin tổng hợp rất phức tạp.

                                                                                                                                                                            Khi áp dụng bất kỳ mẫu thiết kế nào trong miền, mối quan tâm đầu tiên nên là liệu ý tưởng của mẫu đó có thực sự phù hợp với khái niệm trong miền hay không. Có thể thuận tiện khi di chuyển qua một số đối tượng liên kết, nhưng có phải thực sự có một cấu trúc toàn-bộ phần? Bạn đã tìm thấy một sự trừu tượng mà dưới đó tất cả các phần thực sự thuộc cùng một loại khái niệm hay chưa? Nếu có, COMPOSITE sẽ làm cho các khía cạnh đó của mô hình trở nên rõ ràng hơn, đồng thời cho phép bạn khai thác vào thiết kế và các yếu tố thực hiện đã được cân nhắc kỹ lưỡng của mẫu thiết kế.

                                                                                                                                                                            Vì vậy:

                                                                                                                                                                            Định nghĩa một loại trừu tượng bao gồm tất cả các thành viên của COMPOSITE. Các phương thức trả về thông tin được triển khai trên các container để trả về thông tin tổng hợp về nội dung của chúng. Các nút "Lá" thực hiện các phương thức đó dựa trên giá trị của chính chúng. Khách hàng làm việc với loại trừu tượng và không cần phân biệt giữa lá và container.

                                                                                                                                                                            Đây là một mẫu tương đối rõ ràng ở cấp độ cấu trúc, nhưng các nhà thiết kế thường không tự mình phát triển cấp độ vận hành của mẫu này. COMPOSITE cung cấp cùng một hành vi ở mọi cấp độ cấu trúc, và những câu hỏi có ý nghĩa có thể được đặt ra về các bộ phận nhỏ hoặc lớn mà phản ánh một cách rõ ràng cấu trúc của chúng. Sự đối xứng chặt chẽ đó là chìa khóa cho sức mạnh của mẫu thiết kế.

                                                                                                                                                                            Example
                                                                                                                                                                            Shipment Routes Made of Routes

                                                                                                                                                                            Một lộ trình vận chuyển hàng hóa hoàn chỉnh rất phức tạp. Đầu tiên, container phải được vận chuyển bằng xe tải đến một đầu mối đường sắt, sau đó được chuyển đến cảng, sau đó được vận chuyển bằng tàu đến một cảng khác, có thể được chuyển sang các tàu khác, và cuối cùng được vận chuyển bằng đường bộ ở đầu bên kia.

                                                                                                                                                                            Figure 12.3. A schematic of a "route" made up of "legs"

                                                                                                                                                                            graphics/12fig03.gif

                                                                                                                                                                            Một nhóm phát triển ứng dụng đã tạo ra một mô hình đối tượng để thể hiện các chuỗi chân dài tùy ý này kết hợp thành một lộ trình.

                                                                                                                                                                            Figure 12.4. A class diagram of a Route made up of Legs

                                                                                                                                                                            graphics/12fig04.gif

                                                                                                                                                                            Sử dụng mô hình này, các nhà phát triển có thể tạo ra các đối tượng Đường đi dựa trên các yêu cầu đặt chỗ. Họ có thể xử lý các Chặng đường để đưa vào kế hoạch vận hành cho việc xử lý hàng hóa từng bước một. Sau đó, họ phát hiện ra một điều gì đó.

                                                                                                                                                                            Các nhà phát triển luôn coi một lộ trình như một chuỗi các đoạn đường tùy ý, không phân biệt.

                                                                                                                                                                            Figure 12.5. The developers' conception of a route

                                                                                                                                                                            graphics/12fig05.gif

                                                                                                                                                                            Hóa ra, các chuyên gia trong lĩnh vực xem hành trình như một chuỗi năm phân đoạn hợp lý.

                                                                                                                                                                            Figure 12.6. The business experts' conception of a route

                                                                                                                                                                            graphics/12fig06.gif

                                                                                                                                                                            Ngoài những điều khác, các nhánh phụ này có thể được lên kế hoạch vào những thời điểm khác nhau bởi những người khác nhau, vì vậy chúng phải được xem như là khác biệt. Và khi xem xét kỹ lưỡng, "các chân cửa" rất khác biệt so với các chân khác, liên quan đến xe tải được thuê tại chỗ hoặc thậm chí là việc vận chuyển của khách hàng, trái ngược với các phương tiện vận tải đường sắt và hàng hải đã được lên lịch công phu.

                                                                                                                                                                            Một mô hình đối tượng phản ánh tất cả những khác biệt này bắt đầu trở nên phức tạp.

                                                                                                                                                                            Figure 12.7. The elaborated class diagram of Route

                                                                                                                                                                            graphics/12fig07.gif

                                                                                                                                                                            Về cấu trúc, mô hình không tồi, nhưng sự đồng nhất trong việc xử lý kế hoạch vận hành bị mất, vì vậy mã, hoặc thậm chí mô tả về hành vi, trở nên phức tạp hơn nhiều. Các phức tạp khác cũng bắt đầu xuất hiện. Mọi việc di chuyển theo một lộ trình đều liên quan đến nhiều bộ sưu tập các loại đối tượng khác nhau.

                                                                                                                                                                            Nhập COMPOSITE. Sẽ rất tốt, đối với một số khách hàng, khi coi các cấp độ khác nhau trong cấu trúc này một cách đồng nhất, như là các lộ trình bao gồm các lộ trình. Về mặt khái niệm, quan điểm này là đúng. Mỗi cấp độ của Lộ trình là một chuyển động của một container từ một điểm này sang điểm khác, cho đến cấp độ từng đoạn riêng lẻ. (Xem Hình 12.8.)

                                                                                                                                                                            Figure 12.8. A class diagram using COMPOSITE

                                                                                                                                                                            graphics/12fig08.gif

                                                                                                                                                                            Bây giờ, sơ đồ lớp tĩnh không cho chúng ta biết nhiều về cách các chân cửa và các đoạn khác kết hợp với nhau như sơ đồ trước đó. Nhưng mô hình này không chỉ là một sơ đồ lớp tĩnh. Chúng ta sẽ truyền đạt thông tin lắp ráp thông qua các sơ đồ khác (xem Hình 12.9) và qua mã (giờ đã đơn giản hơn nhiều). Mô hình này nắm bắt mối liên hệ sâu sắc giữa tất cả các loại "Route" khác nhau. Việc tạo ra kế hoạch vận hành lại trở nên đơn giản, cũng như các thao tác di chuyển qua tuyến đường khác.

                                                                                                                                                                            Figure 12.9. Instances representing a complete Route

                                                                                                                                                                            graphics/12fig09.gif

                                                                                                                                                                            Với một lộ trình được tạo thành từ các lộ trình khác, nối liền nhau từ đầu đến cuối để di chuyển từ nơi này đến nơi khác, bạn có thể có các triển khai lộ trình với mức độ chi tiết khác nhau. Bạn có thể cắt bỏ phần cuối của một lộ trình và nối vào một phần kết thúc mới, bạn có thể có sự lồng ghép tùy ý của chi tiết, và bạn có thể khai thác mọi loại tùy chọn có thể hữu ích.

                                                                                                                                                                            Tất nhiên, chúng tôi vẫn chưa cần những tùy chọn như vậy. Và trước khi chúng tôi cần những đoạn đường và các đoạn cửa khác nhau đó, chúng tôi đã hoạt động tốt mà không cần đến COMPOSITE. Một mẫu thiết kế chỉ nên được áp dụng khi nó cần thiết.

                                                                                                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif


                                                                                                                                                                              Why Not FLYWEIGHT?

                                                                                                                                                                              Bởi vì tôi đã đề cập đến mẫu FLYWEIGHT trước đó (trong Chương 5), bạn có thể đã giả định rằng nó là một ví dụ về một mẫu để áp dụng cho các mô hình miền. Thực tế, FLYWEIGHT là một ví dụ hay về một mẫu thiết kế không có sự tương ứng với mô hình miền.

                                                                                                                                                                              Khi một tập hợp hạn chế các ĐỐI TƯỢNG GIÁ TRỊ được sử dụng nhiều lần (như trong ví dụ về ổ điện trong một kế hoạch nhà), có thể hợp lý để triển khai chúng dưới dạng FLYWEIGHT. Đây là một tùy chọn triển khai cho ĐỐI TƯỢNG GIÁ TRỊ và không được áp dụng cho CÁNH. Đối lập với điều này là COMPOSITE, trong đó các đối tượng khái niệm được cấu thành từ các đối tượng khái niệm khác. Trong trường hợp đó, mẫu này áp dụng cho cả mô hình và triển khai, điều này là một đặc điểm thiết yếu của một mẫu miền.

                                                                                                                                                                              Tôi sẽ không cố gắng biên soạn một danh sách các mẫu thiết kế có thể được sử dụng như các mẫu miền. Mặc dù tôi không thể nghĩ ra một ví dụ nào về việc sử dụng một trình thông dịch như một mẫu miền, tôi không sẵn sàng nói rằng không có khái niệm nào về miền phù hợp. Yêu cầu duy nhất là mẫu thiết kế phải nói lên điều gì đó về miền khái niệm, không chỉ đơn thuần là một giải pháp kỹ thuật cho một vấn đề kỹ thuật.


                                                                                                                                                                                Chapter Thirteen. Refactoring Toward Deeper Insight

                                                                                                                                                                                Việc tái cấu trúc để đạt được hiểu biết sâu sắc hơn là một quá trình đa diện. Sẽ rất hữu ích nếu dừng lại một chút để tổng hợp các điểm chính. Có ba điều bạn cần tập trung vào.

                                                                                                                                                                                1. Sống trong miền.

                                                                                                                                                                                Hãy tiếp tục nhìn mọi thứ theo một cách khác.

                                                                                                                                                                                Duy trì một cuộc đối thoại liên tục với các chuyên gia trong lĩnh vực.

                                                                                                                                                                                Tìm hiểu về lĩnh vực tạo ra một bối cảnh rộng hơn cho quá trình tái cấu trúc.

                                                                                                                                                                                Kịch bản tái cấu trúc cổ điển liên quan đến một hoặc hai lập trình viên ngồi trước bàn phím, nhận ra rằng một số mã có thể được cải thiện, và sau đó thay đổi nó ngay lập tức (với các bài kiểm tra đơn vị để xác minh kết quả của họ, tất nhiên). Thực hành này nên diễn ra thường xuyên, nhưng nó không phải là toàn bộ câu chuyện.

                                                                                                                                                                                Năm chương trước đã trình bày một cái nhìn mở rộng về việc tái cấu trúc, chồng lên phương pháp tái cấu trúc vi mô truyền thống.


                                                                                                                                                                                  Initiation

                                                                                                                                                                                  Việc tái cấu trúc để có cái nhìn sâu sắc hơn có thể bắt đầu bằng nhiều cách. Nó có thể là phản ứng trước một vấn đề trong mã—một số độ phức tạp hoặc điều gì đó không tự nhiên. Thay vì áp dụng một phép biến đổi tiêu chuẩn cho mã, các lập trình viên cảm nhận rằng gốc rễ của vấn đề nằm ở mô hình miền. Có thể một khái niệm bị thiếu. Có thể một số mối quan hệ là sai.

                                                                                                                                                                                  Trong một sự khác biệt so với quan điểm thông thường về việc tái cấu trúc mã, nhận thức này có thể xuất hiện khi mã trông gọn gàng, nếu ngôn ngữ của mô hình dường như không liên kết với các chuyên gia trong lĩnh vực, hoặc nếu các yêu cầu mới không khớp một cách tự nhiên. Việc tái cấu trúc có thể xảy ra do quá trình học hỏi, khi một lập trình viên đã hiểu sâu hơn nhận thấy cơ hội để có một mô hình rõ ràng hơn hoặc hữu ích hơn.

                                                                                                                                                                                  Nhìn thấy điểm gặp vấn đề thường là phần khó khăn và không chắc chắn nhất. Sau đó, các nhà phát triển có thể hệ thống hóa để tìm kiếm các yếu tố của một mô hình mới. Họ có thể cùng nhau động não với các đồng nghiệp và chuyên gia trong lĩnh vực. Họ có thể dựa vào kiến thức được hệ thống hóa được ghi lại dưới dạng các mẫu phân tích hoặc mẫu thiết kế.


                                                                                                                                                                                    Exploration Teams

                                                                                                                                                                                    Dù nguồn gốc của sự không hài lòng là gì, bước tiếp theo là tìm kiếm một sự tinh chỉnh để mô hình giao tiếp một cách rõ ràng và tự nhiên. Điều này có thể chỉ yêu cầu một thay đổi khiêm tốn mà ngay lập tức có thể thấy rõ và có thể thực hiện trong vài giờ. Trong trường hợp đó, sự thay đổi giống như việc tái cấu trúc truyền thống. Nhưng việc tìm kiếm một mô hình mới có thể cần nhiều thời gian hơn và sự tham gia của nhiều người hơn.

                                                                                                                                                                                    Những người khởi xướng sự thay đổi chọn một vài lập trình viên khác có khả năng tư duy tốt về loại vấn đề đó, những người biết về lĩnh vực đó, hoặc những người có kỹ năng lập mô hình mạnh. Nếu có những vấn đề tinh vi, họ đảm bảo rằng một chuyên gia lĩnh vực tham gia. Nhóm bốn hoặc năm người này đến một phòng hội nghị hoặc quán cà phê và động não trong khoảng nửa giờ đến một giờ rưỡi. Họ phác thảo sơ đồ UML; họ cố gắng đi qua các kịch bản bằng cách sử dụng các đối tượng. Họ đảm bảo rằng chuyên gia về chủ đề hiểu mô hình và thấy nó hữu ích. Khi họ tìm thấy điều gì đó mà họ hài lòng, họ quay lại và lập trình. Hoặc họ quyết định suy nghĩ thêm vài ngày và quay lại làm việc với thứ khác. Vài ngày sau, nhóm tái họp và thực hiện lại bài tập. Lần này họ tự tin hơn, đã cân nhắc những suy nghĩ trước đó, và họ đạt được một số kết luận. Họ quay trở lại máy tính của mình và lập trình thiết kế mới.

                                                                                                                                                                                    Có vài chìa khóa để giữ cho quá trình này hiệu quả.

                                                                                                                                                                                    • Quyết định tự chủ. Một nhóm nhỏ có thể được thành lập ngay lập tức để khám phá một vấn đề thiết kế. Nhóm có thể hoạt động trong vài ngày và sau đó tan rã. Không cần các cấu trúc tổ chức dài hạn và phức tạp.

                                                                                                                                                                                    • Phạm vi và giấc ngủ. Hai hoặc ba cuộc họp ngắn được cách nhau trong vài ngày nên tạo ra một thiết kế đáng để thử nghiệm. Kéo dài thời gian không giúp ích gì. Nếu bạn bị kẹt, có thể bạn đang đảm nhận quá nhiều một lúc. Hãy chọn một khía cạnh nhỏ hơn của thiết kế và tập trung vào đó.

                                                                                                                                                                                    • Thực hiện ngôn ngữ toàn diện. Việc liên kết các thành viên khác trong nhóm—đặc biệt là chuyên gia về vấn đề—trong buổi họp tư duy sẽ tạo ra cơ hội để thực hành và hoàn thiện ngôn ngữ toàn diện. Kết quả cuối cùng của nỗ lực này là sự tinh chỉnh ngôn ngữ mà các nhà phát triển ban đầu sẽ mang về và chính thức hóa trong mã.

                                                                                                                                                                                    Các chương trước trong cuốn sách này đã trình bày một số cuộc đối thoại trong đó các nhà phát triển và chuyên gia trong lĩnh vực khám phá những mô hình tốt hơn. Một buổi brainstorming toàn diện là năng động, không có cấu trúc và cực kỳ hiệu quả.


                                                                                                                                                                                      Prior Art

                                                                                                                                                                                      Không phải lúc nào cũng cần phải phát minh lại bánh xe. Quá trình động não để tìm ra những khái niệm còn thiếu và các mô hình tốt hơn có khả năng hấp thụ ý tưởng từ bất kỳ nguồn nào, kết hợp chúng với kiến thức địa phương, và tiếp tục nghiền ngẫm để tìm kiếm câu trả lời cho tình huống hiện tại.

                                                                                                                                                                                      Bạn có thể lấy ý tưởng từ sách và các nguồn kiến thức khác về lĩnh vực đó. Mặc dù những người trong ngành có thể chưa tạo ra một mô hình phù hợp để chạy phần mềm, họ có thể đã tổ chức các khái niệm và tìm ra một số trừu tượng hữu ích. Việc cung cấp kiến thức theo cách này dẫn đến những kết quả phong phú hơn, nhanh chóng hơn mà cũng có vẻ quen thuộc hơn với các chuyên gia trong lĩnh vực.

                                                                                                                                                                                      Đôi khi, bạn có thể rút kinh nghiệm từ người khác dưới dạng các mẫu phân tích. Loại thông tin này có một phần ảnh hưởng của việc đọc về miền, nhưng trong trường hợp này, nó được định hướng cụ thể cho phát triển phần mềm và nên được dựa trực tiếp trên kinh nghiệm triển khai phần mềm trong miền của bạn. Các mẫu phân tích có thể cung cấp cho bạn những khái niệm mô hình tinh tế và giúp bạn tránh được nhiều sai lầm. Nhưng chúng không cung cấp cho bạn một công thức nấu ăn. Chúng hỗ trợ quá trình xử lý kiến thức.

                                                                                                                                                                                      Khi các phần được ghép lại với nhau, các mối quan tâm về mô hình và thiết kế phải được xử lý song song. Một lần nữa, điều này không nhất thiết có nghĩa là phải sáng tạo mọi thứ từ đầu. Các mẫu thiết kế thường có thể được sử dụng trong tầng miền khi chúng phù hợp với cả nhu cầu thực hiện và khái niệm mô hình.

                                                                                                                                                                                      Tương tự, khi một hình thức chính thức phổ biến, chẳng hạn như số học hoặc logic lượng từ, phù hợp với một phần nào đó của miền, bạn có thể tách phần đó ra và điều chỉnh các quy tắc của hệ thống chính thức. Điều này cung cấp các mô hình rất chặt chẽ và dễ hiểu.


                                                                                                                                                                                        A Design for Developers

                                                                                                                                                                                        Phần mềm không chỉ dành cho người dùng. Nó cũng dành cho các lập trình viên. Các lập trình viên phải tích hợp mã với các phần khác của hệ thống. Trong một quy trình lặp đi lặp lại, các lập trình viên thay đổi mã nhiều lần. Việc tái cấu trúc để có cái nhìn sâu sắc hơn không chỉ dẫn đến mà còn hưởng lợi từ một thiết kế linh hoạt.

                                                                                                                                                                                        Một thiết kế linh hoạt truyền đạt được ý định của nó. Thiết kế giúp dễ dàng dự đoán tác động của việc chạy mã—và do đó dễ dàng dự đoán hậu quả của việc thay đổi nó. Một thiết kế linh hoạt giúp hạn chế quá tải tâm lý, chủ yếu bằng cách giảm thiểu sự phụ thuộc và tác động bên ngoài. Nó dựa trên một mô hình sâu sắc về miền mà chỉ chi tiết ở những nơi quan trọng nhất đối với người dùng. Điều này tạo ra sự linh hoạt ở những nơi thay đổi là phổ biến nhất, và sự đơn giản ở những nơi khác.


                                                                                                                                                                                          Timing

                                                                                                                                                                                          "Nếu bạn chờ đợi cho đến khi có thể đưa ra một sự biện minh hoàn chỉnh cho một thay đổi, bạn đã chờ đợi quá lâu. Dự án của bạn đã chịu chi phí lớn, và những thay đổi bị hoãn lại sẽ khó thực hiện hơn vì mã mục tiêu sẽ trở nên phức tạp hơn và gắn bó hơn với các mã khác."

                                                                                                                                                                                          Liên tục tái cấu trúc đã trở thành một "thực tiễn tốt nhất", nhưng hầu hết các nhóm dự án vẫn còn quá thận trọng về điều này. Họ thấy rủi ro của việc thay đổi mã và chi phí thời gian của lập trình viên để thực hiện một thay đổi; nhưng điều khó thấy hơn là rủi ro của việc giữ lại thiết kế không hợp lý và chi phí phải làm việc xung quanh thiết kế đó. Các lập trình viên muốn tái cấu trúc thường được yêu cầu phải biện minh cho quyết định đó. Dù điều này có vẻ hợp lý, nhưng nó làm cho một điều đã khó khăn trở nên khó khăn hơn gấp bội, và thường khiến việc tái cấu trúc bị kìm hãm (hoặc buộc nó phải diễn ra âm thầm). Phát triển phần mềm không phải là một quá trình có thể đoán định đến mức mà lợi ích của một thay đổi hay chi phí của việc không thực hiện thay đổi có thể được tính toán chính xác.

                                                                                                                                                                                          Việc tái cấu trúc để đạt được cái nhìn sâu sắc hơn cần trở thành một phần của quá trình khám phá liên tục về chủ đề của miền, việc giáo dục các nhà phát triển, và sự gặp gỡ giữa các nhà phát triển và các chuyên gia trong miền. Do đó, hãy tái cấu trúc khi

                                                                                                                                                                                          • Thiết kế không phản ánh sự hiểu biết hiện tại của đội về miền.

                                                                                                                                                                                          • Các khái niệm quan trọng được thể hiện một cách ngầm trong thiết kế (và bạn thấy cách để làm cho chúng trở nên minh bạch); hoặc

                                                                                                                                                                                          • Bạn thấy có cơ hội để làm cho một phần quan trọng của thiết kế trở nên tốt hơn.

                                                                                                                                                                                          Thái độ hung hăng này không biện minh cho bất kỳ sự thay đổi nào vào bất kỳ thời điểm nào. Đừng tái cấu trúc vào ngày trước khi phát hành. Đừng giới thiệu những "thiết kế linh hoạt" chỉ là màn trình diễn kỹ thuật nhưng lại không đi vào cốt lõi của miền. Đừng giới thiệu một "mô hình sâu hơn" mà bạn không thể thuyết phục một chuyên gia trong miền sử dụng, dù nó có tinh tế đến đâu. Đừng tuyệt đối hóa mọi thứ, nhưng hãy thúc đẩy vượt ra ngoài vùng an toàn theo hướng ưu tiên tái cấu trúc.


                                                                                                                                                                                            Crisis as Opportunity

                                                                                                                                                                                            Trong hơn một thế kỷ sau khi Charles Darwin giới thiệu nó, mô hình tiêu chuẩn của sự tiến hóa là các loài thay đổi dần dần, một cách có phần ổn định, theo thời gian. Đột nhiên, vào những năm 1970, mô hình này đã bị thay thế bởi mô hình "cân bằng gián đoạn". Trong cái nhìn mở rộng này về sự tiến hóa, những khoảng thời gian dài của sự thay đổi dần dần hoặc ổn định bị gián đoạn bởi những cơn bùng nổ thay đổi nhanh chóng tương đối ngắn. Sau đó, mọi thứ trở lại trạng thái cân bằng mới. Phát triển phần mềm có một hướng đi có chủ ý mà sự tiến hóa thiếu (dù điều này có thể không rõ ràng trong một số dự án), nhưng tuy nhiên, nó vẫn tuân theo nhịp điệu loại này.

                                                                                                                                                                                            Mô tả cổ điển về refactoring nghe có vẻ rất ổn định. Việc refactoring để đạt được cái nhìn sâu sắc hơn thường không như vậy. Một giai đoạn tinh chỉnh liên tục của một mô hình có thể đột ngột đưa bạn đến một cái nhìn sâu sắc làm lung lay mọi thứ. Những bước đột phá này không xảy ra mỗi ngày, nhưng một tỷ lệ lớn các thay đổi dẫn đến một mô hình sâu sắc và thiết kế linh hoạt xuất phát từ chúng.

                                                                                                                                                                                            Một tình huống như vậy thường không giống như một cơ hội; nó có vẻ như một cuộc khủng hoảng hơn. Đột nhiên có một sự thiếu sót rõ ràng trong mô hình. Có một lỗ hổng lớn trong những gì nó có thể diễn đạt, hoặc một lĩnh vực quan trọng nào đó mà nó không rõ ràng. Có thể nó đưa ra những tuyên bố hoàn toàn sai.

                                                                                                                                                                                            Điều này có nghĩa là đội đã đạt được một cấp độ hiểu biết mới. Từ góc nhìn cao hơn hiện tại, mô hình cũ trông kém hơn. Từ góc nhìn đó, họ có thể hình dung một mô hình tốt hơn nhiều.

                                                                                                                                                                                            Quá trình tái cấu trúc để hướng tới cái nhìn sâu sắc hơn là một quá trình liên tục. Những khái niệm ngầm được nhận ra và trở nên rõ ràng. Các phần của thiết kế trở nên linh hoạt hơn, có thể theo phong cách khai báo. Phát triển đột ngột tiến sát đến một bước đột phá và lao vào một mô hình sâu sắc—và sau đó, quá trình hoàn thiện ổn định lại bắt đầu lần nữa.


                                                                                                                                                                                              Part IV: Strategic Design

                                                                                                                                                                                              Khi các hệ thống trở nên quá phức tạp để hiểu hoàn toàn ở cấp độ các đối tượng cá biệt, chúng ta cần những kỹ thuật để thao tác và hiểu các mô hình lớn. Phần này của cuốn sách trình bày các nguyên tắc cho phép quá trình mô hình hóa mở rộng đến những miền rất phức tạp. Hầu hết những quyết định như vậy phải được thực hiện ở cấp đội nhóm hoặc thậm chí được thương lượng giữa các đội nhóm. Đây là những quyết định mà thiết kế và chính trị thường giao nhau.

                                                                                                                                                                                              Mục tiêu của hệ thống doanh nghiệp tham vọng nhất là một hệ thống tích hợp chặt chẽ trải rộng trên toàn bộ doanh nghiệp. Tuy nhiên, toàn bộ mô hình kinh doanh cho hầu hết bất kỳ tổ chức nào như vậy đều quá lớn và phức tạp để quản lý hoặc thậm chí hiểu như một đơn vị duy nhất. Hệ thống cần phải được chia thành các phần nhỏ hơn, cả về khái niệm lẫn triển khai. Thách thức là thực hiện sự mô-đun này mà không mất đi những lợi ích của sự tích hợp, cho phép các phần khác nhau của hệ thống hoạt động cùng nhau để hỗ trợ việc phối hợp các hoạt động kinh doanh khác nhau. Một mô hình miền đơn thể, toàn diện sẽ trở nên cồng kềnh và chứa đầy những sự trùng lặp và mâu thuẫn tinh vi. Một tập hợp các tiểu hệ thống nhỏ, độc nhất liên kết với nhau bằng các giao diện tạm thời sẽ thiếu sức mạnh để giải quyết các vấn đề trên toàn doanh nghiệp và cho phép các vấn đề nhất quán phát sinh ở mỗi điểm tích hợp. Những cạm bẫy của cả hai cực đoan có thể được tránh khỏi bằng một chiến lược thiết kế có hệ thống và phát triển.

                                                                                                                                                                                              Ngay cả ở quy mô này, thiết kế dựa trên miền không tạo ra các mô hình không liên kết với việc triển khai. Mỗi quyết định phải có tác động trực tiếp đến phát triển hệ thống, nếu không thì nó trở nên không liên quan. Các nguyên tắc thiết kế chiến lược phải hướng dẫn các quyết định thiết kế để giảm sự phụ thuộc lẫn nhau của các phần và cải thiện sự rõ ràng mà không làm mất đi tính tương tác và hợp tác quan trọng. Chúng phải tập trung vào mô hình để nắm bắt lõi khái niệm của hệ thống, "tầm nhìn" của hệ thống. Và chúng phải làm tất cả những điều này mà không làm trì trệ dự án. Để giúp đạt được những mục tiêu này, Phần IV khám phá ba chủ đề rộng lớn: bối cảnh, tinh chế và cấu trúc quy mô lớn.

                                                                                                                                                                                              Ngữ cảnh, nguyên tắc ít hiển nhiên nhất, thực ra lại là nguyên tắc cơ bản nhất. Một mô hình thành công, dù lớn hay nhỏ, phải nhất quán theo logic ở mọi nơi, không có định nghĩa mâu thuẫn hoặc chồng chéo. Các hệ thống doanh nghiệp đôi khi tích hợp các tiểu hệ thống với nguồn gốc khác nhau hoặc có các ứng dụng khác biệt đến mức rất ít trong miền được nhìn nhận cùng một cách. Có thể yêu cầu quá nhiều để thống nhất các mô hình ngầm hiểu trong những phần không liên quan này. Bằng cách định nghĩa rõ ràng một NGỮ CẢNH HẠN CHẾ trong đó một mô hình áp dụng và sau đó, khi cần thiết, xác định mối quan hệ của nó với các ngữ cảnh khác, nhà mô hình có thể tránh làm sai lệch mô hình.

                                                                                                                                                                                              Chưng cất giúp giảm bớt sự lộn xộn và tập trung sự chú ý một cách phù hợp. Thường thì một lượng lớn nỗ lực được dành cho các vấn đề ngoại vi trong lĩnh vực. Mô hình tổng thể của lĩnh vực cần làm nổi bật những khía cạnh có giá trị và đặc biệt nhất của hệ thống của bạn và được cấu trúc để phần đó có sức mạnh tối đa. Trong khi một số thành phần hỗ trợ là rất quan trọng, chúng phải được đặt vào bối cảnh phù hợp. Sự tập trung này không chỉ giúp hướng nỗ lực vào các phần thiết yếu của hệ thống mà còn giữ cho tầm nhìn của hệ thống không bị lạc lối. Chưng cất chiến lược có thể mang lại sự rõ ràng cho một mô hình lớn. Và với cái nhìn rõ ràng hơn, thiết kế của LĨNH VỰC CỐT LÕI có thể trở nên hữu ích hơn.

                                                                                                                                                                                              Cấu trúc quy mô lớn hoàn chỉnh bức tranh. Trong một mô hình rất phức tạp, bạn có thể không nhìn thấy rừng vì những cái cây. Việc chưng cất giúp tập trung sự chú ý vào cốt lõi và trình bày các yếu tố khác trong vai trò hỗ trợ của chúng, nhưng các mối quan hệ vẫn có thể quá rối rắm mà không có một chủ đề tổng thể, áp dụng một số yếu tố và mô hình thiết kế trên toàn hệ thống. Tôi sẽ đưa ra cái nhìn tổng quan về một vài phương pháp cấu trúc quy mô lớn và sau đó đi sâu vào một mô hình như vậy, CÁC LỚP TRÁCH NHIỆM, để khám phá những hệ quả của việc sử dụng cấu trúc như vậy. Những cấu trúc cụ thể được thảo luận chỉ là ví dụ; chúng không phải là một danh mục toàn diện. Những cái mới nên được phát minh khi cần thiết, hoặc những cái này nên được điều chỉnh, thông qua một quá trình THỨ TỰ TIẾN HÓA. Một cấu trúc như vậy có thể mang lại sự đồng nhất cho thiết kế, thúc đẩy phát triển và cải thiện sự tích hợp.

                                                                                                                                                                                              Ba nguyên tắc này, có ích khi được sử dụng riêng lẻ nhưng đặc biệt mạnh mẽ khi kết hợp lại với nhau, giúp tạo ra những thiết kế tốt—ngay cả trong một hệ thống phức tạp mà không ai hoàn toàn hiểu rõ. Cấu trúc quy mô lớn mang lại sự nhất quán cho các phần khác nhau để giúp cho chúng hòa hợp với nhau. Cấu trúc và tinh lọc làm cho mối quan hệ phức tạp giữa các phần trở nên dễ hiểu trong khi vẫn giữ được cái nhìn tổng thể. CÁC NGHĨA HẠN cho phép công việc diễn ra ở các phần khác nhau mà không làm xáo trộn mô hình hoặc vô tình làm phân mảnh nó. Việc thêm những khái niệm này vào NGÔN NGỮ PHỔ BIẾN của nhóm giúp các nhà phát triển tìm ra giải pháp của riêng họ.


                                                                                                                                                                                                Chapter Fourteen. Maintaining Model Integrity

                                                                                                                                                                                                Tôi từng làm việc trong một dự án mà nhiều nhóm làm việc song song trên một hệ thống mới lớn. Một ngày nọ, nhóm làm việc trên mô-đun lập hóa đơn khách hàng đã sẵn sàng để triển khai một đối tượng mà họ gọi là Charge, khi họ phát hiện ra rằng một nhóm khác đã xây dựng một cái rồi. Một cách chăm chỉ, họ đã cố gắng tái sử dụng đối tượng hiện có. Họ phát hiện ra rằng nó không có "mã chi phí," vì vậy họ đã thêm vào. Nó đã có thuộc tính "số tiền đã ghi nhận" mà họ cần. Họ đã dự định gọi nó là "số tiền phải thu," nhưng—tên gọi là gì?—họ đã thay đổi nó. Thêm một vài phương thức và liên kết nữa, họ đã có cái mà họ muốn, mà không làm phiền đến những gì đã có. Họ đã phải bỏ qua nhiều liên kết mà họ không cần, nhưng mô-đun ứng dụng của họ vẫn chạy.

                                                                                                                                                                                                Vài ngày sau, những vấn đề bí ẩn xuất hiện trong mô-đun ứng dụng thanh toán hóa đơn mà Charge ban đầu đã được viết. Những Charge lạ lùng xuất hiện mà không ai nhớ đã nhập và không có ý nghĩa gì. Chương trình bắt đầu gặp sự cố khi một số chức năng được sử dụng, đặc biệt là báo cáo thuế tính đến tháng. Cuộc điều tra cho thấy rằng sự cố xảy ra khi một chức năng được sử dụng để tổng hợp số tiền có thể khấu trừ cho tất cả các khoản thanh toán của tháng hiện tại. Các bản ghi bí ẩn không có giá trị trong trường "tỷ lệ khấu trừ", mặc dù việc xác thực ứng dụng nhập dữ liệu yêu cầu điều này và thậm chí còn đặt giá trị mặc định.

                                                                                                                                                                                                Vấn đề là hai nhóm này có những mô hình khác nhau, nhưng họ không nhận ra điều đó, và không có quy trình nào được thiết lập để phát hiện ra điều này. Mỗi nhóm đều đưa ra những giả định về bản chất của một khoản phí mà cho họ là hữu ích trong bối cảnh của họ (thu tiền từ khách hàng so với thanh toán cho nhà cung cấp). Khi mã của họ được kết hợp mà không giải quyết được những mâu thuẫn này, kết quả là phần mềm không đáng tin cậy.

                                                                                                                                                                                                Nếu họ chỉ nhận thức rõ hơn về thực tế này, họ có thể đã quyết định một cách có ý thức cách giải quyết vấn đề. Điều đó có thể có nghĩa là làm việc cùng nhau để xây dựng một mô hình chung và sau đó viết một bộ kiểm tra tự động để ngăn chặn những bất ngờ trong tương lai. Hoặc có thể chỉ đơn giản là một thỏa thuận để phát triển các mô hình riêng biệt và giữ khoảng cách với mã của nhau. Dù sao đi nữa, mọi thứ bắt đầu bằng một thỏa thuận rõ ràng về các ranh giới mà trong đó mỗi mô hình áp dụng.

                                                                                                                                                                                                Họ đã làm gì khi biết về vấn đề này? Họ đã tạo ra các lớp Customer Charge và Supplier Charge riêng biệt và định nghĩa mỗi lớp theo nhu cầu của từng đội tương ứng. Vấn đề ngay lập tức đã được giải quyết, họ quay lại làm mọi thứ như trước đây. Ồ, thật tiếc.

                                                                                                                                                                                                Mặc dù chúng ta hiếm khi nghĩ đến một cách rõ ràng, yêu cầu cơ bản nhất của một mô hình là nó phải được nhất quán nội bộ; nghĩa là các thuật ngữ của nó luôn có cùng một ý nghĩa, và nó không chứa các quy tắc mâu thuẫn. Tính nhất quán nội bộ của một mô hình, sao cho mỗi thuật ngữ là không mơ hồ và không có quy tắc nào mâu thuẫn, được gọi là sự thống nhất. Một mô hình là vô nghĩa nếu không nhất quán về mặt logic. Trong một thế giới lý tưởng, chúng ta sẽ có một mô hình duy nhất bao trùm toàn bộ lĩnh vực của doanh nghiệp. Mô hình này sẽ được thống nhất, không có bất kỳ định nghĩa mâu thuẫn hoặc chồng chéo nào về các thuật ngữ. Mọi tuyên bố logic về lĩnh vực này sẽ là nhất quán.

                                                                                                                                                                                                Nhưng thế giới phát triển hệ thống lớn không phải là thế giới lý tưởng. Để duy trì mức độ thống nhất đó trong toàn bộ hệ thống doanh nghiệp là một công việc phức tạp hơn nhiều so với giá trị thực của nó. Cần phải cho phép nhiều mô hình phát triển ở các phần khác nhau của hệ thống, nhưng chúng ta cần phải đưa ra những lựa chọn cẩn thận về các phần của hệ thống sẽ được cho phép khác biệt và mối quan hệ của chúng với nhau sẽ như thế nào. Chúng ta cần các phương pháp để giữ cho các phần quan trọng của mô hình được thống nhất chặt chẽ. Tất cả những điều này không xảy ra một cách tự nhiên hoặc chỉ bằng ý định tốt. Nó chỉ xảy ra thông qua các quyết định thiết kế có ý thức và thiết lập các quy trình cụ thể. Sự thống nhất hoàn toàn của mô hình miền cho một hệ thống lớn sẽ không khả thi hoặc hiệu quả về chi phí.

                                                                                                                                                                                                Đôi khi mọi người phản đối thực tế này. Hầu hết mọi người thấy giá phải trả mà nhiều mô hình gây ra bằng cách hạn chế tích hợp và làm cho việc giao tiếp trở nên khó khăn. Hơn nữa, việc có hơn một mô hình dường như có vẻ không thanh lịch. Sự kháng cự đối với nhiều mô hình đôi khi dẫn đến những nỗ lực rất tham vọng nhằm thống nhất tất cả phần mềm trong một dự án lớn dưới một mô hình duy nhất. Tôi biết mình cũng đã mắc lỗi trong loại vượt quá này. Nhưng hãy cân nhắc đến những rủi ro.

                                                                                                                                                                                                1. Quá nhiều sự thay thế di sản có thể được thử nghiệm cùng một lúc.

                                                                                                                                                                                                Các dự án lớn có thể bị chậm lại vì công tác phối hợp vượt quá khả năng của họ.

                                                                                                                                                                                                Các ứng dụng có yêu cầu chuyên biệt có thể phải sử dụng các mô hình không hoàn toàn đáp ứng nhu cầu của họ, buộc họ phải đưa hành vi sang nơi khác.

                                                                                                                                                                                                Ngược lại, cố gắng làm hài lòng mọi người bằng một mô hình duy nhất có thể dẫn đến những tùy chọn phức tạp khiến mô hình trở nên khó sử dụng.

                                                                                                                                                                                                Hơn nữa, sự khác biệt giữa các mô hình có khả năng xuất phát từ phân mảnh chính trị và các ưu tiên quản lý khác nhau cũng như từ các vấn đề kỹ thuật. Sự xuất hiện của các mô hình khác nhau có thể là kết quả của tổ chức đội ngũ và quy trình phát triển. Vì vậy, ngay cả khi không có yếu tố kỹ thuật nào ngăn cản việc tích hợp hoàn toàn, dự án vẫn có thể phải đối mặt với nhiều mô hình.

                                                                                                                                                                                                Xét rằng việc duy trì một mô hình thống nhất cho toàn bộ doanh nghiệp là không khả thi, chúng ta không cần phải để mình bị ảnh hưởng bởi các sự kiện. Thông qua sự kết hợp giữa các quyết định chủ động về những gì nên được thống nhất và sự công nhận thực tế về những gì không thống nhất, chúng ta có thể tạo ra một bức tranh rõ ràng và chia sẻ về tình hình. Với điều đó trong tay, chúng ta có thể bắt tay vào việc đảm bảo rằng các phần chúng ta muốn thống nhất vẫn giữ được như vậy, và các phần không thống nhất không gây ra sự nhầm lẫn hoặc làm hỏng.

                                                                                                                                                                                                Chúng ta cần một cách để đánh dấu ranh giới và mối quan hệ giữa các mô hình khác nhau. Chúng ta cần chọn chiến lược của mình một cách có ý thức và sau đó tuân theo chiến lược đó một cách nhất quán.

                                                                                                                                                                                                Chương này trình bày các kỹ thuật để nhận diện, giao tiếp và chọn lựa giới hạn của một mô hình và mối quan hệ của nó với các mô hình khác. Tất cả bắt đầu bằng việc lập bản đồ hiện trạng của dự án. MỘT NGỮ CẢNH HẠN CHẾ xác định phạm vi áp dụng của từng mô hình, trong khi BẢN ĐỒ NGỮ CẢNH cung cấp tổng quan toàn cầu về các ngữ cảnh của dự án và mối quan hệ giữa chúng. Việc giảm thiểu sự mơ hồ này sẽ tự nó thay đổi cách thức mọi thứ diễn ra trong dự án, nhưng điều đó chưa chắc là đủ. Khi chúng ta đã có một NGỮ CẢNH HẠN CHẾ, quá trình TÍCH HỢP LIÊN TỤC sẽ giữ cho mô hình thống nhất.

                                                                                                                                                                                                Sau đó, bắt đầu từ tình huống ổn định này, chúng ta có thể bắt đầu chuyển sang các chiến lược hiệu quả hơn cho việc GIỚI HẠN BỐI CẢNH và liên kết chúng, từ những bối cảnh liên quan chặt chẽ với CÔN KHE CHUNG đến những mô hình lỏng lẻo đi theo CON ĐƯỜNG RIÊNG của chúng.

                                                                                                                                                                                                Figure 14.1. A navigation map for model integrity patterns

                                                                                                                                                                                                graphics/14fig01.gif


                                                                                                                                                                                                  Bounded Context

                                                                                                                                                                                                  Các tế bào có thể tồn tại vì màng của chúng xác định cái gì ở bên trong và bên ngoài và xác định cái gì có thể đi qua.

                                                                                                                                                                                                  graphics/14inf01.gif

                                                                                                                                                                                                  Nhiều mô hình coexist trên các dự án lớn, và điều này hoạt động tốt trong nhiều trường hợp. Các mô hình khác nhau áp dụng trong các ngữ cảnh khác nhau. Ví dụ, bạn có thể phải tích hợp phần mềm mới của mình với một hệ thống bên ngoài mà đội của bạn không có quyền kiểm soát. Một tình huống như vậy có lẽ rõ ràng với mọi người như một ngữ cảnh khác biệt nơi mô hình đang phát triển không áp dụng, nhưng những tình huống khác có thể mơ hồ và gây nhầm lẫn hơn. Trong câu chuyện mà đã mở đầu chương này, hai đội đang làm việc trên các chức năng khác nhau cho cùng một hệ thống mới. Họ có đang làm việc trên cùng một mô hình không? Ý định của họ là chia sẻ ít nhất một phần những gì họ đã làm, nhưng không có ranh giới nào để cho họ biết họ đã chia sẻ điều gì hoặc không. Và họ không có quy trình nào để giữ cho một mô hình chung cùng nhau hoặc nhanh chóng phát hiện sự khác biệt. Họ nhận ra rằng họ đã khác biệt chỉ sau khi hành vi của hệ thống của họ đột ngột trở nên không thể đoán trước.

                                                                                                                                                                                                  Ngay cả một đội duy nhất cũng có thể có nhiều mô hình. Việc giao tiếp có thể bị thiếu, dẫn đến những diễn giải mơ hồ xung đột về mô hình. Mã cũ thường phản ánh một khái niệm trước đó về mô hình mà có sự khác biệt tinh tế so với mô hình hiện tại.

                                                                                                                                                                                                  Mọi người đều biết rằng định dạng dữ liệu của một hệ thống khác là khác nhau và cần phải chuyển đổi dữ liệu, nhưng đây chỉ là khía cạnh cơ học của vấn đề. Căn bản hơn là sự khác biệt về các mô hình ngầm hiểu trong hai hệ thống này. Khi sự khác biệt không phải với một hệ thống bên ngoài, mà nằm trong cùng một mã nguồn, thì khả năng được nhận ra càng thấp hơn. Tuy nhiên, điều này xảy ra trong tất cả các dự án lớn của nhóm.

                                                                                                                                                                                                  Nhiều mô hình đang hoạt động trong bất kỳ dự án lớn nào. Tuy nhiên, khi mã dựa trên các mô hình khác nhau được kết hợp, phần mềm trở nên có lỗi, không đáng tin cậy và khó hiểu. Giao tiếp giữa các thành viên trong nhóm trở nên rối rắm. Thường thì không rõ trong bối cảnh nào một mô hình không nên được áp dụng.

                                                                                                                                                                                                  Việc không giữ mọi thứ rõ ràng cuối cùng sẽ được tiết lộ khi mã chạy không hoạt động đúng, nhưng vấn đề bắt đầu từ cách tổ chức các nhóm và cách mọi người tương tác. Do đó, để làm rõ bối cảnh của một mô hình, chúng ta phải xem xét cả dự án và các sản phẩm cuối cùng của nó (mã nguồn, sơ đồ cơ sở dữ liệu, và vân vân).

                                                                                                                                                                                                  Một mô hình áp dụng trong một ngữ cảnh. Ngữ cảnh có thể là một phần nhất định của mã, hoặc công việc của một nhóm cụ thể. Đối với một mô hình được phát minh trong một phiên động não, ngữ cảnh có thể bị giới hạn trong cuộc trò chuyện đó. Ngữ cảnh của một mô hình được sử dụng trong một ví dụ trong cuốn sách này là phần ví dụ cụ thể đó và bất kỳ cuộc thảo luận nào về nó sau này. Ngữ cảnh của mô hình là bất kỳ tập hợp điều kiện nào phải áp dụng để có thể nói rằng các thuật ngữ trong một mô hình có ý nghĩa cụ thể.

                                                                                                                                                                                                  Để bắt đầu giải quyết các vấn đề của nhiều mô hình, chúng ta cần xác định rõ ràng phạm vi của một mô hình cụ thể như một phần giới hạn của hệ thống phần mềm, trong đó một mô hình duy nhất sẽ áp dụng và được giữ càng thống nhất càng tốt. Định nghĩa này cần phải được hòa hợp với tổ chức của nhóm.

                                                                                                                                                                                                  Vì vậy:

                                                                                                                                                                                                  Rõ ràng xác định bối cảnh mà mô hình áp dụng. Rõ ràng thiết lập ranh giới về tổ chức đội ngũ, việc sử dụng trong các phần cụ thể của ứng dụng, và các biểu hiện vật lý như mã nguồn và sơ đồ cơ sở dữ liệu. Duy trì mô hình hoàn toàn nhất quán trong những ranh giới này, nhưng đừng bị phân tâm hoặc bối rối bởi các vấn đề bên ngoài.

                                                                                                                                                                                                  MỘT BỐI CẢNH RÀNG BUỘC xác định phạm vi áp dụng của một mô hình cụ thể để các thành viên trong nhóm có sự hiểu biết rõ ràng và chung về những gì cần được nhất quán và cách nó liên quan đến các BỐI CẢNH khác. Trong BỐI CẢNH đó, hãy làm việc để giữ cho mô hình thống nhất về logic, nhưng đừng lo lắng về độ phù hợp bên ngoài các ranh giới đó. Trong các BỐI CẢNH khác, các mô hình khác sẽ áp dụng, với sự khác biệt về thuật ngữ, khái niệm và quy tắc, cũng như các phương ngữ của NGÔN NGỮ PHỔ BIẾN. Bằng cách vẽ một ranh giới rõ ràng, bạn có thể giữ cho mô hình thuần khiết, và do đó mạnh mẽ, nơi nó có thể áp dụng. Đồng thời, bạn tránh được sự nhầm lẫn khi chuyển sự chú ý sang các BỐI CẢNH khác. Việc tích hợp qua các ranh giới sẽ cần một số dịch thuật, mà bạn có thể phân tích một cách rõ ràng.


                                                                                                                                                                                                  BOUNDED CONTEXTS Are Not MODULES

                                                                                                                                                                                                  Các vấn đề đôi khi bị nhầm lẫn, nhưng đây là những mô hình khác nhau với những động lực khác nhau. Thật vậy, khi hai tập hợp đối tượng được nhận diện là tạo thành các mô hình khác nhau, chúng gần như luôn được đặt vào các MODULE riêng biệt. Việc làm như vậy giúp cung cấp các không gian tên khác nhau (cần thiết cho các NGỮ CẢNH khác nhau) và một số sự phân định.

                                                                                                                                                                                                  Nhưng CÁC MÔ-ĐUN cũng tổ chức các yếu tố trong một mô hình; chúng không nhất thiết truyền đạt ý định tách biệt CÁC NGỮ CẢNH. Các không gian tên riêng biệt mà CÁC MÔ-ĐUN tạo ra trong một NGỮ CẢNH GIỚI HẠN thực sự làm cho việc phát hiện phân mảnh mô hình ngẫu nhiên trở nên khó khăn hơn.

                                                                                                                                                                                                  Example
                                                                                                                                                                                                  Booking Context

                                                                                                                                                                                                  Một công ty vận chuyển có một dự án nội bộ để phát triển một ứng dụng mới cho việc đặt chỗ hàng hóa. Ứng dụng này sẽ được điều khiển bởi một mô hình đối tượng. BỐ TRÍ GIỚI HẠN nào mà mô hình này áp dụng? Để trả lời câu hỏi này, chúng ta phải xem xét những gì đang diễn ra trong dự án. Hãy ghi nhớ, đây là cái nhìn về dự án như nó đang có, chứ không phải như nó lý tưởng nên có.

                                                                                                                                                                                                  Một nhóm dự án đang làm việc trên ứng dụng đặt chỗ. Họ không được mong đợi sẽ chỉnh sửa các đối tượng mô hình, nhưng ứng dụng mà họ đang xây dựng phải hiển thị và thao tác với những đối tượng đó. Nhóm này là một người tiêu thụ của mô hình. Mô hình hợp lệ trong ứng dụng (người tiêu thụ chính của nó), và do đó ứng dụng đặt chỗ nằm trong phạm vi.

                                                                                                                                                                                                  Các booking hoàn tất phải được truyền qua hệ thống theo dõi hàng hóa cũ. Một quyết định đã được đưa ra từ trước rằng mô hình mới sẽ khác với mô hình cũ, do đó hệ thống theo dõi hàng hóa cũ nằm ngoài ranh giới. Việc dịch chuyển cần thiết giữa mô hình mới và mô hình cũ sẽ thuộc trách nhiệm của nhóm bảo trì hệ thống cũ. Cơ chế dịch chuyển không được điều khiển bởi mô hình. Nó không nằm trong BỐ CỤC RÀNH MẠCH. (Nó là một phần của ranh giới tự nó, sẽ được thảo luận trong BẢN ĐỒ NGĂN.) Thật tốt khi việc dịch chuyển nằm ngoài BỐ CỤC (không dựa trên mô hình). Sẽ không thực tế khi yêu cầu nhóm cũ tận dụng mô hình một cách thực sự vì công việc chính của họ nằm ngoài BỐ CỤC.

                                                                                                                                                                                                  Nhóm chịu trách nhiệm về mô hình quản lý toàn bộ vòng đời của từng đối tượng, bao gồm cả việc lưu trữ. Bởi vì nhóm này kiểm soát sơ đồ cơ sở dữ liệu, họ đã cố ý giữ cho việc ánh xạ đối tượng - quan hệ được đơn giản. Nói cách khác, sơ đồ đang được điều khiển bởi mô hình và do đó nằm trong giới hạn.

                                                                                                                                                                                                  Một nhóm nữa đang làm việc trên một mô hình và ứng dụng để lập lịch cho các chuyến đi của tàu chở hàng. Các nhóm lập lịch và đặt chỗ đã được khởi xướng cùng nhau, và cả hai nhóm đã dự định tạo ra một hệ thống thống nhất. Hai nhóm đã phối hợp một cách thoải mái với nhau, và họ thỉnh thoảng chia sẻ đối tượng, nhưng họ không có kế hoạch rõ ràng cho việc này. Họ không làm việc trong cùng một BỐI CẢNH GIỚI HẠN. Đây là một rủi ro, vì họ không nghĩ rằng mình đang làm việc trên các mô hình riêng biệt. Đến mức độ họ tích hợp, sẽ có vấn đề trừ khi họ thiết lập quy trình để quản lý tình huống. (KERNEL CHUNG, được thảo luận sau trong chương này, có thể là một sự lựa chọn tốt.) Bước đầu tiên, tuy nhiên, là nhận ra tình huống như nó vốn có. Họ không ở trong cùng một BỐI CẢNH và nên ngừng cố gắng chia sẻ mã cho đến khi có một số thay đổi được thực hiện.

                                                                                                                                                                                                  BỐI CẢNH ĐƯỢC RÀNG BUỘC này bao gồm tất cả các khía cạnh của hệ thống được điều khiển bởi mô hình cụ thể này: các đối tượng mô hình, lược đồ cơ sở dữ liệu lưu trữ các đối tượng mô hình và ứng dụng đặt chỗ. Hai đội ngũ làm việc chủ yếu trong BỐI CẢNH này: đội ngũ mô hình và đội ngũ ứng dụng. Thông tin cần được trao đổi với hệ thống theo dõi di sản, và đội ngũ di sản có trách nhiệm chính trong việc dịch ở ranh giới này, với sự hợp tác từ đội ngũ mô hình. Không có mối quan hệ được xác định rõ giữa mô hình đặt chỗ và mô hình lịch trình chuyến đi, và việc định nghĩa mối quan hệ đó nên là một trong những hành động đầu tiên của các đội ngũ đó. Trong thời gian chờ đợi, họ nên cẩn thận khi chia sẻ mã hoặc dữ liệu.

                                                                                                                                                                                                  Vậy, lợi ích của việc xác định BOUNDED CONTEXT này là gì? Đối với các nhóm làm việc trong CONTEXT: sự rõ ràng. Hai nhóm đó biết rằng họ phải giữ nhất quán với một mô hình. Họ đưa ra quyết định thiết kế dựa trên kiến thức đó và theo dõi những sự rạn nứt. Đối với các nhóm bên ngoài: tự do. Họ không phải đi vào vùng xám, không sử dụng cùng một mô hình, nhưng lại cảm thấy như họ nên làm như vậy. Nhưng lợi ích rõ ràng nhất trong trường hợp cụ thể này có lẽ là nhận ra rủi ro của việc chia sẻ không chính thức giữa nhóm mô hình đặt chỗ và nhóm lịch trình chuyến đi. Để tránh các vấn đề, họ thực sự cần phải quyết định về sự trao đổi chi phí/lợi ích của việc chia sẻ và thiết lập các quy trình để làm cho nó hiệu quả. Điều này sẽ không xảy ra trừ khi mọi người hiểu rõ ranh giới của các mô hình ngữ cảnh.

                                                                                                                                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                  Tất nhiên, các ranh giới là những nơi đặc biệt. Mối quan hệ giữa một BỐI CẢNH HẠN CHẾ và các bối cảnh lân cận cần được chú ý và chăm sóc. BẢN ĐỒ BỐI CẢNH phác thảo lãnh thổ, cung cấp cái nhìn tổng quan về các BỐI CẢNH và các kết nối của chúng, trong khi một số mô hình xác định bản chất của các mối quan hệ khác nhau giữa các BỐI CẢNH. Và một quy trình TÍCH HỢP LIÊN TỤC duy trì sự thống nhất của mô hình trong một BỐI CẢNH HẠN CHẾ.

                                                                                                                                                                                                  Nhưng trước khi tiến hành tất cả những điều đó, việc thống nhất của một mô hình trông như thế nào khi nó bắt đầu bị phá vỡ? Làm thế nào để bạn nhận ra những mảnh vỡ về khái niệm?

                                                                                                                                                                                                  Recognizing Splinters Within a BOUNDED CONTEXT

                                                                                                                                                                                                  Nhiều triệu chứng có thể chỉ ra sự khác biệt giữa các mô hình chưa được nhận diện. Một số biểu hiện rõ ràng nhất là khi các giao diện mã hóa không khớp với nhau. Một cách tinh tế hơn, hành vi không mong đợi là dấu hiệu có khả năng xảy ra. Quy trình TÍCH HỢP LIÊN TỤC với các bài kiểm tra tự động có thể giúp phát hiện những loại vấn đề này. Nhưng cảnh báo sớm thường là sự nhầm lẫn về ngôn ngữ.

                                                                                                                                                                                                  Kết hợp các yếu tố từ những mô hình khác nhau gây ra hai loại vấn đề: khái niệm trùng lặp và từ giả. Khái niệm trùng lặp có nghĩa là có hai phần tử mô hình (và các thực hiện kèm theo) thực sự đại diện cho cùng một khái niệm. Mỗi khi thông tin này thay đổi, nó phải được cập nhật ở hai nơi với các phép chuyển đổi. Mỗi khi kiến thức mới dẫn đến sự thay đổi ở một trong các đối tượng, đối tượng kia cũng phải được phân tích lại và thay đổi theo. Nhưng sự phân tích lại không xảy ra trong thực tế, nên kết quả là có hai phiên bản của cùng một khái niệm theo những quy tắc khác nhau và thậm chí có dữ liệu khác nhau. Hơn thế nữa, các thành viên trong nhóm phải học không chỉ một mà hai cách thực hiện cùng một việc, cùng với tất cả các cách họ được đồng bộ hóa.

                                                                                                                                                                                                  Các từ giả giống có thể ít phổ biến hơn một chút, nhưng lại gây hại một cách tinh vi hơn. Điều này xảy ra khi hai người sử dụng cùng một thuật ngữ (hoặc đối tượng đã triển khai) nghĩ rằng họ đang nói về cùng một điều, nhưng thực sự lại không phải như vậy. Ví dụ ở đầu chương này (hai hoạt động kinh doanh khác nhau đều gọi là Charge) là điển hình, nhưng xung đột có thể tinh vi hơn khi hai định nghĩa thực sự liên quan đến cùng một khía cạnh trong miền, nhưng đã được khái niệm hóa theo những cách hơi khác nhau. Các từ giả giống dẫn đến những đội phát triển chồng chéo lên mã của nhau, cơ sở dữ liệu có những mâu thuẫn kỳ lạ, và sự nhầm lẫn trong giao tiếp trong đội. Thuật ngữ từ giả giống thường được áp dụng cho các ngôn ngữ tự nhiên. Ví dụ, những người nói tiếng Anh học tiếng Tây Ban Nha thường sử dụng sai từ embarazada. Từ này không có nghĩa là "hổ thẹn"; nó có nghĩa là "có thai." Ôi.

                                                                                                                                                                                                  Khi bạn phát hiện ra những vấn đề này, đội ngũ của bạn sẽ phải đưa ra quyết định. Bạn có thể muốn hợp nhất lại mô hình và tinh chỉnh các quy trình để ngăn chặn sự phân mảnh. Hoặc sự phân mảnh có thể là kết quả của những nhóm muốn phát triển mô hình theo những hướng khác nhau vì những lý do chính đáng, và bạn có thể quyết định để họ phát triển một cách độc lập. Việc giải quyết những vấn đề này là chủ đề của các mẫu còn lại trong chương này.


                                                                                                                                                                                                    Continuous Integration

                                                                                                                                                                                                    graphics/14inf02.gif

                                                                                                                                                                                                    Sau khi định nghĩa một BỐI CẢNH HẠN CHẾ, chúng ta phải giữ cho nó vững chắc.

                                                                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                    Khi một số người làm việc trong cùng một BỐI CẢNH ĐƯỢC GIỚI HẠN, có xu hướng mạnh mẽ để mô hình bị phân mảnh. Đội ngũ càng lớn, vấn đề càng lớn, nhưng ngay cả ba hoặc bốn người cũng có thể gặp phải những vấn đề nghiêm trọng. Tuy nhiên, việc chia nhỏ hệ thống thành các BỐI CẢNH ngày càng nhỏ hơn cuối cùng sẽ làm mất đi mức độ tích hợp và sự đồng nhất quý giá.

                                                                                                                                                                                                    Đôi khi các nhà phát triển không hoàn toàn hiểu được ý định của một đối tượng hoặc tương tác nào đó được mô hình hóa bởi người khác, và họ thay đổi nó theo cách làm cho nó không còn khả dụng cho mục đích ban đầu. Đôi khi họ không nhận ra rằng các khái niệm mà họ đang làm việc đã được hiện hữu ở một phần khác của mô hình và họ lặp lại (một cách không chính xác) những khái niệm và hành vi đó. Đôi khi họ biết đến những biểu hiện khác nhưng sợ can thiệp vào chúng, vì lo sợ làm hỏng chức năng hiện có, và vì vậy họ tiếp tục nhân đôi các khái niệm và chức năng.

                                                                                                                                                                                                    Rất khó để duy trì mức độ giao tiếp cần thiết để phát triển một hệ thống thống nhất bất kỳ quy mô nào. Chúng ta cần cách thức để tăng cường giao tiếp và giảm bớt độ phức tạp. Chúng ta cũng cần những mạng lưới an toàn ngăn chặn hành vi quá thận trọng, chẳng hạn như các nhà phát triển sao chép tính năng vì họ sợ sẽ làm hỏng mã hiện có.

                                                                                                                                                                                                    Trong môi trường này, Lập trình Cực đoan (XP) thực sự phát huy được giá trị của nó. Nhiều thực hành của XP nhằm giải quyết vấn đề cụ thể này là duy trì một thiết kế nhất quán đang bị thay đổi liên tục bởi nhiều người. XP ở dạng thuần khiết nhất là rất phù hợp để duy trì tính toàn vẹn của mô hình trong một BỐC BÓ HẠN chế đơn. Tuy nhiên, có sử dụng XP hay không, điều quan trọng là phải có một quy trình TÍCH HỢP LIÊN TỤC nào đó.

                                                                                                                                                                                                    TÍCH HỢP LIÊN TỤC có nghĩa là tất cả công việc trong bối cảnh này được hợp nhất và làm cho nhất quán đủ thường xuyên đến mức khi có sự tách rời xảy ra, chúng sẽ được phát hiện và sửa chữa kịp thời. TÍCH HỢP LIÊN TỤC, giống như mọi thứ khác trong thiết kế hướng theo miền, hoạt động ở hai cấp độ: (1) sự tích hợp các khái niệm mô hình và (2) sự tích hợp của việc triển khai.

                                                                                                                                                                                                    Các khái niệm được tích hợp thông qua việc giao tiếp liên tục giữa các thành viên trong nhóm. Nhóm phải nuôi dưỡng một sự hiểu biết chung về mô hình đang thay đổi không ngừng. Nhiều thực hành giúp ích, nhưng điều cơ bản nhất là liên tục xác định và thống nhất NGÔN NGỮ PHỔ BIẾN. Trong khi đó, các tài liệu triển khai đang được tích hợp thông qua một quy trình kết hợp/xây dựng/kiểm tra có hệ thống, điều này giúp phát hiện sớm các vấn đề phát sinh từ mô hình. Nhiều quy trình tích hợp được sử dụng, nhưng hầu hết những quy trình hiệu quả đều chia sẻ những đặc điểm này:

                                                                                                                                                                                                    • Kỹ thuật gộp/xây dựng từng bước, có thể lặp lại.

                                                                                                                                                                                                    • Bộ kiểm thử tự động; và

                                                                                                                                                                                                    • "Các quy tắc đặt ra một giới hạn tối đa hợp lý nhỏ về thời gian tồn tại của những thay đổi không được tích hợp."

                                                                                                                                                                                                    Mặt khác của đồng xu trong các quy trình hiệu quả, mặc dù hiếm khi được bao gồm chính thức, là sự tích hợp về mặt khái niệm.

                                                                                                                                                                                                    • Liên tục sử dụng NGÔN NGỮ PHỔ BIẾN trong các cuộc thảo luận về mô hình và ứng dụng.

                                                                                                                                                                                                    Hầu hết các dự án Agile có ít nhất là các lần hợp nhất mã thay đổi của mỗi lập trình viên hàng ngày. Tần suất này có thể được điều chỉnh theo nhịp độ thay đổi, miễn là bất kỳ thay đổi nào chưa được tích hợp sẽ được hợp nhất trước khi một lượng công việc không tương thích đáng kể được thực hiện bởi các thành viên trong nhóm khác.

                                                                                                                                                                                                    Trong một THIẾT KẾ DỰA TRÊN MÔ HÌNH, sự tích hợp các khái niệm làm cho việc tích hợp thực thi trở nên suôn sẻ, trong khi tích hợp thực thi chứng minh tính hợp lệ và tính nhất quán của mô hình và phơi bày những vết nứt.

                                                                                                                                                                                                    Do đó:

                                                                                                                                                                                                    Thiết lập một quy trình gộp tất cả mã nguồn và các biến thể thực hiện khác một cách thường xuyên, với các bài kiểm tra tự động để nhanh chóng phát hiện sự phân mảnh. Liên tục sử dụng NGÔN NGỮ PHỔ BIẾN để rèn giũa một cái nhìn chung về mô hình khi các khái niệm phát triển trong đầu từng người khác nhau.

                                                                                                                                                                                                    Cuối cùng, đừng làm công việc trở nên phức tạp hơn mức cần thiết. Tích hợp liên tục là điều cần thiết chỉ trong một BỐI CẢNH ĐƯỢC GIỚI HẠN. Các vấn đề thiết kế liên quan đến các BỐI CẢNH lân cận, bao gồm cả việc dịch thuật, không cần phải giải quyết với cùng một tốc độ.

                                                                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                    TÍCH HỢP LIÊN TỤC sẽ được áp dụng trong bất kỳ BỐI CẢNH GIỚI HẠN cá nhân nào lớn hơn một nhiệm vụ của hai người. Nó duy trì tính toàn vẹn của mô hình đơn lẻ đó. Khi nhiều BỐI CẢNH GIỚI HẠN cùng tồn tại, bạn phải quyết định về mối quan hệ của chúng và thiết kế bất kỳ giao diện cần thiết nào.


                                                                                                                                                                                                      Context Map

                                                                                                                                                                                                      graphics/14inf03.gif

                                                                                                                                                                                                      Một BOUNDING CONTEXT cá nhân vẫn không cung cấp cái nhìn tổng thể. Bối cảnh của các mô hình khác có thể vẫn mơ hồ và đang trong tình trạng biến động.

                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                      Những người ở các nhóm khác sẽ không nhận thức rõ ràng về giới hạn CONTEXT và sẽ vô tình thực hiện những thay đổi làm mờ ranh giới hoặc làm phức tạp các kết nối. Khi cần phải tạo ra các kết nối giữa các ngữ cảnh khác nhau, chúng có xu hướng bị tràn vào nhau.

                                                                                                                                                                                                      Tái sử dụng mã giữa các BỐI CẢNH GIỚI HẠN là một mối nguy cần tránh. Việc tích hợp chức năng và dữ liệu phải thông qua một quá trình chuyển đổi. Bạn có thể giảm bớt sự nhầm lẫn bằng cách xác định mối quan hệ giữa các bối cảnh khác nhau và tạo ra một cái nhìn toàn cầu về tất cả các bối cảnh mô hình trong dự án.

                                                                                                                                                                                                      BẢN ĐỒ NGỮ CẢNH nằm trong sự giao thoa giữa quản lý dự án và thiết kế phần mềm. Dòng chảy tự nhiên của sự kiện là các ranh giới sẽ theo các đường nét của tổ chức đội ngũ. Những người làm việc chặt chẽ sẽ tự nhiên chia sẻ một ngữ cảnh mô hình. Những người ở các đội khác nhau, hoặc những người không giao tiếp, ngay cả khi họ ở cùng một đội, sẽ tách ra thành các ngữ cảnh khác nhau. Không gian văn phòng vật lý cũng có thể ảnh hưởng, vì các thành viên trong đội ở đầu xa nhau của một tòa nhà - chưa kể đến những thành phố khác nhau - sẽ có khả năng phân kỳ mà không cần nỗ lực tích hợp thêm. Hầu hết các quản lý dự án trực giác nhận ra những yếu tố này và tổ chức đội ngũ xung quanh các hệ thống con. Nhưng mối quan hệ giữa tổ chức đội ngũ và mô hình cũng như thiết kế phần mềm vẫn chưa nổi bật đủ. Cả quản lý và các thành viên trong đội cần có cái nhìn rõ ràng về sự phân chia khái niệm đang diễn ra của mô hình và thiết kế phần mềm.

                                                                                                                                                                                                      Vì vậy:

                                                                                                                                                                                                      Xác định từng mô hình trong dự án và định nghĩa BỐI CẢNH GIỚI HẠN của nó. Điều này bao gồm các mô hình ngầm của các hệ thống con không đối tượng. Đặt tên cho mỗi BỐI CẢNH GIỚI HẠN và làm cho các tên này trở thành một phần của NGÔN NGỮ PHỔ BIẾN.

                                                                                                                                                                                                      Mô tả các điểm tiếp xúc giữa các mô hình, nêu rõ sự chuyển giao cuối cùng cho bất kỳ giao tiếp nào và làm nổi bật bất kỳ sự chia sẻ nào.

                                                                                                                                                                                                      Vẽ bản đồ địa hình hiện có. Thực hiện các phép biến đổi sau.

                                                                                                                                                                                                      Trong mỗi BỐI CẢNH HẠN CHẾ, bạn sẽ có một phương ngữ nhất quán của NGÔN NGỮ PHỔ THÔNG. Tên của các BỐI CẢNH HẠN CHẾ sẽ tự chúng trở thành một phần của NGÔN NGỮ đó để bạn có thể nói rõ ràng về mô hình của bất kỳ phần nào trong thiết kế bằng cách làm cho BỐI CẢNH của bạn trở nên rõ ràng.

                                                                                                                                                                                                      MAP không cần phải được tài liệu hóa theo một hình thức cụ thể nào. Tôi thấy các sơ đồ như những cái trong chương này rất hữu ích để hình dung và truyền đạt bản đồ. Những người khác có thể thích một mô tả bằng văn bản rõ ràng hơn hoặc một hình thức đồ họa khác. Trong một số tình huống, việc thảo luận giữa các thành viên trong nhóm có thể là đủ. Mức độ chi tiết có thể khác nhau tùy theo nhu cầu. Dù hình thức của MAP có như thế nào, nó phải được chia sẻ và hiểu rõ bởi tất cả mọi người trong dự án. Nó phải cung cấp một cái tên rõ ràng cho mỗi BOUNDED CONTEXT, và phải làm rõ các điểm liên hệ và bản chất của chúng.

                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                      Mối quan hệ giữa các BỐI CẢNH RÀNG BUỘC có nhiều hình thức khác nhau tùy thuộc vào các vấn đề thiết kế và vấn đề tổ chức dự án. Sau này, chương này sẽ trình bày các mẫu mối quan hệ khác nhau giữa các BỐI CẢNH có hiệu quả trong các tình huống khác nhau, và có thể cung cấp các thuật ngữ để mô tả các mối quan hệ mà bạn tìm thấy trong BẢN ĐỒ của riêng mình. Hãy giữ trong tâm rằng BẢN ĐỒ BỐI CẢNH luôn đại diện cho tình huống hiện có, những mối quan hệ mà bạn tìm thấy có thể không phù hợp với các mẫu này ngay từ đầu. Nếu chúng gần giống, bạn có thể muốn sử dụng tên mẫu, nhưng đừng ép buộc. Hãy chỉ mô tả các mối quan hệ bạn tìm thấy. Sau này, bạn có thể bắt đầu tiến đến các mối quan hệ tiêu chuẩn hóa hơn.

                                                                                                                                                                                                      Vậy, bạn sẽ làm gì nếu bạn phát hiện ra một mảnh vỡ—một mô hình hoàn toàn bị rối rắm nhưng chứa các sự không nhất quán? Đặt một con rồng vào bản đồ và hoàn thành việc mô tả mọi thứ. Sau đó, với cái nhìn toàn cầu chính xác, hãy giải quyết những điểm gây nhầm lẫn. Một mảnh vỡ nhỏ có thể được sửa chữa, và các quy trình có thể được thiết lập để làm vững chắc nó. Nếu một mối quan hệ không rõ ràng, bạn có thể chọn mẫu gần nhất và tiến về phía nó. Nhiệm vụ đầu tiên của bạn là đạt được một BẢN ĐỒ NGỮ CẢNH rõ ràng, và điều này có thể đồng nghĩa với việc khắc phục những vấn đề thực tế mà bạn đã phát hiện. Nhưng đừng để việc sửa chữa cần thiết này dẫn đến sự tổ chức lại toàn bộ. Cho đến khi bạn có một BẢN ĐỒ NGỮ CẢNH rõ ràng, đặt tất cả công việc của bạn vào một NGỮ CẢNH RÀNG BUỘC nào đó, với các mối quan hệ rõ ràng giữa tất cả các mô hình liên kết, hãy chỉ thay đổi những mâu thuẫn rõ ràng.

                                                                                                                                                                                                      Khi bạn có một BẢN ĐỒ BỐ CỤC nhất quán, bạn sẽ thấy những điều bạn muốn thay đổi. Bạn có thể thực hiện những thay đổi cẩn thận đối với cơ cấu tổ chức của các nhóm hoặc thiết kế. Hãy nhớ, đừng thay đổi bản đồ cho đến khi sự thay đổi trong thực tế được thực hiện.

                                                                                                                                                                                                      Example
                                                                                                                                                                                                      Two CONTEXTS in a Shipping Application

                                                                                                                                                                                                      Chúng tôi trở lại với hệ thống vận chuyển. Một trong những tính năng chính của ứng dụng là tự động định tuyến hàng hóa tại thời điểm đặt chỗ. Mô hình giống như thế này:

                                                                                                                                                                                                      Figure 14.2.

                                                                                                                                                                                                      graphics/14fig02.gif

                                                                                                                                                                                                      Dịch vụ Định Tuyến là một DỊCH VỤ bao gồm một cơ chế ẩn sau một GIAO DIỆN TIẾT LỘ Ý ĐỊNH được tạo ra từ các HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ. Kết quả của những hàm đó được đặc trưng bằng CÁC KHẲNG ĐỊNH.

                                                                                                                                                                                                      1. Giao diện tuyên bố rằng khi một Đặc tả Tuyến được truyền vào, một Lịch trình sẽ được trả về.

                                                                                                                                                                                                      CÁC KẾT LUẬN cho biết rằng lộ trình trả về sẽ đáp ứng các Đặc tả Tuyến đường đã được truyền vào.

                                                                                                                                                                                                      Không có thông tin nào về cách thức mà nhiệm vụ rất khó khăn này được thực hiện. Bây giờ, hãy cùng khám phá bí mật để xem cơ chế này.

                                                                                                                                                                                                      Ban đầu trong dự án mà ví dụ này được dựa trên, tôi đã quá cứng nhắc về nội bộ của Dịch vụ Định tuyến. Tôi muốn hoạt động định tuyến thực sự được thực hiện với một mô hình miền mở rộng đại diện cho các chuyến đi của tàu và liên kết trực tiếp chúng với các Chân trong Lịch trình. Nhưng nhóm làm việc về vấn đề định tuyến đã chỉ ra rằng, để đạt được hiệu suất tốt và sử dụng các thuật toán đã được thiết lập, giải pháp cần được thực hiện dưới dạng mạng tối ưu, với mỗi chân của một chuyến đi được đại diện như một phần tử trong ma trận. Họ nhấn mạnh về một mô hình riêng biệt cho các hoạt động vận chuyển biển vì mục đích này.

                                                                                                                                                                                                      Họ rõ ràng đã đúng về các yêu cầu tính toán của quy trình định tuyến như đã thiết kế, và vì không có ý tưởng nào tốt hơn, tôi đã nhượng bộ. Thực tế, chúng tôi đã tạo ra hai BỐI CẢNH GIỚI HẠN riêng biệt, mỗi bối cảnh có tổ chức khái niệm riêng cho các hoạt động vận chuyển. (Xem Hình 14.3.)

                                                                                                                                                                                                      Figure 14.3. Two BOUNDED CONTEXTS formed to allow efficient routing algorithms to be applied

                                                                                                                                                                                                      graphics/14fig03.gif

                                                                                                                                                                                                      Yêu cầu của chúng tôi là nhận một yêu cầu Dịch vụ Định tuyến, dịch nó thành các thuật ngữ mà Dịch vụ Điều hướng Mạng có thể hiểu, sau đó lấy kết quả và dịch nó thành dạng mà Dịch vụ Định tuyến được kỳ vọng cung cấp.

                                                                                                                                                                                                      Điều này có nghĩa là không cần phải ánh xạ tất cả mọi thứ trong hai mô hình này, mà chỉ cần có thể thực hiện hai bản dịch cụ thể.

                                                                                                                                                                                                      Danh sách các mã vị trí chỉ định tuyến

                                                                                                                                                                                                      Danh sách ID nút Lịch trình

                                                                                                                                                                                                      Để làm điều này, chúng ta phải xem xét ý nghĩa của một thành phần trong một mô hình và tìm cách diễn đạt nó theo cách của mô hình kia.

                                                                                                                                                                                                      Bắt đầu với bản dịch đầu tiên (Danh sách mã vị trí của Đặc điểm Tuyến đường), chúng ta cần suy nghĩ về ý nghĩa của chuỗi các vị trí trong danh sách. Vị trí đầu tiên trong danh sách sẽ là điểm khởi đầu của con đường, sau đó sẽ buộc phải đi qua từng vị trí một cho đến khi đến vị trí cuối cùng trong danh sách. Vì vậy, điểm xuất phát và điểm đến là vị trí đầu tiên và cuối cùng trong danh sách, với vị trí thông quan (nếu có) ở giữa.

                                                                                                                                                                                                      Figure 14.4. Translation of a query to the Network Traversal Service

                                                                                                                                                                                                      graphics/14fig04.gif

                                                                                                                                                                                                      (Thật may mắn, hai đội đã sử dụng cùng một mã địa điểm, vì vậy chúng ta không phải xử lý ở cấp độ dịch thuật đó.)

                                                                                                                                                                                                      Lưu ý rằng việc dịch ngược sẽ gây ra sự mơ hồ, vì đầu vào để truy cập mạng cho phép bất kỳ số lượng điểm trung gian nào, không chỉ một điểm cụ thể được chỉ định là điểm thông quan. May mắn thay, điều này không phải là vấn đề vì chúng ta không cần phải dịch theo hướng đó, nhưng nó cho thấy lý do tại sao một số bản dịch là không thể.

                                                                                                                                                                                                      Bây giờ, hãy dịch kết quả (Danh sách ID Node Lịch trình). Chúng ta sẽ giả định rằng có thể sử dụng một REPOSITORY để tra cứu các đối tượng Node và Hoạt động Vận chuyển dựa trên các ID Node mà chúng ta nhận được. Vậy, những Node đó được ánh xạ như thế nào đến các Chân? Dựa trên mã loại hoạt động, chúng ta có thể chia danh sách Node thành các cặp khởi hành/đến. Mỗi cặp sau đó liên quan đến một Chân.

                                                                                                                                                                                                      Figure 14.5. Translation of a route found by the Network Traversal Service

                                                                                                                                                                                                      graphics/14fig05.gif

                                                                                                                                                                                                      Các thuộc tính cho mỗi cặp Node sẽ được ánh xạ như sau:

                                                                                                                                                                                                      departureNode.shippingOperation.vesselVoyageId graphics/arrow.gif leg.vesselVoyageId departureNode.shippingOperation.date graphics/arrow.gif leg.loadDate departureNode.locationCode graphics/arrow.gif leg.loadLocationCode arrivalNode.shippingOperation.date graphics/arrow.gif leg.unloadDate arrivalNode.locationCode graphics/arrow.gif leg.unloadLocationCode 

                                                                                                                                                                                                      Đây là bản đồ dịch khái niệm giữa hai mô hình này. Giờ chúng ta cần triển khai một cái gì đó có thể thực hiện việc dịch cho chúng ta. Trong một trường hợp đơn giản như thế này, tôi thường tạo một đối tượng cho mục đích đó, sau đó tìm hoặc tạo một đối tượng khác để cung cấp dịch vụ cho phần còn lại của hệ thống con của chúng ta.

                                                                                                                                                                                                      Figure 14.6. A two-way translator

                                                                                                                                                                                                      graphics/14fig06.gif

                                                                                                                                                                                                      Đây là một đối tượng mà cả hai đội phải làm việc cùng nhau để duy trì. Thiết kế nên làm cho việc kiểm tra đơn vị trở nên rất dễ dàng, và sẽ là một ý tưởng đặc biệt tốt nếu các đội hợp tác trong một bộ kiểm tra cho nó. Ngoài điều đó ra, họ có thể đi theo những hướng riêng của mình.

                                                                                                                                                                                                      Figure 14.7.

                                                                                                                                                                                                      graphics/14fig07.gif

                                                                                                                                                                                                      Việc triển khai Dịch vụ Định tuyến bây giờ trở thành vấn đề ủy thác cho Bộ dịch và Dịch vụ Xuyên mạng. Hoạt động duy nhất của nó sẽ trông giống như sau:

                                                                                                                                                                                                      public Itinerary route(RouteSpecification spec) { Booking_TransportNetwork_Translator translator = new Booking_TransportNetwork_Translator();] List constraintLocations = translator.convertConstraints(spec); // Get access to the NetworkTraversalService List pathNodes = traversalService.findPath(constraintLocations); Itinerary result = translator.convert(pathNodes); return result; } 

                                                                                                                                                                                                      Không tệ. CÁC NGỮ CẢNH HẠN CHẾ đã giúp giữ cho mỗi mô hình tương đối sạch sẽ, cho phép các đội làm việc phần lớn độc lập, và nếu giả định ban đầu là đúng, có lẽ sẽ phục vụ tốt. (Chúng ta sẽ quay lại vấn đề đó sau trong chương này.)

                                                                                                                                                                                                      Giao diện giữa hai bối cảnh là khá nhỏ. Giao diện của Dịch vụ Định tuyến cách ly phần còn lại của thiết kế BỐI CẢNH ĐẶT PHÒNG khỏi các sự kiện trong thế giới tìm đường. Giao diện dễ dàng để kiểm tra vì nó được cấu thành từ CÁC HÀM KHÔNG CÓ TÁC DỤNG PHỤ. Một trong những bí quyết để cùng tồn tại thoải mái với các BỐI CẢNH khác là có bộ kiểm tra hiệu quả cho các giao diện. "Tin tưởng, nhưng phải xác minh," Tổng thống Reagan đã nói khi đàm phán giảm vũ khí.

                                                                                                                                                                                                      Reagan dịch một câu nói cũ của Nga, tóm gọn bản chất vấn đề cho cả hai bên - một phép ẩn dụ khác về việc kết nối các bối cảnh.

                                                                                                                                                                                                      Nó nên dễ dàng để thiết lập một bộ bài kiểm tra tự động sẽ cung cấp các Đặc tả Tuyến đường vào Dịch vụ Định tuyến và kiểm tra Hành trình trả về.

                                                                                                                                                                                                      Các ngữ cảnh mô hình luôn tồn tại, nhưng nếu không có sự chú ý có ý thức, chúng có thể chồng chéo và dao động. Bằng cách định nghĩa rõ ràng các NGỮ CẢNH HẠN CHẾ và BẢN ĐỒ NGỮ CẢNH, đội ngũ của bạn có thể bắt đầu hướng dẫn quá trình thống nhất các mô hình và kết nối các mô hình khác nhau.

                                                                                                                                                                                                      Testing at the CONTEXT Boundaries

                                                                                                                                                                                                      Các điểm tiếp xúc với các BỐ CỤC RỒNG là đặc biệt quan trọng để kiểm tra. Các bài kiểm tra giúp bù đắp cho những subtilities của việc dịch và mức độ giao tiếp thấp hơn mà thường tồn tại tại các ranh giới. Chúng có thể hoạt động như một hệ thống cảnh báo sớm quý giá, đặc biệt là an ủi trong những trường hợp mà bạn phụ thuộc vào các chi tiết của một mô hình mà bạn không kiểm soát.

                                                                                                                                                                                                      Organizing and Documenting CONTEXT MAPS

                                                                                                                                                                                                      Chỉ có hai điểm quan trọng ở đây:

                                                                                                                                                                                                      1. "CÁC NGÀNH GIỚI HẠN cần có tên gọi để bạn có thể nói về chúng. Những tên gọi đó nên được đưa vào NGÔN NGỮ PHỔ BIẾN của đội ngũ."

                                                                                                                                                                                                      Mọi người phải biết ranh giới nằm ở đâu và có khả năng nhận ra BỐI CẢNH của bất kỳ đoạn mã hoặc tình huống nào.

                                                                                                                                                                                                      Yêu cầu thứ hai có thể được đáp ứng theo nhiều cách khác nhau tùy thuộc vào văn hóa của nhóm. Khi các BOUNDING CONTEXT đã được xác định, việc phân tách mã của các CONTEXT khác nhau thành các MODULE khác nhau trở nên tự nhiên, điều này đặt ra câu hỏi về cách theo dõi MODULE nào thuộc về CONTEXT nào. Một quy ước đặt tên có thể được sử dụng để chỉ ra điều này, hoặc bất kỳ cơ chế nào khác dễ dàng và tránh gây nhầm lẫn.

                                                                                                                                                                                                      Quan trọng không kém là việc truyền đạt các ranh giới khái niệm theo cách mà mọi người trong nhóm đều hiểu giống nhau. Cho mục đích giao tiếp này, tôi thích các sơ đồ không chính thức như trong ví dụ. Có thể tạo ra các sơ đồ hoặc danh sách văn bản chặt chẽ hơn, cho thấy tất cả các gói trong mỗi BỐI CẢNH, cùng với các điểm tiếp xúc và các cơ chế chịu trách nhiệm kết nối và dịch nghĩa. Một số nhóm sẽ cảm thấy thoải mái hơn với cách tiếp cận này, trong khi những nhóm khác sẽ hoạt động tốt dựa trên sự đồng thuận bằng lời và nhiều cuộc thảo luận.

                                                                                                                                                                                                      Trong bất kỳ trường hợp nào, việc đưa BẢN ĐỒ NGỮ CẢNH vào các cuộc thảo luận là rất quan trọng nếu các tên muốn được đưa vào NGÔN NGỮ PHỔ THÔNG. Đừng nói, "Stuff của nhóm George đang thay đổi, vì vậy chúng ta sẽ phải thay đổi stuff của mình để giao tiếp với nó." Hãy nói thay vào đó, "Mô hình Mạng Vận Tải đang thay đổi, vì vậy chúng ta sẽ phải thay đổi bộ dịch cho ngữ cảnh Đặt Chỗ."


                                                                                                                                                                                                        Relationships Between BOUNDED CONTEXTS

                                                                                                                                                                                                        Các mẫu sau đây bao gồm một loạt các chiến lược để liên kết hai mô hình có thể được kết hợp để bao trùm toàn bộ doanh nghiệp. Những mẫu này phục vụ cho hai mục đích: cung cấp mục tiêu để tổ chức công việc phát triển một cách thành công, và cung cấp từ vựng để mô tả tổ chức hiện có.

                                                                                                                                                                                                        Một mối quan hệ hiện có có thể, do tình cờ hoặc có chủ ý, rơi vào gần một trong những mẫu này, trong trường hợp đó bạn có thể mô tả nó bằng thuật ngữ đó, với các biến thể được ghi chú phù hợp. Sau đó, với mỗi thay đổi nhỏ trong thiết kế, mối quan hệ có thể được kéo gần hơn đến mẫu đã chọn.

                                                                                                                                                                                                        Mặt khác, bạn có thể thấy rằng một mối quan hệ hiện tại đang rối rắm hoặc phức tạp hóa. Một số tái tổ chức có thể cần thiết chỉ để làm cho một BẢN ĐỒ NGỮ CẢNH không mơ hồ trở nên khả thi. Trong tình huống này, hoặc bất kỳ tình huống nào mà bạn đang xem xét tái tổ chức, những mẫu này đưa ra một loạt các lựa chọn được ưa chuộng trong những hoàn cảnh khác nhau. Các biến số nổi bật bao gồm mức độ kiểm soát bạn có đối với mô hình khác, mức độ và loại hình hợp tác giữa các nhóm, và mức độ tích hợp các tính năng và dữ liệu.

                                                                                                                                                                                                        Bộ mẫu dưới đây bao phủ một số trường hợp phổ biến và quan trọng nhất, điều này sẽ giúp bạn có được ý tưởng tốt về cách tiếp cận các trường hợp khác. Một nhóm xuất sắc làm việc chặt chẽ trên một sản phẩm tích hợp cao có thể triển khai một mô hình thống nhất lớn. Nhu cầu phục vụ các cộng đồng người dùng khác nhau hoặc một hạn chế về khả năng phối hợp của nhóm có thể dẫn đến mối quan hệ KERNEL CHUNG hoặc KHÁCH HÀNG/NHÀ CUNG CẤP. Đôi khi, một cái nhìn rõ ràng vào các yêu cầu cho thấy rằng việc tích hợp không phải là yếu tố thiết yếu và tốt nhất cho các hệ thống là đi theo con đường RIÊNG CỦA CHÚNG. Và, tất nhiên, hầu hết các dự án phải tích hợp ở một mức độ nào đó với các hệ thống kế thừa và hệ thống bên ngoài, điều này có thể dẫn đến DỊCH VỤ MỞ HOẶC CÁC LỚP BẢO VỆ CHỐNG THAM NHŨNG.


                                                                                                                                                                                                          Shared Kernel

                                                                                                                                                                                                          graphics/14inf04.gif

                                                                                                                                                                                                          Khi việc tích hợp chức năng bị hạn chế, chi phí cho việc TÍCH HỢP LIÊN TỤC có thể được coi là quá cao. Điều này đặc biệt đúng khi các đội ngũ không có kỹ năng hoặc tổ chức chính trị để duy trì tích hợp liên tục, hoặc khi một đội ngũ duy nhất quá lớn và không linh hoạt. Do đó, có thể xác định các BỐI CẢNH RÀNG BUỘC tách biệt và thành lập nhiều đội ngũ.

                                                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                          Các đội ngũ thiếu sự phối hợp làm việc trên những ứng dụng liên quan chặt chẽ có thể tiến dần một cách nhanh chóng trong thời gian đầu, nhưng sản phẩm của họ có thể không phù hợp với nhau. Họ có thể chi nhiều hơn cho các lớp dịch thuật và việc điều chỉnh sau đó so với số tiền họ lẽ ra đã chi cho TÍCH HỢP LIÊN TỤC ngay từ đầu, trong khi đó làm trùng lặp nỗ lực và mất đi lợi ích của một NGÔN NGỮ TOÀN CẦU chung.

                                                                                                                                                                                                          Trong nhiều dự án, tôi đã thấy rằng lớp hạ tầng được chia sẻ giữa các nhóm làm việc chủ yếu độc lập. Một phép loại suy cho điều này cũng có thể hoạt động tốt trong lĩnh vực này. Có thể việc đồng bộ hóa toàn bộ mô hình và mã nguồn sẽ quá nặng nề, nhưng một tập hợp con được chọn lọc cẩn thận có thể cung cấp nhiều lợi ích hơn với chi phí thấp hơn.

                                                                                                                                                                                                          Do đó:

                                                                                                                                                                                                          Xác định một tập con nào đó của mô hình miền mà hai đội đồng ý chia sẻ. Tất nhiên điều này bao gồm, cùng với tập con của mô hình này, tập con mã nguồn hoặc thiết kế cơ sở dữ liệu liên quan đến phần của mô hình đó. Những phần được chia sẻ này có trạng thái đặc biệt, và không nên thay đổi mà không tham vấn với đội kia.

                                                                                                                                                                                                          Tích hợp một hệ thống chức năng thường xuyên, nhưng ít hơn một chút so với nhịp độ TÍCH HỢP LIÊN TỤC trong các đội. Tại những lần tích hợp này, tiến hành chạy các bài kiểm tra của cả hai đội.

                                                                                                                                                                                                          Đó là một sự cân bằng cẩn thận. KERNEL CHIA SẺ không thể được thay đổi tự do như các phần khác của thiết kế. Các quyết định cần có sự tham khảo ý kiến với đội khác. Các bộ kiểm tra tự động phải được tích hợp vì tất cả các bài kiểm tra của cả hai đội phải vượt qua khi có thay đổi. Thông thường, các đội thực hiện thay đổi trên các bản sao riêng biệt của KERNEL, tích hợp với đội khác theo những khoảng thời gian nhất định. (Ví dụ, trong một đội liên tục tích hợp hàng ngày hoặc tốt hơn, việc sáp nhập KERNEL có thể diễn ra hàng tuần.) Bất kể khi nào việc tích hợp mã được lên lịch, thì càng sớm cả hai đội trao đổi về các thay đổi, càng tốt.

                                                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                          KERNEL CHIA SẺ thường là MIỀN CỐT LÕI, một tập hợp các MIỀN PHỤ TÍNH CHUNG, hoặc cả hai (xem Chương 15), nhưng nó có thể là bất kỳ phần nào của mô hình mà cả hai nhóm cần. Mục tiêu là giảm thiểu sự trùng lặp (nhưng không phải để loại bỏ nó, như sẽ xảy ra nếu chỉ có một BỐ CỤC ĐƯỜNG RANH) và làm cho việc tích hợp giữa hai hệ thống con tương đối dễ dàng.


                                                                                                                                                                                                            Customer/Supplier Development Teams

                                                                                                                                                                                                            graphics/14inf05.jpg

                                                                                                                                                                                                            Thường thì một hệ thống con này cơ bản nuôi dưỡng một hệ thống con khác; thành phần "hạ nguồn" thực hiện phân tích hoặc các chức năng khác mà không có sự phản hồi nhiều vào thành phần "thượng nguồn", và tất cả các phụ thuộc chỉ có một chiều. Hai hệ thống con thường phục vụ cho các cộng đồng người dùng rất khác nhau, những người thực hiện các công việc khác nhau, nơi mà các mô hình khác nhau có thể hữu ích. Bộ công cụ cũng có thể khác nhau, do đó mã chương trình không thể được chia sẻ.

                                                                                                                                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                            CÁC HỆ THỐNG THƯỚC DƯỚI VÀ THƯỚC TRÊN tự nhiên tách biệt thành hai NGỮ CẢNH GIỚI HẠN. Điều này đặc biệt đúng khi hai thành phần yêu cầu kỹ năng khác nhau hoặc sử dụng bộ công cụ khác nhau cho việc triển khai. Việc dịch thuật dễ dàng hơn khi chỉ phải hoạt động theo một hướng. Tuy nhiên, các vấn đề có thể phát sinh, phụ thuộc vào mối quan hệ chính trị của hai nhóm.

                                                                                                                                                                                                            Sự phát triển tự do của nhóm upstream có thể bị chèn ép nếu nhóm downstream có quyền phủ quyết đối với các thay đổi, hoặc nếu quy trình yêu cầu thay đổi quá phức tạp. Nhóm upstream thậm chí có thể bị kiềm chế, lo lắng về việc làm hỏng hệ thống downstream. Trong khi đó, nhóm downstream có thể cảm thấy bất lực, phụ thuộc vào các ưu tiên của nhóm upstream.

                                                                                                                                                                                                            Các đội ở hạ nguồn cần những thứ từ các đội ở thượng nguồn, nhưng thượng nguồn không chịu trách nhiệm về các sản phẩm đầu ra của hạ nguồn. Sẽ tốn rất nhiều công sức để dự đoán những gì sẽ ảnh hưởng đến đội kia, và bản chất con người là như vậy, cùng với áp lực về thời gian, thì... Việc chính thức hóa mối quan hệ giữa các đội sẽ làm cho cuộc sống của mọi người dễ dàng hơn. Quy trình có thể được tổ chức để cân bằng nhu cầu của hai cộng đồng người dùng và lập lịch làm việc cho các tính năng cần thiết ở hạ nguồn.

                                                                                                                                                                                                            Trong một dự án Lập trình Cực đoan, đã có một cơ chế sẵn có để thực hiện điều đó: quy trình lập kế hoạch cho chu kỳ. Tất cả những gì chúng ta cần làm là xác định mối quan hệ giữa hai đội theo quy trình lập kế hoạch. Đại diện của đội hạ nguồn có thể hoạt động giống như các đại diện người dùng, tham gia cùng họ trong các phiên lập kế hoạch, thảo luận trực tiếp với các "khách hàng" của họ về những đánh đổi cho các nhiệm vụ mà họ muốn. Kết quả là một kế hoạch chu kỳ cho đội cung cấp bao gồm các nhiệm vụ mà đội hạ nguồn cần nhất hoặc hoãn các nhiệm vụ theo thỏa thuận, vì vậy không có kỳ vọng về việc giao hàng.

                                                                                                                                                                                                            Nếu một quy trình khác ngoài XP được sử dụng, bất kỳ phương pháp tương tự nào phục vụ để cân bằng các mối quan tâm của những người dùng khác nhau có thể được mở rộng để bao gồm nhu cầu của ứng dụng hạ nguồn.

                                                                                                                                                                                                            Do đó:

                                                                                                                                                                                                            Thiết lập một mối quan hệ rõ ràng giữa khách hàng và nhà cung cấp giữa hai đội. Trong các buổi lập kế hoạch, hãy để đội hạ nguồn đóng vai trò khách hàng đối với đội thượng nguồn. Thương lượng và lập ngân sách cho các nhiệm vụ liên quan đến yêu cầu của đội hạ nguồn để mọi người đều hiểu rõ cam kết và lịch trình.

                                                                                                                                                                                                            Phát triển chung các bài kiểm tra chấp nhận tự động để xác thực giao diện mong đợi. Thêm các bài kiểm tra này vào bộ kiểm tra của nhóm upstream, để được chạy như một phần của quá trình tích hợp liên tục. Việc kiểm tra này sẽ giúp nhóm upstream tự do thực hiện thay đổi mà không lo lắng về các tác động phụ ở phía hạ nguồn.

                                                                                                                                                                                                            Trong quá trình lặp, các thành viên đội ngược dòng cần có mặt cho các nhà phát triển dòng chính giống như khách hàng thông thường, để trả lời câu hỏi và giúp giải quyết vấn đề.

                                                                                                                                                                                                            Tự động hóa các bài kiểm tra chấp nhận là một phần quan trọng trong mối quan hệ với khách hàng này. Ngay cả trong dự án hợp tác nhất, mặc dù khách hàng có thể xác định và giao tiếp các phụ thuộc của họ, và nhà cung cấp có thể cố gắng giao tiếp các thay đổi một cách chăm chỉ, nhưng nếu không có các bài kiểm tra, sẽ xảy ra những điều bất ngờ. Chúng sẽ làm gián đoạn công việc của nhóm phía hạ nguồn và buộc nhóm phía thượng nguồn phải thực hiện các sửa chữa khẩn cấp không theo kế hoạch. Thay vào đó, hãy để nhóm khách hàng, phối hợp với nhóm nhà cung cấp, phát triển các bài kiểm tra chấp nhận tự động nhằm xác thực giao diện mà họ mong đợi. Nhóm phía thượng nguồn sẽ chạy các bài kiểm tra này như một phần của bộ bài kiểm tra tiêu chuẩn của mình. Bất kỳ thay đổi nào đối với các bài kiểm tra này đều cần phải có thông tin liên lạc với nhóm kia, vì việc thay đổi các bài kiểm tra có nghĩa là thay đổi giao diện.

                                                                                                                                                                                                            Mối quan hệ khách hàng/nhà cung cấp cũng phát sinh giữa các dự án trong các công ty khác nhau, trong những tình huống mà một khách hàng duy nhất rất quan trọng đối với hoạt động của nhà cung cấp. "Chiếc đuôi có thể vẫy con chó": một khách hàng có ảnh hưởng có thể đưa ra yêu cầu quan trọng đối với sự thành công của dự án ở hạng mục trước, nhưng những yêu cầu đó cũng có thể gây rối cho sự phát triển của dự án ở hạng mục trước. Cả hai bên đều được hưởng lợi từ việc chính thức hóa quá trình phản hồi yêu cầu, vì các cân nhắc chi phí/lợi ích thậm chí còn khó nhìn thấy hơn trong các mối quan hệ bên ngoài so với trong tình huống IT nội bộ.

                                                                                                                                                                                                            Có hai yếu tố quan trọng đối với mẫu này.

                                                                                                                                                                                                            1. Mối quan hệ phải là mối quan hệ giữa khách hàng và nhà cung cấp, với ý nghĩa rằng nhu cầu của khách hàng là ưu tiên hàng đầu. Bởi vì đội ngũ hạ nguồn không phải là khách hàng duy nhất, nên các yêu cầu khác nhau của khách hàng phải được cân bằng trong việc đàm phán - nhưng chúng vẫn là ưu tiên. Tình huống này trái ngược với mối quan hệ "người em nghèo" thường xuất hiện, trong đó đội ngũ hạ nguồn phải đến cầu xin đội ngũ thượng nguồn cho những nhu cầu của mình.

                                                                                                                                                                                                            Phải có một bộ kiểm tra tự động cho phép nhóm upstream thay đổi mã của họ mà không lo làm hỏng nhóm downstream, và cho phép nhóm downstream tập trung vào công việc của riêng họ mà không cần liên tục theo dõi nhóm upstream.

                                                                                                                                                                                                            Trong một cuộc đua tiếp sức, vận động viên chạy phía trước không thể luôn nhìn về phía sau để kiểm tra. Anh ấy hoặc cô ấy phải có thể tin tưởng vào người cầm gậy tiếp sức để thực hiện việc chuyển giao một cách chính xác, nếu không, đội sẽ bị chậm lại không thể cứu vãn.

                                                                                                                                                                                                            Example
                                                                                                                                                                                                            Yield Analysis Versus Booking

                                                                                                                                                                                                            Quay lại ví dụ về vận chuyển mà chúng ta tin cậy. Một đội ngũ chuyên nghiệp đã được thành lập để phân tích tất cả các đơn đặt hàng chảy qua công ty, nhằm xem xét cách tối đa hóa thu nhập. Các thành viên trong nhóm có thể phát hiện ra rằng các tàu có khoảng trống và có thể đề xuất việc đặt quá mức hơn. Họ có thể phát hiện rằng các tàu đang lấp đầy hàng hóa số lượng lớn sớm, buộc công ty phải từ chối những hàng hóa đặc biệt có giá trị hơn. Trong trường hợp đó, họ có thể đề xuất dành không gian cho những loại hàng hóa này hoặc tăng giá đối với hàng hóa số lượng lớn.

                                                                                                                                                                                                            Để thực hiện phân tích này, họ sử dụng các mô hình phức tạp của riêng mình. Để triển khai, họ sử dụng một kho dữ liệu với các công cụ để xây dựng các mô hình phân tích. Họ cần rất nhiều thông tin từ ứng dụng Đặt chỗ.

                                                                                                                                                                                                            Từ đầu, rõ ràng đây là hai BOUNDED CONTEXTS, bởi vì chúng sử dụng các công cụ triển khai khác nhau và, điều quan trọng nhất, các mô hình miền khác nhau. Mối quan hệ giữa chúng nên như thế nào?

                                                                                                                                                                                                            MỘT HẠT LỎNG CHIA SẺ có thể có vẻ hợp lý, vì phân tích doanh thu quan tâm đến một tập hợp con của mô hình Đặt chỗ, và mô hình của họ có một số khái niệm chồng chéo về hàng hóa, giá cả, và những thứ khác. Nhưng HẠT LỎNG CHIA SẺ khó khăn trong trường hợp sử dụng các công nghệ triển khai khác nhau. Hơn nữa, nhu cầu mô hình hóa của đội phân tích doanh thu khá chuyên biệt, và họ liên tục thử nghiệm các mô hình của mình và cố gắng các lựa chọn khác nhau. Họ có thể tốt hơn nếu dịch những gì họ cần từ BỐI CẢNH Đặt chỗ sang mô hình của riêng mình. (Mặt khác, nếu họ có thể sử dụng HẠT LỎNG CHIA SẺ, gánh nặng dịch thuật của họ sẽ nhẹ hơn nhiều. Họ vẫn sẽ phải tái triển khai mô hình và dịch dữ liệu sang triển khai mới, nhưng nếu mô hình giống nhau, việc chuyển giao sẽ đơn giản.)

                                                                                                                                                                                                            Ứng dụng Đặt chỗ không phụ thuộc vào phân tích lợi suất, vì không có ý định tự động điều chỉnh các chính sách. Các chuyên gia con người sẽ đưa ra quyết định và chuyển tiếp chúng đến những người và hệ thống cần thiết. Vì vậy, chúng ta có mối quan hệ giữa phía trên và phía dưới. Những gì phía dưới cần là điều này:

                                                                                                                                                                                                            1. Một số dữ liệu không cần thiết cho bất kỳ hoạt động đặt chỗ nào.

                                                                                                                                                                                                            Một chút ổn định trong sơ đồ cơ sở dữ liệu (hoặc ít nhất là thông báo tin cậy về sự thay đổi) hoặc một tiện ích xuất dữ liệu.

                                                                                                                                                                                                            May mắn thay, giám đốc dự án của nhóm phát triển ứng dụng Đặt chỗ có động lực giúp nhóm phân tích lợi nhuận. Điều này có thể đã trở thành một vấn đề, vì bộ phận vận hành thực sự làm báo cáo đặt chỗ hàng ngày báo cáo cho một phó giám đốc khác với những người thực sự thực hiện phân tích lợi nhuận. Nhưng ban quản lý cấp cao rất quan tâm đến quản lý lợi nhuận và, sau khi nhận thấy những vấn đề hợp tác trong quá khứ giữa hai bộ phận, đã cấu trúc dự án phát triển phần mềm sao cho các giám đốc dự án của cả hai nhóm báo cáo cho cùng một người.

                                                                                                                                                                                                            Do đó, tất cả các yêu cầu đã được thực hiện để áp dụng CÁC ĐỘI PHÁT TRIỂN KHÁCH HÀNG/NHÀ CUNG CẤP.

                                                                                                                                                                                                            Tôi đã thấy kịch bản này phát triển ở nhiều nơi, nơi các nhà phát triển phần mềm phân tích và các nhà phát triển phần mềm vận hành có mối quan hệ khách hàng/nhà cung cấp. Khi các thành viên trong nhóm upstream nghĩ về vai trò của họ như là phục vụ một khách hàng, mọi thứ diễn ra khá suôn sẻ. Nó hầu như luôn được tổ chức một cách không chính thức, và trong mỗi trường hợp, mọi thứ diễn ra cũng tốt như mối quan hệ cá nhân của hai giám đốc dự án.

                                                                                                                                                                                                            Trong một dự án XP, tôi đã thấy mối quan hệ này được chính thức hóa ở chỗ, cho mỗi lần lặp, đại diện của nhóm downstream đã tham gia "trò chơi lập kế hoạch" trong vai trò của khách hàng, hội tụ với những đại diện khách hàng truyền thống hơn (về chức năng ứng dụng) để thương lượng về những nhiệm vụ nào sẽ vào kế hoạch lặp. Dự án này ở một công ty nhỏ, vì vậy sếp chung gần nhất không xa trong chuỗi. Nó hoạt động rất hiệu quả.

                                                                                                                                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                            CÁC ĐỘI NGŨ KHÁCH HÀNG/NHÀ CUNG CẤP có khả năng thành công cao hơn nếu hai đội làm việc dưới cùng một quản lý, để cuối cùng họ chia sẻ mục tiêu, hoặc khi họ ở trong các công ty khác nhau thực sự có những vai trò đó. Khi không có động lực nào cho đội ngược dòng, tình huống sẽ rất khác biệt.


                                                                                                                                                                                                              Conformist

                                                                                                                                                                                                              graphics/14inf06.gif

                                                                                                                                                                                                              Khi hai đội có mối quan hệ đầu vào/đầu ra không được chỉ đạo hiệu quả từ cùng một nguồn, một mô hình hợp tác như ĐỘI NGHỀ KHÁCH HÀNG/CUNG CẤP sẽ không hoạt động. Việc cố gắng áp dụng một cách ngây thơ sẽ khiến đội đầu ra gặp rắc rối. Điều này có thể xảy ra trong một công ty lớn, nơi hai đội cách xa nhau trong hệ thống quản lý hoặc nơi người giám sát chung không quan tâm đến mối quan hệ của hai đội. Nó cũng xảy ra giữa các đội trong các công ty khác nhau khi doanh nghiệp của khách hàng không quan trọng đối với nhà cung cấp. Có lẽ nhà cung cấp có nhiều khách hàng nhỏ, hoặc có thể nhà cung cấp đang thay đổi hướng đi trên thị trường và không còn đánh giá cao các khách hàng cũ. Nhà cung cấp có thể chỉ đơn giản là quản lý kém. Có thể họ đã phá sản. Dù lý do là gì, thực tế là đội đầu ra đang tự mình giải quyết.

                                                                                                                                                                                                              Khi hai nhóm phát triển có mối quan hệ ngược xuôi, trong đó nhóm upstream không có động lực để đáp ứng nhu cầu của nhóm downstream, nhóm downstream trở nên bất lực. Tình thương không vụ lợi có thể thúc đẩy các nhà phát triển upstream hứa hẹn, nhưng ít có khả năng những lời hứa đó được thực hiện. Niềm tin vào những ý định tốt đẹp đó khiến nhóm downstream lập kế hoạch dựa trên những tính năng sẽ không bao giờ có sẵn. Dự án downstream sẽ bị trì hoãn cho đến khi nhóm cuối cùng học cách sống với những gì họ được giao. Một giao diện phù hợp với nhu cầu của nhóm downstream không nằm trong kế hoạch.

                                                                                                                                                                                                              Trong tình huống này, có ba con đường có thể xảy ra. Một là từ bỏ việc sử dụng upstream hoàn toàn. Tùy chọn này nên được đánh giá một cách thực tế, không nên giả định rằng upstream sẽ đáp ứng nhu cầu của downstream. Đôi khi chúng ta ước lượng quá cao giá trị hoặc ước lượng quá thấp chi phí của sự phụ thuộc như vậy. Nếu nhóm downstream quyết định cắt đứt mối liên hệ, họ sẽ đi theo con đường RIÊNG CỦA MÌNH (xem mô tả mẫu sau trong chương này).

                                                                                                                                                                                                              Đôi khi, giá trị của việc sử dụng phần mềm upstream lớn đến nỗi việc duy trì sự phụ thuộc là cần thiết (hoặc một quyết định chính trị đã được đưa ra rằng đội ngũ không thể thay đổi). Trong trường hợp này, hai con đường vẫn còn mở; sự lựa chọn phụ thuộc vào chất lượng và phong cách thiết kế upstream. Nếu thiết kế rất khó làm việc với, có thể do thiếu tính đóng gói, sự trừu tượng khó xử, hoặc mô hình hóa trong một kiểu mà đội ngũ không thể sử dụng, thì đội ngũ downstream vẫn sẽ phải phát triển mô hình riêng của mình. Họ sẽ phải chịu trách nhiệm hoàn toàn cho một lớp dịch mà có khả năng sẽ rất phức tạp. (Xem LỚP CHỐNG THAMNHŨNG, ở phần sau của chương này.)


                                                                                                                                                                                                              Following Isn't Always Bad

                                                                                                                                                                                                              Khi sử dụng một thành phần có sẵn có giao diện lớn, bạn thường nên TUÂN THỦ mô hình ngầm ẩn trong thành phần đó. Bởi vì thành phần và ứng dụng rõ ràng là những BỐC TÁN KHÉP KÍN khác nhau, dựa trên tổ chức đội ngũ và quyền kiểm soát, các bộ điều hợp có thể cần thiết cho những thay đổi định dạng nhỏ, nhưng mô hình nên là tương đương. Nếu không, bạn nên đặt câu hỏi về giá trị của việc có thành phần đó. Nếu nó đủ tốt để mang lại giá trị cho bạn, có thể có kiến thức đã được chắt lọc vào thiết kế của nó. Trong lĩnh vực hẹp của nó, có thể nó vượt trội hơn nhiều so với hiểu biết của bạn. Mô hình của bạn có lẽ mở rộng hơn phạm vi của thành phần này, và các khái niệm của bạn sẽ phát triển cho những phần khác đó. Nhưng nơi chúng kết nối, mô hình của bạn là một NGƯỜI TUÂN THỦ, theo gương mô hình của thành phần. Thực tế, bạn có thể bị kéo vào một thiết kế tốt hơn.

                                                                                                                                                                                                              Khi giao diện của bạn với một thành phần nhỏ, việc chia sẻ một mô hình thống nhất ít quan trọng hơn, và dịch thuật là một lựa chọn khả thi. Nhưng khi giao diện lớn và sự tích hợp trở nên quan trọng hơn, thường thì hợp lý để theo người dẫn đầu.

                                                                                                                                                                                                              Mặt khác, nếu chất lượng không quá tồi và phong cách tương đối tương thích, thì có thể tốt nhất là từ bỏ hoàn toàn mô hình độc lập. Đây là tình huống cần một NGƯỜI TUÂN THỦ.

                                                                                                                                                                                                              Do đó:

                                                                                                                                                                                                              Loại bỏ sự phức tạp của việc dịch giữa các BOUNDED CONTEXTS bằng cách tuân thủ một cách máy móc mô hình của đội ngũ upstream. Mặc dù điều này làm hạn chế phong cách của các nhà thiết kế downstream và có khả năng không mang lại mô hình lý tưởng cho ứng dụng, nhưng việc chọn SỰ PHÙ HỢP sẽ đơn giản hóa đáng kể việc tích hợp. Hơn nữa, bạn sẽ chia sẻ một NGÔN NGỮ PHỔ BIẾN với đội ngũ nhà cung cấp của bạn. Nhà cung cấp đang nắm quyền kiểm soát, vì vậy sẽ là điều tốt khi giúp họ dễ dàng giao tiếp. Tính vị tha có thể là đủ để khiến họ chia sẻ thông tin với bạn.

                                                                                                                                                                                                              Quyết định này làm sâu sắc thêm sự phụ thuộc của bạn vào nguồn gốc và giới hạn ứng dụng của bạn vào các khả năng của mô hình nguồn gốc - cộng với các cải tiến hoàn toàn bổ sung. Điều này rất không hấp dẫn về mặt cảm xúc, đó là lý do tại sao chúng ta lựa chọn nó ít hơn so với những gì chúng ta nên làm.

                                                                                                                                                                                                              Nếu những đánh đổi này là không chấp nhận được, nhưng phụ thuộc vào nguồn gốc là không thể thiếu, thì tùy chọn thứ hai vẫn tồn tại: Tự bảo vệ mình càng nhiều càng tốt bằng cách tạo ra một LỚP CHỐNG THAM NHŨNG, một phương pháp mạnh mẽ để triển khai một bản đồ dịch mà sẽ được thảo luận sau.

                                                                                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                              CONFORMIST giống như SHARED KERNEL ở chỗ cả hai đều có một khu vực chồng chéo, nơi mô hình là giống nhau, những khu vực mà mô hình của bạn đã được mở rộng bằng cách thêm vào, và những khu vực mà mô hình khác không ảnh hưởng đến bạn. Sự khác biệt giữa các mẫu là trong quyết định và quy trình phát triển. Trong khi SHARED KERNEL là một sự hợp tác giữa hai đội mà phối hợp chặt chẽ, CONFORMIST liên quan đến việc tích hợp với một đội không quan tâm đến sự hợp tác.

                                                                                                                                                                                                              Chúng tôi đã tiến hành theo một phổ hợp tác trong việc tích hợp giữa các BỐI CẢNH RANH giới, từ các KERNEL CHIA SẺ rất hợp tác hoặc CÁC ĐỘI NGŨ PHÁT TRIỂN KHÁCH HÀNG/NHÀ CUNG CẤP đến sự một chiều của CONFORMIST. Bây giờ chúng tôi sẽ thực hiện bước cuối cùng đến một cái nhìn bi quan hơn về mối quan hệ, giả định rằng không có hợp tác hay thiết kế sử dụng được từ phía bên kia.


                                                                                                                                                                                                                Anticorruption Layer

                                                                                                                                                                                                                graphics/14inf07.jpg

                                                                                                                                                                                                                Các hệ thống mới gần như luôn phải được tích hợp với các hệ thống kế thừa hoặc các hệ thống khác, những hệ thống này có các mô hình riêng của chúng. Các lớp dịch có thể đơn giản, thậm chí tinh tế, khi kết nối các BOUND CONTEXTS được thiết kế tốt với các đội ngũ hợp tác. Nhưng khi phần bên kia của ranh giới bắt đầu rò rỉ, lớp dịch có thể mang tông chất phòng thủ hơn.

                                                                                                                                                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                Khi một hệ thống mới đang được xây dựng mà phải có một giao diện lớn với một hệ thống khác, sự khó khăn trong việc liên hệ hai mô hình có thể cuối cùng áp đảo ý định của mô hình mới, khiến nó bị sửa đổi để giống với mô hình của hệ thống kia, một cách tùy tiện. Các mô hình của các hệ thống kế thừa thường yếu, và ngay cả những trường hợp phát triển tốt có thể không đáp ứng được nhu cầu của dự án hiện tại. Tuy nhiên, có thể có nhiều giá trị trong việc tích hợp, và đôi khi điều đó là một yêu cầu tuyệt đối.

                                                                                                                                                                                                                Câu trả lời không phải là tránh mọi sự tích hợp với các hệ thống khác. Tôi đã tham gia vào các dự án mà mọi người nhiệt tình bắt tay vào việc thay thế toàn bộ hệ thống cũ, nhưng điều này thực sự quá sức để thực hiện cùng một lúc. Hơn nữa, tích hợp với các hệ thống hiện có là một hình thức tái sử dụng có giá trị. Trong một dự án lớn, một hệ thống con thường phải giao tiếp với một số hệ thống con khác, được phát triển độc lập. Những hệ thống này sẽ phản ánh miền vấn đề theo những cách khác nhau. Khi các hệ thống dựa trên các mô hình khác nhau được kết hợp, nhu cầu cho hệ thống mới thích ứng với ngữ nghĩa của hệ thống khác có thể dẫn đến sự biến dạng của mô hình riêng của hệ thống mới. Ngay cả khi hệ thống khác được thiết kế tốt, nó cũng không dựa trên cùng một mô hình như của khách hàng. Và thường thì hệ thống khác không được thiết kế tốt.

                                                                                                                                                                                                                Có nhiều rào cản trong việc kết nối với một hệ thống bên ngoài. Chẳng hạn, lớp hạ tầng phải cung cấp phương tiện để giao tiếp với một hệ thống khác có thể đang trên một nền tảng khác hoặc sử dụng các giao thức khác nhau. Các kiểu dữ liệu của hệ thống khác phải được dịch sang các kiểu dữ liệu của hệ thống của bạn. Nhưng thường bị bỏ qua là sự chắc chắn rằng hệ thống khác không sử dụng cùng một mô hình miền khái niệm.

                                                                                                                                                                                                                Có vẻ rõ ràng rằng sẽ xảy ra lỗi nếu bạn lấy dữ liệu từ một hệ thống và hiểu sai nó trong một hệ thống khác. Bạn thậm chí có thể làm hỏng cơ sở dữ liệu. Nhưng ngay cả như vậy, vấn đề này thường lén lút xuất hiện với chúng ta vì chúng ta nghĩ rằng những gì chúng ta đang vận chuyển giữa các hệ thống là dữ liệu cơ bản, có nghĩa là không mơ hồ và phải giống nhau ở cả hai bên. Giả định này thường là sai. Những khác biệt tinh vi nhưng quan trọng trong ý nghĩa nảy sinh từ cách dữ liệu được liên kết trong mỗi hệ thống. Và ngay cả khi các phần tử dữ liệu cơ bản có cùng một ý nghĩa chính xác, thường là một sai lầm khi làm cho giao diện với hệ thống khác hoạt động ở mức độ thấp như vậy. Một giao diện mức thấp làm mất đi sức mạnh của mô hình của hệ thống khác để giải thích dữ liệu và ràng buộc các giá trị và mối quan hệ của nó, trong khi đè nặng hệ thống mới với gánh nặng diễn giải dữ liệu cơ bản không theo mô hình riêng của nó.

                                                                                                                                                                                                                Chúng ta cần cung cấp một bản dịch giữa các phần tuân theo những mô hình khác nhau, để các mô hình không bị làm hỏng bởi các yếu tố chưa tiêu hóa từ các mô hình nước ngoài.

                                                                                                                                                                                                                Do đó:

                                                                                                                                                                                                                Tạo một lớp cách ly để cung cấp cho khách hàng chức năng theo mô hình miền của riêng họ. Lớp này giao tiếp với hệ thống khác thông qua giao diện hiện có của nó, yêu cầu ít hoặc không cần thay đổi gì cho hệ thống khác. Bên trong, lớp này chuyển đổi theo cả hai hướng khi cần thiết giữa hai mô hình.

                                                                                                                                                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                Cuộc thảo luận về một cơ chế để liên kết hai hệ thống có thể gợi nhớ đến các vấn đề vận chuyển dữ liệu từ một chương trình này sang chương trình khác hoặc từ một máy chủ này sang máy chủ khác. Tôi sẽ thảo luận về việc kết hợp cơ chế truyền thông kỹ thuật ngay sau đây. Nhưng những chi tiết như vậy không nên bị nhầm lẫn với LỚP CHỐNG THAM NHŨNG, mà không phải là một cơ chế để gửi tin nhắn đến một hệ thống khác. Thay vào đó, đó là một cơ chế dịch các đối tượng và hành động khái niệm từ một mô hình và giao thức này sang một mô hình và giao thức khác.

                                                                                                                                                                                                                Một LỚP CHỐNG THAM NHŨNG có thể trở thành một phần mềm phức tạp tự thân. Tiếp theo, tôi sẽ phác thảo một số yếu tố thiết kế để tạo ra một lớp như vậy.

                                                                                                                                                                                                                Designing the Interface of the ANTICORRUPTION LAYER

                                                                                                                                                                                                                Giao diện công cộng của LỚP CHỐNG THAM NHŨNG thường xuất hiện dưới dạng một tập hợp các DỊCH VỤ, mặc dù đôi khi nó có thể dưới dạng một THỰC THỂ. Xây dựng một lớp hoàn toàn mới chịu trách nhiệm về việc dịch nghĩa giữa hai hệ thống cho chúng ta cơ hội để tái trừu tượng hóa hành vi của hệ thống khác và cung cấp các dịch vụ và thông tin của nó cho hệ thống của chúng ta một cách nhất quán với mô hình của chúng ta. Trong mô hình của chúng ta, có thể không hợp lý để đại diện cho hệ thống bên ngoài như một thành phần duy nhất. Có thể tốt nhất là sử dụng nhiều DỊCH VỤ (hoặc đôi khi là THỰC THỂ), mỗi cái có trách nhiệm rõ ràng theo mô hình của chúng ta.

                                                                                                                                                                                                                Implementing the ANTICORRUPTION LAYER

                                                                                                                                                                                                                Một cách để tổ chức thiết kế của LỚP CHỐNG THAM NHŨNG là kết hợp các FACADE, ADAPTER (cả hai từ Gamma và cộng sự, 1995), và các bộ dịch, cùng với các cơ chế giao tiếp và vận chuyển thường cần thiết để giao tiếp giữa các hệ thống.

                                                                                                                                                                                                                Chúng tôi thường phải tích hợp với các hệ thống có giao diện lớn, phức tạp và rối rắm. Đây là một vấn đề thực hiện, không phải là vấn đề về sự khác biệt mô hình khái niệm đã thúc đẩy việc sử dụng CÁC LỚP CHỐNG THAM NHŨNG, nhưng đây là một vấn đề bạn sẽ gặp phải khi cố gắng tạo ra chúng. Việc chuyển đổi từ mô hình này sang mô hình khác (đặc biệt nếu một mô hình là mờ nhạt) là một công việc đủ khó mà không phải đồng thời xử lý một giao diện phụ hệ thống khó giao tiếp. May mắn thay, đó là lý do vì sao CÁC MẶT TIỀN lại tồn tại.

                                                                                                                                                                                                                MỘT MẶT TIỀN là một giao diện thay thế cho một tiểu hệ thống, đơn giản hóa việc truy cập cho khách hàng và làm cho tiểu hệ thống dễ sử dụng hơn. Bởi vì chúng ta biết chính xác chức năng nào của hệ thống khác mà mình muốn sử dụng, chúng ta có thể tạo ra một MẶT TIỀN giúp thuận tiện và tối ưu hóa việc truy cập vào những tính năng đó và ẩn đi những phần còn lại. MẶT TIỀN không thay đổi mô hình của hệ thống cơ sở. Nó nên được viết hoàn toàn phù hợp với mô hình của hệ thống khác. Nếu không, bạn sẽ chỉ làm suy giảm trách nhiệm phân tích thành nhiều đối tượng và làm quá tải MẶT TIỀN, và tệ hơn nữa là bạn sẽ tạo ra một mô hình khác, một mô hình không thuộc về hệ thống khác hoặc BỐ CỤC RẠNG BUỘC của riêng bạn. MẶT TIỀN thuộc về BỐ CỤC RẠNG BUỘC của hệ thống khác. Nó chỉ đơn thuần trình bày một diện mạo thân thiện hơn, chuyên biệt cho nhu cầu của bạn.

                                                                                                                                                                                                                Một ADAPTER là một lớp bọc cho phép một khách hàng sử dụng một giao thức khác với giao thức mà người thực hiện hành vi hiểu. Khi một khách hàng gửi một tin nhắn đến ADAPTER, nó sẽ được chuyển đổi thành một tin nhắn có nghĩa tương đương và được gửi đến "đối tượng thích ứng." Phản hồi sẽ được chuyển đổi và gửi trả lại. Tôi sử dụng thuật ngữ adapter một cách hơi lỏng lẻo, vì sự nhấn mạnh trong Gamma và các cộng sự năm 1995 là làm cho một đối tượng được bọc tuân thủ một giao diện tiêu chuẩn mà các khách hàng mong đợi, trong khi đó chúng tôi có thể lựa chọn giao diện được thích ứng, và đối tượng thích ứng có thể thậm chí không phải là một đối tượng. Sự nhấn mạnh của chúng tôi là về sự chuyển đổi giữa hai mô hình, nhưng tôi nghĩ điều này nhất quán với ý định của ADAPTER.

                                                                                                                                                                                                                Đối với mỗi DỊCH VỤ mà chúng tôi định nghĩa, chúng tôi cần một BỘ CHUYỂN ĐỔI hỗ trợ giao diện của DỊCH VỤ và biết cách thực hiện các yêu cầu tương đương của hệ thống khác hoặc của BÓC DÂY của nó.

                                                                                                                                                                                                                Phần tử còn lại là bộ dịch. Nhiệm vụ của ADAPTER là biết cách thực hiện một yêu cầu. Việc chuyển đổi thực tế các đối tượng hoặc dữ liệu khái niệm là một nhiệm vụ riêng biệt, phức tạp có thể được đặt trong một đối tượng riêng, giúp cả hai dễ hiểu hơn. Một bộ dịch có thể là một đối tượng nhẹ được khởi tạo khi cần. Nó không cần trạng thái và không cần được phân phối, vì nó thuộc về các ADAPTER mà nó phục vụ.

                                                                                                                                                                                                                Đó là những yếu tố cơ bản mà tôi sử dụng để tạo ra một LỚP CHỐNG THAM NHŨNG. Còn một vài yếu tố khác cần xem xét.

                                                                                                                                                                                                                • Thông thường, hệ thống đang thiết kế (tiểu hệ thống của bạn) sẽ khởi động hành động, như được ngụ ý bởi Hình 14.8. Tuy nhiên, có những trường hợp mà tiểu hệ thống khác có thể cần yêu cầu điều gì đó từ tiểu hệ thống của bạn hoặc thông báo cho nó về một sự kiện nào đó. MỘT LỚP CHỐNG THAM NHŨNG có thể hai chiều, định nghĩa DỊCH VỤ trên cả hai giao diện với các ADAPTER riêng của mình, có khả năng sử dụng cùng một bộ chuyển đổi với các bản dịch đối xứng. Mặc dù việc triển khai LỚP CHỐNG THAM NHŨNG thường không yêu cầu thay đổi gì đối với tiểu hệ thống khác, nhưng có thể cần thiết để hệ thống khác gọi các DỊCH VỤ của LỚP CHỐNG THAM NHŨNG.

                                                                                                                                                                                                                  Figure 14.8. The structure of an ANTICORRUPTION LAYER

                                                                                                                                                                                                                  graphics/14fig08.gif

                                                                                                                                                                                                                • Bạn thường sẽ cần một cơ chế giao tiếp nào đó để kết nối hai hệ thống con, và chúng có thể nằm trên các máy chủ khác nhau. Trong trường hợp này, bạn phải quyết định nơi đặt các liên kết giao tiếp này. Nếu bạn không có quyền truy cập vào hệ thống con khác, bạn có thể phải đặt các liên kết giữa FACADE và hệ thống con kia. Tuy nhiên, nếu FACADE có thể được tích hợp trực tiếp với hệ thống con khác, thì một lựa chọn tốt là đặt liên kết giao tiếp giữa ADAPTER và FACADE, vì giao thức của FACADE có thể đơn giản hơn so với những gì nó bao trùm. Cũng sẽ có những trường hợp toàn bộ LỚP CHỐNG THAM NHŨNG có thể sống với hệ thống con khác, đặt các liên kết giao tiếp hoặc cơ chế phân phối giữa hệ thống con của bạn và các DỊCH VỤ cấu thành giao diện của LỚP CHỐNG THAM NHŨNG. Đây là những quyết định về triển khai và thực hiện cần được đưa ra một cách thực tiễn. Chúng không ảnh hưởng đến vai trò khái niệm của LỚP CHỐNG THAM NHŨNG.

                                                                                                                                                                                                                • Nếu bạn có quyền truy cập vào hệ thống con khác, bạn có thể thấy rằng việc tái cấu trúc một chút ở đó có thể giúp công việc của bạn dễ dàng hơn. Cụ thể, hãy cố gắng viết các giao diện rõ ràng hơn cho các chức năng mà bạn sẽ sử dụng, bắt đầu với các bài kiểm tra tự động, nếu có thể.

                                                                                                                                                                                                                • Nơi yêu cầu tích hợp rộng rãi, chi phí dịch thuật sẽ tăng lên đáng kể. Có thể cần phải đưa ra sự lựa chọn trong mô hình của hệ thống đang thiết kế để giữ nó gần gũi hơn với hệ thống bên ngoài, nhằm làm cho việc dịch thuật trở nên dễ dàng hơn. Hãy thực hiện điều này một cách cẩn thận, mà không làm ảnh hưởng đến tính toàn vẹn của mô hình. Đây chỉ là điều cần làm một cách chọn lọc khi độ khó trong việc dịch thuật trở nên không thể kiểm soát. Nếu phương pháp này có vẻ là giải pháp tự nhiên nhất cho phần quan trọng của vấn đề, hãy xem xét việc làm cho tiểu hệ thống của bạn trở thành một mô hình CONFORMIST, loại bỏ việc dịch thuật.

                                                                                                                                                                                                                • Nếu hệ thống con khác đơn giản hoặc có giao diện rõ ràng, bạn có thể không cần đến FACADE.

                                                                                                                                                                                                                • Chức năng có thể được thêm vào LỚP CHỐNG THAM NHŨNG nếu nó cụ thể cho mối quan hệ của hai hệ thống con. Một bản ghi kiểm toán cho việc sử dụng hệ thống bên ngoài hoặc logic theo dõi để gỡ lỗi các cuộc gọi tới giao diện khác là hai tính năng hữu ích mà tôi nghĩ đến.

                                                                                                                                                                                                                Nhớ rằng, một LỚP CHỐNG THAM NHŨNG là một phương tiện để liên kết hai NGÀNH BÁO CÁO HẠN CHẾ. Thông thường, chúng ta đang nghĩ về một hệ thống được tạo ra bởi người khác; chúng ta có hiểu biết không đầy đủ về hệ thống và ít kiểm soát nó. Nhưng đó không phải là tình huống duy nhất trong đó bạn cần một chút đệm giữa các subsystems. Thậm chí có những tình huống mà việc kết nối hai subsystems do bạn thiết kế với một LỚP CHỐNG THAM NHŨNG có ý nghĩa, nếu chúng dựa trên các mô hình khác nhau. Có lẽ, trong trường hợp như vậy, bạn sẽ có quyền kiểm soát hoàn toàn cả hai bên và thường có thể sử dụng một lớp dịch đơn giản. Tuy nhiên, nếu hai NGÀNH BÁO CÁO HẠN CHẾ đã đi theo những con đường khác nhau nhưng vẫn có một số nhu cầu tích hợp chức năng, một LỚP CHỐNG THAM NHŨNG có thể giảm ma sát giữa chúng.

                                                                                                                                                                                                                Example
                                                                                                                                                                                                                The Legacy Booking Application

                                                                                                                                                                                                                Để có một bản phát hành đầu tiên nhỏ gọn và nhanh chóng, chúng tôi sẽ viết một ứng dụng tối thiểu có thể thiết lập một lô hàng và sau đó chuyển nó đến hệ thống kế thừa thông qua một lớp dịch để thực hiện đặt chỗ và hỗ trợ hoạt động. Bởi vì chúng tôi đã xây dựng lớp dịch cụ thể để bảo vệ mô hình phát triển của mình khỏi ảnh hưởng của thiết kế kế thừa, lớp dịch này được gọi là LỚP NGĂN CHẶN SỰ THAM NHŨNG.

                                                                                                                                                                                                                Ban đầu, LỚP CHỐNG THAM NHŨNG sẽ chấp nhận các đối tượng đại diện cho một lô hàng, chuyển đổi chúng, gửi đến hệ thống cũ và yêu cầu đặt chỗ, sau đó ghi lại xác nhận và dịch lại thành đối tượng xác nhận của thiết kế mới. Việc cách ly này sẽ cho phép chúng tôi phát triển ứng dụng mới của mình hầu như độc lập với ứng dụng cũ, mặc dù chúng tôi sẽ phải đầu tư khá nhiều vào việc dịch thuật.

                                                                                                                                                                                                                Với mỗi lần phát hành tiếp theo, hệ thống mới có thể đảm nhận nhiều chức năng hơn của hệ thống cũ hoặc đơn giản là thêm giá trị mới mà không thay thế các khả năng hiện có, tùy thuộc vào các quyết định sau này. Sự linh hoạt này, cùng với khả năng vận hành liên tục hệ thống kết hợp trong khi thực hiện chuyển đổi dần dần, có lẽ khiến việc xây dựng LỚP CHỐNG THAM NHŨNG trở nên đáng giá.

                                                                                                                                                                                                                A Cautionary Tale

                                                                                                                                                                                                                Để bảo vệ biên giới của họ khỏi các cuộc xâm lăng của các bộ lạc chiến binh du mục láng giềng, người Trung Quốc xưa đã xây dựng Vạn Lý Trường Thành. Nó không phải là một rào cản không thể vượt qua, nhưng nó cho phép thương mại được quản lý với các láng giềng trong khi cung cấp một trở ngại cho cuộc xâm lược và những ảnh hưởng không mong muốn khác. Trong suốt hai nghìn năm, nó đã xác định một ranh giới giúp nền văn minh nông nghiệp Trung Quốc tự xác định với ít sự gián đoạn hơn từ sự hỗn loạn bên ngoài.

                                                                                                                                                                                                                Mặc dù Trung Quốc có thể đã không trở thành một nền văn hóa nổi bật như vậy nếu không có Vạn Lý Trường Thành, nhưng việc xây dựng bức tường này đã tốn kém rất nhiều và đã làm phá sản ít nhất một triều đại, có thể góp phần vào sự sụp đổ của nó. Những lợi ích của các chiến lược cô lập phải được cân nhắc đối với chi phí của chúng. Có lúc cần phải thực dụng và thực hiện những điều chỉnh có tính toán đối với mô hình, để nó có thể hòa nhập một cách trơn tru hơn với các mô hình nước ngoài.

                                                                                                                                                                                                                Có chi phí cao trong bất kỳ sự tích hợp nào, từ việc TÍCH HỢP LIÊN TỤC hoàn toàn bên trong một NGỮ CẢNH GIỚI HẠN, đến những cam kết ít hơn của HẠT GIỐNG CHIA SẺ hoặc CÁC ĐỘI NGŨ PHÁT TRIỂN KHÁCH HÀNG/NHÀ CUNG CẤP, đến tính đơn phương của người TUÂN THỦ và tư thế phòng ngừa của LỚP CHỐNG THAM NHŨNG. Sự tích hợp có thể rất giá trị, nhưng luôn tốn kém. Chúng ta nên chắc chắn rằng nó thực sự cần thiết.


                                                                                                                                                                                                                  Separate Ways

                                                                                                                                                                                                                  graphics/14inf08.gif

                                                                                                                                                                                                                  Chúng ta phải xác định yêu cầu một cách tàn nhẫn. Hai nhóm chức năng không có mối quan hệ thiết yếu nào có thể tách rời khỏi nhau.

                                                                                                                                                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                  Hội nhập luôn tốn kém. Đôi khi lợi ích rất nhỏ.

                                                                                                                                                                                                                  Ngoài chi phí thông thường để phối hợp các đội, việc tích hợp lại cần các thỏa hiệp. Mô hình chuyên biệt đơn giản có thể đáp ứng một nhu cầu cụ thể phải nhường chỗ cho mô hình trừu tượng hơn có thể xử lý mọi tình huống. Có lẽ một số công nghệ hoàn toàn khác có thể cung cấp một số tính năng rất dễ dàng, nhưng khó tích hợp. Có thể một số đội có tính cách khó hòa hợp đến mức không có gì hoạt động tốt khi các đội khác cố gắng hợp tác với họ.

                                                                                                                                                                                                                  Trong nhiều trường hợp, việc tích hợp không mang lại lợi ích đáng kể. Nếu hai phần chức năng không gọi đến chức năng của nhau, hoặc không yêu cầu tương tác giữa các đối tượng được cả hai tác động, hoặc không chia sẻ dữ liệu trong quá trình hoạt động của chúng, thì việc tích hợp, ngay cả thông qua một lớp dịch, có thể không cần thiết. Chỉ vì các tính năng có liên quan trong một trường hợp sử dụng không có nghĩa là chúng phải được tích hợp.

                                                                                                                                                                                                                  Vì vậy:

                                                                                                                                                                                                                  Tuyên bố một BỐC NGUYÊN KHOẢN không có bất kỳ kết nối nào với các bối cảnh khác, cho phép các lập trình viên tìm ra những giải pháp đơn giản, chuyên biệt trong phạm vi nhỏ này.

                                                                                                                                                                                                                  Các tính năng có thể vẫn được tổ chức ở lớp middleware hoặc lớp giao diện người dùng, nhưng sẽ không có việc chia sẻ logic, và có tối thiểu việc chuyển giao dữ liệu qua các lớp dịch chuyển - tốt nhất là không có.

                                                                                                                                                                                                                  Example
                                                                                                                                                                                                                  An Insurance Project Slims Down

                                                                                                                                                                                                                  Một nhóm dự án đã đặt mục tiêu phát triển phần mềm mới cho các yêu cầu bảo hiểm, sẽ tích hợp vào một hệ thống mọi thứ mà một nhân viên chăm sóc khách hàng hoặc một điều chỉnh viên yêu cầu. Sau một năm nỗ lực, các thành viên trong nhóm đã bị mắc kẹt. Sự kết hợp giữa phân tích lưỡng lự và đầu tư lớn vào cơ sở hạ tầng đã khiến họ không có gì để trình bày trước một ban lãnh đạo ngày càng thiếu kiên nhẫn. Tình trạng nghiêm trọng hơn là phạm vi công việc mà họ đang cố gắng thực hiện đã làm họ choáng ngợp.

                                                                                                                                                                                                                  Một người quản lý dự án mới đã buộc mọi người vào một phòng trong suốt một tuần để lập kế hoạch mới. Đầu tiên, họ đã lập danh sách yêu cầu và cố gắng ước lượng độ khó của chúng cũng như phân loại độ quan trọng. Họ đã cắt bỏ những yêu cầu khó khăn và không quan trọng một cách tàn nhẫn. Sau đó, họ bắt đầu sắp xếp lại danh sách còn lại. Nhiều quyết định thông minh đã được đưa ra trong phòng đó trong tuần đó, nhưng cuối cùng, chỉ có một quyết định trở nên quan trọng. Vào một thời điểm nào đó, người ta nhận ra rằng có những tính năng mà việc tích hợp không mang lại giá trị gia tăng lớn. Ví dụ, các điều chỉnh viên cần truy cập vào một số cơ sở dữ liệu hiện có, và việc truy cập hiện tại của họ rất không thuận tiện. Nhưng, mặc dù người dùng cần có dữ liệu này, không có tính năng nào khác của hệ thống phần mềm được đề xuất sẽ sử dụng nó.

                                                                                                                                                                                                                  Các thành viên trong nhóm đã đề xuất nhiều cách để cung cấp quyền truy cập dễ dàng. Trong một trường hợp, một báo cáo quan trọng có thể được xuất dưới định dạng HTML và đặt trên intranet. Trong trường hợp khác, các điều chỉnh viên có thể được cung cấp một truy vấn chuyên biệt được viết bằng cách sử dụng một gói phần mềm chuẩn. Tất cả các chức năng này có thể được tích hợp bằng cách tổ chức các liên kết trên một trang intranet hoặc bằng cách đặt nút trên màn hình chính của người dùng.

                                                                                                                                                                                                                  Nhóm đã khởi động một loạt các dự án nhỏ mà không yêu cầu nhiều tích hợp hơn việc khởi động từ cùng một menu. Nhiều khả năng giá trị đã được cung cấp gần như ngay lập tức. Việc loại bỏ những tính năng không cần thiết đã giúp tinh gọn một tập hợp yêu cầu, dường như trong một thời gian, mang lại hy vọng cho việc bàn giao ứng dụng chính.

                                                                                                                                                                                                                  Nó có thể đã đi theo hướng đó, nhưng không may đội ngũ đã trở lại với những thói quen cũ. Họ lại khiến mình bị tê liệt. Cuối cùng, di sản duy nhất của họ lại là những ứng dụng nhỏ đã đi theo NHỮNG CON ĐƯỜNG RIÊNG của chúng.

                                                                                                                                                                                                                  graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                  Việc đi theo những con đường TÁCH BIỆT sẽ loại bỏ một số tùy chọn. Mặc dù việc tái cấu trúc liên tục có thể cuối cùng khôi phục bất kỳ quyết định nào, nhưng thật khó để hợp nhất các mô hình đã phát triển trong sự cô lập hoàn toàn. Nếu việc tích hợp trở nên cần thiết sau này, các lớp dịch thuật sẽ là cần thiết và có thể phức tạp. Tất nhiên, đó là điều bạn sẽ phải đối mặt dù sao đi nữa.

                                                                                                                                                                                                                  Bây giờ, quay trở lại với những mối quan hệ hợp tác hơn, hãy cùng tìm kiếm các cách để mở rộng sự tích hợp.


                                                                                                                                                                                                                    Open Host Service

                                                                                                                                                                                                                    Thường thì đối với mỗi BOUND CONTEXT, bạn sẽ định nghĩa một lớp dịch cho mỗi thành phần bên ngoài CONTEXT mà bạn cần tích hợp. Khi tích hợp là một lần duy nhất, cách tiếp cận này cho phép chèn một lớp dịch cho mỗi hệ thống bên ngoài, tránh làm hỏng các mô hình với chi phí tối thiểu. Nhưng khi bạn thấy hệ thống con của mình có nhu cầu cao, bạn có thể cần một cách tiếp cận linh hoạt hơn.

                                                                                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                    Khi một tiểu hệ thống phải được tích hợp với nhiều tiểu hệ thống khác, việc tùy chỉnh một trình dịch cho mỗi tiểu hệ thống có thể làm chậm lại đội ngũ. Có ngày càng nhiều thứ cần bảo trì và càng nhiều thứ cần lo lắng khi có sự thay đổi.

                                                                                                                                                                                                                    Nhóm có thể đang làm cùng một việc nhiều lần. Nếu có sự mạch lạc nào đó trong hệ thống con, có lẽ có thể mô tả nó như một tập hợp DỊCH VỤ đáp ứng các nhu cầu chung của các hệ thống con khác.

                                                                                                                                                                                                                    Thiết kế một giao thức đủ rõ ràng để được hiểu và sử dụng bởi nhiều nhóm là rất khó khăn, vì vậy nó chỉ có lợi khi các tài nguyên của tiểu hệ thống có thể được mô tả như một tập hợp DỊCH VỤ gắn kết và khi có một số lượng tích hợp đáng kể. Trong những trường hợp đó, nó có thể tạo ra sự khác biệt giữa chế độ bảo trì và phát triển tiếp tục.

                                                                                                                                                                                                                    Do đó:

                                                                                                                                                                                                                    Xác định một giao thức cung cấp quyền truy cập vào hệ thống con của bạn như một tập hợp DỊCH VỤ. Mở giao thức để tất cả những ai cần tích hợp với bạn có thể sử dụng nó. Nâng cao và mở rộng giao thức để xử lý các yêu cầu tích hợp mới, ngoại trừ khi một nhóm duy nhất có những nhu cầu đặc thù. Sau đó, sử dụng một bộ chuyển đổi đặc biệt để bổ sung giao thức cho trường hợp đặc biệt đó để giao thức chung có thể giữ được sự đơn giản và mạch lạc.

                                                                                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                    Sự hình thức hóa giao tiếp này đòi hỏi một từ vựng mô hình chung - cơ sở của các giao diện DỊCH VỤ. Do đó, các tiểu hệ thống khác trở nên bị ràng buộc với mô hình của HOST MỞ, và các nhóm khác buộc phải học phương ngữ cụ thể được sử dụng bởi nhóm HOST. Trong một số tình huống, việc sử dụng một NGÔN NGỮ ĐƯỢC CÔNG BỐ nổi tiếng làm mô hình trao đổi có thể giảm thiểu độ ràng buộc và dễ dàng hiểu hơn.


                                                                                                                                                                                                                      Published Language

                                                                                                                                                                                                                      Việc dịch giữa các mô hình của hai BOUNDED CONTEXTS yêu cầu một ngôn ngữ chung.

                                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                      Khi hai mô hình miền phải đồng tồn tại và thông tin phải truyền giữa chúng, quá trình dịch chuyển này có thể trở nên phức tạp và khó tài liệu hóa cũng như hiểu. Nếu chúng ta đang xây dựng một hệ thống mới, chúng ta thường tin rằng mô hình mới của mình là tốt nhất, vì vậy chúng ta sẽ nghĩ đến việc dịch chuyển trực tiếp vào đó. Nhưng đôi khi chúng ta đang nâng cấp một tập hợp các hệ thống cũ và cố gắng tích hợp chúng. Việc chọn một mô hình lộn xộn hơn so với mô hình khác có thể là sự lựa chọn của điều kém hơn trong hai điều xấu.

                                                                                                                                                                                                                      Một tình huống khác: Khi các doanh nghiệp muốn trao đổi thông tin với nhau, họ làm điều đó như thế nào? Không chỉ không thực tế khi mong đợi một bên áp dụng mô hình miền của bên kia, mà điều đó cũng có thể không mong muốn cho cả hai bên. Một mô hình miền được phát triển để giải quyết các vấn đề cho người sử dụng của nó; một mô hình như vậy có thể chứa những đặc điểm làm phức tạp không cần thiết cho việc giao tiếp với một hệ thống khác. Ngoài ra, nếu mô hình hỗ trợ một trong các ứng dụng được sử dụng làm phương tiện giao tiếp, nó không thể bị thay đổi tự do để đáp ứng những nhu cầu mới, mà phải rất ổn định để hỗ trợ vai trò giao tiếp liên tục.

                                                                                                                                                                                                                      Việc dịch trực tiếp từ và đến các mô hình miền hiện có có thể không phải là một giải pháp tốt. Những mô hình này có thể quá phức tạp hoặc được phân tách kém. Chúng có thể không được tài liệu hóa. Nếu một trong số chúng được sử dụng như một ngôn ngữ trao đổi dữ liệu, nó về cơ bản sẽ bị đóng băng và không thể đáp ứng nhu cầu phát triển mới.

                                                                                                                                                                                                                      DỊCH VỤ MỞ HOST sử dụng một giao thức tiêu chuẩn cho việc tích hợp nhiều bên. Nó áp dụng một mô hình của miền để trao đổi giữa các hệ thống, mặc dù mô hình đó có thể không được sử dụng nội bộ bởi các hệ thống đó. Ở đây, chúng tôi đi một bước xa hơn và công bố ngôn ngữ đó, hoặc tìm một ngôn ngữ đã được công bố. Bằng cách công bố, tôi chỉ có ý nói rằng ngôn ngữ này có sẵn cho cộng đồng có thể quan tâm đến việc sử dụng nó, và được tài liệu hóa đủ để cho phép các cách hiểu độc lập trở nên tương thích.

                                                                                                                                                                                                                      Gần đây, thế giới thương mại điện tử đã trở nên rất phấn khích về một công nghệ mới: Ngôn ngữ Đánh dấu Mở rộng (XML) hứa hẹn sẽ làm cho việc trao đổi dữ liệu trở nên dễ dàng hơn nhiều. Một tính năng rất có giá trị của XML là, thông qua định nghĩa loại tài liệu (DTD) hoặc thông qua các schema XML, XML cho phép định nghĩa chính thức một ngôn ngữ miền chuyên biệt mà vào đó dữ liệu có thể được dịch. Các nhóm ngành công nghiệp đã bắt đầu hình thành với mục đích định nghĩa một DTD tiêu chuẩn duy nhất cho ngành của họ, để thông tin về công thức hóa học hoặc mã gen có thể được truyền đạt giữa nhiều bên. Về cơ bản, các nhóm này đang tạo ra một mô hình miền chia sẻ dưới dạng định nghĩa ngôn ngữ.

                                                                                                                                                                                                                      Vì vậy:

                                                                                                                                                                                                                      Sử dụng một ngôn ngữ chung được tài liệu hóa tốt, có thể diễn đạt thông tin miền cần thiết như một phương tiện giao tiếp chung, dịch ra và vào ngôn ngữ đó khi cần.

                                                                                                                                                                                                                      Ngôn ngữ không cần phải được tạo ra từ đầu. Nhiều năm trước, tôi đã được một công ty ký hợp đồng để phát triển một sản phẩm phần mềm viết bằng Smalltalk, sử dụng DB2 để lưu trữ dữ liệu. Công ty muốn có sự linh hoạt trong việc phân phối phần mềm cho người dùng mà không cần giấy phép DB2 và đã ký hợp đồng với tôi để xây dựng một giao diện đến Btrieve, một công cụ cơ sở dữ liệu nhẹ hơn có giấy phép phân phối runtime miễn phí. Btrieve không hoàn toàn là quan hệ, nhưng khách hàng của tôi chỉ sử dụng một phần nhỏ sức mạnh của DB2 và nằm trong giới hạn tối thiểu của hai cơ sở dữ liệu. Các nhà phát triển của công ty đã xây dựng trên DB2 một số trừu tượng liên quan đến việc lưu trữ đối tượng. Tôi quyết định sử dụng công việc này làm giao diện cho thành phần Btrieve của tôi.

                                                                                                                                                                                                                      Cách tiếp cận này đã hoạt động. Phần mềm đã tích hợp một cách suôn sẻ với hệ thống của khách hàng. Tuy nhiên, việc thiếu một thông số kỹ thuật chính thức hoặc tài liệu về các trừu tượng của các đối tượng bền vững trong thiết kế của khách hàng đã khiến tôi phải tốn nhiều công sức để tìm hiểu yêu cầu của thành phần mới. Ngoài ra, không có nhiều cơ hội để tái sử dụng thành phần này để di chuyển một ứng dụng khác từ DB2 sang Btrieve. Và phần mềm mới đã làm cho mô hình bền vững của công ty trở nên sâu sắc hơn, vì vậy việc tái cấu trúc mô hình các đối tượng bền vững sẽ còn khó khăn hơn nhiều.

                                                                                                                                                                                                                      Một cách tốt hơn có thể là xác định tập con của giao diện DB2 mà công ty đang sử dụng và sau đó hỗ trợ điều đó. Giao diện của DB2 bao gồm SQL và một số giao thức độc quyền. Mặc dù rất phức tạp, nhưng giao diện này được xác định chặt chẽ và được tài liệu hóa đầy đủ. Độ phức tạp đã được giảm bớt vì chỉ một tập con nhỏ của giao diện được sử dụng. Nếu một thành phần được phát triển để mô phỏng tập con cần thiết của giao diện DB2, nó có thể được tài liệu hóa rất hiệu quả cho các nhà phát triển chỉ bằng cách xác định tập con đó. Ứng dụng mà nó được tích hợp vào đã biết cách giao tiếp với DB2, vì vậy sẽ không cần thêm nhiều công việc. Thiết kế lại trong tương lai của lớp duy trì sẽ chỉ bị giới hạn trong việc sử dụng tập con DB2, như trước khi nâng cấp.

                                                                                                                                                                                                                      Giao diện DB2 là một ví dụ về NGÔN NGỮ ĐƯỢC CÔNG BỐ. Trong trường hợp này, hai mô hình không thuộc miền kinh doanh, nhưng tất cả các nguyên tắc vẫn áp dụng như nhau. Bởi vì một trong các mô hình trong sự hợp tác đã là một NGÔN NGỮ ĐƯỢC CÔNG BỐ, không cần phải giới thiệu một ngôn ngữ thứ ba.

                                                                                                                                                                                                                      Example
                                                                                                                                                                                                                      A PUBLISHED LANGUAGE for Chemistry

                                                                                                                                                                                                                      Có vô số chương trình được sử dụng để lập danh mục, phân tích và thao tác các công thức hóa học trong ngành công nghiệp và học thuật. Việc trao đổi dữ liệu luôn gặp khó khăn, bởi vì hầu hết các chương trình đều sử dụng một mô hình miền khác nhau để đại diện cho các cấu trúc hóa học. Và dĩ nhiên, hầu hết chúng được viết bằng những ngôn ngữ như FORTRAN, mà không thể diễn đạt đầy đủ mô hình miền. Mỗi khi ai đó muốn chia sẻ dữ liệu, họ phải tìm hiểu chi tiết về cơ sở dữ liệu của hệ thống khác và phát triển một loại hệ thống chuyển đổi nào đó.

                                                                                                                                                                                                                      Nhập vào Ngôn ngữ Đánh dấu Hóa học (CML), một phương ngữ của XML được tạo ra như một ngôn ngữ trao đổi chung cho lĩnh vực này, được phát triển và quản lý bởi một nhóm đại diện cho các học giả và ngành công nghiệp (Murray-Rust et al. 1995).

                                                                                                                                                                                                                      Thông tin hóa học rất phức tạp và đa dạng, và nó luôn thay đổi với các phát hiện mới. Vì vậy, họ đã phát triển một ngôn ngữ có thể mô tả những điều cơ bản, chẳng hạn như công thức hóa học của các phân tử hữu cơ và vô cơ, trình tự protein, quang phổ hoặc các đại lượng vật lý.

                                                                                                                                                                                                                      Bây giờ khi ngôn ngữ đã được công bố, các công cụ có thể được phát triển mà trước đây sẽ không xứng đáng để viết ra, khi chúng chỉ có thể sử dụng cho một cơ sở dữ liệu. Ví dụ, một ứng dụng Java, gọi là JUMBO Browser, đã được phát triển để tạo ra các hình ảnh đồ họa của các cấu trúc hóa học được lưu trữ trong CML. Vì vậy, nếu bạn lưu trữ dữ liệu của mình ở định dạng CML, bạn sẽ có quyền truy cập vào các công cụ trực quan như vậy.

                                                                                                                                                                                                                      Trên thực tế, CML đã thu được lợi ích kép bằng cách sử dụng XML, một loại "siêu ngôn ngữ đã được công bố." Đường cong học tập của CML được làm phẳng nhờ sự quen thuộc của mọi người với XML; việc triển khai trở nên dễ dàng hơn nhờ các công cụ sẵn có, chẳng hạn như các trình phân tích cú pháp; và tài liệu được hỗ trợ bởi nhiều cuốn sách viết về tất cả các khía cạnh của việc xử lý XML.

                                                                                                                                                                                                                      Dưới đây là một mẫu nhỏ của CML. Nó chỉ mơ hồ dễ hiểu đối với những người không chuyên như tôi, nhưng nguyên tắc thì rõ ràng.

                                                                                                                                                                                                                      [View full width]
                                                                                                                                                                                                                      <CML.ARR ID="array3" EL.TYPE=FLOAT NAME="ATOMIC ORBITAL ELECTRON POPULATIONS" SIZE=30 GLO graphics/ccc.gif.ENT=CML.THE.AOEPOPS> 1.17947 0.95091 0.97175 1.00000 1.17947 0.95090 0.97174 1.00000 1.17946 0.98215 0.94049 1.00000 1.17946 0.95091 0.97174 1.00000 1.17946 0.95091 0.97174 1.00000 1.17946 0.98215 0.94049 1.00000 0.89789 0.89790 0.89789 0.89789 0.89790 0.89788 </CML.ARR> 

                                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif


                                                                                                                                                                                                                        Unifying an Elephant

                                                                                                                                                                                                                        Có sáu người đàn ông của Ấn Độ Rất thích học hỏi, Họ đã đi để xem voi (Dù tất cả đều mù), Mỗi người bằng quan sát Có thể thỏa mãn tâm trí mình. Người đầu tiên tiếp cận con voi, Và tình cờ va phải Vào bên hông rộng và vững của nó, Liền bắt đầu la lên: "Chúa ơi! Nhưng con voi Giống như một bức tường!" Người thứ ba tiến lại con vật, Và tình cờ nắm Chiếc vòi đang quằn quại trong tay, Vậy là dũng cảm nói lên: "Tôi thấy," anh ta nói, "con voi Giống như một con rắn." Người thứ tư đưa tay ra đầy nhiệt tình, Và sờ quanh đầu gối. "Những gì mà con thú kỳ diệu này giống nhất Rất rõ ràng," anh ta nói; "Rõ ràng con voi Giống như một cái cây!" Người thứ sáu vừa mới bắt đầu Sờ soạng quanh con vật, Thì nắm lấy cái đuôi swinging Rơi vào tầm tay hắn, "Tôi thấy," anh ta nói, "con voi Giống như một sợi dây thừng!" Và như vậy, những người đàn ông của Ấn Độ Tranh luận ồn ào và lâu dài, Mỗi người trong ý kiến riêng Cực kỳ cứng nhắc và mạnh mẽ, Mặc dù mỗi người đều đúng một phần, Và tất cả đều sai!

                                                                                                                                                                                                                        Từ "Những người mù và con voi," của John Godfrey Saxe (1816–1887), dựa trên một câu chuyện trong Udana, một văn bản Hindu.

                                                                                                                                                                                                                        Tùy thuộc vào mục tiêu của họ khi tương tác với con voi, các người mù khác nhau có thể vẫn tiến bộ, ngay cả khi họ không hoàn toàn đồng ý về bản chất của con voi. Nếu không cần tích hợp, thì việc các mô hình không thống nhất là không quan trọng. Nếu họ cần một sự tích hợp nào đó, họ có thể không thực sự phải đồng ý về khái niệm con voi, nhưng họ sẽ nhận được rất nhiều giá trị chỉ bằng việc nhận ra rằng họ không đồng ý. Bằng cách này, ít nhất họ không vô tình nói trái ngược với nhau.

                                                                                                                                                                                                                        Các sơ đồ trong Hình 14.9 là những biểu diễn UML của các mô hình mà những người mù đã hình thành về con voi. Sau khi thiết lập các BOUND CONTEXTS riêng biệt, tình huống trở nên rõ ràng đủ để họ tìm ra cách giao tiếp với nhau về một vài khía cạnh mà họ quan tâm chung: vị trí của con voi, có lẽ.

                                                                                                                                                                                                                        Figure 14.9. Four contexts: no integration

                                                                                                                                                                                                                        graphics/14fig09.gif

                                                                                                                                                                                                                        Figure 14.10. Four contexts: minimal integration

                                                                                                                                                                                                                        graphics/14fig10.gif

                                                                                                                                                                                                                        Khi những người mù muốn chia sẻ thêm thông tin về con voi, giá trị của việc chia sẻ một Bounded Context đơn lẻ tăng lên. Nhưng việc thống nhất các mô hình khác nhau là một thách thức. Không ai trong số họ có khả năng từ bỏ mô hình của mình để áp dụng mô hình của người khác. Sau tất cả, người đã chạm vào đuôi biết rằng con voi không giống như một cái cây, và mô hình đó sẽ vô nghĩa và không hữu ích với anh ta. Việc thống nhất nhiều mô hình gần như luôn có nghĩa là tạo ra một mô hình mới.

                                                                                                                                                                                                                        Với một chút trí tưởng tượng và cuộc thảo luận tiếp tục (có thể căng thẳng), những người mù cuối cùng có thể nhận ra rằng họ đang mô tả và xây dựng các phần khác nhau của một tổng thể lớn hơn. Đối với nhiều mục đích, việc thống nhất phần và toàn thể có thể không yêu cầu quá nhiều công việc bổ sung. Ít nhất, giai đoạn đầu tiên của việc tích hợp chỉ cần tìm ra cách mà các phần liên quan với nhau. Có thể đối với một số nhu cầu, việc xem một con voi như một bức tường, được nâng đỡ bởi các thân cây, với một sợi dây ở một đầu và một con rắn ở đầu kia là đủ.

                                                                                                                                                                                                                        Figure 14.11. One context: crude integration

                                                                                                                                                                                                                        graphics/14fig11.gif

                                                                                                                                                                                                                        Việc thống nhất các mô hình voi khác nhau dễ hơn so với hầu hết các vụ sáp nhập tương tự. Thật không may, đây là trường hợp ngoại lệ khi hai mô hình hoàn toàn mô tả các phần khác nhau của tổng thể, mặc dù đây thường là một khía cạnh của sự khác biệt. Vấn đề trở nên khó khăn hơn khi hai mô hình nhìn vào cùng một phần theo cách khác nhau. Nếu hai người chạm vào cái vòi và một người mô tả nó như một con rắn và người kia mô tả nó như một ống nước chữa cháy, họ sẽ gặp nhiều khó khăn hơn. Không ai có thể chấp nhận mô hình của người kia, vì nó mâu thuẫn với kinh nghiệm của chính mình. Thực tế, họ cần một sự trừu tượng mới kết hợp yếu tố "sống động" của một con rắn với chức năng phun nước của một ống nước chữa cháy, nhưng bỏ qua những hàm ý không phù hợp của các mô hình đầu tiên, chẳng hạn như kỳ vọng về những chiếc răng có thể chứa nọc độc, hoặc khả năng rời khỏi cơ thể và cuộn lại thành một ngăn trong xe chữa cháy.

                                                                                                                                                                                                                        Mặc dù chúng tôi đã kết hợp các phần lại thành một tổng thể, mô hình thu được vẫn còn thô sơ. Nó thiếu tính nhất quán, thiếu cảm giác theo dõi các đường nét của một lĩnh vực cơ bản. Những hiểu biết mới có thể dẫn đến một mô hình sâu sắc hơn trong quá trình tinh chỉnh liên tục. Các yêu cầu ứng dụng mới cũng có thể buộc phải chuyển sang một mô hình sâu sắc hơn. Nếu con voi bắt đầu di chuyển, lý thuyết "cây" sẽ không còn phù hợp, và những người mô hình mù có thể sẽ đột phá vào khái niệm "chân."

                                                                                                                                                                                                                        Figure 14.12. One context: deeper model

                                                                                                                                                                                                                        graphics/14fig12.gif

                                                                                                                                                                                                                        Quá trình tích hợp mô hình lần hai này có xu hướng loại bỏ những khía cạnh thiếu chính xác hoặc không liên quan của các mô hình cá nhân và tạo ra những khái niệm mới—trong trường hợp này, "động vật" với các phần "cái vòi", "chân", "thân", và "đuôi"—mỗi phần đều có các thuộc tính riêng và mối quan hệ rõ ràng với các phần khác. Sự hợp nhất mô hình thành công, phần lớn, dựa vào chủ nghĩa tối giản. Cái vòi của một con voi vừa nhiều hơn vừa ít hơn một con rắn, nhưng phần "ít" có lẽ quan trọng hơn phần "nhiều". Tốt hơn là không có khả năng phun nước hơn là sở hữu một đặc điểm răng độc sai lệch.

                                                                                                                                                                                                                        Nếu mục tiêu đơn giản là tìm con voi, thì việc dịch giữa cách diễn đạt vị trí của mỗi mô hình sẽ đủ. Khi cần nhiều sự tích hợp hơn, mô hình thống nhất không nhất thiết phải đạt được độ chín muồi hoàn toàn trong phiên bản đầu tiên. Có thể đủ cho một số nhu cầu xem con voi như một bức tường, được nâng đỡ bởi các thân cây, với một sợi dây ở một đầu và một con rắn ở đầu bên kia. Sau này, được thúc đẩy bởi các yêu cầu mới và bởi sự hiểu biết cũng như giao tiếp cải thiện, mô hình có thể được đào sâu và tinh chỉnh.

                                                                                                                                                                                                                        Nhận ra nhiều mô hình miền mâu thuẫn thực sự chỉ là đối mặt với thực tế. Bằng cách định nghĩa rõ ràng một ngữ cảnh trong đó mỗi mô hình áp dụng, bạn có thể duy trì tính toàn vẹn của từng mô hình và thấy rõ những tác động của bất kỳ giao diện nào mà bạn muốn tạo ra giữa chúng. Không có cách nào cho những người mù thấy được toàn bộ con voi, nhưng vấn đề của họ sẽ có thể quản lý được nếu chỉ cần họ nhận ra sự không hoàn thiện trong nhận thức của mình.


                                                                                                                                                                                                                          Choosing Your Model Context Strategy

                                                                                                                                                                                                                          Điều quan trọng là luôn luôn vẽ BẢN ĐỒ NGỮ CẢNH để phản ánh tình hình hiện tại tại bất kỳ thời điểm nào. Khi điều đó đã được thực hiện, bạn có thể muốn thay đổi thực tế đó. Bây giờ bạn có thể bắt đầu chọn một cách có ý thức các ranh giới và mối quan hệ của NGỮ CẢNH. Dưới đây là một số hướng dẫn.

                                                                                                                                                                                                                          Team Decision or Higher

                                                                                                                                                                                                                          Đầu tiên, các đội phải đưa ra quyết định về việc định nghĩa các NGỮ CẢNH HẠN CHẾ và loại mối quan hệ nào sẽ có giữa chúng. Các đội phải đưa ra những quyết định này, hoặc ít nhất là những quyết định cần được truyền đạt đến toàn bộ đội và được mọi người hiểu. Thực tế, những quyết định như vậy thường liên quan đến các thỏa thuận ngoài đội của bạn. Về mặt lý thuyết, quyết định về việc mở rộng hay phân tách các NGỮ CẢNH HẠN CHẾ nên dựa trên sự đánh đổi giữa chi phí và lợi ích giữa giá trị của hành động độc lập của đội và giá trị của sự tích hợp trực tiếp và phong phú. Trên thực tế, các mối quan hệ chính trị giữa các đội thường xác định cách thức hệ thống được tích hợp. Một sự hợp nhất về mặt kỹ thuật có thể không khả thi do cấu trúc báo cáo. Quản lý có thể chỉ đạo một sự sáp nhập cồng kềnh. Bạn không luôn luôn có được những gì bạn muốn, nhưng ít nhất bạn có thể đánh giá và truyền đạt một chút về chi phí phát sinh và thực hiện các bước để giảm thiểu nó. Bắt đầu với một BẢN ĐỒ NGỮ CẢNH thực tế và hãy thực tế trong việc lựa chọn các chuyển đổi.

                                                                                                                                                                                                                          Putting Ourselves in Context

                                                                                                                                                                                                                          Khi chúng ta làm việc trên một dự án phần mềm, chúng ta chủ yếu quan tâm đến các phần của hệ thống mà nhóm của chúng ta đang thay đổi (cái được gọi là "hệ thống đang thiết kế") và thứ hai là các hệ thống mà nó sẽ giao tiếp. Trong một trường hợp điển hình, hệ thống đang thiết kế sẽ được chia thành một hoặc hai BOUND CONTEXT mà các đội phát triển chính sẽ làm việc, có thể với một hoặc hai CONTEXT khác trong vai trò hỗ trợ. Ngoài ra, còn có các mối quan hệ giữa những CONTEXT này và các hệ thống bên ngoài. Đây là một cái nhìn đơn giản, điển hình, để đưa ra sự kỳ vọng thô cho những gì bạn có thể gặp phải.

                                                                                                                                                                                                                          Chúng ta thực sự là một phần của ngữ cảnh chính mà chúng ta đang làm việc trong đó, và điều đó chắc chắn sẽ được phản ánh trong BẢN ĐỒ NGỮ CẢNH của chúng ta. Điều này không phải là vấn đề nếu chúng ta nhận thức được sự thiên lệch và chú ý đến khi nào chúng ta vượt ra ngoài giới hạn tính khả thi của BẢN ĐỒ đó.

                                                                                                                                                                                                                          Transforming Boundaries

                                                                                                                                                                                                                          Có một sự đa dạng không giới hạn về các tình huống và vô số tùy chọn để xác định ranh giới của các BỐI CẢNH GIỚI HẠN. Nhưng thường thì cuộc đấu tranh là để cân bằng một tập hợp nào đó của các lực lượng sau đây:

                                                                                                                                                                                                                          Favoring Larger BOUNDED CONTEXTS
                                                                                                                                                                                                                          • Luồng giữa các tác vụ của người dùng trôi chảy hơn khi nhiều vấn đề được xử lý bằng một mô hình thống nhất.

                                                                                                                                                                                                                          • Dễ hiểu hơn khi có một mô hình nhất quán hơn là hai mô hình riêng biệt cộng với các ánh xạ.

                                                                                                                                                                                                                          • Việc dịch giữa hai mô hình có thể khó khăn (đôi khi là không thể).

                                                                                                                                                                                                                          • Ngôn ngữ chung thúc đẩy sự giao tiếp rõ ràng trong nhóm.

                                                                                                                                                                                                                          Favoring Smaller BOUNDED CONTEXTS
                                                                                                                                                                                                                          • Giảm thiểu chi phí giao tiếp giữa các nhà phát triển.

                                                                                                                                                                                                                          • TÍCH HỢP LIÊN TỤC sẽ dễ dàng hơn với các nhóm nhỏ và mã nguồn nhỏ.

                                                                                                                                                                                                                          • Các ngữ cảnh lớn hơn có thể đòi hỏi những mô hình trừu tượng linh hoạt hơn, đòi hỏi những kỹ năng đang khan hiếm.

                                                                                                                                                                                                                          • Các mô hình khác nhau có thể phục vụ cho các nhu cầu đặc biệt hoặc bao gồm các thuật ngữ của các nhóm người dùng chuyên biệt, cùng với các phương ngữ chuyên biệt của NGÔN NGỮ TỒN TẠI.

                                                                                                                                                                                                                          Việc tích hợp sâu giữa các ngữ cảnh giới hạn là không thực tế. Sự tích hợp chỉ giới hạn ở những phần của một mô hình có thể được diễn đạt một cách nghiêm ngặt theo mô hình khác, và ngay cả mức độ tích hợp này cũng có thể tốn nhiều nỗ lực. Điều này là hợp lý khi chỉ có một giao diện nhỏ giữa hai hệ thống.

                                                                                                                                                                                                                          Accepting That Which We Cannot Change: Delineating the External Systems

                                                                                                                                                                                                                          Tốt nhất là bắt đầu với những quyết định dễ nhất. Một số tiểu hệ thống sẽ rõ ràng không nằm trong bất kỳ BỐI CẢNH RÀNG BUỘC nào của hệ thống đang phát triển. Ví dụ có thể là các hệ thống di sản lớn mà bạn không thay thế ngay lập tức và các hệ thống bên ngoài cung cấp dịch vụ mà bạn cần. Bạn có thể xác định những cái này ngay lập tức và chuẩn bị để tách chúng ra khỏi thiết kế của bạn.

                                                                                                                                                                                                                          Ở đây, chúng ta cần phải cẩn thận về những giả định của mình. Thật tiện lợi khi nghĩ rằng mỗi hệ thống này đều tạo thành một BOUND CONTEXT riêng, nhưng hầu hết các hệ thống bên ngoài chỉ yếu đáp ứng định nghĩa này. Đầu tiên, một BOUNDED CONTEXT được định nghĩa bởi ý định thống nhất mô hình trong những ranh giới nhất định. Bạn có thể có quyền kiểm soát việc bảo trì hệ thống kế thừa, trong trường hợp đó bạn có thể tuyên bố ý định, hoặc đội ngũ kế thừa có thể đã được phối hợp tốt và thực hiện một hình thức không chính thức của CONTINUOUS INTEGRATION, nhưng đừng chỉ mặc định điều đó. Hãy kiểm tra nó, và nếu việc phát triển không được tích hợp tốt, hãy đặc biệt cẩn thận. Không phải hiếm gặp việc tìm thấy những mâu thuẫn ngữ nghĩa ở những phần khác nhau của những hệ thống như vậy.

                                                                                                                                                                                                                          Relationships with the External Systems

                                                                                                                                                                                                                          Có ba mô hình có thể áp dụng ở đây. Đầu tiên, xem xét CÁC CÁCH RIÊNG BIỆT. Đúng là bạn sẽ không bao gồm chúng nếu bạn không cần tích hợp. Nhưng hãy chắc chắn rằng điều đó là đúng. Liệu có đủ để cung cấp cho người dùng quyền truy cập dễ dàng vào cả hai hệ thống không? Tích hợp thì tốn kém và gây phân tâm, vì vậy hãy giảm bớt gánh nặng cho dự án của bạn nhiều nhất có thể.

                                                                                                                                                                                                                          Nếu việc tích hợp thật sự cần thiết, bạn có thể chọn giữa hai cực đoan: CONFORMIST (Người tuân thủ) hoặc LỚP CHỐNG THAM NHŨNG. Không vui chút nào khi trở thành một CONFORMIST. Sự sáng tạo và các tùy chọn cho các chức năng mới của bạn sẽ bị hạn chế. Trong việc xây dựng một hệ thống lớn mới, khó có khả năng thực tiễn khi tuân theo mô hình của một hệ thống cũ hoặc hệ thống bên ngoài (sau tất cả, tại sao bạn lại xây dựng một hệ thống mới?). Tuy nhiên, việc giữ nguyên mô hình cũ có thể là hợp lý trong trường hợp mở rộng ngoại vi cho một hệ thống lớn sẽ tiếp tục là hệ thống chi phối. Ví dụ về sự lựa chọn này bao gồm các công cụ hỗ trợ quyết định nhẹ nhàng thường được viết bằng Excel hoặc các công cụ đơn giản khác. Nếu ứng dụng của bạn thực sự là một mở rộng cho hệ thống hiện tại và giao diện của bạn với hệ thống đó sẽ lớn, việc dịch chuyển giữa CÁC BỐI CẢNH có thể dễ dàng trở thành một công việc lớn hơn chính chức năng của ứng dụng. Và vẫn còn một chút không gian cho công việc thiết kế tốt, ngay cả khi bạn đã đặt mình trong BỐI CẢNH HẠN CHẾ của hệ thống khác. Nếu có một mô hình miền rõ ràng phía sau hệ thống khác, bạn có thể cải thiện việc triển khai của mình bằng cách làm cho mô hình đó rõ ràng hơn so với trong hệ thống cũ, miễn là bạn hoàn toàn tuân thủ mô hình cũ. Nếu bạn quyết định thiết kế theo kiểu CONFORMIST, bạn phải làm điều đó với tất cả tâm huyết. Bạn chỉ giới hạn mình trong việc mở rộng, mà không thay đổi mô hình hiện có.

                                                                                                                                                                                                                          Khi chức năng của hệ thống đang được thiết kế sẽ phức tạp hơn so với việc mở rộng một hệ thống hiện có, nơi giao diện của bạn với hệ thống khác rất nhỏ, hoặc nơi hệ thống khác được thiết kế rất kém, bạn thực sự sẽ muốn có một BOUND CONTEXT riêng, điều này có nghĩa là xây dựng một lớp dịch thuật, hoặc thậm chí là một LỚP CHỐNG THAM NHŨNG.

                                                                                                                                                                                                                          The System Under Design

                                                                                                                                                                                                                          Phần mềm mà nhóm dự án của bạn đang thực sự xây dựng là hệ thống đang được thiết kế. Bạn có thể công bố CÁC BỐI CẢNH ĐƯỢC GIỚI HẠN trong khu vực này và áp dụng TÍCH HỢP LIÊN TỤC trong mỗi bối cảnh để giữ cho chúng thống nhất. Nhưng bạn nên có bao nhiêu bối cảnh? Chúng nên có mối quan hệ gì với nhau? Các câu trả lời không rõ ràng như với các hệ thống bên ngoài vì chúng ta có nhiều tự do và kiểm soát hơn.

                                                                                                                                                                                                                          Nó có thể khá đơn giản: một BỐI CẢNH HẠN CHẾ duy nhất cho toàn bộ hệ thống đang được thiết kế. Chẳng hạn, đây sẽ là một lựa chọn hợp lý cho một nhóm có ít hơn mười người làm việc trên các chức năng có liên quan mật thiết với nhau.

                                                                                                                                                                                                                          Khi đội ngũ ngày càng lớn, việc TÍCH HỢP LIÊN TỤC có thể trở nên khó khăn (mặc dù tôi đã thấy nó được duy trì cho các đội lớn hơn một chút). Bạn có thể tìm kiếm một KERNEL CHIA SẺ và tách ra các tập hợp chức năng tương đối độc lập thành các BOUNDED CONTEXT riêng biệt, mỗi cái có ít hơn mười người. Nếu tất cả các phụ thuộc giữa hai cái này đi theo một hướng, bạn có thể thiết lập CÁC ĐỘI PHÁT TRIỂN KHÁCH HÀNG/NHÀ CUNG CẤP.

                                                                                                                                                                                                                          Bạn có thể nhận thấy rằng tư duy của hai nhóm hoàn toàn khác nhau đến mức những nỗ lực mô hình của họ liên tục va chạm. Có thể họ thực sự cần những điều hoàn toàn khác nhau từ mô hình, hoặc chỉ đơn giản là khác biệt về kiến thức nền tảng, hoặc có thể là kết quả của cấu trúc quản lý mà dự án đang tồn tại. Nếu nguyên nhân của sự va chạm là điều bạn không thể thay đổi, hoặc không muốn thay đổi, bạn có thể chọn để cho các mô hình đi theo HƯỚNG RIÊNG BIỆT. Khi cần tích hợp, một lớp dịch có thể được phát triển và duy trì chung bởi hai nhóm như là điểm duy nhất của SỰ TÍCH HỢP LIÊN TỤC. Điều này trái ngược với việc tích hợp với các hệ thống bên ngoài, nơi mà LỚP CHỐNG THAM NHŨNG thường phải thích nghi với hệ thống khác như nó đang có mà không có nhiều hỗ trợ từ phía bên kia.

                                                                                                                                                                                                                          Nói chung, có một sự tương ứng giữa một đội và một BOUNDED CONTEXT. Một đội có thể duy trì nhiều BOUNDED CONTEXTS, nhưng rất khó (dù không phải là không thể) để nhiều đội cùng làm việc trên một BOUNDED CONTEXT.

                                                                                                                                                                                                                          Catering to Special Needs with Distinct Models

                                                                                                                                                                                                                          Các nhóm khác nhau trong cùng một doanh nghiệp thường phát triển những thuật ngữ chuyên biệt của riêng họ, có thể đã khác biệt so với nhau. Những thuật ngữ địa phương này có thể rất chính xác và phù hợp với nhu cầu của họ. Việc thay đổi chúng (chẳng hạn, bằng cách áp đặt một thuật ngữ tiêu chuẩn hóa trên toàn doanh nghiệp) đòi hỏi một quá trình đào tạo và phân tích sâu rộng để giải quyết sự khác biệt. Ngay cả khi đó, thuật ngữ mới có thể không phục vụ tốt như phiên bản đã được tinh chỉnh mà họ đã có.

                                                                                                                                                                                                                          Bạn có thể quyết định đáp ứng những nhu cầu đặc biệt này trong các BỐI CẢNH ĐƯỢC HẠN CHẾ riêng biệt, cho phép các mô hình đi THEO HƯỚNG TÁCH BIỆT, ngoại trừ việc TÍCH HỢP LIÊN TỤC các lớp dịch. Những phương ngữ khác nhau của NGÔN NGỮ PHỔ BIẾN sẽ phát triển xung quanh các mô hình này và thuật ngữ chuyên biệt mà chúng dựa vào. Nếu hai phương ngữ có nhiều điểm chung, một KERNEL CHUNG có thể cung cấp sự chuyên môn cần thiết trong khi giảm thiểu chi phí dịch thuật.

                                                                                                                                                                                                                          Nơi không cần tích hợp hoặc có mức độ hạn chế, điều này cho phép tiếp tục sử dụng thuật ngữ thông thường và tránh làm hỏng các mô hình. Nó cũng có chi phí và rủi ro của nó.

                                                                                                                                                                                                                          • Sự mất đi của ngôn ngữ chung sẽ giảm thiểu khả năng giao tiếp.

                                                                                                                                                                                                                          • Có thêm chi phí trong việc tích hợp.

                                                                                                                                                                                                                          • Sẽ có một số sự trùng lặp trong nỗ lực, khi các mô hình khác nhau của cùng một hoạt động kinh doanh và thực thể phát triển.

                                                                                                                                                                                                                          Nhưng có lẽ rủi ro lớn nhất là nó có thể trở thành một lập luận chống lại sự thay đổi và là sự biện minh cho bất kỳ mô hình độc đáo, hẹp hòi nào. Bạn cần điều chỉnh phần cá nhân này của hệ thống đến mức nào để đáp ứng nhu cầu chuyên biệt? Quan trọng nhất, từ ngữ cụ thể của nhóm người dùng này có giá trị đến đâu? Bạn phải cân nhắc giá trị của hành động độc lập hơn của các nhóm so với rủi ro của việc dịch thuật, luôn lưu ý đến việc biện minh cho những biến thể về thuật ngữ không có giá trị.

                                                                                                                                                                                                                          Đôi khi một mô hình sâu xuất hiện có thể thống nhất các ngôn ngữ khác nhau này và đáp ứng cả hai nhóm. Vấn đề là các mô hình sâu thường xuất hiện muộn trong chu kỳ sống, sau nhiều phát triển và xử lý kiến thức, nếu như chúng xuất hiện. Bạn không thể lên kế hoạch cho một mô hình sâu; bạn chỉ cần chấp nhận cơ hội khi nó xuất hiện, thay đổi chiến lược của mình và tái cấu trúc.

                                                                                                                                                                                                                          Hãy nhớ rằng, khi yêu cầu tích hợp là lớn, chi phí dịch thuật sẽ tăng lên rất nhiều. Một số phối hợp giữa các nhóm, từ việc sửa đổi chính xác một đối tượng có bản dịch phức tạp cho đến một HẠT NHÂN CHUNG, có thể làm cho việc dịch thuật trở nên dễ dàng hơn mà vẫn không yêu cầu sự thống nhất hoàn toàn.

                                                                                                                                                                                                                          Deployment

                                                                                                                                                                                                                          Việc phối hợp đóng gói và triển khai các hệ thống phức tạp là một trong những nhiệm vụ nhàm chán thường khó khăn hơn nhiều so với vẻ bề ngoài. Lựa chọn chiến lược BOUNDED CONTEXT có ảnh hưởng đến việc triển khai. Ví dụ, khi các ĐỘI KHÁCH HÀNG/CUNG CẤP triển khai các phiên bản mới, họ phải phối hợp với nhau để phát hành các phiên bản đã được kiểm tra cùng nhau. Cả mã lệnh và di chuyển dữ liệu đều phải hoạt động trong những sự kết hợp này. Trong một hệ thống phân tán, có thể hữu ích khi giữ các lớp dịch thuật giữa các CONTEXTS bên trong một quy trình duy nhất, để bạn không có nhiều phiên bản tồn tại song song.

                                                                                                                                                                                                                          Ngay cả việc triển khai các thành phần của một BOUND CONTEXT duy nhất cũng có thể gặp khó khăn khi việc di chuyển dữ liệu tốn thời gian hoặc khi các hệ thống phân tán không thể được cập nhật ngay lập tức, dẫn đến việc tồn tại hai phiên bản của mã và dữ liệu.

                                                                                                                                                                                                                          Nhiều yếu tố kỹ thuật cần được xem xét tùy thuộc vào môi trường triển khai và công nghệ. Nhưng mối quan hệ BOUNDED CONTEXT có thể chỉ cho bạn những điểm nóng. Các giao diện dịch đã được đánh dấu.

                                                                                                                                                                                                                          Tính khả thi của một kế hoạch triển khai cần được đưa vào việc xác định các ranh giới của CONTEXT. Khi hai CONTEXT được nối bằng một lớp dịch, một CONTEXT có thể được cập nhật chỉ để một lớp dịch mới cung cấp cùng một giao diện cho CONTEXT kia. KERNEL CHUNG đặt ra gánh nặng lớn hơn rất nhiều về việc phối hợp, không chỉ trong phát triển mà còn trong triển khai. CÁC CON ĐƯỜNG RIÊNG có thể làm cho cuộc sống trở nên đơn giản hơn rất nhiều.

                                                                                                                                                                                                                          The Trade-off

                                                                                                                                                                                                                          Tóm lại những hướng dẫn này, có một loạt chiến lược để thống nhất hoặc tích hợp các mô hình. Nói chung, bạn sẽ đánh đổi lợi ích của việc tích hợp chức năng một cách liền mạch với nỗ lực bổ sung về phối hợp và giao tiếp. Bạn đánh đổi hành động độc lập nhiều hơn với giao tiếp trôi chảy hơn. Sự thống nhất tham vọng hơn yêu cầu kiểm soát thiết kế của các hệ thống con liên quan.

                                                                                                                                                                                                                          Figure 14.13. The relative demands of CONTEXT relationship patterns

                                                                                                                                                                                                                          graphics/14fig13.gif

                                                                                                                                                                                                                          When Your Project Is Already Under Way

                                                                                                                                                                                                                          Có khả năng cao là bạn không bắt đầu một dự án mới mà đang tìm cách cải thiện một dự án đã đang tiến hành. Trong trường hợp này, bước đầu tiên là xác định BỐI CẢNH HẠN CHẾ theo cách mà mọi thứ đang diễn ra hiện tại. Điều này rất quan trọng. Để hiệu quả, BẢN ĐỒ BỐI CẢNH phải phản ánh thực tiễn thật sự của các đội, chứ không phải là tổ chức lý tưởng mà bạn có thể quyết định dựa trên những hướng dẫn vừa được mô tả.

                                                                                                                                                                                                                          Khi bạn đã xác định các BOUNDED CONTEXTS thực sự hiện tại của mình và mô tả các mối quan hệ mà chúng hiện có, bước tiếp theo là cải thiện các thực hành của nhóm xung quanh tổ chức hiện tại đó. Cải thiện quy trình CONTINUOUS INTEGRATION trong các CONTEXTS. Tái cấu trúc bất kỳ mã dịch chuyển lạc lối nào vào các ANTICORRUPTION LAYERS của bạn. Đặt tên cho các BOUNDED CONTEXTS hiện có và đảm bảo rằng chúng nằm trong UBIQUITOUS LANGUAGE của dự án.

                                                                                                                                                                                                                          Bây giờ bạn đã sẵn sàng để xem xét các thay đổi đối với các ranh giới và mối quan hệ tự thân. Những thay đổi này sẽ tự nhiên được thúc đẩy bởi những nguyên tắc mà tôi đã mô tả cho một dự án mới, nhưng chúng sẽ phải được thực hiện từng bước nhỏ, được chọn lựa một cách thực tiễn để mang lại giá trị cao nhất với nỗ lực và sự gián đoạn tối thiểu.

                                                                                                                                                                                                                          Phần tiếp theo thảo luận về cách thực hiện thay đổi các ranh giới CONTEXT của bạn một khi bạn đã quyết định.


                                                                                                                                                                                                                            Transformations

                                                                                                                                                                                                                            Giống như bất kỳ khía cạnh nào khác của mô hình hóa và thiết kế, các quyết định về BỐC KHOẢN NGHĨA là không thể đảo ngược. Chắc chắn sẽ có nhiều trường hợp mà bạn phải thay đổi quyết định ban đầu về ranh giới và mối quan hệ giữa các BỐC KHOẢN NGHĨA. Nói chung, việc tách rời CÁNH VÙNG là khá dễ dàng, nhưng việc hợp nhất chúng hoặc thay đổi mối quan hệ giữa chúng thì rất khó khăn. Tôi sẽ mô tả một vài thay đổi điển hình mà khó khăn nhưng lại quan trọng. Những biến đổi này thường quá lớn để thực hiện trong một lần tái cấu trúc hoặc thậm chí có thể trong một vòng lặp dự án. Vì lý do đó, tôi đã phác thảo các kế hoạch hành động để thực hiện những biến đổi này dưới dạng một loạt các bước khả thi. Đây, tất nhiên, là những hướng dẫn mà bạn sẽ phải điều chỉnh theo hoàn cảnh và sự kiện cụ thể của mình.

                                                                                                                                                                                                                            Merging CONTEXTS: SEPARATE WAYS graphics/arrow.gif SHARED KERNEL

                                                                                                                                                                                                                            Chi phí dịch thuật quá cao. Sự trùng lặp là quá rõ ràng. Có nhiều động lực để hợp nhất các BỐI CẢNH HẠN CHẾ. Điều này rất khó thực hiện. Chưa quá muộn, nhưng cần kiên nhẫn một chút.

                                                                                                                                                                                                                            Ngay cả khi mục tiêu cuối cùng của bạn là sáp nhập hoàn toàn vào một CONTEXT duy nhất với CONTINUOUS INTEGRATION, hãy bắt đầu bằng cách chuyển sang một KERNEL CHIA SẺ.

                                                                                                                                                                                                                            1. Đánh giá tình huống ban đầu. Đảm bảo rằng hai BỐI CẢNH thực sự thống nhất nội bộ trước khi bắt đầu thống nhất chúng với nhau.

                                                                                                                                                                                                                            Thiết lập quy trình. Bạn cần quyết định cách chia sẻ mã và quy tắc đặt tên module. Phải có ít nhất một lần tích hợp mã KERNEL CHIA SẺ hàng tuần. Và nó phải có một bộ kiểm tra. Hãy thiết lập điều này trước khi phát triển bất kỳ mã chia sẻ nào. (Bộ kiểm tra sẽ trống, vì vậy nó sẽ dễ dàng đạt yêu cầu!)

                                                                                                                                                                                                                            Chọn một tiểu miền nhỏ để bắt đầu - một cái gì đó được lặp lại trong cả hai BỐI CẢNH, nhưng không phải là một phần của MIỀN CỐT LÕI. Cuộc hợp nhất đầu tiên này sẽ thiết lập quy trình, vì vậy tốt nhất là sử dụng một cái gì đó đơn giản và tương đối chung chung hoặc không quan trọng. Xem xét các tích hợp và bản dịch đã tồn tại. Việc chọn một cái gì đó đang được dịch có ưu điểm là bắt đầu với một bản dịch đã được chứng minh, ngoài ra bạn cũng sẽ giảm tải lớp dịch của mình.

                                                                                                                                                                                                                            Tại thời điểm này, bạn có hai mô hình giải quyết cùng một tiểu miền. Về cơ bản, có ba cách tiếp cận để hợp nhất. Bạn có thể chọn một mô hình và tái cấu trúc mô hình còn lại để tương thích. Quyết định này có thể được thực hiện một cách tổng thể, đặt ra ý định thay thế một mô hình hoàn toàn và giữ lại tính nhất quán của một mô hình đã được phát triển như một đơn vị. Hoặc bạn có thể chọn từng phần một, có thể cuối cùng sẽ có được những điều tốt nhất từ cả hai (nhưng cần cẩn thận để không kết thúc với một mớ hỗn độn).

                                                                                                                                                                                                                            Lựa chọn thứ ba là tìm một mô hình mới, có thể sâu hơn cả hai mô hình nguyên gốc, có khả năng đảm nhận trách nhiệm của cả hai.

                                                                                                                                                                                                                            1. Hãy hình thành một nhóm từ hai đến bốn nhà phát triển, được chọn từ cả hai đội, để làm việc ra một mô hình chung cho tiểu miền. Bất kể cách thức mô hình được đưa ra, nó phải được làm rõ chi tiết. Điều này bao gồm công việc khó khăn của việc xác định các từ đồng nghĩa và lập bản đồ cho bất kỳ thuật ngữ nào chưa được dịch. Nhóm chung này sẽ phác thảo một bộ bài kiểm tra cơ bản cho mô hình.

                                                                                                                                                                                                                            Các nhà phát triển từ cả hai nhóm đều đảm nhận nhiệm vụ triển khai mô hình (hoặc điều chỉnh mã hiện có để chia sẻ), làm việc với các chi tiết và đảm bảo nó hoạt động. Nếu những nhà phát triển này gặp vấn đề với mô hình, họ sẽ triệu tập lại nhóm từ bước 3 và tham gia vào bất kỳ điều chỉnh cần thiết nào của các khái niệm.

                                                                                                                                                                                                                            Các nhà phát triển của từng đội đảm nhận nhiệm vụ tích hợp với KERNEL CHIA SẺ mới.

                                                                                                                                                                                                                            Xóa bỏ các bản dịch không còn cần thiết nữa.

                                                                                                                                                                                                                            Tại thời điểm này, bạn sẽ có một KERNEL CHIA SẺ rất nhỏ, với một quy trình để duy trì nó. Trong các vòng lặp dự án tiếp theo, lặp lại các bước 3 đến 7 để chia sẻ nhiều hơn. Khi các quy trình trở nên vững chắc và các nhóm tự tin hơn, bạn có thể đảm nhận những miền con phức tạp hơn, nhiều cái cùng một lúc, hoặc những miền con nằm trong MIỀN CỐT LÕI.

                                                                                                                                                                                                                            Một lưu ý: Khi bạn tiếp nhận nhiều phần cụ thể theo lĩnh vực của các mô hình, bạn có thể gặp phải những trường hợp mà hai mô hình đã thích nghi với thuật ngữ chuyên ngành của các cộng đồng người dùng khác nhau. Thật là khôn ngoan khi hoãn hợp nhất chúng vào KERNEL CHUNG trừ khi có một bước đột phá đến mô hình sâu, cung cấp cho bạn một ngôn ngữ có thể vượt trội hơn cả hai ngôn ngữ chuyên biệt. Một lợi thế của KERNEL CHUNG là bạn có thể có một số lợi ích của TÍCH HỢP LIÊN TỤC trong khi vẫn giữ được một số lợi ích của CÁC CÁCH RIÊNG BIỆT.

                                                                                                                                                                                                                            Đây là một số hướng dẫn để hợp nhất vào một KERNEL CHUNG. Trước khi tiến hành, hãy xem xét một phương án thay thế đáp ứng một số nhu cầu đã được đề cập bởi sự biến đổi này. Nếu một trong hai mô hình được ưa thích rõ ràng, hãy xem xét việc chuyển hướng về nó mà không cần tích hợp. Thay vì chia sẻ các tiểu miền chung, chỉ cần chuyển giao trách nhiệm hoàn toàn cho những tiểu miền đó từ một BỐ CỤC GIỚI HẠN sang BỐ CỤC GIỚI HẠN còn lại bằng cách tái cấu trúc các ứng dụng để gọi đến mô hình của BỐ CỤC được ưa thích hơn và thực hiện bất kỳ cải tiến nào mà mô hình đó cần. Không có gánh nặng tích hợp liên tục, bạn đã loại bỏ sự dư thừa. Có thể (nhưng không nhất thiết), BỐ CỤC GIỚI HẠN được ưa thích hơn có thể cuối cùng hoàn toàn tiếp quản, và bạn sẽ tạo ra hiệu ứng giống như một cuộc hôn nhân. Trong quá trình chuyển tiếp (có thể kéo dài hoặc không xác định), điều này sẽ có những lợi ích và bất lợi thông thường của việc ĐI LẠI RIÊNG, và bạn phải cân nhắc chúng so với những ưu điểm và nhược điểm của một KERNEL CHUNG.

                                                                                                                                                                                                                            Merging CONTEXTS: SHARED KERNEL graphics/arrow.gif CONTINUOUS INTEGRATION

                                                                                                                                                                                                                            Nếu KERNEL CHIA SẺ của bạn đang mở rộng, bạn có thể bị cuốn hút bởi những lợi ích của việc hợp nhất hoàn toàn hai BỐI CẢNH GIỚI HẠN. Đây không chỉ là vấn đề giải quyết sự khác biệt trong mô hình. Bạn sẽ phải thay đổi cấu trúc đội ngũ và cuối cùng là ngôn ngữ mà mọi người sử dụng.

                                                                                                                                                                                                                            Bắt đầu bằng cách chuẩn bị cho mọi người và các đội.

                                                                                                                                                                                                                            1. Hãy đảm bảo rằng tất cả các quy trình cần thiết cho TÍCH HỢP LIÊN TỤC (sở hữu mã nguồn chung, tích hợp thường xuyên, và vân vân) đều được thực hiện tại mỗi nhóm, một cách riêng biệt. Hài hòa các quy trình tích hợp giữa hai nhóm để mọi người làm việc theo cùng một cách.

                                                                                                                                                                                                                            Bắt đầu luân chuyển các thành viên trong nhóm giữa các đội. Điều này sẽ tạo ra một nhóm người hiểu cả hai mô hình và sẽ bắt đầu kết nối những người của hai đội.

                                                                                                                                                                                                                            Làm rõ quá trình chưng cất của từng mô hình một cách riêng lẻ. (Xem Chương 15.)

                                                                                                                                                                                                                            Tại thời điểm này, sự tự tin nên đủ cao để bắt đầu hợp nhất miền cốt lõi vào KERNEL CHIA SẺ. Điều này có thể mất vài lần lặp lại, và đôi khi cần có các lớp dịch tạm thời giữa các phần vừa được chia sẻ và các phần chưa được chia sẻ. Khi bắt đầu hợp nhất MIỀN CỐT LÕI, tốt nhất là nên tiến hành nhanh chóng. Đây là một giai đoạn có chi phí cao, đầy rẫy sai sót, và nên được rút ngắn càng nhiều càng tốt, ưu tiên hơn hầu hết các phát triển mới. Nhưng đừng nhận lấy nhiều hơn những gì bạn có thể xử lý.

                                                                                                                                                                                                                            Để hợp nhất các mô hình CORE, bạn có một vài lựa chọn. Bạn có thể giữ nguyên một mô hình và điều chỉnh mô hình kia để tương thích với nó, hoặc bạn có thể tạo ra một mô hình mới cho miền con và điều chỉnh cả hai bối cảnh để sử dụng nó. Hãy cẩn thận nếu hai mô hình đã được điều chỉnh để đáp ứng nhu cầu người dùng khác nhau. Bạn có thể cần sức mạnh chuyên môn của cả hai mô hình gốc. Điều này yêu cầu phát triển một mô hình sâu hơn có thể vượt qua cả hai mô hình gốc. Phát triển một mô hình thống nhất sâu hơn là rất khó khăn, nhưng nếu bạn cam kết hoàn toàn hợp nhất hai BỐI CẢNH, bạn không còn lựa chọn nào khác ngoài việc sử dụng một phương ngữ duy nhất. Sẽ có một phần thưởng về mặt sự rõ ràng trong việc tích hợp mô hình và mã nguồn kết quả. Hãy cẩn thận để điều đó không xảy ra với khả năng của bạn trong việc đáp ứng các nhu cầu chuyên môn của người dùng.

                                                                                                                                                                                                                            1. Khi KERNEL CHIA SẺ phát triển, hãy tăng tần suất tích hợp lên hàng ngày và cuối cùng là TÍCH HỢP LIÊN TỤC.

                                                                                                                                                                                                                            Khi KERNEL CHIA SẺ tiến gần đến việc bao hàm tất cả hai BỐC KHOẢN CŨ, bạn sẽ thấy mình có một đội lớn hoặc hai đội nhỏ hơn có mã nguồn chung mà họ TÍCH HỢP LIÊN TỤC, và thường xuyên trao đổi thành viên giữa các đội.

                                                                                                                                                                                                                            Phasing Out a Legacy System

                                                                                                                                                                                                                            Tất cả những điều tốt đẹp đều phải kết thúc, ngay cả phần mềm máy tính cũ. Nhưng điều đó không xảy ra một cách tự nhiên. Những hệ thống cũ này có thể gắn bó chặt chẽ với doanh nghiệp và các hệ thống khác đến mức việc tách chúng ra có thể mất nhiều năm. May mắn thay, không nhất thiết phải thực hiện tất cả cùng một lúc.

                                                                                                                                                                                                                            Các khả năng quá đa dạng khiến tôi không thể làm gì hơn ngoài việc chỉ sờ lên bề mặt ở đây. Nhưng tôi sẽ thảo luận về một trường hợp phổ biến: Một hệ thống cũ được sử dụng hàng ngày trong doanh nghiệp đã được bổ sung gần đây bởi một vài hệ thống hiện đại hơn tương tác với hệ thống kế thừa thông qua một LỚP CHỐNG THAM NHŨNG.

                                                                                                                                                                                                                            Một trong những bước đầu tiên nên là quyết định về một chiến lược kiểm tra. Các bài kiểm tra đơn vị tự động nên được viết cho các chức năng mới trong các hệ thống mới, nhưng việc loại bỏ các hệ thống cũ sẽ tạo ra những nhu cầu kiểm tra đặc biệt. Một số tổ chức chạy song song các hệ thống mới và cũ trong một khoảng thời gian.

                                                                                                                                                                                                                            Trong bất kỳ vòng lặp nào:

                                                                                                                                                                                                                            1. Xác định các chức năng cụ thể của hệ thống kế thừa có thể được thêm vào một trong những hệ thống được ưu tiên trong một vòng lặp duy nhất.

                                                                                                                                                                                                                            Xác định các bổ sung cần thiết trong LỚP CHỐNG THAM NHŨNG.

                                                                                                                                                                                                                            Triển khai.

                                                                                                                                                                                                                            Triển khai.

                                                                                                                                                                                                                            Đôi khi sẽ cần phải dành nhiều hơn một lần lặp để viết các chức năng tương đương cho một đơn vị có thể được loại bỏ khỏi hệ thống cũ, nhưng vẫn cần lập kế hoạch cho các chức năng mới trong những đơn vị nhỏ, kích thước của lần lặp, chỉ chờ đợi nhiều lần lặp để triển khai.

                                                                                                                                                                                                                            Triển khai là một điểm khác mà có quá nhiều biến thể để có thể bao quát mọi vấn đề. Thật tốt cho sự phát triển nếu những thay đổi nhỏ, dần dần này có thể được triển khai vào sản xuất, nhưng thường thì cần phải tổ chức các bản phát hành lớn hơn. Người dùng phải được đào tạo để sử dụng phần mềm mới. Một giai đoạn song song đôi khi phải được hoàn thành thành công. Nhiều vấn đề logistics sẽ phải được giải quyết.

                                                                                                                                                                                                                            Một khi nó cuối cùng hoạt động trong thực địa:

                                                                                                                                                                                                                            1. Xác định bất kỳ phần không cần thiết nào của LỚP CHỐNG THAM NHŨNG và loại bỏ chúng.

                                                                                                                                                                                                                            Xem xét việc loại bỏ các mô-đun không còn sử dụng của hệ thống cũ, mặc dù điều này có thể không thực tiễn. Mỉa mai thay, hệ thống cũ càng được thiết kế tốt thì việc loại bỏ nó sẽ càng dễ dàng. Nhưng phần mềm được thiết kế kém thì rất khó để tháo dỡ từ từ. Có thể chỉ cần bỏ qua các phần không sử dụng cho đến một thời điểm sau khi phần còn lại đã được loại bỏ và toàn bộ hệ thống có thể được tắt.

                                                                                                                                                                                                                            Lặp lại điều này nhiều lần. Hệ thống kế thừa nên trở nên ít liên quan hơn đến doanh nghiệp, và cuối cùng sẽ có khả năng nhìn thấy ánh sáng ở cuối đường hầm và cuối cùng tắt hệ thống cũ. Trong khi đó, LỚP CHỐNG THAM NHŨNG sẽ thay phiên nhau co lại và phồng lên khi các kết hợp khác nhau tăng hoặc giảm sự phụ thuộc lẫn nhau giữa các hệ thống. Tất cả các yếu tố khác đều giữ nguyên, dĩ nhiên, bạn nên di chuyển trước những chức năng dẫn đến LỚP CHỐNG THAM NHŨNG nhỏ hơn. Nhưng các yếu tố khác có thể chiếm ưu thế, và bạn có thể phải chấp nhận một số bản dịch khó khăn trong một số giai đoạn chuyển tiếp.

                                                                                                                                                                                                                            Open Host Service graphics/arrow.gif Published Language

                                                                                                                                                                                                                            Bạn đã đang tích hợp với các hệ thống khác thông qua một loạt các giao thức tạm thời, nhưng gánh nặng bảo trì đang gia tăng khi ngày càng nhiều hệ thống muốn truy cập, hoặc có thể việc tương tác trở nên rất khó hiểu. Bạn cần chính thức hóa mối quan hệ giữa các hệ thống bằng một NGÔN NGỮ CÔNG BỐ.

                                                                                                                                                                                                                            1. Nếu có một ngôn ngữ tiêu chuẩn trong ngành, hãy đánh giá nó và sử dụng nó nếu có thể.

                                                                                                                                                                                                                            Nếu không có ngôn ngữ tiêu chuẩn hoặc ngôn ngữ đã được công bố sẵn có, thì hãy bắt đầu bằng cách làm rõ LĨNH VỰC CHÍNH của hệ thống sẽ đóng vai trò là máy chủ. (Xem Chương 15.)

                                                                                                                                                                                                                            Sử dụng MIỀN CỐT LÕI làm cơ sở cho ngôn ngữ trao đổi, sử dụng một mô hình trao đổi chuẩn như XML, nếu có thể.

                                                                                                                                                                                                                            Công bố ngôn ngữ mới cho tất cả những người liên quan trong sự hợp tác (ít nhất).

                                                                                                                                                                                                                            Nếu có một kiến trúc hệ thống mới, hãy công bố điều đó.

                                                                                                                                                                                                                            Xây dựng các lớp dịch cho từng hệ thống cộng tác.

                                                                                                                                                                                                                            Chuyển đổi.

                                                                                                                                                                                                                            Tại thời điểm này, các cộng tác viên bổ sung nên có thể tham gia với sự gián đoạn tối thiểu.

                                                                                                                                                                                                                            Nhớ rằng, NGÔN NGỮ CÔNG BỐ phải ổn định, nhưng bạn vẫn cần tự do để thay đổi mô hình của host khi bạn tiếp tục việc tái cấu trúc không ngừng của mình. Do đó, đừng đồng nhất ngôn ngữ trao đổi và mô hình của host. Việc giữ chúng gần nhau sẽ giảm bớt chi phí dịch thuật, và bạn có thể chọn để làm cho host của mình trở thành một CONFORMIST. Nhưng hãy bảo lưu quyền để tăng cường lớp dịch thuật và phân kỳ nếu lợi ích chi phí ủng hộ điều đó.

                                                                                                                                                                                                                            Các lãnh đạo dự án nên định nghĩa BỐI CẢNH HẠN CHẾ dựa trên các yêu cầu tích hợp chức năng và mối quan hệ của các đội phát triển. Khi BỐI CẢNH HẠN CHẾ và BẢN ĐỒ BỐI CẢNH được định nghĩa rõ ràng và được tôn trọng, thì tính nhất quán logic sẽ được bảo vệ. Các vấn đề giao tiếp liên quan ít nhất sẽ được phơi bày để có thể giải quyết.

                                                                                                                                                                                                                            Tuy nhiên, đôi khi bối cảnh của mô hình, dù là được giới hạn một cách có chủ ý hay xảy ra một cách tự nhiên, lại bị áp dụng sai để giải quyết các vấn đề khác ngoài sự không nhất quán logic trong một hệ thống. Nhóm có thể nhận thấy rằng mô hình của một BỐI CẢNH lớn dường như quá phức tạp để hiểu toàn bộ hoặc để phân tích hoàn toàn. Bằng cách lựa chọn hoặc ngẫu nhiên, điều này thường dẫn đến việc chia nhỏ các BỐI CẢNH thành những phần dễ quản lý hơn. Sự phân mảnh này dẫn đến những cơ hội bị mất. Bây giờ, thật đáng để xem xét cẩn thận một quyết định thiết lập một mô hình lớn trong một BỐI CẢNH rộng lớn, và nếu nó không khả thi về mặt tổ chức hoặc chính trị để giữ lại, nếu thực tế nó đang phân mảnh, thì hãy vẽ lại bản đồ và định nghĩa các ranh giới mà bạn có thể giữ. Nhưng nếu một BỐI CẢNH LỚN được xác định để giải quyết các nhu cầu tích hợp cấp bách, và nếu nó có vẻ khả thi ngoài sự phức tạp của chính mô hình, thì việc chia nhỏ BỐI CẢNH có thể không phải là câu trả lời tốt nhất.

                                                                                                                                                                                                                            Có những phương pháp khác để làm cho các mô hình lớn trở nên khả thi mà cần được xem xét trước khi thực hiện sự hy sinh này. Hai chương tiếp theo tập trung vào việc quản lý độ phức tạp trong một mô hình lớn bằng cách áp dụng hai nguyên tắc rộng hơn: chưng cất và cấu trúc quy mô lớn.


                                                                                                                                                                                                                              Chapter Fifteen. Distillation

                                                                                                                                                                                                                              graphics/15inf01.gif

                                                                                                                                                                                                                              Bốn phương trình này, cùng với định nghĩa các thuật ngữ của chúng và cơ sở toán học mà chúng dựa vào, thể hiện toàn bộ lý thuyết điện từ học cổ điển của thế kỷ XIX.

                                                                                                                                                                                                                              James Clerk Maxwell, Luận văn về Điện và Từ trường, 1873

                                                                                                                                                                                                                              Bạn làm thế nào để tập trung vào vấn đề chính của mình và không bị chìm trong một biển các vấn đề phụ? KIẾN TRÚC TẦNG phân tách các khái niệm miền khỏi logic kỹ thuật làm cho một hệ thống máy tính hoạt động, nhưng trong một hệ thống lớn, ngay cả miền đã được tách biệt cũng có thể phức tạp đến mức không thể quản lý.

                                                                                                                                                                                                                              Chưng cất là quá trình tách rời các thành phần của một hỗn hợp để chiết xuất bản chất dưới một hình thức làm cho nó có giá trị và hữu ích hơn. Một mô hình là kết tinh của tri thức. Với mỗi lần tái cấu trúc để có cái nhìn sâu hơn, chúng ta trừu tượng hóa một số khía cạnh quan trọng của tri thức miền và ưu tiên. Bây giờ, từ một cái nhìn chiến lược, chương này sẽ xem xét cách phân biệt những phần rộng lớn của mô hình và chưng cất mô hình miền như một tổng thể.

                                                                                                                                                                                                                              Giống như nhiều quá trình chưng cất hóa học, các sản phẩm phụ tách riêng cũng trở nên có giá trị hơn nhờ vào quá trình chưng cất (như các LĨNH VỰC CHUNG và CƠ CHẾ CỤ THỂ), nhưng nỗ lực này được thúc đẩy bởi mong muốn trích xuất phần đặc biệt quý giá đó, phần phân biệt phần mềm của chúng ta và khiến nó có giá trị để xây dựng: "LĨNH VỰC CỐT LÕI."

                                                                                                                                                                                                                              Chưng cất chiến lược của một mô hình miền thực hiện tất cả những điều sau đây:

                                                                                                                                                                                                                              1. Giúp tất cả các thành viên trong nhóm nắm bắt tổng thể thiết kế của hệ thống và cách mà nó kết hợp với nhau.

                                                                                                                                                                                                                              Giúp tạo điều kiện cho giao tiếp bằng cách xác định một mô hình cốt lõi có kích thước quản lý để vào NGÔN NGỮ PHỔ BIẾN.

                                                                                                                                                                                                                              Hướng dẫn tái cấu trúc

                                                                                                                                                                                                                              Tập trung công việc vào những lĩnh vực của mô hình có giá trị nhất.

                                                                                                                                                                                                                              Hướng dẫn việc thuê ngoài, sử dụng các thành phần có sẵn, và quyết định về phân công.

                                                                                                                                                                                                                              Chương này trình bày một phương pháp hệ thống để tinh chế chiến lược trong LĨNH VỰC CỐT LÕI, và nó giải thích cách chia sẻ hiệu quả một cái nhìn về nó trong nhóm cũng như cung cấp ngôn ngữ để nói về những gì chúng ta đang làm.

                                                                                                                                                                                                                              Figure 15.1. A navigation map for strategic distillation

                                                                                                                                                                                                                              graphics/15fig01.gif

                                                                                                                                                                                                                              Như một người làm vườn tỉa cây, dọn dẹp để cho những nhánh chính phát triển, chúng ta sẽ áp dụng một loạt kỹ thuật để gọt bỏ những điều phân tâm trong mô hình và tập trung chú ý vào phần quan trọng nhất.


                                                                                                                                                                                                                                Core Domain

                                                                                                                                                                                                                                graphics/15inf02.gif

                                                                                                                                                                                                                                Trong việc thiết kế một hệ thống lớn, có rất nhiều thành phần góp phần, tất cả đều phức tạp và hoàn toàn cần thiết cho sự thành công, đến nỗi bản chất của mô hình miền, tài sản kinh doanh thực sự, có thể bị che khuất và bị bỏ quên.

                                                                                                                                                                                                                                Một hệ thống khó hiểu thì cũng khó thay đổi. Ảnh hưởng của một sự thay đổi thì khó dự đoán. Một lập trình viên đi ra ngoài khu vực quen thuộc của mình sẽ bị lạc. (Điều này đặc biệt đúng khi đưa người mới vào một nhóm, nhưng ngay cả một thành viên đã quen thuộc trong nhóm cũng sẽ gặp khó khăn trừ khi mã nguồn rất biểu cảm và có tổ chức.) Điều này buộc mọi người phải chuyên môn hóa. Khi các lập trình viên giới hạn công việc của mình vào các mô-đun cụ thể, điều này càng làm giảm khả năng chuyển giao kiến thức. Với việc phân chia công việc, sự tích hợp mượt mà của hệ thống bị ảnh hưởng, và tính linh hoạt trong việc phân công công việc bị mất. Sự trùng lặp xuất hiện khi một lập trình viên không nhận ra rằng một hành vi đã tồn tại ở nơi khác, và do đó hệ thống trở nên phức tạp hơn.

                                                                                                                                                                                                                                Đó là một số hậu quả của bất kỳ thiết kế nào khó hiểu, nhưng còn một rủi ro nghiêm trọng khác từ việc mất đi bức tranh tổng thể của miền:

                                                                                                                                                                                                                                Thực tế khắc nghiệt là không phải tất cả các phần của thiết kế đều sẽ được tinh chỉnh một cách đồng đều. Cần phải đặt ra các ưu tiên. Để biến mô hình miền thành một tài sản, lõi quan trọng của mô hình phải được tinh gọn và tận dụng hoàn toàn để tạo ra chức năng ứng dụng. Nhưng các nhà phát triển có kỹ năng cao, hiếm hoi thường có xu hướng tập trung vào hạ tầng kỹ thuật hoặc các vấn đề miền dễ định nghĩa mà có thể hiểu được mà không cần kiến thức chuyên môn về miền.

                                                                                                                                                                                                                                Những phần của hệ thống như vậy dường như thu hút các nhà khoa học máy tính, và được coi là xây dựng kỹ năng nghề nghiệp có thể chuyển nhượng và cung cấp tài liệu lý lịch tốt hơn. Phần cốt lõi chuyên biệt, phần của mô hình thực sự phân biệt ứng dụng và biến nó thành tài sản kinh doanh, thường cuối cùng lại được lắp ráp bởi những lập trình viên kém kỹ năng hơn, những người làm việc với các DBA để tạo ra một sơ đồ dữ liệu và sau đó mã hóa từng tính năng mà không khai thác bất kỳ sức mạnh khái niệm nào trong mô hình.

                                                                                                                                                                                                                                Thiết kế hoặc triển khai kém của phần mềm này dẫn đến một ứng dụng không bao giờ mang lại những điều hấp dẫn cho người dùng, bất kể hạ tầng kỹ thuật hoạt động tốt đến đâu, bất kể các tính năng hỗ trợ có hấp dẫn ra sao. Vấn đề âm thầm này có thể xuất hiện khi một dự án thiếu một cái nhìn rõ ràng về thiết kế tổng thể và tầm quan trọng tương đối của các phần khác nhau.

                                                                                                                                                                                                                                Một trong những dự án thành công nhất mà tôi tham gia ban đầu đã gặp phải hội chứng này. Mục tiêu là phát triển một hệ thống cho vay liên kết rất phức tạp. Hầu hết những tài năng mạnh mẽ đều vui vẻ làm việc trên các lớp ánh xạ cơ sở dữ liệu và giao diện nhắn tin, trong khi mô hình kinh doanh lại nằm trong tay những lập trình viên chưa quen với công nghệ đối tượng.

                                                                                                                                                                                                                                Ngoại lệ duy nhất, một nhà phát triển đối tượng có kinh nghiệm làm việc trên một vấn đề miền, đã nghĩ ra cách gắn các bình luận vào bất kỳ đối tượng miền lâu dài nào. Những bình luận này có thể được tổ chức để các nhà giao dịch có thể thấy lý do mà họ hoặc người khác đã ghi lại cho một quyết định trong quá khứ. Anh cũng đã xây dựng một giao diện người dùng thanh lịch mà cung cấp truy cập trực quan đến các tính năng linh hoạt của mô hình bình luận.

                                                                                                                                                                                                                                Các tính năng này rất hữu ích và được thiết kế tốt. Chúng đã được đưa vào sản xuất.

                                                                                                                                                                                                                                Thật không may, họ chỉ là phần phụ. Nhà phát triển tài năng này đã xây dựng một cách lập bình luận thú vị và tổng quát, thực hiện nó một cách rõ ràng và đưa vào tay người dùng. Trong khi đó, một nhà phát triển kém cỏi đã biến module "cho vay" quan trọng cho nhiệm vụ thành một mớ hỗn độn khó hiểu mà dự án gần như không thể hồi phục.

                                                                                                                                                                                                                                Quá trình lập kế hoạch phải tập trung tài nguyên vào những điểm quan trọng nhất trong mô hình và thiết kế. Để làm được điều đó, các điểm đó phải được xác định và hiểu rõ bởi tất cả mọi người trong quá trình lập kế hoạch và phát triển.

                                                                                                                                                                                                                                Những phần của mô hình đặc trưng và trung tâm cho mục đích của các ứng dụng dự kiến tạo thành MIỀN CỐT LÕI. MIỀN CỐT LÕI là nơi giá trị nhất nên được thêm vào hệ thống của bạn.

                                                                                                                                                                                                                                Do đó:

                                                                                                                                                                                                                                Nấu chín mô hình. Tìm miền cốt lõi và cung cấp phương thức dễ dàng để phân biệt nó với khối lượng mô hình và mã hỗ trợ. Đưa những khái niệm quý giá và chuyên biệt nhất vào ánh sáng rõ ràng. Giữ cho miền cốt lõi nhỏ gọn.

                                                                                                                                                                                                                                Áp dụng tài năng hàng đầu vào LĨNH VỰC CỐT LÕI và tuyển dụng theo đó. Dành công sức vào LĨNH VỰC CỐT LÕI để tìm một mô hình sâu và phát triển một thiết kế linh hoạt đủ để thực hiện tầm nhìn của hệ thống. Bào chữa cho việc đầu tư vào bất kỳ phần nào khác bằng cách xem xét cách nó hỗ trợ LĨNH VỰC CỐT LÕI đã được tinh chế.

                                                                                                                                                                                                                                Chưng cất MIỀN CỐT LÕI không dễ, nhưng nó sẽ dẫn đến một số quyết định dễ dàng. Bạn sẽ dành nhiều nỗ lực để làm cho MIỀN CỐT LÕI của bạn trở nên khác biệt, trong khi giữ phần còn lại của thiết kế càng chung chung càng tốt. Nếu bạn cần giữ một số khía cạnh của thiết kế bí mật như một lợi thế cạnh tranh, thì đó chính là MIỀN CỐT LÕI. Không cần phải lãng phí nỗ lực để che giấu phần còn lại. Và bất cứ khi nào phải đưa ra lựa chọn (do hạn chế về thời gian) giữa hai cải tiến mong muốn, lựa chọn nào ảnh hưởng nhiều nhất đến MIỀN CỐT LÕI nên được chọn trước.

                                                                                                                                                                                                                                graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                Các mẫu trong chương này làm cho LĨNH VỰC CỐT LÕI trở nên dễ thấy, dễ sử dụng và thay đổi hơn.

                                                                                                                                                                                                                                Choosing the CORE

                                                                                                                                                                                                                                Chúng tôi đang xem xét các phần của mô hình đặc trưng cho việc đại diện cho lĩnh vực kinh doanh của bạn và giải quyết các vấn đề kinh doanh của bạn.

                                                                                                                                                                                                                                LĨNH VỰC CỐT LÕI mà bạn chọn phụ thuộc vào quan điểm của bạn. Ví dụ, nhiều ứng dụng cần một mô hình tiền tệ tổng quát có thể đại diện cho nhiều loại tiền tệ khác nhau cùng với tỷ giá hối đoái và chuyển đổi của chúng. Mặt khác, một ứng dụng hỗ trợ giao dịch tiền tệ có thể cần một mô hình tiền tệ phức tạp hơn, mà sẽ được coi là một phần của LĨNH VỰC CỐT LÕI. Ngay cả trong trường hợp như vậy, có thể có một phần của mô hình tiền tệ rất tổng quát. Khi hiểu biết về lĩnh vực sâu sắc hơn thông qua kinh nghiệm, quá trình chắt lọc có thể tiếp tục bằng cách tách biệt các khái niệm tiền tệ tổng quát và giữ lại chỉ các khía cạnh chuyên biệt của mô hình trong LĨNH VỰC CỐT LÕI.

                                                                                                                                                                                                                                Trong một ứng dụng vận chuyển, phần lõi có thể là mô hình cách hàng hóa được gộp lại để vận chuyển, cách trách nhiệm được chuyển giao khi các container thay đổi chủ sở hữu, hoặc cách một container cụ thể được định tuyến qua nhiều phương tiện vận chuyển để đến đích. Trong ngân hàng đầu tư, phần lõi có thể bao gồm các mô hình phân phối tài sản giữa các bên được chỉ định và các tham gia viên.

                                                                                                                                                                                                                                Một miền cốt lõi của một ứng dụng là một thành phần hỗ trợ chung của ứng dụng khác. Tuy nhiên, trong suốt một dự án, và thường xuyên trong một công ty, một miền cốt lõi nhất quán có thể được xác định. Giống như mọi phần khác của thiết kế, việc xác định miền cốt lõi nên phát triển qua các vòng lặp. Tầm quan trọng của một tập hợp mối quan hệ cụ thể có thể không rõ ràng ngay từ đầu. Những đối tượng dường như trung tâm rõ ràng vào đầu có thể hóa ra chỉ có vai trò hỗ trợ.

                                                                                                                                                                                                                                Cuộc thảo luận trong các phần tiếp theo, đặc biệt là các MIỀN CON CHUNG, sẽ cung cấp thêm hướng dẫn cho những quyết định này.

                                                                                                                                                                                                                                Who Does the Work?

                                                                                                                                                                                                                                Các thành viên có kỹ năng kỹ thuật tốt nhất trong các đội dự án hiếm khi có nhiều kiến thức về lĩnh vực. Điều này hạn chế tính hữu ích của họ và củng cố xu hướng phân công họ vào các thành phần hỗ trợ, duy trì một vòng luẩn quẩn trong đó việc thiếu kiến thức khiến họ tránh xa công việc sẽ xây dựng kiến thức về lĩnh vực đó.

                                                                                                                                                                                                                                Điều quan trọng là phải phá vỡ chu kỳ này bằng cách tập hợp một đội ngũ gồm những lập trình viên mạnh mẽ, có cam kết lâu dài và có hứng thú trở thành kho tàng kiến thức về lĩnh vực, cùng với một hoặc một vài chuyên gia trong lĩnh vực biết rõ về kinh doanh. Thiết kế miền là công việc thú vị và đầy thách thức về mặt kỹ thuật khi được tiếp cận một cách nghiêm túc, và có thể tìm thấy những lập trình viên nhìn nhận nó theo cách này.

                                                                                                                                                                                                                                Thường thì không thực tế khi thuê chuyên gia thiết kế bên ngoài ngắn hạn cho những chi tiết trong việc tạo ra LĨNH VỰC CỐT LÕI, vì đội ngũ cần tích lũy kiến thức về lĩnh vực đó, và một thành viên tạm thời giống như một lỗ hổng trong xô nước. Mặt khác, một chuyên gia trong vai trò dạy học/hướng dẫn có thể rất quý giá bằng cách giúp đội ngũ xây dựng kỹ năng thiết kế lĩnh vực của họ và tạo điều kiện cho việc áp dụng các nguyên tắc tinh vi mà các thành viên trong đội có thể chưa thành thạo.

                                                                                                                                                                                                                                Vì những lý do tương tự, không có khả năng CORE DOMAIN có thể được mua. Đã có những nỗ lực để xây dựng các khung mô hình cụ thể cho từng ngành, những ví dụ đáng chú ý là khung CIM của hiệp hội ngành công nghiệp bán dẫn SEMATECH cho tự động hóa sản xuất bán dẫn và các khung "San Francisco" của IBM cho nhiều loại doanh nghiệp. Mặc dù đây là một ý tưởng rất hấp dẫn, cho đến nay kết quả vẫn chưa thuyết phục, ngoại trừ có lẽ như CÁC NGÔN NGỮ ĐƯỢC CÔNG BỐ tạo điều kiện cho việc trao đổi dữ liệu (xem Chương 14). Cuốn sách "Khung ứng dụng cụ thể cho miền" (Fayad và Johnson 2000) cung cấp một cái nhìn tổng quan về tình trạng của nghệ thuật này. Khi lĩnh vực này tiến triển, có thể sẽ có nhiều khung làm việc khả thi hơn.

                                                                                                                                                                                                                                Dù vậy, vẫn có một lý do cơ bản hơn cho sự thận trọng: Giá trị lớn nhất của phần mềm tùy chỉnh đến từ việc kiểm soát hoàn toàn MIỀN CỐT LỖI. Một khung thiết kế tốt có thể cung cấp các trừu tượng cấp cao mà bạn có thể chuyên môn hóa cho nhu cầu sử dụng của mình. Nó có thể giúp bạn tránh khỏi việc phát triển những phần tổng quát hơn và để bạn tự do tập trung vào MIỀN CỐT LỖI. Nhưng nếu nó hạn chế bạn nhiều hơn thế, thì có ba khả năng có thể xảy ra.

                                                                                                                                                                                                                                1. Bạn đang mất một tài sản phần mềm thiết yếu. Hãy từ bỏ các framework hạn chế trong MIỀN CỐT LÕI của bạn.

                                                                                                                                                                                                                                Khu vực được xử lý bởi khung không quan trọng như bạn nghĩ. Vẽ lại ranh giới của LĨNH VỰC CỐT LÕI đến phần thực sự đặc trưng của mô hình.

                                                                                                                                                                                                                                Bạn không có nhu cầu đặc biệt trong LĨNH VỰC CỐT LÕI của mình. Hãy xem xét giải pháp có rủi ro thấp hơn, chẳng hạn như mua phần mềm để tích hợp với các ứng dụng của bạn.

                                                                                                                                                                                                                                Một cách hay cách khác, việc tạo ra phần mềm độc đáo trở về việc có một đội ngũ ổn định tích lũy kiến thức chuyên môn và xử lý nó thành một mô hình phong phú. Không có lối tắt. Không có viên đạn kỳ diệu.


                                                                                                                                                                                                                                  An Escalation of Distillations

                                                                                                                                                                                                                                  Các kỹ thuật chưng cất khác nhau tạo nên phần còn lại của chương này có thể được áp dụng theo hầu như bất kỳ thứ tự nào, nhưng có một khoảng cách trong cách mà chúng thay đổi thiết kế.

                                                                                                                                                                                                                                  Một Tuyên bố TẦM NHÌN MIỀN đơn giản truyền đạt các khái niệm cơ bản và giá trị của chúng với khoản đầu tư tối thiểu. LÒNG ĐỘC ĐÁO NỔI BẬT có thể cải thiện giao tiếp và giúp hướng dẫn quyết định - và vẫn yêu cầu ít hoặc không cần điều chỉnh thiết kế.

                                                                                                                                                                                                                                  Việc tái cấu trúc và đóng gói mạnh mẽ hơn sẽ tách biệt rõ ràng các MIỀN CON TỔNG QUÁT, mà sau đó có thể được xử lý một cách riêng biệt. CÁC CƠ CHẾ LIÊN KẾT có thể được bao bọc bằng thiết kế linh hoạt, giao tiếp và mềm mại. Việc loại bỏ những yếu tố gây phân tâm này sẽ gỡ rối cho CỐT LÕI.

                                                                                                                                                                                                                                  Việc đóng gói lại một CORE PHÂN TÁCH làm cho CORE trở nên dễ dàng nhìn thấy, ngay cả trong mã, và tạo điều kiện thuận lợi cho công việc trong tương lai về mô hình CORE.

                                                                                                                                                                                                                                  Và tham vọng nhất là LÕI TRỪU TƯỢNG, biểu thị các khái niệm và mối quan hệ cơ bản nhất dưới dạng thuần khiết (và đòi hỏi phải tổ chức lại và cấu trúc lại mô hình một cách rộng rãi).

                                                                                                                                                                                                                                  Mỗi kỹ thuật trong số này đòi hỏi một cam kết ngày càng lớn hơn, nhưng một con dao sẽ càng sắc bén hơn khi lưỡi dao được mài tinh xảo hơn. Việc chưng cất liên tiếp một mô hình miền sẽ tạo ra một tài sản mang lại tốc độ, sự linh hoạt và độ chính xác trong việc thực hiện cho dự án.

                                                                                                                                                                                                                                  Để bắt đầu, chúng ta có thể loại bỏ những khía cạnh ít đặc trưng nhất của mô hình. CÁC LĨNH VỰC CHUNG cung cấp một sự tương phản với LĨNH VỰC CHÍNH, làm rõ ý nghĩa của từng lĩnh vực.


                                                                                                                                                                                                                                    Generic Subdomains

                                                                                                                                                                                                                                    Một số phần của mô hình làm tăng độ phức tạp mà không nắm bắt hoặc truyền đạt kiến thức chuyên ngành. Bất kỳ điều gì thừa thãi sẽ khiến MIỀN CỐT LÕI trở nên khó phân biệt và hiểu được. Mô hình sẽ bị tắc nghẽn bởi những nguyên tắc tổng quát mà mọi người đều biết hoặc những chi tiết thuộc về các chuyên ngành không phải là trọng tâm chính nhưng lại đóng vai trò hỗ trợ. Tuy nhiên, mặc dù là những yếu tố chung, những phần khác này lại rất cần thiết cho sự vận hành của hệ thống và sự thể hiện đầy đủ của mô hình.

                                                                                                                                                                                                                                    Có một phần trong mô hình của bạn mà bạn muốn coi là hiển nhiên. Nó chắc chắn là một phần của mô hình miền, nhưng nó trừu tượng hóa những khái niệm mà có lẽ sẽ cần thiết cho rất nhiều doanh nghiệp. Ví dụ, sơ đồ tổ chức doanh nghiệp cần thiết dưới một hình thức nào đó cho các doanh nghiệp đa dạng như vận chuyển, ngân hàng hay sản xuất. Một ví dụ khác, nhiều ứng dụng theo dõi các khoản phải thu, sổ cái chi phí và các vấn đề tài chính khác có thể đều được xử lý bằng cách sử dụng một mô hình kế toán chung.

                                                                                                                                                                                                                                    Thường thì rất nhiều nỗ lực được dành cho những vấn đề bên lề trong lĩnh vực này. Tôi đã chứng kiến hai dự án riêng biệt đã sử dụng những lập trình viên giỏi nhất của họ trong nhiều tuần để thiết kế lại ngày tháng và giờ theo múi giờ. Mặc dù các thành phần như vậy phải hoạt động, nhưng chúng không phải là cốt lõi khái niệm của hệ thống.

                                                                                                                                                                                                                                    Ngay cả khi một yếu tố mô hình chung như vậy được coi là rất quan trọng, mô hình miền tổng thể cần phải làm nổi bật những khía cạnh giá trị và đặc biệt nhất của hệ thống của bạn, và cần được cấu trúc để phần đó có sức mạnh tối đa có thể. Điều này rất khó thực hiện khi Lõi được trộn lẫn với tất cả các yếu tố liên quan.

                                                                                                                                                                                                                                    Vì vậy:

                                                                                                                                                                                                                                    Xác định các miền con liên kết không phải là động lực cho dự án của bạn. Tách các mô hình chung của các miền con này ra và đặt chúng vào các MODULE riêng biệt. Không để lại dấu vết nào về các chuyên môn của bạn trong chúng.

                                                                                                                                                                                                                                    Khi đã được tách riêng, hãy ưu tiên phát triển tiếp theo của chúng thấp hơn so với LĨNH VỰC CỐT LÕI, và tránh giao những lập trình viên cốt lõi của bạn vào các nhiệm vụ này (vì họ sẽ học được ít kiến thức về miền từ chúng). Cũng hãy xem xét các giải pháp có sẵn hoặc các mô hình đã được công bố cho các TIỂU MIỀN CHUNG NÀY.

                                                                                                                                                                                                                                    graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                    Bạn có thể có một vài tùy chọn bổ sung khi phát triển các gói này.

                                                                                                                                                                                                                                    Option 1: An Off-the-Shelf Solution

                                                                                                                                                                                                                                    Đôi khi bạn có thể mua một giải pháp hoặc sử dụng mã nguồn mở.

                                                                                                                                                                                                                                    Advantages
                                                                                                                                                                                                                                    • Ít mã để phát triển.

                                                                                                                                                                                                                                    • Gánh nặng bảo trì được chuyển giao ra bên ngoài.

                                                                                                                                                                                                                                    • Mã có lẽ đã trưởng thành hơn, được sử dụng ở nhiều nơi khác nhau và do đó, an toàn hơn và hoàn thiện hơn so với mã tự phát triển.

                                                                                                                                                                                                                                    Disadvantages
                                                                                                                                                                                                                                    • Bạn vẫn phải dành thời gian để đánh giá và hiểu nó trước khi sử dụng.

                                                                                                                                                                                                                                    • Kiểm soát chất lượng trong ngành của chúng ta như thế nào thì bạn không thể mong đợi nó chính xác và ổn định.

                                                                                                                                                                                                                                    • Nó có thể được thiết kế quá mức cho mục đích của bạn; việc tích hợp có thể tốn nhiều công sức hơn so với một giải pháp tự phát triển tối giản.

                                                                                                                                                                                                                                    • Các yếu tố ngoại lai thường không hòa nhập một cách suôn sẻ. Có thể có một BỐI CẢNH RÀNH MẠCH rõ ràng. Ngay cả khi không có, có thể sẽ khó khăn để tham chiếu một cách suôn sẻ các THỰC THỂ từ các gói khác của bạn.

                                                                                                                                                                                                                                    • Nó có thể tạo ra sự phụ thuộc vào nền tảng, sự phụ thuộc vào phiên bản trình biên dịch, và những thứ tương tự.

                                                                                                                                                                                                                                    Các giải pháp subdomain có sẵn trên thị trường đáng để tìm hiểu, nhưng thường không đáng công sức bỏ ra. Tôi đã thấy những câu chuyện thành công trong các ứng dụng có yêu cầu quy trình làm việc rất phức tạp mà sử dụng các hệ thống quy trình làm việc có sẵn trên thương mại với các API hooks. Tôi cũng đã thấy thành công với một gói ghi lỗi được tích hợp sâu vào ứng dụng. Đôi khi, các giải pháp SUBDOMAIN TỔNG QUÁT được đóng gói dưới dạng các khung, thực hiện một mô hình rất trừu tượng có thể tích hợp và được chuyên biệt hóa cho ứng dụng của bạn. Càng tổng quát subcomponent, và mô hình của nó càng tinh gọn, thì càng có khả năng nó sẽ hữu ích.

                                                                                                                                                                                                                                    Option 2: A Published Design or Model

                                                                                                                                                                                                                                    Advantages
                                                                                                                                                                                                                                    • Chín muồi hơn một mô hình tự sản xuất và phản ánh nhiều quan điểm của mọi người.

                                                                                                                                                                                                                                    • Tài liệu ngay lập tức, chất lượng cao

                                                                                                                                                                                                                                    Disadvantage
                                                                                                                                                                                                                                    • Có thể không hoàn toàn phù hợp với nhu cầu của bạn hoặc có thể được thiết kế phức tạp hơn mức cần thiết cho nhu cầu của bạn.

                                                                                                                                                                                                                                    Tom Lehrer (nhà sáng tác hài từ thập niên 1950 và 1960) đã nói rằng bí quyết thành công trong toán học là, "Đạo văn! Đạo văn. Đừng để công trình của bất kỳ ai thoát khỏi tầm mắt của bạn. . . . Chỉ cần chắc chắn luôn gọi nó là, xin vui lòng, nghiên cứu." Lời khuyên tốt trong việc mô hình miền, và đặc biệt khi tấn công vào MỘT TIỂU MIỀN CHUNG.

                                                                                                                                                                                                                                    Điều này hoạt động tốt nhất khi có một mô hình được phân phối rộng rãi, chẳng hạn như những mô hình trong Các mẫu phân tích (Fowler 1996). (Xem Chương 11.)

                                                                                                                                                                                                                                    Khi lĩnh vực đã có một mô hình được chính thức hóa và nghiêm ngặt, hãy sử dụng nó. Kế toán và vật lý là hai ví dụ minh hoạ. Không chỉ những mô hình này rất mạnh mẽ và tinh gọn, mà chúng còn được người dân ở khắp nơi hiểu biết rộng rãi, giảm bớt gánh nặng đào tạo hiện tại và tương lai của bạn. (Xem Chương 10 về việc sử dụng các hình thức đã được thiết lập.)

                                                                                                                                                                                                                                    Đừng cảm thấy bị ép buộc phải thực hiện tất cả các khía cạnh của một mô hình đã xuất bản, nếu bạn có thể xác định một tập hợp đơn giản hóa mà tự nhất quán và đáp ứng nhu cầu của bạn. Nhưng trong những trường hợp có một mô hình đã được thử nghiệm và tài liệu hóa tốt - hoặc tốt hơn nữa, được chính thức hóa - có sẵn, thì không có lý do gì để tái phát minh bánh xe.

                                                                                                                                                                                                                                    Option 3: An Outsourced Implementation

                                                                                                                                                                                                                                    Advantages
                                                                                                                                                                                                                                    • Giữ cho đội ngũ cốt lõi có thời gian làm việc vào MIỀN CỐT LÕI, nơi cần và tích lũy nhiều kiến thức nhất.

                                                                                                                                                                                                                                    • Cho phép phát triển nhiều hơn mà không cần mở rộng đội ngũ một cách vĩnh viễn, nhưng vẫn không làm mất đi kiến thức về LĨNH VỰC CHÍNH.

                                                                                                                                                                                                                                    • Đẩy mạnh thiết kế theo giao diện và giúp giữ cho miền con trở nên tổng quát, vì đặc tả đang được truyền ra ngoài.

                                                                                                                                                                                                                                    Disadvantages
                                                                                                                                                                                                                                    • Vẫn cần thời gian từ nhóm cốt lõi, vì giao diện, tiêu chuẩn lập trình và bất kỳ khía cạnh quan trọng nào khác cần được truyền đạt.

                                                                                                                                                                                                                                    • Gây ra chi phí lớn khi chuyển quyền sở hữu trở lại bên trong, vì mã phải được hiểu. (Tuy nhiên, chi phí này vẫn thấp hơn so với các miền con chuyên biệt, vì một mô hình tổng quát có lẽ không cần kiến thức đặc biệt nào để hiểu.)

                                                                                                                                                                                                                                    • Chất lượng mã có thể khác nhau. Điều này có thể tốt hoặc xấu, tùy thuộc vào trình độ tương đối của hai nhóm.

                                                                                                                                                                                                                                    Các bài kiểm tra tự động có thể đóng một vai trò quan trọng trong việc gia công. Những người thực hiện nên được yêu cầu cung cấp các bài kiểm tra đơn vị cho mã mà họ giao nộp. Một cách tiếp cận thực sự mạnh mẽ - một cách tiếp cận giúp đảm bảo một mức độ chất lượng, làm rõ thông số kỹ thuật, và làm mịn quá trình tái tích hợp - là chỉ định hoặc thậm chí viết các bài kiểm tra chấp nhận tự động cho các thành phần được gia công. Ngoài ra, "gia công thực hiện" có thể là một sự kết hợp tuyệt vời với "thiết kế hoặc mô hình đã được công bố."

                                                                                                                                                                                                                                    Option 4: An In-House Implementation

                                                                                                                                                                                                                                    Advantages
                                                                                                                                                                                                                                    • Tích hợp dễ dàng.

                                                                                                                                                                                                                                    • Bạn nhận được đúng những gì bạn muốn và không có gì thêm.

                                                                                                                                                                                                                                    • Các nhà thầu tạm thời có thể được chỉ định.

                                                                                                                                                                                                                                    Disadvantages
                                                                                                                                                                                                                                    • Gánh nặng bảo trì và đào tạo liên tục.

                                                                                                                                                                                                                                    • Thật dễ để đánh giá thấp thời gian và chi phí phát triển những gói như vậy.

                                                                                                                                                                                                                                    Tất nhiên, điều này cũng kết hợp tốt với "thiết kế hoặc mô hình đã được công bố."

                                                                                                                                                                                                                                    CÁC TÁCH MIỀN TỔNG QUÁT là nơi để áp dụng kiến thức thiết kế từ bên ngoài, vì chúng không yêu cầu hiểu biết sâu về LĨNH VỰC CHÍNH chuyên biệt của bạn, và chúng không mang lại cơ hội lớn để học hỏi về lĩnh vực đó. Vấn đề bảo mật ít quan trọng hơn, vì ít thông tin độc quyền hoặc thực tiễn kinh doanh nào sẽ được liên quan trong các mô-đun như vậy. Một TÁCH MIỀN TỔNG QUÁT làm giảm gánh nặng đào tạo cho những người không cam kết với kiến thức sâu về lĩnh vực đó.

                                                                                                                                                                                                                                    Theo thời gian, tôi tin rằng những ý tưởng của chúng ta về cái gì cấu thành mô hình CỐT LÕI sẽ thu hẹp lại, và ngày càng nhiều mô hình tổng quát sẽ có sẵn dưới dạng các khung thực hiện, hoặc ít nhất là dưới dạng các mô hình đã xuất bản hoặc các mẫu phân tích. Hiện tại, chúng ta vẫn phải phát triển hầu hết những điều này tự mình, nhưng có giá trị lớn trong việc phân chia chúng khỏi mô hình MIỀN CỐT LÕI.

                                                                                                                                                                                                                                    Example
                                                                                                                                                                                                                                    A Tale of Two Time Zones

                                                                                                                                                                                                                                    Hai lần tôi đã chứng kiến những lập trình viên tốt nhất của một dự án dành hàng tuần để giải quyết vấn đề lưu trữ và chuyển đổi thời gian với các múi giờ. Mặc dù tôi luôn nghi ngờ về những hoạt động như vậy, đôi khi điều đó là cần thiết, và hai dự án này cung cấp sự tương phản gần như hoàn hảo.

                                                                                                                                                                                                                                    Cái đầu tiên là một nỗ lực thiết kế phần mềm lập lịch cho vận chuyển hàng hóa. Để lên lịch cho các chuyến vận chuyển quốc tế, việc có những tính toán thời gian chính xác là rất quan trọng, và vì tất cả các lịch trình như vậy đều được theo dõi theo giờ địa phương, nên không thể phối hợp các chuyến vận chuyển mà không có sự chuyển đổi thời gian.

                                                                                                                                                                                                                                    Sau khi đã xác định rõ nhu cầu về chức năng này, đội ngũ đã tiến hành phát triển LĨNH VỰC CỐT LÕI và một số phiên bản đầu tiên của ứng dụng bằng cách sử dụng các lớp thời gian có sẵn và một số dữ liệu giả. Khi ứng dụng bắt đầu phát triển, rõ ràng rằng các lớp thời gian hiện có là không đủ và vấn đề trở nên rất phức tạp do sự khác biệt giữa nhiều quốc gia và độ phức tạp của Đường Đổi Ngày Quốc Tế. Với các yêu cầu đã rõ ràng hơn, họ đã tìm kiếm một giải pháp có sẵn nhưng không tìm thấy ứng viên nào. Họ không có lựa chọn nào khác ngoài việc tự xây dựng nó.

                                                                                                                                                                                                                                    Nhiệm vụ này sẽ yêu cầu nghiên cứu và kỹ thuật chính xác, vì vậy các trưởng nhóm đã chỉ định một trong những lập trình viên giỏi nhất của họ. Nhưng nhiệm vụ này không yêu cầu bất kỳ kiến thức đặc biệt nào về giao hàng và sẽ không phát triển kiến thức đó, vì vậy họ đã chọn một lập trình viên đang làm việc trong dự án theo hợp đồng tạm thời.

                                                                                                                                                                                                                                    Nhà lập trình này không bắt đầu từ đầu. Anh ấy đã nghiên cứu một số triển khai hiện có của các múi giờ, hầu hết trong số đó không đáp ứng yêu cầu, và quyết định điều chỉnh giải pháp công cộng từ BSD Unix, có cơ sở dữ liệu phức tạp và một triển khai bằng C. Anh ấy đã phân tích logic và viết một thủ tục nhập cho cơ sở dữ liệu.

                                                                                                                                                                                                                                    Vấn đề hóa ra còn khó hơn mong đợi (bao gồm, chẳng hạn, việc nhập dữ liệu của các trường hợp đặc biệt), nhưng mã đã được viết và tích hợp với CORE và sản phẩm đã được giao.

                                                                                                                                                                                                                                    Mọi thứ diễn ra rất khác trên dự án khác. Một công ty bảo hiểm đang phát triển một hệ thống xử lý yêu cầu bồi thường mới và dự định ghi lại thời gian của các sự kiện khác nhau (thời gian tai nạn xe hơi, thời gian bão đá, và như vậy). Dữ liệu này sẽ được ghi lại theo giờ địa phương, vì vậy tính năng múi giờ là cần thiết.

                                                                                                                                                                                                                                    Khi tôi đến, họ đã phân công một lập trình viên trẻ, nhưng rất thông minh, cho nhiệm vụ này, mặc dù các yêu cầu chính xác của ứng dụng vẫn đang trong quá trình thảo luận và ngay cả một phiên bản ban đầu cũng chưa được thử nghiệm. Anh ấy đã nghiêm túc bắt đầu xây dựng một mô hình múi giờ trước.

                                                                                                                                                                                                                                    Không biết điều gì sẽ cần thiết, người ta đã giả định rằng nó nên đủ linh hoạt để xử lý bất cứ thứ gì. Lập trình viên được giao nhiệm vụ cần sự trợ giúp với một vấn đề khó khăn như vậy, vì vậy một lập trình viên cấp cao cũng được phân công cho nhiệm vụ này. Họ đã viết mã phức tạp, nhưng không có ứng dụng cụ thể nào sử dụng nó, vì vậy không bao giờ rõ ràng rằng mã này hoạt động chính xác.

                                                                                                                                                                                                                                    Dự án đã gặp khó khăn vì nhiều lý do, và mã múi giờ chưa bao giờ được sử dụng. Nhưng nếu nó được sử dụng, thì chỉ cần lưu trữ thời gian địa phương được gán với múi giờ có thể đã đủ, ngay cả khi không cần chuyển đổi, vì đây chủ yếu là dữ liệu tham chiếu và không phải là cơ sở cho các phép toán. Ngay cả khi chuyển đổi hóa ra là cần thiết, tất cả dữ liệu đều sẽ được thu thập từ Bắc Mỹ, nơi mà việc chuyển đổi múi giờ tương đối đơn giản.

                                                                                                                                                                                                                                    Chi phí chính của việc chú ý đến các múi giờ là sự bỏ qua mô hình LĨNH VỰC CỐT LÕI. Nếu cùng một năng lượng được đặt vào đó, họ có thể đã tạo ra một mẫu hoạt động cho ứng dụng của riêng mình và một bản phác thảo về mô hình miền hoạt động. Hơn nữa, các nhà phát triển tham gia, những người cam kết lâu dài với dự án, nên đã được thấm nhuần trong lĩnh vực bảo hiểm, tích lũy kiến thức quan trọng trong nhóm.

                                                                                                                                                                                                                                    Một điều mà cả hai dự án đã làm đúng là phân tách rõ ràng mô hình múi giờ GENERIC khỏi MIỀN CỐT LÕI. Một mô hình múi giờ cụ thể cho vận chuyển hoặc bảo hiểm sẽ khiến mô hình này gắn chặt với mô hình hỗ trợ chung, làm cho MIỀN CỐT LÕI khó hiểu hơn (bởi vì nó sẽ chứa những chi tiết không liên quan về múi giờ). Điều này cũng sẽ khiến MODULE về múi giờ khó bảo trì hơn (bởi vì người bảo trì sẽ phải hiểu MIỀN CỐT LÕI và mối quan hệ của nó với múi giờ).

                                                                                                                                                                                                                                    Chiến lược Dự án Vận chuyển

                                                                                                                                                                                                                                    Chiến lược Dự án Bảo hiểm

                                                                                                                                                                                                                                    Lợi ích

                                                                                                                                                                                                                                    • Mô hình CHUNG tách rời khỏi CORE.

                                                                                                                                                                                                                                    • Mô hình CORE đã trưởng thành, vì vậy các nguồn lực có thể được chuyển nhượng mà không làm cản trở nó.

                                                                                                                                                                                                                                    • Biết chính xác họ cần gì.

                                                                                                                                                                                                                                    • Chức năng hỗ trợ quan trọng cho lịch trình quốc tế.

                                                                                                                                                                                                                                    • Lập trình viên hợp đồng ngắn hạn được sử dụng cho nhiệm vụ CHUNG.

                                                                                                                                                                                                                                    Nhược điểm

                                                                                                                                                                                                                                    • Chuyển hướng lập trình viên hàng đầu khỏi cốt lõi.

                                                                                                                                                                                                                                    Lợi thế

                                                                                                                                                                                                                                    • Mô hình TỔNG HỢP tách rời khỏi CỐT LÕI.

                                                                                                                                                                                                                                    Nhược điểm

                                                                                                                                                                                                                                    • Mô hình CORE chưa được phát triển, vì vậy sự chú ý vào các vấn đề khác đã tiếp tục sự bỏ qua này.

                                                                                                                                                                                                                                    • Các yêu cầu không rõ ràng đã dẫn đến việc cố gắng đạt được tính tổng quát hoàn toàn, trong khi đó việc chuyển đổi cụ thể cho Bắc Mỹ đơn giản hơn có thể đã đủ.

                                                                                                                                                                                                                                    • Các lập trình viên lâu dài đã được phân công, những người có thể đã là kho tàng kiến thức về lĩnh vực.

                                                                                                                                                                                                                                    Chúng tôi, những người làm kỹ thuật, thường có xu hướng thích những vấn đề có thể xác định được như chuyển đổi múi giờ, và chúng tôi có thể dễ dàng biện minh cho việc dành thời gian cho chúng. Nhưng một cái nhìn có kỷ luật vào các ưu tiên thường chỉ ra miền cốt lõi.

                                                                                                                                                                                                                                    Generic Doesn't Mean Reusable

                                                                                                                                                                                                                                    Lưu ý rằng trong khi tôi đã nhấn mạnh về chất lượng tổng quát của những tiểu miền này, tôi chưa đề cập đến khả năng tái sử dụng mã. Các giải pháp có sẵn có thể hợp lý hoặc không cho một tình huống cụ thể, nhưng giả sử rằng bạn đang thực hiện mã đó tự mình, nội bộ hoặc thuê ngoài, bạn không nên quan tâm đến khả năng tái sử dụng mã đó. Điều này sẽ đi ngược lại với động lực cơ bản của việc chưng cất: bạn nên áp dụng nhiều nỗ lực nhất có thể vào MIỀN CỐT LÕI và chỉ đầu tư vào các TIỂU MIỀN TỔNG QUÁT hỗ trợ khi cần thiết.

                                                                                                                                                                                                                                    Tái sử dụng xảy ra, nhưng không phải lúc nào cũng là tái sử dụng mã. Tái sử dụng mô hình thường là cấp độ tái sử dụng tốt hơn, như khi bạn sử dụng một thiết kế hoặc mô hình đã được công bố. Và nếu bạn phải tạo mô hình của riêng mình, nó có thể sẽ có giá trị trong một dự án liên quan sau này. Nhưng trong khi khái niệm về một mô hình như vậy có thể áp dụng cho nhiều tình huống, bạn không cần phải phát triển mô hình với đầy đủ tính tổng quát của nó. Bạn có thể mô hình hóa và triển khai chỉ phần mà bạn cần cho doanh nghiệp của mình.

                                                                                                                                                                                                                                    Mặc dù bạn nên hiếm khi thiết kế để tái sử dụng, bạn phải nghiêm túc trong việc giữ vững khái niệm chung. Việc giới thiệu các yếu tố mô hình cụ thể cho ngành sẽ có hai chi phí. Đầu tiên, nó sẽ cản trở sự phát triển trong tương lai. Mặc dù bạn chỉ cần một phần nhỏ của mô hình tiểu miền bây giờ, nhưng nhu cầu của bạn sẽ lớn hơn. Bằng cách giới thiệu bất kỳ điều gì vào thiết kế không phải là một phần của khái niệm, bạn làm cho việc mở rộng hệ thống một cách sạch sẽ trở nên khó khăn hơn rất nhiều mà không cần phải xây dựng lại hoàn toàn phần cũ và thiết kế lại các mô-đun khác sử dụng nó.

                                                                                                                                                                                                                                    Lý do thứ hai, và cũng quan trọng hơn, là những khái niệm theo ngành công nghiệp đó thuộc về DÊN CHỦ hoặc những tiểu miền chuyên biệt của riêng chúng, và những mô hình chuyên biệt đó có giá trị hơn nhiều so với những mô hình tổng quát.

                                                                                                                                                                                                                                    Project Risk Management

                                                                                                                                                                                                                                    Các quy trình Agile thường yêu cầu quản lý rủi ro bằng cách thực hiện các nhiệm vụ rủi ro nhất sớm nhất có thể. XP cụ thể yêu cầu đưa một hệ thống toàn diện lên và chạy ngay lập tức. Hệ thống ban đầu này thường chứng minh một kiến trúc kỹ thuật, và thật hấp dẫn khi xây dựng một hệ thống ngoại vi để xử lý một số miền phụ trợ CHUNG vì những điều này thường dễ phân tích hơn. Nhưng hãy cẩn thận; điều này có thể làm sai lệch mục đích của việc quản lý rủi ro.

                                                                                                                                                                                                                                    Các dự án phải đối mặt với rủi ro từ cả hai phía, trong đó một số dự án có rủi ro kỹ thuật lớn hơn và những dự án khác có rủi ro mô hình miền lớn hơn. Hệ thống end-to-end chỉ giảm thiểu rủi ro đến mức nó là một phiên bản phôi thai của các phần khó khăn của hệ thống thực tế. Rất dễ để đánh giá thấp rủi ro mô hình miền. Rủi ro này có thể thể hiện dưới hình thức sự phức tạp không lường trước được, việc thiếu liên lạc với các chuyên gia doanh nghiệp, hoặc thiếu hụt kỹ năng chủ chốt của các nhà phát triển.

                                                                                                                                                                                                                                    Do đó, trừ khi đội ngũ có kỹ năng đã được chứng minh và lĩnh vực rất quen thuộc, hệ thống ban đầu nên dựa trên một phần của MIỀN CHÍNH, dù đơn giản đến đâu.

                                                                                                                                                                                                                                    Nguyên tắc tương tự áp dụng cho bất kỳ quy trình nào cố gắng thúc đẩy các nhiệm vụ có rủi ro cao: MIỀN CỐT LÕI có rủi ro cao bởi vì nó thường khó khăn bất ngờ và vì nếu không có nó, dự án không thể thành công.

                                                                                                                                                                                                                                    Hầu hết các mẫu chưng cất trong chương này thể hiện cách thay đổi mô hình và mã để chưng cất MIỀN CỐT LÕI. Tuy nhiên, hai mẫu tiếp theo, TÀI LIỆU TẦM NHÌN MIỀN và CÁC ĐIỂM NỔI BẬT CỐT LÕI, cho thấy cách sử dụng tài liệu bổ sung có thể, với một khoản đầu tư rất nhỏ, cải thiện giao tiếp và nhận thức về MIỀN CỐT LÕI và tập trung nỗ lực phát triển.


                                                                                                                                                                                                                                      Domain Vision Statement

                                                                                                                                                                                                                                      Vào đầu một dự án, mô hình thường chưa tồn tại, nhưng nhu cầu tập trung vào việc phát triển của nó đã có. Ở các giai đoạn phát triển sau, cần có một giải thích về giá trị của hệ thống mà không cần phải nghiên cứu sâu về mô hình. Ngoài ra, các khía cạnh quan trọng của mô hình miền có thể trải rộng qua nhiều BOUNDED CONTEXTS, nhưng theo quy định, những mô hình khác biệt này không thể được cấu trúc để thể hiện sự tập trung chung của chúng.

                                                                                                                                                                                                                                      Nhiều nhóm dự án viết "tuyên bố tầm nhìn" cho ban lãnh đạo. Những tài liệu tốt nhất trong số này nêu rõ giá trị cụ thể mà ứng dụng sẽ mang lại cho tổ chức. Một số đề cập đến việc tạo ra mô hình miền như một tài sản chiến lược. Thông thường, tài liệu tuyên bố tầm nhìn bị bỏ rơi sau khi dự án được cấp vốn, và nó không bao giờ được sử dụng trong quy trình phát triển thực tế hoặc thậm chí không được đọc bởi nhân viên kỹ thuật.

                                                                                                                                                                                                                                      MỘT BẢN TẦM NHÌN MIỀN là một tài liệu được mô phỏng theo các văn bản như vậy, nhưng nó tập trung vào bản chất của mô hình miền và cách mà nó có giá trị cho doanh nghiệp. Nó có thể được sử dụng trực tiếp bởi ban quản lý và nhân viên kỹ thuật trong tất cả các giai đoạn phát triển để hướng dẫn phân bổ tài nguyên, hướng dẫn lựa chọn mô hình, và giáo dục các thành viên trong nhóm. Nếu mô hình miền phục vụ nhiều bên hữu quan, tài liệu này có thể chỉ ra cách mà lợi ích của họ được cân bằng.

                                                                                                                                                                                                                                      Vì vậy:

                                                                                                                                                                                                                                      Viết một mô tả ngắn (khoảng một trang) về MIỀN CỐT LÕI và giá trị mà nó sẽ mang lại, "đề xuất giá trị." Bỏ qua những khía cạnh không phân biệt mô hình miền này với các mô hình khác. Cho thấy cách mà mô hình miền phục vụ và cân bằng các lợi ích đa dạng. Giữ nó hẹp lại. Viết tuyên bố này sớm và chỉnh sửa nó khi bạn có được hiểu biết mới.

                                                                                                                                                                                                                                      Tuyên bố tầm nhìn miền có thể được sử dụng như một cột mốc giúp đội ngũ phát triển đi đúng hướng theo một hướng chung trong quá trình tinh lọc mô hình và mã nguồn. Nó có thể được chia sẻ với các thành viên trong nhóm không chuyên về kỹ thuật, ban quản lý và thậm chí là khách hàng (trừ khi nó chứa thông tin độc quyền, tất nhiên).

                                                                                                                                                                                                                                      Đây là một phần của TẦM NHÌN MIỀN.

                                                                                                                                                                                                                                      Điều này, mặc dù quan trọng, không phải là phần của Tuyên bố Tầm nhìn Miền.

                                                                                                                                                                                                                                      Hệ thống đặt chỗ hàng không

                                                                                                                                                                                                                                      Mô hình có thể đại diện cho ưu tiên của hành khách và các chiến lược đặt chỗ của hãng hàng không, đồng thời cân bằng những yếu tố này dựa trên các chính sách linh hoạt. Mô hình của hành khách nên phản ánh "mối quan hệ" mà hãng hàng không đang cố gắng phát triển với khách hàng quay lại. Do đó, nó nên đại diện cho lịch sử của hành khách dưới dạng cô đọng hữu ích, sự tham gia vào các chương trình đặc biệt, mối liên hệ với các khách hàng doanh nghiệp chiến lược, và nhiều điều khác nữa.

                                                                                                                                                                                                                                      Các vai trò khác nhau của các người dùng khác nhau (như hành khách, đại lý, quản lý) được biểu diễn để làm phong phú mô hình mối quan hệ và cung cấp thông tin cần thiết cho khung an ninh.

                                                                                                                                                                                                                                      Mô hình cần hỗ trợ tìm kiếm tuyến/ghế hiệu quả và tích hợp với các hệ thống đặt vé máy bay đã được thiết lập.

                                                                                                                                                                                                                                      Hệ thống đặt chỗ hàng không

                                                                                                                                                                                                                                      Giao diện người dùng nên được tối ưu hóa cho người dùng chuyên gia nhưng vẫn dễ tiếp cận cho người dùng lần đầu.

                                                                                                                                                                                                                                      Truy cập sẽ được cung cấp qua Web, bằng cách chuyển dữ liệu đến các hệ thống khác, và có thể qua các giao diện người dùng khác, vì vậy giao diện sẽ được thiết kế dựa trên XML với các lớp biến đổi để phục vụ các trang Web hoặc chuyển đổi sang các hệ thống khác.

                                                                                                                                                                                                                                      Một phiên bản hoạt hình đầy màu sắc của logo cần được lưu trữ trên máy khách để có thể hiển thị nhanh chóng trong những lần truy cập sau.

                                                                                                                                                                                                                                      Khi khách hàng gửi đặt chỗ, hãy xác nhận bằng hình ảnh trong vòng 5 giây.

                                                                                                                                                                                                                                      Một khung bảo mật sẽ xác thực danh tính của người dùng và sau đó hạn chế quyền truy cập vào các tính năng cụ thể dựa trên quyền được gán cho các vai trò người dùng xác định.

                                                                                                                                                                                                                                      Đây là một phần của Tuyên bố Tầm nhìn MIỀN.

                                                                                                                                                                                                                                      Điều này, mặc dù quan trọng, nhưng không phải là một phần của TÀI LIỆU TẦM NHÌN MIỀN.

                                                                                                                                                                                                                                      Tự động hóa nhà máy bán dẫn

                                                                                                                                                                                                                                      Mô hình miền sẽ đại diện cho trạng thái của vật liệu và thiết bị trong một nhà máy sản xuất wafer theo cách mà có thể cung cấp các dấu vết kiểm tra cần thiết và hỗ trợ việc định tuyến sản phẩm tự động.

                                                                                                                                                                                                                                      Mô hình sẽ không bao gồm nguồn nhân lực cần thiết trong quá trình, nhưng phải cho phép tự động hóa quy trình lựa chọn thông qua việc tải xuống công thức.

                                                                                                                                                                                                                                      Sự trình bày về trạng thái của nhà máy nên dễ hiểu đối với các nhà quản lý, để cung cấp cho họ cái nhìn sâu sắc hơn và hỗ trợ việc ra quyết định tốt hơn.

                                                                                                                                                                                                                                      Tự động hóa nhà máy bán dẫn

                                                                                                                                                                                                                                      Phần mềm cần được kích hoạt trên web thông qua một servlet, nhưng được cấu trúc để cho phép các giao diện thay thế.

                                                                                                                                                                                                                                      Cần sử dụng các công nghệ tiêu chuẩn trong ngành bất cứ khi nào có thể để tránh chi phí phát triển và bảo trì nội bộ và tối đa hóa việc tiếp cận chuyên môn bên ngoài. Các giải pháp mã nguồn mở được ưu tiên (chẳng hạn như máy chủ Web Apache).

                                                                                                                                                                                                                                      Máy chủ web sẽ chạy trên một máy chủ chuyên dụng. Ứng dụng sẽ chạy trên một máy chủ chuyên dụng duy nhất.

                                                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                      MỘT Tuyên bố TẦM NHÌN miền cung cấp cho đội ngũ một hướng đi chung. Thường sẽ cần một cầu nối giữa Tuyên bố cấp cao và các chi tiết đầy đủ của mã hoặc mô hình.


                                                                                                                                                                                                                                        Highlighted Core

                                                                                                                                                                                                                                        MỘT TẦM NHÌN VỀ MIỀN XÁC ĐỊNH MIỀN CỐT LÕI theo những cách tổng quát, nhưng nó để lại việc xác định các yếu tố mô hình CỐT LÕI cụ thể cho sự diễn giải của từng cá nhân. Trừ khi có một mức độ giao tiếp cực kỳ cao trong nhóm, TẦM NHÌN ĐÓ sẽ hầu như không có tác động gì.

                                                                                                                                                                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                        Mặc dù các thành viên trong nhóm có thể biết một cách tổng quát những gì cấu thành NỀN TẢNG CỐT LÕI, nhưng những người khác nhau sẽ không chỉ ra những yếu tố giống nhau, và ngay cả cùng một người cũng sẽ không nhất quán từ ngày này sang ngày khác. Việc phải lao động trí óc để liên tục lọc mô hình nhằm xác định các phần quan trọng tiêu tốn năng lượng tập trung đáng lẽ nên được dành cho tư duy thiết kế, và nó đòi hỏi kiến thức sâu rộng về mô hình đó. NỀN TẢNG CỐT LÕI cần phải được dễ nhận thấy hơn.

                                                                                                                                                                                                                                        Những thay đổi cấu trúc đáng kể trong mã là cách lý tưởng để xác định MIỀN CỐT LÕI, nhưng không phải lúc nào cũng thực tế trong ngắn hạn. Thực tế, những thay đổi mã lớn như vậy rất khó thực hiện nếu thiếu cái nhìn tổng thể mà đội ngũ đang thiếu.

                                                                                                                                                                                                                                        Các thay đổi về cấu trúc trong tổ chức mô hình, chẳng hạn như phân tách CÁC TIỀU MIỀN CHUNG và một vài thứ khác sẽ được đề cập sau trong chương này, có thể cho phép CÁC MODULE kể lại câu chuyện. Nhưng việc chỉ sử dụng điều này để truyền đạt MIỀN CỐT LÕI là quá tham vọng để hướng đến ngay từ đầu.

                                                                                                                                                                                                                                        Bạn có thể cần một giải pháp nhẹ nhàng hơn để bổ sung cho những kỹ thuật quyết liệt này. Có thể bạn sẽ gặp phải những hạn chế ngăn cản bạn tách riêng phần CORE về mặt vật lý. Hoặc bạn có thể bắt đầu với mã nguồn hiện có không phân biệt rõ ràng phần CORE, nhưng bạn thực sự cần thấy phần CORE và chia sẻ cái nhìn đó để có thể tái cấu trúc hiệu quả hướng tới việc tinh chế tốt hơn. Và ngay cả trong giai đoạn nâng cao, một vài sơ đồ hoặc tài liệu được chọn lọc cẩn thận cũng cung cấp điểm neo tinh thần và điểm vào cho đội ngũ.

                                                                                                                                                                                                                                        Những vấn đề này phát sinh tương đương cho các dự án sử dụng mô hình UML phức tạp và những dự án (chẳng hạn như dự án XP) ít tài liệu bên ngoài và sử dụng mã nguồn làm kho lưu trữ chính của mô hình. Một đội ngũ lập trình Extreme Programming có thể ít cầu kỳ hơn, giữ cho những tài liệu bổ sung này mang tính chất bình thường và tạm thời hơn (chẳng hạn, một sơ đồ vẽ tay trên tường để mọi người cùng xem), nhưng những kỹ thuật này có thể dễ dàng gộp vào quy trình.

                                                                                                                                                                                                                                        Đánh dấu một phần đặc quyền của mô hình, cùng với việc thực hiện nó, là một phản ánh về mô hình, không nhất thiết là một phần của mô hình tự nó. Bất kỳ kỹ thuật nào giúp mọi người dễ dàng biết về MIỀN CỐT LÕI đều hữu ích. Hai kỹ thuật cụ thể có thể đại diện cho loại giải pháp này.

                                                                                                                                                                                                                                        The Distillation Document

                                                                                                                                                                                                                                        Thường thì tôi tạo một tài liệu riêng để mô tả và giải thích MIỀN CỐT LÕI. Nó có thể đơn giản chỉ là một danh sách các đối tượng khái niệm thiết yếu nhất. Nó có thể là một tập hợp các sơ đồ tập trung vào những đối tượng đó, cho thấy các mối quan hệ quan trọng nhất của chúng. Nó có thể đi qua các tương tác cơ bản ở mức độ trừu tượng hoặc qua ví dụ. Nó có thể sử dụng sơ đồ lớp UML hoặc sơ đồ tuần tự, các sơ đồ không tiêu chuẩn đặc trưng cho miền, các giải thích bằng văn bản được diễn đạt cẩn thận, hoặc sự kết hợp của những điều này. Tài liệu tinh chế không phải là một tài liệu thiết kế hoàn chỉnh. Đó là một điểm khởi đầu tối giản mà phân định và giải thích MIỀN CỐT LÕI và gợi ý những lý do cần xem xét kỹ lưỡng một số phần cụ thể. Người đọc được cung cấp một cái nhìn rộng về cách các phần khớp với nhau và được hướng dẫn đến phần mã phù hợp để biết thêm chi tiết.

                                                                                                                                                                                                                                        Do đó (như một hình thức CỐT LÕI NỔI BẬT):

                                                                                                                                                                                                                                        Viết một tài liệu rất ngắn (từ ba đến bảy trang thưa thớt) mô tả LĨNH VỰC CỐT LÕI và các tương tác chính giữa các yếu tố CỐT LÕI.

                                                                                                                                                                                                                                        Tất cả các rủi ro thông thường của các tài liệu riêng biệt đều áp dụng.

                                                                                                                                                                                                                                        1. Tài liệu có thể không được duy trì.

                                                                                                                                                                                                                                        Tài liệu có thể không được đọc.

                                                                                                                                                                                                                                        Bằng cách nhân lên các nguồn thông tin, tài liệu có thể tự làm mất đi mục đích của nó là làm rõ sự phức tạp.

                                                                                                                                                                                                                                        Cách tốt nhất để hạn chế những rủi ro này là duy trì sự tối giản tuyệt đối. Tránh xa những chi tiết tầm thường và tập trung vào các trừu tượng trung tâm và sự tương tác của chúng cho phép tài liệu chậm lại theo thời gian, bởi vì cấp độ này của mô hình thường ổn định hơn.

                                                                                                                                                                                                                                        Viết tài liệu để mọi thành viên không chuyên môn trong nhóm có thể hiểu. Sử dụng nó như một cái nhìn chung để phân định những gì mọi người cần biết, và như một hướng dẫn mà tất cả các thành viên trong nhóm có thể bắt đầu khám phá mô hình và mã.

                                                                                                                                                                                                                                        The Flagged CORE

                                                                                                                                                                                                                                        Vào ngày đầu tiên của tôi trong một dự án tại một công ty bảo hiểm lớn, tôi nhận được một bản sao của "mô hình miền," một tài liệu dài hai trăm trang, được mua với chi phí lớn từ một liên minh ngành. Tôi đã dành một vài ngày để lội qua một mớ lộn xộn các biểu đồ lớp, bao gồm mọi thứ từ thành phần chi tiết của các chính sách bảo hiểm cho đến những mô hình cực kỳ trừu tượng về mối quan hệ giữa con người. Chất lượng của việc phân tích các mô hình này dao động từ dự án của học sinh trung học đến khá tốt (một số thậm chí đã mô tả các quy tắc kinh doanh, ít nhất là trong văn bản đi kèm). Nhưng bắt đầu từ đâu? Hai trăm trang.

                                                                                                                                                                                                                                        Văn hóa dự án rất ủng hộ việc xây dựng khung trừu tượng, và những người tiền nhiệm của tôi đã tập trung vào một mô hình rất trừu tượng về mối quan hệ của con người với nhau, với đồ vật và với các hoạt động hoặc thỏa thuận. Thực tế, đó là một phân tích hay về những mối quan hệ này, và các thí nghiệm của họ với mô hình có chất lượng như một dự án nghiên cứu học thuật. Nhưng nó không đưa chúng tôi tiến gần đến một ứng dụng bảo hiểm.

                                                                                                                                                                                                                                        Bản năng đầu tiên của tôi là bắt đầu cắt giảm, tìm một LĨNH VỰC CHỦ YẾU nhỏ để quay trở lại, sau đó tái cấu trúc và giới thiệu các phức tạp khác khi chúng tôi đi. Nhưng ban lãnh đạo đã rất lo ngại về thái độ này. Tài liệu đó được đầu tư với quyền lực lớn. Việc sản xuất của nó đã liên quan đến các chuyên gia từ khắp ngành công nghiệp, và dù sao đi nữa, họ đã trả cho liên minh nhiều hơn so với số tiền họ trả cho tôi, vì vậy họ có khả năng không cân nhắc quá nhiều về những đề xuất thay đổi mang tính cách mạng của tôi. Nhưng tôi biết rằng chúng tôi phải có một bức tranh chung về LĨNH VỰC CHỦ YẾU của chúng tôi và tập trung nỗ lực của mọi người vào điều đó.

                                                                                                                                                                                                                                        Thay vì tái cấu trúc, tôi đã xem qua tài liệu và, với sự giúp đỡ của một nhà phân tích kinh doanh người có nhiều kiến thức về ngành bảo hiểm nói chung và các yêu cầu của ứng dụng mà chúng tôi sắp xây dựng nói riêng, tôi đã xác định được một số phần quan trọng thể hiện các khái niệm thiết yếu và khác biệt mà chúng tôi cần làm việc với. Tôi đã cung cấp một hướng dẫn về mô hình rõ ràng cho thấy CORE và mối quan hệ của nó với các tính năng hỗ trợ.

                                                                                                                                                                                                                                        Một nỗ lực tạo mẫu mới bắt đầu từ góc nhìn này và nhanh chóng mang lại một ứng dụng đơn giản hóa, chứng minh một số chức năng cần thiết.

                                                                                                                                                                                                                                        Hai pound giấy tái chế đã trở thành tài sản kinh doanh nhờ một vài tab trang và một ít bút đánh dấu màu vàng.

                                                                                                                                                                                                                                        Kỹ thuật này không chỉ dành riêng cho các sơ đồ đối tượng trên giấy. Một nhóm sử dụng sơ đồ UML một cách rộng rãi có thể sử dụng "định danh" để xác định các yếu tố cốt lõi. Một nhóm sử dụng mã nguồn như là kho lưu trữ duy nhất của mô hình có thể sử dụng các chú thích, có thể được cấu trúc như Java Doc, hoặc có thể sử dụng một công cụ trong môi trường phát triển của mình. Kỹ thuật cụ thể không quan trọng, miễn là nhà phát triển có thể dễ dàng thấy được những gì có trong và những gì không có trong MIỀN CỐT LÕI.

                                                                                                                                                                                                                                        Do đó (dưới dạng một hình thức kích thích cốt lõi khác):

                                                                                                                                                                                                                                        Đánh dấu các yếu tố của LĨNH VỰC CỐT LÕI trong kho lưu trữ chính của mô hình, mà không cố gắng làm rõ vai trò của nó. Giúp cho lập trình viên dễ dàng biết cái gì nằm trong hoặc ngoài LĨNH VỰC CỐT LÕI.

                                                                                                                                                                                                                                        MIỀN CỐT LÕI giờ đây rõ ràng đáng chú ý đối với những người làm việc với mô hình, với nỗ lực khá nhỏ và bảo trì thấp, ít nhất là trong mức độ mà mô hình được phân tích đủ tốt để phân biệt sự đóng góp của các phần.

                                                                                                                                                                                                                                        The Distillation Document as Process Tool

                                                                                                                                                                                                                                        Về lý thuyết trong một dự án XP, bất kỳ cặp nào (hai lập trình viên làm việc cùng nhau) có thể thay đổi bất kỳ mã nào trong hệ thống. Trong thực tế, một số thay đổi có thể có hậu quả lớn và cần sự tham khảo và phối hợp nhiều hơn. Khi làm việc ở tầng hạ tầng, tác động của một thay đổi có thể rõ ràng, nhưng có thể không rõ ràng ở tầng miền, như thường được tổ chức.

                                                                                                                                                                                                                                        Với khái niệm về MIỀN CỐT LÕI, tác động này có thể được làm rõ. Những thay đổi đối với mô hình của MIỀN CỐT LÕI nên có ảnh hưởng lớn. Những thay đổi đối với các yếu tố tổng quát được sử dụng rộng rãi có thể yêu cầu nhiều cập nhật mã, nhưng chúng vẫn không nên tạo ra sự thay đổi khái niệm như những thay đổi về MIỀN CỐT LÕI.

                                                                                                                                                                                                                                        Sử dụng tài liệu chưng cất như một hướng dẫn. Khi các nhà phát triển nhận ra rằng tài liệu chưng cất cần phải thay đổi để phù hợp với sự thay đổi trong mã hoặc mô hình của họ, thì cần phải tham khảo ý kiến. Hoặc họ đang thay đổi cơ bản các yếu tố hoặc mối quan hệ trong MIỀN CỐT LÕI, hoặc họ đang thay đổi ranh giới của MIỀN CỐT LÕI, bao gồm hoặc loại trừ một cái gì đó khác. Việc phổ biến thay đổi mô hình đến toàn bộ đội ngũ là cần thiết thông qua bất kỳ kênh giao tiếp nào mà đội sử dụng, bao gồm cả việc phát hành một phiên bản mới của tài liệu chưng cất.

                                                                                                                                                                                                                                        Nếu tài liệu chưng cất nêu rõ những điều thiết yếu của MIỀN CỐT LÕI, thì nó là một chỉ báo thực tiễn về tầm quan trọng của một sự thay đổi mô hình. Khi một sự thay đổi mô hình hoặc mã ảnh hưởng đến tài liệu chưng cất, nó yêu cầu tham khảo ý kiến từ các thành viên khác trong nhóm. Khi thay đổi được thực hiện, cần ngay lập tức thông báo cho tất cả các thành viên trong nhóm và phát hành phiên bản mới của tài liệu. Những thay đổi bên ngoài MIỀN CỐT LÕI hoặc không bao gồm trong tài liệu chưng cất có thể được tích hợp mà không cần tham khảo ý kiến hay thông báo, và sẽ được các thành viên khác tiếp xúc trong quá trình làm việc của họ. Sau đó, các nhà phát triển có toàn quyền tự quyết như những gì XP đề xuất.

                                                                                                                                                                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                        Mặc dù TẦM NHÌN và CÁC YẾU TỐ NỔI BẬT hướng dẫn và chỉ đạo, nhưng chúng không thực sự thay đổi mô hình hoặc mã nguồn. Phân tách CÁC TIỂU MIỀN CHUNG loại bỏ một số yếu tố gây phân tâm. Các mẫu tiếp theo xem xét cách thay đổi cấu trúc của mô hình và thiết kế để làm cho MIỀN CỐT LÕI trở nên rõ ràng và dễ quản lý hơn.


                                                                                                                                                                                                                                          Cohesive Mechanisms

                                                                                                                                                                                                                                          Việc bao bọc các cơ chế là một nguyên tắc tiêu chuẩn trong thiết kế hướng đối tượng. Việc ẩn giấu các thuật toán phức tạp trong các phương thức với các tên gọi phản ánh ý định tách biệt "cái gì" khỏi "cách nào". Kỹ thuật này làm cho thiết kế trở nên dễ hiểu và dễ sử dụng hơn. Tuy nhiên, nó cũng gặp phải những giới hạn tự nhiên.

                                                                                                                                                                                                                                          Tính toán đôi khi đạt đến một mức độ phức tạp khiến thiết kế trở nên cồng kềnh. Khái niệm "cái gì" bị ngập chìm bởi "như thế nào" cơ học. Một số lượng lớn các phương pháp cung cấp các thuật toán để giải quyết vấn đề lại làm mờ đi các phương pháp thể hiện vấn đề.

                                                                                                                                                                                                                                          Sự gia tăng của các quy trình này là một triệu chứng của vấn đề trong mô hình. Việc tái cấu trúc để hướng tới cái nhìn sâu sắc hơn có thể tạo ra một mô hình và thiết kế mà các yếu tố của nó phù hợp hơn với việc giải quyết vấn đề. Giải pháp đầu tiên cần tìm kiếm là một mô hình làm cho cơ chế tính toán đơn giản. Nhưng thỉnh thoảng, cái nhìn sâu sắc xuất hiện rằng một phần nào đó của cơ chế tự nó lại có tính nhất quán về khái niệm. Tính toán khái niệm này có thể sẽ không bao gồm tất cả những tính toán phức tạp mà bạn cần. Chúng ta không nói về một "máy tính" tổng quát nào đó. Nhưng việc tách biệt phần nhất quán nên giúp cơ chế còn lại dễ hiểu hơn.

                                                                                                                                                                                                                                          Do đó:

                                                                                                                                                                                                                                          Phân chia một cơ chế đồng bộ về mặt khái niệm thành một khung nhẹ tách biệt. Đặc biệt chú ý đến các hình thức hoặc các danh mục thuật toán được tài liệu hóa tốt. Phơi bày khả năng của khung với một giao diện tiết lộ ý định. Bây giờ, các yếu tố khác trong miền có thể tập trung vào việc diễn đạt vấn đề ("cái gì"), ủy thác những phức tạp của giải pháp ("như thế nào") cho khung.

                                                                                                                                                                                                                                          Các cơ chế tách biệt này sau đó được đặt vào vai trò hỗ trợ của chúng, tạo ra một MIỀN CỐT LÕI nhỏ hơn và biểu cảm hơn, sử dụng cơ chế thông qua giao diện theo một phong cách tuyên bố rõ ràng hơn.

                                                                                                                                                                                                                                          Nhận diện một thuật toán hoặc hình thức chuẩn chuyển một phần của độ phức tạp trong thiết kế vào một tập hợp các khái niệm đã được nghiên cứu. Với một hướng dẫn như vậy, chúng ta có thể triển khai giải pháp với sự tự tin và ít thử nghiệm sai. Chúng ta có thể tin tưởng vào việc các nhà phát triển khác biết về nó hoặc ít nhất có thể tra cứu nó. Điều này tương tự như những lợi ích của một mô hình SUBDOMAIN CHUNG đã được công bố, nhưng một thuật toán hoặc phép tính được tài liệu hóa có thể được tìm thấy thường xuyên hơn vì cấp độ khoa học máy tính này đã được nghiên cứu nhiều hơn. Tuy nhiên, thường thì bạn sẽ phải tạo ra thứ gì đó mới. Hãy tập trung một cách hẹp vào phép tính và tránh kết hợp với mô hình miền diễn đạt. Có sự phân tách trách nhiệm: Mô hình của MIỀN CỐT YẾU hoặc một SUBDOMAIN CHUNG xác định một sự thật, quy tắc hoặc vấn đề. MỘT CƠ CHẾ LIÊN KẾT giải quyết quy tắc hoặc hoàn thành phép tính theo cách đã được mô hình hóa.

                                                                                                                                                                                                                                          Example
                                                                                                                                                                                                                                          A Mechanism in an Organization Chart

                                                                                                                                                                                                                                          Tôi đã trải qua quá trình này trong một dự án cần một mô hình sơ đồ tổ chức khá phức tạp. Mô hình này đại diện cho việc một người làm việc cho người khác, và trong những nhánh nào của tổ chức, và nó cung cấp một giao diện mà qua đó các câu hỏi liên quan có thể được đặt ra và trả lời. Bởi vì hầu hết các câu hỏi này liên quan đến "Ai, trong chuỗi mệnh lệnh này, có quyền phê duyệt việc này?" hoặc "Ai, trong bộ phận này, có khả năng xử lý một vấn đề như thế này?", nhóm đã nhận ra rằng hầu hết sự phức tạp liên quan đến việc duyệt qua các nhánh cụ thể của cây tổ chức, tìm kiếm những người hoặc mối quan hệ cụ thể. Đây chính là loại vấn đề được giải quyết bởi hình thức đồ thị phát triển tốt, một tập hợp các nút được kết nối bằng các cung (gọi là cạnh) và các quy tắc cùng thuật toán cần thiết để duyệt qua đồ thị.

                                                                                                                                                                                                                                          Một nhà thầu phụ đã triển khai một khung duyệt đồ thị như là một CƠ CHẾ ĐỒNG NHẤT. Khung này sử dụng thuật ngữ và thuật toán đồ thị tiêu chuẩn mà hầu hết các nhà khoa học máy tính đều quen thuộc và được tài liệu hóa phong phú trong sách giáo khoa. Ông không thực hiện một đồ thị hoàn toàn tổng quát. Đó là một tập con của khung khái niệm đó, bao gồm các tính năng cần thiết cho mô hình tổ chức của chúng tôi. Và với một GIAO DIỆN TIẾT LỘ Ý ĐỊNH, phương thức mà qua đó các câu trả lời được thu nhận không phải là mối quan tâm chính.

                                                                                                                                                                                                                                          Bây giờ, mô hình tổ chức có thể đơn giản nêu rằng, sử dụng thuật ngữ đồ thị tiêu chuẩn, mỗi người là một nút, và mỗi mối quan hệ giữa các người là một cạnh (cung) kết nối các nút đó. Sau đó, có lẽ, các cơ chế trong khuôn khổ đồ thị có thể tìm mối quan hệ giữa bất kỳ hai người nào.

                                                                                                                                                                                                                                          Nếu cơ chế này được tích hợp vào mô hình miền, chúng tôi sẽ phải trả giá theo hai cách. Mô hình sẽ bị ràng buộc với một phương pháp giải quyết vấn đề cụ thể, giới hạn các lựa chọn trong tương lai. Điều quan trọng hơn, mô hình của một tổ chức sẽ trở nên phức tạp và rối ren hơn rất nhiều. Việc giữ cho cơ chế và mô hình tách biệt cho phép một phong cách diễn đạt có tính khẳng định về các tổ chức rõ ràng hơn nhiều. Và đoạn mã phức tạp cho việc thao tác đồ thị được tách biệt trong một khuôn khổ hoàn toàn mang tính cơ học, dựa trên các thuật toán đã được chứng minh, có thể được bảo trì và kiểm tra đơn vị một cách độc lập.

                                                                                                                                                                                                                                          Một ví dụ khác về một CƠ CHẾ LIÊN KẾT sẽ là một khuôn khổ để xây dựng các đối tượng ĐẶC TẢ và hỗ trợ các phép so sánh và kết hợp cơ bản mà chúng mong đợi. Bằng cách áp dụng một khuôn khổ như vậy, MIỀN CỐT LÕI và CÁC TIỂU MIỀN CHUNG có thể tuyên bố các ĐẶC TẢ của họ bằng ngôn ngữ rõ ràng, dễ hiểu được mô tả trong mẫu đó (xem Chương 10). Các thao tác phức tạp liên quan đến việc thực hiện các phép so sánh và kết hợp có thể được bỏ lại cho khuôn khổ.

                                                                                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                          GENERIC SUBDOMAIN Versus COHESIVE MECHANISM

                                                                                                                                                                                                                                          Cả SUBDOMAINS GENERIC và CƠ CHẾ KHOÁI đều được thúc đẩy bởi cùng một mong muốn là giảm bớt gánh nặng cho LĨNH VỰC CỐT LÕI. Sự khác biệt nằm ở bản chất trách nhiệm được đảm nhận. Một SUBDOMAIN GENERIC dựa trên một mô hình diễn đạt thể hiện một khía cạnh nào đó về cách mà nhóm nhìn nhận lĩnh vực. Về điều này, nó không khác gì LĨNH VỰC CỐT LÕI, chỉ là ít trung tâm hơn, ít quan trọng hơn và ít chuyên biệt hơn. Một CƠ CHẾ KHOÁI không đại diện cho lĩnh vực; nó giải quyết một số vấn đề tính toán khó khăn mà các mô hình diễn đạt đặt ra.

                                                                                                                                                                                                                                          Một mô hình đề xuất; một CƠ CHẾ LIÊN KẾT sắp xếp.

                                                                                                                                                                                                                                          Trên thực tế, trừ khi bạn nhận ra một phép toán có hình thức, đã được công bố, sự phân biệt này thường không thuần khiết, ít nhất là trong giai đoạn đầu. Trong quá trình tái cấu trúc liên tiếp, nó có thể được chắt lọc thành một cơ chế thuần khiết hơn hoặc được chuyển đổi thành một MIỀN PHỤ THỂ CHUNG với một số khái niệm mô hình chưa được nhận ra trước đó, điều này sẽ làm cho cơ chế trở nên đơn giản.

                                                                                                                                                                                                                                          When a MECHANISM Is Part of the CORE DOMAIN

                                                                                                                                                                                                                                          Bạn gần như luôn muốn loại bỏ CƠ CHẾ khỏi MIỀN CỐT LÕI. Một ngoại lệ là khi một CƠ CHẾ tự nó là sở hữu trí tuệ và là một phần quan trọng của giá trị phần mềm. Điều này đôi khi xảy ra với các thuật toán chuyên biệt cao. Ví dụ, nếu một trong những đặc điểm nổi bật của một ứng dụng logistics vận chuyển là một thuật toán đặc biệt hiệu quả để tính toán lịch trình, thì CƠ CHẾ đó có thể được coi là một phần của MIỀN CỐT LÕI về mặt khái niệm. Tôi đã từng làm việc trong một dự án tại một ngân hàng đầu tư, nơi các thuật toán sở hữu trí tuệ cao để đánh giá rủi ro chắc chắn nằm trong MIỀN CỐT LÕI. (Thực tế là, chúng được bảo mật đến mức ngay cả phần lớn các nhà phát triển trong MIỀN CỐT LÕI cũng không được phép xem chúng.) Tất nhiên, những thuật toán này có lẽ là một thực hiện cụ thể của một tập hợp các quy tắc thực sự dự đoán rủi ro. Phân tích sâu hơn có thể dẫn đến một mô hình sâu hơn cho phép những quy tắc đó được rõ ràng, với một cơ chế giải quyết được bao bọc.

                                                                                                                                                                                                                                          Nhưng đó sẽ là một cải tiến bổ sung trong thiết kế, vào một ngày khác. Quyết định xem có nên thực hiện bước tiếp theo hay không sẽ dựa trên một phân tích chi phí-lợi ích: Việc phát triển thiết kế mới đó sẽ khó khăn đến mức nào? Thiết kế hiện tại khó hiểu và sửa đổi đến mức nào? Việc làm với một thiết kế tiên tiến hơn sẽ dễ dàng hơn thế nào, đối với những người được dự kiến sẽ thực hiện công việc? Và tất nhiên, có ai biết hình thức của mô hình mới sẽ ra sao không?

                                                                                                                                                                                                                                          Example
                                                                                                                                                                                                                                          Full Circle: Organization Chart Reabsorbs Its MECHANISM

                                                                                                                                                                                                                                          Trên thực tế, một năm sau khi chúng tôi hoàn thành mô hình tổ chức trong ví dụ trước, các nhà phát triển khác đã thiết kế lại nó để loại bỏ sự tách biệt của khung đồ thị. Họ cảm thấy việc tăng số lượng đối tượng và sự phức tạp trong việc tách MECHANISM thành một gói riêng là không cần thiết. Thay vào đó, họ đã thêm hành vi nút vào lớp cha của các THỰC THỂ tổ chức. Tuy nhiên, họ vẫn giữ giao diện công khai khai báo của mô hình tổ chức. Họ thậm chí giữ MECHANISM được đóng gói bên trong các THỰC THỂ tổ chức.

                                                                                                                                                                                                                                          Những vòng tròn đầy này thường gặp, nhưng chúng không trở về điểm khởi đầu. Kết quả cuối cùng thường là một mô hình sâu hơn, phân biệt rõ ràng hơn giữa các sự kiện, mục tiêu và CÁC CƠ CHẾ. Việc tái cấu trúc thực tiễn giữ lại những đức tính quan trọng của các giai đoạn trung gian trong khi loại bỏ những phức tạp không cần thiết.

                                                                                                                                                                                                                                          Distilling to a Declarative Style

                                                                                                                                                                                                                                          Thiết kế khai báo và "phong cách khai báo" là một chủ đề của Chương 10, nhưng phong cách thiết kế đó xứng đáng được đề cập đặc biệt trong chương này về tinh chế chiến lược. Giá trị của tinh chế là có thể nhìn thấy những gì bạn đang làm: cắt giảm để đi đến bản chất mà không bị phân tâm bởi những chi tiết không liên quan. Các phần quan trọng của MIỀN CỐT LÕI có thể theo một phong cách khai báo, khi thiết kế hỗ trợ cung cấp một ngôn ngữ kinh tế để diễn đạt các khái niệm và quy tắc của MIỀN CỐT LÕI trong khi bao trùm các cách thức tính toán hoặc thi hành chúng.

                                                                                                                                                                                                                                          CÁC CƠ CHẾ LIÊN KẾT là rất hữu ích khi chúng cung cấp quyền truy cập thông qua một GIAO DIỆN TIẾT LỘ Ý ĐỊNH, với các KHẲNG ĐỊNH có tính nhất quán khái niệm và CÁC HÀM KHÔNG CÓ TÁC ĐỘNG PHỤ. CÁC CƠ CHẾ và thiết kế linh hoạt cho phép MIỀN HẠNH TRANG chính thực hiện các tuyên bố có ý nghĩa thay vì gọi các hàm mơ hồ. Nhưng một phần thưởng đặc biệt đến khi một phần của MIỀN HẠNH TRANG tự nó đạt đến một mô hình sâu sắc và bắt đầu hoạt động như một ngôn ngữ có thể diễn đạt các kịch bản ứng dụng quan trọng nhất một cách linh hoạt và ngắn gọn.

                                                                                                                                                                                                                                          Một mô hình sâu thường đi kèm với một thiết kế linh hoạt tương ứng. Khi thiết kế linh hoạt đạt đến độ trưởng thành, nó cung cấp một tập hợp các yếu tố dễ hiểu có thể được kết hợp một cách rõ ràng để thực hiện các tác vụ phức tạp hoặc diễn đạt thông tin phức tạp, giống như các từ được kết hợp thành câu. Vào thời điểm đó, mã khách lấy phong cách tuyên bố và có thể cô đọng hơn nhiều.

                                                                                                                                                                                                                                          Việc tách rời CÁC TÊN MIỀN CHUNG giúp giảm bớt sự lộn xộn, và CÁC CƠ CHẾ NHẤT QUÁN phục vụ để bao encapsulate các thao tác phức tạp. Điều này để lại một mô hình tập trung hơn, với ít sự phân tâm hơn mà không có giá trị cụ thể nào cho cách người dùng thực hiện các hoạt động của họ. Nhưng bạn có khả năng sẽ không bao giờ tìm được nơi thích hợp cho mọi thứ trong mô hình miền mà không phải là CỐT LÕI. CỐT LÕI TÁCH BIỆT tiếp cận trực tiếp để đánh dấu cấu trúc CỐT LÕI...


                                                                                                                                                                                                                                            Segregated Core

                                                                                                                                                                                                                                            Các yếu tố trong mô hình có thể phục vụ một phần cho MIỀN CỐT LÕI và một phần đóng vai trò hỗ trợ. Các yếu tố CỐT LÕI có thể gắn kết chặt chẽ với các yếu tố tổng quát. Sự liên kết về mặt khái niệm của MIỀN CỐT LÕI có thể không mạnh mẽ hoặc không rõ ràng. Tất cả những rối ren và chằng chéo này làm nghẹt MIỀN CỐT LÕI. Các nhà thiết kế không thể nhìn thấy rõ những mối quan hệ quan trọng nhất, dẫn đến thiết kế yếu.

                                                                                                                                                                                                                                            Bằng cách trừu tượng hóa các TIỀN MIỀN TỔNG QUÁT, bạn làm rõ một số chi tiết che khuất khỏi miền, làm cho LÕI trở nên dễ nhìn hơn. Nhưng việc xác định và làm rõ tất cả những miền phụ này là một công việc khó khăn, và một số trong số chúng dường như không đáng công sức. Trong khi đó, MIỀN LÕI quan trọng tất yếu vẫn bị vướng víu với phần còn lại.

                                                                                                                                                                                                                                            Vì vậy:

                                                                                                                                                                                                                                            Tái cấu trúc mô hình để tách biệt các khái niệm CỐT LÕI khỏi các yếu tố hỗ trợ (bao gồm cả những yếu tố không rõ ràng) và củng cố sự gắn kết của CỐT LÕI trong khi giảm thiểu sự kết nối của nó với các đoạn mã khác. Phân tách tất cả các yếu tố chung hoặc hỗ trợ thành các đối tượng khác và đặt chúng vào các gói khác, ngay cả khi điều này có nghĩa là tái cấu trúc mô hình theo cách tách biệt các yếu tố gắn kết chặt chẽ.

                                                                                                                                                                                                                                            Điều này cơ bản là áp dụng cùng một nguyên tắc mà chúng tôi đã áp dụng cho CÁC TIỀN TỐ TỔNG QUÁT nhưng từ một hướng khác. Các tiền tố liên kết trọng tâm cho ứng dụng của chúng tôi có thể được xác định và phân chia thành những gói hợp lý riêng. Những gì được làm với khối lượng không phân biệt còn lại là quan trọng, nhưng không quan trọng bằng. Nó có thể được để lại gần như ở nguyên vị trí, hoặc được đặt vào các gói dựa trên các lớp nổi bật. Cuối cùng, ngày càng nhiều phần dư có thể được phân loại thành CÁC TIỀN TỐ TỔNG QUÁT, nhưng trong ngắn hạn, bất kỳ giải pháp dễ dàng nào cũng đủ, miễn là vẫn giữ được sự tập trung vào NỀN TẢNG PHÂN BIỆT.

                                                                                                                                                                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                            Các bước cần thiết để tái cấu trúc thành HẠNG NGUYÊN TÁCH BIỆT thường là như sau:

                                                                                                                                                                                                                                            1. Xác định một tiểu miền CỐT LÕI (có thể rút ra từ tài liệu chưng cất).

                                                                                                                                                                                                                                            Di chuyển các lớp liên quan đến một MODULE mới, được đặt tên theo khái niệm mà chúng liên quan.

                                                                                                                                                                                                                                            Tái cấu trúc mã để tách dữ liệu và chức năng không phải là các biểu thức trực tiếp của khái niệm. Đưa các khía cạnh đã loại bỏ vào (các) lớp (có thể mới) trong các gói khác. Cố gắng đặt chúng với các nhiệm vụ có liên quan về mặt khái niệm, nhưng đừng lãng phí quá nhiều thời gian để hoàn thiện. Tập trung vào việc làm sạch miền con CORE và làm cho các tham chiếu từ nó đến các gói khác trở nên rõ ràng và dễ hiểu.

                                                                                                                                                                                                                                            Tái cấu trúc MODULE LÕI MỚI ĐƯỢC PHÂN TÁCH để làm cho các mối quan hệ và tương tác của nó đơn giản hơn và dễ hiểu hơn, đồng thời giảm thiểu và làm rõ các mối quan hệ của nó với các MODULE khác. (Điều này trở thành một mục tiêu tái cấu trúc liên tục.)

                                                                                                                                                                                                                                            Lặp lại với một miền con CORE khác cho đến khi CORE PHÂN LẬP hoàn thành.

                                                                                                                                                                                                                                            The Costs of Creating a SEGREGATED CORE

                                                                                                                                                                                                                                            Việc tách riêng CORE đôi khi sẽ làm cho mối quan hệ với các lớp không phải CORE liên kết chặt chẽ trở nên mơ hồ hơn hoặc thậm chí phức tạp hơn, nhưng chi phí đó được bù đắp bởi lợi ích của việc làm rõ miền CORE và giúp việc làm việc trở nên dễ dàng hơn rất nhiều.

                                                                                                                                                                                                                                            Lõi PHÂN TÁCH sẽ cho phép bạn tăng cường sự gắn kết của LĨNH VỰC LÕI đó. Có nhiều cách ý nghĩa để phân chia một mô hình, và đôi khi trong quá trình tạo ra một LÕI PHÂN TÁCH, một MODULE có sự gắn kết tốt có thể bị phá vỡ, hy sinh sự gắn kết đó để làm nổi bật sự gắn kết của LĨNH VỰC LÕI. Đây là một sự tăng trưởng ròng, vì giá trị gia tăng lớn nhất của phần mềm doanh nghiệp đến từ các khía cạnh riêng biệt của mô hình theo doanh nghiệp.

                                                                                                                                                                                                                                            Chi phí khác, tất nhiên, là việc phân tách CORE là một công việc rất nặng nhọc. Cần phải thừa nhận rằng quyết định chuyển sang một CORE PHÂN TÁCH có thể sẽ khiến các nhà phát triển bận rộn với các thay đổi trong toàn bộ hệ thống.

                                                                                                                                                                                                                                            Thời điểm để tách ra một LÒNG CỐNG PHÂN TÁCH là khi bạn có một NGỮ CẢNH GIỚI HẠN LỚN mà có vai trò quan trọng đối với hệ thống, nhưng phần thiết yếu của mô hình đang bị che khuất bởi rất nhiều khả năng hỗ trợ.

                                                                                                                                                                                                                                            Evolving Team Decision

                                                                                                                                                                                                                                            Cũng giống như nhiều quyết định thiết kế chiến lược, toàn bộ đội ngũ phải cùng nhau chuyển sang một HẠNG MỤC TÁCH BIỆT. Bước này yêu cầu một quy trình ra quyết định của đội và một đội ngũ có kỷ luật và phối hợp đủ để thực hiện quyết định đó. Thách thức là ràng buộc mọi người sử dụng cùng một định nghĩa về HẠNG MỤC mà không đóng băng quyết định đó. Bởi vì LĨNH VỰC CỐT LÕI phát triển giống như mọi khía cạnh khác của thiết kế, kinh nghiệm làm việc với HẠNG MỤC TÁCH BIỆT sẽ dẫn đến những hiểu biết mới về những gì là thiết yếu và những gì là yếu tố hỗ trợ. Những hiểu biết đó nên được phản hồi lại vào một định nghĩa tinh chỉnh về LĨNH VỰC CỐT LÕI và về CÁC MÔ ĐUN TÁCH BIỆT.

                                                                                                                                                                                                                                            Điều này có nghĩa là những hiểu biết mới phải được chia sẻ với nhóm một cách liên tục, nhưng một cá nhân (hoặc cặp lập trình) không thể hành động dựa trên những hiểu biết đó một cách đơn phương. Dù quy trình ra quyết định chung là gì, cho dù là đồng thuận hay chỉ đạo từ người lãnh đạo nhóm, nó phải đủ linh hoạt để thực hiện các điều chỉnh liên tục. Giao tiếp phải hiệu quả đủ để giữ mọi người cùng có một quan điểm về CỐT LÕI.

                                                                                                                                                                                                                                            Example
                                                                                                                                                                                                                                            Segregating the CORE of a Cargo Shipping Model

                                                                                                                                                                                                                                            Chúng tôi bắt đầu với mô hình được hiển thị trong Hình 15.2 làm cơ sở cho phần mềm điều phối vận chuyển hàng hóa.

                                                                                                                                                                                                                                            Figure 15.2.

                                                                                                                                                                                                                                            graphics/15fig02.gif

                                                                                                                                                                                                                                            Lưu ý rằng điều này được đơn giản hóa rất nhiều so với những gì có thể cần cho một ứng dụng thực tế. Một mô hình thực tế sẽ quá rườm rà cho một ví dụ. Do đó, mặc dù ví dụ này có thể không đủ phức tạp để khiến chúng ta phải chuyển sang một LÕI TÁCH BIỆT, hãy dùng một chút tưởng tượng để xem mô hình này như thể nó quá phức tạp để dễ dàng diễn giải và xử lý như một tổng thể.

                                                                                                                                                                                                                                            Bây giờ, tinh túy của mô hình vận chuyển là gì? Thông thường, một nơi tốt để bắt đầu tìm kiếm là "lợi nhuận cuối cùng." Điều này có thể dẫn chúng ta tập trung vào giá cả và hóa đơn. Nhưng chúng ta thực sự cần phải xem xét TƯỞNG TƯỢNG MIỀN. Đây là một đoạn trích từ cái này.

                                                                                                                                                                                                                                            ... Tăng cường khả năng nhìn thấy hoạt động và cung cấp công cụ để đáp ứng yêu cầu của khách hàng nhanh hơn và đáng tin cậy hơn...

                                                                                                                                                                                                                                            Ứng dụng này không được thiết kế cho bộ phận bán hàng. Nó sẽ được sử dụng bởi các nhân viên tuyến đầu của công ty. Vì vậy, hãy chuyển tất cả các vấn đề liên quan đến tiền đến những vai trò hỗ trợ (dù quan trọng). Ai đó đã đặt một số mục này vào một gói riêng (Hóa đơn). Chúng ta có thể giữ lại điều đó và công nhận rằng nó đóng một vai trò hỗ trợ.

                                                                                                                                                                                                                                            Sự chú trọng cần phải đặt vào việc xử lý hàng hóa: giao hàng theo yêu cầu của khách hàng. Việc tách các lớp liên quan trực tiếp đến những hoạt động này sẽ tạo ra một CỐT LÕI TÁCH BIỆT trong một gói mới có tên là Giao hàng, như được thể hiện trong Hình 15.3.

                                                                                                                                                                                                                                            Figure 15.3. Reliable delivery in adherence with customer requirements is the core goal of this project.

                                                                                                                                                                                                                                            graphics/15fig03.gif

                                                                                                                                                                                                                                            Phần lớn, các lớp chỉ được chuyển vào gói mới, nhưng đã có một vài thay đổi đối với chính mô hình.

                                                                                                                                                                                                                                            Đầu tiên, Thỏa thuận Khách hàng hiện đang hạn chế Bước Xử lý. Đây là điều điển hình cho những hiểu biết thường phát sinh khi nhóm tách biệt CORE. Khi sự chú ý được tập trung vào việc giao hàng hiệu quả và chính xác, rõ ràng rằng những hạn chế giao hàng trong Thỏa thuận Khách hàng là cơ bản và nên được nêu rõ trong mô hình.

                                                                                                                                                                                                                                            Sự thay đổi khác là có tính thực tiễn hơn. Trong mô hình đã được cải tiến, Thỏa thuận Khách hàng được gắn trực tiếp vào Cargo, thay vì yêu cầu phải truy cập qua Khách hàng. (Nó sẽ phải được gắn khi Cargo được đặt chỗ, cũng như Khách hàng.) Vào thời điểm giao hàng thực tế, Khách hàng không quan trọng đối với hoạt động như chính thỏa thuận đó. Trong mô hình khác, Khách hàng đúng phải được tìm ra, dựa vào vai trò mà nó đóng trong lô hàng, và sau đó được truy vấn để lấy Thỏa thuận Khách hàng. Tương tác này sẽ làm tắc nghẽn mọi câu chuyện mà bạn muốn kể về mô hình. Mối liên hệ mới làm cho các kịch bản quan trọng nhất trở nên đơn giản và trực tiếp nhất có thể. Giờ đây, việc tách Khách hàng ra khỏi CORE trở nên dễ dàng hơn.

                                                                                                                                                                                                                                            Và việc kéo Khách hàng ra sao? Trọng tâm là đáp ứng các yêu cầu của Khách hàng, vì vậy ban đầu Khách hàng có vẻ thuộc về Lõi. Tuy nhiên, các tương tác trong quá trình cung cấp thường không cần phải liên quan đến lớp Khách hàng khi Thoả thuận Khách hàng đã có sẵn trực tiếp. Và mô hình cơ bản của một Khách hàng thì khá chung chung.

                                                                                                                                                                                                                                            Có thể đưa ra một lập luận mạnh mẽ cho việc Leg nên ở lại trong CORE. Tôi có xu hướng tối giản trong CORE, và Leg có sự gắn kết chặt chẽ hơn với Lịch trình Vận chuyển, Dịch vụ Định tuyến và Vị trí, tất cả đều không cần thiết phải ở trong CORE. Nhưng nếu nhiều câu chuyện tôi muốn kể về mô hình này liên quan đến Legs, tôi sẽ chuyển nó vào gói Delivery và chấp nhận sự bất tiện của việc tách rời khỏi những lớp khác.

                                                                                                                                                                                                                                            Trong ví dụ này, tất cả các định nghĩa lớp đều giống như trước, nhưng thường thì quá trình tinh chế yêu cầu phải cấu trúc lại các lớp để tách biệt các trách nhiệm chung và đặc thù của miền, điều này sau đó có thể được phân chia.

                                                                                                                                                                                                                                            Bây giờ chúng ta đã có một Lõi Tách biệt, việc tái cấu trúc đã hoàn tất. Nhưng gói Giao hàng mà chúng ta còn lại chỉ là "tất cả những gì còn lại sau khi chúng ta đã tách ra Lõi." Chúng ta có thể tiếp tục với các tái cấu trúc khác để có được các gói ngữ nghĩa hơn, như đã thấy trong Hình 15.4.

                                                                                                                                                                                                                                            Figure 15.4. Meaningful MODULES for non-CORE subdomains follow after the SEGREGATED CORE is complete.

                                                                                                                                                                                                                                            graphics/15fig04.gif

                                                                                                                                                                                                                                            Có thể sẽ cần vài lần tái cấu trúc để đạt được điểm này; không cần phải hoàn thành tất cả cùng một lúc. Ở đây, chúng ta đã có một gói CORE PHÂN TÁCH, một TIỀM NĂNG CHUNG, và hai gói theo miền cụ thể ở vai trò hỗ trợ. Hiểu biết sâu hơn có thể cuối cùng sẽ tạo ra một TIỀM NĂNG CHUNG cho Khách hàng, hoặc nó có thể trở nên chuyên biệt hơn cho việc vận chuyển.

                                                                                                                                                                                                                                            Nhận diện các MODULE hữu ích và có ý nghĩa là một hoạt động mô hình hóa (như đã thảo luận trong Chương 5). Các nhà phát triển và chuyên gia trong lĩnh vực hợp tác trong việc tinh chất chiến lược như một phần của quá trình xử lý kiến thức.


                                                                                                                                                                                                                                              Abstract Core

                                                                                                                                                                                                                                              graphics/15inf03.gif

                                                                                                                                                                                                                                              Ngay cả mô hình CORE DOMAIN thường có quá nhiều chi tiết đến nỗi việc truyền đạt bức tranh tổng thể có thể gặp khó khăn.

                                                                                                                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                              Chúng tôi thường xử lý một mô hình lớn bằng cách chia nhỏ nó thành các miền con hẹp hơn, đủ nhỏ để có thể dễ hiểu, và đặt chúng vào các MODULE riêng biệt. Cách đóng gói theo phong cách giảm thiểu này thường giúp làm cho một mô hình phức tạp trở nên dễ quản lý. Nhưng đôi khi việc tạo ra các MODULE riêng biệt có thể khiến cho các tương tác giữa các miền con trở nên khó hiểu hoặc thậm chí phức tạp hơn.

                                                                                                                                                                                                                                              Khi có nhiều tương tác giữa các tiểu miền trong các MODULE riêng biệt, hoặc nhiều tham chiếu sẽ phải được tạo ra giữa các MODULE, điều này làm mất đi nhiều giá trị của việc phân vùng, hoặc tương tác sẽ phải được thực hiện gián tiếp, điều này làm cho mô hình trở nên khó hiểu.

                                                                                                                                                                                                                                              Xem xét việc cắt ngang thay vì cắt dọc. Tính đa hình cho chúng ta sức mạnh để bỏ qua nhiều biến thể chi tiết giữa các thể hiện của một loại trừu tượng. Nếu hầu hết các tương tác giữa các MODULES có thể được biểu diễn ở cấp độ giao diện đa hình, có thể hợp lý để tái cấu trúc các loại này thành một MODULE CƠ BẢN đặc biệt.

                                                                                                                                                                                                                                              Chúng tôi không tìm kiếm một mẹo kỹ thuật ở đây. Đây là một kỹ thuật giá trị chỉ khi các giao diện đa hình tương ứng với các khái niệm cơ bản trong miền. Trong trường hợp đó, việc tách biệt những trừu tượng này làm cho các MODULES trở nên tách rời trong khi tinh chế một LĨNH VỰC CỐT LÕI nhỏ hơn và gắn kết hơn.

                                                                                                                                                                                                                                              Vì vậy:

                                                                                                                                                                                                                                              Xác định các khái niệm cơ bản nhất trong mô hình và phân loại chúng thành các lớp khác nhau, lớp trừu tượng hoặc giao diện. Thiết kế mô hình trừu tượng này sao cho nó thể hiện hầu hết sự tương tác giữa các thành phần quan trọng. Đặt mô hình tổng thể trừu tượng này vào MODULE riêng, trong khi các lớp triển khai chi tiết, chuyên biệt được để trong các MODULE riêng do tiểu miền xác định.

                                                                                                                                                                                                                                              Hầu hết các lớp chuyên ngành bây giờ sẽ tham khảo MÔ-ĐUN CỐT LÕI TRỪU TƯỢNG nhưng không phải các MÔ-ĐUN chuyên ngành khác. MÔ-ĐUN CỐT LÕI TRỪU TƯỢNG cung cấp cái nhìn tóm tắt về các khái niệm chính và sự tương tác của chúng.

                                                                                                                                                                                                                                              Quá trình tách ra LÕI TRỪU TƯỢNG không phải là cơ học. Chẳng hạn, nếu tất cả các lớp thường xuyên được tham chiếu trong các MODULE được tự động chuyển vào một MODULE riêng, kết quả có thể sẽ là một mớ hỗn độn vô nghĩa. Mô hình hóa LÕI TRỪU TƯỢNG đòi hỏi hiểu biết sâu sắc về các khái niệm chính và vai trò của chúng trong các tương tác chính của hệ thống. Nói cách khác, đây là một ví dụ về việc tái cấu trúc để có cái nhìn sâu sắc hơn. Và thường nó yêu cầu thiết kế lại đáng kể.

                                                                                                                                                                                                                                              CỐT LÕI TRỪU TƯỢNG nên kết thúc với hình dáng giống như tài liệu chưng cất (nếu cả hai được sử dụng cho cùng một dự án, và tài liệu chưng cất đã phát triển cùng với ứng dụng khi sự hiểu biết sâu sắc hơn). Tất nhiên, CỐT LÕI TRỪU TƯỢNG sẽ được viết bằng mã, do đó sẽ nghiêm ngặt hơn và hoàn chỉnh hơn.

                                                                                                                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif


                                                                                                                                                                                                                                                Deep Models Distill

                                                                                                                                                                                                                                                Chưng cất không chỉ hoạt động ở mức độ tổng quát là tách các phần của miền ra khỏi CƠ SỞ. Nó cũng có nghĩa là tinh chỉnh những miền con, đặc biệt là MIỀN CỐT LÕI, thông qua việc liên tục tái cấu trúc để hướng tới sự hiểu biết sâu sắc hơn, tiến tới một mô hình sâu sắc và thiết kế linh hoạt. Mục tiêu là một thiết kế làm cho mô hình trở nên rõ ràng, một mô hình thể hiện miền một cách đơn giản. Một mô hình sâu sắc chưng cất các khía cạnh thiết yếu nhất của một miền thành những phần tử đơn giản có thể kết hợp để giải quyết các vấn đề quan trọng của ứng dụng.

                                                                                                                                                                                                                                                Mặc dù một đột phá vào một mô hình sâu mang lại giá trị ở mọi nơi, nhưng chính trong MIỀN CỐT LÕI mà nó có thể thay đổi quỹ đạo của toàn bộ dự án.


                                                                                                                                                                                                                                                  Choosing Refactoring Targets

                                                                                                                                                                                                                                                  Khi bạn gặp phải một hệ thống lớn mà không được cấu trúc tốt, bạn sẽ bắt đầu từ đâu? Trong cộng đồng XP, câu trả lời thường là một trong những điều này:

                                                                                                                                                                                                                                                  1. Chỉ cần bắt đầu ở bất kỳ đâu, vì mọi thứ đều phải được tái cấu trúc.

                                                                                                                                                                                                                                                  Bắt đầu từ bất cứ đâu mà nó đang đau. Tôi sẽ điều chỉnh những gì tôi cần để hoàn thành nhiệm vụ cụ thể của mình.

                                                                                                                                                                                                                                                  Tôi không đồng ý với cả hai điều này. Điều đầu tiên là không thực tế ngoại trừ trong một vài dự án được lấp đầy hoàn toàn bởi các lập trình viên hàng đầu. Điều thứ hai thường chỉ xử lý những vấn đề bên ngoài, điều trị các triệu chứng và phớt lờ nguyên nhân gốc rễ, tránh xa những mớ bòng bong tồi tệ nhất. Cuối cùng, mã trở nên ngày càng khó để tái cấu trúc.

                                                                                                                                                                                                                                                  Vậy, nếu bạn không thể làm tất cả, và bạn không thể bị thúc đẩy bởi nỗi đau, thì bạn sẽ làm gì?

                                                                                                                                                                                                                                                  1. Trong một quá trình tái cấu trúc do đau đớn, bạn sẽ xem xét liệu gốc rễ có liên quan đến LĨNH VỰC CỐT LÕI hoặc mối quan hệ giữa LĨNH VỰC CỐT LÕI và một yếu tố hỗ trợ hay không. Nếu có, bạn phải dứt khoát sửa chữa điều đó trước tiên.

                                                                                                                                                                                                                                                  Khi bạn có sự thoải mái trong việc tái cấu trúc một cách tự do, bạn trước tiên sẽ tập trung vào việc phân tách tốt hơn của MIỀN CỐT LÕI, cải thiện việc phân chia MIỀN CỐT LÕI, và tinh sạch các miền phụ hỗ trợ để trở nên TỔNG QUÁT.

                                                                                                                                                                                                                                                  Đây là cách để tận dụng tối đa giá trị của việc tái cấu trúc mã.


                                                                                                                                                                                                                                                    Chapter Sixteen. Large-Scale Structure

                                                                                                                                                                                                                                                    Hàng ngàn người đã làm việc độc lập để tạo ra tấm chăn AIDS.

                                                                                                                                                                                                                                                    graphics/16inf01.gif

                                                                                                                                                                                                                                                    Một công ty thiết kế nhỏ ở Silicon Valley đã được hợp đồng để tạo ra một mô phỏng cho một hệ thống truyền thông vệ tinh. Công việc đang tiến triển tốt. Một THIẾT KẾ DỰA TRÊN MÔ HÌNH đang phát triển có thể biểu diễn và mô phỏng một loạt các điều kiện và sự cố mạng.

                                                                                                                                                                                                                                                    Nhưng các nhà phát triển chính trong dự án cảm thấy bất an. Vấn đề vốn đã phức tạp. Bị thúc đẩy bởi nhu cầu làm rõ các mối quan hệ rắc rối trong mô hình, họ đã phân tách thiết kế thành các MODULES đồng nhất với quy mô có thể quản lý. Giờ thì có rất nhiều MODULES. Một nhà phát triển nên tìm ở gói nào để tìm một khía cạnh cụ thể của chức năng? Một lớp mới nên được đặt ở đâu? Một số gói nhỏ này thật sự có ý nghĩa gì? Chúng liên kết với nhau như thế nào? Và vẫn còn nhiều thứ cần phải xây dựng.

                                                                                                                                                                                                                                                    Các lập trình viên đã giao tiếp tốt với nhau và vẫn có thể tìm ra những việc cần làm từ ngày này qua ngày khác, nhưng các lãnh đạo dự án không hài lòng với việc chỉ ở mức hiểu biết. Họ muốn có một cách nào đó để tổ chức thiết kế sao cho có thể hiểu và điều chỉnh khi nó tiến tới mức độ phức tạp tiếp theo.

                                                                                                                                                                                                                                                    Họ đã động não. Có rất nhiều khả năng. Các phương án đóng gói khác nhau đã được đề xuất. Có thể một tài liệu nào đó có thể cung cấp cái nhìn tổng quan về hệ thống, hoặc một số cái nhìn mới về sơ đồ lớp trong công cụ mô hình hóa có thể hướng dẫn một nhà phát triển đến MODULE đúng. Nhưng các lãnh đạo dự án không hài lòng với những mánh khóe này.

                                                                                                                                                                                                                                                    Họ có thể kể một câu chuyện đơn giản về mô phỏng của họ, về cách dữ liệu sẽ được tập hợp qua một cơ sở hạ tầng, sự toàn vẹn và định tuyến của nó được đảm bảo bởi các lớp công nghệ viễn thông. Mọi chi tiết của câu chuyện đó đều có trong mô hình, nhưng vòng cung rộng lớn của câu chuyện thì không thể được nhìn thấy.

                                                                                                                                                                                                                                                    Một số khái niệm cơ bản từ lĩnh vực đã bị thiếu. Nhưng lần này không phải là một hoặc hai lớp bị thiếu trong mô hình đối tượng, mà là một cấu trúc bị thiếu cho toàn bộ mô hình.

                                                                                                                                                                                                                                                    Sau khi các nhà phát triển xem xét vấn đề trong một hoặc hai tuần, ý tưởng bắt đầu hình thành. Họ sẽ áp dụng một cấu trúc cho thiết kế. Toàn bộ mô phỏng sẽ được nhìn nhận như một loạt các lớp liên quan đến các khía cạnh của hệ thống thông tin liên lạc. Lớp dưới cùng sẽ đại diện cho cơ sở hạ tầng vật lý, khả năng cơ bản để truyền tải các bit từ một nút này sang nút khác. Tiếp theo sẽ có một lớp định tuyến gói dữ liệu kết hợp các mối quan tâm về cách một luồng dữ liệu cụ thể sẽ được chỉ đạo. Các lớp khác sẽ xác định các cấp độ khái niệm khác của vấn đề. Những lớp này sẽ phác thảo câu chuyện của hệ thống.

                                                                                                                                                                                                                                                    Họ bắt đầu tái cấu trúc mã để tuân theo cấu trúc mới. CÁC MODULES cần được định nghĩa lại để không trải dài qua các lớp. Trong một số trường hợp, trách nhiệm của các đối tượng đã được tái cấu trúc để mỗi đối tượng rõ ràng thuộc về một lớp. Ngược lại, trong suốt quá trình này, các định nghĩa của các lớp khái niệm đã được tinh chỉnh dựa trên kinh nghiệm thực tế khi áp dụng chúng. Các lớp, CÁC MODULES và các đối tượng đã tiến hóa đồng thời cho đến khi, cuối cùng, toàn bộ thiết kế tuân theo hình dạng của cấu trúc theo lớp này.

                                                                                                                                                                                                                                                    Các lớp này không phải là MODULES hay bất kỳ thành phần nào khác trong mã. Chúng là một tập hợp các quy tắc tổng thể ràng buộc các giới hạn và mối quan hệ của bất kỳ MODULE hoặc đối tượng nào trong toàn bộ thiết kế, ngay cả ở các giao diện với các hệ thống khác.

                                                                                                                                                                                                                                                    Việc áp dụng trật tự này đã đưa thiết kế trở lại với khả năng hiểu biết thoải mái. Mọi người biết đại khái nơi cần tìm để biết chức năng cụ thể. Các cá nhân làm việc độc lập có thể đưa ra quyết định thiết kế phù hợp với nhau. Giới hạn độ phức tạp đã được nâng lên.

                                                                                                                                                                                                                                                    Ngay cả với một sự phân chia MODULE, một mô hình lớn có thể quá phức tạp để hiểu. Các MODULE chia thiết kế thành những phần nhỏ dễ quản lý, nhưng có thể có rất nhiều MODULE như vậy. Ngoài ra, tính mô-đun không nhất thiết mang lại sự đồng nhất cho thiết kế. Từ đối tượng này sang đối tượng khác, từ gói này sang gói khác, có thể có một mớ các quyết định thiết kế được áp dụng, mỗi quyết định đều có thể biện minh nhưng mang tính cá nhân riêng.

                                                                                                                                                                                                                                                    Sự phân tách nghiêm ngặt do BỐI CẢNH HẠN CHẾ đặt ra ngăn chặn sự tham nhũng và nhầm lẫn, nhưng nó không giúp việc nhìn nhận hệ thống tổng thể dễ dàng hơn.

                                                                                                                                                                                                                                                    Chưng cất thực sự giúp bằng cách tập trung sự chú ý vào MIỀN CHỦ YẾU và đặt các miền phụ khác vào vai trò hỗ trợ. Nhưng vẫn cần thiết phải hiểu các yếu tố hỗ trợ và mối quan hệ của chúng với MIỀN CHỦ YẾU - và với nhau. Mặc dù MIỀN CHỦ YẾU lẽ ra sẽ rõ ràng và dễ hiểu đến mức không cần hướng dẫn thêm, chúng ta không phải lúc nào cũng đạt được điều đó.

                                                                                                                                                                                                                                                    Trong một dự án bất kỳ quy mô nào, mọi người phải làm việc khá độc lập trên các phần khác nhau của hệ thống. Nếu không có sự phối hợp hoặc quy tắc, sẽ có sự nhầm lẫn về các phong cách khác nhau và các giải pháp khác nhau cho cùng một vấn đề, khiến cho việc hiểu cách các phần kết hợp với nhau trở nên khó khăn và việc nhìn thấy bức tranh tổng thể trở nên không thể. Việc học hỏi về một phần của thiết kế sẽ không chuyển giao được sang các phần khác, do đó dự án sẽ có những chuyên gia trong các MODULE khác nhau không thể giúp đỡ nhau ngoài phạm vi hẹp của họ. QUÁ TRÌNH TÍCH HỢP LIÊN TỤC bị phá vỡ và BỐ CỤC RÀNG BUỘC bị phân mảnh.

                                                                                                                                                                                                                                                    Trong một hệ thống lớn mà không có nguyên tắc tổng quát nào cho phép các yếu tố được diễn giải theo vai trò của chúng trong các mô hình bao trùm toàn bộ thiết kế, các nhà phát triển không thể nhìn thấy toàn cảnh vì những chi tiết nhỏ. Chúng ta cần có khả năng hiểu vai trò của một phần cá nhân trong toàn bộ mà không cần phải đi sâu vào chi tiết của toàn bộ.

                                                                                                                                                                                                                                                    Một "cấu trúc quy mô lớn" là một ngôn ngữ cho phép bạn thảo luận và hiểu hệ thống một cách tổng quát. Một tập hợp các khái niệm hoặc quy tắc cấp cao, hoặc cả hai, thiết lập một mẫu thiết kế cho toàn bộ hệ thống. Nguyên tắc tổ chức này có thể hướng dẫn thiết kế cũng như hỗ trợ sự hiểu biết. Nó giúp phối hợp công việc độc lập vì có một khái niệm chung về bức tranh tổng thể: cách mà các vai trò của các phần khác nhau hình thành nên toàn bộ.

                                                                                                                                                                                                                                                    Xây dựng một mẫu quy tắc hoặc vai trò và mối quan hệ sẽ trải dài toàn bộ hệ thống và cho phép một sự hiểu biết nào đó về vị trí của mỗi phần trong tổng thể - ngay cả khi không có kiến thức chi tiết về trách nhiệm của phần đó.

                                                                                                                                                                                                                                                    Cấu trúc có thể bị giới hạn trong một BỐI CẢNH RÀNG BUỘC nhưng thường sẽ trải dài qua nhiều bối cảnh, cung cấp tổ chức khái niệm để gắn kết tất cả các đội và hệ thống con tham gia vào dự án. Một cấu trúc tốt mang lại cái nhìn sâu sắc về mô hình và bổ sung cho quá trình tinh chế.

                                                                                                                                                                                                                                                    Bạn không thể biểu diễn hầu hết các cấu trúc quy mô lớn trong UML, và bạn cũng không cần phải làm vậy. Hầu hết các cấu trúc quy mô lớn định hình và giải thích mô hình và thiết kế nhưng không xuất hiện trong đó. Chúng cung cấp một cấp độ giao tiếp bổ sung về thiết kế. Trong các ví dụ của chương này, bạn sẽ thấy nhiều sơ đồ UML không chính thức mà tôi đã chồng thông tin về cấu trúc quy mô lớn lên trên đó.

                                                                                                                                                                                                                                                    Khi một đội ngũ đủ nhỏ và mô hình không quá phức tạp, việc phân chia thành các MODULES được đặt tên hợp lý, một lượng tinh chế nhất định và sự phối hợp không chính thức giữa các nhà phát triển có thể đủ để giữ cho mô hình được tổ chức.

                                                                                                                                                                                                                                                    Cấu trúc quy mô lớn có thể cứu một dự án, nhưng một cấu trúc không phù hợp có thể cản trở nghiêm trọng sự phát triển. Chương này khám phá các mô hình để cấu trúc một thiết kế thành công ở cấp độ này.

                                                                                                                                                                                                                                                    Figure 16.1. Some patterns of large-scale structure

                                                                                                                                                                                                                                                    graphics/16fig01.gif


                                                                                                                                                                                                                                                      Evolving Order

                                                                                                                                                                                                                                                      Nhiều nhà phát triển đã trải qua chi phí của một thiết kế không có cấu trúc. Để tránh sự hỗn loạn, các dự án áp đặt các kiến trúc mà hạn chế việc phát triển theo nhiều cách khác nhau. Một số kiến trúc kỹ thuật giải quyết được các vấn đề kỹ thuật, chẳng hạn như mạng lưới hoặc lưu trữ dữ liệu, nhưng khi các kiến trúc bắt đầu dấn thân vào lĩnh vực của ứng dụng và mô hình miền, chúng có thể tạo ra những vấn đề riêng. Chúng thường ngăn cản các nhà phát triển tạo ra các thiết kế và mô hình phù hợp với đặc thù của vấn đề. Những kiến trúc tham vọng nhất thậm chí có thể lấy đi của các nhà phát triển ứng dụng sự quen thuộc và sức mạnh kỹ thuật của chính ngôn ngữ lập trình. Và cho dù là kiến trúc định hướng kỹ thuật hay miền, những kiến trúc đóng băng nhiều quyết định thiết kế từ trước có thể trở thành một chiếc áo bó khi các yêu cầu thay đổi và sự hiểu biết sâu sắc hơn.

                                                                                                                                                                                                                                                      Trong khi một số kiến trúc kỹ thuật (chẳng hạn như J2EE) đã trở nên nổi bật qua nhiều năm, cấu trúc quy mô lớn trong lớp miền chưa được khám phá nhiều. Nhu cầu khác nhau rất nhiều từ ứng dụng này sang ứng dụng khác.

                                                                                                                                                                                                                                                      Việc áp đặt một cấu trúc quy mô lớn ngay từ đầu có khả năng tốn kém. Khi quá trình phát triển tiến triển, bạn gần như chắc chắn sẽ tìm thấy một cấu trúc phù hợp hơn, và bạn có thể phát hiện ra rằng cấu trúc đã được quy định đang cản trở bạn lựa chọn một hướng thiết kế sẽ làm rõ ràng hoặc đơn giản hóa ứng dụng. Bạn có thể sử dụng một số phần của cấu trúc, nhưng bạn đang từ chối những cơ hội. Công việc của bạn chậm lại khi bạn cố gắng tìm cách làm việc khác hoặc cố gắng đàm phán với các kiến trúc sư. Nhưng các quản lý của bạn nghĩ rằng kiến trúc đã hoàn tất. Nó đáng lẽ phải làm cho ứng dụng này dễ dàng, vậy tại sao bạn không làm việc trên ứng dụng mà lại phải đối phó với tất cả những vấn đề về kiến trúc này? Các quản lý và nhóm kiến trúc có thể thậm chí cởi mở với ý kiến, nhưng nếu mỗi thay đổi đều là một cuộc chiến vĩ đại, thì thật quá mệt mỏi.

                                                                                                                                                                                                                                                      Thiết kế không có tổ chức tạo ra các hệ thống mà không ai có thể hiểu một cách tổng thể, và chúng rất khó để duy trì. Nhưng kiến trúc có thể hạn chế một dự án với những giả định thiết kế từ đầu và lấy đi quá nhiều quyền lực từ các nhà phát triển/nhà thiết kế của những phần cụ thể của ứng dụng. Sớm thôi, các nhà phát triển sẽ giảm bớt tính năng của ứng dụng để phù hợp với cấu trúc, hoặc họ sẽ lật đổ nó và không có cấu trúc nào cả, dẫn đến những vấn đề của sự phát triển không phối hợp.

                                                                                                                                                                                                                                                      Vấn đề không phải là sự tồn tại của các quy tắc hướng dẫn, mà là sự cứng nhắc và nguồn gốc của những quy tắc đó. Nếu các quy tắc chi phối thiết kế thực sự phù hợp với hoàn cảnh, chúng sẽ không cản trở mà thực sự đẩy sự phát triển theo hướng hữu ích, cũng như cung cấp sự nhất quán.

                                                                                                                                                                                                                                                      Vì vậy:

                                                                                                                                                                                                                                                      Hãy để cấu trúc quy mô lớn khái niệm này phát triển theo ứng dụng, có thể thay đổi thành một loại cấu trúc hoàn toàn khác trong quá trình này. Đừng hạn chế quá mức thiết kế chi tiết và các quyết định mẫu cần phải được đưa ra với kiến thức chi tiết.

                                                                                                                                                                                                                                                      Các phần riêng lẻ có cách tổ chức và biểu đạt tự nhiên hoặc hữu ích mà có thể không áp dụng cho toàn bộ, vì vậy việc áp đặt các quy tắc toàn cục sẽ làm cho những phần này trở nên kém lý tưởng. Việc chọn sử dụng một cấu trúc quy mô lớn ưu tiên cho khả năng quản lý của mô hình như một tổng thể hơn là cấu trúc tối ưu của các phần riêng lẻ. Do đó, sẽ có một số thỏa hiệp giữa cấu trúc thống nhất và tự do biểu đạt các thành phần riêng lẻ theo cách tự nhiên nhất. Điều này có thể được giảm thiểu bằng cách chọn cấu trúc dựa trên kinh nghiệm thực tế và kiến thức về lĩnh vực, đồng thời tránh các cấu trúc quá gò bó. Sự phù hợp thực sự giữa cấu trúc với lĩnh vực và yêu cầu sẽ khiến việc mô hình hóa và thiết kế chi tiết trở nên dễ dàng hơn, bằng cách giúp nhanh chóng loại bỏ nhiều lựa chọn.

                                                                                                                                                                                                                                                      Cấu trúc cũng có thể cung cấp các lối tắt cho các quyết định thiết kế mà về nguyên tắc có thể được tìm thấy bằng cách làm việc ở cấp độ đối tượng cá nhân, nhưng trên thực tế sẽ mất quá nhiều thời gian và có kết quả không nhất quán. Tất nhiên, việc tái cấu trúc liên tục vẫn là cần thiết, nhưng điều này sẽ làm cho quá trình trở nên dễ quản lý hơn và giúp những người khác nhau đưa ra những giải pháp nhất quán.

                                                                                                                                                                                                                                                      Một cấu trúc quy mô lớn thường cần phải áp dụng được trong các BỐI CẢNH RÀNG BUỘC. Thông qua việc lặp đi lặp lại trên một dự án thực tế, một cấu trúc sẽ mất đi những đặc điểm chặt chẽ gắn liền với một mô hình cụ thể và phát triển những đặc điểm tương ứng với CÁC ĐƯỜNG CONCEPTUAL của lĩnh vực. Điều này không có nghĩa là nó sẽ không có bất kỳ giả định nào về mô hình, nhưng nó sẽ không áp đặt lên toàn bộ dự án những ý tưởng được điều chỉnh theo một tình huống địa phương cụ thể. Nó phải để lại tự do cho các đội phát triển trong các BỐI CẢNH khác nhau thay đổi mô hình theo những cách phù hợp với nhu cầu địa phương của họ.

                                                                                                                                                                                                                                                      Ngoài ra, các cấu trúc quy mô lớn phải phù hợp với các ràng buộc thực tiễn trong việc phát triển. Chẳng hạn, các nhà thiết kế có thể không kiểm soát được mô hình của một số bộ phận của hệ thống, đặc biệt là trong trường hợp các hệ thống bên ngoài hoặc di sản. Điều này có thể được giải quyết bằng cách thay đổi cấu trúc để phù hợp hơn với các yếu tố bên ngoài cụ thể. Nó có thể được xử lý bằng cách xác định các cách mà ứng dụng liên quan đến các yếu tố bên ngoài. Nó có thể được giải quyết bằng cách làm cho cấu trúc đủ lỏng để có thể linh hoạt với những thực tế khó khăn.

                                                                                                                                                                                                                                                      Khác với BẢN ĐỒ NGỮ CẢNH, cấu trúc quy mô lớn là tùy chọn. Nó nên được áp dụng khi chi phí và lợi ích ủng hộ điều đó, và khi một cấu trúc phù hợp được tìm thấy. Thực tế, nó không cần thiết cho các hệ thống đủ đơn giản để có thể hiểu được khi được chia thành CÁC MÔ-ĐUN. Cấu trúc quy mô lớn nên được áp dụng khi một cấu trúc có thể được tìm thấy để làm rõ hệ thống mà không áp đặt những ràng buộc không tự nhiên lên việc phát triển mô hình. Bởi vì một cấu trúc không phù hợp thì còn tệ hơn không có gì, nên tốt nhất là không nên cố gắng để đạt được tính toàn diện, mà thay vào đó là tìm một tập hợp tối thiểu để giải quyết các vấn đề đã phát sinh. Ít hơn chính là nhiều hơn.

                                                                                                                                                                                                                                                      Một cấu trúc quy mô lớn có thể rất hữu ích và vẫn có một vài ngoại lệ, nhưng những ngoại lệ đó cần phải được đánh dấu bằng cách nào đó, để các nhà phát triển có thể giả định rằng cấu trúc đang được tuân thủ trừ khi có ghi chú khác. Và nếu những ngoại lệ đó bắt đầu trở nên nhiều, cấu trúc cần phải được thay đổi hoặc loại bỏ.

                                                                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                      Như đã đề cập, việc tạo ra một cấu trúc mang lại sự tự do cần thiết cho các nhà phát triển trong khi vẫn tránh được sự hỗn loạn không phải là điều dễ dàng. Mặc dù đã có nhiều công việc được thực hiện về kiến trúc kỹ thuật cho các hệ thống phần mềm, nhưng ít tài liệu đã được công bố về việc cấu trúc lớp miền. Một số phương pháp làm yếu đi ngữ nghĩa hướng đối tượng, chẳng hạn như những phương pháp phân loại miền theo nhiệm vụ ứng dụng hoặc theo trường hợp sử dụng. Toàn bộ lĩnh vực này vẫn chưa phát triển. Tôi đã quan sát thấy một số mô hình chung của các cấu trúc quy mô lớn đã xuất hiện trên nhiều dự án khác nhau. Tôi sẽ thảo luận về bốn mô hình trong chương này. Một trong số này có thể phù hợp với nhu cầu của bạn hoặc dẫn đến ý tưởng cho một cấu trúc phù hợp với dự án của bạn.


                                                                                                                                                                                                                                                        System Metaphor

                                                                                                                                                                                                                                                        Suy nghĩ ẩn dụ rất phổ biến trong phát triển phần mềm, đặc biệt là với các mô hình. Tuy nhiên, thực hành "ẩn dụ" trong Phát triển Cực đoan đã đến để chỉ một cách cụ thể sử dụng ẩn dụ nhằm mang lại trật tự cho việc phát triển toàn bộ hệ thống.

                                                                                                                                                                                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                        Cũng giống như một firewall có thể bảo vệ một tòa nhà khỏi ngọn lửa đang bùng phát qua các tòa nhà lân cận, một "firewall" phần mềm bảo vệ mạng nội bộ khỏi những mối nguy hiểm từ các mạng lớn hơn ở bên ngoài. Ẩn dụ này đã ảnh hưởng đến kiến trúc mạng và định hình một toàn bộ danh mục sản phẩm. Nhiều firewall cạnh tranh - được phát triển độc lập, được hiểu là có thể thay thế cho nhau - có sẵn cho người tiêu dùng. Những người mới bắt đầu trong lĩnh vực mạng dễ dàng nắm bắt khái niệm này. Sự hiểu biết chung này trong toàn ngành và giữa các khách hàng có được phần lớn nhờ vào ẩn dụ.

                                                                                                                                                                                                                                                        Tuy nhiên, đây là một phép ẩn dụ không chính xác, và sức mạnh của nó có hai mặt. Việc sử dụng phép ẩn dụ về tường lửa đã dẫn đến sự phát triển của các rào cản phần mềm đôi khi không đủ chọn lọc và cản trở các cuộc trao đổi mong muốn, trong khi không mang lại sự bảo vệ chống lại các mối đe dọa xuất phát từ bên trong bức tường. Ví dụ, các mạng LAN không dây rất dễ bị tổn thương. Sự rõ ràng của tường lửa đã mang lại lợi ích, nhưng tất cả các phép ẩn dụ đều mang theo một gánh nặng.

                                                                                                                                                                                                                                                        HỆ THỐNG ẨN DỤ cuối cùng đã trở nên rõ ràng với tôi khi tôi nghe Ward Cunningham sử dụng ví dụ về tường lửa trong một buổi giảng tại hội thảo.

                                                                                                                                                                                                                                                        Thiết kế phần mềm thường rất trừu tượng và khó hiểu. Cả lập trình viên và người dùng đều cần những cách cụ thể để hiểu hệ thống và chia sẻ cái nhìn về hệ thống như một tổng thể.

                                                                                                                                                                                                                                                        Ở một mức độ nào đó, phép ẩn dụ chạy sâu trong cách chúng ta tư duy đến mức nó thấm nhuần vào mọi thiết kế. Các hệ thống có "tầng" mà "xếp chồng" lên nhau. Chúng có "nhân" ở "trung tâm" của chúng. Nhưng đôi khi, một phép ẩn dụ xuất hiện có thể truyền tải chủ đề chính của toàn bộ thiết kế và cung cấp sự hiểu biết chung cho tất cả các thành viên trong nhóm.

                                                                                                                                                                                                                                                        Khi điều này xảy ra, hệ thống thực sự được định hình bởi phép ẩn dụ. Một nhà phát triển sẽ đưa ra các quyết định thiết kế phù hợp với phép ẩn dụ của hệ thống. Sự nhất quán này sẽ giúp các nhà phát triển khác hiểu các phần khác nhau của một hệ thống phức tạp theo cùng một phép ẩn dụ. Các nhà phát triển và chuyên gia có một điểm tham chiếu trong các cuộc thảo luận mà có thể cụ thể hơn cả mô hình tự nó.

                                                                                                                                                                                                                                                        HÌNH ẢNH HỆ THỐNG là một cấu trúc quy mô lớn, dễ hiểu, có tính hòa hợp với hình thức đối tượng. Bởi vì HÌNH ẢNH HỆ THỐNG chỉ là một phép so sánh với miền mà thôi, các mô hình khác nhau có thể được ánh xạ một cách gần đúng tới nó, điều này cho phép nó được áp dụng trong nhiều BỐI CẢNH RÕ RÀNG, giúp phối hợp công việc giữa chúng.

                                                                                                                                                                                                                                                        HỆ THỐNG ẨN DỤ đã trở thành một phương pháp phổ biến vì nó là một trong những thực hành cốt lõi của Lập trình cực đoan (Beck 2000). Thật không may, ít dự án tìm được những ẨN DỤ thực sự hữu ích, và mọi người đã cố gắng thúc đẩy ý tưởng này vào những lĩnh vực mà nó gây phản tác dụng. Một ẩn dụ thuyết phụcintroduces sẽ mang lại rủi ro rằng thiết kế sẽ tiếp nhận những khía cạnh của phép ẩn dụ mà không mong muốn cho vấn đề đang được xem xét, hoặc rằng phép ẩn dụ, trong khi hấp dẫn, có thể không phù hợp.

                                                                                                                                                                                                                                                        Điều đó nói lên rằng, ẨN DỤ HỆ THỐNG là một hình thức cấu trúc quy mô lớn được biết đến và hữu ích cho một số dự án, và nó minh họa tốt khái niệm tổng quát về một cấu trúc.

                                                                                                                                                                                                                                                        Vì vậy:

                                                                                                                                                                                                                                                        Khi một phép ẩn dụ cụ thể cho hệ thống xuất hiện, thu hút trí tưởng tượng của các thành viên trong nhóm và dường như dẫn dắt suy nghĩ theo hướng hữu ích, hãy chấp nhận nó như một cấu trúc quy mô lớn. Tổ chức thiết kế xung quanh phép ẩn dụ này và hấp thụ nó vào NGÔN NGỮ PHỔ BIẾN. PHÉP ẨN DỤ HỆ THỐNG nên thuận lợi hóa việc giao tiếp về hệ thống và hướng dẫn quá trình phát triển nó. Điều này tăng cường tính nhất quán ở các phần khác nhau của hệ thống, thậm chí có thể giữa các BỐ CỤC HẠN CHẾ khác nhau. Nhưng vì tất cả các phép ẩn dụ đều không chính xác, hãy liên tục xem xét lại phép ẩn dụ để tránh sự mở rộng quá mức hoặc sự không phù hợp, và sẵn sàng loại bỏ nó nếu nó cản trở.

                                                                                                                                                                                                                                                        graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                        The "Naive Metaphor" and Why We Don't Need It

                                                                                                                                                                                                                                                        Bởi vì một phép ẩn dụ hữu ích không xuất hiện trong hầu hết các dự án, một số người trong cộng đồng XP đã bắt đầu nói về phép ẩn dụ ngây thơ, mà họ có ý nói đến chính mô hình miền.

                                                                                                                                                                                                                                                        Một vấn đề với thuật ngữ này là một mô hình miền trưởng thành hoàn toàn không hề ngây thơ. Trên thực tế, "quy trình trả lương giống như một dây chuyền sản xuất" có lẽ là một quan điểm ngây thơ hơn nhiều so với một mô hình được sản sinh từ nhiều lần nghiền ngẫm kiến thức cùng với các chuyên gia trong lĩnh vực, và đã được chứng minh bằng việc được kết nối chặt chẽ với việc triển khai của một ứng dụng hoạt động.

                                                                                                                                                                                                                                                        Thuật ngữ "ẩn dụ ngây thơ" nên được loại bỏ.

                                                                                                                                                                                                                                                        HÌNH ẢNH HỆ THỐNG không hữu ích cho tất cả các dự án. Cấu trúc quy mô lớn nói chung không phải là điều thiết yếu. Trong 12 thực hành của Lập trình cực đoan, vai trò của HÌNH ẢNH HỆ THỐNG có thể được thực hiện bởi MỘT NGÔN NGỮ PHỔ BIẾN. Các dự án nên bổ sung NGÔN NGỮ đó bằng HÌNH ẢNH HỆ THỐNG hoặc các cấu trúc quy mô lớn khác khi họ tìm thấy một cái phù hợp.


                                                                                                                                                                                                                                                          Responsibility Layers

                                                                                                                                                                                                                                                          Trong toàn bộ cuốn sách này, các đối tượng cá nhân đã được gán những tập hợp trách nhiệm hẹp có liên quan. Thiết kế dựa trên trách nhiệm cũng áp dụng cho quy mô lớn hơn.

                                                                                                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                          Khi mỗi đối tượng riêng lẻ có những trách nhiệm được làm thủ công, sẽ không có hướng dẫn nào, không có sự đồng nhất, và không có khả năng xử lý các phần lớn của miền cùng nhau. Để tạo sự nhất quán cho một mô hình lớn, việc áp đặt một số cấu trúc lên việc phân công những trách nhiệm đó là hữu ích.

                                                                                                                                                                                                                                                          Khi bạn có được sự hiểu biết sâu sắc về một lĩnh vực, những mẫu hình rộng lớn bắt đầu trở nên rõ ràng. Một số lĩnh vực có sự phân tầng tự nhiên. Một số khái niệm và hoạt động diễn ra trên nền tảng của các yếu tố khác mà thay đổi độc lập và với tốc độ khác nhau vì những lý do khác nhau. Làm thế nào chúng ta có thể tận dụng cấu trúc tự nhiên này, khiến nó trở nên rõ ràng và hữu ích hơn? Sự phân tầng này gợi ý đến việc xếp lớp, một trong những mẫu thiết kế kiến trúc thành công nhất (Buschmann et al. 1996, và nhiều tác giả khác).

                                                                                                                                                                                                                                                          Các lớp là các phân vùng của một hệ thống trong đó các thành viên của mỗi phân vùng đều nhận thức và có thể sử dụng các dịch vụ của các lớp "dưới," nhưng không nhận thức và độc lập với các lớp "trên." Khi các phụ thuộc của CÁC MODULE được vẽ ra, chúng thường được sắp xếp sao cho một MODULE có các phụ thuộc nằm dưới các phụ thuộc của nó. Theo cách này, các lớp đôi khi tự sắp xếp sao cho không có đối tượng nào ở các cấp thấp hơn phụ thuộc về mặt khái niệm vào các đối tượng ở các lớp cao hơn.

                                                                                                                                                                                                                                                          Nhưng việc phân lớp tạm thời này, mặc dù có thể làm cho việc theo dõi các phụ thuộc dễ dàng hơn—và đôi khi mang lại một số ý nghĩa trực quan—không cung cấp nhiều cái nhìn sâu sắc về mô hình hoặc hướng dẫn các quyết định mô hình hóa. Chúng ta cần điều gì đó có chủ đích hơn.

                                                                                                                                                                                                                                                          Figure 16.2. Ad hoc layering: What are these packages about?

                                                                                                                                                                                                                                                          graphics/16fig02.gif

                                                                                                                                                                                                                                                          Trong một mô hình có phân tầng tự nhiên, các lớp khái niệm có thể được định nghĩa xung quanh những trách nhiệm chính, kết hợp hai nguyên tắc mạnh mẽ của việc phân lớp và thiết kế dựa trên trách nhiệm.

                                                                                                                                                                                                                                                          Những trách nhiệm này phải rộng hơn nhiều so với những trách nhiệm thường được giao cho các đối tượng đơn lẻ, như các ví dụ sẽ minh họa ngay. Khi các MODULE và AGGREGATES được thiết kế, chúng được phân tích để giữ chúng trong phạm vi của một trong những trách nhiệm chính này. Nhóm trách nhiệm có tên này tự nó có thể nâng cao khả năng hiểu biết của một hệ thống phân mô-đun, vì các trách nhiệm của các MODULE có thể dễ dàng được giải thích hơn. Nhưng việc kết hợp trách nhiệm cấp cao với các lớp cung cấp cho chúng ta một nguyên tắc tổ chức cho một hệ thống.

                                                                                                                                                                                                                                                          Mô hình tầng phục vụ tốt nhất cho CÁC LỚP TRÁCH NHIỆM là biến thể được gọi là HỆ THỐNG LỚP THOẢI MÁI (Buschmann et al. 1996, trang 45), cho phép các thành phần của một lớp truy cập vào bất kỳ lớp dưới nào, chứ không chỉ là lớp ngay phía dưới.

                                                                                                                                                                                                                                                          Do đó:

                                                                                                                                                                                                                                                          Nhìn vào các phụ thuộc khái niệm trong mô hình của bạn và tỷ lệ cũng như nguồn thay đổi khác nhau của các phần khác nhau trong miền của bạn. Nếu bạn xác định được các lớp tự nhiên trong miền, hãy trình bày chúng dưới dạng các trách nhiệm trừu tượng rộng. Những trách nhiệm này nên kể một câu chuyện về mục đích và thiết kế cấp cao của hệ thống của bạn. Cải tổ mô hình để các trách nhiệm của từng đối tượng miền, AGGREGATE và MODULE phù hợp gọn gàng trong trách nhiệm của một lớp.

                                                                                                                                                                                                                                                          Đây là một mô tả khá trừu tượng, nhưng sẽ trở nên rõ ràng với một số ví dụ. Bộ mô phỏng giao tiếp vệ tinh có câu chuyện mở đầu chương này đã phân chia trách nhiệm của nó. Tôi đã thấy CÁC LỚP TRÁCH NHIỆM được sử dụng hiệu quả trong các lĩnh vực đa dạng như kiểm soát sản xuất và quản lý tài chính.

                                                                                                                                                                                                                                                          graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                          Ví dụ sau sẽ khám phá CÁC LỚP TRÁCH NHIỆM một cách chi tiết để giúp hiểu rõ về việc khám phá cấu trúc quy mô lớn dưới bất kỳ hình thức nào, và cách mà nó hướng dẫn và hạn chế việc mô hình hóa và thiết kế.

                                                                                                                                                                                                                                                          Example
                                                                                                                                                                                                                                                          In Depth: Layering a Shipping System

                                                                                                                                                                                                                                                          Hãy xem xét những tác động của việc áp dụng CÁC LỚP TRÁCH NHIỆM vào ứng dụng vận tải hàng hóa đã được thảo luận trong các ví dụ của các chương trước.

                                                                                                                                                                                                                                                          Khi chúng ta quay lại với câu chuyện, đội ngũ đã đạt được nhiều tiến bộ trong việc tạo ra một THIẾT KẾ DỰA TRÊN MÔ HÌNH và tinh tế hóa LĨNH VỰC CỐT LÕI. Nhưng khi thiết kế trở nên rõ ràng hơn, họ gặp khó khăn trong việc phối hợp cách tất cả các phần khớp lại với nhau. Họ đang tìm kiếm một cấu trúc quy mô lớn có thể làm nổi bật các chủ đề chính của hệ thống và giúp mọi người cùng hiểu một trang.

                                                                                                                                                                                                                                                          Đây là cái nhìn về một phần tiêu biểu của mô hình.

                                                                                                                                                                                                                                                          Figure 16.3. A basic shipping domain model for routing cargoes

                                                                                                                                                                                                                                                          graphics/16fig03.gif

                                                                                                                                                                                                                                                          Figure 16.4. Using the model to route a cargo during booking

                                                                                                                                                                                                                                                          graphics/16fig04.gif

                                                                                                                                                                                                                                                          Các thành viên trong nhóm đã ngâm mình trong lĩnh vực vận tải hàng hóa trong nhiều tháng, và họ đã nhận thấy một số phân tầng tự nhiên của các khái niệm liên quan. Thật hợp lý khi thảo luận về lịch trình vận chuyển (các chuyến đi dự kiến của tàu và xe lửa) mà không cần đề cập đến hàng hóa trên các phương tiện vận chuyển đó. Thật khó hơn để nói về việc theo dõi một lô hàng mà không đề cập đến phương tiện vận chuyển mang nó. Sự phụ thuộc khái niệm khá rõ ràng. Nhóm dễ dàng phân biệt hai lớp: "Hoạt động" và nền tảng của các hoạt động đó, mà họ gọi là "Năng lực."

                                                                                                                                                                                                                                                          "Operational" Responsibilities

                                                                                                                                                                                                                                                          Các hoạt động của công ty, trong quá khứ, hiện tại và dự kiến, được tập hợp vào lớp Vận hành. Đối tượng Vận hành rõ ràng nhất là Hàng hóa, là trọng tâm của phần lớn các hoạt động hàng ngày của công ty. Đặc điểm Tuyến đường là một phần thiết yếu của Hàng hóa, chỉ ra các yêu cầu giao hàng. Lịch trình là kế hoạch giao hàng thực tế. Cả hai đối tượng này đều là một phần của TỔ HỢP Hàng hóa, và vòng đời của chúng gắn liền với khung thời gian của một giao hàng đang hoạt động.

                                                                                                                                                                                                                                                          "Capability" Responsibilities

                                                                                                                                                                                                                                                          Lớp này phản ánh các nguồn lực mà công ty sử dụng để thực hiện hoạt động. Chân chuyển tiếp (Transit Leg) là một ví dụ điển hình. Các con tàu được lên lịch chạy và có một công suất nhất định để chở hàng hóa, điều này có thể được sử dụng hết hoặc không.

                                                                                                                                                                                                                                                          Đúng, nếu chúng ta tập trung vào việc vận hành một đội tàu, Transit Leg sẽ nằm trong lớp Vận hành. Nhưng người dùng của hệ thống này không lo lắng về vấn đề đó. (Nếu công ty tham gia cả hai hoạt động đó và muốn chúng được phối hợp, nhóm phát triển có thể phải cân nhắc một sơ đồ phân tầng khác, có thể với hai lớp khác nhau, chẳng hạn như "Hoạt động Vận tải" và "Hoạt động Hàng hóa.")

                                                                                                                                                                                                                                                          Một quyết định phức tạp hơn là nơi đặt Khách hàng. Trong một số doanh nghiệp, khách hàng có xu hướng tạm thời: họ trở nên thú vị trong khi một gói hàng được giao và sau đó hầu như bị quên lãng cho đến lần tiếp theo. Chất lượng này sẽ khiến khách hàng chỉ là một mối quan tâm về hoạt động đối với dịch vụ giao hàng bưu kiện nhắm đến người tiêu dùng cá nhân. Nhưng công ty vận chuyển giả định của chúng ta có xu hướng phát triển mối quan hệ lâu dài với khách hàng, và phần lớn công việc đến từ việc khách hàng quay lại. Với những ý định này của người dùng doanh nghiệp, Khách hàng thuộc về tầng tiềm năng. Như bạn có thể thấy, đây không phải là một quyết định kỹ thuật. Đó là một nỗ lực để nắm bắt và truyền đạt kiến thức về lĩnh vực này.

                                                                                                                                                                                                                                                          Bởi vì mối quan hệ giữa Cargo và Khách hàng chỉ có thể được truy cập theo một hướng, REPOSITORY Cargo sẽ cần một truy vấn để tìm tất cả các Cargo cho một Khách hàng cụ thể. Đã có lý do tốt để thiết kế theo cách đó, nhưng với yêu cầu về cấu trúc quy mô lớn, giờ đây điều đó trở thành một yêu cầu.

                                                                                                                                                                                                                                                          Figure 16.5. A query replaces a bidirectional association that violates the layering.

                                                                                                                                                                                                                                                          graphics/16fig05.gif

                                                                                                                                                                                                                                                          Figure 16.6. A first-pass layered model

                                                                                                                                                                                                                                                          graphics/16fig06.gif

                                                                                                                                                                                                                                                          Trong khi sự phân biệt giữa Hoạt động và Khả năng làm rõ bức tranh, đơn hàng vẫn tiếp tục phát triển. Sau vài tuần thử nghiệm, nhóm tập trung vào một sự phân biệt khác. Phần lớn, cả hai lớp ban đầu đều tập trung vào các tình huống hoặc kế hoạch như chúng đang có. Nhưng Router (và nhiều yếu tố khác không được đưa vào ví dụ này) không phải là một phần của thực tế hay kế hoạch vận hành hiện tại. Nó giúp đưa ra quyết định về việc thay đổi những kế hoạch đó. Nhóm định nghĩa một lớp mới chịu trách nhiệm về "Hỗ trợ Quyết định."

                                                                                                                                                                                                                                                          "Decision Support" Responsibilities

                                                                                                                                                                                                                                                          Lớp này của phần mềm cung cấp cho người dùng các công cụ để lập kế hoạch và ra quyết định, và nó có thể tự động hóa một số quyết định (chẳng hạn như tự động định tuyến lại hàng hóa khi lịch trình vận chuyển thay đổi).

                                                                                                                                                                                                                                                          Bộ định tuyến là một DỊCH VỤ giúp đại lý đặt chỗ chọn cách tốt nhất để gửi hàng hóa. Điều này đặt bộ định tuyến vào vị trí hỗ trợ quyết định.

                                                                                                                                                                                                                                                          Các tham chiếu trong mô hình này đều nhất quán với ba lớp ngoại trừ một yếu tố không đồng nhất: thuộc tính "được ưu tiên" trên Chân vận chuyển. Thuộc tính này tồn tại vì công ty thích sử dụng tàu của chính mình khi có thể, hoặc tàu của một số công ty khác mà công ty có hợp đồng thuận lợi. Thuộc tính "được ưu tiên" được sử dụng để định hướng Router theo những phương tiện vận chuyển được ưu ái này. Thuộc tính này không liên quan gì đến "Khả năng." Đây là một chính sách chỉ đạo việc ra quyết định. Để sử dụng CÁC LỚP TRÁCH NHIỆM mới, mô hình sẽ phải được tái cấu trúc.

                                                                                                                                                                                                                                                          Figure 16.7. Refactoring the model to conform to the new layering structure

                                                                                                                                                                                                                                                          graphics/16fig07.gif

                                                                                                                                                                                                                                                          Việc phân tách này làm cho Chính sách Thiên lệch Tuyến đường trở nên rõ ràng hơn trong khi làm cho Chặng vận chuyển trở nên tập trung hơn vào khái niệm cơ bản của khả năng vận chuyển. Một cấu trúc quy mô lớn dựa trên sự hiểu biết sâu sắc về lĩnh vực thường sẽ thúc đẩy mô hình đi theo những hướng làm sáng tỏ nghĩa của nó.

                                                                                                                                                                                                                                                          Mô hình mới này giờ đây phù hợp mượt mà vào cấu trúc quy mô lớn.

                                                                                                                                                                                                                                                          Figure 16.8. The restructured and refactored model

                                                                                                                                                                                                                                                          graphics/16fig08.gif

                                                                                                                                                                                                                                                          Một nhà phát triển quen thuộc với các lớp đã chọn có thể dễ dàng nhận biết các vai trò và phụ thuộc của các phần. Giá trị của cấu trúc quy mô lớn tăng lên khi sự phức tạp gia tăng.

                                                                                                                                                                                                                                                          Lưu ý rằng mặc dù tôi đang minh họa ví dụ này bằng một sơ đồ UML đã được điều chỉnh, bản vẽ này chỉ là một cách để truyền đạt các lớp. UML không bao gồm ký hiệu này, vì vậy đây là thông tin bổ sung được đưa ra vì lợi ích của người đọc. Nếu mã là tài liệu thiết kế cuối cùng cho dự án của bạn, thì việc có một công cụ để duyệt các lớp theo lớp hoặc ít nhất là để báo cáo chúng theo lớp sẽ rất hữu ích.

                                                                                                                                                                                                                                                          How Does This Structure Affect Ongoing Design?

                                                                                                                                                                                                                                                          Khi một cấu trúc quy mô lớn đã được áp dụng, các quyết định mô hình hóa và thiết kế tiếp theo phải xem xét điều này. Để minh họa, giả sử chúng ta phải thêm một tính năng mới vào thiết kế đã được phân lớp này. Các chuyên gia trong lĩnh vực vừa cho chúng ta biết rằng có những hạn chế về cách thức vận chuyển cho một số loại vật liệu nguy hiểm. Một số vật liệu nhất định có thể không được phép trên một số phương tiện vận chuyển hoặc trong một số cảng. Chúng ta phải làm cho Bộ định tuyến tuân thủ các quy định này.

                                                                                                                                                                                                                                                          Có nhiều cách tiếp cận khác nhau. Trong bối cảnh không có cấu trúc quy mô lớn, một thiết kế hấp dẫn là giao trách nhiệm tích hợp các quy tắc định tuyến cho đối tượng sở hữu Thông số Lộ trình và mã Vật liệu Nguy hiểm (HazMat) — cụ thể là Hàng hóa.

                                                                                                                                                                                                                                                          Figure 16.9. A possible design for routing hazardous cargo

                                                                                                                                                                                                                                                          graphics/16fig09.gif

                                                                                                                                                                                                                                                          Figure 16.10.

                                                                                                                                                                                                                                                          graphics/16fig10.gif

                                                                                                                                                                                                                                                          Vấn đề là thiết kế này không phù hợp với cấu trúc quy mô lớn. Dịch vụ Chính sách Lộ trình Đồ hoá Hóa chất không phải là vấn đề; nó phù hợp một cách gọn gàng vào trách nhiệm của lớp Hỗ trợ Quyết định. Vấn đề là sự phụ thuộc của Cargo (một đối tượng Vận hành) vào Dịch vụ Chính sách Lộ trình Đồ hoá Hóa chất (một đối tượng Hỗ trợ Quyết định). Chừng nào dự án còn cam kết với những lớp này, mô hình này không thể được chấp nhận. Nó sẽ gây nhầm lẫn cho các nhà phát triển mà kỳ vọng cấu trúc sẽ được tuân theo.

                                                                                                                                                                                                                                                          Luôn luôn có nhiều khả năng thiết kế, và chúng ta chỉ cần chọn một phương án khác - một phương án tuân theo quy tắc của cấu trúc quy mô lớn. Dịch vụ Chính sách Đường dẫn HazMat thì tốt, nhưng chúng ta cần chuyển giao trách nhiệm cho việc sử dụng chính sách. Hãy thử giao cho Bộ định tuyến trách nhiệm thu thập các chính sách phù hợp trước khi tìm kiếm một lộ trình. Điều này có nghĩa là thay đổi giao diện Bộ định tuyến để bao gồm các đối tượng mà các chính sách có thể phụ thuộc vào. Đây là một thiết kế khả thi.

                                                                                                                                                                                                                                                          Figure 16.11. A design consistent with layering

                                                                                                                                                                                                                                                          graphics/16fig11.gif

                                                                                                                                                                                                                                                          Một tương tác điển hình được hiển thị trong Hình 16.12 ở trang tiếp theo.

                                                                                                                                                                                                                                                          Figure 16.12.

                                                                                                                                                                                                                                                          graphics/16fig12.gif

                                                                                                                                                                                                                                                          Bây giờ, điều này không nhất thiết là một thiết kế tốt hơn thiết kế kia. Cả hai đều có những ưu điểm và nhược điểm. Nhưng nếu mọi người trong một dự án đưa ra quyết định theo cách nhất quán, thiết kế tổng thể sẽ dễ hiểu hơn nhiều, và điều đó đáng giá một số khoản đánh đổi khi quyết định về những lựa chọn thiết kế chi tiết.

                                                                                                                                                                                                                                                          Nếu cấu trúc buộc phải đưa ra nhiều lựa chọn thiết kế khó xử, thì theo nguyên tắc TRẬT TỰ PHÁT TRIỂN, nó nên được đánh giá và có thể được điều chỉnh hoặc thậm chí loại bỏ.

                                                                                                                                                                                                                                                          Choosing Appropriate Layers

                                                                                                                                                                                                                                                          Việc tìm kiếm các LỚP TRÁCH NHIỆM tốt, hoặc bất kỳ cấu trúc quy mô lớn nào, là vấn đề hiểu rõ miền vấn đề và thử nghiệm. Nếu bạn cho phép SẮP XẾP TIẾN HÓA, điểm khởi đầu ban đầu không quan trọng, mặc dù một lựa chọn kém sẽ tăng thêm công việc. Cấu trúc có thể tiến hóa thành một thứ gì đó không thể nhận ra. Vì vậy, các hướng dẫn được đề xuất ở đây nên được áp dụng khi xem xét các biến đổi của cấu trúc cũng như khi chọn từ đầu.

                                                                                                                                                                                                                                                          Khi các lớp được chuyển đổi, gộp lại, tách ra và định nghĩa lại, đây là một số đặc điểm hữu ích cần tìm kiếm và bảo tồn.

                                                                                                                                                                                                                                                          • Kể chuyện. Các lớp nên truyền đạt những thực tế cơ bản hoặc ưu tiên của lĩnh vực. Việc chọn một cấu trúc quy mô lớn ít hơn là một quyết định kỹ thuật mà hơn là một quyết định mô hình hóa kinh doanh. Các lớp nên làm nổi bật các ưu tiên của doanh nghiệp.

                                                                                                                                                                                                                                                          • Sự phụ thuộc khái niệm. Các khái niệm ở các lớp "trên" nên có ý nghĩa trong bối cảnh của các lớp "dưới", trong khi các khái niệm ở lớp dưới nên có thể mang ý nghĩa độc lập.

                                                                                                                                                                                                                                                          • GÓC KHÁI NIỆM. Nếu các đối tượng của các lớp khác nhau nên có tỷ lệ thay đổi khác nhau hoặc nguồn thay đổi khác nhau, lớp đó sẽ tiếp nhận sự biến dạng giữa chúng.

                                                                                                                                                                                                                                                          Không phải lúc nào cũng cần bắt đầu từ đầu trong việc xác định các lớp cho mỗi mô hình mới. Một số lớp xuất hiện trong cả những họ miền có liên quan.

                                                                                                                                                                                                                                                          Ví dụ, trong các doanh nghiệp dựa trên việc khai thác tài sản cố định lớn, chẳng hạn như nhà máy hoặc tàu chở hàng, phần mềm logistics thường có thể được tổ chức thành một lớp "Tiềm năng" (một tên khác cho lớp "Khả năng" trong ví dụ) và một lớp "Hoạt động".

                                                                                                                                                                                                                                                          • Tiềm năng. Có thể làm gì? Đừng bận tâm đến những gì chúng ta đang dự định làm. Chúng ta có thể làm gì? Tài nguyên của tổ chức, bao gồm cả con người, và cách mà những tài nguyên đó được tổ chức là cốt lõi của lớp Tiềm năng. Các hợp đồng với nhà cung cấp cũng xác định tiềm năng. Lớp này có thể được công nhận trong hầu hết các lĩnh vực kinh doanh, nhưng nó là một phần nổi bật trong câu chuyện của những doanh nghiệp, chẳng hạn như vận tải và sản xuất, mà có các khoản đầu tư vốn cố định tương đối lớn giúp cho doanh nghiệp hoạt động. Tiềm năng bao gồm cả tài sản tạm thời, nhưng một doanh nghiệp chủ yếu được điều hành bởi các tài sản tạm thời có thể chọn các lớp nhấn mạnh vào điều này, như đã thảo luận sau. (Lớp này đã được gọi là "Năng lực" trong ví dụ.)

                                                                                                                                                                                                                                                          • Hoạt động. Điều gì đang được thực hiện? Chúng ta đã quản lý được những tiềm năng đó như thế nào? Giống như lớp Tiềm năng, lớp này nên phản ánh thực tế của tình huống, thay vì những gì chúng ta mong muốn. Trong lớp này, chúng ta đang cố gắng nhìn nhận nỗ lực và hoạt động của chính mình: Những gì chúng ta đang bán, thay vì những gì giúp chúng ta bán. Rất điển hình cho các đối tượng Hoạt động tham chiếu hoặc thậm chí được cấu thành từ các đối tượng Tiềm năng, nhưng một đối tượng Tiềm năng không nên tham chiếu đến lớp Hoạt động.

                                                                                                                                                                                                                                                          Trong nhiều hệ thống hiện có, có lẽ hầu hết, trong các lĩnh vực loại này, hai lớp này bao gồm mọi thứ (mặc dù có thể có một sự phân chia hoàn toàn khác và sâu sắc hơn). Chúng theo dõi tình hình hiện tại và các kế hoạch hoạt động đang diễn ra và phát hành báo cáo hoặc tài liệu về nó. Nhưng việc theo dõi không phải lúc nào cũng đủ. Khi các dự án tìm cách hướng dẫn hoặc hỗ trợ người dùng, hoặc tự động hóa việc ra quyết định, sẽ có một tập hợp trách nhiệm bổ sung có thể được tổ chức thành một lớp khác, nằm trên lớp Hoạt động.

                                                                                                                                                                                                                                                          • Hỗ trợ quyết định. Hành động nào nên được thực hiện hoặc chính sách nào nên được thiết lập? Lớp này dành cho phân tích và ra quyết định. Nó dựa vào thông tin từ các lớp bên dưới, chẳng hạn như Tiềm năng hoặc Vận hành. Phần mềm Hỗ trợ quyết định có thể sử dụng thông tin lịch sử để chủ động tìm kiếm cơ hội cho các hoạt động hiện tại và tương lai.

                                                                                                                                                                                                                                                          Hệ thống hỗ trợ quyết định có những phụ thuộc khái niệm vào các lớp khác như Hoạt động hoặc Tiềm năng vì quyết định không được đưa ra trong chân không. Nhiều dự án triển khai Hệ thống Hỗ trợ Quyết định bằng công nghệ kho dữ liệu. Lớp này trở thành một BỐ CỤC RẠNG BUỘC rõ ràng, với mối quan hệ KHÁCH HÀNG/CUNG CẤP với phần mềm Hoạt động. Trong các dự án khác, nó được tích hợp sâu hơn, như trong ví dụ mở rộng trước đó. Và một trong những lợi thế nội tại của các lớp là các lớp thấp hơn có thể tồn tại mà không cần đến các lớp cao hơn. Điều này có thể tạo điều kiện cho việc giới thiệu theo từng giai đoạn hoặc nâng cấp ở cấp cao hơn được xây dựng trên các hệ thống vận hành cũ.

                                                                                                                                                                                                                                                          Một trường hợp khác là phần mềm thực thi các quy tắc kinh doanh phức tạp hoặc yêu cầu pháp lý, điều này có thể tạo thành một LỚP TRÁCH NHIỆM.

                                                                                                                                                                                                                                                          • Chính sách. Các quy tắc và mục tiêu là gì? Quy tắc và mục tiêu thường chủ yếu là thụ động, nhưng giới hạn hành vi ở các lớp khác. Thiết kế các tương tác này có thể tinh tế. Đôi khi một Chính sách được truyền vào như một tham số cho một phương thức cấp thấp hơn. Đôi khi mẫu STRATEGY được áp dụng. Chính sách hoạt động tốt kết hợp với một lớp Hỗ trợ Quyết định, cung cấp phương tiện để tìm kiếm các mục tiêu được thiết lập bởi Chính sách, bị hạn chế bởi các quy tắc được thiết lập bởi Chính sách.

                                                                                                                                                                                                                                                          Các lớp chính sách có thể được viết bằng cùng một ngôn ngữ như các lớp khác, nhưng đôi khi chúng được triển khai bằng các công cụ quản lý quy tắc. Điều này không nhất thiết khiến chúng nằm trong một BOUNDARY CONTEXT riêng biệt. Thực tế, sự khó khăn trong việc phối hợp các công nghệ triển khai khác nhau có thể được giảm bớt bằng cách cẩn thận sử dụng cùng một mô hình cho cả hai. Khi các quy tắc được viết dựa trên một mô hình khác với các đối tượng mà chúng áp dụng, hoặc là độ phức tạp tăng cao hoặc là các đối tượng bị giảm bớt để giữ cho mọi thứ dễ quản lý.

                                                                                                                                                                                                                                                          Figure 16.13. Conceptual dependencies and shearing points in a factory automation system

                                                                                                                                                                                                                                                          graphics/16fig13.gif

                                                                                                                                                                                                                                                          Nhiều doanh nghiệp không dựa vào khả năng của mình trên thiết bị và máy móc. Trong các dịch vụ tài chính hoặc bảo hiểm, để nêu rõ hai ví dụ, tiềm năng phụ thuộc phần lớn vào hoạt động hiện tại. Khả năng của một công ty bảo hiểm trong việc nhận một rủi ro mới thông qua việc bảo hiểm một thỏa thuận chính sách mới dựa vào sự đa dạng hóa của doanh nghiệp hiện tại. Lớp Tiềm năng có thể sẽ hợp nhất với Hoạt động, và một lớp khác sẽ phát triển.

                                                                                                                                                                                                                                                          Một lĩnh vực thường được chú ý trong những tình huống này là các cam kết đã được thực hiện với khách hàng.

                                                                                                                                                                                                                                                          • Cam kết. Chúng ta đã hứa hẹn điều gì? Lớp này có tính chất của Chính sách, vì nó nêu ra các mục tiêu hướng dẫn các hoạt động trong tương lai, nhưng nó cũng có tính chất của Hoạt động, vì các cam kết phát sinh và thay đổi như một phần của các hoạt động kinh doanh đang diễn ra.

                                                                                                                                                                                                                                                          Figure 16.14. Conceptual dependencies and shearing points in an investment banking system

                                                                                                                                                                                                                                                          graphics/16fig14.gif

                                                                                                                                                                                                                                                          Các lớp Tiềm năng và Cam kết không loại trừ lẫn nhau. Một lĩnh vực mà cả hai đều nổi bật, chẳng hạn như một công ty vận tải với nhiều dịch vụ vận chuyển tùy chỉnh, có thể sử dụng cả hai. Các lớp khác cụ thể cho những lĩnh vực đó cũng có thể hữu ích. Hãy thay đổi mọi thứ. Thử nghiệm. Nhưng tốt nhất là giữ cho hệ thống lớp đơn giản; đi quá bốn hoặc có thể năm lớp thì trở nên cồng kềnh. Có quá nhiều lớp không hiệu quả trong việc kể câu chuyện, và những vấn đề phức tạp mà cấu trúc quy mô lớn được mong muốn giải quyết sẽ trở lại dưới hình thức mới. Cấu trúc quy mô lớn phải được chắt lọc một cách quyết liệt.

                                                                                                                                                                                                                                                          Mặc dù năm lớp này có thể áp dụng cho nhiều hệ thống doanh nghiệp, nhưng chúng không bao quát được các trách nhiệm nổi bật của tất cả các lĩnh vực. Trong những trường hợp khác, việc cố gắng ép thiết kế vào hình dạng này có thể phản tác dụng, nhưng có thể có một bộ LỚP TRÁCH NHIỆM tự nhiên phù hợp. Đối với một lĩnh vực hoàn toàn không liên quan đến những gì chúng ta đã thảo luận, các lớp này có thể phải hoàn toàn mới mẻ. Cuối cùng, bạn cần dùng trực giác của mình, bắt đầu từ một nơi nào đó và để ĐẶT HÀNG TIẾN TRIỂN.


                                                                                                                                                                                                                                                            Knowledge Level

                                                                                                                                                                                                                                                            graphics/16inf02.gif

                                                                                                                                                                                                                                                            "MỨC ĐỘ KIẾN THỨC là một nhóm đối tượng mô tả cách mà một nhóm đối tượng khác nên hành xử."

                                                                                                                                                                                                                                                            CẤP ĐỘ KIẾN THỨC giúp giải quyết các vấn đề khi chúng ta cần để một phần của mô hình trở nên linh hoạt trong tay người dùng nhưng vẫn bị ràng buộc bởi một tập quy tắc rộng hơn. Nó đáp ứng các yêu cầu cho phần mềm có hành vi cấu hình được, trong đó các vai trò và mối quan hệ giữa CÁC THỰC THỂ phải được thay đổi trong quá trình cài đặt hoặc thậm chí trong thời gian chạy.

                                                                                                                                                                                                                                                            Trong các Mẫu Phân Tích (Fowler 1996, trang 24–27), mẫu xuất hiện từ một cuộc thảo luận về việc lập mô hình trách nhiệm trong các tổ chức, và sau đó được áp dụng cho các quy tắc đăng ký trong kế toán. Mặc dù mẫu xuất hiện trong một số chương, nhưng nó không có một chương riêng vì nó khác với hầu hết các mẫu trong sách. Thay vì lập mô hình một miền, như các mẫu phân tích khác, CẤP KIẾN THỨC cấu trúc một mô hình.

                                                                                                                                                                                                                                                            Để thấy vấn đề một cách cụ thể, hãy xem xét các mô hình của "trách nhiệm". Các tổ chức được tạo thành từ con người và các tổ chức nhỏ hơn, và xác định các vai trò mà họ đóng và các mối quan hệ giữa họ. Các quy tắc governing các vai trò và quan hệ đó rất khác nhau cho các tổ chức khác nhau. Tại một công ty, một "phòng ban" có thể do một "Giám đốc" dẫn dắt, người báo cáo cho một "Phó Giám đốc". Ở một công ty khác, một "mô-đun" được dẫn dắt bởi một "Quản lý" người báo cáo cho một "Quản lý cấp cao". Rồi còn có các tổ chức "ma trận", trong đó mỗi người báo cáo cho các quản lý khác nhau cho các mục đích khác nhau.

                                                                                                                                                                                                                                                            Một ứng dụng điển hình sẽ đưa ra một số giả định. Khi những giả định đó không phù hợp, người dùng bắt đầu sử dụng các trường nhập dữ liệu theo cách khác với dự định. Bất kỳ hành vi nào của ứng dụng đều bị sai lệch, vì ngữ nghĩa đã bị người dùng thay đổi. Người dùng sẽ phát triển các cách làm việc thay thế cho hành vi đó, hoặc sẽ không sử dụng được các tính năng cao cấp hơn của ứng dụng. Họ buộc phải học cách ánh xạ phức tạp giữa những gì họ làm trong công việc và cách phần mềm hoạt động. Họ sẽ không bao giờ được phục vụ tốt.

                                                                                                                                                                                                                                                            Khi hệ thống cần phải được thay đổi hoặc thay thế, các nhà phát triển sẽ phát hiện ra (sớm hay muộn) rằng ý nghĩa của các tính năng không phải lúc nào cũng như chúng tưởng. Chúng có thể mang ý nghĩa rất khác nhau trong các cộng đồng người dùng khác nhau hoặc trong các tình huống khác nhau. Việc thay đổi bất cứ điều gì mà không làm hỏng những cách sử dụng chồng lấn này sẽ rất khó khăn. Việc di chuyển dữ liệu đến một hệ thống được tùy chỉnh hơn sẽ yêu cầu hiểu và lập trình cho tất cả những bí quyết đó.

                                                                                                                                                                                                                                                            Example
                                                                                                                                                                                                                                                            Employee Payroll and Pension, Part 1

                                                                                                                                                                                                                                                            Phòng nhân sự của một công ty vừa và nhỏ có một chương trình đơn giản để tính lương và đóng góp hưu trí.

                                                                                                                                                                                                                                                            Figure 16.15. The old model, overconstrained for new requirements

                                                                                                                                                                                                                                                            graphics/16fig15.gif

                                                                                                                                                                                                                                                            Figure 16.16. Some employees represented using the old model

                                                                                                                                                                                                                                                            graphics/16fig16.gif

                                                                                                                                                                                                                                                            Nhưng bây giờ, ban quản lý đã quyết định rằng các nhân viên hành chính văn phòng nên tham gia vào kế hoạch hưu trí "định mức". Vấn đề là các nhân viên hành chính văn phòng được trả lương theo giờ, và mô hình này không cho phép kết hợp. Mô hình sẽ phải thay đổi.

                                                                                                                                                                                                                                                            Đề xuất mô hình tiếp theo rất đơn giản: chỉ cần loại bỏ các ràng buộc.

                                                                                                                                                                                                                                                            Figure 16.17. The proposed model, now underconstrained

                                                                                                                                                                                                                                                            graphics/16fig17.gif

                                                                                                                                                                                                                                                            Figure 16.18. Employees can be associated with the wrong plan.

                                                                                                                                                                                                                                                            graphics/16fig18.gif

                                                                                                                                                                                                                                                            Mô hình này cho phép mỗi nhân viên được liên kết với một trong hai loại kế hoạch hưu trí, vì vậy mỗi quản trị viên văn phòng có thể được thay đổi. Mô hình này bị ban giám đốc từ chối vì nó không phản ánh chính sách của công ty. Một số quản trị viên có thể được thay đổi và những người khác thì không. Hoặc người dọn vệ sinh có thể được thay đổi. Ban giám đốc muốn một mô hình tuân thủ chính sách:

                                                                                                                                                                                                                                                            Cán bộ văn phòng là nhân viên theo giờ với kế hoạch hưu trí theo lợi ích xác định.

                                                                                                                                                                                                                                                            Chính sách này gợi ý rằng trường "chức danh công việc" hiện nay đại diện cho một khái niệm quan trọng trong lĩnh vực. Các nhà phát triển có thể tái cấu trúc để làm cho khái niệm đó trở nên rõ ràng hơn dưới dạng “Loại nhân viên.”

                                                                                                                                                                                                                                                            Figure 16.19. The Type object allows requirements to be met.

                                                                                                                                                                                                                                                            graphics/16fig19.gif

                                                                                                                                                                                                                                                            Figure 16.20. Each Employee Type is assigned a Retirement Plan.

                                                                                                                                                                                                                                                            graphics/16fig20.gif

                                                                                                                                                                                                                                                            Các yêu cầu có thể được diễn đạt bằng NGÔN NGỮ PHỔ BIẾN như sau:

                                                                                                                                                                                                                                                            Một loại nhân viên được gán cho một trong hai Kế hoạch Hưu trí hoặc bảng lương.

                                                                                                                                                                                                                                                            Nhân viên bị ràng buộc bởi loại hình nhân viên.

                                                                                                                                                                                                                                                            Quyền truy cập để chỉnh sửa đối tượng Loại Nhân viên sẽ bị hạn chế cho một "siêu người dùng," người sẽ chỉ thực hiện thay đổi khi chính sách công ty thay đổi. Một người dùng bình thường trong bộ phận nhân sự có thể thay đổi Nhân viên hoặc chỉ định họ vào một Loại Nhân viên khác.

                                                                                                                                                                                                                                                            Mô hình này đáp ứng các yêu cầu. Các nhà phát triển cảm nhận được một hoặc hai khái niệm ngầm, nhưng hiện tại chỉ là một cảm giác lo lắng. Họ không có ý tưởng cụ thể nào để theo đuổi, vì vậy họ quyết định ngừng lại trong ngày hôm nay.

                                                                                                                                                                                                                                                            Một mô hình tĩnh có thể gây ra vấn đề. Nhưng các vấn đề có thể cũng tồi tệ như với một hệ thống hoàn toàn linh hoạt cho phép bất kỳ mối quan hệ nào có thể được trình bày. Một hệ thống như vậy sẽ bất tiện khi sử dụng và không cho phép các quy tắc của tổ chức được thực thi.

                                                                                                                                                                                                                                                            Việc tùy chỉnh phần mềm hoàn toàn cho từng tổ chức là không thực tế vì, ngay cả khi mỗi tổ chức có thể trả tiền cho phần mềm tùy chỉnh, thì cấu trúc tổ chức cũng có khả năng thay đổi thường xuyên.

                                                                                                                                                                                                                                                            Vì vậy, phần mềm như vậy phải cung cấp các tùy chọn để cho phép người dùng cấu hình nó phản ánh cấu trúc hiện tại của tổ chức. Vấn đề là việc thêm các tùy chọn như vậy vào các đối tượng mô hình làm cho chúng trở nên cồng kềnh. Càng thêm nhiều tính linh hoạt, mọi thứ càng trở nên phức tạp hơn.

                                                                                                                                                                                                                                                            Trong một ứng dụng mà các vai trò và mối quan hệ giữa CÁC THỰC THỂ khác nhau trong các tình huống khác nhau, độ phức tạp có thể bùng nổ. Cả mô hình tổng quát hoàn toàn không và các mô hình tùy chỉnh cao đều không đáp ứng được nhu cầu của người dùng. Các đối tượng cuối cùng sẽ có các tham chiếu đến các loại khác để bao phủ nhiều trường hợp, hoặc có các thuộc tính được sử dụng theo những cách khác nhau trong các tình huống khác nhau. Các lớp có cùng dữ liệu và hành vi có thể nhân lên chỉ để đáp ứng các quy tắc lắp ráp khác nhau.

                                                                                                                                                                                                                                                            Nằm gọn trong mô hình của chúng tôi là một mô hình khác về mô hình của chúng tôi. Một CẤP ĐỘ KIẾN THỨC tách biệt khía cạnh tự định nghĩa đó của mô hình và làm cho các ràng buộc của nó trở nên rõ ràng.

                                                                                                                                                                                                                                                            MỨC ĐỘ KIẾN THỨC là một ứng dụng cho lớp miền của mẫu REFLECTION, được sử dụng trong nhiều kiến trúc phần mềm và cơ sở hạ tầng kỹ thuật, và được mô tả tốt trong Buschmann et al. 1996. REFLECTION điều chỉnh các nhu cầu thay đổi bằng cách làm cho phần mềm "tự nhận thức," và làm cho các khía cạnh được chọn của cấu trúc và hành vi của nó có thể truy cập để thích ứng và thay đổi. Điều này được thực hiện bằng cách chia phần mềm thành một "mức cơ sở," chịu trách nhiệm vận hành cho ứng dụng, và một "mức meta," đại diện cho kiến thức về cấu trúc và hành vi của phần mềm.

                                                                                                                                                                                                                                                            Đáng chú ý, mô hình này không được gọi là "tầng" tri thức. Mặc dù nó giống như việc xếp chồng, NHÌN NHẬN liên quan đến các phụ thuộc lẫn nhau chạy theo cả hai hướng.

                                                                                                                                                                                                                                                            Java có một số phản chiếu tích hợp tối thiểu dưới dạng các giao thức để truy vấn một lớp về các phương thức của nó và vân vân. Các cơ chế như vậy cho phép một chương trình đặt câu hỏi về thiết kế của chính nó. CORBA có các giao thức phản chiếu tương tự nhưng phong phú hơn chút. Một số công nghệ lưu trữ mở rộng độ phong phú của mô tả tự nó để hỗ trợ việc ánh xạ tự động một phần giữa các bảng cơ sở dữ liệu và các đối tượng. Còn nhiều ví dụ kỹ thuật khác. Mẫu thiết kế này cũng có thể được áp dụng trong lớp miền.

                                                                                                                                                                                                                                                            CẤP ĐỘ KIẾN THỨC cung cấp hai sự phân biệt hữu ích. Đầu tiên, nó tập trung vào miền ứng dụng, trái ngược với các ứng dụng quen thuộc của PHẢN XẠ. Thứ hai, nó không cố gắng đạt được tính tổng quát hoàn toàn. Giống như một ĐẶC TẢ có thể hữu ích hơn một phép toán tổng quát, một bộ ràng buộc rất chuyên biệt trên một tập hợp các đối tượng và mối quan hệ của chúng có thể hữu ích hơn một khung tổng quát. CẤP ĐỘ KIẾN THỨC đơn giản hơn và có thể truyền đạt ý định cụ thể của người thiết kế.

                                                                                                                                                                                                                                                            Thuật ngữ Fowler

                                                                                                                                                                                                                                                            Thuật ngữ POSA

                                                                                                                                                                                                                                                            Trình độ kiến thức

                                                                                                                                                                                                                                                            Cấp độ Meta

                                                                                                                                                                                                                                                            Cấp độ hoạt động

                                                                                                                                                                                                                                                            Cấp độ cơ bản

                                                                                                                                                                                                                                                            POSA là viết tắt của Kiến trúc Phần mềm Hướng đến Mẫu, do Buschmann và các cộng sự thực hiện vào năm 1996.

                                                                                                                                                                                                                                                            So sánh thuật ngữ CẤP ĐỘ KIẾN THỨC và SỰ PHẢN ÁNH

                                                                                                                                                                                                                                                            Để làm rõ, các công cụ phản chiếu của ngôn ngữ lập trình không được sử dụng để triển khai CẤP KIẾN THỨC của một mô hình miền. Những đối tượng meta này mô tả cấu trúc và hành vi của các đối tượng ngôn ngữ tự nó. Thay vào đó, CẤP KIẾN THỨC phải được xây dựng từ các đối tượng thông thường.

                                                                                                                                                                                                                                                            CẤP ĐỘ KIẾN THỨC cung cấp hai sự phân biệt hữu ích. Đầu tiên, nó tập trung vào lĩnh vực ứng dụng, trái ngược với những cách sử dụng quen thuộc của PHẢN XẠ. Thứ hai, nó không cố gắng đạt được tính tổng quát đầy đủ. Cũng như một ĐẶC TẢ có thể hữu ích hơn một định đề tổng quát, một tập hợp ràng buộc rất chuyên biệt về một tập hợp các đối tượng và mối quan hệ của chúng có thể hữu ích hơn một khuôn khổ tổng quát. CẤP ĐỘ KIẾN THỨC đơn giản hơn và có thể truyền đạt ý định cụ thể của nhà thiết kế.

                                                                                                                                                                                                                                                            Vì vậy:

                                                                                                                                                                                                                                                            Tạo một tập hợp các đối tượng khác biệt có thể được sử dụng để mô tả và hạn chế cấu trúc cũng như hành vi của mô hình cơ bản. Giữ các mối quan tâm này tách biệt thành hai "mức độ", một mức rất cụ thể, mức còn lại phản ánh các quy tắc và kiến thức mà người dùng hoặc siêu người dùng có thể tùy chỉnh.

                                                                                                                                                                                                                                                            Như tất cả các ý tưởng mạnh mẽ, CẢM NHẬN và CÁC CẤP ĐỘ TRI THỨC có thể gây nghiện. Mô hình này nên được sử dụng một cách tiết kiệm. Nó có thể giải quyết sự phức tạp bằng cách giải phóng các đối tượng hoạt động khỏi nhu cầu phải là những người làm mọi thứ, nhưng sự gián tiếp mà nó đưa vào cũng tạo ra một phần nào đó sự mơ hồ trở lại. Nếu CẤP ĐỘ TRI THỨC trở nên phức tạp, hành vi của hệ thống sẽ trở nên khó hiểu đối với cả nhà phát triển và người dùng. Những người dùng (hoặc siêu người dùng) cấu hình nó sẽ cần có kỹ năng của một lập trình viên - và một lập trình viên ở cấp độ meta nữa. Nếu họ mắc lỗi, ứng dụng sẽ hoạt động không chính xác.

                                                                                                                                                                                                                                                            Ngoài ra, các vấn đề cơ bản của việc di chuyển dữ liệu không hoàn toàn biến mất. Khi một cấu trúc ở CẤP KIẾN THỨC thay đổi, các đối tượng ở cấp độ hoạt động hiện có phải được xử lý. Có thể có khả năng cho cái cũ và cái mới đồng tồn tại, nhưng bằng cách này hay cách khác, cần phải phân tích cẩn thận.

                                                                                                                                                                                                                                                            Tất cả những vấn đề này đặt một gánh nặng lớn lên nhà thiết kế của MỨC ĐỘ KIẾN THỨC. Thiết kế phải đủ mạnh mẽ để xử lý không chỉ những kịch bản được trình bày trong quá trình phát triển, mà còn cả bất kỳ kịch bản nào mà người dùng có thể cấu hình phần mềm trong tương lai. Nếu được áp dụng một cách hợp lý, tại những điểm mà việc tùy chỉnh là quan trọng và nếu không sẽ làm biến dạng thiết kế, MỨC ĐỘ KIẾN THỨC có thể giải quyết những vấn đề rất khó khăn để xử lý theo cách khác.

                                                                                                                                                                                                                                                            Example
                                                                                                                                                                                                                                                            Employee Payroll and Pension, Part 2: KNOWLEDGE LEVEL

                                                                                                                                                                                                                                                            Các thành viên trong đội của chúng tôi đã quay trở lại, và sau một giấc ngủ một đêm, một trong số họ đã bắt đầu tìm hiểu một trong những điểm khó xử. Tại sao một số đối tượng bị hạn chế trong khi những đối tượng khác thì có thể chỉnh sửa tự do? Cụm các đối tượng bị hạn chế đã gợi nhớ cho anh ấy về mẫu CẤP ĐỘ KIẾN THỨC, và anh ấy quyết định thử nghiệm nó như một cách để xem mô hình. Anh ấy nhận thấy rằng mô hình hiện có đã có thể được xem theo cách này.

                                                                                                                                                                                                                                                            Figure 16.21. Recognizing the KNOWLEDGE LEVEL implicit in the existing model

                                                                                                                                                                                                                                                            graphics/16fig21.gif

                                                                                                                                                                                                                                                            Các chỉnh sửa bị giới hạn nằm ở CẤP ĐỘ KIẾN THỨC, trong khi các chỉnh sửa hàng ngày nằm ở cấp độ hoạt động. Một sự kết hợp hợp lý. Tất cả các đối tượng trên dòng mô tả các loại hoặc chính sách lâu dài. Loại nhân viên thực sự đã áp đặt hành vi cho nhân viên.

                                                                                                                                                                                                                                                            Nhà phát triển đang chia sẻ những hiểu biết của mình với các đồng nghiệp khi một trong những nhà phát triển khác đã có một hiểu biết khác. Sự rõ ràng của việc nhìn thấy mô hình được tổ chức theo CẤP ĐỘ KIẾN THỨC đã giúp cô nhận ra điều đã khiến cô bận tâm ngày hôm trước. Hai khái niệm khác biệt đang được kết hợp trong cùng một đối tượng. Cô đã nghe thấy điều đó trong ngôn ngữ được sử dụng vào ngày hôm trước nhưng chưa nhận ra điều đó.

                                                                                                                                                                                                                                                            Một loại nhân viên được phân công cho either Kế hoạch nghỉ hưu hoặc tiền lương.

                                                                                                                                                                                                                                                            Nhưng đó thực sự không phải là một tuyên bố bằng NGÔN NGỮ PHỔ BIẾN. Không có "bảng lương" trong mô hình. Họ đã nói bằng ngôn ngữ mà họ muốn, thay vì ngôn ngữ mà họ có. Khái niệm bảng lương đã ngầm hiểu trong mô hình, được gộp lại với Loại Nhân Viên. Trước đó, nó đã không rõ ràng như vậy trước khi CẤP ĐỘ KIẾN THỨC được tách ra, và các yếu tố trong cụm từ quan trọng đó đều xuất hiện cùng một cấp độ với nhau... ngoại trừ một cái.

                                                                                                                                                                                                                                                            Dựa trên hiểu biết này, cô ấy đã tái cấu trúc lại một lần nữa thành một mô hình hỗ trợ tuyên bố đó.

                                                                                                                                                                                                                                                            Nhu cầu về sự kiểm soát của người dùng đối với các quy tắc liên kết các đối tượng đã thúc đẩy nhóm đến một mô hình có MỨC ĐỘ KIẾN THỨC ngầm.

                                                                                                                                                                                                                                                            Figure 16.22. Payroll is now explicit, distinct from Employee Type.

                                                                                                                                                                                                                                                            graphics/16fig22.gif

                                                                                                                                                                                                                                                            Figure 16.23. Each Employee Type now has a Retirement Plan and a Payroll.

                                                                                                                                                                                                                                                            graphics/16fig23.gif

                                                                                                                                                                                                                                                            MỨC ĐỘ KIẾN THỨC được gợi ý bởi các hạn chế truy cập đặc trưng và mối quan hệ kiểu "thứ-thứ". Khi nó được thiết lập, sự rõ ràng mà nó mang lại giúp sản xuất một cái nhìn sâu sắc khác đã làm rõ hai khái niệm quan trọng trong lĩnh vực bằng cách tách riêng Tính bảng lương.

                                                                                                                                                                                                                                                            MỨC ĐỘ KIẾN THỨC, giống như các cấu trúc quy mô lớn khác, không phải là điều cần thiết một cách nghiêm ngặt. Các đối tượng vẫn hoạt động mà không cần nó, và cái nhìn mà đã tách loại nhân viên ra khỏi bảng lương vẫn có thể được tìm thấy và sử dụng. Có thể sẽ đến một lúc mà cấu trúc này không còn có vẻ như đang đóng góp và có thể bị loại bỏ. Nhưng hiện tại, nó dường như kể một câu chuyện hữu ích về hệ thống và giúp các nhà phát triển đối phó với mô hình.

                                                                                                                                                                                                                                                            graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                            Nhìn thoạt đầu, CẤP ĐỘ KIẾN THỨC có vẻ giống như một trường hợp đặc biệt của CÁC LỚP TRÁCH NHIỆM, đặc biệt là lớp "chính sách", nhưng thực tế thì không. Một điều là, các phụ thuộc chạy theo cả hai hướng giữa các cấp độ, nhưng với CÁC LỚP, các lớp thấp hơn độc lập với các lớp cao hơn.

                                                                                                                                                                                                                                                            Trên thực tế, CẤP ĐỘ KIẾN THỨC có thể đồng tồn tại với hầu hết các cấu trúc quy mô lớn khác, cung cấp một chiều hướng tổ chức bổ sung.


                                                                                                                                                                                                                                                              Pluggable Component Framework

                                                                                                                                                                                                                                                              Cơ hội xuất hiện trong một mô hình rất trưởng thành, sâu sắc và tinh gọn. MỘT KHUNG THÀNH PHẦN CÓ THỂ CẮM VÀO THƯỜNG chỉ được áp dụng sau khi một vài ứng dụng đã được triển khai trong cùng một miền.

                                                                                                                                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                              Khi nhiều ứng dụng phải tương tác với nhau, tất cả đều dựa trên những trừu tượng giống nhau nhưng được thiết kế độc lập, việc dịch giữa nhiều BOUNDED CONTEXTS hạn chế khả năng tích hợp. Một KERNEL CHUNG là không thực tế đối với những đội không làm việc chặt chẽ với nhau. Sự trùng lặp và phân mảnh làm gia tăng chi phí phát triển và lắp đặt, và khả năng tương tác trở nên rất khó khăn.

                                                                                                                                                                                                                                                              Một số dự án thành công phân chia thiết kế của chúng thành các thành phần, mỗi thành phần có trách nhiệm với những loại chức năng nhất định. Thông thường, tất cả các thành phần đều kết nối với một trung tâm chính, trung tâm này hỗ trợ bất kỳ giao thức nào mà chúng cần và biết cách giao tiếp với các giao diện mà chúng cung cấp. Cũng có thể sử dụng các mẫu kết nối thành phần khác. Việc thiết kế các giao diện này và trung tâm kết nối chúng phải được phối hợp, trong khi sự độc lập nhiều hơn có thể được áp dụng trong việc thiết kế nội bộ.

                                                                                                                                                                                                                                                              Nhiều khung kỹ thuật được sử dụng rộng rãi hỗ trợ mẫu này, nhưng đó là vấn đề thứ yếu. Một khung kỹ thuật chỉ cần thiết nếu nó giải quyết được một vấn đề kỹ thuật thiết yếu nào đó như phân phối hoặc chia sẻ một thành phần giữa các ứng dụng khác nhau. Mẫu cơ bản là một tổ chức khái niệm về các trách nhiệm. Nó có thể dễ dàng được áp dụng trong một chương trình Java duy nhất.

                                                                                                                                                                                                                                                              Do đó:

                                                                                                                                                                                                                                                              Chắt lọc một CỐT LÕI TRỪU TƯỢNG của các giao diện và tương tác, và tạo một khung cho phép các triển khai đa dạng của những giao diện đó có thể được thay thế tự do. Tương tự, cho phép bất kỳ ứng dụng nào sử dụng những thành phần đó, miễn là nó hoạt động hoàn toàn thông qua các giao diện của CỐT LÕI TRỪU TƯỢNG.

                                                                                                                                                                                                                                                              Các trừu tượng cấp cao được xác định và chia sẻ trên toàn bộ hệ thống; sự chuyên môn hóa xảy ra trong CÁC MODULE. Trung tâm của ứng dụng là một LÕI TRỪU TƯỢNG trong một HẠT CHIA SẺ. Tuy nhiên, nhiều BỐI CẢNH GIỚI HẠN có thể nằm phía sau các giao diện thành phần được đóng gói, do đó cấu trúc này có thể đặc biệt thuận tiện khi nhiều thành phần đến từ nhiều nguồn khác nhau, hoặc khi các thành phần đang đóng gói phần mềm có sẵn để tích hợp.

                                                                                                                                                                                                                                                              Điều này không có nghĩa là các thành phần phải có các mô hình khác nhau. Nhiều thành phần có thể được phát triển trong một NGỮ CẢNH duy nhất nếu các nhóm LIÊN TỤC TÍCH HỢP, hoặc họ có thể xác định một KERNEL CHUNG khác được giữ chung bởi một tập hợp các thành phần có liên quan chặt chẽ. Tất cả các chiến lược này có thể đồng tồn tại một cách dễ dàng trong một cấu trúc quy mô lớn của CÁC THÀNH PHẦN CÓ THỂ CẮM VÀO. Một tùy chọn khác, trong một số trường hợp, là sử dụng MỘT NGÔN NGỮ CÔNG BỐ cho giao diện cắm của trung tâm.

                                                                                                                                                                                                                                                              Có một số nhược điểm khi sử dụng KHUNG THÀNH PHẦN CÓ THỂ CẮM VÀO. Một trong số đó là đây là một mô hình rất khó áp dụng. Nó yêu cầu sự chính xác trong thiết kế các giao diện và một mô hình đủ sâu để nắm bắt những hành vi cần thiết trong CỐT LÕI TRỪU TƯỢNG. Một nhược điểm lớn khác là các ứng dụng có ít tùy chọn. Nếu một ứng dụng cần một cách tiếp cận rất khác đối với CÔNG VIỆC CỐT LÕI, cấu trúc sẽ cản trở. Các nhà phát triển có thể chuyên biệt hóa mô hình, nhưng họ không thể thay đổi CỐT LÕI TRỪU TƯỢNG mà không thay đổi giao thức của tất cả các thành phần đa dạng. Kết quả là, quá trình tinh chỉnh liên tục CỐT LÕI, tái cấu trúc để có cái nhìn sâu sắc hơn, gần như bị đóng băng.

                                                                                                                                                                                                                                                              Fayad và Johnson (2000) cung cấp cái nhìn tốt về những nỗ lực đầy tham vọng trong các KHUNG THÀNH PHẦN CÓ THỂ CẮT GHÉP ở nhiều lĩnh vực khác nhau, bao gồm một cuộc thảo luận về SEMATECH CIM. Sự thành công của những khung như vậy là một câu chuyện hỗn hợp. Có lẽ trở ngại lớn nhất là sự chín muồi của hiểu biết cần thiết để thiết kế một khung hữu ích. Một KHUNG THÀNH PHẦN CÓ THỂ CẮT GHÉP không nên là cấu trúc quy mô lớn đầu tiên được áp dụng trong một dự án, cũng như không nên là cái thứ hai. Những ví dụ thành công nhất đã xuất hiện sau khi phát triển hoàn chỉnh nhiều ứng dụng chuyên biệt.

                                                                                                                                                                                                                                                              Example
                                                                                                                                                                                                                                                              The SEMATECH CIM Framework

                                                                                                                                                                                                                                                              Trong một nhà máy sản xuất vi mạch, các nhóm (gọi là lô) của các tấm silicon được chuyển từ máy này sang máy khác qua hàng trăm bước xử lý cho đến khi mạch vi mô được in và khắc vào chúng hoàn tất. Nhà máy cần phần mềm có thể theo dõi từng lô riêng lẻ, ghi lại chính xác quá trình xử lý đã thực hiện đối với nó, và sau đó chỉ đạo công nhân nhà máy hoặc thiết bị tự động đưa nó đến máy thích hợp tiếp theo và áp dụng quy trình thích hợp tiếp theo. Phần mềm như vậy được gọi là hệ thống thực thi sản xuất (MES).

                                                                                                                                                                                                                                                              Hàng trăm máy móc khác nhau từ hàng chục nhà cung cấp được sử dụng, với các công thức được tùy chỉnh cẩn thận ở mỗi bước. Phát triển phần mềm MES có thể xử lý sự kết hợp phức tạp như vậy là một thách thức lớn và tốn kém. Để phản ứng lại, một liên minh ngành công nghiệp, SEMATECH, đã phát triển CIM Framework.

                                                                                                                                                                                                                                                              Khung CIM rất lớn và phức tạp và có nhiều khía cạnh, nhưng hai khía cạnh là liên quan ở đây. Đầu tiên, khung này định nghĩa các giao diện trừu tượng cho các khái niệm cơ bản của lĩnh vực MES bán dẫn - tức là, MIỀN CỐT LÕI dưới dạng CỐT LÕI TRỪU TƯỢNG. Các định nghĩa giao diện này bao gồm cả hành vi và ngữ nghĩa.

                                                                                                                                                                                                                                                              Figure 16.24. A highly simplified subset of the CIM interfaces, with sample implementations

                                                                                                                                                                                                                                                              graphics/16fig24.gif

                                                                                                                                                                                                                                                              Nếu một nhà cung cấp sản xuất một máy mới, họ phải phát triển một ứng dụng chuyên biệt cho giao diện Máy Quy trình. Nếu họ tuân thủ giao diện đó, thành phần điều khiển máy của họ sẽ có thể tích hợp vào bất kỳ ứng dụng nào dựa trên Khung CIM.

                                                                                                                                                                                                                                                              Sau khi định nghĩa các giao diện này, SEMATECH đã xác định các quy tắc mà thông qua đó chúng có thể tương tác trong một ứng dụng. Bất kỳ ứng dụng nào dựa trên CIM Framework đều phải triển khai một giao thức mà trong đó có chứa các đối tượng thực hiện một số tập con của những giao diện đó. Nếu giao thức này được thực hiện, và ứng dụng tuân thủ nghiêm ngặt các giao diện trừu tượng, thì ứng dụng có thể tin tưởng vào các dịch vụ được hứa hẹn của những giao diện đó, bất kể cách thực hiện. Sự kết hợp của những giao diện này và giao thức để sử dụng chúng tạo thành một cấu trúc lớn chặt chẽ và hạn chế.

                                                                                                                                                                                                                                                              Figure 16.25. The user places a lot in the next machine and logs the move into the computer.

                                                                                                                                                                                                                                                              graphics/16fig25.gif

                                                                                                                                                                                                                                                              Khung này có những yêu cầu hạ tầng rất cụ thể. Nó được ghép chặt với CORBA để cung cấp tính năng lưu trữ, giao dịch, sự kiện và các dịch vụ kỹ thuật khác. Nhưng điều thú vị về nó là định nghĩa về KHUNG THÀNH PHẦN CÓ THỂ CẮT CẮM, cho phép mọi người phát triển phần mềm một cách độc lập và tích hợp mượt mà vào các hệ thống lớn. Không ai biết tất cả các chi tiết của một hệ thống như vậy, nhưng mọi người đều hiểu được sự tổng quát.

                                                                                                                                                                                                                                                              graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                              Làm thế nào mà hàng nghìn người có thể làm việc độc lập để tạo ra một chiếc chăn gồm hơn 40.000 mảnh ghép?

                                                                                                                                                                                                                                                              Một vài quy tắc đơn giản cung cấp một cấu trúc quy mô lớn cho Chiếc Chăn Tưởng Niệm AIDS, để lại các chi tiết cho các người đóng góp cá nhân. Hãy chú ý đến cách các quy tắc tập trung vào sứ mệnh tổng thể (tưởng nhớ những người đã qua đời vì AIDS), các đặc điểm của một thành phần giúp việc tích hợp trở nên thực tiễn và khả năng xử lý chiếc chăn theo những phần lớn hơn (chẳng hạn như gấp lại).

                                                                                                                                                                                                                                                              Đây là cách tạo một panel cho chiếc chăn.

                                                                                                                                                                                                                                                              [Từ trang web Dự án Nhà khăn trải AIDS, www.aidsquilt.org]

                                                                                                                                                                                                                                                              Thiết kế bảng điều khiển

                                                                                                                                                                                                                                                              Bao gồm tên của người bạn đang tưởng nhớ. Hãy thoải mái thêm thông tin bổ sung như ngày tháng năm sinh và ngày mất, cũng như quê quán. . . . [V]ui lòng giới hạn mỗi bảng thông tin cho một cá nhân duy nhất . . . .

                                                                                                                                                                                                                                                              Chọn vật liệu của bạn

                                                                                                                                                                                                                                                              Hãy nhớ rằng chiếc chăn được gấp lại và mở ra nhiều lần, vì vậy độ bền là rất quan trọng. Vì keo có thể bị phân hủy theo thời gian, nên tốt nhất là nên may các thứ vào tấm vải. Một loại vải vừa phải, không co giãn như cotton duck hoặc poplin là lựa chọn tốt nhất.

                                                                                                                                                                                                                                                              Thiết kế của bạn có thể theo chiều dọc hoặc chiều ngang, nhưng tấm vải hoàn thiện, viền phải có kích thước 3 feet x 6 feet (90 cm x 180 cm) - không nhiều hơn và không ít hơn! Khi cắt vải, hãy để dư 2-3 inch ở mỗi bên để tạo viền. Nếu bạn không thể tự viền, chúng tôi sẽ làm điều đó cho bạn. Việc lót cho các tấm vải là không cần thiết, nhưng nên có lớp lót. Lớp lót giúp giữ cho các tấm vải sạch khi chúng được trải ra trên mặt đất. Nó cũng giúp giữ hình dáng của vải.

                                                                                                                                                                                                                                                              Tạo bảng điều khiển

                                                                                                                                                                                                                                                              Khi xây dựng bảng của bạn, bạn có thể muốn sử dụng một số kỹ thuật sau đây:

                                                                                                                                                                                                                                                              • Thêu áp dụng: May vải, chữ cái và những kỷ niệm nhỏ lên vải nền. Đừng phụ thuộc vào keo - nó sẽ không bền.

                                                                                                                                                                                                                                                              • Sơn: Sử dụng sơn vải hoặc thuốc nhuộm bền màu, hoặc dùng bút mực không phai. Vui lòng không sử dụng sơn "phồng"; nó quá dính.

                                                                                                                                                                                                                                                              • Khuôn mẫu: Hãy vẽ thiết kế của bạn lên vải bằng bút chì, nâng khuôn mẫu lên, sau đó sử dụng cọ để áp dụng sơn vải hoặc bút đánh dấu không thể tẩy xóa.

                                                                                                                                                                                                                                                              • Đồ trang trí: Hãy chắc chắn rằng bất kỳ tài liệu nào bạn thêm vào bảng sẽ không làm rách vải (tránh kính và sequins vì lý do này), và hãy đảm bảo tránh các vật thể rất cồng kềnh.

                                                                                                                                                                                                                                                              • Hình ảnh: Cách tốt nhất để bao gồm hình ảnh hoặc thư là sao chép chúng lên giấy chuyển nhiệt, là chúng lên vải 100% cotton và khâu vải đó vào bảng. Bạn cũng có thể đặt hình ảnh vào nhựa vinyl trong suốt và khâu nó vào bảng (không chính giữa để tránh chỗ gập).


                                                                                                                                                                                                                                                                How Restrictive Should a Structure Be?

                                                                                                                                                                                                                                                                Các kiểu cấu trúc quy mô lớn được thảo luận trong chương này dao động từ BIỂU TƯỢNG HỆ THỐNG rất thoải mái đến KHUÔN KHỔ THÀNH PHẦN CÓ THỂ CẮM. Tất nhiên còn nhiều cấu trúc khác có thể, và ngay cả trong một kiểu cấu trúc tổng quát, có rất nhiều sự lựa chọn về mức độ nghiêm ngặt của các quy tắc.

                                                                                                                                                                                                                                                                Ví dụ, CÁC LỚP TRÁCH NHIỆM quy định một loại phân tách các khái niệm mô hình và các phụ thuộc của chúng, nhưng bạn có thể thêm các quy tắc sẽ xác định các mẫu giao tiếp giữa các lớp.

                                                                                                                                                                                                                                                                Xem xét một nhà máy sản xuất, nơi phần mềm chỉ đạo từng bộ phận đến một máy nơi nó được xử lý theo một công thức nào đó. Quy trình chính xác được đặt hàng từ một lớp Chính sách và thực thi trong một lớp Hoạt động. Nhưng chắc chắn sẽ có những sai sót xảy ra trên sàn nhà máy. Tình huống thực tế sẽ không nhất quán với các quy tắc của phần mềm. Bây giờ, một lớp Hoạt động phải phản ánh thế giới như nó đang diễn ra, có nghĩa là khi một bộ phận thỉnh thoảng được đưa vào máy sai, thông tin đó phải được chấp nhận một cách vô điều kiện. Bằng cách nào đó, điều kiện ngoại lệ này cần được truyền đạt đến một lớp cao hơn. Một lớp ra quyết định có thể sau đó sử dụng các chính sách khác để sửa chữa tình huống, có thể bằng cách định tuyến lại bộ phận đến quá trình sửa chữa hoặc loại bỏ nó. Nhưng lớp Hoạt động không biết gì về các lớp cao hơn. Việc giao tiếp phải được thực hiện theo cách không tạo ra sự phụ thuộc hai chiều từ các lớp dưới lên các lớp cao hơn.

                                                                                                                                                                                                                                                                Thường thì, tín hiệu này sẽ được thực hiện thông qua một cơ chế sự kiện nào đó. Các đối tượng Hoạt động sẽ phát sinh sự kiện bất cứ khi nào trạng thái của chúng thay đổi. Các đối tượng trong lớp chính sách sẽ lắng nghe những sự kiện mà chúng quan tâm từ các lớp thấp hơn. Khi một sự kiện xảy ra vi phạm một quy tắc, quy tắc sẽ thực hiện một hành động (một phần trong định nghĩa của quy tắc) để đưa ra phản ứng phù hợp, hoặc có thể phát sinh một sự kiện để phục vụ cho một lớp cao hơn.

                                                                                                                                                                                                                                                                Trong ví dụ về ngân hàng, giá trị của các tài sản thay đổi (Hoạt động), làm thay đổi giá trị của các phân khúc trong danh mục đầu tư. Khi những giá trị này vượt quá giới hạn phân bổ danh mục (Chính sách), có thể một nhà giao dịch sẽ được cảnh báo, người có thể mua hoặc bán tài sản để điều chỉnh lại sự cân bằng.

                                                                                                                                                                                                                                                                Chúng ta có thể giải quyết vấn đề này theo từng trường hợp cụ thể, hoặc có thể quyết định về một mô hình nhất quán để mọi người tuân theo trong việc tương tác với các đối tượng của các lớp cụ thể. Một cấu trúc chặt chẽ hơn tăng tính đồng nhất, làm cho thiết kế dễ hiểu hơn. Nếu cấu trúc phù hợp, các quy tắc có khả năng thúc đẩy các nhà phát triển hướng tới các thiết kế tốt. Những phần riêng lẻ có khả năng kết hợp tốt hơn.

                                                                                                                                                                                                                                                                Mặt khác, các hạn chế có thể lấy đi tính linh hoạt mà các nhà phát triển cần. Những con đường giao tiếp rất cụ thể có thể không thực tế để áp dụng trên các BOUNDED CONTEXTS, đặc biệt là trong các công nghệ triển khai khác nhau, trong một hệ thống không đồng nhất.

                                                                                                                                                                                                                                                                Vì vậy, bạn phải chống lại cám dỗ xây dựng các khuôn khổ và tổ chức việc triển khai cấu trúc quy mô lớn. Đóng góp quan trọng nhất của cấu trúc quy mô lớn là sự nhất quán về khái niệm và cung cấp cái nhìn sâu sắc về lĩnh vực. Mỗi quy tắc cấu trúc nên làm cho việc phát triển trở nên dễ dàng hơn.


                                                                                                                                                                                                                                                                  Refactoring Toward a Fitting Structure

                                                                                                                                                                                                                                                                  Trong một thời đại mà ngành công nghiệp đang từ bỏ thiết kế quá nhiều ở giai đoạn đầu, một số người sẽ coi cấu trúc quy mô lớn là sự trở lại với những ngày tồi tệ của kiến trúc thác nước. Nhưng thực tế, cách duy nhất để tìm ra một cấu trúc hữu ích là từ hiểu biết sâu sắc về lĩnh vực và vấn đề, và cách thực tiễn để đạt được sự hiểu biết đó là một quá trình phát triển lặp đi lặp lại.

                                                                                                                                                                                                                                                                  Một đội ngũ cam kết PHÁT TRIỂN TRẬT TỰ phải dũng cảm xem xét lại cấu trúc quy mô lớn trong suốt vòng đời của dự án. Đội không nên tự bó buộc mình với một cấu trúc được hình thành sớm, khi mà không ai hiểu rõ về lĩnh vực hoặc các yêu cầu.

                                                                                                                                                                                                                                                                  Thật không may, sự tiến hóa đó có nghĩa là cấu trúc cuối cùng của bạn sẽ không có sẵn ngay từ đầu, và điều đó có nghĩa là bạn sẽ phải tái cấu trúc để áp đặt nó khi bạn tiến bước. Điều này có thể tốn kém và khó khăn, nhưng là điều cần thiết. Có một số cách chung để kiểm soát chi phí và tối đa hóa lợi ích.

                                                                                                                                                                                                                                                                  Minimalism

                                                                                                                                                                                                                                                                  Một yếu tố quan trọng để giữ chi phí thấp là giữ cho cấu trúc đơn giản và nhẹ nhàng. Đừng cố gắng bao quát hết mọi vấn đề. Hãy chỉ giải quyết những mối quan tâm nghiêm trọng nhất và để lại những vấn đề còn lại được xử lý theo từng trường hợp cụ thể.

                                                                                                                                                                                                                                                                  Ngay từ đầu, việc chọn một cấu trúc lỏng lẻo, chẳng hạn như một HÌNH ẢNH HỆ THỐNG hoặc một vài LỚP TRÁCH NHIỆM, có thể là hữu ích. Một cấu trúc tối thiểu, lỏng lẻo vẫn có thể cung cấp các hướng dẫn nhẹ nhàng giúp ngăn chặn sự hỗn loạn.

                                                                                                                                                                                                                                                                  Communication and Self-Discipline

                                                                                                                                                                                                                                                                  Toàn bộ đội ngũ phải tuân theo cấu trúc trong phát triển mới và tái cấu trúc. Để làm được điều này, toàn bộ đội ngũ phải hiểu rõ cấu trúc. Thuật ngữ và mối quan hệ phải được đưa vào NGÔN NGỮ PHỔ BIẾN.

                                                                                                                                                                                                                                                                  Cấu trúc quy mô lớn có thể cung cấp một từ vựng cho dự án để xử lý hệ thống một cách rộng rãi, và cho những người khác nhau độc lập đưa ra những quyết định hài hòa. Nhưng vì hầu hết các cấu trúc quy mô lớn đều là những hướng dẫn khái niệm lỏng lẻo, các nhóm phải thực hiện tự kỷ luật.

                                                                                                                                                                                                                                                                  Nếu không có sự tuân thủ nhất quán từ nhiều người tham gia, các cấu trúc có xu hướng bị suy yếu. Mối quan hệ của cấu trúc với các phần chi tiết của mô hình hoặc việc triển khai thường không rõ ràng trong mã, và các bài kiểm tra chức năng không phụ thuộc vào cấu trúc. Hơn nữa, cấu trúc có xu hướng trừu tượng, vì vậy việc duy trì tính nhất quán trong việc áp dụng có thể rất khó khăn trong một đội ngũ lớn (hoặc nhiều đội ngũ).

                                                                                                                                                                                                                                                                  Các loại cuộc trò chuyện diễn ra trong hầu hết các nhóm không đủ để duy trì một cấu trúc quy mô lớn đồng nhất trong một hệ thống. Điều quan trọng là phải tích hợp nó vào NGÔN NGỮ PHỔ BIẾN của dự án, và mọi người cần thực hành ngôn ngữ đó một cách kiên trì.

                                                                                                                                                                                                                                                                  Restructuring Yields Supple Design

                                                                                                                                                                                                                                                                  Thứ hai, bất kỳ sự thay đổi nào đối với cấu trúc có thể dẫn đến việc refactor rất nhiều. Cấu trúc đang phát triển khi độ phức tạp của hệ thống tăng lên và sự hiểu biết sâu sắc hơn. Mỗi khi cấu trúc thay đổi, toàn bộ hệ thống phải được thay đổi để tuân theo trật tự mới. Rõ ràng đó là một khối lượng công việc lớn.

                                                                                                                                                                                                                                                                  Điều này không tệ như nó nghe có vẻ. Tôi đã quan sát rằng một thiết kế với cấu trúc quy mô lớn thường dễ dàng chuyển đổi hơn nhiều so với một thiết kế không có. Điều này dường như đúng ngay cả khi thay đổi từ một loại cấu trúc sang một loại khác, chẳng hạn từ BIỂU TƯỢNG sang LỚP. Tôi không thể hoàn toàn giải thích điều này. Một phần của câu trả lời là việc sắp xếp lại điều gì đó dễ dàng hơn khi bạn có thể hiểu được sự sắp xếp hiện tại của nó, và cấu trúc có sẵn làm cho điều đó dễ dàng hơn. Một phần là do kỷ luật cần thiết để duy trì cấu trúc trước đó thấm nhuần tất cả các khía cạnh của hệ thống. Nhưng tôi nghĩ còn có điều gì đó hơn nữa, vì thậm chí còn dễ dàng hơn để thay đổi một hệ thống đã trải qua hai cấu trúc trước đó.

                                                                                                                                                                                                                                                                  Một chiếc áo khoác da mới thì cứng và không thoải mái, nhưng sau ngày đầu tiên mặc, khuỷu tay đã được uốn cong vài lần và trở nên dễ uốn hơn. Sau một vài lần mặc khác, vai đã trở nên lỏng lẻo hơn, và áo khoác dễ dàng hơn để mặc vào. Sau nhiều tháng sử dụng, da trở nên mềm mại và thoải mái, dễ dàng di chuyển. Cũng giống như các mô hình được biến đổi lặp đi lặp lại bằng các biến đổi âm thanh. Kiến thức ngày càng tăng được tích hợp vào chúng và các trục chính của sự thay đổi đã được xác định và làm linh hoạt, trong khi các khía cạnh ổn định đã được đơn giản hóa. Các ĐƯỜNG CONCEPTUAL RỘNG LỚN hơn của lĩnh vực cơ sở đang hiện ra trong cấu trúc mô hình.

                                                                                                                                                                                                                                                                  Distillation Lightens the Load

                                                                                                                                                                                                                                                                  Một lực lượng quan trọng khác cần được áp dụng vào mô hình là tinh chế liên tục. Điều này làm giảm độ khó trong việc thay đổi cấu trúc theo nhiều cách khác nhau. Đầu tiên, bằng cách loại bỏ các cơ chế, CÁC TIỂU MIỀN CHUNG và các cấu trúc hỗ trợ khác khỏi MIỀN CỐT LÕI, có thể chỉ đơn giản là ít thứ hơn để cấu trúc lại.

                                                                                                                                                                                                                                                                  Nếu có thể, những yếu tố hỗ trợ này nên được định nghĩa để phù hợp với cấu trúc quy mô lớn một cách đơn giản. Ví dụ, trong một hệ thống CÁC LỚP TRÁCH NHIỆM, một TIỂU MIỀN CHUNG có thể được định nghĩa sao cho phù hợp với một lớp duy nhất. Với CÁC THÀNH PHẦN CÓ THỂ CẮT GHÉP, một TIỂU MIỀN CHUNG có thể hoàn toàn thuộc về một thành phần duy nhất, hoặc nó có thể là một HẠNG CHUNG giữa một tập hợp các thành phần liên quan. Những yếu tố hỗ trợ này có thể cần được tái cấu trúc để tìm vị trí của chúng trong cấu trúc; nhưng chúng di chuyển độc lập với MIỀN CỐT LÕI và có xu hướng được tập trung hơn, điều này làm cho việc đó dễ dàng hơn. Cuối cùng, chúng ít quan trọng hơn, vì vậy việc tinh chỉnh trở nên kém quan trọng hơn.

                                                                                                                                                                                                                                                                  Các nguyên tắc của việc chưng cất và tái cấu trúc hướng tới sự sâu sắc hơn cũng áp dụng cho chính cấu trúc quy mô lớn. Ví dụ, các lớp có thể ban đầu được chọn dựa trên sự hiểu biết hời hợt về miền; chúng dần dần được thay thế bằng những sự trừu tượng sâu sắc hơn thể hiện những trách nhiệm cơ bản của hệ thống. Sự rõ ràng sắc nét này cho phép mọi người nhìn sâu vào thiết kế, điều này là mục tiêu. Nó cũng là một phần của phương tiện, vì nó giúp việc thao tác hệ thống ở quy mô lớn trở nên dễ dàng và an toàn hơn.


                                                                                                                                                                                                                                                                    Chapter Seventeen. Bringing the Strategy Together

                                                                                                                                                                                                                                                                    Ba chương trước đã trình bày nhiều nguyên tắc và kỹ thuật cho thiết kế chiến lược dựa trên miền. Trong một hệ thống lớn và phức tạp, bạn có thể cần áp dụng một số trong số đó cho cùng một thiết kế. Cấu trúc quy mô lớn coexist với BẢN ĐỒ NGữ CẢNH như thế nào? Các khối xây dựng phù hợp ở đâu? Bạn nên làm gì trước? Thứ hai? Thứ ba? Bạn tiến hành xây dựng chiến lược của mình như thế nào?


                                                                                                                                                                                                                                                                      Combining Large-Scale Structures and BOUNDED CONTEXTS

                                                                                                                                                                                                                                                                      Figure 17.1.

                                                                                                                                                                                                                                                                      graphics/17fig01.gif

                                                                                                                                                                                                                                                                      Ba nguyên tắc cơ bản của thiết kế chiến lược (ngữ cảnh, chưng cất và cấu trúc quy mô lớn) không phải là những sự thay thế cho nhau; chúng bổ sung cho nhau và tương tác theo nhiều cách. Chẳng hạn, một cấu trúc quy mô lớn có thể tồn tại trong một NGữ CẢNH HẠN CHẾ, hoặc nó có thể cắt ngang qua nhiều ngữ cảnh và tổ chức BẢN ĐỒ NGỮ CẢNH.

                                                                                                                                                                                                                                                                      Các ví dụ trước đây về CÁC LỚP TRÁCH NHIỆM chỉ được giới hạn trong một BỐI CẢNH RÀNG BUỘC. Đây là cách đơn giản nhất để giải thích ý tưởng, và đó là cách sử dụng phổ biến của mẫu này. Trong một kịch bản đơn giản như vậy, ý nghĩa của các tên lớp được giới hạn trong BỐI CẢNH đó, cũng như các tên của các phần tử mô hình hoặc giao diện hệ thống con tồn tại trong BỐI CẢNH đó.

                                                                                                                                                                                                                                                                      Figure 17.2. Structuring a model within a single BOUNDED CONTEXT

                                                                                                                                                                                                                                                                      graphics/17fig02.gif

                                                                                                                                                                                                                                                                      Cấu trúc địa phương như vậy có thể hữu ích trong một mô hình rất phức tạp nhưng thống nhất, nâng cao giới hạn phức tạp về mức độ mà có thể duy trì trong một BỐI CẢNH BỊ GIỚI HẠN duy nhất.

                                                                                                                                                                                                                                                                      Nhưng trên nhiều dự án, thách thức lớn hơn là hiểu cách mà các phần khác nhau hòa hợp với nhau. Chúng có thể được phân chia thành các BỐI CẢNH riêng biệt, nhưng mỗi phần đóng vai trò gì trong hệ thống tích hợp tổng thể và cách các phần liên quan với nhau như thế nào? Sau đó, cấu trúc quy mô lớn có thể được sử dụng để tổ chức BẢN ĐỒ BỐI CẢNH. Trong trường hợp này, thuật ngữ của cấu trúc áp dụng cho toàn bộ dự án (hoặc ít nhất là một phần nào đó có ranh giới rõ ràng).

                                                                                                                                                                                                                                                                      Figure 17.3. Structure imposed on the relationships of components of distinct BOUNDED CONTEXTS

                                                                                                                                                                                                                                                                      graphics/17fig03.gif

                                                                                                                                                                                                                                                                      Giả sử bạn muốn áp dụng CÁC LỚP TRÁCH NHIỆM, nhưng bạn có một hệ thống kế thừa mà cách tổ chức của nó không nhất quán với cấu trúc quy mô lớn mà bạn mong muốn. Bạn có phải từ bỏ CÁC LỚP của mình không? Không, nhưng bạn phải thừa nhận vị trí thực sự mà hệ thống kế thừa có trong cấu trúc. Trên thực tế, có thể có lợi khi đặc trưng hóa hệ thống kế thừa. CÁC DỊCH VỤ mà hệ thống kế thừa cung cấp có thể thực sự chỉ giới hạn ở một vài LỚP. Để có thể nói rằng hệ thống kế thừa phù hợp với các LỚP TRÁCH NHIỆM cụ thể mô tả một khía cạnh chính của phạm vi và vai trò của nó.

                                                                                                                                                                                                                                                                      Figure 17.4. A structure that allows some components to span layers

                                                                                                                                                                                                                                                                      graphics/17fig04.gif

                                                                                                                                                                                                                                                                      Nếu các khả năng của hệ thống di sản đang được truy cập thông qua một FACADE, bạn có thể thiết kế mỗi SERVICE mà FACADE cung cấp để phù hợp với một lớp.

                                                                                                                                                                                                                                                                      Nội thất của ứng dụng Phối hợp Giao hàng, là một di sản trong ví dụ này, được trình bày như một khối đồng nhất. Nhưng một đội trong một dự án với cấu trúc quy mô lớn đã được thiết lập vững chắc trải rộng trên BẢN ĐỒ NGỮ CẢNH có thể chọn, trong NGỮ CẢNH của họ, để sắp xếp mô hình của mình theo cùng những LỚP quen thuộc.

                                                                                                                                                                                                                                                                      Figure 17.5. The same structure applied within a CONTEXT and across the CONTEXT MAP as a whole

                                                                                                                                                                                                                                                                      graphics/17fig05.gif

                                                                                                                                                                                                                                                                      Tất nhiên, vì mỗi BOUND CONTEXT là một không gian tên riêng, một cấu trúc có thể được sử dụng để tổ chức mô hình trong một CONTEXT, trong khi một cấu trúc khác được sử dụng trong một CONTEXT lân cận, và một cấu trúc khác nữa tổ chức BẢN ĐỒ CONTEXT. Tuy nhiên, đi quá xa theo hướng đó có thể làm giảm giá trị của cấu trúc quy mô lớn như một tập hợp khái niệm thống nhất cho dự án.


                                                                                                                                                                                                                                                                        Combining Large-Scale Structures and Distillation

                                                                                                                                                                                                                                                                        Các khái niệm về cấu trúc quy mô lớn và chưng cất cũng hỗ trợ lẫn nhau. Cấu trúc quy mô lớn có thể giúp giải thích các mối quan hệ trong MIỀN CỐT LÕI và giữa các TIỀN MIỀN CHUNG.

                                                                                                                                                                                                                                                                        Figure 17.6. MODULES of the CORE DOMAIN (in bold) and GENERIC SUBDOMAINS are clarified by the layers.

                                                                                                                                                                                                                                                                        graphics/17fig06.gif

                                                                                                                                                                                                                                                                        Đồng thời, cấu trúc quy mô lớn bản thân có thể là một phần quan trọng của MIỀN CỐT LÕI. Ví dụ, việc phân biệt các lớp tiềm năng, hoạt động, chính sách và hỗ trợ quyết định tinh lọc một cái nhìn sâu sắc mà là thiết yếu cho vấn đề kinh doanh được giải quyết bởi phần mềm. Cái nhìn này đặc biệt hữu ích nếu một dự án được chia thành nhiều BỐN BỐ CẢNH, để các đối tượng mô hình của MIỀN CỐT LÕI không có ý nghĩa trên phần lớn của dự án.


                                                                                                                                                                                                                                                                          Assessment First

                                                                                                                                                                                                                                                                          Khi bạn đang giải quyết thiết kế chiến lược cho một dự án, bạn cần bắt đầu từ việc đánh giá rõ ràng về tình hình hiện tại.

                                                                                                                                                                                                                                                                          1. Vẽ một BẢN ĐỒ NGỮ CẢNH. Bạn có thể vẽ một cái nhất quán, hay có những tình huống không rõ ràng?

                                                                                                                                                                                                                                                                          Chú ý đến việc sử dụng ngôn ngữ trong dự án. Có một NGÔN NGỮ PHỔ BIẾN không? Nó có đủ phong phú để hỗ trợ phát triển không?

                                                                                                                                                                                                                                                                          Hiểu điều gì là quan trọng. Có xác định LĨNH VỰC CỐT LÕI không? Có một TÂM NHÌN VỀ LĨNH VỰC không? Bạn có thể viết một cái không?

                                                                                                                                                                                                                                                                          Công nghệ của dự án có phù hợp hay cản trở cho MÔ HÌNH LÁI THIẾT KẾ không?

                                                                                                                                                                                                                                                                          Các nhà phát triển trong đội có những kỹ năng kỹ thuật cần thiết không?

                                                                                                                                                                                                                                                                          Các nhà phát triển có hiểu biết về lĩnh vực này không? Họ có quan tâm đến lĩnh vực này không?

                                                                                                                                                                                                                                                                          Bạn sẽ không tìm thấy câu trả lời hoàn hảo, tất nhiên. Hiện tại bạn biết ít hơn về dự án này hơn bất kỳ lúc nào trong tương lai. Nhưng những câu hỏi này sẽ cho bạn một điểm khởi đầu vững chắc. Khi bạn có những câu trả lời cụ thể ban đầu cho những câu hỏi này, bạn sẽ bắt đầu có cái nhìn sâu sắc vào những gì cấp bách nhất cần phải làm. Khi thời gian trôi qua, bạn có thể tinh chỉnh các câu trả lời - đặc biệt là BẢN ĐỒ BỐ CỤC, TÀI LIỆU TẦM NHÌN MIỀN và bất kỳ tài liệu nào khác mà bạn đã tạo ra - để phản ánh các tình huống đã thay đổi và những cái nhìn mới.


                                                                                                                                                                                                                                                                            Who Sets the Strategy?

                                                                                                                                                                                                                                                                            Theo truyền thống, kiến trúc được truyền lại, được tạo ra trước khi bắt đầu phát triển ứng dụng, bởi một nhóm có quyền lực hơn trong tổ chức so với nhóm phát triển ứng dụng. Nhưng không nhất thiết phải như vậy. Cách đó thường không hoạt động tốt.

                                                                                                                                                                                                                                                                            Thiết kế chiến lược, theo định nghĩa, phải được áp dụng xuyên suốt dự án. Có nhiều cách để tổ chức một dự án, và tôi không muốn đưa ra quá nhiều quy tắc. Tuy nhiên, để bất kỳ quy trình ra quyết định nào có hiệu quả, cần một số nguyên tắc cơ bản.

                                                                                                                                                                                                                                                                            Đầu tiên, hãy nhanh chóng xem qua hai phong cách mà tôi đã thấy mang lại giá trị trong thực tiễn (do đó bỏ qua phong cách "thông thái từ trên cao").

                                                                                                                                                                                                                                                                            Emergent Structure from Application Development

                                                                                                                                                                                                                                                                            Một đội ngũ tự giác, gồm những người giao tiếp rất tốt, có thể hoạt động mà không cần quyền lực trung ương và tuân theo ĐẶT HÀNG ĐANG PHÁT TRIỂN để đạt được một tập hợp các nguyên tắc chung, để trật tự phát triển một cách tự nhiên, chứ không phải do mệnh lệnh.

                                                                                                                                                                                                                                                                            Đây là mô hình điển hình cho một đội ngũ Lập trình Cực đoan. Về lý thuyết, cấu trúc có thể xuất hiện hoàn toàn tự phát từ sự nhận thức của bất kỳ cặp lập trình nào. Thường thì, có một cá nhân hoặc một nhóm nhỏ trong đội ngũ có trách nhiệm giám sát về cấu trúc quy mô lớn giúp giữ cho cấu trúc thống nhất. Cách tiếp cận này hoạt động tốt, đặc biệt nếu như nhà lãnh đạo không chính thức đó là một nhà phát triển thực thụ—một người phân xử và giao tiếp, chứ không phải là nguồn ý tưởng duy nhất. Trong các đội ngũ Lập trình Cực đoan mà tôi đã thấy, sự lãnh đạo thiết kế chiến lược như vậy dường như đã xuất hiện một cách tự phát, thường là ở người huấn luyện viên. Dù ai là nhà lãnh đạo tự nhiên này, họ vẫn là một thành viên của đội ngũ phát triển. Điều đó có nghĩa là đội ngũ phát triển phải có ít nhất một vài người có trình độ đủ để đưa ra các quyết định thiết kế có thể ảnh hưởng đến toàn bộ dự án.

                                                                                                                                                                                                                                                                            Khi một cấu trúc quy mô lớn trải rộng qua nhiều nhóm, các nhóm liên kết chặt chẽ có thể bắt đầu hợp tác không chính thức. Trong tình huống như vậy, mỗi nhóm ứng dụng vẫn thực hiện các phát hiện dẫn đến ý tưởng cho một cấu trúc quy mô lớn, nhưng sau đó các tùy chọn cụ thể được thảo luận bởi ủy ban không chính thức, bao gồm các đại diện của các nhóm khác nhau. Sau khi đánh giá tác động của thiết kế, các thành viên có thể quyết định chấp nhận, điều chỉnh hoặc để nó lại trên bàn. Các nhóm cố gắng di chuyển cùng nhau trong mối liên kết lỏng lẻo này. Sắp xếp này có thể hoạt động khi có tương đối ít nhóm, khi tất cả đều cam kết phối hợp với nhau, khi khả năng thiết kế của họ tương đương, và khi nhu cầu cấu trúc của họ đủ tương đồng để được đáp ứng bởi một cấu trúc quy mô lớn duy nhất.

                                                                                                                                                                                                                                                                            A Customer Focused Architecture Team

                                                                                                                                                                                                                                                                            Khi một chiến lược được chia sẻ giữa nhiều đội, sự tập trung hóa trong việc ra quyết định dường như có vẻ hấp dẫn. Mô hình thất bại của kiến trúc sư trên tháp ngà không phải là khả năng duy nhất. Một đội ngũ kiến trúc có thể đóng vai trò như một đồng nghiệp với các đội ứng dụng khác, giúp phối hợp và harmonize cấu trúc quy mô lớn cũng như các giới hạn BOUNDED CONTEXT và các vấn đề kỹ thuật khác giữa các đội. Để có thể hữu ích trong điều này, họ phải có tư duy chú trọng vào phát triển ứng dụng.

                                                                                                                                                                                                                                                                            Trong sơ đồ tổ chức, đội ngũ này có thể trông giống như đội ngũ kiến trúc truyền thống, nhưng thực sự khác biệt ở mọi hoạt động. Các thành viên trong nhóm là những người cộng tác thực sự với phát triển, khám phá các mô hình cùng với các lập trình viên, thử nghiệm với nhiều nhóm khác nhau để đạt được sự tinh chế, và sẵn sàng tham gia trực tiếp vào công việc.

                                                                                                                                                                                                                                                                            Tôi đã thấy tình huống này vài lần, khi một dự án kết thúc với một kiến trúc sư chính người làm hầu hết các công việc trong danh sách sau.


                                                                                                                                                                                                                                                                              Six Essentials for Strategic Design Decision Making

                                                                                                                                                                                                                                                                              Decisions must reach the entire team

                                                                                                                                                                                                                                                                              Rõ ràng, nếu mọi người không biết đến chiến lược và không tuân theo nó, thì nó không còn ý nghĩa. Yêu cầu này dẫn đến việc mọi người tổ chức xung quanh các nhóm kiến trúc tập trung với "quyền lực" chính thức—để cùng một quy tắc sẽ được áp dụng ở khắp mọi nơi. Thật châm biếm, các kiến trúc sư trong tháp ngà thường bị bỏ qua hoặc bị vượt qua. Các nhà phát triển không có sự lựa chọn nào khi sự thiếu phản hồi của các kiến trúc sư từ các nỗ lực thực tế để áp dụng quy tắc của chính họ vào các ứng dụng thực tế dẫn đến các kế hoạch không khả thi.

                                                                                                                                                                                                                                                                              Trong một dự án có sự giao tiếp rất tốt, một thiết kế chiến lược xuất phát từ nhóm ứng dụng có thể thực sự tiếp cận tất cả mọi người một cách hiệu quả hơn. Chiến lược này sẽ có tính liên quan và sẽ có thẩm quyền gắn liền với các quyết định thông minh của cộng đồng.

                                                                                                                                                                                                                                                                              Dù hệ thống nào đi chăng nữa, hãy ít quan tâm đến quyền lực mà ban quản lý trao cho hơn là mối quan hệ thực tế mà các nhà phát triển có với chiến lược.

                                                                                                                                                                                                                                                                              The decision process must absorb feedback

                                                                                                                                                                                                                                                                              Việc tạo ra một nguyên tắc tổ chức, cấu trúc quy mô lớn hoặc tinh chế của sự tinh tế như vậy yêu cầu một sự hiểu biết thật sâu sắc về nhu cầu của dự án và các khái niệm trong lĩnh vực. Những người duy nhất có được độ sâu kiến thức đó là các thành viên trong đội ngũ phát triển ứng dụng. Điều này giải thích tại sao các kiến trúc ứng dụng được tạo ra bởi các đội ngũ kiến trúc lại hiếm khi có ích, mặc dù tài năng của nhiều kiến trúc sư là điều không thể bàn cãi.

                                                                                                                                                                                                                                                                              Khác với hạ tầng kỹ thuật và kiến trúc, thiết kế chiến lược không đòi hỏi phải viết nhiều mã, mặc dù nó ảnh hưởng đến tất cả các quá trình phát triển. Điều mà nó yêu cầu là sự tham gia của các đội ngũ phát triển ứng dụng. Một kiến trúc sư có kinh nghiệm có thể lắng nghe các ý tưởng đến từ nhiều đội và hỗ trợ sự phát triển của một giải pháp tổng quát.

                                                                                                                                                                                                                                                                              Một nhóm kiến trúc kỹ thuật mà tôi đã làm việc thực sự đã luân chuyển các thành viên của mình qua các đội phát triển ứng dụng khác nhau đang cố gắng sử dụng khuôn khổ của nó. Việc luân chuyển này đã mang lại cho nhóm kiến trúc kinh nghiệm thực tiễn về những thách thức mà các nhà phát triển đang đối mặt, đồng thời chuyển giao kiến thức về cách áp dụng những sắc thái của khuôn khổ. Thiết kế chiến lược cũng cần có một vòng phản hồi khép kín như vậy.

                                                                                                                                                                                                                                                                              The plan must allow for evolution

                                                                                                                                                                                                                                                                              Phát triển phần mềm hiệu quả là một quá trình rất năng động. Khi các quyết định ở cấp độ cao nhất được đặt ra một cách cứng nhắc, đội ngũ sẽ ít có lựa chọn hơn khi phải phản ứng với sự thay đổi. SỰ PHÁT TRIỂN THÍCH ỨNG tránh được cạm bẫy này bằng cách nhấn mạnh sự thay đổi liên tục đối với cấu trúc lớn theo sự thấu hiểu ngày càng sâu sắc.

                                                                                                                                                                                                                                                                              Khi quá nhiều quyết định thiết kế đã được định sẵn, đội ngũ phát triển có thể bị hạn chế, không có đủ linh hoạt để giải quyết các vấn đề mà họ được giao. Vì vậy, trong khi một nguyên tắc hòa hợp có thể có giá trị, nó phải phát triển và thay đổi cùng với sự tiến triển của dự án phát triển, và nó không được lấy quá nhiều quyền lực từ các lập trình viên ứng dụng, những người đã gặp đủ khó khăn trong công việc của họ.

                                                                                                                                                                                                                                                                              Với phản hồi mạnh mẽ, các đổi mới xuất hiện khi gặp phải những trở ngại trong việc xây dựng ứng dụng và khi khám phá ra những cơ hội bất ngờ.

                                                                                                                                                                                                                                                                              Architecture teams must not siphon off all the best and brightest

                                                                                                                                                                                                                                                                              Thiết kế ở cấp độ này yêu cầu sự tinh vi mà có thể đang thiếu hụt. Các nhà quản lý thường chuyển những lập trình viên có kỹ năng kỹ thuật xuất sắc nhất vào các đội kiến trúc và cơ sở hạ tầng, vì họ muốn tận dụng kỹ năng của những nhà thiết kế tiên tiến này. Về phần mình, các lập trình viên bị thu hút bởi cơ hội tạo ra ảnh hưởng rộng hơn hoặc làm việc trên những vấn đề "thú vị hơn". Và có một vị thế gắn liền với việc là thành viên của một đội ngũ tinh nhuệ.

                                                                                                                                                                                                                                                                              Những lực lượng này thường chỉ để lại những nhà phát triển ít kỹ thuật nhất để thực sự xây dựng ứng dụng. Nhưng việc xây dựng ứng dụng tốt yêu cầu kỹ năng thiết kế; đây là một cài đặt cho sự thất bại. Ngay cả khi một đội ngũ chiến lược tạo ra một thiết kế chiến lược tuyệt vời, đội ngũ phát triển ứng dụng sẽ không có đủ sự tinh vi trong thiết kế để thực hiện nó.

                                                                                                                                                                                                                                                                              Ngược lại, những đội ngũ như vậy gần như không bao giờ bao gồm nhà phát triển, người có thể có kỹ năng thiết kế yếu hơn nhưng lại có kinh nghiệm phong phú nhất trong lĩnh vực đó. Thiết kế chiến lược không phải là một nhiệm vụ thuần túy kỹ thuật; việc tách mình ra khỏi các nhà phát triển có kiến thức sâu về lĩnh vực khiến nỗ lực của các kiến trúc sư gặp khó khăn hơn. Và các chuyên gia trong lĩnh vực cũng được cần đến.

                                                                                                                                                                                                                                                                              Rất quan trọng phải có những nhà thiết kế xuất sắc trong tất cả các nhóm ứng dụng. Rất quan trọng phải có kiến thức về lĩnh vực trong bất kỳ nhóm nào cố gắng thực hiện thiết kế chiến lược. Có thể cần phải thuê thêm những nhà thiết kế có trình độ cao hơn. Có thể giúp ích nếu giữ cho các nhóm kiến trúc làm việc bán thời gian. Tôi chắc chắn có nhiều cách làm hiệu quả, nhưng bất kỳ nhóm chiến lược hiệu quả nào cũng phải có một nhóm ứng dụng hiệu quả làm đối tác.

                                                                                                                                                                                                                                                                              Strategic design requires minimalism and humility

                                                                                                                                                                                                                                                                              Chưng cất và chủ nghĩa tối giản là điều thiết yếu cho bất kỳ công việc thiết kế tốt nào, nhưng chủ nghĩa tối giản lại càng quan trọng hơn cho thiết kế chiến lược. Ngay cả những lỗi nhỏ nhất cũng có tiềm năng khủng khiếp để cản trở. Các nhóm kiến trúc phải đặc biệt cẩn thận vì họ ít cảm nhận được các trở ngại mà họ có thể đặt ra trước các nhóm ứng dụng. Cùng lúc đó, sự nhiệt huyết của các kiến trúc sư đối với trách nhiệm chính của họ khiến họ dễ dàng bị cuốn đi. Tôi đã thấy hiện tượng này nhiều lần, và tôi cũng đã từng trải qua. Một ý tưởng hay dẫn đến một ý tưởng khác, và cuối cùng chúng ta có một kiến trúc quá phức tạp mà lại phản tác dụng.

                                                                                                                                                                                                                                                                              Thay vào đó, chúng ta phải kỷ luật bản thân để phát triển các nguyên tắc tổ chức và các mô hình cốt lõi được đơn giản hóa, chỉ chứa đựng những yếu tố thật sự cải thiện đáng kể độ rõ ràng của thiết kế. Sự thật là, gần như mọi thứ đều cản trở điều gì đó, vì vậy mỗi yếu tố đều phải xứng đáng. Nhận ra rằng ý tưởng tốt nhất của bạn có thể cản đường người khác đòi hỏi sự khiêm tốn.

                                                                                                                                                                                                                                                                              Objects are specialists; developers are generalists

                                                                                                                                                                                                                                                                              Bản chất của thiết kế đối tượng tốt là giao cho mỗi đối tượng một trách nhiệm rõ ràng và hẹp, và giảm thiểu sự phụ thuộc lẫn nhau đến mức tối thiểu. Đôi khi, chúng ta cố gắng làm cho các tương tác trong các nhóm gọn gàng như chúng nên có trong phần mềm của chúng ta. Một dự án tốt có nhiều người lấn vào chuyện của người khác. Các nhà phát triển chơi với các khung. Các kiến trúc sư viết mã ứng dụng. Mọi người nói chuyện với nhau. Đó là một sự hỗn loạn hiệu quả. Hãy để các đối tượng trở thành những chuyên gia; hãy để các nhà phát triển trở thành những người tổng quát.

                                                                                                                                                                                                                                                                              Bởi vì tôi đã phân biệt giữa thiết kế chiến lược và các loại thiết kế khác để giúp làm rõ các nhiệm vụ liên quan, tôi phải chỉ ra rằng việc có hai loại hoạt động thiết kế không có nghĩa là có hai loại người. Việc tạo ra một thiết kế linh hoạt dựa trên một mô hình sâu là một hoạt động thiết kế tiên tiến, nhưng các chi tiết thì rất quan trọng đến mức nó phải được thực hiện bởi ai đó làm việc với mã nguồn. Thiết kế chiến lược xuất phát từ thiết kế ứng dụng, tuy nhiên, nó cần một cái nhìn tổng thể về hoạt động, có thể trải dài qua nhiều đội ngũ. Mọi người thích tìm cách phân chia nhiệm vụ để các chuyên gia thiết kế không cần phải hiểu biết về kinh doanh và các chuyên gia trong lĩnh vực không cần phải hiểu công nghệ. Có một giới hạn về mức độ mà một cá nhân có thể học hỏi, nhưng việc chuyên môn hóa quá mức sẽ làm giảm tính hiệu quả của thiết kế dựa trên miền.

                                                                                                                                                                                                                                                                              The Same Goes for the Technical Frameworks

                                                                                                                                                                                                                                                                              Các khung công nghệ có thể tăng tốc đáng kể quy trình phát triển ứng dụng, bao gồm cả lớp miền, bằng cách cung cấp một lớp hạ tầng giải phóng ứng dụng khỏi việc triển khai các dịch vụ cơ bản, và bằng cách giúp cách ly miền khỏi các mối quan tâm khác. Tuy nhiên, có một rủi ro là kiến trúc có thể can thiệp vào việc triển khai biểu đạt của mô hình miền và việc thay đổi dễ dàng. Điều này có thể xảy ra ngay cả khi các nhà thiết kế khung không có ý định tham gia vào các lớp miền hoặc ứng dụng.

                                                                                                                                                                                                                                                                              Những thiên kiến tương tự mà hạn chế các khuyết điểm của thiết kế chiến lược có thể giúp ích cho kiến trúc kỹ thuật. Sự phát triển, chủ nghĩa tối giản và sự tham gia với đội ngũ phát triển ứng dụng có thể dẫn đến một tập hợp các dịch vụ và quy tắc được tinh chỉnh liên tục mà thực sự hỗ trợ phát triển ứng dụng mà không cản trở. Những kiến trúc không đi theo con đường này sẽ hoặc là kìm hãm sự sáng tạo của phát triển ứng dụng hoặc sẽ tìm cách bị lách, để lại cho phát triển ứng dụng, về mặt thực tiễn, không có kiến trúc nào cả.

                                                                                                                                                                                                                                                                              Có một thái độ nhất định sẽ chắc chắn làm hỏng một khuôn khổ.

                                                                                                                                                                                                                                                                              Don't write frameworks for dummies

                                                                                                                                                                                                                                                                              Các bộ phận trong đội ngũ cho rằng một số lập trình viên không đủ thông minh để thiết kế thường sẽ thất bại vì họ đánh giá thấp độ khó trong việc phát triển ứng dụng. Nếu những người đó không đủ thông minh để thiết kế, họ không nên được giao nhiệm vụ phát triển phần mềm. Nếu họ đủ thông minh, thì những nỗ lực chiều chuộng họ chỉ tạo ra rào cản giữa họ và các công cụ họ cần.

                                                                                                                                                                                                                                                                              Thái độ này cũng làm hỏng mối quan hệ giữa các đội. Tôi đã từng tham gia vào những đội ngũ kiêu ngạo như vậy và thường xuyên phải xin lỗi các lập trình viên trong mọi cuộc trò chuyện, cảm thấy xấu hổ vì sự liên kết của mình. (Tôi e rằng mình chưa bao giờ có thể thay đổi được một đội như vậy.)

                                                                                                                                                                                                                                                                              Bây giờ, việc đóng gói các chi tiết kỹ thuật không liên quan hoàn toàn khác với loại việc đóng gói trước mà tôi đang chỉ trích. Một khung (framework) có thể mang đến những trừu tượng và công cụ mạnh mẽ cho các lập trình viên, giải phóng họ khỏi những công việc tẻ nhạt. Thật khó để mô tả sự khác biệt này một cách tổng quát, nhưng bạn có thể nhận ra sự khác biệt bằng cách hỏi các nhà thiết kế khung họ mong đợi gì từ người sẽ sử dụng công cụ/khung/thành phần đó. Nếu các nhà thiết kế có vẻ có sự tôn trọng cao đối với người sử dụng khung, thì họ có khả năng đang đi đúng hướng.

                                                                                                                                                                                                                                                                              Beware the Master Plan

                                                                                                                                                                                                                                                                              Một nhóm kiến trúc sư (cái kiểu thiết kế các tòa nhà vật lý), do Christopher Alexander dẫn đầu, là những người ủng hộ việc phát triển từng phần trong lĩnh vực kiến trúc và quy hoạch đô thị. Họ đã giải thích rất rõ ràng lý do tại sao các kế hoạch tổng thể thất bại.

                                                                                                                                                                                                                                                                              Nếu không có một quá trình lập kế hoạch nào đó, thì chẳng có điều gì trên thế giới có thể khiến Đại học Oregon có được một trật tự nào gần gũi với sự sâu sắc và hòa hợp như trật tự đang tồn tại ở Đại học Cambridge.

                                                                                                                                                                                                                                                                              Kế hoạch tổng thể đã trở thành cách tiếp cận thông thường để giải quyết khó khăn này. Kế hoạch tổng thể cố gắng thiết lập đủ hướng dẫn để đảm bảo tính nhất quán trong môi trường nói chung - và vẫn để lại sự tự do cho các tòa nhà và không gian mở cá nhân thích ứng với nhu cầu địa phương.

                                                                                                                                                                                                                                                                              . . . và tất cả các phần khác nhau của trường đại học tương lai này sẽ tạo thành một tổng thể nhất quán, vì chúng được cắm vào các khe của thiết kế.

                                                                                                                                                                                                                                                                              ... trên thực tế, các quy hoạch tổng thể thường thất bại - vì chúng tạo ra trật tự toàn trị, chứ không phải trật tự hữu cơ. Chúng quá cứng nhắc; không thể dễ dàng thích ứng với những thay đổi tự nhiên và khó lường mà chắc chắn sẽ xảy ra trong đời sống của một cộng đồng. Khi những thay đổi này xảy ra... quy hoạch tổng thể trở nên lỗi thời và không còn được tuân theo nữa. Và ngay cả khi các quy hoạch tổng thể được tuân theo... chúng cũng không chỉ rõ đủ về sự kết nối giữa các tòa nhà, quy mô con người, chức năng cân bằng, v.v., để giúp mỗi hành động xây dựng và thiết kế địa phương trở nên liên quan chặt chẽ với môi trường tổng thể.

                                                                                                                                                                                                                                                                              Sự cố gắng để điều hướng một con đường như vậy giống như tô màu trong một cuốn sách tô màu của trẻ em. Tốt nhất, trật tự mà kết quả từ quá trình này mang lại là nhàm chán.

                                                                                                                                                                                                                                                                              Vì vậy, như một nguồn của trật tự hữu cơ, một kế hoạch tổng thể vừa quá chính xác, vừa không đủ chính xác. Tổng thể thì quá chính xác: các chi tiết thì không đủ chính xác.

                                                                                                                                                                                                                                                                              ... sự tồn tại của một kế hoạch tổng thể khiến người dùng cảm thấy bị tách rời [bởi vì, theo định nghĩa] các thành viên trong cộng đồng có ít ảnh hưởng đến hình dạng tương lai của cộng đồng của họ vì hầu hết các quyết định quan trọng đã được đưa ra.

                                                                                                                                                                                                                                                                              Từ Cuộc Thí Nghiệm Oregon, trang 16–28 (Alexander và cộng sự 1975)

                                                                                                                                                                                                                                                                              Alexander và các đồng nghiệp của ông đã đề xuất một bộ nguyên tắc cho tất cả các thành viên trong cộng đồng áp dụng cho mọi hành động phát triển từng phần, để "trật tự hữu cơ" xuất hiện, được điều chỉnh tốt với hoàn cảnh.


                                                                                                                                                                                                                                                                                Conclusion

                                                                                                                                                                                                                                                                                Hồi kết

                                                                                                                                                                                                                                                                                Mong đợi


                                                                                                                                                                                                                                                                                Epilogues

                                                                                                                                                                                                                                                                                Mặc dù việc làm trên một dự án tiên tiến và thử nghiệm những ý tưởng và công cụ thú vị rất thỏa mãn, nhưng đối với tôi, đó là một trải nghiệm trống rỗng nếu phần mềm không được sử dụng một cách hiệu quả. Thực tế, bài kiểm tra thành công thực sự là cách mà phần mềm phục vụ theo thời gian. Tôi đã có thể theo dõi câu chuyện của một số dự án trước đây của mình trong nhiều năm qua.

                                                                                                                                                                                                                                                                                Tôi sẽ thảo luận ở đây về năm trong số đó, mỗi cái đã nỗ lực nghiêm túc trong việc thiết kế theo miền, mặc dù không có hệ thống và không theo cái tên đó, dĩ nhiên. Tất cả các dự án này đều đã cung cấp phần mềm: một số đã thành công trong việc thực hiện và sản xuất một thiết kế dựa trên mô hình, trong khi một dự án đã trượt khỏi con đường đó. Một số ứng dụng tiếp tục phát triển và thay đổi trong nhiều năm, trong khi một cái thì trì trệ và một cái chết trẻ.

                                                                                                                                                                                                                                                                                Phần mềm thiết kế PCB được mô tả trong Chương 1 đã nhận được sự đón nhận nồng nhiệt từ những người dùng beta trong lĩnh vực. Đáng tiếc, công ty khởi nghiệp đã khởi xướng dự án này hoàn toàn thất bại trong chức năng tiếp thị và cuối cùng đã bị giải thể. Phần mềm hiện nay được sử dụng bởi một vài kỹ sư PCB có những bản sao cũ mà họ giữ lại từ chương trình beta. Giống như bất kỳ phần mềm không có người chăm sóc nào, nó sẽ tiếp tục hoạt động cho đến khi có sự thay đổi nghiêm trọng nào đó trong một trong những chương trình mà nó được tích hợp.

                                                                                                                                                                                                                                                                                Phần mềm cho vay mà câu chuyện được kể trong Chương 9 đã phát triển và tiến hóa theo cùng một hướng trong suốt ba năm sau bước đột phá mà tôi đã viết về. Vào thời điểm đó, dự án đã được tách ra thành một công ty độc lập. Trong cuộc khủng hoảng của sự tái tổ chức này, người quản lý dự án đã dẫn dắt dự án từ ban đầu đã bị loại bỏ, và một số nhà phát triển cốt lõi đã rời bỏ cùng với ông. Đội ngũ mới có một triết lý thiết kế hơi khác, không cam kết hoàn toàn với việc mô hình hóa đối tượng. Tuy nhiên, họ vẫn duy trì một lớp miền riêng biệt với hành vi phức tạp và tiếp tục đánh giá cao kiến thức miền trong đội phát triển. Bảy năm sau khi tách ra, phần mềm tiếp tục được cải tiến với các tính năng mới. Đây là ứng dụng dẫn đầu trong lĩnh vực của nó và phục vụ một số lượng ngày càng tăng các tổ chức khách hàng, cũng như là nguồn doanh thu lớn nhất cho công ty.

                                                                                                                                                                                                                                                                                Một vườn ô liu mới trồng

                                                                                                                                                                                                                                                                                graphics/ap01inf01.gif

                                                                                                                                                                                                                                                                                Cho đến khi phương pháp dựa trên miền trở nên phổ biến hơn, phần mềm thú vị trên nhiều dự án sẽ được xây dựng trong một khoảng thời gian ngắn, hiệu suất cao. Cuối cùng, dự án sẽ chuyển biến thành một thứ gì đó truyền thống hơn mà có thể không khai thác hoàn toàn, chưa nói đến việc nâng cao, sức mạnh của những mô hình sâu mà đã được chắt lọc trước đó. Tôi ước có nhiều hơn thế, nhưng thực sự đó là những thành công mang lại giá trị bền vững cho người dùng trong nhiều năm.

                                                                                                                                                                                                                                                                                Trong một dự án, tôi đã phối hợp với một nhà phát triển khác để viết một tiện ích mà khách hàng cần nhằm tạo ra sản phẩm cốt lõi của họ. Các tính năng khá phức tạp và kết hợp theo những cách tinh vi. Tôi rất thích công việc trong dự án này và chúng tôi đã tạo ra một thiết kế linh hoạt với một CỐT LÕI TRỪU TƯỢNG. Khi phần mềm này được chuyển giao, đó là kết thúc sự tham gia của tất cả những người đã phát triển nó ban đầu. Bởi vì đây là một sự chuyển giao đột ngột, tôi đã dự đoán rằng các tính năng thiết kế hỗ trợ các yếu tố kết hợp có thể gây nhầm lẫn và có thể được thay thế bằng logic trường hợp điển hình hơn. Điều này không xảy ra ngay lập tức. Khi chúng tôi chuyển giao, gói sản phẩm bao gồm một bộ kiểm tra toàn diện và một tài liệu tóm lược. Các thành viên mới trong nhóm đã sử dụng tài liệu đó để hướng dẫn những khám phá của họ, và khi họ xem xét mọi thứ, họ trở nên hào hứng với những khả năng mà thiết kế mang lại. Khi tôi nghe thấy những bình luận của họ một năm sau, tôi nhận ra rằng NGÔN NGỮ PHỔ BIẾN đã lan tỏa sang nhóm khác và tiếp tục sống, tiếp tục phát triển.

                                                                                                                                                                                                                                                                                Bảy năm sau

                                                                                                                                                                                                                                                                                graphics/ap01inf02.gif

                                                                                                                                                                                                                                                                                Một năm sau, tôi nghe một câu chuyện khác. Nhóm đã gặp phải những yêu cầu mới mà các nhà phát triển không thấy cách nào để hoàn thành trong thiết kế kế thừa. Họ đã buộc phải thay đổi thiết kế gần như không còn nhận ra. Khi tôi khai thác thêm chi tiết, tôi có thể thấy rằng các khía cạnh trong mô hình của chúng tôi sẽ khiến việc giải quyết những vấn đề đó trở nên khó khăn. Chính trong những khoảnh khắc như vậy, một bước đột phá để có được một mô hình sâu hơn thường là có thể, đặc biệt là khi, như trong trường hợp này, các nhà phát triển đã tích lũy được kiến thức và kinh nghiệm sâu sắc trong lĩnh vực đó. Trên thực tế, họ đã có một đợt bùng nổ những hiểu biết mới và cuối cùng đã chuyển đổi mô hình và thiết kế dựa trên những hiểu biết đó.

                                                                                                                                                                                                                                                                                Họ kể cho tôi câu chuyện này một cách cẩn thận, khéo léo, có lẽ họ mong rằng tôi sẽ cảm thấy thất vọng khi thấy họ loại bỏ nhiều công việc của tôi như vậy. Tôi không quá tình cảm về các thiết kế của mình. Thành công của một thiết kế không nhất thiết được đánh dấu bởi sự tĩnh lặng của nó. Lấy một hệ thống mà mọi người phụ thuộc vào, làm cho nó trở nên khó hiểu, và nó sẽ sống mãi như một di sản không thể chạm tới. Một mô hình sâu cho phép tầm nhìn rõ ràng có thể mang lại hiểu biết mới, trong khi một thiết kế linh hoạt tạo điều kiện cho sự thay đổi liên tục. Mô hình mà họ đưa ra là sâu hơn, phù hợp hơn với những mối quan tâm thực sự của người dùng. Thiết kế của họ đã giải quyết những vấn đề thực sự. Bản chất của phần mềm là thay đổi, và chương trình này đã tiếp tục phát triển trong tay của đội ngũ sở hữu nó.

                                                                                                                                                                                                                                                                                Các ví dụ về vận chuyển rải rác trong cuốn sách được dựa lỏng lẻo vào một dự án cho một công ty vận chuyển container quốc tế lớn. Ngay từ đầu, ban lãnh đạo của dự án đã cam kết với một phương pháp tiếp cận dựa trên miền, nhưng họ không bao giờ tạo ra một văn hóa phát triển có thể hoàn toàn hỗ trợ nó. Nhiều đội ngũ với các mức độ kỹ năng thiết kế và kinh nghiệm đối tượng khác nhau đã bắt tay vào việc tạo ra các mô-đun, được phối hợp lỏng lẻo thông qua sự hợp tác không chính thức giữa các lãnh đạo đội và bởi một nhóm kiến trúc tập trung vào khách hàng. Chúng tôi đã phát triển một mô hình khá sâu về MIỀN CỐT LÕI, và đã có một NGÔN NGỮ PHỔ QUÁT khả thi.

                                                                                                                                                                                                                                                                                Tuy nhiên, văn hóa công ty đã kiên quyết phản đối phát triển lặp đi lặp lại, và chúng tôi đã chờ đợi quá lâu để đưa ra một bản phát hành nội bộ hoạt động. Do đó, các vấn đề đã được phát hiện ở giai đoạn muộn, khi mà việc sửa chữa chúng trở nên rủi ro và tốn kém hơn. Đến một thời điểm nào đó, chúng tôi phát hiện ra một số khía cạnh cụ thể của mô hình đang gây ra vấn đề về hiệu suất trong cơ sở dữ liệu. Một phần tự nhiên của THIẾT KẾ DỰA TRÊN MÔ HÌNH là phản hồi từ các vấn đề thực hiện đến việc thay đổi mô hình, nhưng vào thời điểm đó, có một cảm nhận rằng chúng tôi đã đi quá xa để thay đổi mô hình cơ bản. Thay vào đó, các thay đổi đã được thực hiện đối với mã nguồn để làm cho nó hiệu quả hơn, và sự kết nối của nó với mô hình đã bị yếu đi. Bản phát hành ban đầu cũng đã làm lộ ra những hạn chế về quy mô trong hạ tầng kỹ thuật đã khiến ban quản lý lo lắng. Chuyên gia đã được mời đến để giải quyết các vấn đề hạ tầng, và dự án đã phục hồi. Nhưng vòng kết nối giữa thực hiện và mô hình miền chưa bao giờ được khép lại.

                                                                                                                                                                                                                                                                                Một vài nhóm đã phát triển phần mềm chất lượng cao với các khả năng phức tạp và mô hình biểu cảm. Những nhóm khác lại cung cấp phần mềm cứng nhắc đã giảm mô hình thành cấu trúc dữ liệu, mặc dù ngay cả họ cũng vẫn giữ lại những dấu vết của NGÔN NGỮ PHỔ BIẾN. Có lẽ một BẢN ĐỒ NGŨ HÀNH sẽ giúp chúng tôi nhiều như bất kỳ điều gì khác, vì mối quan hệ giữa sản phẩm của các nhóm khác nhau là ngẫu nhiên. Tuy nhiên, mô hình CỐT LÕI đó, được thể hiện trong NGÔN NGỮ PHỔ BIẾN, đã giúp các nhóm cuối cùng gắn kết lại thành một hệ thống.

                                                                                                                                                                                                                                                                                Mặc dù phạm vi bị giảm, dự án đã thay thế một số hệ thống kế thừa. Tất cả được kết nối với nhau bằng một bộ khái niệm chung, mặc dù hầu hết thiết kế không được linh hoạt lắm. Bản thân nó giờ đây đã phần nào hóa đá thành di sản, nhiều năm sau, nhưng vẫn phục vụ cho doanh nghiệp toàn cầu 24 giờ một ngày. Mặc dù ảnh hưởng của các nhóm thành công hơn đã lan rộng dần, nhưng thời gian cuối cùng cũng cạn kiệt, ngay cả trong công ty giàu có nhất. Văn hóa của dự án chưa bao giờ thật sự tiếp nhận THIẾT KẾ HƯỚNG MÔ HÌNH. Phát triển mới ngày nay diễn ra trên các nền tảng khác nhau và chỉ bị ảnh hưởng gián tiếp bởi công việc mà chúng tôi đã thực hiện - khi các nhà phát triển mới CĂN CỨ vào di sản của họ.

                                                                                                                                                                                                                                                                                Trong một số lĩnh vực, những mục tiêu tham vọng như những gì công ty vận tải đã đặt ra ban đầu đã bị coi thường. Có vẻ tốt hơn khi thực hiện những ứng dụng nhỏ mà chúng ta biết cách thực hiện. Tốt hơn là tuân theo tiêu chuẩn tối thiểu của thiết kế để thực hiện những điều đơn giản. Cách tiếp cận bảo thủ này có vị trí của nó và cho phép thực hiện các dự án có phạm vi rõ ràng và phản ứng nhanh. Nhưng các hệ thống mô hình tích hợp hứa hẹn giá trị mà những mảnh ghép đó không thể mang lại. Có một cách thứ ba. Thiết kế hướng miền cho phép phát triển từng phần của các hệ thống lớn với chức năng phong phú, bằng cách xây dựng trên một mô hình sâu sắc và thiết kế linh hoạt.

                                                                                                                                                                                                                                                                                Tôi sẽ kết thúc danh sách này với Evant, một công ty phát triển phần mềm quản lý tồn kho, nơi tôi đóng một vai trò hỗ trợ thứ cấp và đóng góp vào một văn hóa thiết kế đã rất mạnh mẽ. Những người khác đã viết về dự án này như một ví dụ điển hình của Lập trình Tối ưu Cực, nhưng điều không thường được nhắc đến là dự án này có tính chất định hướng theo miền rất cao. Những mô hình càng sâu sắc hơn được chưng cất và thể hiện trong những thiết kế ngày càng linh hoạt hơn. Dự án này phát triển mạnh mẽ cho đến khi sự sụp đổ "dot com" năm 2001. Sau đó, thiếu hụt nguồn vốn đầu tư, công ty thu hẹp lại, phát triển phần mềm gần như ngừng lại, và có vẻ như kết thúc đã cận kề. Nhưng vào mùa hè năm 2002, Evant đã được tiếp cận bởi một trong mười nhà bán lẻ hàng đầu thế giới. Khách hàng tiềm năng này thích sản phẩm, nhưng cần có những thay đổi về thiết kế để cho phép ứng dụng mở rộng cho một hoạt động lập kế hoạch tồn kho khổng lồ. Đây là cơ hội cuối cùng của Evant.

                                                                                                                                                                                                                                                                                Mặc dù được giảm xuống chỉ còn bốn nhà phát triển, nhóm vẫn có những tài sản. Họ có kỹ năng, am hiểu về lĩnh vực, và một thành viên có chuyên môn về các vấn đề mở rộng. Họ có một văn hóa phát triển rất hiệu quả. Và họ có một mã nguồn với thiết kế linh hoạt, tạo điều kiện cho sự thay đổi. Mùa hè đó, bốn nhà phát triển đã nỗ lực phát triển heroically, dẫn đến khả năng xử lý hàng tỷ yếu tố lập kế hoạch và hàng trăm người dùng. Dựa vào những khả năng đó, Evant đã giành được khách hàng khổng lồ và không lâu sau, đã bị mua lại bởi một công ty khác muốn tận dụng phần mềm và khả năng đã được chứng minh của họ để đáp ứng các yêu cầu mới.

                                                                                                                                                                                                                                                                                Văn hóa thiết kế theo miền (cũng như văn hóa Lập trình cực đoan) đã vượt qua giai đoạn chuyển tiếp và được làm mới. Ngày nay, mô hình và thiết kế tiếp tục phát triển, phong phú và linh hoạt hơn rất nhiều so với hai năm trước khi tôi thực hiện đóng góp của mình. Và thay vì bị assimil vào công ty mua lại, các thành viên của đội Evant dường như đang truyền cảm hứng cho các nhóm dự án hiện có của công ty để làm theo họ. Câu chuyện này vẫn chưa kết thúc.

                                                                                                                                                                                                                                                                                Không có dự án nào sẽ sử dụng mọi kỹ thuật trong cuốn sách này. Dù vậy, bất kỳ dự án nào cam kết với thiết kế hướng miền sẽ được nhận diện bằng một số điểm khác biệt. Đặc điểm xác định là ưu tiên hiểu rõ miền mục tiêu và kết hợp hiểu biết đó vào phần mềm. Mọi thứ khác xuất phát từ tiền đề đó. Các thành viên trong nhóm đều nhận thức được việc sử dụng ngôn ngữ trong dự án và trau dồi sự tinh tế của nó. Họ khó hài lòng với chất lượng của mô hình miền, vì họ luôn học hỏi thêm về miền. Họ coi việc tinh chỉnh liên tục là một cơ hội và một mô hình không phù hợp là một rủi ro. Họ xem trọng kỹ năng thiết kế vì không dễ để phát triển phần mềm đạt chất lượng sản xuất mà phản ánh rõ ràng mô hình miền. Họ gặp phải trở ngại, nhưng vẫn giữ vững các nguyên tắc khi đứng dậy và tiếp tục tiến về phía trước.


                                                                                                                                                                                                                                                                                  Looking Forward

                                                                                                                                                                                                                                                                                  Thời tiết, hệ sinh thái và sinh học từng được coi là những lĩnh vực "mềm" và hỗn độn so với vật lý hay hóa học. Gần đây, tuy nhiên, mọi người đã nhận ra rằng sự xuất hiện của "sự hỗn độn" thực sự tạo ra một thách thức kỹ thuật sâu sắc để khám phá và hiểu được trật tự trong những hiện tượng rất phức tạp này. Lĩnh vực gọi là "phức tạp" đang dẫn đầu trong nhiều ngành khoa học. Mặc dù các nhiệm vụ thuần túy về công nghệ thường có vẻ thú vị và thách thức nhất đối với các kỹ sư phần mềm tài năng, nhưng thiết kế theo hướng miền mở ra một lĩnh vực thách thức mới mà ít nhất cũng ngang bằng. Phần mềm kinh doanh không nhất thiết phải là một mớ hỗn độn lắp ghép. Việc chế ngự một miền phức tạp thành một thiết kế phần mềm dễ hiểu là một thách thức thú vị cho những người có kỹ năng kỹ thuật mạnh mẽ.

                                                                                                                                                                                                                                                                                  Chúng ta vẫn chưa đến thời kỳ mà những người không chuyên có thể tạo ra phần mềm phức tạp hoạt động hiệu quả. Những đội ngũ lập trình viên với kỹ năng cơ bản có thể sản xuất ra một số loại phần mềm nhất định, nhưng không phải loại phần mềm có thể cứu doanh nghiệp trong giờ phút quyết định. Điều cần thiết là các nhà phát triển công cụ phải đặt tâm huyết vào việc mở rộng sức mạnh và năng suất của các nhà phát triển phần mềm tài năng. Điều cần thiết là những cách khám phá mô hình miền sắc nét hơn và thể hiện chúng trong phần mềm hoạt động. Tôi rất mong được thử nghiệm với các công cụ và công nghệ mới được thiết kế cho mục đích này.

                                                                                                                                                                                                                                                                                  Nhưng mặc dù các công cụ được cải thiện sẽ rất hữu ích, chúng ta không nên bị phân tâm bởi chúng và mất đi tầm nhìn về thực tế cốt lõi rằng việc tạo ra phần mềm tốt là một hoạt động học hỏi và suy nghĩ. Mô hình hóa đòi hỏi trí tưởng tượng và kỷ luật tự giác. Các công cụ giúp chúng ta suy nghĩ hoặc tránh phân tâm là tốt. Nỗ lực tự động hóa những gì phải là sản phẩm của tư duy là ngây thơ và không hiệu quả.

                                                                                                                                                                                                                                                                                  Với các công cụ và công nghệ mà chúng ta đã có, chúng ta có thể xây dựng những hệ thống giá trị hơn nhiều so với hầu hết các dự án hiện tại. Chúng ta có thể viết phần mềm dễ sử dụng và dễ làm việc, phần mềm không giới hạn chúng ta khi nó phát triển mà còn tạo ra những cơ hội mới và tiếp tục mang lại giá trị cho chủ sở hữu.


                                                                                                                                                                                                                                                                                    Appendix The Use of Patterns in This Book

                                                                                                                                                                                                                                                                                    Chiếc "xe đẹp" đầu tiên của tôi, được tặng ngay sau khi tốt nghiệp đại học, là một chiếc Peugeot đã tám năm tuổi. Đôi khi được gọi là "Mercedes của Pháp," chiếc xe này được chế tạo rất tinh xảo, lái rất thích, và rất đáng tin cậy. Nhưng khi tôi nhận được nó, chiếc xe đã đến tuổi mà những vấn đề bắt đầu phát sinh và cần nhiều bảo trì hơn.

                                                                                                                                                                                                                                                                                    Peugeot là một công ty lâu đời, và nó đã đi theo con đường tiến hóa riêng của mình qua nhiều thập kỷ. Nó có hệ thống thuật ngữ cơ khí riêng, và các thiết kế của nó thì kỳ quặc; ngay cả việc phân chia chức năng thành các bộ phận cũng đôi khi không theo tiêu chuẩn. Kết quả là một chiếc xe mà chỉ những chuyên gia của Peugeot mới có thể sửa chữa, điều này có thể gây khó khăn cho ai đó với thu nhập của một sinh viên cao học.

                                                                                                                                                                                                                                                                                    Trong một dịp điển hình, tôi đã đưa xe đến một thợ sửa xe địa phương để kiểm tra một vết rò rỉ chất lỏng. Ông ấy đã kiểm tra gầm xe và nói với tôi rằng dầu đang "rò rỉ từ một cái hộp nhỏ khoảng hai phần ba hành trình về phía sau có vẻ như liên quan đến việc phân phối lực phanh giữa phía trước và phía sau." Sau đó, ông từ chối không động vào xe và khuyên tôi nên đến đại lý, cách đó năm mươi dặm. Ai cũng có thể sửa chữa một chiếc Ford hoặc Honda; đó là lý do tại sao những chiếc xe đó tiện lợi hơn và ít tốn kém hơn để sở hữu, mặc dù chúng cũng phức tạp về mặt cơ khí.

                                                                                                                                                                                                                                                                                    Tôi đã yêu chiếc xe đó, nhưng tôi sẽ không bao giờ sở hữu một chiếc xe kỳ quặc nữa. Có một ngày khi một vấn đề đặc biệt đắt tiền được chẩn đoán, và tôi đã đủ với những chiếc Peugeot. Tôi đã đưa nó đến một tổ chức từ thiện địa phương chấp nhận xe làm quyên góp. Sau đó, tôi đã mua một chiếc Honda Civic cũ kỹ với giá khoảng bằng chi phí sửa chữa.

                                                                                                                                                                                                                                                                                    Các yếu tố thiết kế chuẩn đang thiếu cho sự phát triển miền, vì vậy mỗi mô hình miền và triển khai tương ứng đều kỳ quặc và khó hiểu. Hơn nữa, mỗi đội ngũ đều phải phát minh lại bánh xe (hoặc bánh răng, hoặc cần gạt nước). Trong thế giới thiết kế đối tượng, mọi thứ đều là một đối tượng, một tham chiếu, hoặc một tin nhắn—điều này, tất nhiên, là một trừu tượng hữu ích. Nhưng điều đó không đủ để hạn chế phạm vi các lựa chọn thiết kế miền và không hỗ trợ một cuộc thảo luận kinh tế về mô hình miền.

                                                                                                                                                                                                                                                                                    Dừng lại ở câu "Mọi thứ đều là một đối tượng" giống như một thợ mộc hoặc kiến trúc sư tóm tắt các ngôi nhà bằng cách nói "Mọi thứ đều là một phòng." Sẽ có một phòng lớn với ổ cắm cao thế và một bồn rửa, nơi bạn có thể nấu ăn. Sẽ có một phòng nhỏ ở trên lầu, nơi bạn có thể ngủ. Sẽ tốn nhiều trang để mô tả một ngôi nhà bình thường. Những người xây dựng hoặc sử dụng nhà cửa nhận ra rằng các phòng tuân theo những mẫu hình, những mẫu hình có tên gọi đặc biệt, chẳng hạn như "bếp." Ngôn ngữ này giúp cho việc thảo luận về thiết kế nhà cửa trở nên hiệu quả hơn.

                                                                                                                                                                                                                                                                                    Hơn nữa, không phải tất cả các sự kết hợp của các chức năng đều thực tế. Tại sao không có một căn phòng nơi bạn vừa tắm vừa ngủ? Không phải sẽ tiện lợi hơn sao? Nhưng kinh nghiệm lâu dài đã hình thành thành thói quen, và chúng ta tách biệt "phòng ngủ" khỏi "phòng tắm." Cuối cùng, các tiện nghi tắm rửa thường được chia sẻ giữa nhiều người hơn phòng ngủ, và chúng cần sự riêng tư tối đa, ngay cả từ những người khác cùng chia sẻ phòng ngủ. Và các phòng tắm có yêu cầu cơ sở hạ tầng chuyên biệt và tốn kém. Bồn tắm và bồn cầu thường kết thúc trong cùng một phòng vì cả hai đều yêu cầu cùng một cơ sở hạ tầng (nước và thoát nước) và cả hai đều được sử dụng trong sự riêng tư.

                                                                                                                                                                                                                                                                                    Một phòng khác có yêu cầu cơ sở hạ tầng đặc biệt là phòng mà bạn có thể chuẩn bị bữa ăn, còn được biết đến với tên gọi "nhà bếp." Khác với phòng tắm, nhà bếp không có yêu cầu về sự riêng tư đặc biệt. Do chi phí cao, thường chỉ có một nhà bếp, ngay cả trong những ngôi nhà tương đối lớn. Sự độc nhất này cũng thuận lợi cho các phong tục chuẩn bị và ăn uống chung của chúng ta.

                                                                                                                                                                                                                                                                                    Khi tôi nói rằng tôi muốn một ngôi nhà có ba phòng ngủ, hai phòng tắm và một nhà bếp mở, tôi đã chứa đựng một khối lượng thông tin khổng lồ trong một câu ngắn gọn, và tôi đã tránh được nhiều sai lầm ngớ ngẩn—chẳng hạn như đặt một cái toilet cạnh tủ lạnh.

                                                                                                                                                                                                                                                                                    Trong từng lĩnh vực thiết kế—nhà ở, ô tô, thuyền rowboat, hoặc phần mềm—chúng ta xây dựng dựa trên các mẫu đã được chứng minh là hiệu quả trong quá khứ, cải biên trong các chủ đề đã được thiết lập. Đôi khi chúng ta phải phát minh ra một cái gì đó hoàn toàn mới. Nhưng bằng cách dựa trên các yếu tố tiêu chuẩn theo mẫu, chúng ta tránh lãng phí năng lượng vào những vấn đề có giải pháp đã biết để tập trung vào những nhu cầu đặc biệt của mình. Ngoài ra, việc xây dựng từ các mẫu thông thường giúp chúng ta tránh thiết kế quá đặc trưng đến mức khó giao tiếp.

                                                                                                                                                                                                                                                                                    Mặc dù thiết kế miền phần mềm chưa phát triển như các lĩnh vực thiết kế khác - và trong bất kỳ trường hợp nào có thể quá đa dạng để phù hợp với các mẫu cụ thể như những mẫu được sử dụng cho các bộ phận ô tô hoặc các phòng - nhưng vẫn cần phải tiến xa hơn "Mọi thứ đều là đối tượng" ít nhất là tương đương với việc phân biệt giữa đinh ốc và lò xo.

                                                                                                                                                                                                                                                                                    Một hình thức chia sẻ và chuẩn hóa hiểu biết thiết kế đã được giới thiệu vào những năm 1970 bởi một nhóm kiến trúc sư do Christopher Alexander dẫn dắt (Alexander et al. 1977). "Ngôn ngữ mẫu" của họ kết hợp những giải pháp thiết kế đã được thử nghiệm và chứng minh cho các vấn đề phổ biến (tinh tế hơn nhiều so với ví dụ "bếp" của tôi, điều này có thể khiến một số độc giả của Alexander cảm thấy khó chịu). Mục đích là các nhà thầu và người sử dụng sẽ giao tiếp bằng ngôn ngữ này, và họ sẽ được hướng dẫn bởi các mẫu để tạo ra những tòa nhà đẹp, hoạt động tốt và mang lại cảm giác dễ chịu cho những người sử dụng chúng.

                                                                                                                                                                                                                                                                                    Dù các kiến trúc sư có thể nghĩ gì về ý tưởng này, ngôn ngữ mẫu đã có ảnh hưởng lớn đến thiết kế phần mềm. Vào những năm 1990, các mẫu phần mềm đã được áp dụng theo nhiều cách với một số thành công, nổi bật là trong thiết kế chi tiết (Gamma et al. 1995) và kiến trúc kỹ thuật (Buschmann et al. 1996). Gần đây, các mẫu đã được sử dụng để tài liệu hóa các kỹ thuật thiết kế hướng đối tượng cơ bản (Larman 1998) và kiến trúc doanh nghiệp (Fowler 2002, Alur et al. 2001). Ngôn ngữ của các mẫu giờ đây là một kỹ thuật chính thống để tổ chức các ý tưởng thiết kế phần mềm.

                                                                                                                                                                                                                                                                                    Tên các mẫu được dự định trở thành các thuật ngữ trong ngôn ngữ của nhóm, và tôi đã sử dụng chúng theo cách đó trong cuốn sách này. Khi một tên mẫu xuất hiện trong cuộc thảo luận, nó được ĐỊNH DẠNG BẰNG CHỮ IN HOA NHỎ để được nhấn mạnh.

                                                                                                                                                                                                                                                                                    Dưới đây là cách tôi đã định dạng các mẫu trong cuốn sách này. Có một số biến thể xung quanh kế hoạch cơ bản này, vì tôi đã ưu tiên sự rõ ràng và dễ đọc theo từng trường hợp hơn là cấu trúc cứng nhắc.


                                                                                                                                                                                                                                                                                      Pattern Name

                                                                                                                                                                                                                                                                                      [Minh họa khái niệm. Đôi khi là phép ẩn dụ trực quan hoặc văn bản gợi cảm.]

                                                                                                                                                                                                                                                                                      [Ngữ cảnh. Một giải thích ngắn gọn về cách khái niệm này liên quan đến các mẫu khác. Trong một số trường hợp, một cái nhìn tổng quan ngắn gọn về mẫu.]

                                                                                                                                                                                                                                                                                      Tuy nhiên, nhiều phần thảo luận về bối cảnh trong cuốn sách này nằm ở phần giới thiệu chương và các đoạn nội dung khác, thay vì trong các mẫu.

                                                                                                                                                                                                                                                                                      ]

                                                                                                                                                                                                                                                                                      [Thảo luận về vấn đề.]

                                                                                                                                                                                                                                                                                      Tóm tắt vấn đề.

                                                                                                                                                                                                                                                                                      Thảo luận về việc giải quyết các lực vấn đề thành một giải pháp.

                                                                                                                                                                                                                                                                                      Do đó:

                                                                                                                                                                                                                                                                                      Tóm tắt giải pháp.

                                                                                                                                                                                                                                                                                      Hậu quả. Các yếu tố cần xem xét khi thực hiện. Ví dụ.

                                                                                                                                                                                                                                                                                      graphics/astric.gif graphics/astric.gif graphics/astric.gif

                                                                                                                                                                                                                                                                                      Ngữ cảnh kết quả: Một giải thích ngắn gọn về cách mà mẫu này dẫn đến các mẫu sau.

                                                                                                                                                                                                                                                                                      [Thảo luận về những thách thức trong việc thực hiện. Trong định dạng gốc của Alexander, thảo luận này sẽ được kết hợp vào phần mô tả cách giải quyết vấn đề, và tôi thường tuân theo cách tổ chức của Alexander trong cuốn sách này. Nhưng một số mẫu yêu cầu những thảo luận dài hơn về việc thực hiện. Để giữ cho phần thảo luận về mẫu trung tâm gọn gàng, tôi đã di chuyển những thảo luận dài về việc thực hiện ra ngoài, sau mẫu.]

                                                                                                                                                                                                                                                                                      Ngoài ra, các ví dụ dài, đặc biệt là những ví dụ kết hợp nhiều mô hình, thường nằm ngoài các mô hình.


                                                                                                                                                                                                                                                                                        GLOSSARY

                                                                                                                                                                                                                                                                                        Dưới đây là định nghĩa ngắn gọn của một số thuật ngữ, tên mẫu và các khái niệm khác được sử dụng trong cuốn sách.

                                                                                                                                                                                                                                                                                        AGGREGATE

                                                                                                                                                                                                                                                                                        Một cụm các đối tượng liên quan được coi là một đơn vị cho mục đích thay đổi dữ liệu. Các tham chiếu bên ngoài bị hạn chế đối với một thành viên của AGGREGATE, được chỉ định là gốc. Một bộ quy tắc nhất quán áp dụng trong ranh giới của AGGREGATE.



                                                                                                                                                                                                                                                                                        analysis pattern

                                                                                                                                                                                                                                                                                        Một nhóm khái niệm đại diện cho một cấu trúc chung trong mô hình kinh doanh. Nó có thể chỉ liên quan đến một lĩnh vực duy nhất hoặc có thể trải rộng qua nhiều lĩnh vực.



                                                                                                                                                                                                                                                                                        ASSERTION

                                                                                                                                                                                                                                                                                        Một phát biểu về trạng thái đúng đắn của một chương trình tại một thời điểm nào đó, độc lập với cách thức thực hiện. Thông thường, một ĐIỀU KIỆN chỉ ra kết quả của một thao tác hoặc một bất biến của một yếu tố thiết kế.



                                                                                                                                                                                                                                                                                        BOUNDED CONTEXT

                                                                                                                                                                                                                                                                                        Tính áp dụng có giới hạn của một mô hình cụ thể. CÁC BỐI CẢNH RÀNG BUỘC mang lại cho các thành viên trong nhóm một sự hiểu biết rõ ràng và chung về những gì cần phải nhất quán và những gì có thể phát triển độc lập.



                                                                                                                                                                                                                                                                                        client

                                                                                                                                                                                                                                                                                        Một phần tử chương trình đang gọi phần tử đang được thiết kế, sử dụng các khả năng của nó.



                                                                                                                                                                                                                                                                                        cohesion

                                                                                                                                                                                                                                                                                        Thỏa thuận và phụ thuộc logic.



                                                                                                                                                                                                                                                                                        command (a.k.a. modifier)

                                                                                                                                                                                                                                                                                        Một thao tác tác động đến hệ thống (ví dụ, thiết lập một biến). Một thao tác cố tình tạo ra một tác dụng phụ.



                                                                                                                                                                                                                                                                                        CONCEPTUAL CONTOUR

                                                                                                                                                                                                                                                                                        Một sự nhất quán cơ bản của chính miền, mà nếu được phản ánh trong một mô hình, có thể giúp thiết kế dễ dàng tiếp nhận thay đổi hơn.



                                                                                                                                                                                                                                                                                        context

                                                                                                                                                                                                                                                                                        Ngữ cảnh mà một từ hoặc câu xuất hiện, giúp xác định ý nghĩa của nó.

                                                                                                                                                                                                                                                                                        See also [BOUNDED CONTEXT]


                                                                                                                                                                                                                                                                                        CONTEXT MAP

                                                                                                                                                                                                                                                                                        Một biểu diễn của CÁC BỐI CẢNH HẠN CHẾ liên quan đến một dự án và các mối quan hệ thực tế giữa chúng và các mô hình của chúng.



                                                                                                                                                                                                                                                                                        CORE DOMAIN

                                                                                                                                                                                                                                                                                        Phần đặc trưng của mô hình, trung tâm của mục tiêu người dùng, làm cho ứng dụng trở nên khác biệt và có giá trị.



                                                                                                                                                                                                                                                                                        declarative design

                                                                                                                                                                                                                                                                                        Một hình thức lập trình trong đó một mô tả chính xác về các thuộc tính thực sự kiểm soát phần mềm. Một đặc tả có thể thực thi.



                                                                                                                                                                                                                                                                                        deep model

                                                                                                                                                                                                                                                                                        Một diễn đạt sắc bén về những mối quan tâm chính của các chuyên gia trong lĩnh vực và kiến thức liên quan nhất của họ. Một mô hình sâu lắng loại bỏ những khía cạnh nông cạn của lĩnh vực và những diễn giải ngây thơ.



                                                                                                                                                                                                                                                                                        design pattern

                                                                                                                                                                                                                                                                                        Mô tả về các đối tượng và lớp được giao tiếp mà được tùy chỉnh để giải quyết một vấn đề thiết kế chung trong một ngữ cảnh cụ thể.



                                                                                                                                                                                                                                                                                        distillation

                                                                                                                                                                                                                                                                                        Một quá trình tách các thành phần của một hỗn hợp để chiết xuất bản chất theo hình thức làm cho nó có giá trị và hữu ích hơn. Trong thiết kế phần mềm, việc trừu tượng hóa các khía cạnh chính trong một mô hình, hoặc phân chia một hệ thống lớn hơn để làm nổi bật MIỀN CHỦ YẾU.



                                                                                                                                                                                                                                                                                        domain

                                                                                                                                                                                                                                                                                        Một lĩnh vực kiến thức, ảnh hưởng hoặc hoạt động.



                                                                                                                                                                                                                                                                                        domain expert

                                                                                                                                                                                                                                                                                        Một thành viên của dự án phần mềm có lĩnh vực là lĩnh vực ứng dụng, thay vì phát triển phần mềm. Không chỉ là bất kỳ người dùng nào của phần mềm, chuyên gia trong lĩnh vực này có kiến thức sâu sắc về chủ đề.



                                                                                                                                                                                                                                                                                        domain layer

                                                                                                                                                                                                                                                                                        Phần của thiết kế và triển khai chịu trách nhiệm cho logic miền trong một KIẾN TRÚC TẦNG. Tầng miền là nơi mà biểu thức phần mềm của mô hình miền tồn tại.



                                                                                                                                                                                                                                                                                        ENTITY

                                                                                                                                                                                                                                                                                        Một đối tượng được định nghĩa không chỉ bởi các thuộc tính của nó, mà còn bởi một sợi chỉ liên tục và bản sắc.



                                                                                                                                                                                                                                                                                        FACTORY

                                                                                                                                                                                                                                                                                        Một cơ chế để đóng gói logic tạo ra phức tạp và trừu tượng hóa loại của một đối tượng được tạo ra vì lợi ích của khách hàng.



                                                                                                                                                                                                                                                                                        function

                                                                                                                                                                                                                                                                                        Một phép toán thực hiện và trả về một kết quả mà không có tác động phụ quan sát được.



                                                                                                                                                                                                                                                                                        immutable

                                                                                                                                                                                                                                                                                        Tính chất không bao giờ thay đổi trạng thái quan sát được sau khi tạo ra.



                                                                                                                                                                                                                                                                                        implicit concept

                                                                                                                                                                                                                                                                                        Một khái niệm cần thiết để hiểu ý nghĩa của một mô hình hoặc thiết kế nhưng không bao giờ được đề cập.



                                                                                                                                                                                                                                                                                        INTENTION-REVEALING INTERFACE

                                                                                                                                                                                                                                                                                        Một thiết kế trong đó tên của các lớp, phương thức và các phần tử khác truyền đạt cả mục đích ban đầu của nhà phát triển khi tạo ra chúng và giá trị của chúng đối với một nhà phát triển khác.



                                                                                                                                                                                                                                                                                        invariant

                                                                                                                                                                                                                                                                                        Một KHẲNG ĐỊNH về một yếu tố thiết kế phải luôn đúng, ngoại trừ trong những tình huống tạm thời cụ thể như trong quá trình thực thi một phương thức, hoặc trong giữa một giao dịch cơ sở dữ liệu chưa được xác nhận.



                                                                                                                                                                                                                                                                                        iteration

                                                                                                                                                                                                                                                                                        Một quy trình trong đó một chương trình được cải thiện liên tục qua các bước nhỏ. Cũng là một trong những bước đó.



                                                                                                                                                                                                                                                                                        large-scale structure

                                                                                                                                                                                                                                                                                        Một bộ các khái niệm, quy tắc hoặc cả hai ở mức độ cao thiết lập một mẫu thiết kế cho toàn bộ hệ thống. Một ngôn ngữ cho phép hệ thống được thảo luận và hiểu theo cách tổng quát.



                                                                                                                                                                                                                                                                                        LAYERED ARCHITECTURE

                                                                                                                                                                                                                                                                                        Một kỹ thuật để tách biệt các mối quan tâm trong một hệ thống phần mềm, cô lập một lớp miền, giữa các thứ khác.



                                                                                                                                                                                                                                                                                        life cycle

                                                                                                                                                                                                                                                                                        Một chuỗi các trạng thái mà một đối tượng có thể trải qua từ khi tạo ra đến khi bị xóa, thường có các ràng buộc để đảm bảo tính toàn vẹn khi chuyển đổi từ trạng thái này sang trạng thái khác. Có thể bao gồm việc di chuyển một THỰC THỂ giữa các hệ thống và các BỐ CỤC HẠN CHẾ khác nhau.



                                                                                                                                                                                                                                                                                        model

                                                                                                                                                                                                                                                                                        Một hệ thống trừu tượng mô tả các khía cạnh đã chọn của một lĩnh vực và có thể được sử dụng để giải quyết các vấn đề liên quan đến lĩnh vực đó.



                                                                                                                                                                                                                                                                                        MODEL-DRIVEN DESIGN

                                                                                                                                                                                                                                                                                        Một thiết kế trong đó một tập con của các yếu tố phần mềm tương ứng chặt chẽ với các yếu tố của một mô hình. Ngoài ra, một quy trình phát triển đồng thời một mô hình và một triển khai mà giữ được sự đồng bộ với nhau.



                                                                                                                                                                                                                                                                                        modeling paradigm

                                                                                                                                                                                                                                                                                        Một phong cách cụ thể trong việc khai thác các khái niệm trong một lĩnh vực, kết hợp với các công cụ để tạo ra các tương đương phần mềm của những khái niệm đó (ví dụ, lập trình hướng đối tượng và lập trình logic).



                                                                                                                                                                                                                                                                                        REPOSITORY

                                                                                                                                                                                                                                                                                        Cơ chế để bao gọn hành vi lưu trữ, truy xuất và tìm kiếm mà mô phỏng một tập hợp các đối tượng.



                                                                                                                                                                                                                                                                                        responsibility

                                                                                                                                                                                                                                                                                        Nghĩa vụ thực hiện một nhiệm vụ hoặc biết thông tin (Wirfs-Brock et al. 2003, tr. 3).



                                                                                                                                                                                                                                                                                        SERVICE

                                                                                                                                                                                                                                                                                        Một phép toán được cung cấp như một giao diện độc lập trong mô hình, không có trạng thái được bao bọc.



                                                                                                                                                                                                                                                                                        side effect

                                                                                                                                                                                                                                                                                        Bất kỳ sự thay đổi trạng thái nào có thể quan sát được xảy ra do một hoạt động, dù có chủ ý hay không, thậm chí là một cập nhật có chủ đích.



                                                                                                                                                                                                                                                                                        SIDE-EFFECT-FREE FUNCTION
                                                                                                                                                                                                                                                                                        See [function]
                                                                                                                                                                                                                                                                                        STANDALONE CLASS

                                                                                                                                                                                                                                                                                        Một lớp có thể được hiểu và kiểm tra mà không cần tham chiếu đến bất kỳ lớp nào khác, ngoại trừ các nguyên thủy của hệ thống và các thư viện cơ bản.



                                                                                                                                                                                                                                                                                        stateless

                                                                                                                                                                                                                                                                                        Tính chất của một yếu tố thiết kế cho phép khách hàng sử dụng bất kỳ chức năng nào của nó mà không cần quan tâm đến lịch sử của yếu tố đó. Một yếu tố không trạng thái có thể sử dụng thông tin có sẵn toàn cầu và thậm chí có thể thay đổi thông tin toàn cầu đó (nghĩa là, nó có thể có các tác dụng phụ) nhưng không giữ trạng thái riêng tư nào ảnh hưởng đến hành vi của nó.



                                                                                                                                                                                                                                                                                        strategic design

                                                                                                                                                                                                                                                                                        Các quyết định về mô hình hóa và thiết kế áp dụng cho các phần lớn của hệ thống. Những quyết định này ảnh hưởng đến toàn bộ dự án và phải được quyết định ở cấp độ nhóm.



                                                                                                                                                                                                                                                                                        supple design

                                                                                                                                                                                                                                                                                        Một thiết kế đưa sức mạnh vốn có của một mô hình sâu vào tay các nhà phát triển client để tạo ra những biểu thức rõ ràng, linh hoạt mang lại kết quả như mong đợi một cách vững chắc. Cũng quan trọng không kém, nó tận dụng chính mô hình sâu đó để làm cho thiết kế trở nên dễ dàng cho người thực hiện để tạo hình và điều chỉnh nhằm phù hợp với những hiểu biết mới.



                                                                                                                                                                                                                                                                                        UBIQUITOUS LANGUAGE

                                                                                                                                                                                                                                                                                        Một ngôn ngữ được cấu trúc xung quanh mô hình miền và được sử dụng bởi tất cả các thành viên trong nhóm để kết nối tất cả các hoạt động của nhóm với phần mềm.



                                                                                                                                                                                                                                                                                        unification

                                                                                                                                                                                                                                                                                        Tính nhất quán nội tại của một mô hình sao cho mỗi yếu tố đều rõ ràng và không có quy tắc nào mâu thuẫn.



                                                                                                                                                                                                                                                                                        VALUE OBJECT

                                                                                                                                                                                                                                                                                        Một đối tượng mô tả một số đặc điểm hoặc thuộc tính nhưng không mang theo khái niệm về danh tính.



                                                                                                                                                                                                                                                                                        WHOLE VALUE

                                                                                                                                                                                                                                                                                        Một đối tượng mô phỏng một khái niệm đơn lẻ, hoàn chỉnh.




                                                                                                                                                                                                                                                                                          References

                                                                                                                                                                                                                                                                                          Alexandra, C., M. Silverstein, S. Angel, S. Ishikawa, và D. Abrams. 1975. Thí nghiệm Oregon. Nhà xuất bản Oxford.

                                                                                                                                                                                                                                                                                          Alexander, C., S. Ishikawa, và M. Silverstein. 1977. Ngôn ngữ mẫu: Thị trấn, tòa nhà, xây dựng. Nhà xuất bản Oxford.

                                                                                                                                                                                                                                                                                          Alur, D., J. Crupi và D. Malks. 2001. Các mẫu J2EE cốt lõi. Nhà xuất bản Sun Microsystems.

                                                                                                                                                                                                                                                                                          Beck, K. 1997. Các Mẫu Thực Hành Tốt Nhất trong Smalltalk. Prentice Hall PTR.

                                                                                                                                                                                                                                                                                          2000. Lập Trình Cực Đoan Giải Thích: Đón Nhận Sự Thay Đổi. Addison-Wesley.

                                                                                                                                                                                                                                                                                          2003. Phát triển phần mềm theo hướng kiểm thử: Qua ví dụ. Addison-Wesley.

                                                                                                                                                                                                                                                                                          Buschmann, F., R. Meunier, H. Rohnert, P. Sommerlad, và M. Stal. 1996. Kiến trúc phần mềm theo mẫu: Một hệ thống các mẫu. Wiley.

                                                                                                                                                                                                                                                                                          Cockburn, A. 1998. Sống sót qua các dự án Hướng đối tượng: Hướng dẫn cho nhà quản lý. Addison-Wesley.

                                                                                                                                                                                                                                                                                          Evans, E., và M. Fowler. 1997. "Thông số kỹ thuật." Tài liệu Hội nghị PLoP 97.

                                                                                                                                                                                                                                                                                          Fayad, M., và R. Johnson. 2000. Khung ứng dụng chuyên biệt theo miền. Wiley.

                                                                                                                                                                                                                                                                                          Fowler, M. 1997. Mô Hình Phân Tích: Các Mô Hình Đối Tượng Tái Sử Dụng. Addison-Wesley.

                                                                                                                                                                                                                                                                                          1999. Tái cấu trúc: Cải thiện thiết kế của mã nguồn hiện có. Addison-Wesley.

                                                                                                                                                                                                                                                                                          2003. Mô hình Kiến Trúc Ứng Dụng Doanh Nghiệp. Addison-Wesley.

                                                                                                                                                                                                                                                                                          Gamma, E., R. Helm, R. Johnson, và J. Vlissides. 1995. Mẫu thiết kế. Addison-Wesley.

                                                                                                                                                                                                                                                                                          Kerievsky, J. 2003. "Học Tập Liên Tục," trong Quan Điểm Về Lập Trình Cực Đoan, Michele Marchesi và cộng sự. Addison-Wesley.

                                                                                                                                                                                                                                                                                          2003. Trang web: http://www.industriallogic.com/xp/refactoring.

                                                                                                                                                                                                                                                                                          Larman, C. 1998. Áp dụng UML và Mô hình: Giới thiệu về Phân tích và Thiết kế Hướng Đối Tượng. Prentice Hall PTR.

                                                                                                                                                                                                                                                                                          Merriam-Webster. 1993. Từ điển đại học Merriam-Webster. Phiên bản thứ mười. Merriam-Webster.

                                                                                                                                                                                                                                                                                          Meyer, B. 1988. Xây dựng phần mềm hướng đối tượng. Prentice Hall PTR.

                                                                                                                                                                                                                                                                                          Murray-Rust, P., H. Rzepa, và C. Leach. 1995. Tóm tắt 40. Được trình bày dưới dạng áp phích tại cuộc họp ACS lần thứ 210 ở Chicago vào ngày 21 tháng 8 năm 1995. http://www.ch.ic.ac.uk/cml/

                                                                                                                                                                                                                                                                                          Pinker, S. 1994. Bản năng ngôn ngữ: Cách mà tâm trí tạo ra ngôn ngữ. HarperCollins.

                                                                                                                                                                                                                                                                                          Succi, G. J., D. Wells, M. Marchesi, và L. Williams. 2002. Những Góc Nhìn Về Lập Trình Năng Động. Nhà Xuất Bản Giáo Dục Pearson.

                                                                                                                                                                                                                                                                                          Warmer, J., và A. Kleppe. 1999. Ngôn ngữ ràng buộc đối tượng: Mô hình chính xác với UML. Addison-Wesley.

                                                                                                                                                                                                                                                                                          Wirfs-Brock, R., B. Wilkerson, và L. Wiener. 1990. Thiết kế Phần mềm Hướng đối Tượng. Prentice Hall PTR.

                                                                                                                                                                                                                                                                                          Wirfs-Brock, R., và A. McKean. 2003. Thiết kế Đối tượng: Vai trò, Trách nhiệm và Sự hợp tác. Addison-Wesley.


                                                                                                                                                                                                                                                                                            PHOTO CREDITS

                                                                                                                                                                                                                                                                                            Tất cả các bức ảnh xuất hiện trong cuốn sách này đã được sử dụng với sự cho phép.

                                                                                                                                                                                                                                                                                            Richard A. Paselk, Đại học Humboldt Astrolabe (Chương 3, trang 47)

                                                                                                                                                                                                                                                                                            © Miễn phí bản quyền/Corbis Dấu vân tay (Chương 5, trang 89), Trạm dịch vụ (Chương 5, trang 104), Nhà máy ô tô (Chương 6, trang 136), Thủ thư (Chương 6, trang 147)

                                                                                                                                                                                                                                                                                            Martine Jousset Nho (Chương 6, trang 125), Cây ô liu (trẻ và già) (Kết luận, trang 500–501)

                                                                                                                                                                                                                                                                                            Công ty Biophoto/Photo Researchers, Inc. Kỹ thuật hiển vi điện tử của Oscillatoria (Chương 14, trang 335)

                                                                                                                                                                                                                                                                                            Ross J. Venables Người chèo thuyền (nhóm và đơn) (Chương 14, trang 341 và 371)

                                                                                                                                                                                                                                                                                            Photodisc Green/Getty Images Người chạy (Chương 14, trang 356), Trẻ em (Chương 14, trang 361)

                                                                                                                                                                                                                                                                                            Cơ quan Quản lý Đại dương và Khí quyển Quốc gia Hoa Kỳ Vạn Lý Trường Thành (Chương 14, trang 364)

                                                                                                                                                                                                                                                                                            © 2003 Quỹ Dự Án NAMES, Atlanta, Georgia. Nhiếp ảnh gia Paul Margolies. www.aidsquilt.org Chặng đường AIDS (Chương 16, trang 439)


                                                                                                                                                                                                                                                                                              Settings

                                                                                                                                                                                                                                                                                              Theme

                                                                                                                                                                                                                                                                                              Font Size
                                                                                                                                                                                                                                                                                              32px
                                                                                                                                                                                                                                                                                              Line Height
                                                                                                                                                                                                                                                                                              2
                                                                                                                                                                                                                                                                                              Weight
                                                                                                                                                                                                                                                                                              400
                                                                                                                                                                                                                                                                                              Align
                                                                                                                                                                                                                                                                                              Font
                                                                                                                                                                                                                                                                                              Width
                                                                                                                                                                                                                                                                                              900px

                                                                                                                                                                                                                                                                                              Ask about this book

                                                                                                                                                                                                                                                                                              Ask anything about this book.