Vì cuộc đời quá ngắn ngủi để vẽ lại sơ đồ Gần đây tôi đã gia nhập một công ty mới với tư cách là . Như mọi khi, tôi phải bắt đầu lại từ đầu. Những thứ như: Mã cho một ứng dụng đang hoạt động ở đâu? Làm thế nào nó được triển khai? Các cấu hình đến từ đâu? Rất may, các đồng nghiệp của tôi đã làm rất tốt khi biến mọi thứ thành 'cơ sở hạ tầng dưới dạng mã'. Vì vậy, tôi chợt nghĩ: Kỹ sư phần mềm Nếu mọi thứ đều nằm trong mã, tại sao không có công cụ nào để kết nối tất cả các dấu chấm? Công cụ này sẽ xem xét cơ sở mã và xây dựng sơ đồ kiến trúc ứng dụng, nêu bật các khía cạnh chính. Một kỹ sư mới có thể nhìn vào sơ đồ và nói: “À, được rồi, đây là cách nó hoạt động.” Điều đầu tiên trước tiên Cho dù tôi có tìm kiếm kỹ đến đâu, tôi cũng không thể tìm thấy thứ gì như thế. Kết quả phù hợp nhất mà tôi tìm thấy là các dịch vụ vẽ sơ đồ cơ sở hạ tầng. Tôi đưa một số trong số chúng vào để bạn có thể xem xét kỹ hơn. Cuối cùng, tôi đã từ bỏ việc tìm kiếm trên Google và quyết định thử phát triển một số nội dung thú vị mới. bài đánh giá này Đầu tiên, tôi xây dựng một ứng dụng mẫu với Gradle, và Terraform. Quy trình hành động của GitHub triển khai ứng dụng trên Amazon Elastic Container Service. Kho lưu trữ này sẽ là nguồn cho công cụ tôi sẽ xây dựng (mã ở ). Java Docker đây Thứ hai, tôi đã vẽ một sơ đồ cấp cao về kết quả mà tôi muốn thấy: Tôi quyết định sẽ có hai loại tài nguyên: Thánh tích Tôi thấy thuật ngữ quá tải nên tôi đã chọn . Vậy Di tích là gì? Đó là 90% những gì bạn muốn xem. Bao gồm nhưng không giới hạn trong: tạo tác Relic Hiện vật (hộp màu xanh lam trên sơ đồ, ví dụ: Lọ, hình ảnh Docker), Định cấu hình tài nguyên Terraform (hộp màu hồng trên sơ đồ, tức là các phiên bản EC2, hàng đợi ECS, SQS), Tài nguyên Kubernetes, Và nhiều nhiều hơn nữa Mỗi Relic đều có tên (ví dụ: my-shiny-app), loại tùy chọn (ví dụ: Jar) và một tập hợp các cặp khóa → giá trị (ví dụ: đường dẫn → /build/libs/my-shiny-app.jar) mô tả đầy đủ Relic. Chúng được gọi là . Di tích càng có nhiều Định nghĩa - càng tốt. Định nghĩa Nguồn Loại thứ hai là . Các nguồn xác định, xây dựng hoặc cung cấp Di tích (ví dụ: hộp màu vàng ở trên). Nguồn mô tả Di tích ở một nơi nào đó và cho biết nó đến từ đâu. Mặc dù Nguồn là thành phần mà chúng tôi nhận được nhiều thông tin nhất nhưng chúng thường có ý nghĩa phụ trên sơ đồ. Bạn có thể không cần nhiều mũi tên đi từ Terraform hoặc Gradle đến mọi Di tích khác. Nguồn Relic và Source có mối quan hệ nhiều-nhiều. Phân chia và chinh phục Bao gồm mọi đoạn mã là không thể. Các ứng dụng hiện đại có thể có nhiều khung, công cụ hoặc thành phần đám mây. Chỉ riêng AWS đã có khoảng 950 tài nguyên và nguồn dữ liệu cho Terraform! Công cụ này phải dễ dàng mở rộng và tách rời theo thiết kế để những người hoặc công ty khác có thể đóng góp. Mặc dù tôi là một người rất hâm mộ kiến trúc của các nhà cung cấp Terraform có khả năng cắm cực kỳ cao, nhưng tôi đã quyết định xây dựng kiến trúc tương tự, mặc dù đã được đơn giản hóa: có một trách nhiệm rõ ràng: xây dựng Di tích dựa trên các tệp nguồn được yêu cầu. Ví dụ: đọc các tệp *.gradle và trả về , hoặc Relics. Mỗi nhà cung cấp xây dựng Di tích theo loại mà họ biết. Nhà cung cấp không quan tâm đến sự tương tác giữa các Di tích. Họ xây dựng Di tích một cách khai báo, hoàn toàn tách biệt với nhau. Nhà cung cấp GradleProvider Jar War Gz Với cách tiếp cận đó, thật dễ dàng để đi sâu như bạn muốn. Một ví dụ điển hình là GitHub Actions. Tệp YAML quy trình công việc điển hình bao gồm hàng chục bước sử dụng các thành phần và dịch vụ được liên kết lỏng lẻo. Một quy trình công việc có thể xây dựng một JAR, sau đó là hình ảnh Docker và triển khai nó vào môi trường. Mỗi bước trong quy trình làm việc đều có thể được nhà cung cấp của nó thực hiện. Vì vậy, giả sử các nhà phát triển tạo một Nhà cung cấp chỉ liên quan đến các bước họ quan tâm. Docker Actions Cách tiếp cận này cho phép bất kỳ số lượng người nào làm việc song song, bổ sung thêm tính logic cho công cụ. Người dùng cuối cũng có thể nhanh chóng triển khai Nhà cung cấp của họ (trong trường hợp một số công nghệ độc quyền). Xem thêm trong phần Tùy chỉnh bên dưới. Hợp nhất hay không hợp nhất Hãy cùng xem xét cái bẫy tiếp theo trước khi đi vào phần hấp dẫn nhất. Hai Nhà cung cấp, mỗi nhà cung cấp tạo ra một Thánh tích. Tốt rồi. Nhưng điều gì sẽ xảy ra nếu hai trong số các Thánh tích này chỉ là biểu diễn của cùng một thành phần được xác định ở hai nơi? Đây là một ví dụ. phân tích định nghĩa tác vụ JSON và tạo ra Relic với loại . Quy trình hành động GitHub cũng có một bước liên quan đến ECS, do đó, một nhà cung cấp khác sẽ tạo Bản di tích . Bây giờ, chúng tôi có các bản sao vì cả hai nhà cung cấp đều không biết gì về nhau. Hơn nữa, việc bất kỳ ai trong số họ cho rằng người khác đã tạo ra Thánh tích là không chính xác. Rồi sao? AmazonECSProvider AmazonECSTask triển khai AmazonECSTask Chúng tôi không thể loại bỏ một trong hai bản sao vì Định nghĩa (thuộc tính) mà mỗi bản sao có. Cách duy nhất là hợp nhất chúng. Theo mặc định, logic tiếp theo xác định quyết định hợp nhất: relic1.name() == relic2.name() && relic1.source() != relic2.source() Chúng tôi hợp nhất hai Thánh tích nếu tên của chúng bằng nhau nhưng chúng được xác định trong các Nguồn khác nhau (như trong ví dụ của chúng tôi, JSON trong kho lưu trữ và tham chiếu định nghĩa tác vụ nằm trong Hành động GithHub). Khi hợp nhất, chúng tôi: Chọn tên duy nhất Hợp nhất tất cả các Định nghĩa (cặp khóa → giá trị) Tạo Nguồn tổng hợp đề cập đến cả hai Nguồn ban đầu Vẽ đường thẳng Tôi đã cố tình bỏ qua một khía cạnh quan trọng của Thánh tích. Nó có thể có — và tốt hơn là nên có nó! Matcher là một hàm boolean nhận một đối số và kiểm tra nó. Bộ so khớp là phần quan trọng của quá trình liên kết. Nếu Thánh tích khớp với bất kỳ định nghĩa nào về Thánh tích của người khác, chúng sẽ được liên kết với nhau. Matcher Bạn có nhớ khi tôi nói rằng Nhà cung cấp không biết gì về Di tích do Nhà cung cấp khác tạo ra không? Điều đó vẫn đúng. Tuy nhiên, Nhà cung cấp xác định Trình so khớp cho Di tích. Nói cách khác, nó đại diện cho một bên của mũi tên giữa hai hộp trên sơ đồ kết quả. Ví dụ. Dockerfile có lệnh ENTRYPOINT. ENTRYPOINT java -jar /app/arch-diagram-sample.jar Với một chút chắc chắn, chúng ta có thể nói rằng Docker bất cứ thứ gì được chỉ định trong . Vì vậy, Relic có chức năng Matcher đơn giản: . Rất có thể, một số Di tích có trong Định nghĩa sẽ khớp với nó. Nếu có, một mũi tên giữa và Relics sẽ xuất hiện. chứa ENTRYPOINT Dockerfile entrypointInstruction.contains(anotherRelicsDefinition) Jar arch-diagram-sample.jar Dockerfile Jar Với Matcher được xác định, quá trình liên kết trông khá đơn giản. Dịch vụ liên kết lặp lại trên tất cả các Di tích và gọi các chức năng của Trình so khớp chúng. Thánh tích A có khớp với bất kỳ định nghĩa B nào của Thánh tích không? Đúng? Thêm một cạnh giữa các Thánh tích đó trong biểu đồ kết quả. Cạnh cũng có thể được đặt tên. Hình dung Bước cuối cùng là hình dung biểu đồ cuối cùng của chúng ta về giai đoạn trước. Ngoài PNG rõ ràng, công cụ này còn hỗ trợ các định dạng bổ sung, chẳng hạn như , và . Những định dạng văn bản này có thể trông kém hấp dẫn hơn, nhưng lợi thế rất lớn là bạn có thể nhúng những văn bản đó vào hầu hết mọi trang wiki ( , và nhiều cái khác). Nàng tiên cá UML thực vật DOT GitHub , Hợp lưu Đây là sơ đồ cuối cùng của repo mẫu: Tùy chỉnh Khả năng cắm các thành phần tùy chỉnh hoặc điều chỉnh logic hiện có là điều cần thiết, đặc biệt khi một công cụ đang ở giai đoạn đầu. Di tích và Nguồn theo mặc định đủ linh hoạt; bạn có thể đặt bất cứ điều gì bạn muốn vào chúng. Mọi thành phần khác đều có thể tùy chỉnh. Các nhà cung cấp hiện tại không cung cấp đủ nguồn lực bạn cần? Thực hiện của riêng bạn một cách dễ dàng. Không hài lòng với logic hợp nhất hoặc liên kết được mô tả ở trên? Không có gì; thêm hoặc của riêng bạn. Đóng gói mọi thứ vào một tệp JAR và thêm nó khi khởi động. Đọc thêm . LinkStrategy MergeStrategy tại đây Ngoại truyện Việc tạo sơ đồ dựa trên mã nguồn có thể sẽ thu hút được sự chú ý. Và đặc biệt là công cụ (vâng, đây là tên của công cụ tôi đang nói đến). ! NoReDraw Những người đóng góp được chào đón Lợi ích đáng chú ý nhất (xuất phát từ cái tên) là không cần phải vẽ lại sơ đồ khi các thành phần thay đổi. Việc thiếu sự quan tâm kỹ thuật là lý do khiến tài liệu nói chung (và sơ đồ nói riêng) trở nên lỗi thời. Với các công cụ như , điều này sẽ không còn là vấn đề nữa vì nó có thể dễ dàng kết nối với bất kỳ quy trình PR/CI nào. Hãy nhớ rằng, 😉 NoReDraw cuộc sống quá ngắn để vẽ lại sơ đồ